/*********************************************************** Copyright (c) 2000, BeOpen.com. Copyright (c) 1995-2000, Corporation for National Research Initiatives. Copyright (c) 1990-1995, Stichting Mathematisch Centrum. All rights reserved. See the file "Misc/COPYRIGHT" for information on usage and redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. ******************************************************************/ /* Readline interface for tokenizer.c and [raw_]input() in bltinmodule.c. By default, or when stdin is not a tty device, we have a super simple my_readline function using fgets. Optionally, we can use the GNU readline library. my_readline() has a different return value from GNU readline(): - NULL if an interrupt occurred or if an error occurred - a malloc'ed empty string if EOF was read - a malloc'ed string ending in \n normally */ #include "Python.h" #ifdef HAVE_LIMITS_H #include #endif int (*PyOS_InputHook)() = NULL; /* This function restarts a fgets() after an EINTR error occurred except if PyOS_InterruptOccurred() returns true. */ static int my_fgets(buf, len, fp) char *buf; int len; FILE *fp; { char *p; for (;;) { if (PyOS_InputHook != NULL) (void)(PyOS_InputHook)(); errno = 0; p = fgets(buf, len, fp); if (p != NULL) return 0; /* No error */ if (feof(fp)) { return -1; /* EOF */ } #ifdef EINTR if (errno == EINTR) { if (PyOS_InterruptOccurred()) { return 1; /* Interrupt */ } continue; } #endif if (PyOS_InterruptOccurred()) { return 1; /* Interrupt */ } return -2; /* Error */ } /* NOTREACHED */ } /* Readline implementation using fgets() */ char * PyOS_StdioReadline(prompt) char *prompt; { size_t n; char *p; n = 100; if ((p = PyMem_MALLOC(n)) == NULL) return NULL; fflush(stdout); if (prompt) fprintf(stderr, "%s", prompt); fflush(stderr); switch (my_fgets(p, (int)n, stdin)) { case 0: /* Normal case */ break; case 1: /* Interrupt */ PyMem_FREE(p); return NULL; case -1: /* EOF */ case -2: /* Error */ default: /* Shouldn't happen */ *p = '\0'; break; } #ifdef MPW /* Hack for MPW C where the prompt comes right back in the input */ /* XXX (Actually this would be rather nice on most systems...) */ n = strlen(prompt); if (strncmp(p, prompt, n) == 0) memmove(p, p + n, strlen(p) - n + 1); #endif n = strlen(p); while (n > 0 && p[n-1] != '\n') { size_t incr = n+2; p = PyMem_REALLOC(p, n + incr); if (p == NULL) return NULL; if (incr > INT_MAX) { PyErr_SetString(PyExc_OverflowError, "input line too long"); } if (my_fgets(p+n, (int)incr, stdin) != 0) break; n += strlen(p+n); } return PyMem_REALLOC(p, n+1); } /* By initializing this function pointer, systems embedding Python can override the readline function. Note: Python expects in return a buffer allocated with PyMem_Malloc. */ char *(*PyOS_ReadlineFunctionPointer)(char *); /* Interface used by tokenizer.c and bltinmodule.c */ char * PyOS_Readline(prompt) char *prompt; { char *rv; if (PyOS_ReadlineFunctionPointer == NULL) { PyOS_ReadlineFunctionPointer = PyOS_StdioReadline; } Py_BEGIN_ALLOW_THREADS rv = (*PyOS_ReadlineFunctionPointer)(prompt); Py_END_ALLOW_THREADS return rv; }