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 : }
|