9front - general discussion about 9front
 help / color / mirror / Atom feed
* rc: null list in concatenation line numbers
@ 2020-10-16  1:40 ori
  2020-10-16  3:43 ` [9front] " Xiao-Yong Jin
                   ` (2 more replies)
  0 siblings, 3 replies; 16+ messages in thread
From: ori @ 2020-10-16  1:40 UTC (permalink / raw)
  To: 9front

This change causes rc to print the line number of an error
within Xerror(), meaning that the feared 'null list in
concatenation' will now tell you from where it came, like
so:

	stdin:10: null 
	test.rc:6: null list in concatenation

This change works by adding a bytecode instruction to
our code which updates a location. In the interests of
not bloating the bytecode too much, the new Xloc
instruction packs both the line number and file
into one integer, which limits us to 2048 filenames
and 1 million lines per file. Hitting these limits
won't break scripts, but they will turn the location
information into garbage. I think this is acceptable:
if you source thousands of files, you deserve it.

I also failed to resist temptation to clean up some
style annoyances -- lack of 'extern' on variables,
inconsistent repetition of typedef'ed tags, and
some useless casts from malloc, so this patch is a
bit noisier than it could be.

Testing and review welcome.

diff -r e05e4b6c6546 sys/src/cmd/rc/code.c
--- a/sys/src/cmd/rc/code.c	Mon Oct 12 02:03:52 2020 +0200
+++ b/sys/src/cmd/rc/code.c	Thu Oct 15 18:39:30 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 e05e4b6c6546 sys/src/cmd/rc/exec.c
--- a/sys/src/cmd/rc/exec.c	Mon Oct 12 02:03:52 2020 +0200
+++ b/sys/src/cmd/rc/exec.c	Thu Oct 15 18:39:30 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 e05e4b6c6546 sys/src/cmd/rc/exec.h
--- a/sys/src/cmd/rc/exec.h	Mon Oct 12 02:03:52 2020 +0200
+++ b/sys/src/cmd/rc/exec.h	Thu Oct 15 18:39:30 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 e05e4b6c6546 sys/src/cmd/rc/lex.c
--- a/sys/src/cmd/rc/lex.c	Mon Oct 12 02:03:52 2020 +0200
+++ b/sys/src/cmd/rc/lex.c	Thu Oct 15 18:39:30 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 e05e4b6c6546 sys/src/cmd/rc/pfnc.c
--- a/sys/src/cmd/rc/pfnc.c	Mon Oct 12 02:03:52 2020 +0200
+++ b/sys/src/cmd/rc/pfnc.c	Thu Oct 15 18:39:30 2020 -0700
@@ -51,6 +51,7 @@
 	Xrdfn, "Xrdfn",
 	Xsimple, "Xsimple",
 	Xqw, "Xqw",
+	Xloc, "Xloc",
 0};
 
 void
diff -r e05e4b6c6546 sys/src/cmd/rc/rc.h
--- a/sys/src/cmd/rc/rc.h	Mon Oct 12 02:03:52 2020 +0200
+++ b/sys/src/cmd/rc/rc.h	Thu Oct 15 18:39:30 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<<LSHIFT)-1)
+#define LFMAX	(1<<(8*sizeof(int)-LSHIFT-1))
+
 /*
  * 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 +141,15 @@
  */
 #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 lexfile;
+extern int lexline;
+extern char **lexpath;
+extern int nlexpath;
+
 /*
  * Which fds are the reading/writing end of a pipe?
  * Unfortunately, this can vary from system to system.
@@ -143,7 +163,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;
diff -r e05e4b6c6546 sys/src/cmd/rc/simple.c
--- a/sys/src/cmd/rc/simple.c	Mon Oct 12 02:03:52 2020 +0200
+++ b/sys/src/cmd/rc/simple.c	Thu Oct 15 18:39:30 2020 -0700
@@ -11,7 +11,7 @@
  */
 int
 exitnext(void){
-	union code *c=&runq->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,20 @@
 		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){
+		lexpath = erealloc(lexpath, (nlexpath + 1)*sizeof(char*));
+		lexpath[nlexpath] = estrdup(zero);
+		lexfile = nlexpath;
+		nlexpath++;
+	}
 	/* set up for a new command loop */
 	start(dotcmds, 1, (struct var *)0);
 	pushredir(RCLOSE, fd, 0);
diff -r e05e4b6c6546 sys/src/cmd/rc/tree.c
--- a/sys/src/cmd/rc/tree.c	Mon Oct 12 02:03:52 2020 +0200
+++ b/sys/src/cmd/rc/tree.c	Thu Oct 15 18:39:30 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;
 }



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [9front] rc: null list in concatenation line numbers
  2020-10-16  1:40 rc: null list in concatenation line numbers ori
@ 2020-10-16  3:43 ` Xiao-Yong Jin
  2020-10-17  1:47   ` ori
  2020-10-16  5:40 ` Iruatã Souza
  2020-10-22  1:18 ` ori
  2 siblings, 1 reply; 16+ messages in thread
From: Xiao-Yong Jin @ 2020-10-16  3:43 UTC (permalink / raw)
  To: 9front


