home *** CD-ROM | disk | FTP | other *** search
/ linuxmafia.com 2016 / linuxmafia.com.tar / linuxmafia.com / pub / palmos / pippy-0.6beta-src.tar.gz / pippy-0.6beta-src.tar / pippy-0.6beta-src / src / Objects / fileobject.c < prev    next >
C/C++ Source or Header  |  2000-12-21  |  24KB  |  1,117 lines

  1. /***********************************************************
  2. Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
  3. The Netherlands.
  4.  
  5.                         All Rights Reserved
  6.  
  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 or Corporation for National Research Initiatives or
  13. CNRI not be used in advertising or publicity pertaining to
  14. distribution of the software without specific, written prior
  15. permission.
  16.  
  17. While CWI is the initial source for this software, a modified version
  18. is made available by the Corporation for National Research Initiatives
  19. (CNRI) at the Internet address ftp://ftp.python.org.
  20.  
  21. STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
  22. REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
  23. MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
  24. CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
  25. DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  26. PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  27. TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  28. PERFORMANCE OF THIS SOFTWARE.
  29.  
  30. ******************************************************************/
  31.  
  32. /* File object implementation */
  33.  
  34. #include "Python.h"
  35. #include "structmember.h"
  36.  
  37. #ifndef DONT_HAVE_SYS_TYPES_H
  38. #include <sys/types.h>
  39. #endif /* DONT_HAVE_SYS_TYPES_H */
  40.  
  41. #ifdef HAVE_UNISTD_H
  42. #include <unistd.h>
  43. #endif
  44.  
  45. #ifdef MS_WIN32
  46. #define ftruncate _chsize
  47. #define fileno _fileno
  48. #define HAVE_FTRUNCATE
  49. #endif
  50.  
  51. #ifdef macintosh
  52. #ifdef USE_GUSI
  53. #define HAVE_FTRUNCATE
  54. #endif
  55. #endif
  56.  
  57. #ifdef THINK_C
  58. #define HAVE_FOPENRF
  59. #endif
  60. #ifdef __MWERKS__
  61. /* Mwerks fopen() doesn't always set errno */
  62. #define NO_FOPEN_ERRNO
  63. #endif
  64.  
  65. #define BUF(v) PyString_AS_STRING((PyStringObject *)v)
  66.  
  67. #ifndef DONT_HAVE_ERRNO_H
  68. #include <errno.h>
  69. #endif
  70.  
  71. typedef struct {
  72.     PyObject_HEAD
  73.     FILE *f_fp;
  74.     PyObject *f_name;
  75.     PyObject *f_mode;
  76.     int (*f_close) Py_PROTO((FILE *));
  77.     int f_softspace; /* Flag used by 'print' command */
  78. } PyFileObject;
  79.  
  80. #include "other/fileobject_c.h"
  81.  
  82. FILE *
  83. PyFile_AsFile(f)
  84.     PyObject *f;
  85. {
  86.     if (f == NULL || !PyFile_Check(f))
  87.         return NULL;
  88.     else
  89.         return ((PyFileObject *)f)->f_fp;
  90. }
  91.  
  92. PyObject *
  93. PyFile_Name(f)
  94.     PyObject *f;
  95. {
  96.     if (f == NULL || !PyFile_Check(f))
  97.         return NULL;
  98.     else
  99.         return ((PyFileObject *)f)->f_name;
  100. }
  101.  
  102. PyObject *
  103. PyFile_FromFile(fp, name, mode, close)
  104.     FILE *fp;
  105.     char *name;
  106.     char *mode;
  107.     int (*close) Py_FPROTO((FILE *));
  108. {
  109.     PyFileObject *f = PyObject_NEW(PyFileObject, &PyFile_Type);
  110.     if (f == NULL)
  111.         return NULL;
  112.     f->f_fp = NULL;
  113.     f->f_name = PyString_FromString(name);
  114.     f->f_mode = PyString_FromString(mode);
  115.     f->f_close = close;
  116.     f->f_softspace = 0;
  117.     if (f->f_name == NULL || f->f_mode == NULL) {
  118.         Py_DECREF(f);
  119.         return NULL;
  120.     }
  121.     f->f_fp = fp;
  122.     return (PyObject *) f;
  123. }
  124.  
  125. PyObject *
  126. PyFile_FromString(name, mode)
  127.     char *name, *mode;
  128. {
  129.     extern int fclose Py_PROTO((FILE *));
  130.     PyFileObject *f;
  131.     f = (PyFileObject *) PyFile_FromFile((FILE *)NULL, name, mode, fclose);
  132.     if (f == NULL)
  133.         return NULL;
  134. #ifdef HAVE_FOPENRF
  135.     if (*mode == '*') {
  136.         FILE *fopenRF();
  137.         f->f_fp = fopenRF(name, mode+1);
  138.     }
  139.     else
  140. #endif
  141.     {
  142.         Py_BEGIN_ALLOW_THREADS
  143.         f->f_fp = fopen(name, mode);
  144.         Py_END_ALLOW_THREADS
  145.     }
  146.     if (f->f_fp == NULL) {
  147. #ifdef NO_FOPEN_ERRNO
  148.         /* Metroworks only, not testable, so unchanged */
  149.         if ( errno == 0 ) {
  150.             PyErr_SetString(PyExc_IOError, "Cannot open file");
  151.             Py_DECREF(f);
  152.             return NULL;
  153.         }
  154. #endif
  155.         PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
  156.         Py_DECREF(f);
  157.         return NULL;
  158.     }
  159.     return (PyObject *)f;
  160. }
  161.  
  162. void
  163. PyFile_SetBufSize(f, bufsize)
  164.     PyObject *f;
  165.     int bufsize;
  166. {
  167.     if (bufsize >= 0) {
  168. #ifdef HAVE_SETVBUF
  169.         int type;
  170.         switch (bufsize) {
  171.         case 0:
  172.             type = _IONBF;
  173.             break;
  174.         case 1:
  175.             type = _IOLBF;
  176.             bufsize = BUFSIZ;
  177.             break;
  178.         default:
  179.             type = _IOFBF;
  180.         }
  181.         setvbuf(((PyFileObject *)f)->f_fp, (char *)NULL,
  182.             type, bufsize);
  183. #else /* !HAVE_SETVBUF */
  184.         if (bufsize <= 1)
  185.             setbuf(((PyFileObject *)f)->f_fp, (char *)NULL);
  186. #endif /* !HAVE_SETVBUF */
  187.     }
  188. }
  189.  
  190. static PyObject *
  191. err_closed()
  192. {
  193.     PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
  194.     return NULL;
  195. }
  196.  
  197. /* Methods */
  198.  
  199. static void
  200. file_dealloc(f)
  201.     PyFileObject *f;
  202. {
  203.     if (f->f_fp != NULL && f->f_close != NULL) {
  204.         Py_BEGIN_ALLOW_THREADS
  205.         (*f->f_close)(f->f_fp);
  206.         Py_END_ALLOW_THREADS
  207.     }
  208.     if (f->f_name != NULL) {
  209.         Py_DECREF(f->f_name);
  210.     }
  211.     if (f->f_mode != NULL) {
  212.         Py_DECREF(f->f_mode);
  213.     }
  214.     free((char *)f);
  215. }
  216.  
  217. static PyObject *
  218. file_repr(f)
  219.     PyFileObject *f;
  220. {
  221.     char buf[300];
  222.     sprintf(buf, "<%s file '%.256s', mode '%.10s' at %lx>",
  223.         f->f_fp == NULL ? "closed" : "open",
  224.         PyString_AsString(f->f_name),
  225.         PyString_AsString(f->f_mode),
  226.         (long)f);
  227.     return PyString_FromString(buf);
  228. }
  229.  
  230. static PyObject *
  231. file_close(f, args)
  232.     PyFileObject *f;
  233.     PyObject *args;
  234. {
  235.     int sts = 0;
  236.     if (!PyArg_NoArgs(args))
  237.         return NULL;
  238.     if (f->f_fp != NULL) {
  239.         if (f->f_close != NULL) {
  240.             Py_BEGIN_ALLOW_THREADS
  241.             errno = 0;
  242.             sts = (*f->f_close)(f->f_fp);
  243.             Py_END_ALLOW_THREADS
  244.         }
  245.         f->f_fp = NULL;
  246.     }
  247.     if (sts == EOF)
  248.         return PyErr_SetFromErrno(PyExc_IOError);
  249.     if (sts != 0)
  250.         return PyInt_FromLong((long)sts);
  251.     Py_INCREF(Py_None);
  252.     return Py_None;
  253. }
  254.  
  255. static PyObject *
  256. file_seek(f, args)
  257.     PyFileObject *f;
  258.     PyObject *args;
  259. {
  260.     int whence;
  261.     int ret;
  262.     off_t offset;
  263.     PyObject *offobj;
  264.     
  265.     if (f->f_fp == NULL)
  266.         return err_closed();
  267.     whence = 0;
  268.     if (!PyArg_ParseTuple(args, "O|i:seek", &offobj, &whence))
  269.         return NULL;
  270. #if !defined(HAVE_LARGEFILE_SUPPORT)
  271.     offset = PyInt_AsLong(offobj);
  272. #else
  273.     offset = PyLong_Check(offobj) ?
  274.         PyLong_AsLongLong(offobj) : PyInt_AsLong(offobj);
  275. #endif
  276.     if (PyErr_Occurred())
  277.         return NULL;
  278.     Py_BEGIN_ALLOW_THREADS
  279.     errno = 0;
  280. #if defined(HAVE_FSEEKO)
  281.     ret = fseeko(f->f_fp, offset, whence);
  282. #elif defined(HAVE_FSEEK64)
  283.     ret = fseek64(f->f_fp, offset, whence);
  284. #else
  285.     ret = fseek(f->f_fp, offset, whence);
  286. #endif
  287.     Py_END_ALLOW_THREADS
  288.     if (ret != 0) {
  289.         PyErr_SetFromErrno(PyExc_IOError);
  290.         clearerr(f->f_fp);
  291.         return NULL;
  292.     }
  293.     Py_INCREF(Py_None);
  294.     return Py_None;
  295. }
  296.  
  297. #ifdef HAVE_FTRUNCATE
  298. static PyObject *
  299. file_truncate(f, args)
  300.     PyFileObject *f;
  301.     PyObject *args;
  302. {
  303.     int ret;
  304.     off_t newsize;
  305.     PyObject *newsizeobj;
  306.     
  307.     if (f->f_fp == NULL)
  308.         return err_closed();
  309.     newsizeobj = NULL;
  310.     if (!PyArg_ParseTuple(args, "|O:truncate", &newsizeobj))
  311.         return NULL;
  312.     if (newsizeobj != NULL) {
  313. #if !defined(HAVE_LARGEFILE_SUPPORT)
  314.         newsize = PyInt_AsLong(newsizeobj);
  315. #else
  316.         newsize = PyLong_Check(newsizeobj) ?
  317.                 PyLong_AsLongLong(newsizeobj) :
  318.                 PyInt_AsLong(newsizeobj);
  319. #endif
  320.         if (PyErr_Occurred())
  321.             return NULL;
  322.     } else {
  323.         /* Default to current position*/
  324.         Py_BEGIN_ALLOW_THREADS
  325.         errno = 0;
  326. #if defined(HAVE_FTELLO) && defined(HAVE_LARGEFILE_SUPPORT)
  327.         newsize =  ftello(f->f_fp);
  328. #elif defined(HAVE_FTELL64) && defined(HAVE_LARGEFILE_SUPPORT)
  329.         newsize =  ftell64(f->f_fp);
  330. #else
  331.         newsize =  ftell(f->f_fp);
  332. #endif
  333.         Py_END_ALLOW_THREADS
  334.         if (newsize == -1) {
  335.                 PyErr_SetFromErrno(PyExc_IOError);
  336.             clearerr(f->f_fp);
  337.             return NULL;
  338.         }
  339.     }
  340.     Py_BEGIN_ALLOW_THREADS
  341.     errno = 0;
  342.     ret = fflush(f->f_fp);
  343.     Py_END_ALLOW_THREADS
  344.     if (ret == 0) {
  345.             Py_BEGIN_ALLOW_THREADS
  346.         errno = 0;
  347.         ret = ftruncate(fileno(f->f_fp), newsize);
  348.         Py_END_ALLOW_THREADS
  349.     }
  350.     if (ret != 0) {
  351.         PyErr_SetFromErrno(PyExc_IOError);
  352.         clearerr(f->f_fp);
  353.         return NULL;
  354.     }
  355.     Py_INCREF(Py_None);
  356.     return Py_None;
  357. }
  358. #endif /* HAVE_FTRUNCATE */
  359.  
  360. static PyObject *
  361. file_tell(f, args)
  362.     PyFileObject *f;
  363.     PyObject *args;
  364. {
  365.     off_t offset;
  366.     if (f->f_fp == NULL)
  367.         return err_closed();
  368.     if (!PyArg_NoArgs(args))
  369.         return NULL;
  370.     Py_BEGIN_ALLOW_THREADS
  371.     errno = 0;
  372. #if defined(HAVE_FTELLO) && defined(HAVE_LARGEFILE_SUPPORT)
  373.     offset = ftello(f->f_fp);
  374. #elif defined(HAVE_FTELL64) && defined(HAVE_LARGEFILE_SUPPORT)
  375.     offset = ftell64(f->f_fp);
  376. #else
  377.     offset = ftell(f->f_fp);
  378. #endif
  379.     Py_END_ALLOW_THREADS
  380.     if (offset == -1) {
  381.         PyErr_SetFromErrno(PyExc_IOError);
  382.         clearerr(f->f_fp);
  383.         return NULL;
  384.     }
  385. #if !defined(HAVE_LARGEFILE_SUPPORT)
  386.     return PyInt_FromLong(offset);
  387. #else
  388.     return PyLong_FromLongLong(offset);
  389. #endif
  390. }
  391.  
  392. static PyObject *
  393. file_fileno(f, args)
  394.     PyFileObject *f;
  395.     PyObject *args;
  396. {
  397.     if (f->f_fp == NULL)
  398.         return err_closed();
  399.     if (!PyArg_NoArgs(args))
  400.         return NULL;
  401.     return PyInt_FromLong((long) fileno(f->f_fp));
  402. }
  403.  
  404. static PyObject *
  405. file_flush(f, args)
  406.     PyFileObject *f;
  407.     PyObject *args;
  408. {
  409.     int res;
  410.     
  411.     if (f->f_fp == NULL)
  412.         return err_closed();
  413.     if (!PyArg_NoArgs(args))
  414.         return NULL;
  415.     Py_BEGIN_ALLOW_THREADS
  416.     errno = 0;
  417.     res = fflush(f->f_fp);
  418.     Py_END_ALLOW_THREADS
  419.     if (res != 0) {
  420.         PyErr_SetFromErrno(PyExc_IOError);
  421.         clearerr(f->f_fp);
  422.         return NULL;
  423.     }
  424.     Py_INCREF(Py_None);
  425.     return Py_None;
  426. }
  427.  
  428. static PyObject *
  429. file_isatty(f, args)
  430.     PyFileObject *f;
  431.     PyObject *args;
  432. {
  433.     long res;
  434.     if (f->f_fp == NULL)
  435.         return err_closed();
  436.     if (!PyArg_NoArgs(args))
  437.         return NULL;
  438.     Py_BEGIN_ALLOW_THREADS
  439.     res = isatty((int)fileno(f->f_fp));
  440.     Py_END_ALLOW_THREADS
  441.     return PyInt_FromLong(res);
  442. }
  443.  
  444. /* We expect that fstat exists on most systems.
  445.    It's confirmed on Unix, Mac and Windows.
  446.    If you don't have it, add #define DONT_HAVE_FSTAT to your config.h. */
  447. #ifndef DONT_HAVE_FSTAT
  448. #define HAVE_FSTAT
  449.  
  450. #ifndef DONT_HAVE_SYS_TYPES_H
  451. #include <sys/types.h>
  452. #endif
  453.  
  454. #ifndef DONT_HAVE_SYS_STAT_H
  455. #include <sys/stat.h>
  456. #endif
  457.  
  458. #endif /* DONT_HAVE_FSTAT */
  459.  
  460. #if BUFSIZ < 8192
  461. #define SMALLCHUNK 8192
  462. #else
  463. #define SMALLCHUNK BUFSIZ
  464. #endif
  465.  
  466. #if SIZEOF_INT < 4
  467. #define BIGCHUNK  (512 * 32)
  468. #else
  469. #define BIGCHUNK  (512 * 1024)
  470. #endif
  471.  
  472. static size_t
  473. new_buffersize(f, currentsize)
  474.     PyFileObject *f;
  475.     size_t currentsize;
  476. {
  477. #ifdef HAVE_FSTAT
  478.     long pos, end;
  479.     struct stat st;
  480.     if (fstat(fileno(f->f_fp), &st) == 0) {
  481.         end = st.st_size;
  482.         /* The following is not a bug: we really need to call lseek()
  483.            *and* ftell().  The reason is that some stdio libraries
  484.            mistakenly flush their buffer when ftell() is called and
  485.            the lseek() call it makes fails, thereby throwing away
  486.            data that cannot be recovered in any way.  To avoid this,
  487.            we first test lseek(), and only call ftell() if lseek()
  488.            works.  We can't use the lseek() value either, because we
  489.            need to take the amount of buffered data into account.
  490.            (Yet another reason why stdio stinks. :-) */
  491.         pos = lseek(fileno(f->f_fp), 0L, SEEK_CUR);
  492.         if (pos >= 0)
  493.             pos = ftell(f->f_fp);
  494.         if (pos < 0)
  495.             clearerr(f->f_fp);
  496.         if (end > pos && pos >= 0)
  497.             return currentsize + end - pos + 1;
  498.         /* Add 1 so if the file were to grow we'd notice. */
  499.     }
  500. #endif
  501.     if (currentsize > SMALLCHUNK) {
  502.         /* Keep doubling until we reach BIGCHUNK;
  503.            then keep adding BIGCHUNK. */
  504.         if (currentsize <= BIGCHUNK)
  505.             return currentsize + currentsize;
  506.         else
  507.             return currentsize + BIGCHUNK;
  508.     }
  509.     return currentsize + SMALLCHUNK;
  510. }
  511.  
  512. static PyObject *
  513. file_read(f, args)
  514.     PyFileObject *f;
  515.     PyObject *args;
  516. {
  517.     long bytesrequested = -1;
  518.     size_t bytesread, buffersize, chunksize;
  519.     PyObject *v;
  520.     
  521.     if (f->f_fp == NULL)
  522.         return err_closed();
  523.     if (!PyArg_ParseTuple(args, "|l:read", &bytesrequested))
  524.         return NULL;
  525.     if (bytesrequested < 0)
  526.         buffersize = new_buffersize(f, (size_t)0);
  527.     else
  528.         buffersize = bytesrequested;
  529.     v = PyString_FromStringAndSize((char *)NULL, buffersize);
  530.     if (v == NULL)
  531.         return NULL;
  532.     bytesread = 0;
  533.     for (;;) {
  534.         Py_BEGIN_ALLOW_THREADS
  535.         errno = 0;
  536.         chunksize = fread(BUF(v) + bytesread, 1,
  537.                   buffersize - bytesread, f->f_fp);
  538.         Py_END_ALLOW_THREADS
  539.         if (chunksize == 0) {
  540.             if (!ferror(f->f_fp))
  541.                 break;
  542.             PyErr_SetFromErrno(PyExc_IOError);
  543.             clearerr(f->f_fp);
  544.             Py_DECREF(v);
  545.             return NULL;
  546.         }
  547.         bytesread += chunksize;
  548.         if (bytesread < buffersize)
  549.             break;
  550.         if (bytesrequested < 0) {
  551.             buffersize = new_buffersize(f, buffersize);
  552.             if (_PyString_Resize(&v, buffersize) < 0)
  553.                 return NULL;
  554.         }
  555.     }
  556.     if (bytesread != buffersize)
  557.         _PyString_Resize(&v, bytesread);
  558.     return v;
  559. }
  560.  
  561. static PyObject *
  562. file_readinto(f, args)
  563.     PyFileObject *f;
  564.     PyObject *args;
  565. {
  566.     char *ptr;
  567.     int ntodo, ndone, nnow;
  568.     
  569.     if (f->f_fp == NULL)
  570.         return err_closed();
  571.     if (!PyArg_Parse(args, "w#", &ptr, &ntodo))
  572.         return NULL;
  573.     ndone = 0;
  574.     while (ntodo > 0) {
  575.         Py_BEGIN_ALLOW_THREADS
  576.         errno = 0;
  577.         nnow = fread(ptr+ndone, 1, ntodo, f->f_fp);
  578.         Py_END_ALLOW_THREADS
  579.         if (nnow == 0) {
  580.             if (!ferror(f->f_fp))
  581.                 break;
  582.             PyErr_SetFromErrno(PyExc_IOError);
  583.             clearerr(f->f_fp);
  584.             return NULL;
  585.         }
  586.         ndone += nnow;
  587.         ntodo -= nnow;
  588.     }
  589.     return PyInt_FromLong(ndone);
  590. }
  591.  
  592.  
  593. /* Internal routine to get a line.
  594.    Size argument interpretation:
  595.    > 0: max length;
  596.    = 0: read arbitrary line;
  597.    < 0: strip trailing '\n', raise EOFError if EOF reached immediately
  598. */
  599.  
  600. static PyObject *
  601. getline(f, n)
  602.     PyFileObject *f;
  603.     int n;
  604. {
  605.     register FILE *fp;
  606.     register int c;
  607.     register char *buf, *end;
  608.     int n1, n2;
  609.     PyObject *v;
  610.  
  611.     fp = f->f_fp;
  612.     n2 = n > 0 ? n : 100;
  613.     v = PyString_FromStringAndSize((char *)NULL, n2);
  614.     if (v == NULL)
  615.         return NULL;
  616.     buf = BUF(v);
  617.     end = buf + n2;
  618.  
  619.     Py_BEGIN_ALLOW_THREADS
  620.     for (;;) {
  621.         if ((c = getc(fp)) == EOF) {
  622.             clearerr(fp);
  623.             Py_BLOCK_THREADS
  624.             if (PyErr_CheckSignals()) {
  625.                 Py_DECREF(v);
  626.                 return NULL;
  627.             }
  628.             if (n < 0 && buf == BUF(v)) {
  629.                 Py_DECREF(v);
  630.                 PyErr_SetString(PyExc_EOFError,
  631.                        "EOF when reading a line");
  632.                 return NULL;
  633.             }
  634.             Py_UNBLOCK_THREADS
  635.             break;
  636.         }
  637.         if ((*buf++ = c) == '\n') {
  638.             if (n < 0)
  639.                 buf--;
  640.             break;
  641.         }
  642.         if (buf == end) {
  643.             if (n > 0)
  644.                 break;
  645.             n1 = n2;
  646.             n2 += 1000;
  647.             Py_BLOCK_THREADS
  648.             if (_PyString_Resize(&v, n2) < 0)
  649.                 return NULL;
  650.             Py_UNBLOCK_THREADS
  651.             buf = BUF(v) + n1;
  652.             end = BUF(v) + n2;
  653.         }
  654.     }
  655.     Py_END_ALLOW_THREADS
  656.  
  657.     n1 = buf - BUF(v);
  658.     if (n1 != n2)
  659.         _PyString_Resize(&v, n1);
  660.     return v;
  661. }
  662.  
  663. /* External C interface */
  664.  
  665. PyObject *
  666. PyFile_GetLine(f, n)
  667.     PyObject *f;
  668.     int n;
  669. {
  670.     if (f == NULL) {
  671.         PyErr_BadInternalCall();
  672.         return NULL;
  673.     }
  674.     if (!PyFile_Check(f)) {
  675.         PyObject *reader;
  676.         PyObject *args;
  677.         PyObject *result;
  678.         reader = PyObject_GetAttrString(f, "readline");
  679.         if (reader == NULL)
  680.             return NULL;
  681.         if (n <= 0)
  682.             args = Py_BuildValue("()");
  683.         else
  684.             args = Py_BuildValue("(i)", n);
  685.         if (args == NULL) {
  686.             Py_DECREF(reader);
  687.             return NULL;
  688.         }
  689.         result = PyEval_CallObject(reader, args);
  690.         Py_DECREF(reader);
  691.         Py_DECREF(args);
  692.         if (result != NULL && !PyString_Check(result)) {
  693.             Py_DECREF(result);
  694.             result = NULL;
  695.             PyErr_SetString(PyExc_TypeError,
  696.                    "object.readline() returned non-string");
  697.         }
  698.         if (n < 0 && result != NULL) {
  699.             char *s = PyString_AsString(result);
  700.             int len = PyString_Size(result);
  701.             if (len == 0) {
  702.                 Py_DECREF(result);
  703.                 result = NULL;
  704.                 PyErr_SetString(PyExc_EOFError,
  705.                        "EOF when reading a line");
  706.             }
  707.             else if (s[len-1] == '\n') {
  708.                 if (result->ob_refcnt == 1)
  709.                     _PyString_Resize(&result, len-1);
  710.                 else {
  711.                     PyObject *v;
  712.                     v = PyString_FromStringAndSize(s,
  713.                                        len-1);
  714.                     Py_DECREF(result);
  715.                     result = v;
  716.                 }
  717.             }
  718.         }
  719.         return result;
  720.     }
  721.     if (((PyFileObject*)f)->f_fp == NULL)
  722.         return err_closed();
  723.     return getline((PyFileObject *)f, n);
  724. }
  725.  
  726. /* Python method */
  727.  
  728. static PyObject *
  729. file_readline(f, args)
  730.     PyFileObject *f;
  731.     PyObject *args;
  732. {
  733.     int n = -1;
  734.  
  735.     if (f->f_fp == NULL)
  736.         return err_closed();
  737.     if (!PyArg_ParseTuple(args, "|i:readline", &n))
  738.         return NULL;
  739.     if (n == 0)
  740.         return PyString_FromString("");
  741.     if (n < 0)
  742.         n = 0;
  743.     return getline(f, n);
  744. }
  745.  
  746. static PyObject *
  747. file_readlines(f, args)
  748.     PyFileObject *f;
  749.     PyObject *args;
  750. {
  751.     long sizehint = 0;
  752.     PyObject *list;
  753.     PyObject *line;
  754.     char small_buffer[SMALLCHUNK];
  755.     char *buffer = small_buffer;
  756.     size_t buffersize = SMALLCHUNK;
  757.     PyObject *big_buffer = NULL;
  758.     size_t nfilled = 0;
  759.     size_t nread;
  760.     size_t totalread = 0;
  761.     char *p, *q, *end;
  762.     int err;
  763.  
  764.     if (f->f_fp == NULL)
  765.         return err_closed();
  766.     if (!PyArg_ParseTuple(args, "|l:readlines", &sizehint))
  767.         return NULL;
  768.     if ((list = PyList_New(0)) == NULL)
  769.         return NULL;
  770.     for (;;) {
  771.         Py_BEGIN_ALLOW_THREADS
  772.         errno = 0;
  773.         nread = fread(buffer+nfilled, 1, buffersize-nfilled, f->f_fp);
  774.         Py_END_ALLOW_THREADS
  775.         if (nread == 0) {
  776.             sizehint = 0;
  777.             if (!ferror(f->f_fp))
  778.                 break;
  779.             PyErr_SetFromErrno(PyExc_IOError);
  780.             clearerr(f->f_fp);
  781.           error:
  782.             Py_DECREF(list);
  783.             list = NULL;
  784.             goto cleanup;
  785.         }
  786.         totalread += nread;
  787.         p = memchr(buffer+nfilled, '\n', nread);
  788.         if (p == NULL) {
  789.             /* Need a larger buffer to fit this line */
  790.             nfilled += nread;
  791.             buffersize *= 2;
  792.             if (big_buffer == NULL) {
  793.                 /* Create the big buffer */
  794.                 big_buffer = PyString_FromStringAndSize(
  795.                     NULL, buffersize);
  796.                 if (big_buffer == NULL)
  797.                     goto error;
  798.                 buffer = PyString_AS_STRING(big_buffer);
  799.                 memcpy(buffer, small_buffer, nfilled);
  800.             }
  801.             else {
  802.                 /* Grow the big buffer */
  803.                 _PyString_Resize(&big_buffer, buffersize);
  804.                 buffer = PyString_AS_STRING(big_buffer);
  805.             }
  806.             continue;
  807.         }
  808.         end = buffer+nfilled+nread;
  809.         q = buffer;
  810.         do {
  811.             /* Process complete lines */
  812.             p++;
  813.             line = PyString_FromStringAndSize(q, p-q);
  814.             if (line == NULL)
  815.                 goto error;
  816.             err = PyList_Append(list, line);
  817.             Py_DECREF(line);
  818.             if (err != 0)
  819.                 goto error;
  820.             q = p;
  821.             p = memchr(q, '\n', end-q);
  822.         } while (p != NULL);
  823.         /* Move the remaining incomplete line to the start */
  824.         nfilled = end-q;
  825.         memmove(buffer, q, nfilled);
  826.         if (sizehint > 0)
  827.             if (totalread >= (size_t)sizehint)
  828.                 break;
  829.     }
  830.     if (nfilled != 0) {
  831.         /* Partial last line */
  832.         line = PyString_FromStringAndSize(buffer, nfilled);
  833.         if (line == NULL)
  834.             goto error;
  835.         if (sizehint > 0) {
  836.             /* Need to complete the last line */
  837.             PyObject *rest = getline(f, 0);
  838.             if (rest == NULL) {
  839.                 Py_DECREF(line);
  840.                 goto error;
  841.             }
  842.             PyString_Concat(&line, rest);
  843.             Py_DECREF(rest);
  844.             if (line == NULL)
  845.                 goto error;
  846.         }
  847.         err = PyList_Append(list, line);
  848.         Py_DECREF(line);
  849.         if (err != 0)
  850.             goto error;
  851.     }
  852.   cleanup:
  853.     if (big_buffer) {
  854.         Py_DECREF(big_buffer);
  855.     }
  856.     return list;
  857. }
  858.  
  859. static PyObject *
  860. file_write(f, args)
  861.     PyFileObject *f;
  862.     PyObject *args;
  863. {
  864.     char *s;
  865.     int n, n2;
  866.     if (f->f_fp == NULL)
  867.         return err_closed();
  868.     if (!PyArg_Parse(args, "s#", &s, &n))
  869.         return NULL;
  870.     f->f_softspace = 0;
  871.     Py_BEGIN_ALLOW_THREADS
  872.     errno = 0;
  873.     n2 = fwrite(s, 1, n, f->f_fp);
  874.     Py_END_ALLOW_THREADS
  875.     if (n2 != n) {
  876.         PyErr_SetFromErrno(PyExc_IOError);
  877.         clearerr(f->f_fp);
  878.         return NULL;
  879.     }
  880.     Py_INCREF(Py_None);
  881.     return Py_None;
  882. }
  883.  
  884. static PyObject *
  885. file_writelines(f, args)
  886.     PyFileObject *f;
  887.     PyObject *args;
  888. {
  889.     int i, n;
  890.     if (f->f_fp == NULL)
  891.         return err_closed();
  892.     if (args == NULL || !PyList_Check(args)) {
  893.         PyErr_SetString(PyExc_TypeError,
  894.                "writelines() requires list of strings");
  895.         return NULL;
  896.     }
  897.     n = PyList_Size(args);
  898.     f->f_softspace = 0;
  899.     Py_BEGIN_ALLOW_THREADS
  900.     errno = 0;
  901.     for (i = 0; i < n; i++) {
  902.         PyObject *line = PyList_GetItem(args, i);
  903.         int len;
  904.         int nwritten;
  905.         if (!PyString_Check(line)) {
  906.             Py_BLOCK_THREADS
  907.             PyErr_SetString(PyExc_TypeError,
  908.                    "writelines() requires list of strings");
  909.             return NULL;
  910.         }
  911.         len = PyString_Size(line);
  912.         nwritten = fwrite(PyString_AsString(line), 1, len, f->f_fp);
  913.         if (nwritten != len) {
  914.             Py_BLOCK_THREADS
  915.             PyErr_SetFromErrno(PyExc_IOError);
  916.             clearerr(f->f_fp);
  917.             return NULL;
  918.         }
  919.     }
  920.     Py_END_ALLOW_THREADS
  921.     Py_INCREF(Py_None);
  922.     return Py_None;
  923. }
  924.  
  925. static PyMethodDef file_methods[] = {
  926.     {"readline",    (PyCFunction)file_readline, 1},
  927.     {"read",    (PyCFunction)file_read, 1},
  928.     {"write",    (PyCFunction)file_write, 0},
  929.     {"fileno",    (PyCFunction)file_fileno, 0},
  930.     {"seek",    (PyCFunction)file_seek, 1},
  931. #ifdef HAVE_FTRUNCATE
  932.     {"truncate",    (PyCFunction)file_truncate, 1},
  933. #endif
  934.     {"tell",    (PyCFunction)file_tell, 0},
  935.     {"readinto",    (PyCFunction)file_readinto, 0},
  936.     {"readlines",    (PyCFunction)file_readlines, 1},
  937.     {"writelines",    (PyCFunction)file_writelines, 0},
  938.     {"flush",    (PyCFunction)file_flush, 0},
  939.     {"close",    (PyCFunction)file_close, 0},
  940.     {"isatty",    (PyCFunction)file_isatty, 0},
  941.     {NULL,        NULL}        /* sentinel */
  942. };
  943.  
  944. #define OFF(x) offsetof(PyFileObject, x)
  945.  
  946. static struct memberlist file_memberlist[] = {
  947.     {"softspace",    T_INT,        OFF(f_softspace)},
  948.     {"mode",    T_OBJECT,    OFF(f_mode),    RO},
  949.     {"name",    T_OBJECT,    OFF(f_name),    RO},
  950.     /* getattr(f, "closed") is implemented without this table */
  951.     {"closed",    T_INT,        0,        RO},
  952.     {NULL}    /* Sentinel */
  953. };
  954.  
  955. static PyObject *
  956. file_getattr(f, name)
  957.     PyFileObject *f;
  958.     char *name;
  959. {
  960.     PyObject *res;
  961.  
  962.     res = Py_FindMethod(file_methods, (PyObject *)f, name);
  963.     if (res != NULL)
  964.         return res;
  965.     PyErr_Clear();
  966.     if (strcmp(name, "closed") == 0)
  967.         return PyInt_FromLong((long)(f->f_fp == 0));
  968.     return PyMember_Get((char *)f, file_memberlist, name);
  969. }
  970.  
  971. static int
  972. file_setattr(f, name, v)
  973.     PyFileObject *f;
  974.     char *name;
  975.     PyObject *v;
  976. {
  977.     if (v == NULL) {
  978.         PyErr_SetString(PyExc_AttributeError,
  979.                 "can't delete file attributes");
  980.         return -1;
  981.     }
  982.     return PyMember_Set((char *)f, file_memberlist, name, v);
  983. }
  984.  
  985. PyTypeObject PyFile_Type = {
  986.     PyObject_HEAD_INIT(&PyType_Type)
  987.     0,
  988.     "file",
  989.     sizeof(PyFileObject),
  990.     0,
  991.     (destructor)file_dealloc, /*tp_dealloc*/
  992.     0,        /*tp_print*/
  993.     (getattrfunc)file_getattr, /*tp_getattr*/
  994.     (setattrfunc)file_setattr, /*tp_setattr*/
  995.     0,        /*tp_compare*/
  996.     (reprfunc)file_repr, /*tp_repr*/
  997. };
  998.  
  999. /* Interface for the 'soft space' between print items. */
  1000.  
  1001. int
  1002. PyFile_SoftSpace(f, newflag)
  1003.     PyObject *f;
  1004.     int newflag;
  1005. {
  1006.     int oldflag = 0;
  1007.     if (f == NULL) {
  1008.         /* Do nothing */
  1009.     }
  1010.     else if (PyFile_Check(f)) {
  1011.         oldflag = ((PyFileObject *)f)->f_softspace;
  1012.         ((PyFileObject *)f)->f_softspace = newflag;
  1013.     }
  1014.     else {
  1015.         PyObject *v;
  1016.         v = PyObject_GetAttrString(f, "softspace");
  1017.         if (v == NULL)
  1018.             PyErr_Clear();
  1019.         else {
  1020.             if (PyInt_Check(v))
  1021.                 oldflag = PyInt_AsLong(v);
  1022.             Py_DECREF(v);
  1023.         }
  1024.         v = PyInt_FromLong((long)newflag);
  1025.         if (v == NULL)
  1026.             PyErr_Clear();
  1027.         else {
  1028.             if (PyObject_SetAttrString(f, "softspace", v) != 0)
  1029.                 PyErr_Clear();
  1030.             Py_DECREF(v);
  1031.         }
  1032.     }
  1033.     return oldflag;
  1034. }
  1035.  
  1036. /* Interfaces to write objects/strings to file-like objects */
  1037.  
  1038. int
  1039. PyFile_WriteObject(v, f, flags)
  1040.     PyObject *v;
  1041.     PyObject *f;
  1042.     int flags;
  1043. {
  1044.     PyObject *writer, *value, *args, *result;
  1045.     if (f == NULL) {
  1046.         PyErr_SetString(PyExc_TypeError, "writeobject with NULL file");
  1047.         return -1;
  1048.     }
  1049.     else if (PyFile_Check(f)) {
  1050.         FILE *fp = PyFile_AsFile(f);
  1051.         if (fp == NULL) {
  1052.             err_closed();
  1053.             return -1;
  1054.         }
  1055.         return PyObject_Print(v, fp, flags);
  1056.     }
  1057.     writer = PyObject_GetAttrString(f, "write");
  1058.     if (writer == NULL)
  1059.         return -1;
  1060.     if (flags & Py_PRINT_RAW)
  1061.         value = PyObject_Str(v);
  1062.     else
  1063.         value = PyObject_Repr(v);
  1064.     if (value == NULL) {
  1065.         Py_DECREF(writer);
  1066.         return -1;
  1067.     }
  1068.     args = Py_BuildValue("(O)", value);
  1069.     if (args == NULL) {
  1070.         Py_DECREF(value);
  1071.         Py_DECREF(writer);
  1072.         return -1;
  1073.     }
  1074.     result = PyEval_CallObject(writer, args);
  1075.     Py_DECREF(args);
  1076.     Py_DECREF(value);
  1077.     Py_DECREF(writer);
  1078.     if (result == NULL)
  1079.         return -1;
  1080.     Py_DECREF(result);
  1081.     return 0;
  1082. }
  1083.  
  1084. int
  1085. PyFile_WriteString(s, f)
  1086.     char *s;
  1087.     PyObject *f;
  1088. {
  1089.     if (f == NULL) {
  1090.         /* Should be caused by a pre-existing error */
  1091.         if(!PyErr_Occurred())
  1092.             PyErr_SetString(PyExc_SystemError,
  1093.                     "null file for PyFile_WriteString");
  1094.         return -1;
  1095.     }
  1096.     else if (PyFile_Check(f)) {
  1097.         FILE *fp = PyFile_AsFile(f);
  1098.         if (fp == NULL) {
  1099.             err_closed();
  1100.             return -1;
  1101.         }
  1102.         fputs(s, fp);
  1103.         return 0;
  1104.     }
  1105.     else if (!PyErr_Occurred()) {
  1106.         PyObject *v = PyString_FromString(s);
  1107.         int err;
  1108.         if (v == NULL)
  1109.             return -1;
  1110.         err = PyFile_WriteObject(v, f, Py_PRINT_RAW);
  1111.         Py_DECREF(v);
  1112.         return err;
  1113.     }
  1114.     else
  1115.         return -1;
  1116. }
  1117.