Fix sf bug 666219: assertion error in httplib.
[python/dscho.git] / Parser / myreadline.c
blobfcc4667d7f64ffcb495b3d98e9d66fa8573b4ccc
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
12 #include "Python.h"
13 #ifdef MS_WINDOWS
14 #define WIN32_LEAN_AND_MEAN
15 #include "windows.h"
16 #endif /* MS_WINDOWS */
18 #ifdef __VMS
19 extern char* vms__StdioReadline(FILE *sys_stdin, FILE *sys_stdout, char *prompt);
20 #endif
22 int (*PyOS_InputHook)(void) = NULL;
24 #ifdef RISCOS
25 int Py_RISCOSWimpFlag;
26 #endif
28 /* This function restarts a fgets() after an EINTR error occurred
29 except if PyOS_InterruptOccurred() returns true. */
31 static int
32 my_fgets(char *buf, int len, FILE *fp)
34 char *p;
35 for (;;) {
36 if (PyOS_InputHook != NULL)
37 (void)(PyOS_InputHook)();
38 errno = 0;
39 p = fgets(buf, len, fp);
40 if (p != NULL)
41 return 0; /* No error */
42 #ifdef MS_WINDOWS
43 /* In the case of a Ctrl+C or some other external event
44 interrupting the operation:
45 Win2k/NT: ERROR_OPERATION_ABORTED is the most recent Win32
46 error code (and feof() returns TRUE).
47 Win9x: Ctrl+C seems to have no effect on fgets() returning
48 early - the signal handler is called, but the fgets()
49 only returns "normally" (ie, when Enter hit or feof())
51 if (GetLastError()==ERROR_OPERATION_ABORTED) {
52 /* Signals come asynchronously, so we sleep a brief
53 moment before checking if the handler has been
54 triggered (we cant just return 1 before the
55 signal handler has been called, as the later
56 signal may be treated as a separate interrupt).
58 Sleep(1);
59 if (PyOS_InterruptOccurred()) {
60 return 1; /* Interrupt */
62 /* Either the sleep wasn't long enough (need a
63 short loop retrying?) or not interrupted at all
64 (in which case we should revisit the whole thing!)
65 Logging some warning would be nice. assert is not
66 viable as under the debugger, the various dialogs
67 mean the condition is not true.
70 #endif /* MS_WINDOWS */
71 if (feof(fp)) {
72 return -1; /* EOF */
74 #ifdef EINTR
75 if (errno == EINTR) {
76 if (PyOS_InterruptOccurred()) {
77 return 1; /* Interrupt */
79 continue;
81 #endif
82 if (PyOS_InterruptOccurred()) {
83 return 1; /* Interrupt */
85 return -2; /* Error */
87 /* NOTREACHED */
91 /* Readline implementation using fgets() */
93 char *
94 PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
96 size_t n;
97 char *p;
98 n = 100;
99 if ((p = PyMem_MALLOC(n)) == NULL)
100 return NULL;
101 fflush(sys_stdout);
102 #ifndef RISCOS
103 if (prompt)
104 fprintf(stderr, "%s", prompt);
105 #else
106 if (prompt) {
107 if(Py_RISCOSWimpFlag)
108 fprintf(stderr, "\x0cr%s\x0c", prompt);
109 else
110 fprintf(stderr, "%s", prompt);
112 #endif
113 fflush(stderr);
114 switch (my_fgets(p, (int)n, sys_stdin)) {
115 case 0: /* Normal case */
116 break;
117 case 1: /* Interrupt */
118 PyMem_FREE(p);
119 return NULL;
120 case -1: /* EOF */
121 case -2: /* Error */
122 default: /* Shouldn't happen */
123 *p = '\0';
124 break;
126 #ifdef MPW
127 /* Hack for MPW C where the prompt comes right back in the input */
128 /* XXX (Actually this would be rather nice on most systems...) */
129 n = strlen(prompt);
130 if (strncmp(p, prompt, n) == 0)
131 memmove(p, p + n, strlen(p) - n + 1);
132 #endif
133 n = strlen(p);
134 while (n > 0 && p[n-1] != '\n') {
135 size_t incr = n+2;
136 p = PyMem_REALLOC(p, n + incr);
137 if (p == NULL)
138 return NULL;
139 if (incr > INT_MAX) {
140 PyErr_SetString(PyExc_OverflowError, "input line too long");
142 if (my_fgets(p+n, (int)incr, sys_stdin) != 0)
143 break;
144 n += strlen(p+n);
146 return PyMem_REALLOC(p, n+1);
150 /* By initializing this function pointer, systems embedding Python can
151 override the readline function.
153 Note: Python expects in return a buffer allocated with PyMem_Malloc. */
155 char *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, char *);
158 /* Interface used by tokenizer.c and bltinmodule.c */
160 char *
161 PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
163 char *rv;
165 if (PyOS_ReadlineFunctionPointer == NULL) {
166 #ifdef __VMS
167 PyOS_ReadlineFunctionPointer = vms__StdioReadline;
168 #else
169 PyOS_ReadlineFunctionPointer = PyOS_StdioReadline;
170 #endif
173 Py_BEGIN_ALLOW_THREADS
175 /* This is needed to handle the unlikely case that the
176 * interpreter is in interactive mode *and* stdin/out are not
177 * a tty. This can happen, for example if python is run like
178 * this: python -i < test1.py
180 if (!isatty (fileno (sys_stdin)) || !isatty (fileno (sys_stdout)))
181 rv = PyOS_StdioReadline (sys_stdin, sys_stdout, prompt);
182 else
183 rv = (*PyOS_ReadlineFunctionPointer)(sys_stdin, sys_stdout,
184 prompt);
185 Py_END_ALLOW_THREADS
186 return rv;