rc: show line numbers on error
This change provides a location for errors like 'null list in concatenation'.
This commit is contained in:
parent
dbd54342fd
commit
d75d842cf5
10 changed files with 107 additions and 35 deletions
|
@ -6,10 +6,12 @@
|
||||||
#define c0 t->child[0]
|
#define c0 t->child[0]
|
||||||
#define c1 t->child[1]
|
#define c1 t->child[1]
|
||||||
#define c2 t->child[2]
|
#define c2 t->child[2]
|
||||||
|
code *codebuf;
|
||||||
int codep, ncode;
|
int codep, ncode;
|
||||||
#define emitf(x) ((codep!=ncode || morecode()), codebuf[codep].f = (x), codep++)
|
#define emitf(x) ((codep!=ncode || morecode()), codebuf[codep].f = (x), codep++)
|
||||||
#define emiti(x) ((codep!=ncode || morecode()), codebuf[codep].i = (x), codep++)
|
#define emiti(x) ((codep!=ncode || morecode()), codebuf[codep].i = (x), codep++)
|
||||||
#define emits(x) ((codep!=ncode || morecode()), codebuf[codep].s = (x), codep++)
|
#define emits(x) ((codep!=ncode || morecode()), codebuf[codep].s = (x), codep++)
|
||||||
|
|
||||||
void stuffdot(int);
|
void stuffdot(int);
|
||||||
char *fnstr(tree*);
|
char *fnstr(tree*);
|
||||||
void outcode(tree*, int);
|
void outcode(tree*, int);
|
||||||
|
@ -38,7 +40,7 @@ int
|
||||||
compile(tree *t)
|
compile(tree *t)
|
||||||
{
|
{
|
||||||
ncode = 100;
|
ncode = 100;
|
||||||
codebuf = (code *)emalloc(ncode*sizeof codebuf[0]);
|
codebuf = emalloc(ncode*sizeof codebuf[0]);
|
||||||
codep = 0;
|
codep = 0;
|
||||||
emiti(0); /* reference count */
|
emiti(0); /* reference count */
|
||||||
outcode(t, flag['e']?1:0);
|
outcode(t, flag['e']?1:0);
|
||||||
|
@ -64,12 +66,8 @@ fnstr(tree *t)
|
||||||
{
|
{
|
||||||
io *f = openstr();
|
io *f = openstr();
|
||||||
void *v;
|
void *v;
|
||||||
extern char nl;
|
|
||||||
char svnl = nl;
|
|
||||||
|
|
||||||
nl = ';';
|
|
||||||
pfmt(f, "%t", t);
|
pfmt(f, "%t", t);
|
||||||
nl = svnl;
|
|
||||||
v = f->strp;
|
v = f->strp;
|
||||||
f->strp = 0;
|
f->strp = 0;
|
||||||
closeio(f);
|
closeio(f);
|
||||||
|
@ -79,12 +77,19 @@ fnstr(tree *t)
|
||||||
void
|
void
|
||||||
outcode(tree *t, int eflag)
|
outcode(tree *t, int eflag)
|
||||||
{
|
{
|
||||||
|
static int line;
|
||||||
int p, q;
|
int p, q;
|
||||||
tree *tt;
|
tree *tt;
|
||||||
|
char *f;
|
||||||
if(t==0)
|
if(t==0)
|
||||||
return;
|
return;
|
||||||
if(t->type!=NOT && t->type!=';')
|
if(t->type!=NOT && t->type!=';')
|
||||||
runq->iflast = 0;
|
runq->iflast = 0;
|
||||||
|
if(t->line != line){
|
||||||
|
line = t->line;
|
||||||
|
emitf(Xsrcline);
|
||||||
|
emiti(line);
|
||||||
|
}
|
||||||
switch(t->type){
|
switch(t->type){
|
||||||
default:
|
default:
|
||||||
pfmt(err, "bad type %d in outcode\n", t->type);
|
pfmt(err, "bad type %d in outcode\n", t->type);
|
||||||
|
@ -174,6 +179,12 @@ outcode(tree *t, int eflag)
|
||||||
emitf(Xfn);
|
emitf(Xfn);
|
||||||
p = emiti(0);
|
p = emiti(0);
|
||||||
emits(fnstr(c1));
|
emits(fnstr(c1));
|
||||||
|
if((f = curfile(runq)) != nil){
|
||||||
|
emitf(Xsrcfile);
|
||||||
|
emits(strdup(f));
|
||||||
|
}
|
||||||
|
emitf(Xsrcline);
|
||||||
|
emiti(lexline);
|
||||||
outcode(c1, eflag);
|
outcode(c1, eflag);
|
||||||
emitf(Xunlocal); /* get rid of $* */
|
emitf(Xunlocal); /* get rid of $* */
|
||||||
emitf(Xreturn);
|
emitf(Xreturn);
|
||||||
|
|
|
@ -14,11 +14,12 @@ start(code *c, int pc, var *local)
|
||||||
struct thread *p = new(struct thread);
|
struct thread *p = new(struct thread);
|
||||||
|
|
||||||
p->code = codecopy(c);
|
p->code = codecopy(c);
|
||||||
|
p->line = runq?runq->line:0;
|
||||||
p->pc = pc;
|
p->pc = pc;
|
||||||
p->argv = 0;
|
p->argv = 0;
|
||||||
p->redir = p->startredir = runq?runq->redir:0;
|
p->redir = p->startredir = runq?runq->redir:nil;
|
||||||
p->local = local;
|
p->local = local;
|
||||||
p->cmdfile = 0;
|
p->cmdfile = nil;
|
||||||
p->cmdfd = 0;
|
p->cmdfd = 0;
|
||||||
p->eof = 0;
|
p->eof = 0;
|
||||||
p->iflag = 0;
|
p->iflag = 0;
|
||||||
|
@ -201,10 +202,14 @@ main(int argc, char *argv[])
|
||||||
bootstrap[i++].f = Xexit;
|
bootstrap[i++].f = Xexit;
|
||||||
bootstrap[i].i = 0;
|
bootstrap[i].i = 0;
|
||||||
start(bootstrap, 1, (var *)0);
|
start(bootstrap, 1, (var *)0);
|
||||||
|
runq->cmdfile = strdup("rc");
|
||||||
/* prime bootstrap argv */
|
/* prime bootstrap argv */
|
||||||
pushlist();
|
pushlist();
|
||||||
argv0 = estrdup(argv[0]);
|
argv0 = estrdup(argv[0]);
|
||||||
for(i = argc-1;i!=0;--i) pushword(argv[i]);
|
for(i = argc-1;i!=0;--i) pushword(argv[i]);
|
||||||
|
|
||||||
|
lexline = 0;
|
||||||
|
|
||||||
for(;;){
|
for(;;){
|
||||||
if(flag['r'])
|
if(flag['r'])
|
||||||
pfnc(err, runq);
|
pfnc(err, runq);
|
||||||
|
@ -260,6 +265,8 @@ main(int argc, char *argv[])
|
||||||
* Xunlocal delete local variable
|
* Xunlocal delete local variable
|
||||||
* Xword[string] push string
|
* Xword[string] push string
|
||||||
* Xwrite(file)[fd] open file to write
|
* Xwrite(file)[fd] open file to write
|
||||||
|
* Xsrcline[line] set current line number
|
||||||
|
* Xsrcfile[file] set current file name
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -932,7 +939,7 @@ Xrdcmds(void)
|
||||||
if(p->cmdfile)
|
if(p->cmdfile)
|
||||||
free(p->cmdfile);
|
free(p->cmdfile);
|
||||||
closeio(p->cmdfd);
|
closeio(p->cmdfd);
|
||||||
Xreturn(); /* should this be omitted? */
|
Xreturn();
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if(Eintr()){
|
if(Eintr()){
|
||||||
|
@ -950,13 +957,22 @@ Xrdcmds(void)
|
||||||
freenodes();
|
freenodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
curfile(thread *p)
|
||||||
|
{
|
||||||
|
for(; p != nil; p = p->ret)
|
||||||
|
if(p->cmdfile != nil)
|
||||||
|
return p->cmdfile;
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Xerror(char *s)
|
Xerror(char *s)
|
||||||
{
|
{
|
||||||
if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
|
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
|
else
|
||||||
pfmt(err, "rc (%s): %s: %r\n", argv0, s);
|
pfmt(err, "%s:%d: %s: %r\n", curfile(runq), runq->line, s);
|
||||||
flush(err);
|
flush(err);
|
||||||
setstatus("error");
|
setstatus("error");
|
||||||
while(!runq->iflag) Xreturn();
|
while(!runq->iflag) Xreturn();
|
||||||
|
@ -966,9 +982,9 @@ void
|
||||||
Xerror1(char *s)
|
Xerror1(char *s)
|
||||||
{
|
{
|
||||||
if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
|
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
|
else
|
||||||
pfmt(err, "rc (%s): %s\n", argv0, s);
|
pfmt(err, "%s:%d: %s\n", curfile(runq), runq->line, s);
|
||||||
flush(err);
|
flush(err);
|
||||||
setstatus("error");
|
setstatus("error");
|
||||||
while(!runq->iflag) Xreturn();
|
while(!runq->iflag) Xreturn();
|
||||||
|
@ -1025,3 +1041,16 @@ Xglob(void)
|
||||||
{
|
{
|
||||||
globlist(runq->argv->words);
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ extern void Xappend(void), Xasync(void), Xbackq(void), Xbang(void), Xclose(void)
|
||||||
extern void Xconc(void), Xcount(void), Xdelfn(void), Xdol(void), Xqw(void), Xdup(void);
|
extern void 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 Xexit(void), Xfalse(void), Xfn(void), Xfor(void), Xglob(void);
|
||||||
extern void Xjump(void), Xmark(void), Xmatch(void), Xpipe(void), Xread(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 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 Xtrue(void), Xword(void), Xglobs(void), Xwrite(void), Xpipefd(void), Xcase(void);
|
||||||
extern void Xlocal(void), Xunlocal(void), Xassign(void), Xsimple(void), Xpopm(void);
|
extern void Xlocal(void), Xunlocal(void), Xassign(void), Xsimple(void), Xpopm(void);
|
||||||
|
@ -30,7 +30,7 @@ word *newword(char *, word *), *copywords(word *, word *);
|
||||||
struct redir{
|
struct redir{
|
||||||
char type; /* what to do */
|
char type; /* what to do */
|
||||||
short from, to; /* what to do it to */
|
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) */
|
#define NSTATUS ERRMAX /* length of status (from plan 9) */
|
||||||
/*
|
/*
|
||||||
|
@ -40,14 +40,15 @@ struct redir{
|
||||||
#define RDUP 2 /* dup2(from, to); */
|
#define RDUP 2 /* dup2(from, to); */
|
||||||
#define RCLOSE 3 /* close(from); */
|
#define RCLOSE 3 /* close(from); */
|
||||||
struct thread{
|
struct thread{
|
||||||
union code *code; /* code for this thread */
|
code *code; /* code for this thread */
|
||||||
int pc; /* code[pc] is the next instruction */
|
int pc; /* code[pc] is the next instruction */
|
||||||
struct list *argv; /* argument stack */
|
int line; /* source code line */
|
||||||
struct redir *redir; /* redirection stack */
|
list *argv; /* argument stack */
|
||||||
struct redir *startredir; /* redir inheritance point */
|
redir *redir; /* redirection stack */
|
||||||
struct var *local; /* list of local variables */
|
redir *startredir; /* redir inheritance point */
|
||||||
|
var *local; /* list of local variables */
|
||||||
char *cmdfile; /* file name in Xrdcmd */
|
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 iflast; /* static `if not' checking */
|
||||||
int eof; /* is cmdfd at eof? */
|
int eof; /* is cmdfd at eof? */
|
||||||
int iflag; /* interactive? */
|
int iflag; /* interactive? */
|
||||||
|
@ -55,7 +56,7 @@ struct thread{
|
||||||
int pid; /* process for Xpipewait to wait for */
|
int pid; /* process for Xpipewait to wait for */
|
||||||
char status[NSTATUS]; /* status for Xpipewait */
|
char status[NSTATUS]; /* status for Xpipewait */
|
||||||
tree *treenodes; /* tree nodes created by this process */
|
tree *treenodes; /* tree nodes created by this process */
|
||||||
thread *ret; /* who continues when this finishes */
|
thread *ret; /* who continues when this finishes */
|
||||||
};
|
};
|
||||||
thread *runq;
|
thread *runq;
|
||||||
code *codecopy(code*);
|
code *codecopy(code*);
|
||||||
|
@ -74,3 +75,4 @@ int execforkexec(void);
|
||||||
void execexit(void), execshift(void);
|
void execexit(void), execshift(void);
|
||||||
void execwait(void), execumask(void), execdot(void), execflag(void);
|
void execwait(void), execumask(void), execdot(void), execflag(void);
|
||||||
void execfunc(var*), execcmds(io *);
|
void execfunc(var*), execcmds(io *);
|
||||||
|
char *curfile(thread*);
|
|
@ -25,6 +25,13 @@ int future = EOF;
|
||||||
int doprompt = 1;
|
int doprompt = 1;
|
||||||
int inquote;
|
int inquote;
|
||||||
int incomm;
|
int incomm;
|
||||||
|
int lastc;
|
||||||
|
int ndot;
|
||||||
|
int nerror;
|
||||||
|
int lexline;
|
||||||
|
int nlexpath;
|
||||||
|
int lexpathsz;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Look ahead in the input stream
|
* Look ahead in the input stream
|
||||||
*/
|
*/
|
||||||
|
@ -39,13 +46,14 @@ nextc(void)
|
||||||
/*
|
/*
|
||||||
* Consume the lookahead character.
|
* Consume the lookahead character.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
advance(void)
|
advance(void)
|
||||||
{
|
{
|
||||||
int c = nextc();
|
int c = nextc();
|
||||||
lastc = future;
|
lastc = future;
|
||||||
future = EOF;
|
future = EOF;
|
||||||
|
if(c == '\n')
|
||||||
|
lexline++;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
char nl='\n'; /* change to semicolon for bourne-proofing */
|
|
||||||
#define c0 t->child[0]
|
#define c0 t->child[0]
|
||||||
#define c1 t->child[1]
|
#define c1 t->child[1]
|
||||||
#define c2 t->child[2]
|
#define c2 t->child[2]
|
||||||
|
@ -76,7 +76,7 @@ pcmd(io *f, tree *t)
|
||||||
case ';':
|
case ';':
|
||||||
if(c0){
|
if(c0){
|
||||||
if(c1)
|
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", c0);
|
||||||
}
|
}
|
||||||
else pfmt(f, "%t", c1);
|
else pfmt(f, "%t", c1);
|
||||||
|
|
|
@ -51,6 +51,7 @@ struct{
|
||||||
Xrdfn, "Xrdfn",
|
Xrdfn, "Xrdfn",
|
||||||
Xsimple, "Xsimple",
|
Xsimple, "Xsimple",
|
||||||
Xqw, "Xqw",
|
Xqw, "Xqw",
|
||||||
|
Xsrcline, "Xsrcline",
|
||||||
0};
|
0};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -59,7 +60,8 @@ pfnc(io *fd, thread *t)
|
||||||
int i;
|
int i;
|
||||||
void (*fn)(void) = t->code[t->pc].f;
|
void (*fn)(void) = t->code[t->pc].f;
|
||||||
list *a;
|
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){
|
for(i = 0;fname[i].f;i++) if(fname[i].f==fn){
|
||||||
pstr(fd, fname[i].name);
|
pstr(fd, fname[i].name);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -164,9 +164,12 @@ Xrdfn(void)
|
||||||
if(runq->argv->words == 0)
|
if(runq->argv->words == 0)
|
||||||
poplist();
|
poplist();
|
||||||
else {
|
else {
|
||||||
|
free(runq->cmdfile);
|
||||||
int f = open(runq->argv->words->word, 0);
|
int f = open(runq->argv->words->word, 0);
|
||||||
popword();
|
lexline = 0;
|
||||||
|
runq->cmdfile = strdup(runq->argv->words->word);
|
||||||
runq->pc--;
|
runq->pc--;
|
||||||
|
popword();
|
||||||
if(f>=0) execcmds(openfd(f));
|
if(f>=0) execcmds(openfd(f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ struct tree{
|
||||||
char *str;
|
char *str;
|
||||||
int quoted;
|
int quoted;
|
||||||
int iskw;
|
int iskw;
|
||||||
|
int line;
|
||||||
tree *child[3];
|
tree *child[3];
|
||||||
tree *next;
|
tree *next;
|
||||||
};
|
};
|
||||||
|
@ -54,6 +55,7 @@ tree *mung3(tree*, tree*, tree*, tree*), *epimung(tree*, tree*);
|
||||||
tree *simplemung(tree*), *heredoc(tree*);
|
tree *simplemung(tree*), *heredoc(tree*);
|
||||||
void freetree(tree*);
|
void freetree(tree*);
|
||||||
tree *cmdtree;
|
tree *cmdtree;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The first word of any code vector is a reference count.
|
* The first word of any code vector is a reference count.
|
||||||
* Always create a new reference to a code vector by calling codecopy(.).
|
* Always create a new reference to a code vector by calling codecopy(.).
|
||||||
|
@ -126,10 +128,12 @@ int mypid;
|
||||||
*/
|
*/
|
||||||
#define onebyte(c) ((c&0x80)==0x00)
|
#define onebyte(c) ((c&0x80)==0x00)
|
||||||
|
|
||||||
char **argp;
|
extern char **argp;
|
||||||
char **args;
|
extern char **args;
|
||||||
int nerror; /* number of errors encountered during compilation */
|
extern int nerror; /* number of errors encountered during compilation */
|
||||||
int doprompt; /* is it time for a prompt? */
|
extern int doprompt; /* is it time for a prompt? */
|
||||||
|
extern int lexline;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Which fds are the reading/writing end of a pipe?
|
* Which fds are the reading/writing end of a pipe?
|
||||||
* Unfortunately, this can vary from system to system.
|
* Unfortunately, this can vary from system to system.
|
||||||
|
@ -143,7 +147,7 @@ char Rcmain[], Fdprefix[];
|
||||||
* How many dot commands have we executed?
|
* How many dot commands have we executed?
|
||||||
* Used to ensure that -v flag doesn't print rcmain.
|
* Used to ensure that -v flag doesn't print rcmain.
|
||||||
*/
|
*/
|
||||||
int ndot;
|
extern int ndot;
|
||||||
|
extern int lastc;
|
||||||
|
extern int lastword;
|
||||||
char *getstatus(void);
|
char *getstatus(void);
|
||||||
int lastc;
|
|
||||||
int lastword;
|
|
||||||
|
|
|
@ -11,8 +11,15 @@
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
exitnext(void){
|
exitnext(void){
|
||||||
union code *c=&runq->code[runq->pc];
|
code *c=&runq->code[runq->pc];
|
||||||
while(c->f==Xpopredir || c->f==Xunlocal) c++;
|
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;
|
return c->f==Xexit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,6 +267,7 @@ void
|
||||||
execcmds(io *f)
|
execcmds(io *f)
|
||||||
{
|
{
|
||||||
static int first = 1;
|
static int first = 1;
|
||||||
|
|
||||||
if(first){
|
if(first){
|
||||||
rdcmds[0].i = 1;
|
rdcmds[0].i = 1;
|
||||||
rdcmds[1].f = Xrdcmds;
|
rdcmds[1].f = Xrdcmds;
|
||||||
|
@ -319,6 +327,7 @@ execdot(void)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
eflagok = 1;
|
eflagok = 1;
|
||||||
|
|
||||||
popword();
|
popword();
|
||||||
if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){
|
if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){
|
||||||
iflag = 1;
|
iflag = 1;
|
||||||
|
@ -354,6 +363,9 @@ execdot(void)
|
||||||
Xerror(".: can't open");
|
Xerror(".: can't open");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lexline = 1;
|
||||||
|
|
||||||
/* set up for a new command loop */
|
/* set up for a new command loop */
|
||||||
start(dotcmds, 1, (struct var *)0);
|
start(dotcmds, 1, (struct var *)0);
|
||||||
pushredir(RCLOSE, fd, 0);
|
pushredir(RCLOSE, fd, 0);
|
||||||
|
|
|
@ -16,6 +16,7 @@ newtree(void)
|
||||||
t->str = 0;
|
t->str = 0;
|
||||||
t->child[0] = t->child[1] = t->child[2] = 0;
|
t->child[0] = t->child[1] = t->child[2] = 0;
|
||||||
t->next = treenodes;
|
t->next = treenodes;
|
||||||
|
t->line = lexline;
|
||||||
treenodes = t;
|
treenodes = t;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue