sbase

suckless unix tools
git clone git://git.suckless.org/sbase
Log | Files | Refs | README | LICENSE

commit 1e10bf6069f472637450f3f1f1933b73dff88a83
parent b710ee81fcdb077d6ff088aa5beab021f58dc3d9
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed, 29 Nov 2023 13:25:07 +0100

ed: Add getinput() and setinput()

These functions allow to read from stdin the full next
line or seting as input a character array. These functions
avoid all the complexity about repeat commands that is very
fragile and depends on having multiple global variables with
weak relation between them.

Diffstat:
Med.c | 171++++++++++++++++++++++++++++++++++++++++++-------------------------------------
1 file changed, 92 insertions(+), 79 deletions(-)

diff --git a/ed.c b/ed.c @@ -64,30 +64,15 @@ static int pflag, modflag, uflag, gflag; static size_t csize; static String cmdline; static char *ocmdline; -static int repidx; +static int inputidx; static char *rhs; static char *lastmatch; static struct undo udata; static int newcmd; -int eol, bol; +static int eol, bol; static sig_atomic_t intr, hup; -static void -discard(void) -{ - int c; - - if (repidx >= 0 || cmdline.siz == 0) - return; - - /* discard until the end of the line */ - if (cmdline.str[cmdline.siz-1] != '\n') { - while ((c = getchar()) != '\n' && c != EOF) - ; - } -} - static void undo(void); static void @@ -102,7 +87,6 @@ error(char *msg) if (!newcmd) undo(); - discard(); curln = ocurln; longjmp(savesp, 1); } @@ -172,30 +156,22 @@ static void chksignals(void); static int input(void) { - int c; - - if (repidx >= 0) - return ocmdline[repidx++]; - - if ((c = getchar()) != EOF) - addchar(c, &cmdline); + int ch; chksignals(); - return c; + ch = cmdline.str[inputidx]; + if (ch != '\0') + inputidx++; + return ch; } static int back(int c) { - if (repidx > 0) { - --repidx; - } else { - ungetc(c, stdin); - if (c != EOF) - --cmdline.siz; - } - return c; + if (c == '\0') + return c; + return cmdline.str[--inputidx] = c; } static int @@ -203,7 +179,8 @@ makeline(char *s, int *off) { struct hline *lp; size_t len; - char c, *begin = s; + char *begin = s; + int c; if (lastidx >= idxsize) { lp = NULL; @@ -426,18 +403,14 @@ compile(int delim) eol = bol = bracket = lastre.siz = 0; for (n = 0;; ++n) { - if ((c = input()) == delim && !bracket) + c = input(); + if (c == delim && !bracket || c == '\0') { break; - if (c == '^') { + } else if (c == '^') { bol = 1; } else if (c == '$') { eol = 1; - } else if (c == '\n' || c == EOF) { - back(c); - break; - } - - if (c == '\\') { + } else if (c == '\\') { addchar(c, &lastre); c = input(); } else if (c == '[') { @@ -521,9 +494,8 @@ ensureblank(void) case ' ': case '\t': skipblank(); - case '\n': + case '\0': back(c); - case EOF: break; default: error("unknown command"); @@ -681,6 +653,46 @@ quit(void) exit(exstatus); } +static void +setinput(char *s) +{ + copystring(&cmdline, s); + inputidx = 0; +} + +static void +getinput(void) +{ + int ch; + + string(&cmdline); + + while ((ch = getchar()) != '\n' && ch != EOF) { + if (ch == '\\') { + if ((ch = getchar()) == EOF) + break; + if (ch != '\n') { + ungetc(ch, stdin); + ch = '\\'; + } + } + addchar(ch, &cmdline); + } + + addchar('\0', &cmdline); + inputidx = 0; + + if (ch == EOF) { + chksignals(); + if (ferror(stdin)) { + exstatus = 1; + fputs("ed: error reading input\n", stderr); + } + quit(); + } +} + + static void dowrite(const char *, int); static void @@ -872,12 +884,12 @@ chkprint(int flag) else back(c); } - if (input() != '\n') + if (input() != '\0') error("invalid command suffix"); } static char * -getfname(char comm) +getfname(int comm) { int c; char *bp; @@ -885,7 +897,7 @@ getfname(char comm) skipblank(); for (bp = fname; bp < &fname[FILENAME_MAX]; *bp++ = c) { - if ((c = input()) == EOF || c == '\n') + if ((c = input()) == '\0') break; } if (bp == fname) { @@ -1040,7 +1052,7 @@ execsh(void) error("no previous command"); } - while ((c = input()) != EOF && c != '\n') { + while ((c = input()) != '\0') { if (c == '%' && (cmd.siz == 0 || cmd.str[cmd.siz - 1] != '\\')) { if (savfname[0] == '\0') error("no current filename"); @@ -1067,12 +1079,10 @@ getrhs(int delim) static String s; string(&s); - while ((c = input()) != '\n' && c != EOF && c != delim) + while ((c = input()) != '\0' && c != delim) addchar(c, &s); addchar('\0', &s); - if (c == EOF) - error("invalid pattern delimiter"); - if (c == '\n') { + if (c == '\0') { pflag = 'p'; back(c); } @@ -1201,8 +1211,7 @@ subst(int nth) static void docmd(void) { - char cmd; - int rep = 0, c, line3, num, trunc; + int cmd, c, line3, num, trunc; repeat: skipblank(); @@ -1210,21 +1219,18 @@ repeat: trunc = pflag = 0; switch (cmd) { case '&': + /* This is not working now */ skipblank(); chkprint(0); if (!ocmdline) error("no previous command"); - rep = 1; - repidx = 0; + setinput(ocmdline); getlst(); goto repeat; case '!': execsh(); break; - case EOF: - if (cmdline.siz == 0) - quit(); - case '\n': + case '\0': if (gflag && uflag) return; num = gflag ? curln : curln+1; @@ -1378,7 +1384,7 @@ repeat: ensureblank(); if (nlines > 0) goto unexpected; - if (back(input()) != '\n') + if (back(input()) != '\0') getfname(cmd); else puts(savfname); @@ -1410,21 +1416,11 @@ repeat: } if (!pflag) - goto save_last_cmd; - + return; line1 = line2 = curln; + print: doprint(); - -save_last_cmd: - if (!uflag) - repidx = 0; - if (rep) - return; - free(ocmdline); - addchar('\0', &cmdline); - if ((ocmdline = strdup(cmdline.str)) == NULL) - error("out of memory"); } static int @@ -1469,12 +1465,26 @@ chkglobal(void) } static void +savecmd(void) +{ + int ch; + + skipblank(); + ch = input(); + if (ch != '&') { + ocmdline = strdup(cmdline.str); + if (ocmdline == NULL) + error("out of memory"); + } + back(ch); +} + +static void doglobal(void) { - int cnt, ln, k; + int cnt, ln, k, idx; skipblank(); - string(&cmdline); gflag = 1; if (uflag) chkprint(0); @@ -1491,15 +1501,18 @@ doglobal(void) line1 = line2 = ln; pflag = 0; doprint(); + getinput(); + savecmd(); } + idx = inputidx; getlst(); docmd(); + inputidx = idx; } else { cnt++; ln = nextln(ln); } } - discard(); /* cover the case of not matching anything */ } static void @@ -1527,12 +1540,12 @@ edit(void) newcmd = 1; ocurln = curln; olastln = lastln; - cmdline.siz = 0; - repidx = -1; if (optprompt) { fputs(prompt, stdout); fflush(stdout); } + + getinput(); getlst(); chkglobal() ? doglobal() : docmd(); }