(py-indent-right, py-outdent-left): new commands, bound to C-c C-r and
[python/dscho.git] / Objects / fileobject.c
blobdf27caf41fba4a7944113a2d5310ecd4bad1525d
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 /* File object implementation */
27 #include "allobjects.h"
28 #include "modsupport.h"
29 #include "structmember.h"
30 #include "ceval.h"
32 #ifdef THINK_C
33 #define HAVE_FOPENRF
34 #endif
36 #define BUF(v) GETSTRINGVALUE((stringobject *)v)
38 #include <errno.h>
40 typedef struct {
41 OB_HEAD
42 FILE *f_fp;
43 object *f_name;
44 object *f_mode;
45 int (*f_close) PROTO((FILE *));
46 int f_softspace; /* Flag used by 'print' command */
47 } fileobject;
49 FILE *
50 getfilefile(f)
51 object *f;
53 if (f == NULL || !is_fileobject(f))
54 return NULL;
55 else
56 return ((fileobject *)f)->f_fp;
59 object *
60 getfilename(f)
61 object *f;
63 if (f == NULL || !is_fileobject(f))
64 return NULL;
65 else
66 return ((fileobject *)f)->f_name;
69 object *
70 newopenfileobject(fp, name, mode, close)
71 FILE *fp;
72 char *name;
73 char *mode;
74 int (*close) FPROTO((FILE *));
76 fileobject *f = NEWOBJ(fileobject, &Filetype);
77 if (f == NULL)
78 return NULL;
79 f->f_fp = NULL;
80 f->f_name = newstringobject(name);
81 f->f_mode = newstringobject(mode);
82 f->f_close = close;
83 f->f_softspace = 0;
84 if (f->f_name == NULL || f->f_mode == NULL) {
85 DECREF(f);
86 return NULL;
88 f->f_fp = fp;
89 return (object *) f;
92 object *
93 newfileobject(name, mode)
94 char *name, *mode;
96 extern int fclose PROTO((FILE *));
97 fileobject *f;
98 f = (fileobject *) newopenfileobject((FILE *)NULL, name, mode, fclose);
99 if (f == NULL)
100 return NULL;
101 #ifdef HAVE_FOPENRF
102 if (*mode == '*') {
103 FILE *fopenRF();
104 f->f_fp = fopenRF(name, mode+1);
106 else
107 #endif
109 BGN_SAVE
110 f->f_fp = fopen(name, mode);
111 END_SAVE
113 if (f->f_fp == NULL) {
114 err_errno(IOError);
115 DECREF(f);
116 return NULL;
118 return (object *)f;
121 void
122 setfilebufsize(f, bufsize)
123 object *f;
124 int bufsize;
126 if (bufsize >= 0) {
127 #ifdef HAVE_SETVBUF
128 int type;
129 switch (bufsize) {
130 case 0:
131 type = _IONBF;
132 break;
133 case 1:
134 type = _IOLBF;
135 bufsize = BUFSIZ;
136 break;
137 default:
138 type = _IOFBF;
140 setvbuf(((fileobject *)f)->f_fp, (char *)NULL, type, bufsize);
141 #endif /* HAVE_SETVBUF */
145 static object *
146 err_closed()
148 err_setstr(ValueError, "I/O operation on closed file");
149 return NULL;
152 /* Methods */
154 static void
155 file_dealloc(f)
156 fileobject *f;
158 if (f->f_fp != NULL && f->f_close != NULL) {
159 BGN_SAVE
160 (*f->f_close)(f->f_fp);
161 END_SAVE
163 if (f->f_name != NULL)
164 DECREF(f->f_name);
165 if (f->f_mode != NULL)
166 DECREF(f->f_mode);
167 free((char *)f);
170 static object *
171 file_repr(f)
172 fileobject *f;
174 char buf[300];
175 sprintf(buf, "<%s file '%.256s', mode '%.10s' at %lx>",
176 f->f_fp == NULL ? "closed" : "open",
177 getstringvalue(f->f_name),
178 getstringvalue(f->f_mode),
179 (long)f);
180 return newstringobject(buf);
183 static object *
184 file_close(f, args)
185 fileobject *f;
186 object *args;
188 int sts = 0;
189 if (!getnoarg(args))
190 return NULL;
191 if (f->f_fp != NULL) {
192 if (f->f_close != NULL) {
193 BGN_SAVE
194 errno = 0;
195 sts = (*f->f_close)(f->f_fp);
196 END_SAVE
198 f->f_fp = NULL;
200 if (sts == EOF)
201 return err_errno(IOError);
202 if (sts != 0)
203 return newintobject((long)sts);
204 INCREF(None);
205 return None;
208 static object *
209 file_seek(f, args)
210 fileobject *f;
211 object *args;
213 long offset;
214 int whence;
215 int ret;
217 if (f->f_fp == NULL)
218 return err_closed();
219 whence = 0;
220 if (!getargs(args, "l", &offset)) {
221 err_clear();
222 if (!getargs(args, "(li)", &offset, &whence))
223 return NULL;
225 BGN_SAVE
226 errno = 0;
227 ret = fseek(f->f_fp, offset, whence);
228 END_SAVE
229 if (ret != 0) {
230 err_errno(IOError);
231 clearerr(f->f_fp);
232 return NULL;
234 INCREF(None);
235 return None;
238 #ifdef HAVE_FTRUNCATE
239 static object *
240 file_truncate(f, args)
241 fileobject *f;
242 object *args;
244 long newsize;
245 int ret;
247 if (f->f_fp == NULL)
248 return err_closed();
249 if (!getargs(args, "l", &newsize)) {
250 err_clear();
251 if (!getnoarg(args))
252 return NULL;
253 BGN_SAVE
254 errno = 0;
255 newsize = ftell(f->f_fp); /* default to current position*/
256 END_SAVE
257 if (newsize == -1L) {
258 err_errno(IOError);
259 clearerr(f->f_fp);
260 return NULL;
263 BGN_SAVE
264 errno = 0;
265 ret = fflush(f->f_fp);
266 END_SAVE
267 if (ret == 0) {
268 BGN_SAVE
269 errno = 0;
270 ret = ftruncate(fileno(f->f_fp), newsize);
271 END_SAVE
273 if (ret != 0) {
274 err_errno(IOError);
275 clearerr(f->f_fp);
276 return NULL;
278 INCREF(None);
279 return None;
281 #endif /* HAVE_FTRUNCATE */
283 static object *
284 file_tell(f, args)
285 fileobject *f;
286 object *args;
288 long offset;
289 if (f->f_fp == NULL)
290 return err_closed();
291 if (!getnoarg(args))
292 return NULL;
293 BGN_SAVE
294 errno = 0;
295 offset = ftell(f->f_fp);
296 END_SAVE
297 if (offset == -1L) {
298 err_errno(IOError);
299 clearerr(f->f_fp);
300 return NULL;
302 return newintobject(offset);
305 static object *
306 file_fileno(f, args)
307 fileobject *f;
308 object *args;
310 if (f->f_fp == NULL)
311 return err_closed();
312 if (!getnoarg(args))
313 return NULL;
314 return newintobject((long) fileno(f->f_fp));
317 static object *
318 file_flush(f, args)
319 fileobject *f;
320 object *args;
322 int res;
324 if (f->f_fp == NULL)
325 return err_closed();
326 if (!getnoarg(args))
327 return NULL;
328 BGN_SAVE
329 errno = 0;
330 res = fflush(f->f_fp);
331 END_SAVE
332 if (res != 0) {
333 err_errno(IOError);
334 clearerr(f->f_fp);
335 return NULL;
337 INCREF(None);
338 return None;
341 static object *
342 file_isatty(f, args)
343 fileobject *f;
344 object *args;
346 long res;
347 if (f->f_fp == NULL)
348 return err_closed();
349 if (!getnoarg(args))
350 return NULL;
351 BGN_SAVE
352 res = isatty((int)fileno(f->f_fp));
353 END_SAVE
354 return newintobject(res);
357 static object *
358 file_read(f, args)
359 fileobject *f;
360 object *args;
362 int n, n1, n2, n3;
363 object *v;
365 if (f->f_fp == NULL)
366 return err_closed();
367 if (args == NULL)
368 n = 0;
369 else {
370 if (!getargs(args, "i", &n))
371 return NULL;
372 if (n < 0) {
373 err_setstr(ValueError, "negative read count");
374 return NULL;
377 n2 = n != 0 ? n : BUFSIZ;
378 v = newsizedstringobject((char *)NULL, n2);
379 if (v == NULL)
380 return NULL;
381 n1 = 0;
382 BGN_SAVE
383 for (;;) {
384 n3 = fread(BUF(v)+n1, 1, n2-n1, f->f_fp);
385 /* XXX Error check? */
386 if (n3 == 0)
387 break;
388 n1 += n3;
389 if (n1 == n)
390 break;
391 if (n == 0) {
392 n2 = n1 + BUFSIZ;
393 RET_SAVE
394 if (resizestring(&v, n2) < 0)
395 return NULL;
396 RES_SAVE
399 END_SAVE
400 if (n1 != n2)
401 resizestring(&v, n1);
402 return v;
405 /* Internal routine to get a line.
406 Size argument interpretation:
407 > 0: max length;
408 = 0: read arbitrary line;
409 < 0: strip trailing '\n', raise EOFError if EOF reached immediately
412 static object *
413 getline(f, n)
414 fileobject *f;
415 int n;
417 register FILE *fp;
418 register int c;
419 register char *buf, *end;
420 int n1, n2;
421 object *v;
423 fp = f->f_fp;
424 n2 = n > 0 ? n : 100;
425 v = newsizedstringobject((char *)NULL, n2);
426 if (v == NULL)
427 return NULL;
428 buf = BUF(v);
429 end = buf + n2;
431 BGN_SAVE
432 for (;;) {
433 if ((c = getc(fp)) == EOF) {
434 clearerr(fp);
435 if (sigcheck()) {
436 RET_SAVE
437 DECREF(v);
438 return NULL;
440 if (n < 0 && buf == BUF(v)) {
441 RET_SAVE
442 DECREF(v);
443 err_setstr(EOFError,
444 "EOF when reading a line");
445 return NULL;
447 break;
449 if ((*buf++ = c) == '\n') {
450 if (n < 0)
451 buf--;
452 break;
454 if (buf == end) {
455 if (n > 0)
456 break;
457 n1 = n2;
458 n2 += 1000;
459 RET_SAVE
460 if (resizestring(&v, n2) < 0)
461 return NULL;
462 RES_SAVE
463 buf = BUF(v) + n1;
464 end = BUF(v) + n2;
467 END_SAVE
469 n1 = buf - BUF(v);
470 if (n1 != n2)
471 resizestring(&v, n1);
472 return v;
475 /* External C interface */
477 object *
478 filegetline(f, n)
479 object *f;
480 int n;
482 if (f == NULL) {
483 err_badcall();
484 return NULL;
486 if (!is_fileobject(f)) {
487 object *reader;
488 object *args;
489 object *result;
490 reader = getattr(f, "readline");
491 if (reader == NULL)
492 return NULL;
493 if (n <= 0)
494 args = mkvalue("()");
495 else
496 args = mkvalue("(i)", n);
497 if (args == NULL) {
498 DECREF(reader);
499 return NULL;
501 result = call_object(reader, args);
502 DECREF(reader);
503 DECREF(args);
504 if (result != NULL && !is_stringobject(result)) {
505 DECREF(result);
506 result = NULL;
507 err_setstr(TypeError,
508 "object.readline() returned non-string");
510 if (n < 0 && result != NULL) {
511 char *s = getstringvalue(result);
512 int len = getstringsize(result);
513 if (len == 0) {
514 DECREF(result);
515 result = NULL;
516 err_setstr(EOFError,
517 "EOF when reading a line");
519 else if (s[len-1] == '\n') {
520 if (result->ob_refcnt == 1)
521 resizestring(&result, len-1);
522 else {
523 object *v;
524 v = newsizedstringobject(s, len-1);
525 DECREF(result);
526 result = v;
530 return result;
532 if (((fileobject*)f)->f_fp == NULL)
533 return err_closed();
534 return getline((fileobject *)f, n);
537 /* Python method */
539 static object *
540 file_readline(f, args)
541 fileobject *f;
542 object *args;
544 int n;
546 if (f->f_fp == NULL)
547 return err_closed();
548 if (args == NULL)
549 n = 0; /* Unlimited */
550 else {
551 if (!getintarg(args, &n))
552 return NULL;
553 if (n < 0) {
554 err_setstr(ValueError, "negative readline count");
555 return NULL;
559 return getline(f, n);
562 static object *
563 file_readlines(f, args)
564 fileobject *f;
565 object *args;
567 object *list;
568 object *line;
570 if (f->f_fp == NULL)
571 return err_closed();
572 if (!getnoarg(args))
573 return NULL;
574 if ((list = newlistobject(0)) == NULL)
575 return NULL;
576 for (;;) {
577 line = getline(f, 0);
578 if (line != NULL && getstringsize(line) == 0) {
579 DECREF(line);
580 break;
582 if (line == NULL || addlistitem(list, line) != 0) {
583 DECREF(list);
584 XDECREF(line);
585 return NULL;
587 DECREF(line);
589 return list;
592 static object *
593 file_write(f, args)
594 fileobject *f;
595 object *args;
597 char *s;
598 int n, n2;
599 if (f->f_fp == NULL)
600 return err_closed();
601 if (!getargs(args, "s#", &s, &n))
602 return NULL;
603 f->f_softspace = 0;
604 BGN_SAVE
605 errno = 0;
606 n2 = fwrite(s, 1, n, f->f_fp);
607 END_SAVE
608 if (n2 != n) {
609 err_errno(IOError);
610 clearerr(f->f_fp);
611 return NULL;
613 INCREF(None);
614 return None;
617 static object *
618 file_writelines(f, args)
619 fileobject *f;
620 object *args;
622 int i, n;
623 if (f->f_fp == NULL)
624 return err_closed();
625 if (args == NULL || !is_listobject(args)) {
626 err_setstr(TypeError,
627 "writelines() requires list of strings");
628 return NULL;
630 n = getlistsize(args);
631 f->f_softspace = 0;
632 BGN_SAVE
633 errno = 0;
634 for (i = 0; i < n; i++) {
635 object *line = getlistitem(args, i);
636 int len;
637 int nwritten;
638 if (!is_stringobject(line)) {
639 RET_SAVE
640 err_setstr(TypeError,
641 "writelines() requires list of strings");
642 return NULL;
644 len = getstringsize(line);
645 nwritten = fwrite(getstringvalue(line), 1, len, f->f_fp);
646 if (nwritten != len) {
647 RET_SAVE
648 err_errno(IOError);
649 clearerr(f->f_fp);
650 return NULL;
653 END_SAVE
654 INCREF(None);
655 return None;
658 static struct methodlist file_methods[] = {
659 {"close", (method)file_close, 0},
660 {"flush", (method)file_flush, 0},
661 {"fileno", (method)file_fileno, 0},
662 {"isatty", (method)file_isatty, 0},
663 {"read", (method)file_read, 0},
664 {"readline", (method)file_readline, 0},
665 {"readlines", (method)file_readlines, 0},
666 {"seek", (method)file_seek, 0},
667 #ifdef HAVE_FTRUNCATE
668 {"truncate", (method)file_truncate, 0},
669 #endif
670 {"tell", (method)file_tell, 0},
671 {"write", (method)file_write, 0},
672 {"writelines", (method)file_writelines, 0},
673 {NULL, NULL} /* sentinel */
676 #define OFF(x) offsetof(fileobject, x)
678 static struct memberlist file_memberlist[] = {
679 {"softspace", T_INT, OFF(f_softspace)},
680 {"mode", T_OBJECT, OFF(f_mode), RO},
681 {"name", T_OBJECT, OFF(f_name), RO},
682 /* getattr(f, "closed") is implemented without this table */
683 {"closed", T_INT, 0, RO},
684 {NULL} /* Sentinel */
687 static object *
688 file_getattr(f, name)
689 fileobject *f;
690 char *name;
692 object *res;
694 res = findmethod(file_methods, (object *)f, name);
695 if (res != NULL)
696 return res;
697 err_clear();
698 if (strcmp(name, "closed") == 0)
699 return newintobject((long)(f->f_fp == 0));
700 return getmember((char *)f, file_memberlist, name);
703 static int
704 file_setattr(f, name, v)
705 fileobject *f;
706 char *name;
707 object *v;
709 if (v == NULL) {
710 err_setstr(AttributeError, "can't delete file attributes");
711 return -1;
713 return setmember((char *)f, file_memberlist, name, v);
716 typeobject Filetype = {
717 OB_HEAD_INIT(&Typetype)
719 "file",
720 sizeof(fileobject),
722 (destructor)file_dealloc, /*tp_dealloc*/
723 0, /*tp_print*/
724 (getattrfunc)file_getattr, /*tp_getattr*/
725 (setattrfunc)file_setattr, /*tp_setattr*/
726 0, /*tp_compare*/
727 (reprfunc)file_repr, /*tp_repr*/
730 /* Interface for the 'soft space' between print items. */
733 softspace(f, newflag)
734 object *f;
735 int newflag;
737 int oldflag = 0;
738 if (f == NULL) {
739 /* Do nothing */
741 else if (is_fileobject(f)) {
742 oldflag = ((fileobject *)f)->f_softspace;
743 ((fileobject *)f)->f_softspace = newflag;
745 else {
746 object *v;
747 v = getattr(f, "softspace");
748 if (v == NULL)
749 err_clear();
750 else {
751 if (is_intobject(v))
752 oldflag = getintvalue(v);
753 DECREF(v);
755 v = newintobject((long)newflag);
756 if (v == NULL)
757 err_clear();
758 else {
759 if (setattr(f, "softspace", v) != 0)
760 err_clear();
761 DECREF(v);
764 return oldflag;
767 /* Interfaces to write objects/strings to file-like objects */
770 writeobject(v, f, flags)
771 object *v;
772 object *f;
773 int flags;
775 object *writer, *value, *result;
776 if (f == NULL) {
777 err_setstr(TypeError, "writeobject with NULL file");
778 return -1;
780 else if (is_fileobject(f)) {
781 FILE *fp = getfilefile(f);
782 if (fp == NULL) {
783 err_closed();
784 return -1;
786 return printobject(v, fp, flags);
788 writer = getattr(f, "write");
789 if (writer == NULL)
790 return -1;
791 if (flags & PRINT_RAW)
792 value = strobject(v);
793 else
794 value = reprobject(v);
795 if (value == NULL) {
796 DECREF(writer);
797 return -1;
799 result = call_object(writer, value);
800 DECREF(writer);
801 DECREF(value);
802 if (result == NULL)
803 return -1;
804 DECREF(result);
805 return 0;
808 void
809 writestring(s, f)
810 char *s;
811 object *f;
813 if (f == NULL) {
814 /* Do nothing */
816 else if (is_fileobject(f)) {
817 FILE *fp = getfilefile(f);
818 if (fp != NULL)
819 fputs(s, fp);
821 else if (!err_occurred()) {
822 object *v = newstringobject(s);
823 if (v == NULL) {
824 err_clear();
826 else {
827 if (writeobject(v, f, PRINT_RAW) != 0)
828 err_clear();
829 DECREF(v);