blob: b168ccfabbfc8f1e10590f3565c7cc3d3d1155d1 [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) {
98 err_errno(RuntimeError);
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
120static void
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");
127 printobject(f->f_name, fp, flags);
128 fprintf(fp, ", mode ");
129 printobject(f->f_mode, fp, flags);
130 fprintf(fp, ">");
131}
132
133static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000134file_repr(f)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000135 fileobject *f;
136{
137 char buf[300];
Guido van Rossum3f5da241990-12-20 15:06:42 +0000138 /* XXX This differs from file_print if the filename contains
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000139 quotes or other funny characters. */
140 sprintf(buf, "<%s file '%.256s', mode '%.10s'>",
141 f->f_fp == NULL ? "closed" : "open",
142 getstringvalue(f->f_name),
143 getstringvalue(f->f_mode));
144 return newstringobject(buf);
145}
146
147static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000148file_close(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000149 fileobject *f;
150 object *args;
151{
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000152 int sts = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000153 if (args != NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000154 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000155 return NULL;
156 }
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000157 errno = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000158 if (f->f_fp != NULL) {
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000159 if (f->f_close != NULL)
160 sts = (*f->f_close)(f->f_fp);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000161 f->f_fp = NULL;
162 }
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000163 if (sts == EOF) {
164 if (errno == 0)
165 errno = EIO;
166 return err_errno(RuntimeError);
167 }
168 if (sts != 0)
169 return newintobject((long)sts);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000170 INCREF(None);
171 return None;
172}
173
174static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000175file_seek(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000176 fileobject *f;
177 object *args;
178{
Guido van Rossumce5ba841991-03-06 13:06:18 +0000179 long offset;
180 long whence;
181
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000182 if (f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000183 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000184 return NULL;
185 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000186 if (args != NULL && is_intobject(args)) {
187 offset = getintvalue(args);
188 whence = 0; /* SEEK_SET */
189 }
190 else {
191 if (!getlonglongargs(args, &offset, &whence))
192 return NULL;
193 }
194 errno = 0;
195 if (fseek(f->f_fp, offset, (int)whence) != 0) {
196 if (errno == 0)
197 errno = EIO;
198 return err_errno(RuntimeError);
199 }
200 INCREF(None);
201 return None;
202}
203
204static object *
205file_tell(f, args)
206 fileobject *f;
207 object *args;
208{
209 long offset;
210 if (args != NULL || f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000211 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000212 return NULL;
213 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000214 errno = 0;
215 offset = ftell(f->f_fp);
216 if (offset == -1L) {
217 if (errno == 0)
218 errno = EIO;
219 return err_errno(RuntimeError);
220 }
221 return newintobject(offset);
222}
223
224static object *
225file_flush(f, args)
226 fileobject *f;
227 object *args;
228{
229 if (args != NULL || f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000230 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000231 return NULL;
232 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000233 errno = 0;
234 if (fflush(f->f_fp) != 0) {
235 if (errno == 0)
236 errno = EIO;
237 return err_errno(RuntimeError);
238 }
239 INCREF(None);
240 return None;
241}
242
243static object *
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000244file_isatty(f, args)
245 fileobject *f;
246 object *args;
247{
248 if (args != NULL || f->f_fp == NULL) {
249 err_badarg();
250 return NULL;
251 }
252 return newintobject((long)isatty(fileno(f->f_fp)));
253}
254
255static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000256file_read(f, args)
257 fileobject *f;
258 object *args;
259{
260 int n, n1, n2, n3;
261 object *v;
262
263 if (f->f_fp == NULL) {
264 err_badarg();
265 return NULL;
266 }
267 if (args == 0)
268 n = 0;
269 else {
270 if (!getintarg(args, &n))
271 return NULL;
272 if (n < 0) {
273 err_badarg();
274 return NULL;
275 }
276 }
277
278 n2 = n != 0 ? n : BUFSIZ;
279 v = newsizedstringobject((char *)NULL, n2);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000280 if (v == NULL)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000281 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000282 n1 = 0;
283 for (;;) {
284 n3 = fread(BUF(v)+n1, 1, n2-n1, f->f_fp);
285 /* XXX Error check? */
286 if (n3 == 0)
287 break;
288 n1 += n3;
289 if (n1 == n)
290 break;
291 if (n == 0) {
292 n2 = n1 + BUFSIZ;
293 if (resizestring(&v, n2) < 0)
294 return NULL;
295 }
296 }
297 if (n1 != n2)
298 resizestring(&v, n1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000299 return v;
300}
301
Guido van Rossum0bd24411991-04-04 15:21:57 +0000302/* Internal routine to get a line.
303 Size argument interpretation:
304 > 0: max length;
305 = 0: read arbitrary line;
306 < 0: strip trailing '\n', raise EOFError if EOF reached immediately
Guido van Rossumce5ba841991-03-06 13:06:18 +0000307*/
308
Guido van Rossum0bd24411991-04-04 15:21:57 +0000309object *
310getline(f, n)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000311 fileobject *f;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000312 int n;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000313{
Guido van Rossumce5ba841991-03-06 13:06:18 +0000314 register FILE *fp;
315 register int c;
316 register char *buf, *end;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000317 int n1, n2;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000318 object *v;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000319
Guido van Rossumce5ba841991-03-06 13:06:18 +0000320 if ((fp = f->f_fp) == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000321 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000322 return NULL;
323 }
Guido van Rossum0bd24411991-04-04 15:21:57 +0000324
325 n2 = n > 0 ? n : 100;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000326 v = newsizedstringobject((char *)NULL, n2);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000327 if (v == NULL)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000328 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000329 buf = BUF(v);
330 end = buf + n2;
331
332 for (;;) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000333 if ((c = getc(fp)) == EOF) {
Guido van Rossum76ad8ed1991-06-03 10:54:55 +0000334 clearerr(fp);
Guido van Rossum0bd24411991-04-04 15:21:57 +0000335 if (intrcheck()) {
336 DECREF(v);
337 err_set(KeyboardInterrupt);
338 return NULL;
339 }
340 if (n < 0 && buf == BUF(v)) {
341 DECREF(v);
342 err_set(EOFError);
343 return NULL;
344 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000345 break;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000346 }
347 if ((*buf++ = c) == '\n') {
348 if (n < 0)
349 buf--;
350 break;
351 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000352 if (buf == end) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000353 if (n > 0)
Guido van Rossumce5ba841991-03-06 13:06:18 +0000354 break;
355 n1 = n2;
356 n2 += 1000;
357 if (resizestring(&v, n2) < 0)
358 return NULL;
359 buf = BUF(v) + n1;
360 end = BUF(v) + n2;
361 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000362 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000363
364 n1 = buf - BUF(v);
365 if (n1 != n2)
366 resizestring(&v, n1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000367 return v;
368}
369
Guido van Rossum0bd24411991-04-04 15:21:57 +0000370/* External C interface */
371
372object *
373filegetline(f, n)
374 object *f;
375 int n;
376{
377 if (f == NULL || !is_fileobject(f)) {
378 err_badcall();
379 return NULL;
380 }
381 return getline((fileobject *)f, n);
382}
383
384/* Python method */
385
386static object *
387file_readline(f, args)
388 fileobject *f;
389 object *args;
390{
391 int n;
392
393 if (args == NULL)
394 n = 0; /* Unlimited */
395 else {
396 if (!getintarg(args, &n))
397 return NULL;
398 if (n < 0) {
399 err_badarg();
400 return NULL;
401 }
402 }
403
404 return getline((object *)f, n);
405}
406
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000407static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000408file_readlines(f, args)
409 fileobject *f;
410 object *args;
411{
412 object *list;
413 object *line;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000414
415 if (!getnoarg(args))
416 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000417 if ((list = newlistobject(0)) == NULL)
418 return NULL;
419 for (;;) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000420 line = getline(f, 0);
Guido van Rossumce5ba841991-03-06 13:06:18 +0000421 if (line != NULL && getstringsize(line) == 0) {
422 DECREF(line);
423 break;
424 }
425 if (line == NULL || addlistitem(list, line) != 0) {
426 DECREF(list);
427 XDECREF(line);
428 return NULL;
429 }
430 DECREF(line);
431 }
432 return list;
433}
434
435static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000436file_write(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000437 fileobject *f;
438 object *args;
439{
440 int n, n2;
441 if (f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000442 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000443 return NULL;
444 }
445 if (args == NULL || !is_stringobject(args)) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000446 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000447 return NULL;
448 }
Guido van Rossumeb183da1991-04-04 10:44:06 +0000449 f->f_softspace = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000450 errno = 0;
451 n2 = fwrite(getstringvalue(args), 1, n = getstringsize(args), f->f_fp);
452 if (n2 != n) {
453 if (errno == 0)
454 errno = EIO;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000455 err_errno(RuntimeError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000456 return NULL;
457 }
458 INCREF(None);
459 return None;
460}
461
Guido van Rossum3f5da241990-12-20 15:06:42 +0000462static struct methodlist file_methods[] = {
Guido van Rossumce5ba841991-03-06 13:06:18 +0000463 {"close", file_close},
464 {"flush", file_flush},
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000465 {"isatty", file_isatty},
Guido van Rossum3f5da241990-12-20 15:06:42 +0000466 {"read", file_read},
467 {"readline", file_readline},
Guido van Rossumce5ba841991-03-06 13:06:18 +0000468 {"readlines", file_readlines},
469 {"seek", file_seek},
470 {"tell", file_tell},
471 {"write", file_write},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000472 {NULL, NULL} /* sentinel */
473};
474
475static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000476file_getattr(f, name)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000477 fileobject *f;
478 char *name;
479{
Guido van Rossum3f5da241990-12-20 15:06:42 +0000480 return findmethod(file_methods, (object *)f, name);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000481}
482
483typeobject Filetype = {
484 OB_HEAD_INIT(&Typetype)
485 0,
486 "file",
487 sizeof(fileobject),
488 0,
Guido van Rossum3f5da241990-12-20 15:06:42 +0000489 file_dealloc, /*tp_dealloc*/
490 file_print, /*tp_print*/
491 file_getattr, /*tp_getattr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000492 0, /*tp_setattr*/
493 0, /*tp_compare*/
Guido van Rossum3f5da241990-12-20 15:06:42 +0000494 file_repr, /*tp_repr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000495};
Guido van Rossumeb183da1991-04-04 10:44:06 +0000496
497/* Interface for the 'soft space' between print items. */
498
499int
500softspace(f, newflag)
501 object *f;
502 int newflag;
503{
504 int oldflag = 0;
505 if (f != NULL && is_fileobject(f)) {
506 oldflag = ((fileobject *)f)->f_softspace;
507 ((fileobject *)f)->f_softspace = newflag;
508 }
509 return oldflag;
510}