summaryrefslogtreecommitdiff
path: root/sys/src/cmd/rc/exec.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2021-12-31 15:27:10 +0000
committercinap_lenrek <cinap_lenrek@felloff.net>2021-12-31 15:27:10 +0000
commitb90036a062ca330ac5f667cd1ee503686cbe0b80 (patch)
treeab9538715188d5017843c6d94e2ee4c5e155448a /sys/src/cmd/rc/exec.c
parent855cf4326f5a07d7142c2d8918f5fa856d912b85 (diff)
rc: fix everything
Untangle the lexer and interpreter thread state. Fix the file and line number error reporting, getting rid of Xsrcfile instruction, as the whole code block can only come from a single file, stuff the source file in slot[1] of the code block instead. Remove limitations for globber (path element limits) and be more intelligent about handling globbing by inserting Xglob instruction only when needed and not run it over every Xsimple argument list. Remove fragile ndot magic and make it explicit by adding the -q flag to . builtin command. Add -b flag for full compilation. Make exitnext() smart, so we can speculate thru rcmain and avoid the fork(). Get rid of all print(2) format functions and use io instead. Improve the io library, adding rstr() to handle tokenization, which allows us to look ahead in the already read buffer for the terminators, avoiding alot of string copies. Auto indent pcmd(), to make line number reporting more usefull. Implement here documents properly, so they can work everywhere.
Diffstat (limited to 'sys/src/cmd/rc/exec.c')
-rw-r--r--sys/src/cmd/rc/exec.c639
1 files changed, 336 insertions, 303 deletions
diff --git a/sys/src/cmd/rc/exec.c b/sys/src/cmd/rc/exec.c
index 7cada279d..f200f3065 100644
--- a/sys/src/cmd/rc/exec.c
+++ b/sys/src/cmd/rc/exec.c
@@ -3,64 +3,96 @@
#include "exec.h"
#include "io.h"
#include "fns.h"
+
/*
* Start executing the given code at the given pc with the given redirection
*/
-char *argv0="rc";
-
void
-start(code *c, int pc, var *local)
+start(code *c, int pc, var *local, redir *redir)
{
- struct thread *p = new(struct thread);
-
+ thread *p = new(thread);
p->code = codecopy(c);
- p->line = runq?runq->line:0;
+ p->line = 0;
p->pc = pc;
p->argv = 0;
- p->redir = p->startredir = runq?runq->redir:nil;
+ p->redir = p->startredir = redir;
+ p->lex = 0;
p->local = local;
- p->cmdfile = nil;
- p->cmdfd = 0;
- p->eof = 0;
p->iflag = 0;
- p->lineno = runq ? runq->lineno : 1;
p->ret = runq;
runq = p;
}
+void
+startfunc(var *func, word *starval, var *local, redir *redir)
+{
+ start(func->fn, func->pc, local, redir);
+ runq->local = newvar("*", runq->local);
+ runq->local->val = starval;
+ runq->local->changed = 1;
+}
+
+static void
+popthread(void)
+{
+ thread *p = runq;
+ while(p->argv) poplist();
+ while(p->local && (p->ret==0 || p->local!=p->ret->local))
+ Xunlocal();
+ runq = p->ret;
+ if(p->lex) freelexer(p->lex);
+ codefree(p->code);
+ free(p);
+}
+
word*
-Newword(char *wd, word *next)
+Newword(char *s, word *next)
{
- word *p = new(word);
- p->word = wd;
+ word *p=new(word);
+ p->word = s;
p->next = next;
- p->glob = 0;
return p;
}
word*
-Pushword(char *wd)
+newword(char *s, word *next)
{
- word *w;
+ return Newword(estrdup(s), next);
+}
+word*
+Pushword(char *s)
+{
+ word *p;
+ if(s==0)
+ panic("null pushword", 0);
if(runq->argv==0)
panic("pushword but no argv!", 0);
- w = Newword(wd, runq->argv->words);
- runq->argv->words = w;
- return w;
+ p = Newword(s, runq->argv->words);
+ runq->argv->words = p;
+ return p;
}
-
word*
-newword(char *wd, word *next)
+pushword(char *s)
{
- return Newword(estrdup(wd), next);
+ return Pushword(estrdup(s));
}
-word*
-pushword(char *wd)
+char*
+Freeword(word *p)
{
- return Pushword(estrdup(wd));
+ char *s = p->word;
+ free(p);
+ return s;
}
-
void
-popword(void)
+freewords(word *w)
+{
+ word *p;
+ while((p = w)!=0){
+ w = w->next;
+ free(Freeword(p));
+ }
+}
+char*
+Popword(void)
{
word *p;
if(runq->argv==0)
@@ -69,40 +101,38 @@ popword(void)
if(p==0)
panic("popword but no word!", 0);
runq->argv->words = p->next;
- free(p->word);
- free(p);
+ return Freeword(p);
}
-
void
-freelist(word *w)
-{
- word *nw;
- while(w){
- nw = w->next;
- free(w->word);
- free(w);
- w = nw;
- }
+popword(void)
+{
+ free(Popword());
}
void
pushlist(void)
{
list *p = new(list);
- p->next = runq->argv;
p->words = 0;
+ p->next = runq->argv;
runq->argv = p;
}
-
-void
-poplist(void)
+word*
+Poplist(void)
{
+ word *w;
list *p = runq->argv;
if(p==0)
panic("poplist but no argv", 0);
- freelist(p->words);
+ w = p->words;
runq->argv = p->next;
free(p);
+ return w;
+}
+void
+poplist(void)
+{
+ freewords(Poplist());
}
int
@@ -116,7 +146,7 @@ count(word *w)
void
pushredir(int type, int from, int to)
{
- redir * rp = new(redir);
+ redir *rp = new(redir);
rp->type = type;
rp->from = from;
rp->to = to;
@@ -124,6 +154,43 @@ pushredir(int type, int from, int to)
runq->redir = rp;
}
+static void
+dontclose(int fd)
+{
+ redir *rp;
+
+ if(fd<0)
+ return;
+ for(rp = runq->redir; rp != runq->startredir; rp = rp->next){
+ if(rp->type == RCLOSE && rp->from == fd){
+ rp->type = 0;
+ break;
+ }
+ }
+}
+
+/*
+ * we are about to start a new thread that should exit on
+ * return, so the current stack is not needed anymore.
+ * free all the threads and lexers, but preserve the
+ * redirections and anything referenced by local.
+ */
+void
+turfstack(var *local)
+{
+ while(local){
+ thread *p;
+
+ for(p = runq; p && p->local == local; p = p->ret)
+ p->local = local->next;
+ local = local->next;
+ }
+ while(runq) {
+ if(runq->lex) dontclose(runq->lex->input->fd);
+ popthread();
+ }
+}
+
void
shuffleredir(void)
{
@@ -139,33 +206,25 @@ shuffleredir(void)
*rr = rp;
}
-var*
-newvar(char *name, var *next)
-{
- var *v = new(var);
- v->name = estrdup(name);
- v->val = 0;
- v->fn = 0;
- v->changed = 0;
- v->fnchanged = 0;
- v->next = next;
- return v;
-}
/*
* get command line flags, initialize keywords & traps.
* get values from environment.
* set $pid, $cflag, $*
- * fabricate bootstrap code and start it (*=(argv);. /usr/lib/rcmain $*)
+ * fabricate bootstrap code and start it (*=(argv);. -bq /usr/lib/rcmain $*)
* start interpreting code
*/
+char *argv0="rc";
void
main(int argc, char *argv[])
{
- code bootstrap[17];
- char num[12], *rcmain;
+ code bootstrap[20];
+ char num[12];
+ char *rcmain=Rcmain;
+
int i;
- argc = getflags(argc, argv, "SsrdiIlxepvVc:1m:1[command]", 1);
+ argv0 = argv[0];
+ argc = getflags(argc, argv, "SsrdiIlxebpvVc:1m:1[command]", 1);
if(argc==-1)
usage("[file [arg ...]]");
if(argv[0][0]=='-')
@@ -173,8 +232,8 @@ main(int argc, char *argv[])
if(flag['I'])
flag['i'] = 0;
else if(flag['i']==0 && argc==1 && Isatty(0)) flag['i'] = flagset;
- rcmain = flag['m']?flag['m'][0]:Rcmain;
- err = openfd(2);
+ if(flag['m']) rcmain = flag['m'][0];
+ err = openiofd(2);
kinit();
Trapinit();
Vinit();
@@ -183,38 +242,36 @@ main(int argc, char *argv[])
setvar("cflag", flag['c']?newword(flag['c'][0], (word *)0)
:(word *)0);
setvar("rcname", newword(argv[0], (word *)0));
- i = 0;
- bootstrap[i++].i = 1;
- bootstrap[i++].f = Xmark;
- bootstrap[i++].f = Xword;
- bootstrap[i++].s="*";
- bootstrap[i++].f = Xassign;
- bootstrap[i++].f = Xmark;
- bootstrap[i++].f = Xmark;
- bootstrap[i++].f = Xword;
- bootstrap[i++].s="*";
- bootstrap[i++].f = Xdol;
- bootstrap[i++].f = Xword;
- bootstrap[i++].s = rcmain;
- bootstrap[i++].f = Xword;
- bootstrap[i++].s=".";
- bootstrap[i++].f = Xsimple;
- bootstrap[i++].f = Xexit;
- bootstrap[i].i = 0;
- start(bootstrap, 1, (var *)0);
- runq->cmdfile = strdup("rc");
- runq->lexline = 0;
+ bootstrap[0].i = 1;
+ bootstrap[1].s="*bootstrap*";
+ bootstrap[2].f = Xmark;
+ bootstrap[3].f = Xword;
+ bootstrap[4].s="*";
+ bootstrap[5].f = Xassign;
+ bootstrap[6].f = Xmark;
+ bootstrap[7].f = Xmark;
+ bootstrap[8].f = Xword;
+ bootstrap[9].s="*";
+ bootstrap[10].f = Xdol;
+ bootstrap[11].f = Xword;
+ bootstrap[12].s = rcmain;
+ bootstrap[13].f = Xword;
+ bootstrap[14].s="-bq";
+ bootstrap[15].f = Xword;
+ bootstrap[16].s=".";
+ bootstrap[17].f = Xsimple;
+ bootstrap[18].f = Xexit;
+ bootstrap[19].f = 0;
+ start(bootstrap, 2, (var*)0, (redir*)0);
+
/* prime bootstrap argv */
pushlist();
- argv0 = estrdup(argv[0]);
for(i = argc-1;i!=0;--i) pushword(argv[i]);
-
for(;;){
if(flag['r'])
pfnc(err, runq);
- runq->pc++;
- (*runq->code[runq->pc-1].f)();
+ (*runq->code[runq->pc++].f)();
if(ntrap)
dotrap();
}
@@ -236,15 +293,13 @@ main(int argc, char *argv[])
* Xconc(left, right) concatenate, push results
* Xcount(name) push var count
* Xdelfn(name) delete function definition
- * Xdeltraps(names) delete named traps
* Xdol(name) get variable value
- * Xqw(list) quote list, push result
* Xdup[i j] dup file descriptor
* Xexit rc exits with status
* Xfalse{...} execute {} if false
- * Xfn(name){... Xreturn} define function
+ * Xfn(name){... Xreturn} define function
* Xfor(var, list){... Xreturn} for loop
- * Xglobs[string globsize] push globbing string
+ * Xglob(word) glob word inplace
* Xjump[addr] goto
* Xlocal(name, val) create local variable, assign value
* Xmark mark stack
@@ -254,26 +309,26 @@ main(int argc, char *argv[])
* Xpipefd[type]{... Xreturn} connect {} to pipe (input or output,
* depending on type), push /dev/fd/??
* Xpopm(value) pop value from stack
+ * Xpush(words) push words down a list
+ * Xqw(words) quote words inplace
* Xrdwr(file)[fd] open file for reading and writing
* Xread(file)[fd] open file to read
- * Xsettraps(names){... Xreturn} define trap functions
- * Xshowtraps print trap list
- * Xsimple(args) run command and wait
* Xreturn kill thread
+ * Xsimple(args) run command and wait
+ * Xsrcline[line] set current source line number
* Xsubshell{... Xexit} execute {} in a subshell and wait
* Xtrue{...} execute {} if true
* 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
Xappend(void)
{
char *file;
- int f;
+ int fd;
+
switch(count(runq->argv->words)){
default:
Xerror1(">> requires singleton");
@@ -285,14 +340,12 @@ Xappend(void)
break;
}
file = runq->argv->words->word;
- if((f = open(file, 1))<0 && (f = Creat(file))<0){
- pfmt(err, "%s: ", file);
+ if((fd = Open(file, 1))<0 && (fd = Creat(file))<0){
Xerror("can't open");
return;
}
- Seek(f, 0L, 2);
- pushredir(ROPEN, f, runq->code[runq->pc].i);
- runq->pc++;
+ Seek(fd, 0L, 2);
+ pushredir(ROPEN, fd, runq->code[runq->pc++].i);
poplist();
}
@@ -311,8 +364,7 @@ Xbang(void)
void
Xclose(void)
{
- pushredir(RCLOSE, runq->code[runq->pc].i, 0);
- runq->pc++;
+ pushredir(RCLOSE, runq->code[runq->pc++].i, 0);
}
void
@@ -325,26 +377,21 @@ Xdup(void)
void
Xeflag(void)
{
- if(eflagok && !truestatus()) Xexit();
+ if(!truestatus()) Xexit();
}
void
Xexit(void)
{
- struct var *trapreq;
- struct word *starval;
static int beenhere = 0;
+
if(getpid()==mypid && !beenhere){
- trapreq = vlook("sigexit");
+ var *trapreq = vlook("sigexit");
+ word *starval = vlook("*")->val;
if(trapreq->fn){
beenhere = 1;
--runq->pc;
- starval = vlook("*")->val;
- start(trapreq->fn, trapreq->pc, (struct var *)0);
- runq->local = newvar("*", runq->local);
- runq->local->val = copywords(starval, (struct word *)0);
- runq->local->changed = 1;
- runq->redir = runq->startredir = 0;
+ startfunc(trapreq, copywords(starval, (word*)0), (var*)0, (redir*)0);
return;
}
}
@@ -387,87 +434,115 @@ Xpopm(void)
}
void
-Xread(void)
+Xpush(void)
+{
+ word *t, *h = Poplist();
+ for(t = h; t->next; t = t->next)
+ ;
+ t->next = runq->argv->words;
+ runq->argv->words = h;
+}
+
+void
+Xhere(void)
{
char *file;
- int f;
+ int fd;
+ io *io;
+
switch(count(runq->argv->words)){
default:
- Xerror1("< requires singleton\n");
+ Xerror1("<< requires singleton");
return;
case 0:
- Xerror1("< requires file\n");
+ Xerror1("<< requires file");
return;
case 1:
break;
}
- file = runq->argv->words->word;
- if((f = open(file, 0))<0){
- pfmt(err, "%s: ", file);
+ file = mktemp(runq->argv->words->word);
+ if((fd = Creat(file))<0){
+ Xerror("can't open");
+ return;
+ }
+ io = openiofd(fd);
+ psubst(io, (uchar*)runq->code[runq->pc++].s);
+ flushio(io);
+ closeio(io);
+ /* open for reading and unlink */
+ if((fd = Open(file, 3))<0){
Xerror("can't open");
return;
}
- pushredir(ROPEN, f, runq->code[runq->pc].i);
- runq->pc++;
+ pushredir(ROPEN, fd, runq->code[runq->pc++].i);
poplist();
}
void
-Xrdwr(void)
+Xread(void)
{
- char *file;
- int f;
+ int fd;
switch(count(runq->argv->words)){
default:
- Xerror1("<> requires singleton\n");
+ Xerror1("< requires singleton");
return;
case 0:
- Xerror1("<> requires file\n");
+ Xerror1("< requires file");
return;
case 1:
break;
}
- file = runq->argv->words->word;
- if((f = open(file, ORDWR))<0){
- pfmt(err, "%s: ", file);
+ if((fd = Open(runq->argv->words->word, 0))<0){
Xerror("can't open");
return;
}
- pushredir(ROPEN, f, runq->code[runq->pc].i);
- runq->pc++;
+ pushredir(ROPEN, fd, runq->code[runq->pc++].i);
poplist();
}
void
-turfredir(void)
+Xrdwr(void)
{
- while(runq->redir!=runq->startredir)
- Xpopredir();
+ int fd;
+
+ switch(count(runq->argv->words)){
+ default:
+ Xerror1("<> requires singleton");
+ return;
+ case 0:
+ Xerror1("<> requires file");
+ return;
+ case 1:
+ break;
+ }
+ if((fd = Open(runq->argv->words->word, 2))<0){
+ Xerror("can't open");
+ return;
+ }
+ pushredir(ROPEN, fd, runq->code[runq->pc++].i);
+ poplist();
}
void
Xpopredir(void)
{
- struct redir *rp = runq->redir;
+ redir *rp = runq->redir;
+
if(rp==0)
- panic("turfredir null!", 0);
+ panic("Xpopredir null!", 0);
runq->redir = rp->next;
if(rp->type==ROPEN)
- close(rp->from);
+ Close(rp->from);
free(rp);
}
void
Xreturn(void)
{
- struct thread *p = runq;
- turfredir();
- while(p->argv) poplist();
- codefree(p->code);
- free(p->cmdfile);
- runq = p->ret;
- free(p);
+ while(runq->redir!=runq->startredir)
+ Xpopredir();
+ popthread();
if(runq==0)
Exit(getstatus());
}
@@ -500,71 +575,41 @@ Xword(void)
}
void
-Xglobs(void)
-{
- word *w = pushword(runq->code[runq->pc++].s);
- w->glob = runq->code[runq->pc++].i;
-}
-
-void
Xwrite(void)
{
- char *file;
- int f;
+ int fd;
+
switch(count(runq->argv->words)){
default:
- Xerror1("> requires singleton\n");
+ Xerror1("> requires singleton");
return;
case 0:
- Xerror1("> requires file\n");
+ Xerror1("> requires file");
return;
case 1:
break;
}
- file = runq->argv->words->word;
- if((f = Creat(file))<0){
- pfmt(err, "%s: ", file);
+ if((fd = Creat(runq->argv->words->word))<0){
Xerror("can't open");
return;
}
- pushredir(ROPEN, f, runq->code[runq->pc].i);
- runq->pc++;
+ pushredir(ROPEN, fd, runq->code[runq->pc++].i);
poplist();
}
-char*
-list2str(word *words)
-{
- char *value, *s, *t;
- int len = 0;
- word *ap;
- for(ap = words;ap;ap = ap->next)
- len+=1+strlen(ap->word);
- value = emalloc(len+1);
- s = value;
- for(ap = words;ap;ap = ap->next){
- for(t = ap->word;*t;) *s++=*t++;
- *s++=' ';
- }
- if(s==value)
- *s='\0';
- else s[-1]='\0';
- return value;
-}
-
void
Xmatch(void)
{
word *p;
- char *subject;
- subject = list2str(runq->argv->words);
+ char *s;
+
setstatus("no match");
+ s = runq->argv->words->word;
for(p = runq->argv->next->words;p;p = p->next)
- if(match(subject, p->word, '\0')){
+ if(match(s, p->word, '\0')){
setstatus("");
break;
}
- free(subject);
poplist();
poplist();
}
@@ -575,14 +620,14 @@ Xcase(void)
word *p;
char *s;
int ok = 0;
- s = list2str(runq->argv->next->words);
+
+ s = runq->argv->next->words->word;
for(p = runq->argv->words;p;p = p->next){
if(match(s, p->word, '\0')){
ok = 1;
break;
}
}
- free(s);
if(ok)
runq->pc++;
else
@@ -590,7 +635,7 @@ Xcase(void)
poplist();
}
-word*
+static word*
conclist(word *lp, word *rp, word *tail)
{
word *v, *p, **end;
@@ -601,8 +646,6 @@ conclist(word *lp, word *rp, word *tail)
p = Newword(emalloc(ln+rn+1), (word *)0);
memmove(p->word, lp->word, ln);
memmove(p->word+ln, rp->word, rn+1);
- if(lp->glob || rp->glob)
- p->glob = Globsize(p->word);
*end = p, end = &p->next;
if(lp->next == 0 && rp->next == 0)
break;
@@ -636,41 +679,30 @@ Xconc(void)
runq->argv->words = vp;
}
-char*
-Str(word *a)
-{
- char *s = a->word;
- if(a->glob){
- a->glob = 0;
- deglob(s);
- }
- return s;
-}
-
void
Xassign(void)
{
var *v;
+
if(count(runq->argv->words)!=1){
Xerror1("variable name not singleton!");
return;
}
- v = vlook(Str(runq->argv->words));
+ v = vlook(runq->argv->words->word);
poplist();
freewords(v->val);
- v->val = globlist(runq->argv->words);
+ v->val = Poplist();
v->changed = 1;
- runq->argv->words = 0;
- poplist();
}
+
/*
* copy arglist a, adding the copy to the front of tail
*/
-
word*
copywords(word *a, word *tail)
{
word *v = 0, **end;
+
for(end=&v;a;a = a->next,end=&(*end)->next)
*end = newword(a->word, 0);
*end = tail;
@@ -683,12 +715,13 @@ Xdol(void)
word *a, *star;
char *s, *t;
int n;
+
if(count(runq->argv->words)!=1){
Xerror1("variable name not singleton!");
return;
}
- s = Str(runq->argv->words);
n = 0;
+ s = runq->argv->words->word;
for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0';
a = runq->argv->next->words;
if(n==0 || *t)
@@ -707,23 +740,34 @@ Xdol(void)
void
Xqw(void)
{
- char *s;
- word *a;
+ char *s, *d;
+ word *a, *p;
+ int n;
a = runq->argv->words;
- if(a && a->next == 0){
- runq->argv->words = 0;
- poplist();
- a->next = runq->argv->words;
- runq->argv->words = a;
+ if(a==0){
+ pushword("");
return;
}
- s = list2str(a);
- poplist();
- Pushword(s);
+ if(a->next==0)
+ return;
+ n=0;
+ for(p=a;p;p=p->next)
+ n+=1+strlen(p->word);
+ s = emalloc(n+1);
+ d = s;
+ d += strlen(strcpy(d, a->word));
+ for(p=a->next;p;p=p->next){
+ *d++=' ';
+ d += strlen(strcpy(d, p->word));
+ }
+ free(a->word);
+ freewords(a->next);
+ a->word = s;
+ a->next = 0;
}
-word*
+static word*
copynwords(word *a, word *tail, int n)
{
word *v, **end;
@@ -739,15 +783,16 @@ copynwords(word *a, word *tail, int n)
return v;
}
-word*
+static word*
subwords(word *val, int len, word *sub, word *a)
{
int n, m;
char *s;
- if(!sub)
+
+ if(sub==0)
return a;
a = subwords(val, len, sub->next, a);
- s = Str(sub);
+ s = sub->word;
m = 0;
n = 0;
while('0'<=*s && *s<='9')
@@ -775,11 +820,12 @@ Xsub(void)
{
word *a, *v;
char *s;
+
if(count(runq->argv->next->words)!=1){
Xerror1("variable name not singleton!");
return;
}
- s = Str(runq->argv->next->words);
+ s = runq->argv->next->words->word;
a = runq->argv->next->next->words;
v = vlook(s)->val;
a = subwords(v, count(v), runq->argv->words, a);
@@ -792,15 +838,15 @@ void
Xcount(void)
{
word *a;
- char *s, *t;
+ char *s, *t, num[12];
int n;
- char num[12];
+
if(count(runq->argv->words)!=1){
Xerror1("variable name not singleton!");
return;
}
- s = Str(runq->argv->words);
n = 0;
+ s = runq->argv->words->word;
for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0';
if(n==0 || *t){
a = vlook(s)->val;
@@ -818,41 +864,25 @@ void
Xlocal(void)
{
if(count(runq->argv->words)!=1){
- Xerror1("variable name must be singleton\n");
+ Xerror1("variable name must be singleton");
return;
}
- runq->local = newvar(Str(runq->argv->words), runq->local);
+ runq->local = newvar(runq->argv->words->word, runq->local);
poplist();
- runq->local->val = globlist(runq->argv->words);
+ runq->local->val = Poplist();
runq->local->changed = 1;
- runq->argv->words = 0;
- poplist();
}
void
Xunlocal(void)
{
- var *v = runq->local, *hid;
+ var *hid, *v = runq->local;
if(v==0)
panic("Xunlocal: no locals!", 0);
runq->local = v->next;
hid = vlook(v->name);
hid->changed = 1;
- free(v->name);
- freewords(v->val);
- free(v);
-}
-
-void
-freewords(word *w)
-{
- word *nw;
- while(w){
- free(w->word);
- nw = w->next;
- free(w);
- w = nw;
- }
+ freevar(v);
}
void
@@ -860,17 +890,16 @@ Xfn(void)
{
var *v;
word *a;
- int end;
- end = runq->code[runq->pc].i;
- for(a = globlist(runq->argv->words);a;a = a->next){
+ int pc = runq->pc;
+ runq->pc = runq->code[pc].i;
+ for(a = runq->argv->words;a;a = a->next){
v = gvlook(a->word);
if(v->fn)
codefree(v->fn);
v->fn = codecopy(runq->code);
- v->pc = runq->pc+2;
+ v->pc = pc+2;
v->fnchanged = 1;
}
- runq->pc = end;
poplist();
}
@@ -889,7 +918,7 @@ Xdelfn(void)
poplist();
}
-char*
+static char*
concstatus(char *s, char *t)
{
static char v[NSTATUS+1];
@@ -918,62 +947,80 @@ Xpipewait(void)
}
}
+static char *promptstr;
+
void
Xrdcmds(void)
{
- struct thread *p = runq;
- word *prompt;
+ thread *p = runq;
- flush(err);
- nerror = 0;
if(flag['s'] && !truestatus())
pfmt(err, "status=%v\n", vlook("status")->val);
- if(runq->iflag){
- prompt = vlook("prompt")->val;
+ flushio(err);
+
+ lex = p->lex;
+ if(p->iflag){
+ word *prompt = vlook("prompt")->val;
if(prompt)
promptstr = prompt->word;
else
promptstr="% ";
}
Noerror();
+ nerror = 0;
if(yyparse()){
- if(!p->iflag || p->eof && !Eintr()){
- closeio(p->cmdfd);
- Xreturn();
- }
- else{
+ if(p->iflag && (!lex->eof || Eintr())){
if(Eintr()){
pchr(err, '\n');
- p->eof = 0;
+ lex->eof = 0;
}
--p->pc; /* go back for next command */
}
}
else{
+ if(lex->eof){
+ dontclose(lex->input->fd);
+ freelexer(lex);
+ p->lex = 0;
+ } else
+ --p->pc; /* re-execute Xrdcmds after codebuf runs */
ntrap = 0; /* avoid double-interrupts during blocked writes */
- --p->pc; /* re-execute Xrdcmds after codebuf runs */
- start(codebuf, 1, runq->local);
+ start(codebuf, 2, p->local, p->redir);
}
+ lex = 0;
freenodes();
}
+void
+pprompt(void)
+{
+ word *prompt;
+
+ if(!runq->iflag)
+ return;
+
+ Prompt(promptstr);
+ doprompt = 0;
+
+ prompt = vlook("prompt")->val;
+ if(prompt && prompt->next)
+ promptstr = prompt->next->word;
+ else
+ promptstr = "\t";
+}
+
char*
-curfile(thread *p)
+srcfile(thread *p)
{
- for(; p != nil; p = p->ret)
- if(p->cmdfile != nil)
- return p->cmdfile;
- return "unknown";
+ return p->code[1].s;
}
void
Xerror(char *s)
{
- if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
- pfmt(err, "rc:%d: %s: %r\n", runq->line, s);
- else
- pfmt(err, "%s:%d: %s: %r\n", curfile(runq), runq->line, s);
- flush(err);
+ pfln(err, srcfile(runq), runq->line);
+ pfmt(err, ": %s: %r\n", s);
+ flushio(err);
setstatus("error");
while(!runq->iflag) Xreturn();
}
@@ -981,11 +1028,9 @@ Xerror(char *s)
void
Xerror1(char *s)
{
- if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
- pfmt(err, "rc:%d: %s\n", runq->line, s);
- else
- pfmt(err, "%s:%d: %s\n", curfile(runq), runq->line, s);
- flush(err);
+ pfln(err, srcfile(runq), runq->line);
+ pfmt(err, ": %s\n", s);
+ flushio(err);
setstatus("error");
while(!runq->iflag) Xreturn();
}
@@ -1014,24 +1059,19 @@ truestatus(void)
}
void
-Xdelhere(void)
-{
- Unlink(runq->code[runq->pc++].s);
-}
-
-void
Xfor(void)
{
- if(runq->argv->words==0){
+ word *a = runq->argv->words;
+ if(a==0){
poplist();
runq->pc = runq->code[runq->pc].i;
}
else{
- freelist(runq->local->val);
- runq->local->val = runq->argv->words;
+ runq->argv->words = a->next;
+ a->next = 0;
+ freewords(runq->local->val);
+ runq->local->val = a;
runq->local->changed = 1;
- runq->argv->words = runq->argv->words->next;
- runq->local->val->next = 0;
runq->pc++;
}
}
@@ -1039,7 +1079,7 @@ Xfor(void)
void
Xglob(void)
{
- globlist(runq->argv->words);
+ globword(runq->argv->words);
}
void
@@ -1047,10 +1087,3 @@ Xsrcline(void)
{
runq->line = runq->code[runq->pc++].i;
}
-
-void
-Xsrcfile(void)
-{
- free(runq->cmdfile);
- runq->cmdfile = strdup(runq->code[runq->pc++].s);
-}