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