rc

[fork] interactive rc shell
Log | Files | Refs | README | LICENSE

commit 3202133256713848312dddefba2250a6803bfec6
parent 27e15d138e55da4dbb626b727424d550a1464a69
Author: tjg <tjg>
Date:   Tue, 30 Sep 2003 13:36:41 +0000

checkpoint

Diffstat:
Minput.c | 233+++++++++++++++++++++++++++++++++++++++++--------------------------------------
1 file changed, 122 insertions(+), 111 deletions(-)

diff --git a/input.c b/input.c @@ -4,6 +4,7 @@ #include <errno.h> +#include "edit.h" #include "input.h" #include "jbwrap.h" @@ -13,30 +14,42 @@ to support only one unget of EOF. */ +typedef enum inputtype { + iFd, iString, iEdit +} inputtype; + typedef struct Input { + bool saved, eofread; inputtype t; - char *ibuf; int fd, index, read, lineno, last; - bool saved, eofread; + char *ibuf; + void *cookie; + int (*gchar)(void); + void (*ugchar)(int); } Input; #define BUFSIZE ((size_t) 256) -static char *prompt2; - static char *inbuf; static size_t istacksize, chars_out, chars_in; static bool eofread = FALSE, save_lineno = TRUE; static Input *istack, *itop; -static int (*realgchar)(void); -static void (*realugchar)(int); - int lastchar; -#if EDITLINE || READLINE -static char *rlinebuf, *prompt; -#endif +static char *prompt, *prompt2; + +extern void ugchar(int c) { + if (c == EOF) + eofread = TRUE; + else + (*istack->ugchar)(c); +} + +static void fdstringugchar(int c) { + assert(chars_out); + inbuf[--chars_out] = c; +} extern int gchar() { int c; @@ -46,31 +59,12 @@ extern int gchar() { return lastchar = EOF; } - while ((c = (*realgchar)()) == '\0') + while ((c = (*istack->gchar)()) == '\0') pr_error("warning: null character ignored", 0); return c; } -extern void ugchar(int c) { - (*realugchar)(c); -} - -static int dead() { - return lastchar = EOF; -} - -static void ugdead(int ignore) { - return; -} - -static void ugalive(int c) { - if (c == EOF) - eofread = TRUE; - else - inbuf[--chars_out] = c; -} - /* get the next character from a string. */ static int stringgchar() { @@ -110,64 +104,34 @@ static void history() { } } -/* - read a character from a file-descriptor. If GNU readline is defined, - add a newline and doctor the buffer to look like a regular fdgchar - buffer. -*/ +/* read a character from a file descriptor */ static int fdgchar() { - - if (chars_out >= chars_in + 2) { /* has the buffer been exhausted? if so, replenish it */ - while (1) { -#if EDITLINE || READLINE - if (interactive && istack->t == iFd && isatty(istack->fd)) { - /* The readline library doesn't handle - * read() returning EAGAIN or EIO. */ - makeblocking(istack->fd); - makesamepgrp(istack->fd); - rlinebuf = rc_readline(prompt); - if (rlinebuf == NULL) { - chars_in = 0; - } else { - if (*rlinebuf != '\0') - add_history(rlinebuf); - chars_in = strlen(rlinebuf) + 1; - efree(inbuf); - inbuf = ealloc(chars_in + 3); - strcpy(inbuf+2, rlinebuf); - strcat(inbuf+2, "\n"); - efree(rlinebuf); - } - } else -#endif - { - ssize_t r; - do { - r = rc_read(istack->fd, inbuf + 2, BUFSIZE); - sigchk(); - switch (errno) { - case EAGAIN: - if (!makeblocking(istack->fd)) - panic("not O_NONBLOCK"); + if (chars_out >= chars_in + 2) { /* replenish empty buffer */ + ssize_t r; + do { + r = rc_read(istack->fd, inbuf + 2, BUFSIZE); + sigchk(); + if (r == -1) + switch (errno) { + case EAGAIN: + if (!makeblocking(istack->fd)) + panic("not O_NONBLOCK"); + errno = EINTR; + break; + case EIO: + if (makesamepgrp(istack->fd)) errno = EINTR; - break; - case EIO: - if (makesamepgrp(istack->fd)) - errno = EINTR; - else - errno = EIO; - break; - } - } while (r < 0 && errno == EINTR); - if (r < 0) { - uerror("read"); - rc_raise(eError); + else + errno = EIO; + break; } - chars_in = (size_t) r; - } - break; + } while (r < 0 && errno == EINTR); + if (r < 0) { + uerror("read"); + rc_raise(eError); } + chars_in = (size_t) r; if (chars_in == 0) return lastchar = EOF; chars_out = 2; @@ -175,16 +139,54 @@ static int fdgchar() { writeall(2, inbuf + 2, chars_in); history(); } + + return lastchar = inbuf[chars_out++]; +} + +enum { UNGETSIZE = 2 }; +static int ungetbuf[UNGETSIZE]; +static int ungetcount = 0; + +static void editugchar(int c) { + fprint(2, "in editugchar, with c = %d and ungetcount = %d\n", c, ungetcount); + assert(ungetcount < UNGETSIZE); + ungetbuf[ungetcount++] = c; +} + +/* read a character from a line-editing file descriptor */ + +static int editgchar() { + if (ungetcount) + return lastchar = ungetbuf[--ungetcount]; + + if (chars_out >= chars_in) { /* replenish empty buffer */ + edit_free(istack->cookie); + inbuf = edit_alloc(istack->cookie, &chars_in); + if (inbuf == NULL) { + chars_in = 0; + fprint(2, "exit\n"); + return lastchar = EOF; + } + + chars_out = 0; + if (dashvee) + writeall(2, inbuf, chars_in); + history(); + } + return lastchar = inbuf[chars_out++]; } +void termchange(void) { + if (istack->t == iEdit) + edit_reset(istack->cookie); +} + /* set up the input stack, and put a "dead" input at the bottom, so that yyparse will always read eof */ extern void initinput() { istack = itop = ealloc(istacksize = 256 * sizeof (Input)); - istack->t = iFd; - istack->fd = -1; - realugchar = ugalive; + istack->eofread = TRUE; } /* push an input source onto the stack. set up a new input buffer, and set gchar() */ @@ -204,19 +206,26 @@ static void pushcommon() { itop = erealloc(itop, istacksize *= 2); istack = itop + idiff; } - realugchar = ugalive; chars_out = 2; chars_in = 0; } extern void pushfd(int fd) { pushcommon(); - istack->t = iFd; save_lineno = TRUE; istack->fd = fd; - realgchar = fdgchar; - inbuf = ealloc(BUFSIZE + 2); lineno = 1; + if (editing && interactive && isatty(fd)) { + istack->t = iEdit; + istack->gchar = editgchar; + istack->ugchar = editugchar; + istack->cookie = edit_begin(fd); + } else { + istack->t = iFd; + istack->gchar = fdgchar; + istack->ugchar = fdstringugchar; + inbuf = ealloc(BUFSIZE + 2); + } } extern void pushstring(char **a, bool save) { @@ -224,25 +233,23 @@ extern void pushstring(char **a, bool save) { istack->t = iString; save_lineno = save; inbuf = mprint("..%A", a); - realgchar = stringgchar; + istack->gchar = stringgchar; + istack->ugchar = fdstringugchar; if (save_lineno) lineno = 1; else --lineno; } -/* remove an input source from the stack. restore the right kind of getchar (string,fd) etc. */ +/* remove an input source from the stack. restore associated variables etc. */ extern void popinput() { - if (istack->t == iFd) + if (istack->t == iEdit) + edit_end(istack->cookie); + if (istack->t == iFd || istack->t == iEdit) close(istack->fd); efree(inbuf); --istack; - realgchar = (istack->t == iString ? stringgchar : fdgchar); - if (istack->t == iFd && istack->fd == -1) { /* top of input stack */ - realgchar = dead; - realugchar = ugdead; - } lastchar = istack->last; eofread = istack->eofread; inbuf = istack->ibuf; @@ -285,6 +292,7 @@ extern Node *doit(bool clobberexecit) { for (eof = FALSE; !eof;) { Edata block; Estack e2; + block.b = newblock(); except(eArena, block, &e2); sigchk(); @@ -301,15 +309,20 @@ extern Node *doit(bool clobberexecit) { } died = FALSE; } - if ((s = varlookup("prompt")) != NULL) { -#if EDITLINE || READLINE - if (istack->t == iFd && isatty(istack->fd)) - prompt = s->w; + s = varlookup("prompt"); + if (s != NULL) { + prompt = s->w; + if (s->n != NULL) + prompt2 = s->n->w; else -#endif - fprint(2, "%s", s->w); - prompt2 = (s->n == NULL ? "" : s->n->w); + prompt2 = ""; + } else { + prompt = prompt2 = ""; } + if (istack->t == iFd) + fprint(2, "%s", prompt); + else if (istack->t == iEdit) + edit_prompt(istack->cookie, prompt); } inityy(); if (yyparse() == 1 && execit) @@ -354,14 +367,12 @@ extern void closefds() { } } -extern void print_prompt2() { +extern void nextline() { lineno++; if (interactive) { -#if EDITLINE || READLINE - if (istack->t == iFd && isatty(istack->fd)) - prompt = prompt2; - else -#endif + if (istack->t == iFd) fprint(2, "%s", prompt2); + else if (istack->t == iEdit) + edit_prompt(istack->cookie, prompt2); } }