blob: 47461f99a59b891f4d47e034f3fb9bdd793a7e90 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossumbab9d031992-04-05 14:26:55 +00002Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The
Guido van Rossumf70e43a1991-02-19 12:39:46 +00003Netherlands.
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;
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 Rossumfebd5511992-03-04 16:39:24 +0000166 if (sts == EOF)
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000167 return err_errno(IOError);
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000168 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 {
Guido van Rossum18a372f1991-09-10 14:55:58 +0000191 if (!getlonglongarg(args, &offset, &whence))
Guido van Rossumce5ba841991-03-06 13:06:18 +0000192 return NULL;
193 }
194 errno = 0;
195 if (fseek(f->f_fp, offset, (int)whence) != 0) {
Guido van Rossumfebd5511992-03-04 16:39:24 +0000196 err_errno(IOError);
197 clearerr(f->f_fp);
198 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000199 }
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) {
Guido van Rossumfebd5511992-03-04 16:39:24 +0000217 err_errno(IOError);
218 clearerr(f->f_fp);
219 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000220 }
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) {
Guido van Rossumfebd5511992-03-04 16:39:24 +0000235 err_errno(IOError);
236 clearerr(f->f_fp);
237 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000238 }
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 }
Guido van Rossum51415a71992-03-27 17:23:38 +0000252 return newintobject((long)isatty((int)fileno(f->f_fp)));
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000253}
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);
Guido van Rossum201be051991-12-24 13:26:41 +0000342 err_setstr(EOFError,
343 "EOF when reading a line");
Guido van Rossum0bd24411991-04-04 15:21:57 +0000344 return NULL;
345 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000346 break;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000347 }
348 if ((*buf++ = c) == '\n') {
349 if (n < 0)
350 buf--;
351 break;
352 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000353 if (buf == end) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000354 if (n > 0)
Guido van Rossumce5ba841991-03-06 13:06:18 +0000355 break;
356 n1 = n2;
357 n2 += 1000;
358 if (resizestring(&v, n2) < 0)
359 return NULL;
360 buf = BUF(v) + n1;
361 end = BUF(v) + n2;
362 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000363 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000364
365 n1 = buf - BUF(v);
366 if (n1 != n2)
367 resizestring(&v, n1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000368 return v;
369}
370
Guido van Rossum0bd24411991-04-04 15:21:57 +0000371/* External C interface */
372
373object *
374filegetline(f, n)
375 object *f;
376 int n;
377{
378 if (f == NULL || !is_fileobject(f)) {
379 err_badcall();
380 return NULL;
381 }
382 return getline((fileobject *)f, n);
383}
384
385/* Python method */
386
387static object *
388file_readline(f, args)
389 fileobject *f;
390 object *args;
391{
392 int n;
393
394 if (args == NULL)
395 n = 0; /* Unlimited */
396 else {
397 if (!getintarg(args, &n))
398 return NULL;
399 if (n < 0) {
400 err_badarg();
401 return NULL;
402 }
403 }
404
Guido van Rossum51415a71992-03-27 17:23:38 +0000405 return getline(f, n);
Guido van Rossum0bd24411991-04-04 15:21:57 +0000406}
407
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000408static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000409file_readlines(f, args)
410 fileobject *f;
411 object *args;
412{
413 object *list;
414 object *line;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000415
416 if (!getnoarg(args))
417 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000418 if ((list = newlistobject(0)) == NULL)
419 return NULL;
420 for (;;) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000421 line = getline(f, 0);
Guido van Rossumce5ba841991-03-06 13:06:18 +0000422 if (line != NULL && getstringsize(line) == 0) {
423 DECREF(line);
424 break;
425 }
426 if (line == NULL || addlistitem(list, line) != 0) {
427 DECREF(list);
428 XDECREF(line);
429 return NULL;
430 }
431 DECREF(line);
432 }
433 return list;
434}
435
436static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000437file_write(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000438 fileobject *f;
439 object *args;
440{
441 int n, n2;
442 if (f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000443 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000444 return NULL;
445 }
446 if (args == NULL || !is_stringobject(args)) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000447 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000448 return NULL;
449 }
Guido van Rossumeb183da1991-04-04 10:44:06 +0000450 f->f_softspace = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000451 errno = 0;
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000452 n2 = fwrite(getstringvalue(args), 1, n = getstringsize(args), f->f_fp);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000453 if (n2 != n) {
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000454 err_errno(IOError);
Guido van Rossumfebd5511992-03-04 16:39:24 +0000455 clearerr(f->f_fp);
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}