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