diff -r bdd5a746e8c5 sys/src/cmd/rc/code.c --- a/sys/src/cmd/rc/code.c Sun Oct 18 19:30:14 2020 -0700 +++ b/sys/src/cmd/rc/code.c Wed Oct 21 17:27:22 2020 -0700 @@ -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); @@ -37,9 +39,9 @@ int compile(tree *t) { + codep = 0; ncode = 100; - codebuf = (code *)emalloc(ncode*sizeof codebuf[0]); - codep = 0; + codebuf = emalloc(ncode*sizeof codebuf[0]); emiti(0); /* reference count */ outcode(t, flag['e']?1:0); if(nerror){ @@ -79,12 +81,28 @@ void outcode(tree *t, int eflag) { - int p, q; + static int file, line; + int p, q, f, l; tree *tt; if(t==0) return; if(t->type!=NOT && t->type!=';') runq->iflast = 0; + if(t->file != file || t->line != line){ + file = t->file; + line = t->line; + + /* + * These are small enough that with a ton of sourcing, + * overflow is a realistic risk. If we run out of files, + * set to file 0, which is always '???' + */ + f = (t->file > LFMAX) ? 0 : t->file << LSHIFT; + l = (t->line > LMASK) ? -1 : t->line; + + emitf(Xloc); + emiti(f|l); + } switch(t->type){ default: pfmt(err, "bad type %d in outcode\n", t->type); diff -r bdd5a746e8c5 sys/src/cmd/rc/exec.c --- a/sys/src/cmd/rc/exec.c Sun Oct 18 19:30:14 2020 -0700 +++ b/sys/src/cmd/rc/exec.c Wed Oct 21 17:27:22 2020 -0700 @@ -14,6 +14,7 @@ struct thread *p = new(struct thread); p->code = codecopy(c); + p->loc = 0; p->pc = pc; p->argv = 0; p->redir = p->startredir = runq?runq->redir:0; @@ -205,6 +206,11 @@ pushlist(); argv0 = estrdup(argv[0]); for(i = argc-1;i!=0;--i) pushword(argv[i]); + + lexpath = erealloc(lexpath, sizeof(char*)); + nlexpath = 1; + lexpath[0] = strdup("???"); + for(;;){ if(flag['r']) pfnc(err, runq); @@ -953,10 +959,15 @@ void Xerror(char *s) { + int f, l; + + f = runq->loc >> LSHIFT; + l = runq->loc & LMASK; + assert(f >= 0 && f < nlexpath); if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0) - pfmt(err, "rc: %s: %r\n", s); + pfmt(err, "rc:%d: %s: %r\n", l, s); else - pfmt(err, "rc (%s): %s: %r\n", argv0, s); + pfmt(err, "%s:%d: %s: %r\n", lexpath[f], l, s); flush(err); setstatus("error"); while(!runq->iflag) Xreturn(); @@ -965,10 +976,15 @@ void Xerror1(char *s) { + int f, l; + + f = runq->loc >> LSHIFT; + l = runq->loc & LMASK; + assert(f >= 0 && f < nlexpath); if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0) - pfmt(err, "rc: %s\n", s); + pfmt(err, "rc:%d: %s\n", l, s); else - pfmt(err, "rc (%s): %s\n", argv0, s); + pfmt(err, "%s:%d: %s\n", lexpath[f], l, s); flush(err); setstatus("error"); while(!runq->iflag) Xreturn(); @@ -1025,3 +1041,10 @@ { globlist(runq->argv->words); } + +void +Xloc(void) +{ + runq->loc = runq->code[runq->pc].i; + runq->pc++; +} diff -r bdd5a746e8c5 sys/src/cmd/rc/exec.h --- a/sys/src/cmd/rc/exec.h Sun Oct 18 19:30:14 2020 -0700 +++ b/sys/src/cmd/rc/exec.h Wed Oct 21 17:27:22 2020 -0700 @@ -5,7 +5,7 @@ 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), Xloc(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 @@ 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 @@ #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 loc; /* source code location */ + 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 @@ 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*); diff -r bdd5a746e8c5 sys/src/cmd/rc/lex.c --- a/sys/src/cmd/rc/lex.c Sun Oct 18 19:30:14 2020 -0700 +++ b/sys/src/cmd/rc/lex.c Wed Oct 21 17:27:22 2020 -0700 @@ -25,6 +25,13 @@ int doprompt = 1; int inquote; int incomm; +int lastc; +int ndot; +int nerror; +int lexline; +int lexfile; +char **lexpath; +int nlexpath; /* * Look ahead in the input stream */ @@ -39,13 +46,14 @@ /* * Consume the lookahead character. */ - int advance(void) { int c = nextc(); lastc = future; future = EOF; + if(c == '\n') + lexline++; return c; } /* diff -r bdd5a746e8c5 sys/src/cmd/rc/pfnc.c --- a/sys/src/cmd/rc/pfnc.c Sun Oct 18 19:30:14 2020 -0700 +++ b/sys/src/cmd/rc/pfnc.c Wed Oct 21 17:27:22 2020 -0700 @@ -51,6 +51,7 @@ Xrdfn, "Xrdfn", Xsimple, "Xsimple", Xqw, "Xqw", + Xloc, "Xloc", 0}; void diff -r bdd5a746e8c5 sys/src/cmd/rc/rc.h --- a/sys/src/cmd/rc/rc.h Sun Oct 18 19:30:14 2020 -0700 +++ b/sys/src/cmd/rc/rc.h Wed Oct 21 17:27:22 2020 -0700 @@ -43,6 +43,8 @@ char *str; int quoted; int iskw; + int file; + int line; tree *child[3]; tree *next; }; @@ -54,6 +56,19 @@ tree *simplemung(tree*), *heredoc(tree*); void freetree(tree*); tree *cmdtree; + +/* + * Locations are stored as instructions in the rc bytecode. + * To avoid wasting too much space, both the file and line + * is packed into a single integer, as + * (file << LSHIFT) | line + * With 32 bit integers, this gives us 2048 filenames, with + * just over 1 million lines of code in each. + */ +#define LSHIFT 20 +#define LMASK ((1<code[runq->pc]; + code *c=&runq->code[runq->pc]; while(c->f==Xpopredir || c->f==Xunlocal) c++; return c->f==Xexit; } @@ -294,7 +294,7 @@ execdot(void) { int iflag = 0; - int fd; + int fd, i; list *av; thread *p = runq; char *zero, *file; @@ -354,6 +354,22 @@ Xerror(".: can't open"); return; } + + lexline = 1; + for(i = 0; i < nlexpath; i++){ + if(strcmp(lexpath[i], zero) == 0){ + lexfile = i; + break; + } + } + if(i == nlexpath){ + if(nlexpath < LFMAX){ + lexpath = erealloc(lexpath, (nlexpath + 1)*sizeof(char*)); + lexpath[nlexpath] = estrdup(zero); + lexfile = nlexpath++; + }else + lexfile = 0; + } /* set up for a new command loop */ start(dotcmds, 1, (struct var *)0); pushredir(RCLOSE, fd, 0); diff -r bdd5a746e8c5 sys/src/cmd/rc/tree.c --- a/sys/src/cmd/rc/tree.c Sun Oct 18 19:30:14 2020 -0700 +++ b/sys/src/cmd/rc/tree.c Wed Oct 21 17:27:22 2020 -0700 @@ -16,6 +16,8 @@ t->str = 0; t->child[0] = t->child[1] = t->child[2] = 0; t->next = treenodes; + t->file = lexfile; + t->line = lexline; treenodes = t; return t; }