> On Oct 15, 2020, at 8:40 PM, ori@eigenstate.org wrote:
> 
> -		pfmt(err, "rc (%s): %s: %r\n", argv0, s);
> +		pfmt(err, "%s:%d: %s: %r\n", lexpath[f], l, s);

It's better to keep argv0 in Xerror and Xerror1 perhaps with
	pfmt(err, "rc (%s): %s:%d: %s: %r\n", argv0, lexpath[f], l, s);



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [9front] rc: null list in concatenation line numbers
  2020-10-16  1:40 rc: null list in concatenation line numbers ori
  2020-10-16  3:43 ` [9front] " Xiao-Yong Jin
@ 2020-10-16  5:40 ` Iruatã Souza
  2020-10-22  1:18 ` ori
  2 siblings, 0 replies; 16+ messages in thread
From: Iruatã Souza @ 2020-10-16  5:40 UTC (permalink / raw)
  To: 9front

On Fri, Oct 16, 2020 at 3:41 AM <ori@eigenstate.org> wrote:
> into one integer, which limits us to 2048 filenames
> and 1 million lines per file. Hitting these limits
> won't break scripts, but they will turn the location
> information into garbage. I think this is acceptable:
> if you source thousands of files, you deserve it.

Maybe add a note about these limits to the man page?


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [9front] rc: null list in concatenation line numbers
  2020-10-16  3:43 ` [9front] " Xiao-Yong Jin
@ 2020-10-17  1:47   ` ori
  0 siblings, 0 replies; 16+ messages in thread
From: ori @ 2020-10-17  1:47 UTC (permalink / raw)
  To: meta.jxy, 9front

>> On Oct 15, 2020, at 8:40 PM, ori@eigenstate.org wrote:
>> 
>> -		pfmt(err, "rc (%s): %s: %r\n", argv0, s);
>> +		pfmt(err, "%s:%d: %s: %r\n", lexpath[f], l, s);
> 
> It's better to keep argv0 in Xerror and Xerror1 perhaps with
> 	pfmt(err, "rc (%s): %s:%d: %s: %r\n", argv0, lexpath[f], l, s);

I prefer the terser format, but I'm not attached to it.
If there are strong feelings about keeping argv0 in the
output, I can change it. Both options are plumbable.



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [9front] rc: null list in concatenation line numbers
  2020-10-16  1:40 rc: null list in concatenation line numbers ori
  2020-10-16  3:43 ` [9front] " Xiao-Yong Jin
  2020-10-16  5:40 ` Iruatã Souza
@ 2020-10-22  1:18 ` ori
  2020-10-22 12:11   ` tlaronde
  2020-10-25 20:29   ` ori
  2 siblings, 2 replies; 16+ messages in thread
From: ori @ 2020-10-22  1:18 UTC (permalink / raw)
  To: 9front

> Testing and review welcome.

Another iteration: This one caps the number of filenames
that we put into the name table. It's pointless to past
the name table past the maximum number of files that fit
into the location.

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 18:15:06 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 18:15:06 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 18:15:06 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 18:15:06 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 18:15:06 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 18:15:06 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<<LSHIFT)-1)
+#define LFMAX	(1<<(8*sizeof(int)-LSHIFT-1))
+
 /*
  * 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 +141,15 @@
  */
 #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 lexfile;
+extern int lexline;
+extern char **lexpath;
+extern int nlexpath;
+
 /*
  * Which fds are the reading/writing end of a pipe?
  * Unfortunately, this can vary from system to system.
@@ -143,7 +163,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;
diff -r bdd5a746e8c5 sys/src/cmd/rc/simple.c
--- a/sys/src/cmd/rc/simple.c	Sun Oct 18 19:30:14 2020 -0700
+++ b/sys/src/cmd/rc/simple.c	Wed Oct 21 18:15:06 2020 -0700
@@ -11,7 +11,7 @@
  */
 int
 exitnext(void){
-	union code *c=&runq->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 18:15:06 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;
 }



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [9front] rc: null list in concatenation line numbers
  2020-10-22  1:18 ` ori
@ 2020-10-22 12:11   ` tlaronde
  2020-10-25 20:29   ` ori
  1 sibling, 0 replies; 16+ messages in thread
From: tlaronde @ 2020-10-22 12:11 UTC (permalink / raw)
  To: 9front

Hello,

On Wed, Oct 21, 2020 at 06:18:28PM -0700, ori@eigenstate.org wrote:
> > Testing and review welcome.
> 
> Another iteration: This one caps the number of filenames
> that we put into the name table. It's pointless to past
> the name table past the maximum number of files that fit
> into the location.

FWIW, since the error I have when calling a rc script (hget(1)) from
a sh script under APE is "null list in concatenation", having something
to do with the definition of "path" been apparently empty (I have to set it
explicitely before calling hget), I tried the patches.

This queer problem under APE (in a very peculiar context because I have
been unable to find a small example reproducing the behavior) is still
there---I don't pretend the patches were to address this problem; I
simply tried them, because of the subject line "null list in concatenation",
to see if by side effect they would solve it.

Best,
-- 
        Thierry Laronde <tlaronde +AT+ polynum +dot+ com>
                     http://www.kergis.com/
                http://www.kergis.com/kertex.html
                       http://www.sbfa.fr/
Key fingerprint = 0FF7 E906 FBAF FE95 FD89  250D 52B1 AE95 6006 F40C


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [9front] rc: null list in concatenation line numbers
  2020-10-22  1:18 ` ori
  2020-10-22 12:11   ` tlaronde
@ 2020-10-25 20:29   ` ori
  2020-10-25 23:18     ` cinap_lenrek
  2020-10-25 23:41     ` cinap_lenrek
  1 sibling, 2 replies; 16+ messages in thread
