| 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 | { | 
 | 38 | 	char *p; | 
 | 39 | 	for (;;) { | 
| Guido van Rossum | 4462064 | 1997-08-11 18:57:29 +0000 | [diff] [blame] | 40 | 		if (PyOS_InputHook != NULL) | 
 | 41 | 			(void)(PyOS_InputHook)(); | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 42 | 		errno = 0; | 
 | 43 | 		p = fgets(buf, len, fp); | 
 | 44 | 		if (p != NULL) | 
 | 45 | 			return 0; /* No error */ | 
| Mark Hammond | 2f10cb8 | 2002-07-14 23:12:29 +0000 | [diff] [blame] | 46 | #ifdef MS_WINDOWS | 
 | 47 | 		/* In the case of a Ctrl+C or some other external event  | 
 | 48 | 		   interrupting the operation: | 
 | 49 | 		   Win2k/NT: ERROR_OPERATION_ABORTED is the most recent Win32  | 
 | 50 | 		   error code (and feof() returns TRUE). | 
 | 51 | 		   Win9x: Ctrl+C seems to have no effect on fgets() returning | 
 | 52 | 		   early - the signal handler is called, but the fgets() | 
 | 53 | 		   only returns "normally" (ie, when Enter hit or feof()) | 
 | 54 | 		*/ | 
 | 55 | 		if (GetLastError()==ERROR_OPERATION_ABORTED) { | 
 | 56 | 			/* Signals come asynchronously, so we sleep a brief  | 
 | 57 | 			   moment before checking if the handler has been  | 
 | 58 | 			   triggered (we cant just return 1 before the  | 
 | 59 | 			   signal handler has been called, as the later  | 
 | 60 | 			   signal may be treated as a separate interrupt). | 
 | 61 | 			*/ | 
 | 62 | 			Sleep(1); | 
 | 63 | 			if (PyOS_InterruptOccurred()) { | 
 | 64 | 				return 1; /* Interrupt */ | 
 | 65 | 			} | 
 | 66 | 			/* Either the sleep wasn't long enough (need a | 
 | 67 | 			   short loop retrying?) or not interrupted at all | 
 | 68 | 			   (in which case we should revisit the whole thing!) | 
 | 69 | 			   Logging some warning would be nice.  assert is not | 
 | 70 | 			   viable as under the debugger, the various dialogs | 
 | 71 | 			   mean the condition is not true. | 
 | 72 | 			*/ | 
 | 73 | 		} | 
 | 74 | #endif /* MS_WINDOWS */ | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 75 | 		if (feof(fp)) { | 
 | 76 | 			return -1; /* EOF */ | 
 | 77 | 		} | 
 | 78 | #ifdef EINTR | 
 | 79 | 		if (errno == EINTR) { | 
| Michael W. Hudson | 30ea2f2 | 2004-07-07 17:44:12 +0000 | [diff] [blame] | 80 | 			int s; | 
| Michael W. Hudson | e3afc59 | 2005-04-07 10:11:19 +0000 | [diff] [blame] | 81 | #ifdef WITH_THREAD | 
| Michael W. Hudson | 30ea2f2 | 2004-07-07 17:44:12 +0000 | [diff] [blame] | 82 | 			PyEval_RestoreThread(_PyOS_ReadlineTState); | 
| Michael W. Hudson | e3afc59 | 2005-04-07 10:11:19 +0000 | [diff] [blame] | 83 | #endif | 
| Michael W. Hudson | 30ea2f2 | 2004-07-07 17:44:12 +0000 | [diff] [blame] | 84 | 			s = PyErr_CheckSignals(); | 
| Michael W. Hudson | e3afc59 | 2005-04-07 10:11:19 +0000 | [diff] [blame] | 85 | #ifdef WITH_THREAD | 
| Michael W. Hudson | 2384990 | 2004-07-08 15:28:26 +0000 | [diff] [blame] | 86 | 			PyEval_SaveThread(); | 
| Michael W. Hudson | e3afc59 | 2005-04-07 10:11:19 +0000 | [diff] [blame] | 87 | #endif | 
| Michael W. Hudson | 30ea2f2 | 2004-07-07 17:44:12 +0000 | [diff] [blame] | 88 | 			if (s < 0) { | 
 | 89 | 				return 1; | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 90 | 			} | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 91 | 		} | 
 | 92 | #endif | 
 | 93 | 		if (PyOS_InterruptOccurred()) { | 
 | 94 | 			return 1; /* Interrupt */ | 
 | 95 | 		} | 
 | 96 | 		return -2; /* Error */ | 
 | 97 | 	} | 
 | 98 | 	/* NOTREACHED */ | 
 | 99 | } | 
 | 100 |  | 
 | 101 |  | 
 | 102 | /* Readline implementation using fgets() */ | 
 | 103 |  | 
 | 104 | char * | 
