1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
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"
36 #define BUF(v) GETSTRINGVALUE((stringobject *)v)
45 int (*f_close
) PROTO((FILE *));
46 int f_softspace
; /* Flag used by 'print' command */
53 if (f
== NULL
|| !is_fileobject(f
))
56 return ((fileobject
*)f
)->f_fp
;
63 if (f
== NULL
|| !is_fileobject(f
))
66 return ((fileobject
*)f
)->f_name
;
70 newopenfileobject(fp
, name
, mode
, close
)
74 int (*close
) FPROTO((FILE *));
76 fileobject
*f
= NEWOBJ(fileobject
, &Filetype
);
80 f
->f_name
= newstringobject(name
);
81 f
->f_mode
= newstringobject(mode
);
84 if (f
->f_name
== NULL
|| f
->f_mode
== NULL
) {
93 newfileobject(name
, mode
)
96 extern int fclose
PROTO((FILE *));
98 f
= (fileobject
*) newopenfileobject((FILE *)NULL
, name
, mode
, fclose
);
104 f
->f_fp
= fopenRF(name
, mode
+1);
110 f
->f_fp
= fopen(name
, mode
);
113 if (f
->f_fp
== NULL
) {
122 setfilebufsize(f
, bufsize
)
140 setvbuf(((fileobject
*)f
)->f_fp
, (char *)NULL
, type
, bufsize
);
141 #endif /* HAVE_SETVBUF */
148 err_setstr(ValueError
, "I/O operation on closed file");
158 if (f
->f_fp
!= NULL
&& f
->f_close
!= NULL
) {
160 (*f
->f_close
)(f
->f_fp
);
163 if (f
->f_name
!= NULL
)
165 if (f
->f_mode
!= NULL
)
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
),
180 return newstringobject(buf
);
191 if (f
->f_fp
!= NULL
) {
192 if (f
->f_close
!= NULL
) {
195 sts
= (*f
->f_close
)(f
->f_fp
);
201 return err_errno(IOError
);
203 return newintobject((long)sts
);
220 if (!getargs(args
, "l", &offset
)) {
222 if (!getargs(args
, "(li)", &offset
, &whence
))
227 ret
= fseek(f
->f_fp
, offset
, whence
);
238 #ifdef HAVE_FTRUNCATE
240 file_truncate(f
, args
)
249 if (!getargs(args
, "l", &newsize
)) {
255 newsize
= ftell(f
->f_fp
); /* default to current position*/
257 if (newsize
== -1L) {
265 ret
= fflush(f
->f_fp
);
270 ret
= ftruncate(fileno(f
->f_fp
), newsize
);
281 #endif /* HAVE_FTRUNCATE */
295 offset
= ftell(f
->f_fp
);
302 return newintobject(offset
);
314 return newintobject((long) fileno(f
->f_fp
));
330 res
= fflush(f
->f_fp
);
352 res
= isatty((int)fileno(f
->f_fp
));
354 return newintobject(res
);
370 if (!getargs(args
, "i", &n
))
373 err_setstr(ValueError
, "negative read count");
377 n2
= n
!= 0 ? n
: BUFSIZ
;
378 v
= newsizedstringobject((char *)NULL
, n2
);
384 n3
= fread(BUF(v
)+n1
, 1, n2
-n1
, f
->f_fp
);
385 /* XXX Error check? */
394 if (resizestring(&v
, n2
) < 0)
401 resizestring(&v
, n1
);
405 /* Internal routine to get a line.
406 Size argument interpretation:
408 = 0: read arbitrary line;
409 < 0: strip trailing '\n', raise EOFError if EOF reached immediately
419 register char *buf
, *end
;
424 n2
= n
> 0 ? n
: 100;
425 v
= newsizedstringobject((char *)NULL
, n2
);
433 if ((c
= getc(fp
)) == EOF
) {
440 if (n
< 0 && buf
== BUF(v
)) {
444 "EOF when reading a line");
449 if ((*buf
++ = c
) == '\n') {
460 if (resizestring(&v
, n2
) < 0)
471 resizestring(&v
, n1
);
475 /* External C interface */
486 if (!is_fileobject(f
)) {
490 reader
= getattr(f
, "readline");
494 args
= mkvalue("()");
496 args
= mkvalue("(i)", n
);
501 result
= call_object(reader
, args
);
504 if (result
!= NULL
&& !is_stringobject(result
)) {
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
);
517 "EOF when reading a line");
519 else if (s
[len
-1] == '\n') {
520 if (result
->ob_refcnt
== 1)
521 resizestring(&result
, len
-1);
524 v
= newsizedstringobject(s
, len
-1);
532 if (((fileobject
*)f
)->f_fp
== NULL
)
534 return getline((fileobject
*)f
, n
);
540 file_readline(f
, args
)
549 n
= 0; /* Unlimited */
551 if (!getintarg(args
, &n
))
554 err_setstr(ValueError
, "negative readline count");
559 return getline(f
, n
);
563 file_readlines(f
, args
)
574 if ((list
= newlistobject(0)) == NULL
)
577 line
= getline(f
, 0);
578 if (line
!= NULL
&& getstringsize(line
) == 0) {
582 if (line
== NULL
|| addlistitem(list
, line
) != 0) {
601 if (!getargs(args
, "s#", &s
, &n
))
606 n2
= fwrite(s
, 1, n
, f
->f_fp
);
618 file_writelines(f
, args
)
625 if (args
== NULL
|| !is_listobject(args
)) {
626 err_setstr(TypeError
,
627 "writelines() requires list of strings");
630 n
= getlistsize(args
);
634 for (i
= 0; i
< n
; i
++) {
635 object
*line
= getlistitem(args
, i
);
638 if (!is_stringobject(line
)) {
640 err_setstr(TypeError
,
641 "writelines() requires list of strings");
644 len
= getstringsize(line
);
645 nwritten
= fwrite(getstringvalue(line
), 1, len
, f
->f_fp
);
646 if (nwritten
!= len
) {
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},
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 */
688 file_getattr(f
, name
)
694 res
= findmethod(file_methods
, (object
*)f
, name
);
698 if (strcmp(name
, "closed") == 0)
699 return newintobject((long)(f
->f_fp
== 0));
700 return getmember((char *)f
, file_memberlist
, name
);
704 file_setattr(f
, name
, v
)
710 err_setstr(AttributeError
, "can't delete file attributes");
713 return setmember((char *)f
, file_memberlist
, name
, v
);
716 typeobject Filetype
= {
717 OB_HEAD_INIT(&Typetype
)
722 (destructor
)file_dealloc
, /*tp_dealloc*/
724 (getattrfunc
)file_getattr
, /*tp_getattr*/
725 (setattrfunc
)file_setattr
, /*tp_setattr*/
727 (reprfunc
)file_repr
, /*tp_repr*/
730 /* Interface for the 'soft space' between print items. */
733 softspace(f
, newflag
)
741 else if (is_fileobject(f
)) {
742 oldflag
= ((fileobject
*)f
)->f_softspace
;
743 ((fileobject
*)f
)->f_softspace
= newflag
;
747 v
= getattr(f
, "softspace");
752 oldflag
= getintvalue(v
);
755 v
= newintobject((long)newflag
);
759 if (setattr(f
, "softspace", v
) != 0)
767 /* Interfaces to write objects/strings to file-like objects */
770 writeobject(v
, f
, flags
)
775 object
*writer
, *value
, *result
;
777 err_setstr(TypeError
, "writeobject with NULL file");
780 else if (is_fileobject(f
)) {
781 FILE *fp
= getfilefile(f
);
786 return printobject(v
, fp
, flags
);
788 writer
= getattr(f
, "write");
791 if (flags
& PRINT_RAW
)
792 value
= strobject(v
);
794 value
= reprobject(v
);
799 result
= call_object(writer
, value
);
816 else if (is_fileobject(f
)) {
817 FILE *fp
= getfilefile(f
);
821 else if (!err_occurred()) {
822 object
*v
= newstringobject(s
);
827 if (writeobject(v
, f
, PRINT_RAW
) != 0)