blob: 8e35e7e493b39d2827153a6879a212153ceec24f [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 Rossumfebd5511992-03-04 16:39:24 +0000167 if (sts == EOF)
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000168 return err_errno(IOError);
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000169 if (sts != 0)
170 return newintobject((long)sts);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000171 INCREF(None);
172 return None;
173}
174
175static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000176file_seek(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000177 fileobject *f;
178 object *args;
179{
Guido van Rossumce5ba841991-03-06 13:06:18 +0000180 long offset;
181 long whence;
182
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000183 if (f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000184 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000185 return NULL;
186 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000187 if (args != NULL && is_intobject(args)) {
188 offset = getintvalue(args);
189 whence = 0; /* SEEK_SET */
190 }
191 else {
Guido van Rossum18a372f1991-09-10 14:55:58 +0000192 if (!getlonglongarg(args, &offset, &whence))
Guido van Rossumce5ba841991-03-06 13:06:18 +0000193 return NULL;
194 }
195 errno = 0;
196 if (fseek(f->f_fp, offset, (int)whence) != 0) {
Guido van Rossumfebd5511992-03-04 16:39:24 +0000197 err_errno(IOError);
198 clearerr(f->f_fp);
199 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000200 }
201 INCREF(None);
202 return None;
203}
204
205static object *
206file_tell(f, args)
207 fileobject *f;
208 object *args;
209{
210 long offset;
211 if (args != NULL || f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000212 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000213 return NULL;
214 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000215 errno = 0;
216 offset = ftell(f->f_fp);
217 if (offset == -1L) {
Guido van Rossumfebd5511992-03-04 16:39:24 +0000218 err_errno(IOError);
219 clearerr(f->f_fp);
220 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000221 }
222 return newintobject(offset);
223}
224
225static object *
226file_flush(f, args)
227 fileobject *f;
228 object *args;
229{
230 if (args != NULL || f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000231 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000232 return NULL;
233 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000234 errno = 0;
235 if (fflush(f->f_fp) != 0) {
Guido van Rossumfebd5511992-03-04 16:39:24 +0000236 err_errno(IOError);
237 clearerr(f->f_fp);
238 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000239 }
240 INCREF(None);
241 return None;
242}
243
244static object *
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000245file_isatty(f, args)
246 fileobject *f;
247 object *args;
248{
249 if (args != NULL || f->f_fp == NULL) {
250 err_badarg();
251 return NULL;
252 }
253 return newintobject((long)isatty(fileno(f->f_fp)));
254}
255
256static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000257file_read(f, args)
258 fileobject *f;
259 object *args;
260{
261 int n, n1, n2, n3;
262 object *v;
263
264 if (f->f_fp == NULL) {
265 err_badarg();
266 return NULL;
267 }
268 if (args == 0)
269 n = 0;
270 else {
271 if (!getintarg(args, &n))
272 return NULL;
273 if (n < 0) {
274 err_badarg();
275 return NULL;
276 }
277 }
278
279 n2 = n != 0 ? n : BUFSIZ;
280 v = newsizedstringobject((char *)NULL, n2);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000281 if (v == NULL)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000282 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000283 n1 = 0;
284 for (;;) {
285 n3 = fread(BUF(v)+n1, 1, n2-n1, f->f_fp);
286 /* XXX Error check? */
287 if (n3 == 0)
288 break;
289 n1 += n3;
290 if (n1 == n)
291 break;
292 if (n == 0) {
293 n2 = n1 + BUFSIZ;
294 if (resizestring(&v, n2) < 0)
295 return NULL;
296 }
297 }
298 if (n1 != n2)
299 resizestring(&v, n1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000300 return v;
301}
302
Guido van Rossum0bd24411991-04-04 15:21:57 +0000303/* Internal routine to get a line.
304 Size argument interpretation:
305 > 0: max length;
306 = 0: read arbitrary line;
307 < 0: strip trailing '\n', raise EOFError if EOF reached immediately
Guido van Rossumce5ba841991-03-06 13:06:18 +0000308*/
309
Guido van Rossum0bd24411991-04-04 15:21:57 +0000310object *
311getline(f, n)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000312 fileobject *f;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000313 int n;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000314{
Guido van Rossumce5ba841991-03-06 13:06:18 +0000315 register FILE *fp;
316 register int c;
317 register char *buf, *end;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000318 int n1, n2;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000319 object *v;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000320
Guido van Rossumce5ba841991-03-06 13:06:18 +0000321 if ((fp = f->f_fp) == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000322 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000323 return NULL;
324 }
Guido van Rossum0bd24411991-04-04 15:21:57 +0000325
326 n2 = n > 0 ? n : 100;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000327 v = newsizedstringobject((char *)NULL, n2);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000328 if (v == NULL)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000329 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000330 buf = BUF(v);
331 end = buf + n2;
332
333 for (;;) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000334 if ((c = getc(fp)) == EOF) {
Guido van Rossum76ad8ed1991-06-03 10:54:55 +0000335 clearerr(fp);
Guido van Rossum0bd24411991-04-04 15:21:57 +0000336 if (intrcheck()) {
337 DECREF(v);
338 err_set(KeyboardInterrupt);
339 return NULL;
340 }
341 if (n < 0 && buf == BUF(v)) {
342 DECREF(v);
Guido van Rossum201be051991-12-24 13:26:41 +0000343 err_setstr(EOFError,
344 "EOF when reading a line");
Guido van Rossum0bd24411991-04-04 15:21:57 +0000345 return NULL;
346 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000347 break;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000348 }
349 if ((*buf++ = c) == '\n') {
350 if (n < 0)
351 buf--;
352 break;
353 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000354 if (buf == end) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000355 if (n > 0)
Guido van Rossumce5ba841991-03-06 13:06:18 +0000356 break;
357 n1 = n2;
358 n2 += 1000;
359 if (resizestring(&v, n2) < 0)
360 return NULL;
361 buf = BUF(v) + n1;
362 end = BUF(v) + n2;
363 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000364 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000365
366 n1 = buf - BUF(v);
367 if (n1 != n2)
368 resizestring(&v, n1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000369 return v;
370}
371
Guido van Rossum0bd24411991-04-04 15:21:57 +0000372/* External C interface */
373
374object *
375filegetline(f, n)
376 object *f;
377 int n;
378{
379 if (f == NULL || !is_fileobject(f)) {
380 err_badcall();
381 return NULL;
382 }
383 return getline((fileobject *)f, n);
384}
385
386/* Python method */
387
388static object *
389file_readline(f, args)
390 fileobject *f;
391 object *args;
392{
393 int n;
394
395 if (args == NULL)
396 n = 0; /* Unlimited */
397 else {
398 if (!getintarg(args, &n))
399 return NULL;
400 if (n < 0) {
401 err_badarg();
402 return NULL;
403 }
404 }
405
406 return getline((object *)f, n);
407}
408
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000409static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000410file_readlines(f, args)
411 fileobject *f;
412 object *args;
413{
414 object *list;
415 object *line;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000416
417 if (!getnoarg(args))
418 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000419 if ((list = newlistobject(0)) == NULL)
420 return NULL;
421 for (;;) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000422 line = getline(f, 0);
Guido van Rossumce5ba841991-03-06 13:06:18 +0000423 if (line != NULL && getstringsize(line) == 0) {
424 DECREF(line);
425 break;
426 }
427 if (line == NULL || addlistitem(list, line) != 0) {
428 DECREF(list);
429 XDECREF(line);
430 return NULL;
431 }
432 DECREF(line);
433 }
434 return list;
435}
436
437static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000438file_write(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000439 fileobject *f;
440 object *args;
441{
442 int n, n2;
443 if (f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000444 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000445 return NULL;
446 }
447 if (args == NULL || !is_stringobject(args)) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000448 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000449 return NULL;
450 }
Guido van Rossumeb183da1991-04-04 10:44:06 +0000451 f->f_softspace = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000452 errno = 0;
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000453 n2 = fwrite(getstringvalue(args), 1, n = getstringsize(args), f->f_fp);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000454 if (n2 != n) {
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000455 err_errno(IOError);
Guido van Rossumfebd5511992-03-04 16:39:24 +0000456 clearerr(f->f_fp);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000457 return NULL;
458 }
459 INCREF(None);
460 return None;
461}
462
Guido van Rossum3f5da241990-12-20 15:06:42 +0000463static struct methodlist file_methods[] = {
Guido van Rossumce5ba841991-03-06 13:06:18 +0000464 {"close", file_close},
465 {"flush", file_flush},
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000466 {"isatty", file_isatty},
Guido van Rossum3f5da241990-12-20 15:06:42 +0000467 {"read", file_read},
468 {"readline", file_readline},
Guido van Rossumce5ba841991-03-06 13:06:18 +0000469 {"readlines", file_readlines},
470 {"seek", file_seek},
471 {"tell", file_tell},
472 {"write", file_write},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000473 {NULL, NULL} /* sentinel */
474};
475
476static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000477file_getattr(f, name)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000478 fileobject *f;
479 char *name;
480{
Guido van Rossum3f5da241990-12-20 15:06:42 +0000481 return findmethod(file_methods, (object *)f, name);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000482}
483
484typeobject Filetype = {
485 OB_HEAD_INIT(&Typetype)
486 0,
487 "file",
488 sizeof(fileobject),
489 0,
Guido van Rossum3f5da241990-12-20 15:06:42 +0000490 file_dealloc, /*tp_dealloc*/
491 file_print, /*tp_print*/
492 file_getattr, /*tp_getattr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000493 0, /*tp_setattr*/
494 0, /*tp_compare*/
Guido van Rossum3f5da241990-12-20 15:06:42 +0000495 file_repr, /*tp_repr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000496};
Guido van Rossumeb183da1991-04-04 10:44:06 +0000497
498/* Interface for the 'soft space' between print items. */
499
500int
501softspace(f, newflag)
502 object *f;
503 int newflag;
504{
505 int oldflag = 0;
506 if (f != NULL && is_fileobject(f)) {
507 oldflag = ((fileobject *)f)->f_softspace;
508 ((fileobject *)f)->f_softspace = newflag;
509 }
510 return oldflag;
511}