From: ori @ 2020-10-25 20:29 UTC (permalink / raw)
  To: ori, 9front

>> Testing and review welcome.
> 
> Another iteration: This one caps the number of filenames
> that we put into the name table. It's pointless to past
> the name table past the maximum number of files that fit
> into the location.

And one more, which restores the location correctly after
sourcing a file; thanks to kvik for testing it out and
reporting back.

diff -r 0281cd6caa8c sys/src/cmd/rc/code.c
--- a/sys/src/cmd/rc/code.c	Sat Oct 24 17:24:59 2020 -0700
+++ b/sys/src/cmd/rc/code.c	Sun Oct 25 13:28:14 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,30 @@
 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;
+
+		if(f|l != 0){
+			emitf(Xloc);
+			emiti(f|l);
+		}
+	}
 	switch(t->type){
 	default:
 		pfmt(err, "bad type %d in outcode\n", t->type);
diff -r 0281cd6caa8c sys/src/cmd/rc/exec.c
--- a/sys/src/cmd/rc/exec.c	Sat Oct 24 17:24:59 2020 -0700
+++ b/sys/src/cmd/rc/exec.c	Sun Oct 25 13:28:14 2020 -0700
@@ -14,6 +14,7 @@
 	struct thread *p = new(struct thread);
 
 	p->code = codecopy(c);
+	p->loc = runq?runq->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);
@@ -932,7 +938,9 @@
 			if(p->cmdfile)
 				free(p->cmdfile);
 			closeio(p->cmdfd);
-			Xreturn();	/* should this be omitted? */
+			Xreturn();
+			lexfile = runq->loc >> LSHIFT;
+			lexline = runq->loc & LMASK;
 		}
 		else{
 			if(Eintr()){
@@ -953,10 +961,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 +978,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 +1043,10 @@
 {
 	globlist(runq->argv->words);
 }
+
+void
+Xloc(void)
+{
+	runq->loc = runq->code[runq->pc].i;
+	runq->pc++;
+}
diff -r 0281cd6caa8c sys/src/cmd/rc/exec.h
--- a/sys/src/cmd/rc/exec.h	Sat Oct 24 17:24:59 2020 -0700
+++ b/sys/src/cmd/rc/exec.h	Sun Oct 25 13:28:14 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 0281cd6caa8c sys/src/cmd/rc/lex.c
--- a/sys/src/cmd/rc/lex.c	Sat Oct 24 17:24:59 2020 -0700
+++ b/sys/src/cmd/rc/lex.c	Sun Oct 25 13:28:14 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 0281cd6caa8c sys/src/cmd/rc/pfnc.c
--- a/sys/src/cmd/rc/pfnc.c	Sat Oct 24 17:24:59 2020 -0700
+++ b/sys/src/cmd/rc/pfnc.c	Sun Oct 25 13:28:14 2020 -0700
@@ -51,6 +51,7 @@
 	Xrdfn, "Xrdfn",
 	Xsimple, "Xsimple",
 	Xqw, "Xqw",
+	Xloc, "Xloc",
 0};
 
 void
@@ -59,7 +60,7 @@
 	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, "pid %d cycle %p %d %s:%d ", getpid(), t->code, t->pc, lexpath[t->loc>>LSHIFT], t->loc&LMASK);
 	for(i = 0;fname[i].f;i++) if(fname[i].f==fn){
 		pstr(fd, fname[i].name);
 		break;
diff -r 0281cd6caa8c sys/src/cmd/rc/rc.h
--- a/sys/src/cmd/rc/rc.h	Sat Oct 24 17:24:59 2020 -0700
+++ b/sys/src/cmd/rc/rc.h	Sun Oct 25 13:28:14 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<<LSHIFT)-1)
+#define LFMAX	(1<<(8*sizeof(int)-LSHIFT-1))
+
 /*
  * 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 +141,15 @@
  */
 #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 lexfile;
+extern int lexline;
+extern char **lexpath;
+extern int nlexpath;
+
 /*
  * Which fds are the reading/writing end of a pipe?
  * Unfortunately, this can vary from system to system.
@@ -143,7 +163,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;
diff -r 0281cd6caa8c sys/src/cmd/rc/simple.c
--- a/sys/src/cmd/rc/simple.c	Sat Oct 24 17:24:59 2020 -0700
+++ b/sys/src/cmd/rc/simple.c	Sun Oct 25 13:28:14 2020 -0700
@@ -11,7 +11,7 @@
  */
 int
 exitnext(void){
-	union code *c=&runq->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, f, l;
 	list *av;
 	thread *p = runq;
 	char *zero, *file;
@@ -319,6 +319,12 @@
 	}
 	else
 		eflagok = 1;
