LCOV - code coverage report
Current view: top level - Parser - myreadline.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 0 58 0.0 %
Date: 2017-04-19 Functions: 0 3 0.0 %

          Line data    Source code
       1             : 
       2             : /* Readline interface for tokenizer.c and [raw_]input() in bltinmodule.c.
       3             :    By default, or when stdin is not a tty device, we have a super
       4             :    simple my_readline function using fgets.
       5             :    Optionally, we can use the GNU readline library.
       6             :    my_readline() has a different return value from GNU readline():
       7             :    - NULL if an interrupt occurred or if an error occurred
       8             :    - a malloc'ed empty string if EOF was read
       9             :    - a malloc'ed string ending in \n normally
      10             : */
      11             : 
      12             : #include "Python.h"
      13             : #ifdef MS_WINDOWS
      14             : #define WIN32_LEAN_AND_MEAN
      15             : #include "windows.h"
      16             : #endif /* MS_WINDOWS */
      17             : 
      18             : #ifdef __VMS
      19             : extern char* vms__StdioReadline(FILE *sys_stdin, FILE *sys_stdout, char *prompt);
      20             : #endif
      21             : 
      22             : 
      23             : PyThreadState* _PyOS_ReadlineTState;
      24             : 
      25             : #ifdef WITH_THREAD
      26             : #include "pythread.h"
      27             : static PyThread_type_lock _PyOS_ReadlineLock = NULL;
      28             : #endif
      29             : 
      30             : int (*PyOS_InputHook)(void) = NULL;
      31             : 
      32             : #ifdef RISCOS
      33             : int Py_RISCOSWimpFlag;
      34             : #endif
      35             : 
      36             : /* This function restarts a fgets() after an EINTR error occurred
      37             :    except if PyOS_InterruptOccurred() returns true. */
      38             : 
      39             : static int
      40           0 : my_fgets(char *buf, int len, FILE *fp)
      41             : {
      42             :     char *p;
      43             : #ifdef MS_WINDOWS
      44             :     int i;
      45             : #endif
      46             : 
      47             :     while (1) {
      48           0 :         if (PyOS_InputHook != NULL)
      49           0 :             (void)(PyOS_InputHook)();
      50           0 :         errno = 0;
      51           0 :         clearerr(fp);
      52           0 :         p = fgets(buf, len, fp);
      53           0 :         if (p != NULL)
      54           0 :             return 0; /* No error */
      55             : #ifdef MS_WINDOWS
      56             :         /* Ctrl-C anywhere on the line or Ctrl-Z if the only character
      57             :            on a line will set ERROR_OPERATION_ABORTED. Under normal
      58             :            circumstances Ctrl-C will also have caused the SIGINT handler
      59             :            to fire. This signal fires in another thread and is not
      60             :            guaranteed to have occurred before this point in the code.
      61             : 
      62             :            Therefore: check in a small loop to see if the trigger has
      63             :            fired, in which case assume this is a Ctrl-C event. If it
      64             :            hasn't fired within 10ms assume that this is a Ctrl-Z on its
      65             :            own or that the signal isn't going to fire for some other
      66             :            reason and drop through to check for EOF.
      67             :         */
      68             :         if (GetLastError()==ERROR_OPERATION_ABORTED) {
      69             :             for (i = 0; i < 10; i++) {
      70             :                 if (PyOS_InterruptOccurred())
      71             :                     return 1;
      72             :                 Sleep(1);
      73             :             }
      74             :         }
      75             : #endif /* MS_WINDOWS */
      76           0 :         if (feof(fp)) {
      77           0 :             clearerr(fp);
      78           0 :             return -1; /* EOF */
      79             :         }
      80             : #ifdef EINTR
      81           0 :         if (errno == EINTR) {
      82             :             int s;
      83             : #ifdef WITH_THREAD
      84             :             PyEval_RestoreThread(_PyOS_ReadlineTState);
      85             : #endif
      86           0 :             s = PyErr_CheckSignals();
      87             : #ifdef WITH_THREAD
      88             :             PyEval_SaveThread();
      89             : #endif
      90           0 :             if (s < 0)
      91           0 :                     return 1;
      92             :             /* try again */
      93           0 :             continue;
      94             :         }
      95             : #endif
      96           0 :         if (PyOS_InterruptOccurred()) {
      97           0 :             return 1; /* Interrupt */
      98             :         }
      99           0 :         return -2; /* Error */
     100           0 :     }
     101             :     /* NOTREACHED */
     102             : }
     103             : 
     104             : 
     105             : /* Readline implementation using fgets() */
     106             : 
     107             : char *
     108           0 : PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
     109             : {
     110             :     size_t n;
     111             :     char *p;
     112           0 :     n = 100;
     113           0 :     if ((p = (char *)PyMem_MALLOC(n)) == NULL)
     114           0 :         return NULL;
     115           0 :     fflush(sys_stdout);
     116             : #ifndef RISCOS
     117           0 :     if (prompt)
     118           0 :         fprintf(stderr, "%s", prompt);
     119             : #else
     120             :     if (prompt) {
     121             :         if(Py_RISCOSWimpFlag)
     122             :             fprintf(stderr, "\x0cr%s\x0c", prompt);
     123             :         else
     124             :             fprintf(stderr, "%s", prompt);
     125             :     }
     126             : #endif
     127           0 :     fflush(stderr);
     128           0 :     switch (my_fgets(p, (int)n, sys_stdin)) {
     129             :     case 0: /* Normal case */
     130           0 :         break;
     131             :     case 1: /* Interrupt */
     132           0 :         PyMem_FREE(p);
     133           0 :         return NULL;
     134             :     case -1: /* EOF */
     135             :     case -2: /* Error */
     136             :     default: /* Shouldn't happen */
     137           0 :         *p = '\0';
     138           0 :         break;
     139             :     }
     140           0 :     n = strlen(p);
     141           0 :     while (n > 0 && p[n-1] != '\n') {
     142           0 :         size_t incr = n+2;
     143           0 :         p = (char *)PyMem_REALLOC(p, n + incr);
     144           0 :         if (p == NULL)
     145           0 :             return NULL;
     146           0 :         if (incr > INT_MAX) {
     147           0 :             PyErr_SetString(PyExc_OverflowError, "input line too long");
     148             :         }
     149           0 :         if (my_fgets(p+n, (int)incr, sys_stdin) != 0)
     150           0 :             break;
     151           0 :         n += strlen(p+n);
     152             :     }
     153           0 :     return (char *)PyMem_REALLOC(p, n+1);
     154             : }
     155             : 
     156             : 
     157             : /* By initializing this function pointer, systems embedding Python can
     158             :    override the readline function.
     159             : 
     160             :    Note: Python expects in return a buffer allocated with PyMem_Malloc. */
     161             : 
     162             : char *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, char *);
     163             : 
     164             : 
     165             : /* Interface used by tokenizer.c and bltinmodule.c */
     166             : 
     167             : char *
     168           0 : PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
     169             : {
     170             :     char *rv;
     171             : 
     172           0 :     if (_PyOS_ReadlineTState == PyThreadState_GET()) {
     173           0 :         PyErr_SetString(PyExc_RuntimeError,
     174             :                         "can't re-enter readline");
     175           0 :         return NULL;
     176             :     }
     177             : 
     178             : 
     179           0 :     if (PyOS_ReadlineFunctionPointer == NULL) {
     180             : #ifdef __VMS
     181             :         PyOS_ReadlineFunctionPointer = vms__StdioReadline;
     182             : #else
     183           0 :         PyOS_ReadlineFunctionPointer = PyOS_StdioReadline;
     184             : #endif
     185             :     }
     186             : 
     187             : #ifdef WITH_THREAD
     188             :     if (_PyOS_ReadlineLock == NULL) {
     189             :         _PyOS_ReadlineLock = PyThread_allocate_lock();
     190             :     }
     191             : #endif
     192             : 
     193           0 :     _PyOS_ReadlineTState = PyThreadState_GET();
     194             :     Py_BEGIN_ALLOW_THREADS
     195             : #ifdef WITH_THREAD
     196             :     PyThread_acquire_lock(_PyOS_ReadlineLock, 1);
     197             : #endif
     198             : 
     199             :     /* This is needed to handle the unlikely case that the
     200             :      * interpreter is in interactive mode *and* stdin/out are not
     201             :      * a tty.  This can happen, for example if python is run like
     202             :      * this: python -i < test1.py
     203             :      */
     204           0 :     if (!isatty (fileno (sys_stdin)) || !isatty (fileno (sys_stdout)))
     205           0 :         rv = PyOS_StdioReadline (sys_stdin, sys_stdout, prompt);
     206             :     else
     207           0 :         rv = (*PyOS_ReadlineFunctionPointer)(sys_stdin, sys_stdout,
     208             :                                              prompt);
     209             :     Py_END_ALLOW_THREADS
     210             : 
     211             : #ifdef WITH_THREAD
     212             :     PyThread_release_lock(_PyOS_ReadlineLock);
     213             : #endif
     214             : 
     215           0 :     _PyOS_ReadlineTState = NULL;
     216             : 
     217           0 :     return rv;
     218             : }

Generated by: LCOV version 1.10