| Guido van Rossum | 6fa6343 | 1993-12-24 10:36:57 +0000 | [diff] [blame] | 1 |  | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 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. | 
| Guido van Rossum | 6fa6343 | 1993-12-24 10:36:57 +0000 | [diff] [blame] | 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 |  | 
| Guido van Rossum | 8efa47b | 1998-08-27 19:43:43 +0000 | [diff] [blame] | 12 | #include "Python.h" | 
| Mark Hammond | 2f10cb8 | 2002-07-14 23:12:29 +0000 | [diff] [blame] | 13 | #ifdef MS_WINDOWS | 
 | 14 | #define WIN32_LEAN_AND_MEAN | 
 | 15 | #include "windows.h" | 
 | 16 | #endif /* MS_WINDOWS */ | 
| Guido van Rossum | 6fa6343 | 1993-12-24 10:36:57 +0000 | [diff] [blame] | 17 |  | 
| Martin v. Löwis | c16f3bd | 2003-05-03 09:14:54 +0000 | [diff] [blame] | 18 | #ifdef __VMS | 
 | 19 | extern char* vms__StdioReadline(FILE *sys_stdin, FILE *sys_stdout, char *prompt); | 
 | 20 | #endif | 
 | 21 |  | 
| Michael W. Hudson | 30ea2f2 | 2004-07-07 17:44:12 +0000 | [diff] [blame] | 22 |  | 
 | 23 | PyThreadState* _PyOS_ReadlineTState; | 
 | 24 |  | 
| Tim Peters | b7e898a | 2004-07-07 20:42:07 +0000 | [diff] [blame] | 25 | #ifdef WITH_THREAD | 
| Michael W. Hudson | 30ea2f2 | 2004-07-07 17:44:12 +0000 | [diff] [blame] | 26 | #include "pythread.h" | 
 | 27 | static PyThread_type_lock _PyOS_ReadlineLock = NULL; | 
 | 28 | #endif | 
 | 29 |  | 
| Thomas Wouters | 23c9e00 | 2000-07-22 19:20:54 +0000 | [diff] [blame] | 30 | int (*PyOS_InputHook)(void) = NULL; | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 31 |  | 
 | 32 | /* This function restarts a fgets() after an EINTR error occurred | 
 | 33 |    except if PyOS_InterruptOccurred() returns true. */ | 
 | 34 |  | 
 | 35 | static int | 
