blob: 495737e96836a32b83ccf9cd8090c3d2da928d5e [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 Rossumdd5c7be1990-10-26 14:58:11 +000027/* XXX This should become a built-in module 'io'. It should support more
28 functionality, better exception handling for invalid calls, etc.
Guido van Rossum3f5da241990-12-20 15:06:42 +000029 (Especially reading on a write-only file or vice versa!)
Guido van Rossumdd5c7be1990-10-26 14:58:11 +000030 It should also cooperate with posix to support popen(), which should
31 share most code but have a special close function. */
32
Guido van Rossum3f5da241990-12-20 15:06:42 +000033#include "allobjects.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000034
Guido van Rossumce5ba841991-03-06 13:06:18 +000035#define BUF(v) GETSTRINGVALUE((stringobject *)v)
36
Guido van Rossum3f5da241990-12-20 15:06:42 +000037#include "errno.h"
38#ifndef errno
39extern int errno;
40#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000041
42typedef struct {
43 OB_HEAD
44 FILE *f_fp;
45 object *f_name;
46 object *f_mode;
Guido van Rossumeb183da1991-04-04 10:44:06 +000047 int f_softspace; /* Flag used by 'print' command */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000048} fileobject;
49
50FILE *
51getfilefile(f)
52 object *f;
53{
54 if (!is_fileobject(f)) {
Guido van Rossum3f5da241990-12-20 15:06:42 +000055 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000056 return NULL;
57 }
58 return ((fileobject *)f)->f_fp;
59}
60
61object *
62newopenfileobject(fp, name, mode)
63 FILE *fp;
64 char *name;
65 char *mode;
66{
67 fileobject *f = NEWOBJ(fileobject, &Filetype);
68 if (f == NULL)
69 return NULL;
70 f->f_fp = NULL;
71 f->f_name = newstringobject(name);
72 f->f_mode = newstringobject(mode);
Guido van Rossumeb183da1991-04-04 10:44:06 +000073 f->f_softspace = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000074 if (f->f_name == NULL || f->f_mode == NULL) {
75 DECREF(f);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000076 return NULL;
77 }
78 f->f_fp = fp;
79 return (object *) f;
80}
81
82object *
83newfileobject(name, mode)
84 char *name, *mode;
85{
86 fileobject *f;
87 FILE *fp;
88 f = (fileobject *) newopenfileobject((FILE *)NULL, name, mode);
89 if (f == NULL)
90 return NULL;
Guido van Rossuma08095a1991-02-13 23:25:27 +000091#ifdef THINK_C
92 if (*mode == '*') {
93 FILE *fopenRF();
94 f->f_fp = fopenRF(name, mode+1);
95 }
96 else
97#endif
98 f->f_fp = fopen(name, mode);
99 if (f->f_fp == NULL) {
100 err_errno(RuntimeError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000101 DECREF(f);
102 return NULL;
103 }
104 return (object *)f;
105}
106
107/* Methods */
108
109static void
Guido van Rossum3f5da241990-12-20 15:06:42 +0000110file_dealloc(f)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000111 fileobject *f;
112{
113 if (f->f_fp != NULL)
114 fclose(f->f_fp);
115 if (f->f_name != NULL)
116 DECREF(f->f_name);
117 if (f->f_mode != NULL)
118 DECREF(f->f_mode);
119 free((char *)f);
120}
121
122static void
Guido van Rossum3f5da241990-12-20 15:06:42 +0000123file_print(f, fp, flags)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000124 fileobject *f;
125 FILE *fp;
126 int flags;
127{
128 fprintf(fp, "<%s file ", f->f_fp == NULL ? "closed" : "open");
129 printobject(f->f_name, fp, flags);
130 fprintf(fp, ", mode ");
131 printobject(f->f_mode, fp, flags);
132 fprintf(fp, ">");
133}
134
135static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000136file_repr(f)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000137 fileobject *f;
138{
139 char buf[300];
Guido van Rossum3f5da241990-12-20 15:06:42 +0000140 /* XXX This differs from file_print if the filename contains
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000141 quotes or other funny characters. */
142 sprintf(buf, "<%s file '%.256s', mode '%.10s'>",
143 f->f_fp == NULL ? "closed" : "open",
144 getstringvalue(f->f_name),
145 getstringvalue(f->f_mode));
146 return newstringobject(buf);
147}
148
149static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000150file_close(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000151 fileobject *f;
152 object *args;
153{
154 if (args != NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000155 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000156 return NULL;
157 }
158 if (f->f_fp != NULL) {
159 fclose(f->f_fp);
160 f->f_fp = NULL;
161 }
162 INCREF(None);
163 return None;
164}
165
166static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000167file_seek(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000168 fileobject *f;
169 object *args;
170{
Guido van Rossumce5ba841991-03-06 13:06:18 +0000171 long offset;
172 long whence;
173
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000174 if (f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000175 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000176 return NULL;
177 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000178 if (args != NULL && is_intobject(args)) {
179 offset = getintvalue(args);
180 whence = 0; /* SEEK_SET */
181 }
182 else {
183 if (!getlonglongargs(args, &offset, &whence))
184 return NULL;
185 }
186 errno = 0;
187 if (fseek(f->f_fp, offset, (int)whence) != 0) {
188 if (errno == 0)
189 errno = EIO;
190 return err_errno(RuntimeError);
191 }
192 INCREF(None);
193 return None;
194}
195
196static object *
197file_tell(f, args)
198 fileobject *f;
199 object *args;
200{
201 long offset;
202 if (args != NULL || f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000203 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000204 return NULL;
205 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000206 errno = 0;
207 offset = ftell(f->f_fp);
208 if (offset == -1L) {
209 if (errno == 0)
210 errno = EIO;
211 return err_errno(RuntimeError);
212 }
213 return newintobject(offset);
214}
215
216static object *
217file_flush(f, args)
218 fileobject *f;
219 object *args;
220{
221 if (args != NULL || f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000222 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000223 return NULL;
224 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000225 errno = 0;
226 if (fflush(f->f_fp) != 0) {
227 if (errno == 0)
228 errno = EIO;
229 return err_errno(RuntimeError);
230 }
231 INCREF(None);
232 return None;
233}
234
235static object *
236file_read(f, args)
237 fileobject *f;
238 object *args;
239{
240 int n, n1, n2, n3;
241 object *v;
242
243 if (f->f_fp == NULL) {
244 err_badarg();
245 return NULL;
246 }
247 if (args == 0)
248 n = 0;
249 else {
250 if (!getintarg(args, &n))
251 return NULL;
252 if (n < 0) {
253 err_badarg();
254 return NULL;
255 }
256 }
257
258 n2 = n != 0 ? n : BUFSIZ;
259 v = newsizedstringobject((char *)NULL, n2);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000260 if (v == NULL)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000261 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000262 n1 = 0;
263 for (;;) {
264 n3 = fread(BUF(v)+n1, 1, n2-n1, f->f_fp);
265 /* XXX Error check? */
266 if (n3 == 0)
267 break;
268 n1 += n3;
269 if (n1 == n)
270 break;
271 if (n == 0) {
272 n2 = n1 + BUFSIZ;
273 if (resizestring(&v, n2) < 0)
274 return NULL;
275 }
276 }
277 if (n1 != n2)
278 resizestring(&v, n1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000279 return v;
280}
281
Guido van Rossum0bd24411991-04-04 15:21:57 +0000282/* Internal routine to get a line.
283 Size argument interpretation:
284 > 0: max length;
285 = 0: read arbitrary line;
286 < 0: strip trailing '\n', raise EOFError if EOF reached immediately
Guido van Rossumce5ba841991-03-06 13:06:18 +0000287*/
288
Guido van Rossum0bd24411991-04-04 15:21:57 +0000289object *
290getline(f, n)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000291 fileobject *f;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000292 int n;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000293{
Guido van Rossumce5ba841991-03-06 13:06:18 +0000294 register FILE *fp;
295 register int c;
296 register char *buf, *end;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000297 int n1, n2;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000298 object *v;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000299
Guido van Rossumce5ba841991-03-06 13:06:18 +0000300 if ((fp = f->f_fp) == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000301 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000302 return NULL;
303 }
Guido van Rossum0bd24411991-04-04 15:21:57 +0000304
305 n2 = n > 0 ? n : 100;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000306 v = newsizedstringobject((char *)NULL, n2);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000307 if (v == NULL)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000308 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000309 buf = BUF(v);
310 end = buf + n2;
311
312 for (;;) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000313 if ((c = getc(fp)) == EOF) {
314 if (intrcheck()) {
315 DECREF(v);
316 err_set(KeyboardInterrupt);
317 return NULL;
318 }
319 if (n < 0 && buf == BUF(v)) {
320 DECREF(v);
321 err_set(EOFError);
322 return NULL;
323 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000324 break;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000325 }
326 if ((*buf++ = c) == '\n') {
327 if (n < 0)
328 buf--;
329 break;
330 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000331 if (buf == end) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000332 if (n > 0)
Guido van Rossumce5ba841991-03-06 13:06:18 +0000333 break;
334 n1 = n2;
335 n2 += 1000;
336 if (resizestring(&v, n2) < 0)
337 return NULL;
338 buf = BUF(v) + n1;
339 end = BUF(v) + n2;
340 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000341 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000342
343 n1 = buf - BUF(v);
344 if (n1 != n2)
345 resizestring(&v, n1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000346 return v;
347}
348
Guido van Rossum0bd24411991-04-04 15:21:57 +0000349/* External C interface */
350
351object *
352filegetline(f, n)
353 object *f;
354 int n;
355{
356 if (f == NULL || !is_fileobject(f)) {
357 err_badcall();
358 return NULL;
359 }
360 return getline((fileobject *)f, n);
361}
362
363/* Python method */
364
365static object *
366file_readline(f, args)
367 fileobject *f;
368 object *args;
369{
370 int n;
371
372 if (args == NULL)
373 n = 0; /* Unlimited */
374 else {
375 if (!getintarg(args, &n))
376 return NULL;
377 if (n < 0) {
378 err_badarg();
379 return NULL;
380 }
381 }
382
383 return getline((object *)f, n);
384}
385
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000386static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000387file_readlines(f, args)
388 fileobject *f;
389 object *args;
390{
391 object *list;
392 object *line;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000393
394 if (!getnoarg(args))
395 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000396 if ((list = newlistobject(0)) == NULL)
397 return NULL;
398 for (;;) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000399 line = getline(f, 0);
Guido van Rossumce5ba841991-03-06 13:06:18 +0000400 if (line != NULL && getstringsize(line) == 0) {
401 DECREF(line);
402 break;
403 }
404 if (line == NULL || addlistitem(list, line) != 0) {
405 DECREF(list);
406 XDECREF(line);
407 return NULL;
408 }
409 DECREF(line);
410 }
411 return list;
412}
413
414static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000415file_write(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000416 fileobject *f;
417 object *args;
418{
419 int n, n2;
420 if (f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000421 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000422 return NULL;
423 }
424 if (args == NULL || !is_stringobject(args)) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000425 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000426 return NULL;
427 }
Guido van Rossumeb183da1991-04-04 10:44:06 +0000428 f->f_softspace = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000429 errno = 0;
430 n2 = fwrite(getstringvalue(args), 1, n = getstringsize(args), f->f_fp);
431 if (n2 != n) {
432 if (errno == 0)
433 errno = EIO;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000434 err_errno(RuntimeError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000435 return NULL;
436 }
437 INCREF(None);
438 return None;
439}
440
Guido van Rossum3f5da241990-12-20 15:06:42 +0000441static struct methodlist file_methods[] = {
Guido van Rossumce5ba841991-03-06 13:06:18 +0000442 {"close", file_close},
443 {"flush", file_flush},
Guido van Rossum3f5da241990-12-20 15:06:42 +0000444 {"read", file_read},
445 {"readline", file_readline},
Guido van Rossumce5ba841991-03-06 13:06:18 +0000446 {"readlines", file_readlines},
447 {"seek", file_seek},
448 {"tell", file_tell},
449 {"write", file_write},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000450 {NULL, NULL} /* sentinel */
451};
452
453static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000454file_getattr(f, name)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000455 fileobject *f;
456 char *name;
457{
Guido van Rossum3f5da241990-12-20 15:06:42 +0000458 return findmethod(file_methods, (object *)f, name);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000459}
460
461typeobject Filetype = {
462 OB_HEAD_INIT(&Typetype)
463 0,
464 "file",
465 sizeof(fileobject),
466 0,
Guido van Rossum3f5da241990-12-20 15:06:42 +0000467 file_dealloc, /*tp_dealloc*/
468 file_print, /*tp_print*/
469 file_getattr, /*tp_getattr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000470 0, /*tp_setattr*/
471 0, /*tp_compare*/
Guido van Rossum3f5da241990-12-20 15:06:42 +0000472 file_repr, /*tp_repr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000473};
Guido van Rossumeb183da1991-04-04 10:44:06 +0000474
475/* Interface for the 'soft space' between print items. */
476
477int
478softspace(f, newflag)
479 object *f;
480 int newflag;
481{
482 int oldflag = 0;
483 if (f != NULL && is_fileobject(f)) {
484 oldflag = ((fileobject *)f)->f_softspace;
485 ((fileobject *)f)->f_softspace = newflag;
486 }
487 return oldflag;
488}