ed

simple ed
git clone git://git.2f30.org/ed
Log | Files | Refs | LICENSE

commit 2f36543e57275fe1736838e421b9cd248e20b706
parent 2dd7cf8673ea46255b65b7eb1000280ba452530f
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed,  9 Dec 2015 15:28:12 +0100

Remove any reference to cmdp

This version is totally wrong and unstable, but we already
removed all the references to cmdp, and everything is based
in getchar().

Diffstat:
Med.c | 532+++++++++++++++++++++++++++++++++++--------------------------------------------
1 file changed, 238 insertions(+), 294 deletions(-)

diff --git a/ed.c b/ed.c @@ -24,11 +24,8 @@ struct hline { int next, prev; }; -char *cmdp; -char *cmd; char *prompt = "*"; regex_t *pattern; -size_t cmdsiz, cmdcap; int optverbose, optprompt, exstatus, optdiag = 1; int marks['z' - 'a']; @@ -39,7 +36,7 @@ char *lasterr; size_t idxsize, lastidx; struct hline *zero; char *text; -char *savfname; +char savfname[FILENAME_MAX]; char tmpname[FILENAME_MAX]; size_t sizetxt, memtxt; int scratch; @@ -293,31 +290,15 @@ match(int way) static void skipblank(void) { - while (*cmdp == ' ' || *cmdp == '\t') - ++cmdp; -} - -static int -getnum(void) -{ - int ln, n; - - for (ln = 0; isdigit(*cmdp); ln += n) { - if (ln > INT_MAX/10) - error("invalid address"); - ln *= 10; - n = *cmdp++ - '0'; - if (INT_MAX - ln < n) - error("invalid address"); - } - return ln; + char c; -invalid: - error("invalid address"); + while ((c = getchar()) == ' ' || c == '\t') + /* nothing */; + ungetc(c, stdin); } static int -xgetnum(void) +getnum(void) { int ln, n, c; @@ -341,17 +322,15 @@ linenum(int *line) { int ln, c, ret = 1; - while (isspace(c = getchar())) - /* nothing */; + skipblank(); - switch (c) { + switch (c = getchar()) { case '.': ln = curln; break; case '\'': - while (isspace(c = getchar())) - /* nothing */; - if (!isalpha(c)) + skipblank(); + if (!isalpha(c = getchar())) error("invalid mark character"); if (!(ln = marks[c])) error("invalid address"); @@ -373,7 +352,7 @@ linenum(int *line) default: ungetc(c, stdin); if (isdigit(c)) - ln = xgetnum(); + ln = getnum(); else ret = 0; break; @@ -391,12 +370,11 @@ address(int *line) return 0; for (;;) { - while (isspace(c = getchar())) - /* nothing */; - if (c != '+' && c != '-') + skipblank(); + if ((c = getchar()) != '+' && c != '-') break; sign = c == '+'; - num = isdigit(ungetc(getchar(), stdin)) ? xgetnum() : 1; + num = isdigit(ungetc(getchar(), stdin)) ? getnum() : 1; num *= sign; if (INT_MAX - ln < num) goto invalid; @@ -430,9 +408,9 @@ getlst() line1 = line2; line2 = ln; ++nlines; - while (isspace(c = getchar())) - /* nothing */; - if (c != ',' && c != ';') + skipblank(); + + if ((c = getchar()) != ',' && c != ';') break; if (c == ';') curln = line2; @@ -456,19 +434,6 @@ deflines(int def1, int def2) } static void -setfname(char *fname) -{ - char *s; - - if (fname == savfname) - return; - if (!(s = strdup(fname))) - error("out of memory"); - free(savfname); - savfname = s; -} - -static void dowrite(char *fname, int trunc) { FILE *fp; @@ -484,7 +449,7 @@ dowrite(char *fname, int trunc) curln = line2; if (fclose(fp)) error("input/output error"); - setfname(fname); + strcpy(savfname, fname); modflag = 0; } @@ -501,8 +466,8 @@ doread(char *fname) if (fp) fclose(fp); - if (!savfname) - setfname(fname); + if (savfname[0] == '\0') + strcpy(savfname, fname); if (!(fp = fopen(fname, "r"))) error("input/output error"); @@ -575,8 +540,6 @@ doprint(void) static void dohelp(void) { - if (nlines > 0) - error("invalid address"); if (lasterr) fprintf(stderr, "%s\n", lasterr); } @@ -587,33 +550,39 @@ chkprint(int flag) char c; if (flag) { - if ((c = *cmdp) == 'p' || c == 'l' || c == 'n') { + if ((c = getchar()) == 'p' || c == 'l' || c == 'n') pflag = c; - ++cmdp; - } + else + ungetc(c, stdin); } - if (*cmdp++ != '\n') + if (getchar() != '\n') error("invalid command suffix"); } static char * -getfname(char *s) +getfname(void) { - char c, *p; + int c; + char *bp; + static char fname[FILENAME_MAX]; - if ((c = *s) != '\n' && c != ' ' && c != '\0') + if ((c = getchar()) != '\n' && c != ' ' && c != '\0') error("invalid command suffix"); - while ((c = *s) == ' ' || c == '\t' || c == '\n') - ++s; - if (*s) { - for (p = s; *p && *p != '\n'; ++p) - ; - *p = '\0'; - return s; - } else if (savfname) { + + skipblank(); + for (bp = fname; bp < &fname[FILENAME_MAX]; *bp = c) { + if ((c = getchar()) != EOF || c == '\n') + break; + } + if (bp == fname) { + if (savfname[0] == '\0') + error("no current filename"); return savfname; + } else if (bp == &fname[FILENAME_MAX]) { + error("file name too long"); } else { - error("no current filename"); + *bp = '\0'; + return fname; } } @@ -732,199 +701,209 @@ static void execsh(void) { static char *cmd; + static size_t siz, cap; + char c; skipblank(); - if (*cmdp != '!') { - free(cmd); - if (!(cmd = strdup(cmdp))) - error("out of memory"); + if ((c = getchar()) != '!') { + siz = 0; + while ((c = getchar()) != EOF && c != '\n') + cmd = addchar(c, cmd, &cap, &siz); + cmd = addchar('\0', cmd, &cap, &siz); + } else if (!cmd) { + error("no previous command"); } system(cmd); - if (!cmd) - error("no previous command"); puts("!"); } static void -docmd() +docmd(char cmd) { char c, *s; int num, trunc, line3; + static int lline1, lline2, lline3; + static int ocmd, oline1, oline2, oline3; - while (*cmdp) { - trunc = pflag = 0; +repeat: + trunc = pflag = 0; + switch (cmd) { + case '&': skipblank(); + chkprint(0); + cmd = ocmd; + line1 = oline1; + line2 = oline2; + line3 = oline3; + goto repeat; + case '!': + execsh(); + break; + case '\n': + deflines(curln+1, curln+1); + pflag = 'p'; + goto print; + case 'l': + case 'n': + case 'p': + ungetc(cmd, stdin); + chkprint(1); + deflines(curln, curln); + goto print; + case 'g': + case 'G': + case 'v': + case 'V': + error("cannot nest global commands"); + case 'H': + optverbose ^= 1; + case 'h': + if (nlines > 0) + goto unexpected; + chkprint(0); + dohelp(); + break; + case 'w': + trunc = 1; + case 'W': + chkprint(0); + deflines(nextln(0), lastln); + dowrite(getfname(), trunc); + break; + case 'r': + if (nlines > 1) + goto bad_address; + deflines(lastln, lastln); + doread(getfname()); + break; + case 'd': + chkprint(1); + deflines(curln, curln); + delete(line1, line2); + break; + case '=': + if (nlines > 1) + goto bad_address; + chkprint(1); + deflines(lastln, lastln); + printf("%d\n", line1); + break; + case 'i': + if (nlines > 1) + goto bad_address; + chkprint(1); + deflines(curln, curln); + if (!line1) + goto bad_address; + append(prevln(line1)); + break; + case 'a': + if (nlines > 1) + goto bad_address; + chkprint(1); + deflines(curln, curln); + append(line1); + break; + case 'm': + deflines(curln, curln); + if (!address(&line3)) + line3 = curln; + chkprint(1); + move(line3); + break; + case 't': + deflines(curln, curln); + if (!address(&line3)) + line3 = curln; + chkprint(1); + copy(line3); + break; + case 'c': + chkprint(1); + deflines(curln, curln); + delete(line1, line2); + append(prevln(line1)); + break; + case 'j': + chkprint(1); + deflines(curln, curln+1); + if (!line1) + goto bad_address; + join(); + break; + case 'z': + if (nlines > 1) + goto bad_address; + if (isdigit(ungetc(getchar(), stdin))) + num = getnum(); + else + num = 24; + chkprint(1); + scroll(num); + break; + case 'k': + if (nlines > 1) + goto bad_address; + if (!islower(c = getchar())) + error("invalid mark character"); + chkprint(1); + deflines(curln, curln); + marks[c] = line1; + break; + case 'P': + if (nlines > 0) + goto unexpected; + chkprint(1); + optprompt ^= 1; + break; + case 'Q': + modflag = 0; + case 'q': + if (nlines > 0) + goto unexpected; + if (modflag) + goto modified; + quit(); + break; + case 'f': + if (nlines > 0) + goto unexpected; + if (!strcmp(s = getfname(), savfname)) + puts(savfname); + else + strcpy(savfname, s); + break; + case 'E': + modflag = 0; + case 'e': + chkprint(0); + if (nlines > 0) + goto unexpected; + if (modflag) + goto modified; + setscratch(); + strcpy(savfname, getfname()); + deflines(curln, curln); + doread(savfname); + modflag = 0; + break; + default: + error("unknown command"); + bad_address: + error("invalid address"); + modified: + modflag = 0; + error("warning: file modified"); + unexpected: + error("unexpected address"); + } - switch (*cmdp++) { - case '!': - execsh(); - break; - case '\n': - deflines(curln+1, curln+1); - pflag = 'p'; - goto print; - case 'l': - case 'n': - case 'p': - --cmdp; - chkprint(1); - deflines(curln, curln); - goto print; - case 'g': - case 'G': - case 'v': - case 'V': - error("cannot nest global commands"); - case 'H': - optverbose ^= 1; - case 'h': - if (nlines > 0) - goto unexpected; - chkprint(0); - dohelp(); - break; - case 'w': - trunc = 1; - case 'W': - chkprint(0); - deflines(nextln(0), lastln); - dowrite(getfname(cmdp), trunc); - break; - case 'r': - if (nlines > 1) - goto bad_address; - deflines(lastln, lastln); - doread(getfname(cmdp)); - break; - case 'd': - chkprint(1); - deflines(curln, curln); - delete(line1, line2); - break; - case '=': - if (nlines > 1) - goto bad_address; - chkprint(1); - deflines(lastln, lastln); - printf("%d\n", line1); - break; - case 'i': - if (nlines > 1) - goto bad_address; - chkprint(1); - deflines(curln, curln); - if (!line1) - goto bad_address; - append(prevln(line1)); - break; - case 'a': - if (nlines > 1) - goto bad_address; - chkprint(1); - deflines(curln, curln); - append(line1); - break; - case 'm': - deflines(curln, curln); - if (!address(&line3)) - line3 = curln; - chkprint(1); - move(line3); - break; - case 't': - deflines(curln, curln); - if (!address(&line3)) - line3 = curln; - chkprint(1); - copy(line3); - break; - case 'c': - chkprint(1); - deflines(curln, curln); - delete(line1, line2); - append(prevln(line1)); - break; - case 'j': - chkprint(1); - deflines(curln, curln+1); - if (!line1) - goto bad_address; - join(); - break; - case 'z': - if (nlines > 1) - goto bad_address; - if (isdigit(*cmdp)) - num = getnum(); - else - num = 24; - chkprint(1); - scroll(num); - break; - case 'k': - if (nlines > 1) - goto bad_address; - if (!islower(c = *cmdp++)) - error("invalid mark character"); - chkprint(1); - deflines(curln, curln); - marks[c] = line1; - break; - case 'P': - if (nlines > 0) - goto unexpected; - chkprint(1); - optprompt ^= 1; - break; - case 'Q': - modflag = 0; - case 'q': - if (nlines > 0) - goto unexpected; - if (modflag) - goto modified; - quit(); - break; - case 'f': - if (nlines > 0) - goto unexpected; - if ((s = getfname(cmdp)) == savfname) - puts(savfname); - else - setfname(s); - break; - case 'E': - modflag = 0; - case 'e': - chkprint(0); - if (nlines > 0) - goto unexpected; - if (modflag) - goto modified; - setscratch(); - setfname(getfname(cmdp)); - deflines(curln, curln); - doread(savfname); - modflag = 0; - break; - default: - error("unknown command"); - bad_address: - error("invalid address"); - modified: - modflag = 0; - error("warning: file modified"); - unexpected: - error("unexpected address"); - } - - if (!pflag) - continue; + if (!pflag) + return; - line1 = line2 = curln; - print: - doprint(); - } + line1 = line2 = curln; +print: + doprint(); } static int @@ -933,10 +912,9 @@ chkglobal(void) int c, nmatch, i; uflag = 1; - while (isspace(c = getchar())) - /* nothing */; + skipblank(); - switch (c) { + switch (c = getchar()) { case 'g': uflag = 0; case 'G': @@ -962,24 +940,6 @@ chkglobal(void) } static void -readcmd(void) -{ - int c; - - cmdsiz = 0; - for (;;) { - if ((c = getchar()) == EOF || c == '\n') - break; - if (c == '\\' && (c = getchar()) == EOF) - break; - cmd = addchar(c, cmd, &cmdcap, &cmdsiz); - } - cmd = addchar('\n', cmd, &cmdcap, &cmdsiz); - cmd = addchar('\0', cmd, &cmdcap, &cmdsiz); - cmdp = cmd; -} - -static void doglobal(void) { int i, k; @@ -988,31 +948,18 @@ doglobal(void) if (uflag) chkprint(0); - s = cmdp; for (i = 1; i <= lastln; i++) { k = getindex(i); if (!zero[k].global) continue; - cmdp = s; curln = i; nlines = 0; if (uflag) { line1 = line2 = i; pflag = 0; doprint(); - /* - * FIXME: this code can let garbage in - * the input stream - */ - if ((c = getchar()) == '&') { - if (getchar() != '\n') - error("Unknown command"); - cmdp = cmd; - } else { - readcmd(); - } } - docmd(); + docmd('&'); } } @@ -1082,7 +1029,9 @@ main(int argc, char *argv[]) if (!setjmp(savesp)) { setscratch(); if (*argv) { - setfname(*argv); + if (strlen(*argv) >= FILENAME_MAX) + error("file name too long"); + strcpy(savfname, *argv); doread(savfname); modflag = 0; } @@ -1092,13 +1041,8 @@ main(int argc, char *argv[]) if (optprompt) fputs(prompt, stdout); getlst(); - if (chkglobal()) { - readcmd(); - doglobal(); - } else { - readcmd(); - docmd(); - } + skipblank(); + chkglobal() ? doglobal() : docmd(getchar()); } /* not reached */