blob: f0383275115fd1d8594f08299fd9acd47094c3fb [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;
47 /* XXX Should move the 'need space' on printing flag here */
48} 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);
73 if (f->f_name == NULL || f->f_mode == NULL) {
74 DECREF(f);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000075 return NULL;
76 }
77 f->f_fp = fp;
78 return (object *) f;
79}
80
81object *
82newfileobject(name, mode)
83 char *name, *mode;
84{
85 fileobject *f;
86 FILE *fp;
87 f = (fileobject *) newopenfileobject((FILE *)NULL, name, mode);
88 if (f == NULL)
89 return NULL;
Guido van Rossuma08095a1991-02-13 23:25:27 +000090#ifdef THINK_C
91 if (*mode == '*') {
92 FILE *fopenRF();
93 f->f_fp = fopenRF(name, mode+1);
94 }
95 else
96#endif
97 f->f_fp = fopen(name, mode);
98 if (f->f_fp == NULL) {
99 err_errno(RuntimeError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000100 DECREF(f);
101 return NULL;
102 }
103 return (object *)f;
104}
105
106/* Methods */
107
108static void
Guido van Rossum3f5da241990-12-20 15:06:42 +0000109file_dealloc(f)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000110 fileobject *f;
111{
112 if (f->f_fp != NULL)
113 fclose(f->f_fp);
114 if (f->f_name != NULL)
115 DECREF(f->f_name);
116 if (f->f_mode != NULL)
117 DECREF(f->f_mode);
118 free((char *)f);
119}
120
121static void
Guido van Rossum3f5da241990-12-20 15:06:42 +0000122file_print(f, fp, flags)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000123 fileobject *f;
124 FILE *fp;
125 int flags;
126{
127 fprintf(fp, "<%s file ", f->f_fp == NULL ? "closed" : "open");
128 printobject(f->f_name, fp, flags);
129 fprintf(fp, ", mode ");
130 printobject(f->f_mode, fp, flags);
131 fprintf(fp, ">");
132}
133
134static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000135file_repr(f)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000136 fileobject *f;
137{
138 char buf[300];
Guido van Rossum3f5da241990-12-20 15:06:42 +0000139 /* XXX This differs from file_print if the filename contains
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000140 quotes or other funny characters. */
141 sprintf(buf, "<%s file '%.256s', mode '%.10s'>",
142 f->f_fp == NULL ? "closed" : "open",
143 getstringvalue(f->f_name),
144 getstringvalue(f->f_mode));
145 return newstringobject(buf);
146}
147
148static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000149file_close(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000150 fileobject *f;
151 object *args;
152{
153 if (args != NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000154 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000155 return NULL;
156 }
157 if (f->f_fp != NULL) {
158 fclose(f->f_fp);
159 f->f_fp = NULL;
160 }
161 INCREF(None);
162 return None;
163}
164
165static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000166file_seek(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000167 fileobject *f;
168 object *args;
169{
Guido van Rossumce5ba841991-03-06 13:06:18 +0000170 long offset;
171 long whence;
172
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000173 if (f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000174 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000175 return NULL;
176 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000177 if (args != NULL && is_intobject(args)) {
178 offset = getintvalue(args);
179 whence = 0; /* SEEK_SET */
180 }
181 else {
182 if (!getlonglongargs(args, &offset, &whence))
183 return NULL;
184 }
185 errno = 0;
186 if (fseek(f->f_fp, offset, (int)whence) != 0) {
187 if (errno == 0)
188 errno = EIO;
189 return err_errno(RuntimeError);
190 }
191 INCREF(None);
192 return None;
193}
194
195static object *
196file_tell(f, args)
197 fileobject *f;
198 object *args;
199{
200 long offset;
201 if (args != NULL || f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000202 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000203 return NULL;
204 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000205 errno = 0;
206 offset = ftell(f->f_fp);
207 if (offset == -1L) {
208 if (errno == 0)
209 errno = EIO;
210 return err_errno(RuntimeError);
211 }
212 return newintobject(offset);
213}
214
215static object *
216file_flush(f, args)
217 fileobject *f;
218 object *args;
219{
220 if (args != NULL || f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000221 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000222 return NULL;
223 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000224 errno = 0;
225 if (fflush(f->f_fp) != 0) {
226 if (errno == 0)
227 errno = EIO;
228 return err_errno(RuntimeError);
229 }
230 INCREF(None);
231 return None;
232}
233
234static object *
235file_read(f, args)
236 fileobject *f;
237 object *args;
238{
239 int n, n1, n2, n3;
240 object *v;
241
242 if (f->f_fp == NULL) {
243 err_badarg();
244 return NULL;
245 }
246 if (args == 0)
247 n = 0;
248 else {
249 if (!getintarg(args, &n))
250 return NULL;
251 if (n < 0) {
252 err_badarg();
253 return NULL;
254 }
255 }
256
257 n2 = n != 0 ? n : BUFSIZ;
258 v = newsizedstringobject((char *)NULL, n2);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000259 if (v == NULL)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000260 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000261 n1 = 0;
262 for (;;) {
263 n3 = fread(BUF(v)+n1, 1, n2-n1, f->f_fp);
264 /* XXX Error check? */
265 if (n3 == 0)
266 break;
267 n1 += n3;
268 if (n1 == n)
269 break;
270 if (n == 0) {
271 n2 = n1 + BUFSIZ;
272 if (resizestring(&v, n2) < 0)
273 return NULL;
274 }
275 }
276 if (n1 != n2)
277 resizestring(&v, n1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000278 return v;
279}
280
Guido van Rossumce5ba841991-03-06 13:06:18 +0000281/* Read a line.
282 Without argument, or with a zero argument, read until end of line
283 or EOF, whichever comes first.
284 With a positive argument n, read at most n bytes until end of line
285 or EOF, whichever comes first.
286 Negative and non-integer arguments are illegal.
287 When EOF is hit immediately, return an empty string.
288 A newline character is returned as the last character of the buffer
289 if it is read.
290*/
291
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000292/* XXX Should this be unified with raw_input()? */
293
294static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000295file_readline(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000296 fileobject *f;
297 object *args;
298{
Guido van Rossumce5ba841991-03-06 13:06:18 +0000299 register FILE *fp;
300 register int c;
301 register char *buf, *end;
302 int n, n1, n2;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000303 object *v;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000304
305 if ((fp = f->f_fp) == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000306 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000307 return NULL;
308 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000309
310 if (args == NULL)
311 n = 0; /* Unlimited */
312 else {
313 if (!getintarg(args, &n))
314 return NULL;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000315 if (n < 0) {
316 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000317 return NULL;
318 }
319 }
Guido van Rossumce5ba841991-03-06 13:06:18 +0000320
321 n2 = n != 0 ? n : 100;
322 v = newsizedstringobject((char *)NULL, n2);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000323 if (v == NULL)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000324 return NULL;
Guido van Rossumce5ba841991-03-06 13:06:18 +0000325 buf = BUF(v);
326 end = buf + n2;
327
328 for (;;) {
329 if ((c = getc(fp)) == EOF || (*buf++ = c) == '\n')
330 break;
331 /* XXX Error check? */
332 if (buf == end) {
333 if (n != 0)
334 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
350static object *
Guido van Rossumce5ba841991-03-06 13:06:18 +0000351file_readlines(f, args)
352 fileobject *f;
353 object *args;
354{
355 object *list;
356 object *line;
357
358 if ((list = newlistobject(0)) == NULL)
359 return NULL;
360 for (;;) {
361 line = file_readline(f, args);
362 if (line != NULL && getstringsize(line) == 0) {
363 DECREF(line);
364 break;
365 }
366 if (line == NULL || addlistitem(list, line) != 0) {
367 DECREF(list);
368 XDECREF(line);
369 return NULL;
370 }
371 DECREF(line);
372 }
373 return list;
374}
375
376static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000377file_write(f, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000378 fileobject *f;
379 object *args;
380{
381 int n, n2;
382 if (f->f_fp == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000383 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000384 return NULL;
385 }
386 if (args == NULL || !is_stringobject(args)) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000387 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000388 return NULL;
389 }
390 errno = 0;
391 n2 = fwrite(getstringvalue(args), 1, n = getstringsize(args), f->f_fp);
392 if (n2 != n) {
393 if (errno == 0)
394 errno = EIO;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000395 err_errno(RuntimeError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000396 return NULL;
397 }
398 INCREF(None);
399 return None;
400}
401
Guido van Rossum3f5da241990-12-20 15:06:42 +0000402static struct methodlist file_methods[] = {
Guido van Rossumce5ba841991-03-06 13:06:18 +0000403 {"close", file_close},
404 {"flush", file_flush},
Guido van Rossum3f5da241990-12-20 15:06:42 +0000405 {"read", file_read},
406 {"readline", file_readline},
Guido van Rossumce5ba841991-03-06 13:06:18 +0000407 {"readlines", file_readlines},
408 {"seek", file_seek},
409 {"tell", file_tell},
410 {"write", file_write},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000411 {NULL, NULL} /* sentinel */
412};
413
414static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000415file_getattr(f, name)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000416 fileobject *f;
417 char *name;
418{
Guido van Rossum3f5da241990-12-20 15:06:42 +0000419 return findmethod(file_methods, (object *)f, name);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000420}
421
422typeobject Filetype = {
423 OB_HEAD_INIT(&Typetype)
424 0,
425 "file",
426 sizeof(fileobject),
427 0,
Guido van Rossum3f5da241990-12-20 15:06:42 +0000428 file_dealloc, /*tp_dealloc*/
429 file_print, /*tp_print*/
430 file_getattr, /*tp_getattr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000431 0, /*tp_setattr*/
432 0, /*tp_compare*/
Guido van Rossum3f5da241990-12-20 15:06:42 +0000433 file_repr, /*tp_repr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000434};