+
+	/* set up Xreturn to restore the right address */
+	f = (lexfile > LFMAX) ? 0 : lexfile << LSHIFT;
+	l = (lexline > LMASK) ? -1 : lexline;
+	runq->loc = f|l;
+	
 	popword();
 	if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){
 		iflag = 1;
@@ -354,6 +360,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 0281cd6caa8c sys/src/cmd/rc/tree.c
--- a/sys/src/cmd/rc/tree.c	Sat Oct 24 17:24:59 2020 -0700
+++ b/sys/src/cmd/rc/tree.c	Sun Oct 25 13:28:14 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;
 }



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [9front] rc: null list in concatenation line numbers
  2020-10-25 20:29   ` ori
@ 2020-10-25 23:18     ` cinap_lenrek
  2020-10-26  1:00       ` ori
  2020-10-25 23:41     ` cinap_lenrek
  1 sibling, 1 reply; 16+ messages in thread
From: cinap_lenrek @ 2020-10-25 23:18 UTC (permalink / raw)
  To: 9front

+		if(f|l != 0){
+			emitf(Xloc);
+			emiti(f|l);
+		}

you need parentesis there around: f|l

+		/*
+		 * 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;

setting line to -1 also implicitely makes the file all ones...

+	if(i == nlexpath){
+		if(nlexpath < LFMAX){
+			lexpath = erealloc(lexpath, (nlexpath + 1)*sizeof(char*));
+			lexpath[nlexpath] = estrdup(zero);
+			lexfile = nlexpath++;
+		}else
+			lexfile = 0;
+	}

might want to use doubling the size for each realloc...

also wonder if the file can even change in the tree...
the file would only change when we source a file, no?

so i wonder if we need to keep track of the file in
the tree at all, and not just update it at runtime
in the thread.

--
cinap


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [9front] rc: null list in concatenation line numbers
  2020-10-25 20:29   ` ori
  2020-10-25 23:18     ` cinap_lenrek
@ 2020-10-25 23:41     ` cinap_lenrek
  2020-10-26  1:33       ` ori
  1 sibling, 1 reply; 16+ messages in thread
From: cinap_lenrek @ 2020-10-25 23:41 UTC (permalink / raw)
  To: 9front

hm... thinking about it. basically, change of file can
only happen when we do execdot() *AND* when calling a
function.

but this should be easy. we could have a Xsrcfile pseudo
operation that just updates the filename and has the
filename as a immediate string in the opstream.

in fact, you could even just have a Xdbgname() that sets
a generic stirng prefix, so you could also capture the
function name.

--
cinap


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [9front] rc: null list in concatenation line numbers
  2020-10-25 23:18     ` cinap_lenrek
@ 2020-10-26  1:00       ` ori
  0 siblings, 0 replies; 16+ messages in thread
From: ori @ 2020-10-26  1:00 UTC (permalink / raw)
  To: cinap_lenrek, 9front

> +		if(f|l != 0){
> +			emitf(Xloc);
> +			emiti(f|l);
> +		}
> 
> you need parentesis there around: f|l

Or I can get rid of the check entirely; if it ever happens,
it's harmless.

> +		/*
> +		 * 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;
> 
> setting line to -1 also implicitely makes the file all ones...

Oops -- fixed. Good catch.
 
> +	if(i == nlexpath){
> +		if(nlexpath < LFMAX){
> +			lexpath = erealloc(lexpath, (nlexpath + 1)*sizeof(char*));
> +			lexpath[nlexpath] = estrdup(zero);
> +			lexfile = nlexpath++;
> +		}else
> +			lexfile = 0;
> +	}
> 
> might want to use doubling the size for each realloc...

Easy enough to do, but by the time we're sourcing a file,
we're already doing so much other work that doing an extra
realloc probably won't matter. We're currently limiting to
2048 calls over the lifetime of a shell anyways.

Even if that restriction is limited, I'd like to put a
relatively small cap on this, so we're not doing a ton
of O(n) searches -- the only way I can imagine someone
running into the limit is if they generate scripts to
source in a long running script, and an unlimited table
here would be a memory leak.

Still, it's a couple of lines, I'll make the change.

> also wonder if the file can even change in the tree...
> the file would only change when we source a file, no?
> 
> so i wonder if we need to keep track of the file in
> the tree at all, and not just update it at runtime
> in the thread.

You're right, we can just use lexfile directly; the
trees never come from a file other than the one we're
parsing.



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [9front] rc: null list in concatenation line numbers
  2020-10-25 23:41     ` cinap_lenrek
@ 2020-10-26  1:33       ` ori
  2020-10-26  7:36         ` cinap_lenrek
  0 siblings, 1 reply; 16+ messages in thread
From: ori @ 2020-10-26  1:33 UTC (permalink / raw)
  To: cinap_lenrek, 9front

> hm... thinking about it. basically, change of file can
> only happen when we do execdot() *AND* when calling a
> function.
> 
> but this should be easy. we could have a Xsrcfile pseudo
> operation that just updates the filename and has the
> filename as a immediate string in the opstream.
> 
> in fact, you could even just have a Xdbgname() that sets
> a generic stirng prefix, so you could also capture the
> function name.

After spending some time experimenting with this approach,
it feels fragile with the code as is. Xreturn also changes
the filename, and it's a bit messy to keep the file in sync
with the current code.

Here's the current iteration:

diff -r 0281cd6caa8c sys/src/cmd/rc/code.c
--- a/sys/src/cmd/rc/code.c	Sat Oct 24 17:24:59 2020 -0700
+++ b/sys/src/cmd/rc/code.c	Sun Oct 25 18:23:40 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,26 @@
 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->line != line || lexfile != file){
+		line = t->line;
+		file = lexfile;
+		/*
+		 * 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 = (lexfile > LFMAX) ? 0 : lexfile << LSHIFT;
+		l = (t->line > LMASK) ? 0 : t->line;
+		emitf(Xloc);
+		emiti(f|l);
+	}
 	switch(t->type){
 	default:
 		pfmt(err, "bad type %d in outcode\n", t->type);
diff -r 0281cd6caa8c sys/src/cmd/rc/exec.c
--- a/sys/src/cmd/rc/exec.c	Sat Oct 24 17:24:59 2020 -0700
+++ b/sys/src/cmd/rc/exec.c	Sun Oct 25 18:23:40 2020 -0700
@@ -14,6 +14,7 @@
 	struct thread *p = new(struct thread);
 
 	p->code = codecopy(c);
+	p->loc = runq?runq->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 = emalloc(sizeof(char*));
+	nlexpath = 1;
+	lexpath[0] = strdup("unknown");
+
 	for(;;){
 		if(flag['r'])
 			pfnc(err, runq);
@@ -932,7 +938,9 @@
 			if(p->cmdfile)
 				free(p->cmdfile);
 			closeio(p->cmdfd);
-			Xreturn();	/* should this be omitted? */
+			Xreturn();
+			lexfile = runq->loc >> LSHIFT;
+			lexline = runq->loc & LMASK;
 		}
 		else{
 			if(Eintr()){
@@ -953,10 +961,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 +978,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 +1043,9 @@
 {
 	globlist(runq->argv->words);
 }
+
+void
+Xloc(void)
+{
+	runq->loc = runq->code[runq->pc++].i;
+}
diff -r 0281cd6caa8c sys/src/cmd/rc/exec.h
--- a/sys/src/cmd/rc/exec.h	Sat Oct 24 17:24:59 2020 -0700
+++ b/sys/src/cmd/rc/exec.h	Sun Oct 25 18:23:40 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 0281cd6caa8c sys/src/cmd/rc/lex.c
--- a/sys/src/cmd/rc/lex.c	Sat Oct 24 17:24:59 2020 -0700
+++ b/sys/src/cmd/rc/lex.c	Sun Oct 25 18:23:40 2020 -0700
@@ -25,6 +25,15 @@
 int doprompt = 1;
 int inquote;
 int incomm;
+int lastc;
+int ndot;
+int nerror;
+int lexline;
+int lexfile;
+char **lexpath;
+int nlexpath;
+int lexpathsz;
+
 /*
  * Look ahead in the input stream
  */
@@ -39,13 +48,14 @@
 /*
  * Consume the lookahead character.
  */
-
 int
 advance(void)
 {
 	int c = nextc();
 	lastc = future;
 	future = EOF;
+	if(c == '\n')
+		lexline++;
 	return c;
 }
 /*
diff -r 0281cd6caa8c sys/src/cmd/rc/pfnc.c
--- a/sys/src/cmd/rc/pfnc.c	Sat Oct 24 17:24:59 2020 -0700
+++ b/sys/src/cmd/rc/pfnc.c	Sun Oct 25 18:23:40 2020 -0700
@@ -51,6 +51,7 @@
 	Xrdfn, "Xrdfn",
 	Xsimple, "Xsimple",
 	Xqw, "Xqw",
+	Xloc, "Xloc",
 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 ", lexpath[t->loc>>LSHIFT], t->loc&LMASK, getpid(), t->code, t->pc);
 	for(i = 0;fname[i].f;i++) if(fname[i].f==fn){
 		pstr(fd, fname[i].name);
 		break;
diff -r 0281cd6caa8c sys/src/cmd/rc/rc.h
--- a/sys/src/cmd/rc/rc.h	Sat Oct 24 17:24:59 2020 -0700
+++ b/sys/src/cmd/rc/rc.h	Sun Oct 25 18:23:40 2020 -0700
@@ -43,6 +43,7 @@
 	char	*str;
 	int	quoted;
 	int	iskw;
+	int	line;
 	tree	*child[3];
 	tree	*next;
 };
@@ -54,6 +55,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<<LSHIFT)-1)
+#define LFMAX	(1<<(8*sizeof(int)-LSHIFT-1))
+
 /*
  * 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 +140,16 @@
  */
 #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 lexfile;
+extern int lexline;
+extern char **lexpath;
+extern int nlexpath;
+extern int lexpathsz;
+
 /*
  * Which fds are the reading/writing end of a pipe?
  * Unfortunately, this can vary from system to system.
@@ -143,7 +163,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;
diff -r 0281cd6caa8c sys/src/cmd/rc/simple.c
--- a/sys/src/cmd/rc/simple.c	Sat Oct 24 17:24:59 2020 -0700
+++ b/sys/src/cmd/rc/simple.c	Sun Oct 25 18:23:40 2020 -0700
@@ -11,7 +11,7 @@
  */
 int
 exitnext(void){
-	union code *c=&runq->code[runq->pc];
+	code *c=&runq->code[runq->pc];
 	while(c->f==Xpopredir || c->f==Xunlocal) c++;
 	return c->f==Xexit;
 }
@@ -257,9 +257,16 @@
 union code rdcmds[4];
 
 void
-execcmds(io *f)
+execcmds(io *in)
 {
 	static int first = 1;
+	int f, l;
+
+	/* set up Xreturn to restore the right address */
+	f = (lexfile > LFMAX) ? 0 : lexfile << LSHIFT;
+	l = (lexline > LMASK) ? 0 : lexline;
+	runq->loc = f|l;
+
 	if(first){
 		rdcmds[0].i = 1;
 		rdcmds[1].f = Xrdcmds;
@@ -267,7 +274,7 @@
 		first = 0;
 	}
 	start(rdcmds, 1, runq->local);
-	runq->cmdfd = f;
+	runq->cmdfd = in;
 	runq->iflast = 0;
 }
 
@@ -294,7 +301,7 @@
 execdot(void)
 {
 	int iflag = 0;
-	int fd;
+	int fd, i, f, l;
 	list *av;
 	thread *p = runq;
 	char *zero, *file;
@@ -319,6 +326,12 @@
 	}
 	else
 		eflagok = 1;
+
+	/* set up Xreturn to restore the right address */
+	f = (lexfile > LFMAX) ? 0 : lexfile << LSHIFT;
+	l = (lexline > LMASK) ? 0 : lexline;
+	runq->loc = f|l;
+	
 	popword();
 	if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){
 		iflag = 1;
@@ -354,6 +367,23 @@
 		Xerror(".: can't open");
 		return;
 	}
+
+	lexline = 1;
+	lexfile = 0;
+	for(i = 0; i < nlexpath; i++){
+		if(strcmp(lexpath[i], zero) == 0){
+			lexfile = i;
+			break;
+		}
+	}
+	if(i == nlexpath && i < LFMAX){
+		if(nlexpath == lexpathsz){
+			lexpathsz *= 2;
+			lexpath = erealloc(lexpath, lexpathsz*sizeof(char*));
+		}
+		lexpath[nlexpath] = estrdup(zero);
+		lexfile = nlexpath++;
+	}
 	/* set up for a new command loop */
 	start(dotcmds, 1, (struct var *)0);
 	pushredir(RCLOSE, fd, 0);
diff -r 0281cd6caa8c sys/src/cmd/rc/tree.c
--- a/sys/src/cmd/rc/tree.c	Sat Oct 24 17:24:59 2020 -0700
+++ b/sys/src/cmd/rc/tree.c	Sun Oct 25 18:23:40 2020 -0700
@@ -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;
 }



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [9front] rc: null list in concatenation line numbers
  2020-10-26  1:33       ` ori
@ 2020-10-26  7:36         ` cinap_lenrek
  2020-10-28  3:16           ` ori
  0 siblings, 1 reply; 16+ messages in thread
From: cinap_lenrek @ 2020-10-26  7:36 UTC (permalink / raw)
  To: 9front

> After spending some time experimenting with this approach,
> it feels fragile with the code as is. Xreturn also changes
> the filename, and it's a bit messy to keep the file in sync
> with the current code.

yeah, but Xreturn just pops the thread! so just put the code
file name in the thread and it will restore automatically.
just like the thread references the code block... but maybe
i'm missing something else?

the idea basically was that you can completely get rid of
the file name table then...

--
cinap


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [9front] rc: null list in concatenation line numbers
  2020-10-26  7:36         ` cinap_lenrek
