shithub: riscv

Download patch

ref: d75d842cf576cb4785f89c5f5b73a4f73170001b
parent: dbd54342fd66fd372f5c2edd1597019814f41c9c
author: Ori Bernstein <[email protected]>
date: Sun Nov 1 06:56:26 EST 2020

rc: show line numbers on error

This change provides a location for errors
like 'null list in concatenation'.

--- 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 @@
 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 @@
 {
 	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 @@
 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 @@
 			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);
--- a/sys/src/cmd/rc/exec.c
+++ b/sys/src/cmd/rc/exec.c
@@ -14,11 +14,12 @@
 	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 @@
 	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 @@
  * 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 @@
 			if(p->cmdfile)
 				free(p->cmdfile);
 			closeio(p->cmdfd);
-			Xreturn();	/* should this be omitted? */
+			Xreturn();
 		}
 		else{
 			if(Eintr()){
@@ -950,13 +957,22 @@
 	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 @@
 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();
@@ -1024,4 +1040,17 @@
 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);
 }
--- a/sys/src/cmd/rc/exec.h
+++ b/sys/src/cmd/rc/exec.h
@@ -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), 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 @@
 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 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 @@
 	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 @@
 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
--- a/sys/src/cmd/rc/lex.c
+++ b/sys/src/cmd/rc/lex.c
@@ -25,6 +25,13 @@
 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,7 +46,6 @@
 /*
  * Consume the lookahead character.
  */
-
 int
 advance(void)
 {
@@ -46,6 +52,8 @@
 	int c = nextc();
 	lastc = future;
 	future = EOF;
+	if(c == '\n')
+		lexline++;
 	return c;
 }
 /*
--- 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 @@
 	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);
--- a/sys/src/cmd/rc/pfnc.c
+++ b/sys/src/cmd/rc/pfnc.c
@@ -51,6 +51,7 @@
 	Xrdfn, "Xrdfn",
 	Xsimple, "Xsimple",
 	Xqw, "Xqw",
+	Xsrcline, "Xsrcline",
 0};
 
 void
@@ -59,7 +60,8 @@
 	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;
--- a/sys/src/cmd/rc/plan9.c
+++ b/sys/src/cmd/rc/plan9.c
@@ -164,9 +164,12 @@
 	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));
 	}
 }
--- a/sys/src/cmd/rc/rc.h
+++ b/sys/src/cmd/rc/rc.h
@@ -43,6 +43,7 @@
 	char	*str;
 	int	quoted;
 	int	iskw;
+	int	line;
 	tree	*child[3];
 	tree	*next;
 };
@@ -54,6 +55,7 @@
 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 @@
  */
 #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 @@
  * 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;
--- 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 @@
 execcmds(io *f)
 {
 	static int first = 1;
+
 	if(first){
 		rdcmds[0].i = 1;
 		rdcmds[1].f = Xrdcmds;
@@ -319,6 +327,7 @@
 	}
 	else
 		eflagok = 1;
+
 	popword();
 	if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){
 		iflag = 1;
@@ -354,6 +363,9 @@
 		Xerror(".: can't open");
 		return;
 	}
+
+	lexline = 1;
+
 	/* set up for a new command loop */
 	start(dotcmds, 1, (struct var *)0);
 	pushredir(RCLOSE, fd, 0);
--- a/sys/src/cmd/rc/tree.c
+++ b/sys/src/cmd/rc/tree.c
@@ -16,6 +16,7 @@
 	t->str = 0;
 	t->child[0] = t->child[1] = t->child[2] = 0;
 	t->next = treenodes;
+	t->line = lexline;
 	treenodes = t;
 	return t;
 }