| Martin v. Löwis | 566f6af | 2002-10-26 14:39:10 +0000 | [diff] [blame] | 105 | PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, char *prompt) | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 106 | { | 
| Guido van Rossum | 6da3434 | 2000-06-28 22:00:02 +0000 | [diff] [blame] | 107 | 	size_t n; | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 108 | 	char *p; | 
| Guido van Rossum | 6fa6343 | 1993-12-24 10:36:57 +0000 | [diff] [blame] | 109 | 	n = 100; | 
| Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 110 | 	if ((p = (char *)PyMem_MALLOC(n)) == NULL) | 
| Guido van Rossum | 6fa6343 | 1993-12-24 10:36:57 +0000 | [diff] [blame] | 111 | 		return NULL; | 
| Martin v. Löwis | 566f6af | 2002-10-26 14:39:10 +0000 | [diff] [blame] | 112 | 	fflush(sys_stdout); | 
| Guido van Rossum | 6fa6343 | 1993-12-24 10:36:57 +0000 | [diff] [blame] | 113 | 	if (prompt) | 
 | 114 | 		fprintf(stderr, "%s", prompt); | 
| Guido van Rossum | c7fea2f | 1996-01-12 01:30:55 +0000 | [diff] [blame] | 115 | 	fflush(stderr); | 
| Martin v. Löwis | 566f6af | 2002-10-26 14:39:10 +0000 | [diff] [blame] | 116 | 	switch (my_fgets(p, (int)n, sys_stdin)) { | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 117 | 	case 0: /* Normal case */ | 
 | 118 | 		break; | 
 | 119 | 	case 1: /* Interrupt */ | 
| Guido van Rossum | b18618d | 2000-05-03 23:44:39 +0000 | [diff] [blame] | 120 | 		PyMem_FREE(p); | 
| Guido van Rossum | 6fa6343 | 1993-12-24 10:36:57 +0000 | [diff] [blame] | 121 | 		return NULL; | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 122 | 	case -1: /* EOF */ | 
 | 123 | 	case -2: /* Error */ | 
 | 124 | 	default: /* Shouldn't happen */ | 
 | 125 | 		*p = '\0'; | 
 | 126 | 		break; | 
| Guido van Rossum | 6fa6343 | 1993-12-24 10:36:57 +0000 | [diff] [blame] | 127 | 	} | 
 | 128 | 	n = strlen(p); | 
 | 129 | 	while (n > 0 && p[n-1] != '\n') { | 
| Guido van Rossum | 6da3434 | 2000-06-28 22:00:02 +0000 | [diff] [blame] | 130 | 		size_t incr = n+2; | 
| Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 131 | 		p = (char *)PyMem_REALLOC(p, n + incr); | 
| Guido van Rossum | 6fa6343 | 1993-12-24 10:36:57 +0000 | [diff] [blame] | 132 | 		if (p == NULL) | 
 | 133 | 			return NULL; | 
| Guido van Rossum | 6da3434 | 2000-06-28 22:00:02 +0000 | [diff] [blame] | 134 | 		if (incr > INT_MAX) { | 
 | 135 | 			PyErr_SetString(PyExc_OverflowError, "input line too long"); | 
 | 136 | 		} | 
| Martin v. Löwis | 566f6af | 2002-10-26 14:39:10 +0000 | [diff] [blame] | 137 | 		if (my_fgets(p+n, (int)incr, sys_stdin) != 0) | 
| Guido van Rossum | 6fa6343 | 1993-12-24 10:36:57 +0000 | [diff] [blame] | 138 | 			break; | 
 | 139 | 		n += strlen(p+n); | 
 | 140 | 	} | 
| Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 141 | 	return (char *)PyMem_REALLOC(p, n+1); | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 142 | } | 
 | 143 |  | 
 | 144 |  | 
 | 145 | /* By initializing this function pointer, systems embedding Python can | 
| Guido van Rossum | b18618d | 2000-05-03 23:44:39 +0000 | [diff] [blame] | 146 |    override the readline function. | 
 | 147 |  | 
 | 148 |    Note: Python expects in return a buffer allocated with PyMem_Malloc. */ | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 149 |  | 
| Martin v. Löwis | 566f6af | 2002-10-26 14:39:10 +0000 | [diff] [blame] | 150 | char *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, char *); | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 151 |  | 
 | 152 |  | 
 | 153 | /* Interface used by tokenizer.c and bltinmodule.c */ | 
 | 154 |  | 
 | 155 | char * | 
