blob: e6461a14d5ee7bb7ed4ff4831658dd11f2bde0a8 [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) {
Guido van Rossum76ad8ed1991-06-03 10:54:55 +0000314 clearerr(fp);
Guido van Rossum0bd24411991-04-04 15:21:57 +0000315 if (intrcheck()) {
316 DECREF(v);
317 err_set(KeyboardInterrupt);
318 return NULL;
319 }
320 if (n < 0 && buf == BUF(v)) {
321 DECREF(v);
322 err_set(EOFError);
323 return NULL;
324 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000325 break;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000326 }
327 if ((*buf++ = c) == '\n') {
328 if (n < 0)
329 buf--;
330 break;
331 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000332 if (buf == end) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000333 if (n > 0)
Guido van Rossumce5ba841991-03-06 13:06:18 +0000334 break;
335 n1 = n2;
336 n2 += 1000;
337 if (resizestring(&v, n2) < 0)
338 return NULL;
339 buf = BUF(v) + n1;
340 end = BUF(v) + n2;
341 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000342 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000343
344 n1 = buf - BUF(v);
345 if (n1 != n2)
346 resizestring(&v, n1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000347 return v;
348}
349
Guido van Rossum0bd24411991-04-04 15:21:57 +0000350/* External C interface */
351
352object *
353filegetline(f, n)
354 object *f;
355 int n;
356{
357 if (f == NULL || !is_fileobject(f)) {
358 err_badcall();
359 return NULL;
360 }
361 return getline((fileobject *)f, n);
362}
363
364/* Python method */
365
366static object *
367file_readline(f, args)
368 fileobject *f;
369 object *args;
370{
371 int n;
372
373 if (args == NULL)
374 n = 0; /* Unlimited */
375 else {
376 if (!getintarg(args, &n))
377 return NULL;
378 if (n < 0) {
379 err_badarg();
380 return NULL;
381 }
382 }
383
384 return getline((object *)f, n);
385}
386
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000387static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000388file_readlines(f, args)
389 fileobject *f;
390 object *args;
391{
392 object *list;
393 object *line;
Guido van Rossum0bd24411991-04-04 15:21:57 +0000394
395 if (!getnoarg(args))
396 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000397 if ((list = newlistobject(0)) == NULL)
398 return NULL;
399 for (;;) {
Guido van Rossum0bd24411991-04-04 15:21:57 +0000400 line = getline(f, 0);
Guido van Rossumce5ba841991-03-06 13:06:18 +0000401 if (line != NULL && getstringsize(line) == 0) {
402 DECREF(line);
403 break;
404 }
405 if (line == NULL || addlistitem(list, line) != 0) {
406 DECREF(list);
407 XDECREF(line);
408 return NULL;
409 }
410 DECREF(line);
411 }
412 return list;
413}
414
415static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000416file_write(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000417 fileobject *f;
418 object *args;
419{
420 int n, n2;
421 if (f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000422 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000423 return NULL;
424 }
425 if (args == NULL || !is_stringobject(args)) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000426 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000427 return NULL;
428 }
Guido van Rossumeb183da1991-04-04 10:44:06 +0000429 f->f_softspace = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000430 errno = 0;
431 n2 = fwrite(getstringvalue(args), 1, n = getstringsize(args), f->f_fp);
432 if (n2 != n) {
433 if (errno == 0)
434 errno = EIO;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000435 err_errno(RuntimeError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000436 return NULL;
437 }
438 INCREF(None);
439 return None;
440}
441
Guido van Rossum3f5da241990-12-20 15:06:42 +0000442static struct methodlist file_methods[] = {
Guido van Rossumce5ba841991-03-06 13:06:18 +0000443 {"close", file_close},
444 {"flush", file_flush},
Guido van Rossum3f5da241990-12-20 15:06:42 +0000445 {"read", file_read},
446 {"readline", file_readline},
Guido van Rossumce5ba841991-03-06 13:06:18 +0000447 {"readlines", file_readlines},
448 {"seek", file_seek},
449 {"tell", file_tell},
450 {"write", file_write},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000451 {NULL, NULL} /* sentinel */
452};
453
454static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000455file_getattr(f, name)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000456 fileobject *f;
457 char *name;
458{
Guido van Rossum3f5da241990-12-20 15:06:42 +0000459 return findmethod(file_methods, (object *)f, name);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000460}
461
462typeobject Filetype = {
463 OB_HEAD_INIT(&Typetype)
464 0,
465 "file",
466 sizeof(fileobject),
467 0,
Guido van Rossum3f5da241990-12-20 15:06:42 +0000468 file_dealloc, /*tp_dealloc*/
469 file_print, /*tp_print*/
470 file_getattr, /*tp_getattr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000471 0, /*tp_setattr*/
472 0, /*tp_compare*/
Guido van Rossum3f5da241990-12-20 15:06:42 +0000473 file_repr, /*tp_repr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000474};
Guido van Rossumeb183da1991-04-04 10:44:06 +0000475
476/* Interface for the 'soft space' between print items. */
477
478int
479softspace(f, newflag)
480 object *f;
481 int newflag;
482{
483 int oldflag = 0;
484 if (f != NULL && is_fileobject(f)) {
485 oldflag = ((fileobject *)f)->f_softspace;
486 ((fileobject *)f)->f_softspace = newflag;
487 }
488 return oldflag;
489}