2222 */
2323
2424Input * input ;
25+ char * prompt , * prompt2 ;
26+
2527Boolean ignoreeof = FALSE;
2628
2729
@@ -101,8 +103,11 @@ extern void unget(Input *in, int c) {
101103/* get -- get a character, filter out nulls */
102104static int get (Input * in ) {
103105 int c ;
106+ Boolean uf = (in -> fill == ungetfill );
104107 while ((c = (in -> buf < in -> bufend ? * in -> buf ++ : (* in -> fill )(in ))) == '\0' )
105108 warn ("null character ignored" );
109+ if (!uf && c != EOF )
110+ addhistbuffer ((char )c );
106111 return c ;
107112}
108113
@@ -126,9 +131,58 @@ static int eoffill(Input UNUSED *in) {
126131 return EOF ;
127132}
128133
134+ #if HAVE_READLINE
135+ /* callreadline -- readline wrapper */
136+ static char * callreadline (char * prompt0 ) {
137+ char * volatile prompt = prompt0 ;
138+ char * r ;
139+ if (prompt == NULL )
140+ prompt = "" ; /* bug fix for readline 2.0 */
141+ rlsetup (FALSE);
142+ interrupted = FALSE;
143+ if (!setjmp (slowlabel )) {
144+ slow = TRUE;
145+ r = interrupted ? NULL : readline (prompt );
146+ if (interrupted )
147+ errno = EINTR ;
148+ } else {
149+ r = NULL ;
150+ errno = EINTR ;
151+ }
152+ slow = FALSE;
153+ SIGCHK ();
154+ return r ;
155+ }
156+ #endif
157+
129158/* fdfill -- fill input buffer by reading from a file descriptor */
130159static int fdfill (Input * in ) {
131160 long nread ;
161+ assert (in -> buf == in -> bufend );
162+ assert (in -> fd >= 0 );
163+
164+ #if HAVE_READLINE
165+ if (in -> runflags & run_interactive && in -> fd == 0 ) {
166+ char * rlinebuf = NULL ;
167+ do {
168+ rlinebuf = callreadline (prompt );
169+ } while (rlinebuf == NULL && errno == EINTR );
170+
171+ if (rlinebuf == NULL )
172+ nread = 0 ;
173+ else {
174+ nread = strlen (rlinebuf ) + 1 ;
175+ if (in -> buflen < (unsigned int )nread ) {
176+ while (in -> buflen < (unsigned int )nread )
177+ in -> buflen *= 2 ;
178+ in -> bufbegin = erealloc (in -> bufbegin , in -> buflen );
179+ }
180+ memcpy (in -> bufbegin , rlinebuf , nread - 1 );
181+ in -> bufbegin [nread - 1 ] = '\n' ;
182+ efree (rlinebuf );
183+ }
184+ } else
185+ #endif
132186 do {
133187 nread = eread (in -> fd , (char * ) in -> bufbegin , in -> buflen );
134188 SIGCHK ();
@@ -151,69 +205,13 @@ static int fdfill(Input *in) {
151205 return * in -> buf ++ ;
152206}
153207
154- static List * fillcmd = NULL ;
155-
156- static int cmdfill (Input * in ) {
157- char * read ;
158- List * result ;
159- size_t nread ;
160- int oldf ;
161-
162- assert (in -> buf == in -> bufend );
163- assert (in -> fd >= 0 );
164-
165- if (fillcmd == NULL )
166- return fdfill (in );
167-
168- oldf = dup (0 );
169- if (dup2 (in -> fd , 0 ) == -1 )
170- fail ("$&parse" , "dup2: %s" , esstrerror (errno ));
171-
172- ExceptionHandler
173-
174- result = eval (fillcmd , NULL , 0 );
175-
176- CatchException (e )
177-
178- mvfd (oldf , 0 );
179- throw (e );
180-
181- EndExceptionHandler
182-
183- mvfd (oldf , 0 );
184-
185- if (result == NULL ) { /* eof */
186- if (!ignoreeof ) {
187- close (in -> fd );
188- in -> fd = -1 ;
189- in -> fill = eoffill ;
190- in -> runflags &= ~run_interactive ;
191- }
192- return EOF ;
193- }
194- read = str ("%L\n" , result , " " );
195-
196- if ((nread = strlen (read )) > in -> buflen ) {
197- in -> bufbegin = erealloc (in -> bufbegin , nread );
198- in -> buflen = nread ;
199- }
200- memcpy (in -> bufbegin , read , nread );
201-
202- in -> buf = in -> bufbegin ;
203- in -> bufend = & in -> buf [nread ];
204-
205- return * in -> buf ++ ;
206- }
207208
208209/*
209210 * the input loop
210211 */
211212
212-
213- static Boolean parsing = FALSE;
214-
215- /* parse -- call yyparse() and catch errors */
216- extern Tree * parse (List * fc ) {
213+ /* parse -- call yyparse(), but disable garbage collection and catch errors */
214+ extern Tree * parse (char * pr1 , char * pr2 ) {
217215 int result ;
218216 assert (error == NULL );
219217
@@ -223,27 +221,17 @@ extern Tree *parse(List *fc) {
223221 if (ISEOF (input ))
224222 throw (mklist (mkstr ("eof" ), NULL ));
225223
226- if (parsing )
227- fail ("$&parse" , "cannot perform nested parsing" );
228-
229- fillcmd = fc ;
230- parsing = TRUE;
231-
232- ExceptionHandler
233-
234- result = yyparse ();
235-
236- CatchException (e )
237-
238- parsing = FALSE;
239- fillcmd = NULL ;
240- pseal (NULL );
241- throw (e );
242-
243- EndExceptionHandler
224+ #if HAVE_READLINE
225+ prompt = (pr1 == NULL ) ? "" : pr1 ;
226+ #else
227+ if (pr1 != NULL )
228+ eprint ("%s" , pr1 );
229+ #endif
230+ prompt2 = pr2 ;
244231
245- parsing = FALSE;
246- fillcmd = NULL ;
232+ gcdisable ();
233+ result = yyparse ();
234+ gcenable ();
247235
248236 if (result || error != NULL ) {
249237 char * e ;
@@ -340,7 +328,7 @@ extern List *runfd(int fd, const char *name, int flags) {
340328
341329 memzero (& in , sizeof (Input ));
342330 in .lineno = 1 ;
343- in .fill = cmdfill ;
331+ in .fill = fdfill ;
344332 in .cleanup = fdcleanup ;
345333 in .fd = fd ;
346334 registerfd (& in .fd , TRUE);
@@ -403,7 +391,7 @@ extern Tree *parseinput(Input *in) {
403391 input = in ;
404392
405393 ExceptionHandler
406- result = parse (NULL );
394+ result = parse (NULL , NULL );
407395 if (get (in ) != EOF )
408396 fail ("$&parse" , "more than one value in term" );
409397 CatchException (e )
@@ -451,7 +439,7 @@ extern Boolean isinteractive(void) {
451439}
452440
453441extern Boolean isfromfd (void ) {
454- return input == NULL ? FALSE : (input -> fill == fdfill || input -> fill == cmdfill );
442+ return input == NULL ? FALSE : (input -> fill == fdfill );
455443}
456444
457445
@@ -464,6 +452,7 @@ extern void initinput(void) {
464452 input = NULL ;
465453
466454 /* declare the global roots */
467- globalroot (& fillcmd );
468455 globalroot (& error ); /* parse errors */
456+ globalroot (& prompt ); /* main prompt */
457+ globalroot (& prompt2 ); /* secondary prompt */
469458}
0 commit comments