blob: 76bcad4faacfe93ed611186b6e5fb558a96affa3 [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 *
Guido van Rossumed233a51992-06-23 09:07:03 +0000225file_fileno(f, args)
226 fileobject *f;
227 object *args;
228{
229 if (!getnoarg(args))
230 return NULL;
231 return newintobject((long) fileno(f->f_fp));
232}
233
234static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000235file_flush(f, args)
236 fileobject *f;
237 object *args;
238{
239 if (args != NULL || f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000240 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000241 return NULL;
242 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000243 errno = 0;
244 if (fflush(f->f_fp) != 0) {
Guido van Rossumfebd5511992-03-04 16:39:24 +0000245 err_errno(IOError);
246 clearerr(f->f_fp);
247 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000248 }
249 INCREF(None);
250 return None;
251}
252
253static object *
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000254file_isatty(f, args)
255 fileobject *f;
256 object *args;
257{
258 if (args != NULL || f->f_fp == NULL) {
259 err_badarg();
260 return NULL;
261 }
Guido van Rossum51415a71992-03-27 17:23:38 +0000262 return newintobject((long)isatty((int)fileno(f->f_fp)));
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000263}
264
265static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000266file_read(f, args)
267 fileobject *f;
268 object *args;
269{
270 int n, n1, n2, n3;
271 object *v;
272
273 if (f->f_fp == NULL) {
274 err_badarg();
275 return NULL;
276 }
277 if (args == 0)
278 n = 0;
279 else {
280 if (!getintarg(args, &n))
281 return NULL;
282 if (n < 0) {
283 err_badarg();
284 return NULL;
285 }
286 }
287
288 n2 = n != 0 ? n : BUFSIZ;
289 v = newsizedstringobject((char *)NULL, n2);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000290 if (v == NULL)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000291 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000292 n1 = 0;
293 for (;;) {
294 n3 = fread(BUF(v)+n1, 1, n2-n1, f->f_fp);
295 /* XXX Error check? */
296 if (n3 == 0)
297 break;
298 n1 += n3;
299 if (n1 == n)
300 break;
301 if (n == 0) {
302 n2 = n1 + BUFSIZ;
303 if (resizestring(&v, n2) < 0)
304 return NULL;
305 }
306 }
307 if (n1 != n2)
308 resizestring(&v, n1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000309 return v;
310}
311
Guido van Rossum0bd24411991-04-04 15:21:57 +0000312/* Internal routine to get a line.
313 Size argument interpretation:
314 > 0: max length;
315 = 0: read arbitrary line;
316 < 0: strip trailing '\n', raise EOFError if EOF reached immediately
Guido van Rossumce5ba841991-03-06 13:06:18 +0000317*/
318
Guido van Rossum0bd24411991-04-04 15:21:57 +0000319object *
320getline(f, n)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000321 fileobject *f;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000322 int n;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000323{
Guido van Rossumce5ba841991-03-06 13:06:18 +0000324 register FILE *fp;
325 register int c;
326 register char *buf, *end;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000327 int n1, n2;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000328 object *v;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000329
Guido van Rossumce5ba841991-03-06 13:06:18 +0000330 if ((fp = f->f_fp) == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000331 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000332 return NULL;
333 }
Guido van Rossum0bd24411991-04-04 15:21:57 +0000334
335 n2 = n > 0 ? n : 100;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000336 v = newsizedstringobject((char *)NULL, n2);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000337 if (v == NULL)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000338 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000339 buf = BUF(v);
340 end = buf + n2;
341
342 for (;;) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000343 if ((c = getc(fp)) == EOF) {
Guido van Rossum76ad8ed1991-06-03 10:54:55 +0000344 clearerr(fp);
Guido van Rossum0bd24411991-04-04 15:21:57 +0000345 if (intrcheck()) {
346 DECREF(v);
347 err_set(KeyboardInterrupt);
348 return NULL;
349 }
350 if (n < 0 && buf == BUF(v)) {
351 DECREF(v);
Guido van Rossum201be051991-12-24 13:26:41 +0000352 err_setstr(EOFError,
353 "EOF when reading a line");
Guido van Rossum0bd24411991-04-04 15:21:57 +0000354 return NULL;
355 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000356 break;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000357 }
358 if ((*buf++ = c) == '\n') {
359 if (n < 0)
360 buf--;
361 break;
362 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000363 if (buf == end) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000364 if (n > 0)
Guido van Rossumce5ba841991-03-06 13:06:18 +0000365 break;
366 n1 = n2;
367 n2 += 1000;
368 if (resizestring(&v, n2) < 0)
369 return NULL;
370 buf = BUF(v) + n1;
371 end = BUF(v) + n2;
372 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000373 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000374
375 n1 = buf - BUF(v);
376 if (n1 != n2)
377 resizestring(&v, n1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000378 return v;
379}
380
Guido van Rossum0bd24411991-04-04 15:21:57 +0000381/* External C interface */
382
383object *
384filegetline(f, n)
385 object *f;
386 int n;
387{
388 if (f == NULL || !is_fileobject(f)) {
389 err_badcall();
390 return NULL;
391 }
392 return getline((fileobject *)f, n);
393}
394
395/* Python method */
396
397static object *
398file_readline(f, args)
399 fileobject *f;
400 object *args;
401{
402 int n;
403
404 if (args == NULL)
405 n = 0; /* Unlimited */
406 else {
407 if (!getintarg(args, &n))
408 return NULL;
409 if (n < 0) {
410 err_badarg();
411 return NULL;
412 }
413 }
414
Guido van Rossum51415a71992-03-27 17:23:38 +0000415 return getline(f, n);
Guido van Rossum0bd24411991-04-04 15:21:57 +0000416}
417
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000418static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000419file_readlines(f, args)
420 fileobject *f;
421 object *args;
422{
423 object *list;
424 object *line;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000425
426 if (!getnoarg(args))
427 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000428 if ((list = newlistobject(0)) == NULL)
429 return NULL;
430 for (;;) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000431 line = getline(f, 0);
Guido van Rossumce5ba841991-03-06 13:06:18 +0000432 if (line != NULL && getstringsize(line) == 0) {
433 DECREF(line);
434 break;
435 }
436 if (line == NULL || addlistitem(list, line) != 0) {
437 DECREF(list);
438 XDECREF(line);
439 return NULL;
440 }
441 DECREF(line);
442 }
443 return list;
444}
445
446static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000447file_write(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000448 fileobject *f;
449 object *args;
450{
451 int n, n2;
452 if (f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000453 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000454 return NULL;
455 }
456 if (args == NULL || !is_stringobject(args)) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000457 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000458 return NULL;
459 }
Guido van Rossumeb183da1991-04-04 10:44:06 +0000460 f->f_softspace = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000461 errno = 0;
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000462 n2 = fwrite(getstringvalue(args), 1, n = getstringsize(args), f->f_fp);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000463 if (n2 != n) {
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000464 err_errno(IOError);
Guido van Rossumfebd5511992-03-04 16:39:24 +0000465 clearerr(f->f_fp);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000466 return NULL;
467 }
468 INCREF(None);
469 return None;
470}
471
Guido van Rossum3f5da241990-12-20 15:06:42 +0000472static struct methodlist file_methods[] = {
Guido van Rossumce5ba841991-03-06 13:06:18 +0000473 {"close", file_close},
474 {"flush", file_flush},
Guido van Rossumed233a51992-06-23 09:07:03 +0000475 {"fileno", file_fileno},
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000476 {"isatty", file_isatty},
Guido van Rossum3f5da241990-12-20 15:06:42 +0000477 {"read", file_read},
478 {"readline", file_readline},
Guido van Rossumce5ba841991-03-06 13:06:18 +0000479 {"readlines", file_readlines},
480 {"seek", file_seek},
481 {"tell", file_tell},
482 {"write", file_write},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000483 {NULL, NULL} /* sentinel */
484};
485
486static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000487file_getattr(f, name)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000488 fileobject *f;
489 char *name;
490{
Guido van Rossum3f5da241990-12-20 15:06:42 +0000491 return findmethod(file_methods, (object *)f, name);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000492}
493
494typeobject Filetype = {
495 OB_HEAD_INIT(&Typetype)
496 0,
497 "file",
498 sizeof(fileobject),
499 0,
Guido van Rossum3f5da241990-12-20 15:06:42 +0000500 file_dealloc, /*tp_dealloc*/
501 file_print, /*tp_print*/
502 file_getattr, /*tp_getattr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000503 0, /*tp_setattr*/
504 0, /*tp_compare*/
Guido van Rossum3f5da241990-12-20 15:06:42 +0000505 file_repr, /*tp_repr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000506};
Guido van Rossumeb183da1991-04-04 10:44:06 +0000507
508/* Interface for the 'soft space' between print items. */
509
510int
511softspace(f, newflag)
512 object *f;
513 int newflag;
514{
515 int oldflag = 0;
516 if (f != NULL && is_fileobject(f)) {
517 oldflag = ((fileobject *)f)->f_softspace;
518 ((fileobject *)f)->f_softspace = newflag;
519 }
520 return oldflag;
521}