| Thomas Wouters | 23c9e00 | 2000-07-22 19:20:54 +0000 | [diff] [blame] | 36 | my_fgets(char *buf, int len, FILE *fp) | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 37 | { | 
| Tim Golden | 9175c3d | 2012-06-29 18:39:26 +0100 | [diff] [blame] | 38 | #ifdef MS_WINDOWS | 
 | 39 |     HANDLE hInterruptEvent; | 
 | 40 | #endif | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 41 |     char *p; | 
| Antoine Pitrou | c345ce1 | 2011-12-16 12:28:32 +0100 | [diff] [blame] | 42 |     int err; | 
| Victor Stinner | 52c950f | 2011-04-09 15:55:44 +0200 | [diff] [blame] | 43 |     while (1) { | 
| Antoine Pitrou | 7f14f0d | 2010-05-09 16:14:21 +0000 | [diff] [blame] | 44 |         if (PyOS_InputHook != NULL) | 
 | 45 |             (void)(PyOS_InputHook)(); | 
 | 46 |         errno = 0; | 
| Victor Stinner | 4f71101 | 2011-05-30 23:46:00 +0200 | [diff] [blame] | 47 |         clearerr(fp); | 
| Martin v. Löwis | e654c11 | 2012-04-30 06:10:41 +0200 | [diff] [blame] | 48 |         if (_PyVerify_fd(fileno(fp))) | 
 | 49 |             p = fgets(buf, len, fp); | 
 | 50 |         else | 
 | 51 |             p = NULL; | 
| Antoine Pitrou | 7f14f0d | 2010-05-09 16:14:21 +0000 | [diff] [blame] | 52 |         if (p != NULL) | 
 | 53 |             return 0; /* No error */ | 
| Antoine Pitrou | c345ce1 | 2011-12-16 12:28:32 +0100 | [diff] [blame] | 54 |         err = errno; | 
| Mark Hammond | 2f10cb8 | 2002-07-14 23:12:29 +0000 | [diff] [blame] | 55 | #ifdef MS_WINDOWS | 
| Tim Golden | 9175c3d | 2012-06-29 18:39:26 +0100 | [diff] [blame] | 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 which will have set the event object returned by | 
 | 60 |            _PyOS_SigintEvent. This signal fires in another thread and | 
 | 61 |            is not guaranteed to have occurred before this point in the | 
 | 62 |            code. | 
 | 63 |  | 
 | 64 |            Therefore: check whether the event is set with a small timeout. | 
 | 65 |            If it is, assume this is a Ctrl-C and reset the event. If it | 
 | 66 |            isn't set assume that this is a Ctrl-Z on its own and drop | 
 | 67 |            through to check for EOF. | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 68 |         */ | 
| Antoine Pitrou | 7f14f0d | 2010-05-09 16:14:21 +0000 | [diff] [blame] | 69 |         if (GetLastError()==ERROR_OPERATION_ABORTED) { | 
| Tim Golden | 9175c3d | 2012-06-29 18:39:26 +0100 | [diff] [blame] | 70 |             hInterruptEvent = _PyOS_SigintEvent(); | 
| Martin v. Löwis | b26a9b1 | 2013-01-25 14:25:48 +0100 | [diff] [blame] | 71 |             switch (WaitForSingleObjectEx(hInterruptEvent, 10, FALSE)) { | 
| Tim Golden | 9175c3d | 2012-06-29 18:39:26 +0100 | [diff] [blame] | 72 |             case WAIT_OBJECT_0: | 
 | 73 |                 ResetEvent(hInterruptEvent); | 
| Antoine Pitrou | 7f14f0d | 2010-05-09 16:14:21 +0000 | [diff] [blame] | 74 |                 return 1; /* Interrupt */ | 
| Tim Golden | 9175c3d | 2012-06-29 18:39:26 +0100 | [diff] [blame] | 75 |             case WAIT_FAILED: | 
 | 76 |                 return -2; /* Error */ | 
| Antoine Pitrou | 7f14f0d | 2010-05-09 16:14:21 +0000 | [diff] [blame] | 77 |             } | 
| Antoine Pitrou | 7f14f0d | 2010-05-09 16:14:21 +0000 | [diff] [blame] | 78 |         } | 
| Mark Hammond | 2f10cb8 | 2002-07-14 23:12:29 +0000 | [diff] [blame] | 79 | #endif /* MS_WINDOWS */ | 
| Antoine Pitrou | 7f14f0d | 2010-05-09 16:14:21 +0000 | [diff] [blame] | 80 |         if (feof(fp)) { | 
| Victor Stinner | 4755ab0 | 2011-05-10 00:19:53 +0200 | [diff] [blame] | 81 |             clearerr(fp); | 
| Antoine Pitrou | 7f14f0d | 2010-05-09 16:14:21 +0000 | [diff] [blame] | 82 |             return -1; /* EOF */ | 
 | 83 |         } | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 84 | #ifdef EINTR | 
| Antoine Pitrou | c345ce1 | 2011-12-16 12:28:32 +0100 | [diff] [blame] | 85 |         if (err == EINTR) { | 
| Antoine Pitrou | 7f14f0d | 2010-05-09 16:14:21 +0000 | [diff] [blame] | 86 |             int s; | 
| Michael W. Hudson | e3afc59 | 2005-04-07 10:11:19 +0000 | [diff] [blame] | 87 | #ifdef WITH_THREAD | 
| Antoine Pitrou | 7f14f0d | 2010-05-09 16:14:21 +0000 | [diff] [blame] | 88 |             PyEval_RestoreThread(_PyOS_ReadlineTState); | 
| Michael W. Hudson | e3afc59 | 2005-04-07 10:11:19 +0000 | [diff] [blame] | 89 | #endif | 
| Antoine Pitrou | 7f14f0d | 2010-05-09 16:14:21 +0000 | [diff] [blame] | 90 |             s = PyErr_CheckSignals(); | 
| Michael W. Hudson | e3afc59 | 2005-04-07 10:11:19 +0000 | [diff] [blame] | 91 | #ifdef WITH_THREAD | 
| Antoine Pitrou | 7f14f0d | 2010-05-09 16:14:21 +0000 | [diff] [blame] | 92 |             PyEval_SaveThread(); | 
| Michael W. Hudson | e3afc59 | 2005-04-07 10:11:19 +0000 | [diff] [blame] | 93 | #endif | 
| Victor Stinner | 52c950f | 2011-04-09 15:55:44 +0200 | [diff] [blame] | 94 |             if (s < 0) | 
 | 95 |                     return 1; | 
| Tim Golden | 9175c3d | 2012-06-29 18:39:26 +0100 | [diff] [blame] | 96 |         /* try again */ | 
| Victor Stinner | 52c950f | 2011-04-09 15:55:44 +0200 | [diff] [blame] | 97 |             continue; | 
| Antoine Pitrou | 7f14f0d | 2010-05-09 16:14:21 +0000 | [diff] [blame] | 98 |         } | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 99 | #endif | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 100 |         if (PyOS_InterruptOccurred()) { | 
 | 101 |             return 1; /* Interrupt */ | 
 | 102 |         } | 
| Antoine Pitrou | 7f14f0d | 2010-05-09 16:14:21 +0000 | [diff] [blame] | 103 |         return -2; /* Error */ | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 104 |     } | 
| Antoine Pitrou | 7f14f0d | 2010-05-09 16:14:21 +0000 | [diff] [blame] | 105 |     /* NOTREACHED */ | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 106 | } | 
 | 107 |  | 
 | 108 |  | 
 | 109 | /* Readline implementation using fgets() */ | 
 | 110 |  | 
 | 111 | char * | 
