blob: a996a6ef908574a8891a2c5c7f4d891901cd6da6 [file] [log] [blame]
Guido van Rossum6fa63431993-12-24 10:36:57 +00001/***********************************************************
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00002Copyright (c) 2000, BeOpen.com.
3Copyright (c) 1995-2000, Corporation for National Research Initiatives.
4Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
5All rights reserved.
Guido van Rossum6fa63431993-12-24 10:36:57 +00006
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00007See the file "Misc/COPYRIGHT" for information on usage and
8redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
Guido van Rossum6fa63431993-12-24 10:36:57 +00009******************************************************************/
10
Guido van Rossumfbd64c81997-02-18 21:53:32 +000011/* Readline interface for tokenizer.c and [raw_]input() in bltinmodule.c.
12 By default, or when stdin is not a tty device, we have a super
13 simple my_readline function using fgets.
14 Optionally, we can use the GNU readline library.
Guido van Rossum6fa63431993-12-24 10:36:57 +000015 my_readline() has a different return value from GNU readline():
16 - NULL if an interrupt occurred or if an error occurred
17 - a malloc'ed empty string if EOF was read
18 - a malloc'ed string ending in \n normally
19*/
20
Guido van Rossum8efa47b1998-08-27 19:43:43 +000021#include "Python.h"
Jack Jansen41aa8e52000-07-03 21:39:47 +000022#ifdef HAVE_LIMITS_H
23#include <limits.h>
24#endif
Guido van Rossum6fa63431993-12-24 10:36:57 +000025
Thomas Wouters23c9e002000-07-22 19:20:54 +000026int (*PyOS_InputHook)(void) = NULL;
Guido van Rossumfbd64c81997-02-18 21:53:32 +000027
28/* This function restarts a fgets() after an EINTR error occurred
29 except if PyOS_InterruptOccurred() returns true. */
30
31static int
Thomas Wouters23c9e002000-07-22 19:20:54 +000032my_fgets(char *buf, int len, FILE *fp)
Guido van Rossumfbd64c81997-02-18 21:53:32 +000033{
34 char *p;
35 for (;;) {
Guido van Rossum44620641997-08-11 18:57:29 +000036 if (PyOS_InputHook != NULL)
37 (void)(PyOS_InputHook)();
Guido van Rossumfbd64c81997-02-18 21:53:32 +000038 errno = 0;
39 p = fgets(buf, len, fp);
40 if (p != NULL)
41 return 0; /* No error */
42 if (feof(fp)) {
43 return -1; /* EOF */
44 }
45#ifdef EINTR
46 if (errno == EINTR) {
47 if (PyOS_InterruptOccurred()) {
48 return 1; /* Interrupt */
49 }
50 continue;
51 }
52#endif
53 if (PyOS_InterruptOccurred()) {
54 return 1; /* Interrupt */
55 }
56 return -2; /* Error */
57 }
58 /* NOTREACHED */
59}
60
61
62/* Readline implementation using fgets() */
63
64char *
Thomas Wouters23c9e002000-07-22 19:20:54 +000065PyOS_StdioReadline(char *prompt)
Guido van Rossumfbd64c81997-02-18 21:53:32 +000066{
Guido van Rossum6da34342000-06-28 22:00:02 +000067 size_t n;
Guido van Rossumfbd64c81997-02-18 21:53:32 +000068 char *p;
Guido van Rossum6fa63431993-12-24 10:36:57 +000069 n = 100;
Guido van Rossumb18618d2000-05-03 23:44:39 +000070 if ((p = PyMem_MALLOC(n)) == NULL)
Guido van Rossum6fa63431993-12-24 10:36:57 +000071 return NULL;
Guido van Rossumc7fea2f1996-01-12 01:30:55 +000072 fflush(stdout);
Guido van Rossum6fa63431993-12-24 10:36:57 +000073 if (prompt)
74 fprintf(stderr, "%s", prompt);
Guido van Rossumc7fea2f1996-01-12 01:30:55 +000075 fflush(stderr);
Guido van Rossum6da34342000-06-28 22:00:02 +000076 switch (my_fgets(p, (int)n, stdin)) {
Guido van Rossumb6775db1994-08-01 11:34:53 +000077 case 0: /* Normal case */
78 break;
79 case 1: /* Interrupt */
Guido van Rossumb18618d2000-05-03 23:44:39 +000080 PyMem_FREE(p);
Guido van Rossum6fa63431993-12-24 10:36:57 +000081 return NULL;
Guido van Rossumb6775db1994-08-01 11:34:53 +000082 case -1: /* EOF */
83 case -2: /* Error */
84 default: /* Shouldn't happen */
85 *p = '\0';
86 break;
Guido van Rossum6fa63431993-12-24 10:36:57 +000087 }
Guido van Rossumb6775db1994-08-01 11:34:53 +000088#ifdef MPW
89 /* Hack for MPW C where the prompt comes right back in the input */
90 /* XXX (Actually this would be rather nice on most systems...) */
91 n = strlen(prompt);
92 if (strncmp(p, prompt, n) == 0)
93 memmove(p, p + n, strlen(p) - n + 1);
94#endif
Guido van Rossum6fa63431993-12-24 10:36:57 +000095 n = strlen(p);
96 while (n > 0 && p[n-1] != '\n') {
Guido van Rossum6da34342000-06-28 22:00:02 +000097 size_t incr = n+2;
Guido van Rossumb18618d2000-05-03 23:44:39 +000098 p = PyMem_REALLOC(p, n + incr);
Guido van Rossum6fa63431993-12-24 10:36:57 +000099 if (p == NULL)
100 return NULL;
Guido van Rossum6da34342000-06-28 22:00:02 +0000101 if (incr > INT_MAX) {
102 PyErr_SetString(PyExc_OverflowError, "input line too long");
103 }
104 if (my_fgets(p+n, (int)incr, stdin) != 0)
Guido van Rossum6fa63431993-12-24 10:36:57 +0000105 break;
106 n += strlen(p+n);
107 }
Guido van Rossumb18618d2000-05-03 23:44:39 +0000108 return PyMem_REALLOC(p, n+1);
Guido van Rossumfbd64c81997-02-18 21:53:32 +0000109}
110
111
112/* By initializing this function pointer, systems embedding Python can
Guido van Rossumb18618d2000-05-03 23:44:39 +0000113 override the readline function.
114
115 Note: Python expects in return a buffer allocated with PyMem_Malloc. */
Guido van Rossumfbd64c81997-02-18 21:53:32 +0000116
Tim Petersdbd9ba62000-07-09 03:09:57 +0000117char *(*PyOS_ReadlineFunctionPointer)(char *);
Guido van Rossumfbd64c81997-02-18 21:53:32 +0000118
119
120/* Interface used by tokenizer.c and bltinmodule.c */
121
122char *
Thomas Wouters23c9e002000-07-22 19:20:54 +0000123PyOS_Readline(char *prompt)
Guido van Rossumfbd64c81997-02-18 21:53:32 +0000124{
Guido van Rossum80c7bcf1998-08-29 16:03:27 +0000125 char *rv;
Guido van Rossumfbd64c81997-02-18 21:53:32 +0000126 if (PyOS_ReadlineFunctionPointer == NULL) {
Guido van Rossumfbd64c81997-02-18 21:53:32 +0000127 PyOS_ReadlineFunctionPointer = PyOS_StdioReadline;
128 }
Guido van Rossum8efa47b1998-08-27 19:43:43 +0000129 Py_BEGIN_ALLOW_THREADS
Guido van Rossum80c7bcf1998-08-29 16:03:27 +0000130 rv = (*PyOS_ReadlineFunctionPointer)(prompt);
Guido van Rossum8efa47b1998-08-27 19:43:43 +0000131 Py_END_ALLOW_THREADS
Guido van Rossum80c7bcf1998-08-29 16:03:27 +0000132 return rv;
Guido van Rossum6fa63431993-12-24 10:36:57 +0000133}