From: ori@eigenstate.org
To: 9front@9front.org
Subject: rc: null list in concatenation line numbers
Date: Thu, 15 Oct 2020 18:40:53 -0700 [thread overview]
Message-ID: <71CE86A5EC086742886B6A2E7F09C255@eigenstate.org> (raw)
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;
}
next reply other threads:[~2020-10-16 1:40 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-10-16 1:40 ori [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=71CE86A5EC086742886B6A2E7F09C255@eigenstate.org \
--to=ori@eigenstate.org \
--cc=9front@9front.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).