| Serhiy Storchaka | c679227 | 2013-10-19 21:03:34 +0300 | [diff] [blame] | 112 | PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt) | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 113 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 114 |     size_t n; | 
| Christian Heimes | 9ae513c | 2013-08-06 15:59:16 +0200 | [diff] [blame] | 115 |     char *p, *pr; | 
| Victor Stinner | 2fe9bac | 2013-10-10 16:18:20 +0200 | [diff] [blame] | 116 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 117 |     n = 100; | 
| Victor Stinner | 2fe9bac | 2013-10-10 16:18:20 +0200 | [diff] [blame] | 118 |     p = (char *)PyMem_RawMalloc(n); | 
 | 119 |     if (p == NULL) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 120 |         return NULL; | 
| Victor Stinner | 2fe9bac | 2013-10-10 16:18:20 +0200 | [diff] [blame] | 121 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 122 |     fflush(sys_stdout); | 
 | 123 |     if (prompt) | 
 | 124 |         fprintf(stderr, "%s", prompt); | 
 | 125 |     fflush(stderr); | 
| Victor Stinner | 2fe9bac | 2013-10-10 16:18:20 +0200 | [diff] [blame] | 126 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 127 |     switch (my_fgets(p, (int)n, sys_stdin)) { | 
 | 128 |     case 0: /* Normal case */ | 
 | 129 |         break; | 
 | 130 |     case 1: /* Interrupt */ | 
| Victor Stinner | 2fe9bac | 2013-10-10 16:18:20 +0200 | [diff] [blame] | 131 |         PyMem_RawFree(p); | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 132 |         return NULL; | 
 | 133 |     case -1: /* EOF */ | 
 | 134 |     case -2: /* Error */ | 
 | 135 |     default: /* Shouldn't happen */ | 
 | 136 |         *p = '\0'; | 
 | 137 |         break; | 
 | 138 |     } | 
 | 139 |     n = strlen(p); | 
 | 140 |     while (n > 0 && p[n-1] != '\n') { | 
 | 141 |         size_t incr = n+2; | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 142 |         if (incr > INT_MAX) { | 
| Victor Stinner | c548660 | 2013-10-19 02:40:16 +0200 | [diff] [blame] | 143 |             PyMem_RawFree(p); | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 144 |             PyErr_SetString(PyExc_OverflowError, "input line too long"); | 
| Christian Heimes | 9ae513c | 2013-08-06 15:59:16 +0200 | [diff] [blame] | 145 |             return NULL; | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 146 |         } | 
| Victor Stinner | 2fe9bac | 2013-10-10 16:18:20 +0200 | [diff] [blame] | 147 |         pr = (char *)PyMem_RawRealloc(p, n + incr); | 
| Christian Heimes | 9ae513c | 2013-08-06 15:59:16 +0200 | [diff] [blame] | 148 |         if (pr == NULL) { | 
| Victor Stinner | c548660 | 2013-10-19 02:40:16 +0200 | [diff] [blame] | 149 |             PyMem_RawFree(p); | 
| Christian Heimes | 9ae513c | 2013-08-06 15:59:16 +0200 | [diff] [blame] | 150 |             PyErr_NoMemory(); | 
 | 151 |             return NULL; | 
 | 152 |         } | 
 | 153 |         p = pr; | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 154 |         if (my_fgets(p+n, (int)incr, sys_stdin) != 0) | 
 | 155 |             break; | 
 | 156 |         n += strlen(p+n); | 
 | 157 |     } | 
