rc: show line numbers on error

This change provides a location for errors
like 'null list in concatenation'.
This commit is contained in:
Ori Bernstein 2020-11-01 11:56:26 -08:00
parent dbd54342fd
commit d75d842cf5
10 changed files with 107 additions and 35 deletions

View file

@ -6,10 +6,12 @@
#define c0 t->child[0] #define c0 t->child[0]
#define c1 t->child[1] #define c1 t->child[1]
#define c2 t->child[2] #define c2 t->child[2]
code *codebuf;
int codep, ncode; int codep, ncode;
#define emitf(x) ((codep!=ncode || morecode()), codebuf[codep].f = (x), codep++) #define emitf(x) ((codep!=ncode || morecode()), codebuf[codep].f = (x), codep++)
#define emiti(x) ((codep!=ncode || morecode()), codebuf[codep].i = (x), codep++) #define emiti(x) ((codep!=ncode || morecode()), codebuf[codep].i = (x), codep++)
#define emits(x) ((codep!=ncode || morecode()), codebuf[codep].s = (x), codep++) #define emits(x) ((codep!=ncode || morecode()), codebuf[codep].s = (x), codep++)
void stuffdot(int); void stuffdot(int);
char *fnstr(tree*); char *fnstr(tree*);
void outcode(tree*, int); void outcode(tree*, int);
@ -38,7 +40,7 @@ int
compile(tree *t) compile(tree *t)
{ {
ncode = 100; ncode = 100;
codebuf = (code *)emalloc(ncode*sizeof codebuf[0]); codebuf = emalloc(ncode*sizeof codebuf[0]);
codep = 0; codep = 0;
emiti(0); /* reference count */ emiti(0); /* reference count */
outcode(t, flag['e']?1:0); outcode(t, flag['e']?1:0);
@ -64,12 +66,8 @@ fnstr(tree *t)
{ {
io *f = openstr(); io *f = openstr();
void *v; void *v;
extern char nl;
char svnl = nl;
nl = ';';
pfmt(f, "%t", t); pfmt(f, "%t", t);
nl = svnl;
v = f->strp; v = f->strp;
f->strp = 0; f->strp = 0;
closeio(f); closeio(f);
@ -79,12 +77,19 @@ fnstr(tree *t)
void void
outcode(tree *t, int eflag) outcode(tree *t, int eflag)
{ {
static int line;
int p, q; int p, q;
tree *tt; tree *tt;
char *f;
if(t==0) if(t==0)
return; return;
if(t->type!=NOT && t->type!=';') if(t->type!=NOT && t->type!=';')
runq->iflast = 0; runq->iflast = 0;
if(t->line != line){
line = t->line;
emitf(Xsrcline);
emiti(line);
}
switch(t->type){ switch(t->type){
default: default:
pfmt(err, "bad type %d in outcode\n", t->type); pfmt(err, "bad type %d in outcode\n", t->type);
@ -174,6 +179,12 @@ outcode(tree *t, int eflag)
emitf(Xfn); emitf(Xfn);
p = emiti(0); p = emiti(0);
emits(fnstr(c1)); emits(fnstr(c1));
if((f = curfile(runq)) != nil){
emitf(Xsrcfile);
emits(strdup(f));
}
emitf(Xsrcline);
emiti(lexline);
outcode(c1, eflag); outcode(c1, eflag);
emitf(Xunlocal); /* get rid of $* */ emitf(Xunlocal); /* get rid of $* */
emitf(Xreturn); emitf(Xreturn);

View file

@ -14,11 +14,12 @@ start(code *c, int pc, var *local)
struct thread *p = new(struct thread); struct thread *p = new(struct thread);
p->code = codecopy(c); p->code = codecopy(c);
p->line = runq?runq->line:0;
p->pc = pc; p->pc = pc;
p->argv = 0; p->argv = 0;
p->redir = p->startredir = runq?runq->redir:0; p->redir = p->startredir = runq?runq->redir:nil;
p->local = local; p->local = local;
p->cmdfile = 0; p->cmdfile = nil;
p->cmdfd = 0; p->cmdfd = 0;
p->eof = 0; p->eof = 0;
p->iflag = 0; p->iflag = 0;
@ -201,10 +202,14 @@ main(int argc, char *argv[])
bootstrap[i++].f = Xexit; bootstrap[i++].f = Xexit;
bootstrap[i].i = 0; bootstrap[i].i = 0;
start(bootstrap, 1, (var *)0); start(bootstrap, 1, (var *)0);
runq->cmdfile = strdup("rc");
/* prime bootstrap argv */ /* prime bootstrap argv */
pushlist(); pushlist();
argv0 = estrdup(argv[0]); argv0 = estrdup(argv[0]);
for(i = argc-1;i!=0;--i) pushword(argv[i]); for(i = argc-1;i!=0;--i) pushword(argv[i]);
lexline = 0;
for(;;){ for(;;){
if(flag['r']) if(flag['r'])
pfnc(err, runq); pfnc(err, runq);
@ -260,6 +265,8 @@ main(int argc, char *argv[])
* Xunlocal delete local variable * Xunlocal delete local variable
* Xword[string] push string * Xword[string] push string
* Xwrite(file)[fd] open file to write * Xwrite(file)[fd] open file to write
* Xsrcline[line] set current line number
* Xsrcfile[file] set current file name
*/ */
void void
@ -932,7 +939,7 @@ Xrdcmds(void)
if(p->cmdfile) if(p->cmdfile)
free(p->cmdfile); free(p->cmdfile);
closeio(p->cmdfd); closeio(p->cmdfd);
Xreturn(); /* should this be omitted? */ Xreturn();
} }
else{ else{
if(Eintr()){ if(Eintr()){
@ -950,13 +957,22 @@ Xrdcmds(void)
freenodes(); freenodes();
} }
char*
curfile(thread *p)
{
for(; p != nil; p = p->ret)
if(p->cmdfile != nil)
return p->cmdfile;
return "unknown";
}
void void
Xerror(char *s) Xerror(char *s)
{ {
if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0) if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
pfmt(err, "rc: %s: %r\n", s); pfmt(err, "rc:%d: %s: %r\n", runq->line, s);
else else
pfmt(err, "rc (%s): %s: %r\n", argv0, s); pfmt(err, "%s:%d: %s: %r\n", curfile(runq), runq->line, s);
flush(err); flush(err);
setstatus("error"); setstatus("error");
while(!runq->iflag) Xreturn(); while(!runq->iflag) Xreturn();
@ -966,9 +982,9 @@ void
Xerror1(char *s) Xerror1(char *s)
{ {
if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0) if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
pfmt(err, "rc: %s\n", s); pfmt(err, "rc:%d: %s\n", runq->line, s);
else else
pfmt(err, "rc (%s): %s\n", argv0, s); pfmt(err, "%s:%d: %s\n", curfile(runq), runq->line, s);
flush(err); flush(err);
setstatus("error"); setstatus("error");
while(!runq->iflag) Xreturn(); while(!runq->iflag) Xreturn();
@ -1025,3 +1041,16 @@ Xglob(void)
{ {
globlist(runq->argv->words); globlist(runq->argv->words);
} }
void
Xsrcline(void)
{
runq->line = runq->code[runq->pc++].i;
}
void
Xsrcfile(void)
{
free(runq->cmdfile);
runq->cmdfile = strdup(runq->code[runq->pc++].s);
}

View file

@ -5,7 +5,7 @@ extern void Xappend(void), Xasync(void), Xbackq(void), Xbang(void), Xclose(void)
extern void Xconc(void), Xcount(void), Xdelfn(void), Xdol(void), Xqw(void), Xdup(void); extern void Xconc(void), Xcount(void), Xdelfn(void), Xdol(void), Xqw(void), Xdup(void);
extern void Xexit(void), Xfalse(void), Xfn(void), Xfor(void), Xglob(void); extern void Xexit(void), Xfalse(void), Xfn(void), Xfor(void), Xglob(void);
extern void Xjump(void), Xmark(void), Xmatch(void), Xpipe(void), Xread(void); extern void Xjump(void), Xmark(void), Xmatch(void), Xpipe(void), Xread(void);
extern void Xrdwr(void); extern void Xrdwr(void), Xsrcline(void), Xsrcfile(void);
extern void Xrdfn(void), Xunredir(void), Xstar(void), Xreturn(void), Xsubshell(void); extern void Xrdfn(void), Xunredir(void), Xstar(void), Xreturn(void), Xsubshell(void);
extern void Xtrue(void), Xword(void), Xglobs(void), Xwrite(void), Xpipefd(void), Xcase(void); extern void Xtrue(void), Xword(void), Xglobs(void), Xwrite(void), Xpipefd(void), Xcase(void);
extern void Xlocal(void), Xunlocal(void), Xassign(void), Xsimple(void), Xpopm(void); extern void Xlocal(void), Xunlocal(void), Xassign(void), Xsimple(void), Xpopm(void);
@ -30,7 +30,7 @@ word *newword(char *, word *), *copywords(word *, word *);
struct redir{ struct redir{
char type; /* what to do */ char type; /* what to do */
short from, to; /* what to do it to */ short from, to; /* what to do it to */
struct redir *next; /* what else to do (reverse order) */ redir *next; /* what else to do (reverse order) */
}; };
#define NSTATUS ERRMAX /* length of status (from plan 9) */ #define NSTATUS ERRMAX /* length of status (from plan 9) */
/* /*
@ -40,14 +40,15 @@ struct redir{
#define RDUP 2 /* dup2(from, to); */ #define RDUP 2 /* dup2(from, to); */
#define RCLOSE 3 /* close(from); */ #define RCLOSE 3 /* close(from); */
struct thread{ struct thread{
union code *code; /* code for this thread */ code *code; /* code for this thread */
int pc; /* code[pc] is the next instruction */ int pc; /* code[pc] is the next instruction */
struct list *argv; /* argument stack */ int line; /* source code line */
struct redir *redir; /* redirection stack */ list *argv; /* argument stack */
struct redir *startredir; /* redir inheritance point */ redir *redir; /* redirection stack */
struct var *local; /* list of local variables */ redir *startredir; /* redir inheritance point */
var *local; /* list of local variables */
char *cmdfile; /* file name in Xrdcmd */ char *cmdfile; /* file name in Xrdcmd */
struct io *cmdfd; /* file descriptor for Xrdcmd */ io *cmdfd; /* file descriptor for Xrdcmd */
int iflast; /* static `if not' checking */ int iflast; /* static `if not' checking */
int eof; /* is cmdfd at eof? */ int eof; /* is cmdfd at eof? */
int iflag; /* interactive? */ int iflag; /* interactive? */
@ -55,7 +56,7 @@ struct thread{
int pid; /* process for Xpipewait to wait for */ int pid; /* process for Xpipewait to wait for */
char status[NSTATUS]; /* status for Xpipewait */ char status[NSTATUS]; /* status for Xpipewait */
tree *treenodes; /* tree nodes created by this process */ tree *treenodes; /* tree nodes created by this process */
thread *ret; /* who continues when this finishes */ thread *ret; /* who continues when this finishes */
}; };
thread *runq; thread *runq;
code *codecopy(code*); code *codecopy(code*);
@ -74,3 +75,4 @@ int execforkexec(void);
void execexit(void), execshift(void); void execexit(void), execshift(void);
void execwait(void), execumask(void), execdot(void), execflag(void); void execwait(void), execumask(void), execdot(void), execflag(void);
void execfunc(var*), execcmds(io *); void execfunc(var*), execcmds(io *);
char *curfile(thread*);

View file

@ -25,6 +25,13 @@ int future = EOF;
int doprompt = 1; int doprompt = 1;
int inquote; int inquote;
int incomm; int incomm;
int lastc;
int ndot;
int nerror;
int lexline;
int nlexpath;
int lexpathsz;
/* /*
* Look ahead in the input stream * Look ahead in the input stream
*/ */
@ -39,13 +46,14 @@ nextc(void)
/* /*
* Consume the lookahead character. * Consume the lookahead character.
*/ */
int int
advance(void) advance(void)
{ {
int c = nextc(); int c = nextc();
lastc = future; lastc = future;
future = EOF; future = EOF;
if(c == '\n')
lexline++;
return c; return c;
} }
/* /*

View file

@ -1,7 +1,7 @@
#include "rc.h" #include "rc.h"
#include "io.h" #include "io.h"
#include "fns.h" #include "fns.h"
char nl='\n'; /* change to semicolon for bourne-proofing */
#define c0 t->child[0] #define c0 t->child[0]
#define c1 t->child[1] #define c1 t->child[1]
#define c2 t->child[2] #define c2 t->child[2]
@ -76,7 +76,7 @@ pcmd(io *f, tree *t)
case ';': case ';':
if(c0){ if(c0){
if(c1) if(c1)
pfmt(f, "%t%c%t", c0, nl, c1); pfmt(f, "%t\n%t", c0, c1);
else pfmt(f, "%t", c0); else pfmt(f, "%t", c0);
} }
else pfmt(f, "%t", c1); else pfmt(f, "%t", c1);

View file

@ -51,6 +51,7 @@ struct{
Xrdfn, "Xrdfn", Xrdfn, "Xrdfn",
Xsimple, "Xsimple", Xsimple, "Xsimple",
Xqw, "Xqw", Xqw, "Xqw",
Xsrcline, "Xsrcline",
0}; 0};
void void
@ -59,7 +60,8 @@ pfnc(io *fd, thread *t)
int i; int i;
void (*fn)(void) = t->code[t->pc].f; void (*fn)(void) = t->code[t->pc].f;
list *a; list *a;
pfmt(fd, "pid %d cycle %p %d ", getpid(), t->code, t->pc);
pfmt(fd, "%s:%d: pid %d cycle %p %d ", t->cmdfile, t->line, getpid(), t->code, t->pc);
for(i = 0;fname[i].f;i++) if(fname[i].f==fn){ for(i = 0;fname[i].f;i++) if(fname[i].f==fn){
pstr(fd, fname[i].name); pstr(fd, fname[i].name);
break; break;

View file

@ -164,9 +164,12 @@ Xrdfn(void)
if(runq->argv->words == 0) if(runq->argv->words == 0)
poplist(); poplist();
else { else {
free(runq->cmdfile);
int f = open(runq->argv->words->word, 0); int f = open(runq->argv->words->word, 0);
popword(); lexline = 0;
runq->cmdfile = strdup(runq->argv->words->word);
runq->pc--; runq->pc--;
popword();
if(f>=0) execcmds(openfd(f)); if(f>=0) execcmds(openfd(f));
} }
} }

View file

@ -43,6 +43,7 @@ struct tree{
char *str; char *str;
int quoted; int quoted;
int iskw; int iskw;
int line;
tree *child[3]; tree *child[3];
tree *next; tree *next;
}; };
@ -54,6 +55,7 @@ tree *mung3(tree*, tree*, tree*, tree*), *epimung(tree*, tree*);
tree *simplemung(tree*), *heredoc(tree*); tree *simplemung(tree*), *heredoc(tree*);
void freetree(tree*); void freetree(tree*);
tree *cmdtree; tree *cmdtree;
/* /*
* The first word of any code vector is a reference count. * The first word of any code vector is a reference count.
* Always create a new reference to a code vector by calling codecopy(.). * Always create a new reference to a code vector by calling codecopy(.).
@ -126,10 +128,12 @@ int mypid;
*/ */
#define onebyte(c) ((c&0x80)==0x00) #define onebyte(c) ((c&0x80)==0x00)
char **argp; extern char **argp;
char **args; extern char **args;
int nerror; /* number of errors encountered during compilation */ extern int nerror; /* number of errors encountered during compilation */
int doprompt; /* is it time for a prompt? */ extern int doprompt; /* is it time for a prompt? */
extern int lexline;
/* /*
* Which fds are the reading/writing end of a pipe? * Which fds are the reading/writing end of a pipe?
* Unfortunately, this can vary from system to system. * Unfortunately, this can vary from system to system.
@ -143,7 +147,7 @@ char Rcmain[], Fdprefix[];
* How many dot commands have we executed? * How many dot commands have we executed?
* Used to ensure that -v flag doesn't print rcmain. * Used to ensure that -v flag doesn't print rcmain.
*/ */
int ndot; extern int ndot;
extern int lastc;
extern int lastword;
char *getstatus(void); char *getstatus(void);
int lastc;
int lastword;

View file

@ -11,8 +11,15 @@
*/ */
int int
exitnext(void){ exitnext(void){
union code *c=&runq->code[runq->pc]; code *c=&runq->code[runq->pc];
while(c->f==Xpopredir || c->f==Xunlocal) c++; while(1){
if(c->f==Xpopredir || c->f==Xunlocal)
c++;
else if(c->f==Xsrcline || c->f==Xsrcfile)
c += 2;
else
break;
}
return c->f==Xexit; return c->f==Xexit;
} }
@ -260,6 +267,7 @@ void
execcmds(io *f) execcmds(io *f)
{ {
static int first = 1; static int first = 1;
if(first){ if(first){
rdcmds[0].i = 1; rdcmds[0].i = 1;
rdcmds[1].f = Xrdcmds; rdcmds[1].f = Xrdcmds;
@ -319,6 +327,7 @@ execdot(void)
} }
else else
eflagok = 1; eflagok = 1;
popword(); popword();
if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){ if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){
iflag = 1; iflag = 1;
@ -354,6 +363,9 @@ execdot(void)
Xerror(".: can't open"); Xerror(".: can't open");
return; return;
} }
lexline = 1;
/* set up for a new command loop */ /* set up for a new command loop */
start(dotcmds, 1, (struct var *)0); start(dotcmds, 1, (struct var *)0);
pushredir(RCLOSE, fd, 0); pushredir(RCLOSE, fd, 0);

View file

@ -16,6 +16,7 @@ newtree(void)
t->str = 0; t->str = 0;
t->child[0] = t->child[1] = t->child[2] = 0; t->child[0] = t->child[1] = t->child[2] = 0;
t->next = treenodes; t->next = treenodes;
t->line = lexline;
treenodes = t; treenodes = t;
return t; return t;
} }