| Martin v. Löwis | 566f6af | 2002-10-26 14:39:10 +0000 | [diff] [blame] | 156 | PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt) | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 157 | { | 
| Guido van Rossum | 80c7bcf | 1998-08-29 16:03:27 +0000 | [diff] [blame] | 158 | 	char *rv; | 
| Martin v. Löwis | 566f6af | 2002-10-26 14:39:10 +0000 | [diff] [blame] | 159 |  | 
| Michael W. Hudson | 30ea2f2 | 2004-07-07 17:44:12 +0000 | [diff] [blame] | 160 | 	if (_PyOS_ReadlineTState == PyThreadState_GET()) { | 
 | 161 | 		PyErr_SetString(PyExc_RuntimeError, | 
 | 162 | 				"can't re-enter readline"); | 
 | 163 | 		return NULL; | 
 | 164 | 	} | 
 | 165 | 	 | 
 | 166 |  | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 167 | 	if (PyOS_ReadlineFunctionPointer == NULL) { | 
| Martin v. Löwis | c16f3bd | 2003-05-03 09:14:54 +0000 | [diff] [blame] | 168 | #ifdef __VMS | 
 | 169 |                 PyOS_ReadlineFunctionPointer = vms__StdioReadline; | 
 | 170 | #else | 
| Martin v. Löwis | 566f6af | 2002-10-26 14:39:10 +0000 | [diff] [blame] | 171 |                 PyOS_ReadlineFunctionPointer = PyOS_StdioReadline; | 
| Martin v. Löwis | c16f3bd | 2003-05-03 09:14:54 +0000 | [diff] [blame] | 172 | #endif | 
| Guido van Rossum | fbd64c8 | 1997-02-18 21:53:32 +0000 | [diff] [blame] | 173 | 	} | 
| Michael W. Hudson | 30ea2f2 | 2004-07-07 17:44:12 +0000 | [diff] [blame] | 174 | 	 | 
| Tim Peters | b7e898a | 2004-07-07 20:42:07 +0000 | [diff] [blame] | 175 | #ifdef WITH_THREAD | 
| Michael W. Hudson | 30ea2f2 | 2004-07-07 17:44:12 +0000 | [diff] [blame] | 176 | 	if (_PyOS_ReadlineLock == NULL) { | 
 | 177 | 		_PyOS_ReadlineLock = PyThread_allocate_lock();		 | 
 | 178 | 	} | 
 | 179 | #endif | 
| Martin v. Löwis | 566f6af | 2002-10-26 14:39:10 +0000 | [diff] [blame] | 180 |  | 
| Michael W. Hudson | 30ea2f2 | 2004-07-07 17:44:12 +0000 | [diff] [blame] | 181 | 	_PyOS_ReadlineTState = PyThreadState_GET(); | 
| Guido van Rossum | 8efa47b | 1998-08-27 19:43:43 +0000 | [diff] [blame] | 182 | 	Py_BEGIN_ALLOW_THREADS | 
| Tim Peters | b7e898a | 2004-07-07 20:42:07 +0000 | [diff] [blame] | 183 | #ifdef WITH_THREAD | 
| Michael W. Hudson | 30ea2f2 | 2004-07-07 17:44:12 +0000 | [diff] [blame] | 184 | 	PyThread_acquire_lock(_PyOS_ReadlineLock, 1); | 
 | 185 | #endif | 
| Martin v. Löwis | 566f6af | 2002-10-26 14:39:10 +0000 | [diff] [blame] | 186 |  | 
 | 187 |         /* This is needed to handle the unlikely case that the | 
 | 188 |          * interpreter is in interactive mode *and* stdin/out are not | 
 | 189 |          * a tty.  This can happen, for example if python is run like | 
 | 190 |          * this: python -i < test1.py | 
 | 191 |          */ | 
 | 192 |         if (!isatty (fileno (sys_stdin)) || !isatty (fileno (sys_stdout))) | 
 | 193 |                 rv = PyOS_StdioReadline (sys_stdin, sys_stdout, prompt); | 
 | 194 |         else | 
 | 195 |                 rv = (*PyOS_ReadlineFunctionPointer)(sys_stdin, sys_stdout, | 
 | 196 |                                                      prompt); | 
| Guido van Rossum | 8efa47b | 1998-08-27 19:43:43 +0000 | [diff] [blame] | 197 | 	Py_END_ALLOW_THREADS | 
| 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 | 
| Michael W. Hudson | 30ea2f2 | 2004-07-07 17:44:12 +0000 | [diff] [blame] | 200 | 	PyThread_release_lock(_PyOS_ReadlineLock); | 
 | 201 | #endif | 
 | 202 |  | 
 | 203 | 	_PyOS_ReadlineTState = NULL; | 
 | 204 |  | 
| Guido van Rossum | 80c7bcf | 1998-08-29 16:03:27 +0000 | [diff] [blame] | 205 | 	return rv; | 
| Guido van Rossum | 6fa6343 | 1993-12-24 10:36:57 +0000 | [diff] [blame] | 206 | } |