@ 2020-10-28  3:16           ` ori
  2020-10-28  9:50             ` cinap_lenrek
  0 siblings, 1 reply; 16+ messages in thread
From: ori @ 2020-10-28  3:16 UTC (permalink / raw)
  To: cinap_lenrek, 9front

> yeah, but Xreturn just pops the thread! so just put the code
> file name in the thread and it will restore automatically.
> just like the thread references the code block... but maybe
> i'm missing something else?
> 
> the idea basically was that you can completely get rid of
> the file name table then...

Yep, I was being too clever, and getting tripped up by
the rewind/replay logic. Doing less made it work.

Here's another iteration. It also handles /env/fn#foo,
and uses \n as the line separator for /env/fn#foo so
that we have some useful line numbers.

We can probably figure out some javascript source maps
or something to map back from /env/fn#foo to the file
that it came from, after.

Thanks mischief for the question.

diff -r 0e47f4a0c4d6 sys/src/cmd/rc/code.c
--- a/sys/src/cmd/rc/code.c	Tue Oct 27 15:16:03 2020 +0100
+++ b/sys/src/cmd/rc/code.c	Tue Oct 27 20:15:43 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);
@@ -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);
diff -r 0e47f4a0c4d6 sys/src/cmd/rc/exec.c
--- a/sys/src/cmd/rc/exec.c	Tue Oct 27 15:16:03 2020 +0100
+++ b/sys/src/cmd/rc/exec.c	Tue Oct 27 20:15:43 2020 -0700
@@ -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);
@@ -932,7 +937,7 @@
 			if(p->cmdfile)
 				free(p->cmdfile);
 			closeio(p->cmdfd);