| Victor Stinner | 2fe9bac | 2013-10-10 16:18:20 +0200 | [diff] [blame] | 158 |     pr = (char *)PyMem_RawRealloc(p, n+1); | 
| Christian Heimes | 9ae513c | 2013-08-06 15:59:16 +0200 | [diff] [blame] | 159 |     if (pr == NULL) { | 
| Victor Stinner | c548660 | 2013-10-19 02:40:16 +0200 | [diff] [blame] | 160 |         PyMem_RawFree(p); | 
| Christian Heimes | 9ae513c | 2013-08-06 15:59:16 +0200 | [diff] [blame] | 161 |         PyErr_NoMemory(); | 
 | 162 |         return NULL; | 
 | 163 |     } | 
 | 164 |     return pr; | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 165 | } | 
 | 166 |  | 
 | 167 |  | 
 | 168 | /* By initializing this function pointer, systems embedding Python can | 
| Guido van Rossum | b18618d | 2000-05-03 23:44:39 +0000 | [diff] [blame] | 169 |    override the readline function. | 
 | 170 |  | 
 | 171 |    Note: Python expects in return a buffer allocated with PyMem_Malloc. */ | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 172 |  | 
| Serhiy Storchaka | c679227 | 2013-10-19 21:03:34 +0300 | [diff] [blame] | 173 | char *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *); | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 174 |  | 
 | 175 |  | 
 | 176 | /* Interface used by tokenizer.c and bltinmodule.c */ | 
 | 177 |  | 
 | 178 | char * | 
