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:
M | ed.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 */