blob: 18f8b1d01b8d66ed83a030909323e0ac00b5cd7b [file] [log] [blame]
Guido van Rossum6fa63431993-12-24 10:36:57 +00001/***********************************************************
Guido van Rossumb6775db1994-08-01 11:34:53 +00002Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Guido van Rossum6fa63431993-12-24 10:36:57 +00003Amsterdam, The Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* Readline interface for tokenizer.c.
26 By default, we have a super simple my_readline function.
27 Optionally, we can use the GNU readline library (to be found in the
28 bash distribution).
29 my_readline() has a different return value from GNU readline():
30 - NULL if an interrupt occurred or if an error occurred
31 - a malloc'ed empty string if EOF was read
32 - a malloc'ed string ending in \n normally
33*/
34
Guido van Rossumb6775db1994-08-01 11:34:53 +000035#ifdef HAVE_CONFIG_H
36#include "config.h"
37#endif
38
Guido van Rossum6fa63431993-12-24 10:36:57 +000039#include <stdio.h>
40#include <string.h>
Guido van Rossumb6775db1994-08-01 11:34:53 +000041#include <errno.h>
Guido van Rossum6fa63431993-12-24 10:36:57 +000042
Guido van Rossumb6775db1994-08-01 11:34:53 +000043#include "myproto.h"
Guido van Rossum6fa63431993-12-24 10:36:57 +000044#include "mymalloc.h"
Guido van Rossumb6775db1994-08-01 11:34:53 +000045#include "intrcheck.h"
Guido van Rossum6fa63431993-12-24 10:36:57 +000046
Guido van Rossumb6775db1994-08-01 11:34:53 +000047#ifdef WITH_READLINE
Guido van Rossum6fa63431993-12-24 10:36:57 +000048
49extern char *readline();
50
51#include <setjmp.h>
52#include <signal.h>
53
54static jmp_buf jbuf;
55
56/* ARGSUSED */
57static RETSIGTYPE
58onintr(sig)
59 int sig;
60{
61 longjmp(jbuf, 1);
62}
63
Guido van Rossumb6775db1994-08-01 11:34:53 +000064#else /* !WITH_READLINE */
65
66/* This function restarts a fgets() after an EINTR error occurred
67 except if intrcheck() returns true. */
68
69static int
70my_fgets(buf, len, fp)
71 char *buf;
72 int len;
73 FILE *fp;
74{
75 char *p;
76 for (;;) {
77 errno = 0;
78 p = fgets(buf, len, fp);
79 if (p != NULL)
80 return 0; /* No error */
81 if (feof(fp)) {
82 return -1; /* EOF */
83 }
84#ifdef EINTR
85 if (errno == EINTR) {
86 if (intrcheck()) {
87 return 1; /* Interrupt */
88 }
89 continue;
90 }
91#endif
92 if (intrcheck()) {
93 return 1; /* Interrupt */
94 }
95 return -2; /* Error */
96 }
97 /* NOTREACHED */
98}
99
100#endif /* WITH_READLINE */
101
Guido van Rossum6fa63431993-12-24 10:36:57 +0000102
103char *
104my_readline(prompt)
105 char *prompt;
106{
107 int n;
108 char *p;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000109#ifdef WITH_READLINE
Guido van Rossum6fa63431993-12-24 10:36:57 +0000110 RETSIGTYPE (*old_inthandler)();
111 static int been_here;
112 if (!been_here) {
113 /* Force rebind of TAB to insert-tab */
114 extern int rl_insert();
115 rl_bind_key('\t', rl_insert);
116 been_here++;
117 }
118 old_inthandler = signal(SIGINT, onintr);
119 if (setjmp(jbuf)) {
120 signal(SIGINT, old_inthandler);
121 return NULL;
122 }
123 p = readline(prompt);
124 signal(SIGINT, old_inthandler);
125 if (p == NULL) {
126 p = malloc(1);
127 if (p != NULL)
128 *p = '\0';
129 return p;
130 }
131 n = strlen(p);
132 if (n > 0)
133 add_history(p);
134 if ((p = realloc(p, n+2)) != NULL) {
135 p[n] = '\n';
136 p[n+1] = '\0';
137 }
138 return p;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000139#else /* !WITH_READLINE */
Guido van Rossum6fa63431993-12-24 10:36:57 +0000140 n = 100;
141 if ((p = malloc(n)) == NULL)
142 return NULL;
143 if (prompt)
144 fprintf(stderr, "%s", prompt);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000145 switch (my_fgets(p, n, stdin)) {
146 case 0: /* Normal case */
147 break;
148 case 1: /* Interrupt */
Guido van Rossum6fa63431993-12-24 10:36:57 +0000149 free(p);
150 return NULL;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000151 case -1: /* EOF */
152 case -2: /* Error */
153 default: /* Shouldn't happen */
154 *p = '\0';
155 break;
Guido van Rossum6fa63431993-12-24 10:36:57 +0000156 }
Guido van Rossumb6775db1994-08-01 11:34:53 +0000157#ifdef MPW
158 /* Hack for MPW C where the prompt comes right back in the input */
159 /* XXX (Actually this would be rather nice on most systems...) */
160 n = strlen(prompt);
161 if (strncmp(p, prompt, n) == 0)
162 memmove(p, p + n, strlen(p) - n + 1);
163#endif
Guido van Rossum6fa63431993-12-24 10:36:57 +0000164 n = strlen(p);
165 while (n > 0 && p[n-1] != '\n') {
166 int incr = n+2;
167 p = realloc(p, n + incr);
168 if (p == NULL)
169 return NULL;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000170 if (my_fgets(p+n, incr, stdin) != 0)
Guido van Rossum6fa63431993-12-24 10:36:57 +0000171 break;
172 n += strlen(p+n);
173 }
174 return realloc(p, n+1);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000175#endif /* !WITH_READLINE */
Guido van Rossum6fa63431993-12-24 10:36:57 +0000176}