blob: db9a088eb1deda71ea65114c30cea75e48cd8653 [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 Rossum85a5fbb1990-10-14 12:07:46 +000028
Guido van Rossumce5ba841991-03-06 13:06:18 +000029#define BUF(v) GETSTRINGVALUE((stringobject *)v)
30
Guido van Rossum3f5da241990-12-20 15:06:42 +000031#include "errno.h"
32#ifndef errno
33extern int errno;
34#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000035
36typedef struct {
37 OB_HEAD
38 FILE *f_fp;
39 object *f_name;
40 object *f_mode;
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +000041 int (*f_close) PROTO((FILE *));
Guido van Rossumeb183da1991-04-04 10:44:06 +000042 int f_softspace; /* Flag used by 'print' command */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000043} fileobject;
44
45FILE *
46getfilefile(f)
47 object *f;
48{
49 if (!is_fileobject(f)) {
Guido van Rossum3f5da241990-12-20 15:06:42 +000050 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000051 return NULL;
52 }
53 return ((fileobject *)f)->f_fp;
54}
55
56object *
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +000057newopenfileobject(fp, name, mode, close)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000058 FILE *fp;
59 char *name;
60 char *mode;
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +000061 int (*close) FPROTO((FILE *));
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000062{
63 fileobject *f = NEWOBJ(fileobject, &Filetype);
64 if (f == NULL)
65 return NULL;
66 f->f_fp = NULL;
67 f->f_name = newstringobject(name);
68 f->f_mode = newstringobject(mode);
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +000069 f->f_close = close;
Guido van Rossumeb183da1991-04-04 10:44:06 +000070 f->f_softspace = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000071 if (f->f_name == NULL || f->f_mode == NULL) {
72 DECREF(f);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000073 return NULL;
74 }
75 f->f_fp = fp;
76 return (object *) f;
77}
78
79object *
80newfileobject(name, mode)
81 char *name, *mode;
82{
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +000083 extern int fclose PROTO((FILE *));
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000084 fileobject *f;
85 FILE *fp;
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +000086 f = (fileobject *) newopenfileobject((FILE *)NULL, name, mode, fclose);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000087 if (f == NULL)
88 return NULL;
Guido van Rossuma08095a1991-02-13 23:25:27 +000089#ifdef THINK_C
90 if (*mode == '*') {
91 FILE *fopenRF();
92 f->f_fp = fopenRF(name, mode+1);
93 }
94 else
95#endif
96 f->f_fp = fopen(name, mode);
97 if (f->f_fp == NULL) {
Guido van Rossum87e7ea71991-12-10 14:00:03 +000098 err_errno(IOError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000099 DECREF(f);
100 return NULL;
101 }
102 return (object *)f;
103}
104
105/* Methods */
106
107static void
Guido van Rossum3f5da241990-12-20 15:06:42 +0000108file_dealloc(f)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000109 fileobject *f;
110{
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000111 if (f->f_fp != NULL && f->f_close != NULL)
112 (*f->f_close)(f->f_fp);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000113 if (f->f_name != NULL)
114 DECREF(f->f_name);
115 if (f->f_mode != NULL)
116 DECREF(f->f_mode);
117 free((char *)f);
118}
119
Guido van Rossum90933611991-06-07 16:10:43 +0000120static int
Guido van Rossum3f5da241990-12-20 15:06:42 +0000121file_print(f, fp, flags)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000122 fileobject *f;
123 FILE *fp;
124 int flags;
125{
126 fprintf(fp, "<%s file ", f->f_fp == NULL ? "closed" : "open");
Guido van Rossum90933611991-06-07 16:10:43 +0000127 if (printobject(f->f_name, fp, flags) != 0)
128 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000129 fprintf(fp, ", mode ");
Guido van Rossum90933611991-06-07 16:10:43 +0000130 if (printobject(f->f_mode, fp, flags) != 0)
131 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000132 fprintf(fp, ">");
Guido van Rossum90933611991-06-07 16:10:43 +0000133 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000134}
135
136static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000137file_repr(f)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000138 fileobject *f;
139{
140 char buf[300];
Guido van Rossum3f5da241990-12-20 15:06:42 +0000141 /* XXX This differs from file_print if the filename contains
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000142 quotes or other funny characters. */
143 sprintf(buf, "<%s file '%.256s', mode '%.10s'>",
144 f->f_fp == NULL ? "closed" : "open",
145 getstringvalue(f->f_name),
146 getstringvalue(f->f_mode));
147 return newstringobject(buf);
148}
149
150static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000151file_close(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000152 fileobject *f;
153 object *args;
154{
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000155 int sts = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000156 if (args != NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000157 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000158 return NULL;
159 }
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000160 errno = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000161 if (f->f_fp != NULL) {
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000162 if (f->f_close != NULL)
163 sts = (*f->f_close)(f->f_fp);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000164 f->f_fp = NULL;
165 }
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000166 if (sts == EOF) {
167 if (errno == 0)
168 errno = EIO;
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000169 return err_errno(IOError);
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000170 }
171 if (sts != 0)
172 return newintobject((long)sts);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000173 INCREF(None);
174 return None;
175}
176
177static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000178file_seek(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000179 fileobject *f;
180 object *args;
181{
Guido van Rossumce5ba841991-03-06 13:06:18 +0000182 long offset;
183 long whence;
184
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000185 if (f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000186 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000187 return NULL;
188 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000189 if (args != NULL && is_intobject(args)) {
190 offset = getintvalue(args);
191 whence = 0; /* SEEK_SET */
192 }
193 else {
Guido van Rossum18a372f1991-09-10 14:55:58 +0000194 if (!getlonglongarg(args, &offset, &whence))
Guido van Rossumce5ba841991-03-06 13:06:18 +0000195 return NULL;
196 }
197 errno = 0;
198 if (fseek(f->f_fp, offset, (int)whence) != 0) {
199 if (errno == 0)
200 errno = EIO;
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000201 return err_errno(IOError);
Guido van Rossumce5ba841991-03-06 13:06:18 +0000202 }
203 INCREF(None);
204 return None;
205}
206
207static object *
208file_tell(f, args)
209 fileobject *f;
210 object *args;
211{
212 long offset;
213 if (args != NULL || f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000214 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000215 return NULL;
216 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000217 errno = 0;
218 offset = ftell(f->f_fp);
219 if (offset == -1L) {
220 if (errno == 0)
221 errno = EIO;
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000222 return err_errno(IOError);
Guido van Rossumce5ba841991-03-06 13:06:18 +0000223 }
224 return newintobject(offset);
225}
226
227static object *
228file_flush(f, args)
229 fileobject *f;
230 object *args;
231{
232 if (args != NULL || f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000233 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000234 return NULL;
235 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000236 errno = 0;
237 if (fflush(f->f_fp) != 0) {
238 if (errno == 0)
239 errno = EIO;
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000240 return err_errno(IOError);
Guido van Rossumce5ba841991-03-06 13:06:18 +0000241 }
242 INCREF(None);
243 return None;
244}
245
246static object *
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000247file_isatty(f, args)
248 fileobject *f;
249 object *args;
250{
251 if (args != NULL || f->f_fp == NULL) {
252 err_badarg();
253 return NULL;
254 }
255 return newintobject((long)isatty(fileno(f->f_fp)));
256}
257
258static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000259file_read(f, args)
260 fileobject *f;
261 object *args;
262{
263 int n, n1, n2, n3;
264 object *v;
265
266 if (f->f_fp == NULL) {
267 err_badarg();
268 return NULL;
269 }
270 if (args == 0)
271 n = 0;
272 else {
273 if (!getintarg(args, &n))
274 return NULL;
275 if (n < 0) {
276 err_badarg();
277 return NULL;
278 }
279 }
280
281 n2 = n != 0 ? n : BUFSIZ;
282 v = newsizedstringobject((char *)NULL, n2);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000283 if (v == NULL)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000284 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000285 n1 = 0;
286 for (;;) {
287 n3 = fread(BUF(v)+n1, 1, n2-n1, f->f_fp);
288 /* XXX Error check? */
289 if (n3 == 0)
290 break;
291 n1 += n3;
292 if (n1 == n)
293 break;
294 if (n == 0) {
295 n2 = n1 + BUFSIZ;
296 if (resizestring(&v, n2) < 0)
297 return NULL;
298 }
299 }
300 if (n1 != n2)
301 resizestring(&v, n1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000302 return v;
303}
304
Guido van Rossum0bd24411991-04-04 15:21:57 +0000305/* Internal routine to get a line.
306 Size argument interpretation:
307 > 0: max length;
308 = 0: read arbitrary line;
309 < 0: strip trailing '\n', raise EOFError if EOF reached immediately
Guido van Rossumce5ba841991-03-06 13:06:18 +0000310*/
311
Guido van Rossum0bd24411991-04-04 15:21:57 +0000312object *
313getline(f, n)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000314 fileobject *f;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000315 int n;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000316{
Guido van Rossumce5ba841991-03-06 13:06:18 +0000317 register FILE *fp;
318 register int c;
319 register char *buf, *end;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000320 int n1, n2;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000321 object *v;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000322
Guido van Rossumce5ba841991-03-06 13:06:18 +0000323 if ((fp = f->f_fp) == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000324 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000325 return NULL;
326 }
Guido van Rossum0bd24411991-04-04 15:21:57 +0000327
328 n2 = n > 0 ? n : 100;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000329 v = newsizedstringobject((char *)NULL, n2);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000330 if (v == NULL)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000331 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000332 buf = BUF(v);
333 end = buf + n2;
334
335 for (;;) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000336 if ((c = getc(fp)) == EOF) {
Guido van Rossum76ad8ed1991-06-03 10:54:55 +0000337 clearerr(fp);
Guido van Rossum0bd24411991-04-04 15:21:57 +0000338 if (intrcheck()) {
339 DECREF(v);
340 err_set(KeyboardInterrupt);
341 return NULL;
342 }
343 if (n < 0 && buf == BUF(v)) {
344 DECREF(v);
Guido van Rossum201be051991-12-24 13:26:41 +0000345 err_setstr(EOFError,
346 "EOF when reading a line");
Guido van Rossum0bd24411991-04-04 15:21:57 +0000347 return NULL;
348 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000349 break;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000350 }
351 if ((*buf++ = c) == '\n') {
352 if (n < 0)
353 buf--;
354 break;
355 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000356 if (buf == end) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000357 if (n > 0)
Guido van Rossumce5ba841991-03-06 13:06:18 +0000358 break;
359 n1 = n2;
360 n2 += 1000;
361 if (resizestring(&v, n2) < 0)
362 return NULL;
363 buf = BUF(v) + n1;
364 end = BUF(v) + n2;
365 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000366 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000367
368 n1 = buf - BUF(v);
369 if (n1 != n2)
370 resizestring(&v, n1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000371 return v;
372}
373
Guido van Rossum0bd24411991-04-04 15:21:57 +0000374/* External C interface */
375
376object *
377filegetline(f, n)
378 object *f;
379 int n;
380{
381 if (f == NULL || !is_fileobject(f)) {
382 err_badcall();
383 return NULL;
384 }
385 return getline((fileobject *)f, n);
386}
387
388/* Python method */
389
390static object *
391file_readline(f, args)
392 fileobject *f;
393 object *args;
394{
395 int n;
396
397 if (args == NULL)
398 n = 0; /* Unlimited */
399 else {
400 if (!getintarg(args, &n))
401 return NULL;
402 if (n < 0) {
403 err_badarg();
404 return NULL;
405 }
406 }
407
408 return getline((object *)f, n);
409}
410
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000411static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000412file_readlines(f, args)
413 fileobject *f;
414 object *args;
415{
416 object *list;
417 object *line;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000418
419 if (!getnoarg(args))
420 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000421 if ((list = newlistobject(0)) == NULL)
422 return NULL;
423 for (;;) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000424 line = getline(f, 0);
Guido van Rossumce5ba841991-03-06 13:06:18 +0000425 if (line != NULL && getstringsize(line) == 0) {
426 DECREF(line);
427 break;
428 }
429 if (line == NULL || addlistitem(list, line) != 0) {
430 DECREF(list);
431 XDECREF(line);
432 return NULL;
433 }
434 DECREF(line);
435 }
436 return list;
437}
438
439static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000440file_write(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000441 fileobject *f;
442 object *args;
443{
444 int n, n2;
445 if (f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000446 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000447 return NULL;
448 }
449 if (args == NULL || !is_stringobject(args)) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000450 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000451 return NULL;
452 }
Guido van Rossumeb183da1991-04-04 10:44:06 +0000453 f->f_softspace = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000454 errno = 0;
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000455 n2 = fwrite(getstringvalue(args), 1, n = getstringsize(args), f->f_fp);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000456 if (n2 != n) {
457 if (errno == 0)
458 errno = EIO;
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000459 err_errno(IOError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000460 return NULL;
461 }
462 INCREF(None);
463 return None;
464}
465
Guido van Rossum3f5da241990-12-20 15:06:42 +0000466static struct methodlist file_methods[] = {
Guido van Rossumce5ba841991-03-06 13:06:18 +0000467 {"close", file_close},
468 {"flush", file_flush},
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000469 {"isatty", file_isatty},
Guido van Rossum3f5da241990-12-20 15:06:42 +0000470 {"read", file_read},
471 {"readline", file_readline},
Guido van Rossumce5ba841991-03-06 13:06:18 +0000472 {"readlines", file_readlines},
473 {"seek", file_seek},
474 {"tell", file_tell},
475 {"write", file_write},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000476 {NULL, NULL} /* sentinel */
477};
478
479static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000480file_getattr(f, name)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000481 fileobject *f;
482 char *name;
483{
Guido van Rossum3f5da241990-12-20 15:06:42 +0000484 return findmethod(file_methods, (object *)f, name);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000485}
486
487typeobject Filetype = {
488 OB_HEAD_INIT(&Typetype)
489 0,
490 "file",
491 sizeof(fileobject),
492 0,
Guido van Rossum3f5da241990-12-20 15:06:42 +0000493 file_dealloc, /*tp_dealloc*/
494 file_print, /*tp_print*/
495 file_getattr, /*tp_getattr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000496 0, /*tp_setattr*/
497 0, /*tp_compare*/
Guido van Rossum3f5da241990-12-20 15:06:42 +0000498 file_repr, /*tp_repr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000499};
Guido van Rossumeb183da1991-04-04 10:44:06 +0000500
501/* Interface for the 'soft space' between print items. */
502
503int
504softspace(f, newflag)
505 object *f;
506 int newflag;
507{
508 int oldflag = 0;
509 if (f != NULL && is_fileobject(f)) {
510 oldflag = ((fileobject *)f)->f_softspace;
511 ((fileobject *)f)->f_softspace = newflag;
512 }
513 return oldflag;
514}