Home | History | Annotate | Download | only in Parser
      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 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         if (PyOS_InputHook != NULL)
     49             (void)(PyOS_InputHook)();
     50         errno = 0;
     51         clearerr(fp);
     52         p = fgets(buf, len, fp);
     53         if (p != NULL)
     54             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         if (feof(fp)) {
     77             clearerr(fp);
     78             return -1; /* EOF */
     79         }
     80 #ifdef EINTR
     81         if (errno == EINTR) {
     82             int s;
     83 #ifdef WITH_THREAD
     84             PyEval_RestoreThread(_PyOS_ReadlineTState);
     85 #endif
     86             s = PyErr_CheckSignals();
     87 #ifdef WITH_THREAD
     88             PyEval_SaveThread();
     89 #endif
     90             if (s < 0)
     91                     return 1;
     92 	    /* try again */
     93             continue;
     94         }
     95 #endif
     96         if (PyOS_InterruptOccurred()) {
     97             return 1; /* Interrupt */
     98         }
     99         return -2; /* Error */
    100     }
    101     /* NOTREACHED */
    102 }
    103 
    104 
    105 /* Readline implementation using fgets() */
    106 
    107 char *
    108 PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
    109 {
    110     size_t n;
    111     char *p;
    112     n = 100;
    113     if ((p = (char *)PyMem_MALLOC(n)) == NULL)
    114         return NULL;
    115     fflush(sys_stdout);
    116 #ifndef RISCOS
    117     if (prompt)
    118         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     fflush(stderr);
    128     switch (my_fgets(p, (int)n, sys_stdin)) {
    129     case 0: /* Normal case */
    130         break;
    131     case 1: /* Interrupt */
    132         PyMem_FREE(p);
    133         return NULL;
    134     case -1: /* EOF */
    135     case -2: /* Error */
    136     default: /* Shouldn't happen */
    137         *p = '\0';
    138         break;
    139     }
    140     n = strlen(p);
    141     while (n > 0 && p[n-1] != '\n') {
    142         size_t incr = n+2;
    143         p = (char *)PyMem_REALLOC(p, n + incr);
    144         if (p == NULL)
    145             return NULL;
    146         if (incr > INT_MAX) {
    147             PyErr_SetString(PyExc_OverflowError, "input line too long");
    148         }
    149         if (my_fgets(p+n, (int)incr, sys_stdin) != 0)
    150             break;
    151         n += strlen(p+n);
    152     }
    153     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 PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
    169 {
    170     char *rv;
    171 
    172     if (_PyOS_ReadlineTState == PyThreadState_GET()) {
    173         PyErr_SetString(PyExc_RuntimeError,
    174                         "can't re-enter readline");
    175         return NULL;
    176     }
    177 
    178 
    179     if (PyOS_ReadlineFunctionPointer == NULL) {
    180 #ifdef __VMS
    181         PyOS_ReadlineFunctionPointer = vms__StdioReadline;
    182 #else
    183         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     _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     if (!isatty (fileno (sys_stdin)) || !isatty (fileno (sys_stdout)))
    205         rv = PyOS_StdioReadline (sys_stdin, sys_stdout, prompt);
    206     else
    207         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     _PyOS_ReadlineTState = NULL;
    216 
    217     return rv;
    218 }
    219