-			Xreturn();	/* should this be omitted? */
+			Xreturn();
 		}
 		else{
 			if(Eintr()){
@@ -950,13 +955,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 +980,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();
@@ -1025,3 +1039,16 @@
 {
 	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 -r 0e47f4a0c4d6 sys/src/cmd/rc/exec.h
--- a/sys/src/cmd/rc/exec.h	Tue Oct 27 15:16:03 2020 +0100
+++ b/sys/src/cmd/rc/exec.h	Tue Oct 27 20:15:43 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), 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
diff -r 0e47f4a0c4d6 sys/src/cmd/rc/lex.c
--- a/sys/src/cmd/rc/lex.c	Tue Oct 27 15:16:03 2020 +0100
+++ b/sys/src/cmd/rc/lex.c	Tue Oct 27 20:15:43 2020 -0700
@@ -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,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 0e47f4a0c4d6 sys/src/cmd/rc/pcmd.c
--- a/sys/src/cmd/rc/pcmd.c	Tue Oct 27 15:16:03 2020 +0100
+++ b/sys/src/cmd/rc/pcmd.c	Tue Oct 27 20:15:43 2020 -0700
@@ -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);
diff -r 0e47f4a0c4d6 sys/src/cmd/rc/pfnc.c
--- a/sys/src/cmd/rc/pfnc.c	Tue Oct 27 15:16:03 2020 +0100
+++ b/sys/src/cmd/rc/pfnc.c	Tue Oct 27 20:15:43 2020 -0700
@@ -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;
diff -r 0e47f4a0c4d6 sys/src/cmd/rc/plan9.c
--- a/sys/src/cmd/rc/plan9.c	Tue Oct 27 15:16:03 2020 +0100
+++ b/sys/src/cmd/rc/plan9.c	Tue Oct 27 20:15:43 2020 -0700
@@ -164,9 +164,12 @@
 	if(runq->argv->words == 0)
 		poplist();
 	else {
+		free(runq->cmdfile);
 		int f = open(runq->argv->words->word, 0);
+		lexline = 0;
+		runq->cmdfile = strdup(runq->argv->words->word);
+		runq->pc--;
 		popword();
-		runq->pc--;
 		if(f>=0) execcmds(openfd(f));
 	}
 }
