blob: e925b4d3244a7ea6c6f4dd12ee1cb6d5ff4463dc [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
2Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
3Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000025/* File object implementation */
26
Guido van Rossum3f5da241990-12-20 15:06:42 +000027#include "allobjects.h"
Guido van Rossumfa3da8a1992-01-27 16:53:23 +000028#include "modsupport.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000029
Guido van Rossumce5ba841991-03-06 13:06:18 +000030#define BUF(v) GETSTRINGVALUE((stringobject *)v)
31
Guido van Rossum3f5da241990-12-20 15:06:42 +000032#include "errno.h"
33#ifndef errno
34extern int errno;
35#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000036
37typedef struct {
38 OB_HEAD
39 FILE *f_fp;
40 object *f_name;
41 object *f_mode;
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +000042 int (*f_close) PROTO((FILE *));
Guido van Rossumeb183da1991-04-04 10:44:06 +000043 int f_softspace; /* Flag used by 'print' command */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000044} fileobject;
45
46FILE *
47getfilefile(f)
48 object *f;
49{
50 if (!is_fileobject(f)) {
Guido van Rossum3f5da241990-12-20 15:06:42 +000051 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000052 return NULL;
53 }
54 return ((fileobject *)f)->f_fp;
55}
56
57object *
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +000058newopenfileobject(fp, name, mode, close)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000059 FILE *fp;
60 char *name;
61 char *mode;
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +000062 int (*close) FPROTO((FILE *));
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000063{
64 fileobject *f = NEWOBJ(fileobject, &Filetype);
65 if (f == NULL)
66 return NULL;
67 f->f_fp = NULL;
68 f->f_name = newstringobject(name);
69 f->f_mode = newstringobject(mode);
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +000070 f->f_close = close;
Guido van Rossumeb183da1991-04-04 10:44:06 +000071 f->f_softspace = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000072 if (f->f_name == NULL || f->f_mode == NULL) {
73 DECREF(f);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000074 return NULL;
75 }
76 f->f_fp = fp;
77 return (object *) f;
78}
79
80object *
81newfileobject(name, mode)
82 char *name, *mode;
83{
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +000084 extern int fclose PROTO((FILE *));
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000085 fileobject *f;
86 FILE *fp;
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +000087 f = (fileobject *) newopenfileobject((FILE *)NULL, name, mode, fclose);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000088 if (f == NULL)
89 return NULL;
Guido van Rossuma08095a1991-02-13 23:25:27 +000090#ifdef THINK_C
91 if (*mode == '*') {
92 FILE *fopenRF();
93 f->f_fp = fopenRF(name, mode+1);
94 }
95 else
96#endif
97 f->f_fp = fopen(name, mode);
98 if (f->f_fp == NULL) {
Guido van Rossum87e7ea71991-12-10 14:00:03 +000099 err_errno(IOError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000100 DECREF(f);
101 return NULL;
102 }
103 return (object *)f;
104}
105
106/* Methods */
107
108static void
Guido van Rossum3f5da241990-12-20 15:06:42 +0000109file_dealloc(f)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000110 fileobject *f;
111{
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000112 if (f->f_fp != NULL && f->f_close != NULL)
113 (*f->f_close)(f->f_fp);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000114 if (f->f_name != NULL)
115 DECREF(f->f_name);
116 if (f->f_mode != NULL)
117 DECREF(f->f_mode);
118 free((char *)f);
119}
120
Guido van Rossum90933611991-06-07 16:10:43 +0000121static int
Guido van Rossum3f5da241990-12-20 15:06:42 +0000122file_print(f, fp, flags)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000123 fileobject *f;
124 FILE *fp;
125 int flags;
126{
127 fprintf(fp, "<%s file ", f->f_fp == NULL ? "closed" : "open");
Guido van Rossum90933611991-06-07 16:10:43 +0000128 if (printobject(f->f_name, fp, flags) != 0)
129 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000130 fprintf(fp, ", mode ");
Guido van Rossum90933611991-06-07 16:10:43 +0000131 if (printobject(f->f_mode, fp, flags) != 0)
132 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000133 fprintf(fp, ">");
Guido van Rossum90933611991-06-07 16:10:43 +0000134 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000135}
136
137static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000138file_repr(f)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000139 fileobject *f;
140{
141 char buf[300];
Guido van Rossum3f5da241990-12-20 15:06:42 +0000142 /* XXX This differs from file_print if the filename contains
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000143 quotes or other funny characters. */
144 sprintf(buf, "<%s file '%.256s', mode '%.10s'>",
145 f->f_fp == NULL ? "closed" : "open",
146 getstringvalue(f->f_name),
147 getstringvalue(f->f_mode));
148 return newstringobject(buf);
149}
150
151static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000152file_close(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000153 fileobject *f;
154 object *args;
155{
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000156 int sts = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000157 if (args != NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000158 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000159 return NULL;
160 }
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000161 errno = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000162 if (f->f_fp != NULL) {
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000163 if (f->f_close != NULL)
164 sts = (*f->f_close)(f->f_fp);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000165 f->f_fp = NULL;
166 }
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000167 if (sts == EOF) {
168 if (errno == 0)
169 errno = EIO;
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000170 return err_errno(IOError);
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000171 }
172 if (sts != 0)
173 return newintobject((long)sts);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000174 INCREF(None);
175 return None;
176}
177
178static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000179file_seek(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000180 fileobject *f;
181 object *args;
182{
Guido van Rossumce5ba841991-03-06 13:06:18 +0000183 long offset;
184 long whence;
185
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000186 if (f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000187 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000188 return NULL;
189 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000190 if (args != NULL && is_intobject(args)) {
191 offset = getintvalue(args);
192 whence = 0; /* SEEK_SET */
193 }
194 else {
Guido van Rossum18a372f1991-09-10 14:55:58 +0000195 if (!getlonglongarg(args, &offset, &whence))
Guido van Rossumce5ba841991-03-06 13:06:18 +0000196 return NULL;
197 }
198 errno = 0;
199 if (fseek(f->f_fp, offset, (int)whence) != 0) {
200 if (errno == 0)
201 errno = EIO;
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000202 return err_errno(IOError);
Guido van Rossumce5ba841991-03-06 13:06:18 +0000203 }
204 INCREF(None);
205 return None;
206}
207
208static object *
209file_tell(f, args)
210 fileobject *f;
211 object *args;
212{
213 long offset;
214 if (args != NULL || f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000215 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000216 return NULL;
217 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000218 errno = 0;
219 offset = ftell(f->f_fp);
220 if (offset == -1L) {
221 if (errno == 0)
222 errno = EIO;
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000223 return err_errno(IOError);
Guido van Rossumce5ba841991-03-06 13:06:18 +0000224 }
225 return newintobject(offset);
226}
227
228static object *
229file_flush(f, args)
230 fileobject *f;
231 object *args;
232{
233 if (args != NULL || f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000234 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000235 return NULL;
236 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000237 errno = 0;
238 if (fflush(f->f_fp) != 0) {
239 if (errno == 0)
240 errno = EIO;
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000241 return err_errno(IOError);
Guido van Rossumce5ba841991-03-06 13:06:18 +0000242 }
243 INCREF(None);
244 return None;
245}
246
247static object *
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000248file_isatty(f, args)
249 fileobject *f;
250 object *args;
251{
252 if (args != NULL || f->f_fp == NULL) {
253 err_badarg();
254 return NULL;
255 }
256 return newintobject((long)isatty(fileno(f->f_fp)));
257}
258
259static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000260file_read(f, args)
261 fileobject *f;
262 object *args;
263{
264 int n, n1, n2, n3;
265 object *v;
266
267 if (f->f_fp == NULL) {
268 err_badarg();
269 return NULL;
270 }
271 if (args == 0)
272 n = 0;
273 else {
274 if (!getintarg(args, &n))
275 return NULL;
276 if (n < 0) {
277 err_badarg();
278 return NULL;
279 }
280 }
281
282 n2 = n != 0 ? n : BUFSIZ;
283 v = newsizedstringobject((char *)NULL, n2);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000284 if (v == NULL)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000285 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000286 n1 = 0;
287 for (;;) {
288 n3 = fread(BUF(v)+n1, 1, n2-n1, f->f_fp);
289 /* XXX Error check? */
290 if (n3 == 0)
291 break;
292 n1 += n3;
293 if (n1 == n)
294 break;
295 if (n == 0) {
296 n2 = n1 + BUFSIZ;
297 if (resizestring(&v, n2) < 0)
298 return NULL;
299 }
300 }
301 if (n1 != n2)
302 resizestring(&v, n1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000303 return v;
304}
305
Guido van Rossum0bd24411991-04-04 15:21:57 +0000306/* Internal routine to get a line.
307 Size argument interpretation:
308 > 0: max length;
309 = 0: read arbitrary line;
310 < 0: strip trailing '\n', raise EOFError if EOF reached immediately
Guido van Rossumce5ba841991-03-06 13:06:18 +0000311*/
312
Guido van Rossum0bd24411991-04-04 15:21:57 +0000313object *
314getline(f, n)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000315 fileobject *f;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000316 int n;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000317{
Guido van Rossumce5ba841991-03-06 13:06:18 +0000318 register FILE *fp;
319 register int c;
320 register char *buf, *end;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000321 int n1, n2;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000322 object *v;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000323
Guido van Rossumce5ba841991-03-06 13:06:18 +0000324 if ((fp = f->f_fp) == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000325 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000326 return NULL;
327 }
Guido van Rossum0bd24411991-04-04 15:21:57 +0000328
329 n2 = n > 0 ? n : 100;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000330 v = newsizedstringobject((char *)NULL, n2);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000331 if (v == NULL)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000332 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000333 buf = BUF(v);
334 end = buf + n2;
335
336 for (;;) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000337 if ((c = getc(fp)) == EOF) {
Guido van Rossum76ad8ed1991-06-03 10:54:55 +0000338 clearerr(fp);
Guido van Rossum0bd24411991-04-04 15:21:57 +0000339 if (intrcheck()) {
340 DECREF(v);
341 err_set(KeyboardInterrupt);
342 return NULL;
343 }
344 if (n < 0 && buf == BUF(v)) {
345 DECREF(v);
Guido van Rossum201be051991-12-24 13:26:41 +0000346 err_setstr(EOFError,
347 "EOF when reading a line");
Guido van Rossum0bd24411991-04-04 15:21:57 +0000348 return NULL;
349 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000350 break;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000351 }
352 if ((*buf++ = c) == '\n') {
353 if (n < 0)
354 buf--;
355 break;
356 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000357 if (buf == end) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000358 if (n > 0)
Guido van Rossumce5ba841991-03-06 13:06:18 +0000359 break;
360 n1 = n2;
361 n2 += 1000;
362 if (resizestring(&v, n2) < 0)
363 return NULL;
364 buf = BUF(v) + n1;
365 end = BUF(v) + n2;
366 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000367 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000368
369 n1 = buf - BUF(v);
370 if (n1 != n2)
371 resizestring(&v, n1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000372 return v;
373}
374
Guido van Rossum0bd24411991-04-04 15:21:57 +0000375/* External C interface */
376
377object *
378filegetline(f, n)
379 object *f;
380 int n;
381{
382 if (f == NULL || !is_fileobject(f)) {
383 err_badcall();
384 return NULL;
385 }
386 return getline((fileobject *)f, n);
387}
388
389/* Python method */
390
391static object *
392file_readline(f, args)
393 fileobject *f;
394 object *args;
395{
396 int n;
397
398 if (args == NULL)
399 n = 0; /* Unlimited */
400 else {
401 if (!getintarg(args, &n))
402 return NULL;
403 if (n < 0) {
404 err_badarg();
405 return NULL;
406 }
407 }
408
409 return getline((object *)f, n);
410}
411
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000412static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000413file_readlines(f, args)
414 fileobject *f;
415 object *args;
416{
417 object *list;
418 object *line;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000419
420 if (!getnoarg(args))
421 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000422 if ((list = newlistobject(0)) == NULL)
423 return NULL;
424 for (;;) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000425 line = getline(f, 0);
Guido van Rossumce5ba841991-03-06 13:06:18 +0000426 if (line != NULL && getstringsize(line) == 0) {
427 DECREF(line);
428 break;
429 }
430 if (line == NULL || addlistitem(list, line) != 0) {
431 DECREF(list);
432 XDECREF(line);
433 return NULL;
434 }
435 DECREF(line);
436 }
437 return list;
438}
439
440static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000441file_write(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000442 fileobject *f;
443 object *args;
444{
445 int n, n2;
446 if (f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000447 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000448 return NULL;
449 }
450 if (args == NULL || !is_stringobject(args)) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000451 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000452 return NULL;
453 }
Guido van Rossumeb183da1991-04-04 10:44:06 +0000454 f->f_softspace = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000455 errno = 0;
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000456 n2 = fwrite(getstringvalue(args), 1, n = getstringsize(args), f->f_fp);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000457 if (n2 != n) {
458 if (errno == 0)
459 errno = EIO;
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000460 err_errno(IOError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000461 return NULL;
462 }
463 INCREF(None);
464 return None;
465}
466
Guido van Rossum3f5da241990-12-20 15:06:42 +0000467static struct methodlist file_methods[] = {
Guido van Rossumce5ba841991-03-06 13:06:18 +0000468 {"close", file_close},
469 {"flush", file_flush},
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000470 {"isatty", file_isatty},
Guido van Rossum3f5da241990-12-20 15:06:42 +0000471 {"read", file_read},
472 {"readline", file_readline},
Guido van Rossumce5ba841991-03-06 13:06:18 +0000473 {"readlines", file_readlines},
474 {"seek", file_seek},
475 {"tell", file_tell},
476 {"write", file_write},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000477 {NULL, NULL} /* sentinel */
478};
479
480static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000481file_getattr(f, name)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000482 fileobject *f;
483 char *name;
484{
Guido van Rossum3f5da241990-12-20 15:06:42 +0000485 return findmethod(file_methods, (object *)f, name);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000486}
487
488typeobject Filetype = {
489 OB_HEAD_INIT(&Typetype)
490 0,
491 "file",
492 sizeof(fileobject),
493 0,
Guido van Rossum3f5da241990-12-20 15:06:42 +0000494 file_dealloc, /*tp_dealloc*/
495 file_print, /*tp_print*/
496 file_getattr, /*tp_getattr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000497 0, /*tp_setattr*/
498 0, /*tp_compare*/
Guido van Rossum3f5da241990-12-20 15:06:42 +0000499 file_repr, /*tp_repr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000500};
Guido van Rossumeb183da1991-04-04 10:44:06 +0000501
502/* Interface for the 'soft space' between print items. */
503
504int
505softspace(f, newflag)
506 object *f;
507 int newflag;
508{
509 int oldflag = 0;
510 if (f != NULL && is_fileobject(f)) {
511 oldflag = ((fileobject *)f)->f_softspace;
512 ((fileobject *)f)->f_softspace = newflag;
513 }
514 return oldflag;
515}