diff options
author | Ori Bernstein <ori@eigenstate.org> | 2020-11-01 11:56:26 -0800 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2020-11-01 11:56:26 -0800 |
commit | d75d842cf576cb4785f89c5f5b73a4f73170001b (patch) | |
tree | 008a1cd386c97ee735ab2e1129eeda890093bcef /sys/src/cmd/rc | |
parent | dbd54342fd66fd372f5c2edd1597019814f41c9c (diff) |
rc: show line numbers on error
This change provides a location for errors
like 'null list in concatenation'.
Diffstat (limited to 'sys/src/cmd/rc')
-rw-r--r-- | sys/src/cmd/rc/code.c | 21 | ||||
-rw-r--r-- | sys/src/cmd/rc/exec.c | 43 | ||||
-rw-r--r-- | sys/src/cmd/rc/exec.h | 20 | ||||
-rw-r--r-- | sys/src/cmd/rc/lex.c | 10 | ||||
-rw-r--r-- | sys/src/cmd/rc/pcmd.c | 4 | ||||
-rw-r--r-- | sys/src/cmd/rc/pfnc.c | 4 | ||||
-rw-r--r-- | sys/src/cmd/rc/plan9.c | 5 | ||||
-rw-r--r-- | sys/src/cmd/rc/rc.h | 18 | ||||
-rw-r--r-- | sys/src/cmd/rc/simple.c | 16 | ||||
-rw-r--r-- | sys/src/cmd/rc/tree.c | 1 |
10 files changed, 107 insertions, 35 deletions
diff --git a/sys/src/cmd/rc/code.c b/sys/src/cmd/rc/code.c index 4a415bd54..d85a12260 100644 --- a/sys/src/cmd/rc/code.c +++ b/sys/src/cmd/rc/code.c @@ -6,10 +6,12 @@ #define c0 t->child[0] #define c1 t->child[1] #define c2 t->child[2] +code *codebuf; int codep, ncode; #define emitf(x) ((codep!=ncode || morecode()), codebuf[codep].f = (x), codep++) #define emiti(x) ((codep!=ncode || morecode()), codebuf[codep].i = (x), codep++) #define emits(x) ((codep!=ncode || morecode()), codebuf[codep].s = (x), codep++) + void stuffdot(int); char *fnstr(tree*); void outcode(tree*, int); @@ -38,7 +40,7 @@ int compile(tree *t) { ncode = 100; - codebuf = (code *)emalloc(ncode*sizeof codebuf[0]); + codebuf = emalloc(ncode*sizeof codebuf[0]); codep = 0; emiti(0); /* reference count */ outcode(t, flag['e']?1:0); @@ -64,12 +66,8 @@ fnstr(tree *t) { io *f = openstr(); void *v; - extern char nl; - char svnl = nl; - nl = ';'; pfmt(f, "%t", t); - nl = svnl; v = f->strp; f->strp = 0; closeio(f); @@ -79,12 +77,19 @@ fnstr(tree *t) void outcode(tree *t, int eflag) { + static int line; int p, q; tree *tt; + char *f; if(t==0) return; if(t->type!=NOT && t->type!=';') runq->iflast = 0; + if(t->line != line){ + line = t->line; + emitf(Xsrcline); + emiti(line); + } switch(t->type){ default: pfmt(err, "bad type %d in outcode\n", t->type); @@ -174,6 +179,12 @@ outcode(tree *t, int eflag) emitf(Xfn); p = emiti(0); emits(fnstr(c1)); + if((f = curfile(runq)) != nil){ + emitf(Xsrcfile); + emits(strdup(f)); + } + emitf(Xsrcline); + emiti(lexline); outcode(c1, eflag); emitf(Xunlocal); /* get rid of $* */ emitf(Xreturn); diff --git a/sys/src/cmd/rc/exec.c b/sys/src/cmd/rc/exec.c index 3d1b0ac5a..04b3a4120 100644 --- a/sys/src/cmd/rc/exec.c +++ b/sys/src/cmd/rc/exec.c @@ -14,11 +14,12 @@ start(code *c, int pc, var *local) struct thread *p = new(struct thread); p->code = codecopy(c); + p->line = runq?runq->line:0; p->pc = pc; p->argv = 0; - p->redir = p->startredir = runq?runq->redir:0; + p->redir = p->startredir = runq?runq->redir:nil; p->local = local; - p->cmdfile = 0; + p->cmdfile = nil; p->cmdfd = 0; p->eof = 0; p->iflag = 0; @@ -201,10 +202,14 @@ main(int argc, char *argv[]) bootstrap[i++].f = Xexit; bootstrap[i].i = 0; start(bootstrap, 1, (var *)0); + runq->cmdfile = strdup("rc"); /* prime bootstrap argv */ pushlist(); argv0 = estrdup(argv[0]); for(i = argc-1;i!=0;--i) pushword(argv[i]); + + lexline = 0; + for(;;){ if(flag['r']) pfnc(err, runq); @@ -260,6 +265,8 @@ main(int argc, char *argv[]) * Xunlocal delete local variable * Xword[string] push string * Xwrite(file)[fd] open file to write + * Xsrcline[line] set current line number + * Xsrcfile[file] set current file name */ void @@ -932,7 +939,7 @@ Xrdcmds(void) if(p->cmdfile) free(p->cmdfile); closeio(p->cmdfd); - Xreturn(); /* should this be omitted? */ + Xreturn(); } else{ if(Eintr()){ @@ -950,13 +957,22 @@ Xrdcmds(void) freenodes(); } +char* +curfile(thread *p) +{ + for(; p != nil; p = p->ret) + if(p->cmdfile != nil) + return p->cmdfile; + return "unknown"; +} + void Xerror(char *s) { 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 - pfmt(err, "rc (%s): %s: %r\n", argv0, s); + pfmt(err, "%s:%d: %s: %r\n", curfile(runq), runq->line, s); flush(err); setstatus("error"); while(!runq->iflag) Xreturn(); @@ -966,9 +982,9 @@ void Xerror1(char *s) { 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 - pfmt(err, "rc (%s): %s\n", argv0, s); + pfmt(err, "%s:%d: %s\n", curfile(runq), runq->line, s); flush(err); setstatus("error"); while(!runq->iflag) Xreturn(); @@ -1025,3 +1041,16 @@ Xglob(void) { 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); +} diff --git a/sys/src/cmd/rc/exec.h b/sys/src/cmd/rc/exec.h index 3f07404a4..7975596bd 100644 --- a/sys/src/cmd/rc/exec.h +++ b/sys/src/cmd/rc/exec.h @@ -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 Xexit(void), Xfalse(void), Xfn(void), Xfor(void), Xglob(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 Xtrue(void), Xword(void), Xglobs(void), Xwrite(void), Xpipefd(void), Xcase(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{ char type; /* what to do */ 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) */ /* @@ -40,14 +40,15 @@ struct redir{ #define RDUP 2 /* dup2(from, to); */ #define RCLOSE 3 /* close(from); */ struct thread{ - union code *code; /* code for this thread */ + code *code; /* code for this thread */ int pc; /* code[pc] is the next instruction */ - struct list *argv; /* argument stack */ - struct redir *redir; /* redirection stack */ - struct redir *startredir; /* redir inheritance point */ - struct var *local; /* list of local variables */ + int line; /* source code line */ + list *argv; /* argument stack */ + redir *redir; /* redirection stack */ + redir *startredir; /* redir inheritance point */ + var *local; /* list of local variables */ 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 eof; /* is cmdfd at eof? */ int iflag; /* interactive? */ @@ -55,7 +56,7 @@ struct thread{ int pid; /* process for Xpipewait to wait for */ char status[NSTATUS]; /* status for Xpipewait */ tree *treenodes; /* tree nodes created by this process */ - thread *ret; /* who continues when this finishes */ + thread *ret; /* who continues when this finishes */ }; thread *runq; code *codecopy(code*); @@ -74,3 +75,4 @@ int execforkexec(void); void execexit(void), execshift(void); void execwait(void), execumask(void), execdot(void), execflag(void); void execfunc(var*), execcmds(io *); +char *curfile(thread*);
\ No newline at end of file diff --git a/sys/src/cmd/rc/lex.c b/sys/src/cmd/rc/lex.c index 662c1970a..52ded7769 100644 --- a/sys/src/cmd/rc/lex.c +++ b/sys/src/cmd/rc/lex.c @@ -25,6 +25,13 @@ int future = EOF; int doprompt = 1; int inquote; int incomm; +int lastc; +int ndot; +int nerror; +int lexline; +int nlexpath; +int lexpathsz; + /* * Look ahead in the input stream */ @@ -39,13 +46,14 @@ nextc(void) /* * Consume the lookahead character. */ - int advance(void) { int c = nextc(); lastc = future; future = EOF; + if(c == '\n') + lexline++; return c; } /* diff --git a/sys/src/cmd/rc/pcmd.c b/sys/src/cmd/rc/pcmd.c index 51370ac23..8061669e2 100644 --- a/sys/src/cmd/rc/pcmd.c +++ b/sys/src/cmd/rc/pcmd.c @@ -1,7 +1,7 @@ #include "rc.h" #include "io.h" #include "fns.h" -char nl='\n'; /* change to semicolon for bourne-proofing */ + #define c0 t->child[0] #define c1 t->child[1] #define c2 t->child[2] @@ -76,7 +76,7 @@ pcmd(io *f, tree *t) case ';': if(c0){ 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", c1); diff --git a/sys/src/cmd/rc/pfnc.c b/sys/src/cmd/rc/pfnc.c index f8505cfc6..83f871ff8 100644 --- a/sys/src/cmd/rc/pfnc.c +++ b/sys/src/cmd/rc/pfnc.c @@ -51,6 +51,7 @@ struct{ Xrdfn, "Xrdfn", Xsimple, "Xsimple", Xqw, "Xqw", + Xsrcline, "Xsrcline", 0}; void @@ -59,7 +60,8 @@ pfnc(io *fd, thread *t) int i; void (*fn)(void) = t->code[t->pc].f; 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){ pstr(fd, fname[i].name); break; diff --git a/sys/src/cmd/rc/plan9.c b/sys/src/cmd/rc/plan9.c index 4ac9a0bf7..634570c26 100644 --- a/sys/src/cmd/rc/plan9.c +++ b/sys/src/cmd/rc/plan9.c @@ -164,9 +164,12 @@ Xrdfn(void) if(runq->argv->words == 0) poplist(); else { + free(runq->cmdfile); int f = open(runq->argv->words->word, 0); - popword(); + lexline = 0; + runq->cmdfile = strdup(runq->argv->words->word); runq->pc--; + popword(); if(f>=0) execcmds(openfd(f)); } } diff --git a/sys/src/cmd/rc/rc.h b/sys/src/cmd/rc/rc.h index eddad8ede..165f044e3 100644 --- a/sys/src/cmd/rc/rc.h +++ b/sys/src/cmd/rc/rc.h @@ -43,6 +43,7 @@ struct tree{ char *str; int quoted; int iskw; + int line; tree *child[3]; tree *next; }; @@ -54,6 +55,7 @@ tree *mung3(tree*, tree*, tree*, tree*), *epimung(tree*, tree*); tree *simplemung(tree*), *heredoc(tree*); void freetree(tree*); tree *cmdtree; + /* * The first word of any code vector is a reference count. * Always create a new reference to a code vector by calling codecopy(.). @@ -126,10 +128,12 @@ int mypid; */ #define onebyte(c) ((c&0x80)==0x00) -char **argp; -char **args; -int nerror; /* number of errors encountered during compilation */ -int doprompt; /* is it time for a prompt? */ +extern char **argp; +extern char **args; +extern int nerror; /* number of errors encountered during compilation */ +extern int doprompt; /* is it time for a prompt? */ +extern int lexline; + /* * Which fds are the reading/writing end of a pipe? * Unfortunately, this can vary from system to system. @@ -143,7 +147,7 @@ char Rcmain[], Fdprefix[]; * How many dot commands have we executed? * Used to ensure that -v flag doesn't print rcmain. */ -int ndot; +extern int ndot; +extern int lastc; +extern int lastword; char *getstatus(void); -int lastc; -int lastword; diff --git a/sys/src/cmd/rc/simple.c b/sys/src/cmd/rc/simple.c index 8971f201f..3987dbe5a 100644 --- a/sys/src/cmd/rc/simple.c +++ b/sys/src/cmd/rc/simple.c @@ -11,8 +11,15 @@ */ int exitnext(void){ - union code *c=&runq->code[runq->pc]; - while(c->f==Xpopredir || c->f==Xunlocal) c++; + code *c=&runq->code[runq->pc]; + 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; } @@ -260,6 +267,7 @@ void execcmds(io *f) { static int first = 1; + if(first){ rdcmds[0].i = 1; rdcmds[1].f = Xrdcmds; @@ -319,6 +327,7 @@ execdot(void) } else eflagok = 1; + popword(); if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){ iflag = 1; @@ -354,6 +363,9 @@ execdot(void) Xerror(".: can't open"); return; } + + lexline = 1; + /* set up for a new command loop */ start(dotcmds, 1, (struct var *)0); pushredir(RCLOSE, fd, 0); diff --git a/sys/src/cmd/rc/tree.c b/sys/src/cmd/rc/tree.c index 2d0750cf4..557d14d6c 100644 --- a/sys/src/cmd/rc/tree.c +++ b/sys/src/cmd/rc/tree.c @@ -16,6 +16,7 @@ newtree(void) t->str = 0; t->child[0] = t->child[1] = t->child[2] = 0; t->next = treenodes; + t->line = lexline; treenodes = t; return t; } |