| Serhiy Storchaka | c679227 | 2013-10-19 21:03:34 +0300 | [diff] [blame] | 179 | PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt) | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 180 | { | 
| Victor Stinner | 2fe9bac | 2013-10-10 16:18:20 +0200 | [diff] [blame] | 181 |     char *rv, *res; | 
 | 182 |     size_t len; | 
| Martin v. Löwis | 566f6af | 2002-10-26 14:39:10 +0000 | [diff] [blame] | 183 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 184 |     if (_PyOS_ReadlineTState == PyThreadState_GET()) { | 
 | 185 |         PyErr_SetString(PyExc_RuntimeError, | 
 | 186 |                         "can't re-enter readline"); | 
 | 187 |         return NULL; | 
 | 188 |     } | 
| Michael W. Hudson | 30ea2f2 | 2004-07-07 17:44:12 +0000 | [diff] [blame] | 189 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 190 |  | 
 | 191 |     if (PyOS_ReadlineFunctionPointer == NULL) { | 
| Martin v. Löwis | c16f3bd | 2003-05-03 09:14:54 +0000 | [diff] [blame] | 192 | #ifdef __VMS | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 193 |         PyOS_ReadlineFunctionPointer = vms__StdioReadline; | 
| Martin v. Löwis | c16f3bd | 2003-05-03 09:14:54 +0000 | [diff] [blame] | 194 | #else | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 195 |         PyOS_ReadlineFunctionPointer = PyOS_StdioReadline; | 
| Martin v. Löwis | c16f3bd | 2003-05-03 09:14:54 +0000 | [diff] [blame] | 196 | #endif | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 197 |     } | 
| Michael W. Hudson | 30ea2f2 | 2004-07-07 17:44:12 +0000 | [diff] [blame] | 198 |  | 
| Tim Peters | b7e898a | 2004-07-07 20:42:07 +0000 | [diff] [blame] | 199 | #ifdef WITH_THREAD | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 200 |     if (_PyOS_ReadlineLock == NULL) { | 
 | 201 |         _PyOS_ReadlineLock = PyThread_allocate_lock(); | 
 | 202 |     } | 
| Michael W. Hudson | 30ea2f2 | 2004-07-07 17:44:12 +0000 | [diff] [blame] | 203 | #endif | 
 | 204 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 205 |     _PyOS_ReadlineTState = PyThreadState_GET(); | 
 | 206 |     Py_BEGIN_ALLOW_THREADS | 
 | 207 | #ifdef WITH_THREAD | 
 | 208 |     PyThread_acquire_lock(_PyOS_ReadlineLock, 1); | 
 | 209 | #endif | 
| Michael W. Hudson | 30ea2f2 | 2004-07-07 17:44:12 +0000 | [diff] [blame] | 210 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 211 |     /* This is needed to handle the unlikely case that the | 
 | 212 |      * interpreter is in interactive mode *and* stdin/out are not | 
 | 213 |      * a tty.  This can happen, for example if python is run like | 
 | 214 |      * this: python -i < test1.py | 
 | 215 |      */ | 
 | 216 |     if (!isatty (fileno (sys_stdin)) || !isatty (fileno (sys_stdout))) | 
 | 217 |         rv = PyOS_StdioReadline (sys_stdin, sys_stdout, prompt); | 
 | 218 |     else | 
 | 219 |         rv = (*PyOS_ReadlineFunctionPointer)(sys_stdin, sys_stdout, | 
 | 220 |                                              prompt); | 
 | 221 |     Py_END_ALLOW_THREADS | 
 | 222 |  | 
 | 223 | #ifdef WITH_THREAD | 
 | 224 |     PyThread_release_lock(_PyOS_ReadlineLock); | 
 | 225 | #endif | 
 | 226 |  | 
 | 227 |     _PyOS_ReadlineTState = NULL; | 
 | 228 |  | 
| Victor Stinner | 2fe9bac | 2013-10-10 16:18:20 +0200 | [diff] [blame] | 229 |     if (rv == NULL) | 
 | 230 |         return NULL; | 
 | 231 |  | 
 | 232 |     len = strlen(rv) + 1; | 
 | 233 |     res = PyMem_Malloc(len); | 
 | 234 |     if (res != NULL) | 
 | 235 |         memcpy(res, rv, len); | 
 | 236 |     PyMem_RawFree(rv); | 
 | 237 |  | 
 | 238 |     return res; | 
| Guido van Rossum | 6fa6343 | 1993-12-24 10:36:57 +0000 | [diff] [blame] | 239 | } |