diff -r 0e47f4a0c4d6 sys/src/cmd/rc/rc.h
--- a/sys/src/cmd/rc/rc.h	Tue Oct 27 15:16:03 2020 +0100
+++ b/sys/src/cmd/rc/rc.h	Tue Oct 27 20:15:43 2020 -0700
@@ -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;
diff -r 0e47f4a0c4d6 sys/src/cmd/rc/simple.c
--- a/sys/src/cmd/rc/simple.c	Tue Oct 27 15:16:03 2020 +0100
+++ b/sys/src/cmd/rc/simple.c	Tue Oct 27 20:15:43 2020 -0700
@@ -11,7 +11,7 @@
  */
 int
 exitnext(void){
-	union code *c=&runq->code[runq->pc];
+	code *c=&runq->code[runq->pc];
 	while(c->f==Xpopredir || c->f==Xunlocal) c++;
 	return c->f==Xexit;
 }
@@ -260,6 +260,7 @@
 execcmds(io *f)
 {
 	static int first = 1;
+
 	if(first){
 		rdcmds[0].i = 1;
 		rdcmds[1].f = Xrdcmds;
@@ -319,6 +320,7 @@
 	}
 	else
 		eflagok = 1;
+
 	popword();
 	if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){
 		iflag = 1;
@@ -354,6 +356,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);
diff -r 0e47f4a0c4d6 sys/src/cmd/rc/tree.c
--- a/sys/src/cmd/rc/tree.c	Tue Oct 27 15:16:03 2020 +0100
+++ b/sys/src/cmd/rc/tree.c	Tue Oct 27 20:15:43 2020 -0700
@@ -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;
 }



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [9front] rc: null list in concatenation line numbers
  2020-10-28  3:16           ` ori
@ 2020-10-28  9:50             ` cinap_lenrek
  2020-10-28 17:59               ` ori
  2020-10-31  1:55               ` ori
  0 siblings, 2 replies; 16+ messages in thread
From: cinap_lenrek @ 2020-10-28  9:50 UTC (permalink / raw)
  To: 9front

> Here's another iteration. It also handles /env/fn#foo,
> and uses \n as the line separator for /env/fn#foo so
> that we have some useful line numbers.

i wonder if this breaks "whatis fuction".

this is also used in rcpu to serialize the rc functions
to the remote side...

there might be programs that only expect single line
output?

--
cinap


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [9front] rc: null list in concatenation line numbers
  2020-10-28  9:50             ` cinap_lenrek
@ 2020-10-28 17:59               ` ori
  2020-10-31  1:55               ` ori
  1 sibling, 0 replies; 16+ messages in thread
From: ori @ 2020-10-28 17:59 UTC (permalink / raw)
  To: cinap_lenrek, 9front

> there might be programs that only expect single line
> output?

Then they're already broken:

	fn foo{a'
	'b;c}

The comment indicated that it was for the sake
of the bourne shell.



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [9front] rc: null list in concatenation line numbers
  2020-10-28  9:50             ` cinap_lenrek
  2020-10-28 17:59               ` ori
@ 2020-10-31  1:55               ` ori
  1 sibling, 0 replies; 16+ messages in thread
