ยปCore Development>Code coverage>Parser/myreadline.c

Python code coverage for Parser/myreadline.c

#countcontent
1n/a
2n/a/* Readline interface for tokenizer.c and [raw_]input() in bltinmodule.c.
3n/a By default, or when stdin is not a tty device, we have a super
4n/a simple my_readline function using fgets.
5n/a Optionally, we can use the GNU readline library.
6n/a my_readline() has a different return value from GNU readline():
7n/a - NULL if an interrupt occurred or if an error occurred
8n/a - a malloc'ed empty string if EOF was read
9n/a - a malloc'ed string ending in \n normally
10n/a*/
11n/a
12n/a#include "Python.h"
13n/a#ifdef MS_WINDOWS
14n/a#define WIN32_LEAN_AND_MEAN
15n/a#include "windows.h"
16n/a#endif /* MS_WINDOWS */
17n/a
18n/a
19n/aPyThreadState* _PyOS_ReadlineTState;
20n/a
21n/a#ifdef WITH_THREAD
22n/a#include "pythread.h"
23n/astatic PyThread_type_lock _PyOS_ReadlineLock = NULL;
24n/a#endif
25n/a
26n/aint (*PyOS_InputHook)(void) = NULL;
27n/a
28n/a/* This function restarts a fgets() after an EINTR error occurred
29n/a except if PyOS_InterruptOccurred() returns true. */
30n/a
31n/astatic int
32n/amy_fgets(char *buf, int len, FILE *fp)
33n/a{
34n/a#ifdef MS_WINDOWS
35n/a HANDLE hInterruptEvent;
36n/a#endif
37n/a char *p;
38n/a int err;
39n/a while (1) {
40n/a if (PyOS_InputHook != NULL)
41n/a (void)(PyOS_InputHook)();
42n/a errno = 0;
43n/a clearerr(fp);
44n/a p = fgets(buf, len, fp);
45n/a if (p != NULL)
46n/a return 0; /* No error */
47n/a err = errno;
48n/a#ifdef MS_WINDOWS
49n/a /* Ctrl-C anywhere on the line or Ctrl-Z if the only character
50n/a on a line will set ERROR_OPERATION_ABORTED. Under normal
51n/a circumstances Ctrl-C will also have caused the SIGINT handler
52n/a to fire which will have set the event object returned by
53n/a _PyOS_SigintEvent. This signal fires in another thread and
54n/a is not guaranteed to have occurred before this point in the
55n/a code.
56n/a
57n/a Therefore: check whether the event is set with a small timeout.
58n/a If it is, assume this is a Ctrl-C and reset the event. If it
59n/a isn't set assume that this is a Ctrl-Z on its own and drop
60n/a through to check for EOF.
61n/a */
62n/a if (GetLastError()==ERROR_OPERATION_ABORTED) {
63n/a hInterruptEvent = _PyOS_SigintEvent();
64n/a switch (WaitForSingleObjectEx(hInterruptEvent, 10, FALSE)) {
65n/a case WAIT_OBJECT_0:
66n/a ResetEvent(hInterruptEvent);
67n/a return 1; /* Interrupt */
68n/a case WAIT_FAILED:
69n/a return -2; /* Error */
70n/a }
71n/a }
72n/a#endif /* MS_WINDOWS */
73n/a if (feof(fp)) {
74n/a clearerr(fp);
75n/a return -1; /* EOF */
76n/a }
77n/a#ifdef EINTR
78n/a if (err == EINTR) {
79n/a int s;
80n/a#ifdef WITH_THREAD
81n/a PyEval_RestoreThread(_PyOS_ReadlineTState);
82n/a#endif
83n/a s = PyErr_CheckSignals();
84n/a#ifdef WITH_THREAD
85n/a PyEval_SaveThread();
86n/a#endif
87n/a if (s < 0)
88n/a return 1;
89n/a /* try again */
90n/a continue;
91n/a }
92n/a#endif
93n/a if (PyOS_InterruptOccurred()) {
94n/a return 1; /* Interrupt */
95n/a }
96n/a return -2; /* Error */
97n/a }
98n/a /* NOTREACHED */
99n/a}
100n/a
101n/a#ifdef MS_WINDOWS
102n/a/* Readline implementation using ReadConsoleW */
103n/a
104n/aextern char _get_console_type(HANDLE handle);
105n/a
106n/achar *
107n/a_PyOS_WindowsConsoleReadline(HANDLE hStdIn)
108n/a{
109n/a static wchar_t wbuf_local[1024 * 16];
110n/a const DWORD chunk_size = 1024;
111n/a
112n/a DWORD n_read, total_read, wbuflen, u8len;
113n/a wchar_t *wbuf;
114n/a char *buf = NULL;
115n/a int err = 0;
116n/a
117n/a n_read = 0;
118n/a total_read = 0;
119n/a wbuf = wbuf_local;
120n/a wbuflen = sizeof(wbuf_local) / sizeof(wbuf_local[0]) - 1;
121n/a while (1) {
122n/a if (!ReadConsoleW(hStdIn, &wbuf[total_read], wbuflen - total_read, &n_read, NULL)) {
123n/a err = GetLastError();
124n/a goto exit;
125n/a }
126n/a if (n_read == 0) {
127n/a int s;
128n/a err = GetLastError();
129n/a if (err != ERROR_OPERATION_ABORTED)
130n/a goto exit;
131n/a err = 0;
132n/a HANDLE hInterruptEvent = _PyOS_SigintEvent();
133n/a if (WaitForSingleObjectEx(hInterruptEvent, 100, FALSE)
134n/a == WAIT_OBJECT_0) {
135n/a ResetEvent(hInterruptEvent);
136n/a#ifdef WITH_THREAD
137n/a PyEval_RestoreThread(_PyOS_ReadlineTState);
138n/a#endif
139n/a s = PyErr_CheckSignals();
140n/a#ifdef WITH_THREAD
141n/a PyEval_SaveThread();
142n/a#endif
143n/a if (s < 0)
144n/a goto exit;
145n/a }
146n/a break;
147n/a }
148n/a
149n/a total_read += n_read;
150n/a if (total_read == 0 || wbuf[total_read - 1] == L'\n') {
151n/a break;
152n/a }
153n/a wbuflen += chunk_size;
154n/a if (wbuf == wbuf_local) {
155n/a wbuf[total_read] = '\0';
156n/a wbuf = (wchar_t*)PyMem_RawMalloc(wbuflen * sizeof(wchar_t));
157n/a if (wbuf)
158n/a wcscpy_s(wbuf, wbuflen, wbuf_local);
159n/a }
160n/a else
161n/a wbuf = (wchar_t*)PyMem_RawRealloc(wbuf, wbuflen * sizeof(wchar_t));
162n/a }
163n/a
164n/a if (wbuf[0] == '\x1a') {
165n/a buf = PyMem_RawMalloc(1);
166n/a if (buf)
167n/a buf[0] = '\0';
168n/a goto exit;
169n/a }
170n/a
171n/a u8len = WideCharToMultiByte(CP_UTF8, 0, wbuf, total_read, NULL, 0, NULL, NULL);
172n/a buf = PyMem_RawMalloc(u8len + 1);
173n/a u8len = WideCharToMultiByte(CP_UTF8, 0, wbuf, total_read, buf, u8len, NULL, NULL);
174n/a buf[u8len] = '\0';
175n/a
176n/aexit:
177n/a if (wbuf != wbuf_local)
178n/a PyMem_RawFree(wbuf);
179n/a
180n/a if (err) {
181n/a#ifdef WITH_THREAD
182n/a PyEval_RestoreThread(_PyOS_ReadlineTState);
183n/a#endif
184n/a PyErr_SetFromWindowsErr(err);
185n/a#ifdef WITH_THREAD
186n/a PyEval_SaveThread();
187n/a#endif
188n/a }
189n/a
190n/a return buf;
191n/a}
192n/a
193n/a#endif
194n/a
195n/a
196n/a/* Readline implementation using fgets() */
197n/a
198n/achar *
199n/aPyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
200n/a{
201n/a size_t n;
202n/a char *p, *pr;
203n/a
204n/a#ifdef MS_WINDOWS
205n/a if (!Py_LegacyWindowsStdioFlag && sys_stdin == stdin) {
206n/a HANDLE hStdIn, hStdErr;
207n/a
208n/a _Py_BEGIN_SUPPRESS_IPH
209n/a hStdIn = (HANDLE)_get_osfhandle(fileno(sys_stdin));
210n/a hStdErr = (HANDLE)_get_osfhandle(fileno(stderr));
211n/a _Py_END_SUPPRESS_IPH
212n/a
213n/a if (_get_console_type(hStdIn) == 'r') {
214n/a fflush(sys_stdout);
215n/a if (prompt) {
216n/a if (_get_console_type(hStdErr) == 'w') {
217n/a wchar_t *wbuf;
218n/a int wlen;
219n/a wlen = MultiByteToWideChar(CP_UTF8, 0, prompt, -1,
220n/a NULL, 0);
221n/a if (wlen &&
222n/a (wbuf = PyMem_RawMalloc(wlen * sizeof(wchar_t)))) {
223n/a wlen = MultiByteToWideChar(CP_UTF8, 0, prompt, -1,
224n/a wbuf, wlen);
225n/a if (wlen) {
226n/a DWORD n;
227n/a fflush(stderr);
228n/a /* wlen includes null terminator, so subtract 1 */
229n/a WriteConsoleW(hStdErr, wbuf, wlen - 1, &n, NULL);
230n/a }
231n/a PyMem_RawFree(wbuf);
232n/a }
233n/a } else {
234n/a fprintf(stderr, "%s", prompt);
235n/a fflush(stderr);
236n/a }
237n/a }
238n/a clearerr(sys_stdin);
239n/a return _PyOS_WindowsConsoleReadline(hStdIn);
240n/a }
241n/a }
242n/a#endif
243n/a
244n/a n = 100;
245n/a p = (char *)PyMem_RawMalloc(n);
246n/a if (p == NULL)
247n/a return NULL;
248n/a
249n/a fflush(sys_stdout);
250n/a if (prompt)
251n/a fprintf(stderr, "%s", prompt);
252n/a fflush(stderr);
253n/a
254n/a switch (my_fgets(p, (int)n, sys_stdin)) {
255n/a case 0: /* Normal case */
256n/a break;
257n/a case 1: /* Interrupt */
258n/a PyMem_RawFree(p);
259n/a return NULL;
260n/a case -1: /* EOF */
261n/a case -2: /* Error */
262n/a default: /* Shouldn't happen */
263n/a *p = '\0';
264n/a break;
265n/a }
266n/a n = strlen(p);
267n/a while (n > 0 && p[n-1] != '\n') {
268n/a size_t incr = n+2;
269n/a if (incr > INT_MAX) {
270n/a PyMem_RawFree(p);
271n/a PyErr_SetString(PyExc_OverflowError, "input line too long");
272n/a return NULL;
273n/a }
274n/a pr = (char *)PyMem_RawRealloc(p, n + incr);
275n/a if (pr == NULL) {
276n/a PyMem_RawFree(p);
277n/a PyErr_NoMemory();
278n/a return NULL;
279n/a }
280n/a p = pr;
281n/a if (my_fgets(p+n, (int)incr, sys_stdin) != 0)
282n/a break;
283n/a n += strlen(p+n);
284n/a }
285n/a pr = (char *)PyMem_RawRealloc(p, n+1);
286n/a if (pr == NULL) {
287n/a PyMem_RawFree(p);
288n/a PyErr_NoMemory();
289n/a return NULL;
290n/a }
291n/a return pr;
292n/a}
293n/a
294n/a
295n/a/* By initializing this function pointer, systems embedding Python can
296n/a override the readline function.
297n/a
298n/a Note: Python expects in return a buffer allocated with PyMem_Malloc. */
299n/a
300n/achar *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *);
301n/a
302n/a
303n/a/* Interface used by tokenizer.c and bltinmodule.c */
304n/a
305n/achar *
306n/aPyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
307n/a{
308n/a char *rv, *res;
309n/a size_t len;
310n/a
311n/a if (_PyOS_ReadlineTState == PyThreadState_GET()) {
312n/a PyErr_SetString(PyExc_RuntimeError,
313n/a "can't re-enter readline");
314n/a return NULL;
315n/a }
316n/a
317n/a
318n/a if (PyOS_ReadlineFunctionPointer == NULL) {
319n/a PyOS_ReadlineFunctionPointer = PyOS_StdioReadline;
320n/a }
321n/a
322n/a#ifdef WITH_THREAD
323n/a if (_PyOS_ReadlineLock == NULL) {
324n/a _PyOS_ReadlineLock = PyThread_allocate_lock();
325n/a }
326n/a#endif
327n/a
328n/a _PyOS_ReadlineTState = PyThreadState_GET();
329n/a Py_BEGIN_ALLOW_THREADS
330n/a#ifdef WITH_THREAD
331n/a PyThread_acquire_lock(_PyOS_ReadlineLock, 1);
332n/a#endif
333n/a
334n/a /* This is needed to handle the unlikely case that the
335n/a * interpreter is in interactive mode *and* stdin/out are not
336n/a * a tty. This can happen, for example if python is run like
337n/a * this: python -i < test1.py
338n/a */
339n/a if (!isatty (fileno (sys_stdin)) || !isatty (fileno (sys_stdout)))
340n/a rv = PyOS_StdioReadline (sys_stdin, sys_stdout, prompt);
341n/a else
342n/a rv = (*PyOS_ReadlineFunctionPointer)(sys_stdin, sys_stdout,
343n/a prompt);
344n/a Py_END_ALLOW_THREADS
345n/a
346n/a#ifdef WITH_THREAD
347n/a PyThread_release_lock(_PyOS_ReadlineLock);
348n/a#endif
349n/a
350n/a _PyOS_ReadlineTState = NULL;
351n/a
352n/a if (rv == NULL)
353n/a return NULL;
354n/a
355n/a len = strlen(rv) + 1;
356n/a res = PyMem_Malloc(len);
357n/a if (res != NULL)
358n/a memcpy(res, rv, len);
359n/a PyMem_RawFree(rv);
360n/a
361n/a return res;
362n/a}