blob: 143f6971d7eef9557575cfb3433c23f34abc521b [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
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;
169 return err_errno(RuntimeError);
170 }
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 {
194 if (!getlonglongargs(args, &offset, &whence))
195 return NULL;
196 }
197 errno = 0;
198 if (fseek(f->f_fp, offset, (int)whence) != 0) {
199 if (errno == 0)
200 errno = EIO;
201 return err_errno(RuntimeError);
202 }
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;
222 return err_errno(RuntimeError);
223 }
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;
240 return err_errno(RuntimeError);
241 }
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);
345 err_set(EOFError);
346 return NULL;
347 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000348 break;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000349 }
350 if ((*buf++ = c) == '\n') {
351 if (n < 0)
352 buf--;
353 break;
354 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000355 if (buf == end) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000356 if (n > 0)
Guido van Rossumce5ba841991-03-06 13:06:18 +0000357 break;
358 n1 = n2;
359 n2 += 1000;
360 if (resizestring(&v, n2) < 0)
361 return NULL;
362 buf = BUF(v) + n1;
363 end = BUF(v) + n2;
364 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000365 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000366
367 n1 = buf - BUF(v);
368 if (n1 != n2)
369 resizestring(&v, n1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000370 return v;
371}
372
Guido van Rossum0bd24411991-04-04 15:21:57 +0000373/* External C interface */
374
375object *
376filegetline(f, n)
377 object *f;
378 int n;
379{
380 if (f == NULL || !is_fileobject(f)) {
381 err_badcall();
382 return NULL;
383 }
384 return getline((fileobject *)f, n);
385}
386
387/* Python method */
388
389static object *
390file_readline(f, args)
391 fileobject *f;
392 object *args;
393{
394 int n;
395
396 if (args == NULL)
397 n = 0; /* Unlimited */
398 else {
399 if (!getintarg(args, &n))
400 return NULL;
401 if (n < 0) {
402 err_badarg();
403 return NULL;
404 }
405 }
406
407 return getline((object *)f, n);
408}
409
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000410static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000411file_readlines(f, args)
412 fileobject *f;
413 object *args;
414{
415 object *list;
416 object *line;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000417
418 if (!getnoarg(args))
419 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000420 if ((list = newlistobject(0)) == NULL)
421 return NULL;
422 for (;;) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000423 line = getline(f, 0);
Guido van Rossumce5ba841991-03-06 13:06:18 +0000424 if (line != NULL && getstringsize(line) == 0) {
425 DECREF(line);
426 break;
427 }
428 if (line == NULL || addlistitem(list, line) != 0) {
429 DECREF(list);
430 XDECREF(line);
431 return NULL;
432 }
433 DECREF(line);
434 }
435 return list;
436}
437
438static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000439file_write(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000440 fileobject *f;
441 object *args;
442{
443 int n, n2;
444 if (f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000445 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000446 return NULL;
447 }
448 if (args == NULL || !is_stringobject(args)) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000449 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000450 return NULL;
451 }
Guido van Rossumeb183da1991-04-04 10:44:06 +0000452 f->f_softspace = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000453 errno = 0;
454 n2 = fwrite(getstringvalue(args), 1, n = getstringsize(args), f->f_fp);
455 if (n2 != n) {
456 if (errno == 0)
457 errno = EIO;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000458 err_errno(RuntimeError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000459 return NULL;
460 }
461 INCREF(None);
462 return None;
463}
464
Guido van Rossum3f5da241990-12-20 15:06:42 +0000465static struct methodlist file_methods[] = {
Guido van Rossumce5ba841991-03-06 13:06:18 +0000466 {"close", file_close},
467 {"flush", file_flush},
Guido van Rossuma1ab7fa1991-06-04 19:37:39 +0000468 {"isatty", file_isatty},
Guido van Rossum3f5da241990-12-20 15:06:42 +0000469 {"read", file_read},
470 {"readline", file_readline},
Guido van Rossumce5ba841991-03-06 13:06:18 +0000471 {"readlines", file_readlines},
472 {"seek", file_seek},
473 {"tell", file_tell},
474 {"write", file_write},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000475 {NULL, NULL} /* sentinel */
476};
477
478static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000479file_getattr(f, name)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000480 fileobject *f;
481 char *name;
482{
Guido van Rossum3f5da241990-12-20 15:06:42 +0000483 return findmethod(file_methods, (object *)f, name);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000484}
485
486typeobject Filetype = {
487 OB_HEAD_INIT(&Typetype)
488 0,
489 "file",
490 sizeof(fileobject),
491 0,
Guido van Rossum3f5da241990-12-20 15:06:42 +0000492 file_dealloc, /*tp_dealloc*/
493 file_print, /*tp_print*/
494 file_getattr, /*tp_getattr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000495 0, /*tp_setattr*/
496 0, /*tp_compare*/
Guido van Rossum3f5da241990-12-20 15:06:42 +0000497 file_repr, /*tp_repr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000498};
Guido van Rossumeb183da1991-04-04 10:44:06 +0000499
500/* Interface for the 'soft space' between print items. */
501
502int
503softspace(f, newflag)
504 object *f;
505 int newflag;
506{
507 int oldflag = 0;
508 if (f != NULL && is_fileobject(f)) {
509 oldflag = ((fileobject *)f)->f_softspace;
510 ((fileobject *)f)->f_softspace = newflag;
511 }
512 return oldflag;
513}