From: ori @ 2020-10-31  1:55 UTC (permalink / raw)
  To: cinap_lenrek, 9front

>> Here's another iteration. It also handles /env/fn#foo,
>> and uses \n as the line separator for /env/fn#foo so
>> that we have some useful line numbers.
> 
> i wonder if this breaks "whatis fuction".
> 
> this is also used in rcpu to serialize the rc functions
> to the remote side...
> 
> there might be programs that only expect single line
> output?

Now, with corrected exitnext. Can look at optimizing
and #pragma line in some other commit.

diff -r 391d290cfbbe sys/src/cmd/rc/code.c
--- a/sys/src/cmd/rc/code.c	Fri Oct 30 13:23:16 2020 -0700
+++ b/sys/src/cmd/rc/code.c	Fri Oct 30 18:54:41 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);
@@ -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);
diff -r 391d290cfbbe sys/src/cmd/rc/exec.c
--- a/sys/src/cmd/rc/exec.c	Fri Oct 30 13:23:16 2020 -0700
+++ b/sys/src/cmd/rc/exec.c	Fri Oct 30 18:54:41 2020 -0700
@@ -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();
@@ -1025,3 +1041,16 @@
 {
 	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 -r 391d290cfbbe sys/src/cmd/rc/exec.h
--- a/sys/src/cmd/rc/exec.h	Fri Oct 30 13:23:16 2020 -0700
+++ b/sys/src/cmd/rc/exec.h	Fri Oct 30 18:54:41 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), 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
diff -r 391d290cfbbe sys/src/cmd/rc/lex.c
--- a/sys/src/cmd/rc/lex.c	Fri Oct 30 13:23:16 2020 -0700
+++ b/sys/src/cmd/rc/lex.c	Fri Oct 30 18:54:41 2020 -0700
@@ -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,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 391d290cfbbe sys/src/cmd/rc/pcmd.c
--- a/sys/src/cmd/rc/pcmd.c	Fri Oct 30 13:23:16 2020 -0700
+++ b/sys/src/cmd/rc/pcmd.c	Fri Oct 30 18:54:41 2020 -0700
@@ -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);
diff -r 391d290cfbbe sys/src/cmd/rc/pfnc.c
--- a/sys/src/cmd/rc/pfnc.c	Fri Oct 30 13:23:16 2020 -0700
+++ b/sys/src/cmd/rc/pfnc.c	Fri Oct 30 18:54:41 2020 -0700
@@ -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;
diff -r 391d290cfbbe sys/src/cmd/rc/plan9.c
--- a/sys/src/cmd/rc/plan9.c	Fri Oct 30 13:23:16 2020 -0700
+++ b/sys/src/cmd/rc/plan9.c	Fri Oct 30 18:54:41 2020 -0700
@@ -164,9 +164,12 @@
 	if(runq->argv->words == 0)
 		poplist();
 	else {
+		free(runq->cmdfile);
 		int f = open(runq->argv->words->word, 0);
+		lexline = 0;
+		runq->cmdfile = strdup(runq->argv->words->word);
+		runq->pc--;
 		popword();
-		runq->pc--;
 		if(f>=0) execcmds(openfd(f));
 	}
 }
diff -r 391d290cfbbe sys/src/cmd/rc/rc.h
--- a/sys/src/cmd/rc/rc.h	Fri Oct 30 13:23:16 2020 -0700
+++ b/sys/src/cmd/rc/rc.h	Fri Oct 30 18:54:41 2020 -0700
@@ -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;
diff -r 391d290cfbbe sys/src/cmd/rc/simple.c
--- a/sys/src/cmd/rc/simple.c	Fri Oct 30 13:23:16 2020 -0700
+++ b/sys/src/cmd/rc/simple.c	Fri Oct 30 18:54:41 2020 -0700
@@ -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);
diff -r 391d290cfbbe sys/src/cmd/rc/tree.c
--- a/sys/src/cmd/rc/tree.c	Fri Oct 30 13:23:16 2020 -0700
+++ b/sys/src/cmd/rc/tree.c	Fri Oct 30 18:54:41 2020 -0700
@@ -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;
 }



^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2020-10-31  1:55 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-16  1:40 rc: null list in concatenation line numbers ori
2020-10-16  3:43 ` [9front] " Xiao-Yong Jin
2020-10-17  1:47   ` ori
2020-10-16  5:40 ` Iruatã Souza
2020-10-22  1:18 ` ori
2020-10-22 12:11   ` tlaronde
2020-10-25 20:29   ` ori
2020-10-25 23:18     ` cinap_lenrek
2020-10-26  1:00       ` ori
2020-10-25 23:41     ` cinap_lenrek
2020-10-26  1:33       ` ori
2020-10-26  7:36         ` cinap_lenrek
2020-10-28  3:16           ` ori
2020-10-28  9:50             ` cinap_lenrek
2020-10-28 17:59               ` ori
2020-10-31  1:55               ` ori

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).