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
14 #define WIN32_LEAN_AND_MEAN
16 #endif /* MS_WINDOWS */
19 extern char* vms__StdioReadline(FILE *sys_stdin
, FILE *sys_stdout
, char *prompt
);
23 PyThreadState
* _PyOS_ReadlineTState
;
27 static PyThread_type_lock _PyOS_ReadlineLock
= NULL
;
30 int (*PyOS_InputHook
)(void) = NULL
;
33 int Py_RISCOSWimpFlag
;
36 /* This function restarts a fgets() after an EINTR error occurred
37 except if PyOS_InterruptOccurred() returns true. */
40 my_fgets(char *buf
, int len
, FILE *fp
)
48 if (PyOS_InputHook
!= NULL
)
49 (void)(PyOS_InputHook
)();
52 p
= fgets(buf
, len
, fp
);
54 return 0; /* No error */
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.
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.
68 if (GetLastError()==ERROR_OPERATION_ABORTED
) {
69 for (i
= 0; i
< 10; i
++) {
70 if (PyOS_InterruptOccurred())
75 #endif /* MS_WINDOWS */
84 PyEval_RestoreThread(_PyOS_ReadlineTState
);
86 s
= PyErr_CheckSignals();
96 if (PyOS_InterruptOccurred()) {
97 return 1; /* Interrupt */
99 return -2; /* Error */
105 /* Readline implementation using fgets() */
108 PyOS_StdioReadline(FILE *sys_stdin
, FILE *sys_stdout
, char *prompt
)
113 if ((p
= (char *)PyMem_MALLOC(n
)) == NULL
)
118 fprintf(stderr
, "%s", prompt
);
121 if(Py_RISCOSWimpFlag
)
122 fprintf(stderr
, "\x0cr%s\x0c", prompt
);
124 fprintf(stderr
, "%s", prompt
);
128 switch (my_fgets(p
, (int)n
, sys_stdin
)) {
129 case 0: /* Normal case */
131 case 1: /* Interrupt */
136 default: /* Shouldn't happen */
141 while (n
> 0 && p
[n
-1] != '\n') {
143 p
= (char *)PyMem_REALLOC(p
, n
+ incr
);
146 if (incr
> INT_MAX
) {
147 PyErr_SetString(PyExc_OverflowError
, "input line too long");
149 if (my_fgets(p
+n
, (int)incr
, sys_stdin
) != 0)
153 return (char *)PyMem_REALLOC(p
, n
+1);
157 /* By initializing this function pointer, systems embedding Python can
158 override the readline function.
160 Note: Python expects in return a buffer allocated with PyMem_Malloc. */
162 char *(*PyOS_ReadlineFunctionPointer
)(FILE *, FILE *, char *);
165 /* Interface used by tokenizer.c and bltinmodule.c */
168 PyOS_Readline(FILE *sys_stdin
, FILE *sys_stdout
, char *prompt
)
172 if (_PyOS_ReadlineTState
== PyThreadState_GET()) {
173 PyErr_SetString(PyExc_RuntimeError
,
174 "can't re-enter readline");
179 if (PyOS_ReadlineFunctionPointer
== NULL
) {
181 PyOS_ReadlineFunctionPointer
= vms__StdioReadline
;
183 PyOS_ReadlineFunctionPointer
= PyOS_StdioReadline
;
188 if (_PyOS_ReadlineLock
== NULL
) {
189 _PyOS_ReadlineLock
= PyThread_allocate_lock();
193 _PyOS_ReadlineTState
= PyThreadState_GET();
194 Py_BEGIN_ALLOW_THREADS
196 PyThread_acquire_lock(_PyOS_ReadlineLock
, 1);
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
204 if (!isatty (fileno (sys_stdin
)) || !isatty (fileno (sys_stdout
)))
205 rv
= PyOS_StdioReadline (sys_stdin
, sys_stdout
, prompt
);
207 rv
= (*PyOS_ReadlineFunctionPointer
)(sys_stdin
, sys_stdout
,
212 PyThread_release_lock(_PyOS_ReadlineLock
);
215 _PyOS_ReadlineTState
= NULL
;