1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006 |
- #include "rc.h"
- #include "getflags.h"
- #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)
- {
- struct thread *p = new(struct thread);
- p->code = codecopy(c);
- p->pc = pc;
- p->argv = 0;
- p->redir = p->startredir = runq?runq->redir:0;
- p->local = local;
- p->cmdfile = 0;
- p->cmdfd = 0;
- p->eof = 0;
- p->iflag = 0;
- p->lineno = 1;
- p->ret = runq;
- runq = p;
- }
- word*
- newword(char *wd, word *next)
- {
- word *p = new(word);
- p->word = strdup(wd);
- p->next = next;
- return p;
- }
- void
- pushword(char *wd)
- {
- if(runq->argv==0)
- panic("pushword but no argv!", 0);
- runq->argv->words = newword(wd, runq->argv->words);
- }
- void
- popword(void)
- {
- word *p;
- if(runq->argv==0)
- panic("popword but no argv!", 0);
- p = runq->argv->words;
- if(p==0)
- panic("popword but no word!", 0);
- runq->argv->words = p->next;
- efree(p->word);
- efree((char *)p);
- }
- void
- freelist(word *w)
- {
- word *nw;
- while(w){
- nw = w->next;
- efree(w->word);
- efree((char *)w);
- w = nw;
- }
- }
- void
- pushlist(void)
- {
- list *p = new(list);
- p->next = runq->argv;
- p->words = 0;
- runq->argv = p;
- }
- void
- poplist(void)
- {
- list *p = runq->argv;
- if(p==0)
- panic("poplist but no argv", 0);
- freelist(p->words);
- runq->argv = p->next;
- efree((char *)p);
- }
- int
- count(word *w)
- {
- int n;
- for(n = 0;w;n++) w = w->next;
- return n;
- }
- void
- pushredir(int type, int from, int to)
- {
- redir * rp = new(redir);
- rp->type = type;
- rp->from = from;
- rp->to = to;
- rp->next = runq->redir;
- runq->redir = rp;
- }
- var*
- newvar(char *name, var *next)
- {
- var *v = new(var);
- v->name = 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 $*)
- * start interpreting code
- */
- void
- main(int argc, char *argv[])
- {
- code bootstrap[17];
- char num[12], *rcmain;
- int i;
- argc = getflags(argc, argv, "SsrdiIlxepvVc:1m:1[command]", 1);
- if(argc==-1)
- usage("[file [arg ...]]");
- if(argv[0][0]=='-')
- flag['l'] = flagset;
- 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);
- kinit();
- Trapinit();
- Vinit();
- inttoascii(num, mypid = getpid());
- setvar("pid", newword(num, (word *)0));
- setvar("cflag", flag['c']?newword(flag['c'][0], (word *)0)
- :(word *)0);
- setvar("rcname", newword(argv[0], (word *)0));
- i = 0;
- memset(bootstrap, 0, sizeof bootstrap);
- 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);
- /* prime bootstrap argv */
- pushlist();
- argv0 = strdup(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)();
- if(ntrap)
- dotrap();
- }
- }
- /*
- * Opcode routines
- * Arguments on stack (...)
- * Arguments in line [...]
- * Code in line with jump around {...}
- *
- * Xappend(file)[fd] open file to append
- * Xassign(name, val) assign val to name
- * Xasync{... Xexit} make thread for {}, no wait
- * Xbackq{... Xreturn} make thread for {}, push stdout
- * Xbang complement condition
- * Xcase(pat, value){...} exec code on match, leave (value) on
- * stack
- * Xclose[i] close file descriptor
- * Xconc(left, right) concatenate, push results
- * Xcount(name) push var count
- * Xdelfn(name) delete function definition
- * Xdelhere
- * Xdol(name) get variable value
- * Xdup[i j] dup file descriptor
- * Xeflag
- * Xerror
- * Xexit rc exits with status
- * Xfalse{...} execute {} if false
- * Xfn(name){... Xreturn} define function
- * Xfor(var, list){... Xreturn} for loop
- * Xglob
- * Xif
- * Xifnot
- * Xjump[addr] goto
- * Xlocal(name, val) create local variable, assign value
- * Xmark mark stack
- * Xmatch(pat, str) match pattern, set status
- * Xpipe[i j]{... Xreturn}{... Xreturn} construct a pipe between 2 new threads,
- * wait for both
- * Xpipefd[type]{... Xreturn} connect {} to pipe (input or output,
- * depending on type), push /dev/fd/??
- * Xpipewait
- * Xpopm(value) pop value from stack
- * Xpopredir
- * Xrdcmds
- * Xrdfn
- * Xrdwr(file)[fd] open file for reading and writing
- * Xread(file)[fd] open file to read
- * Xqdol(name) concatenate variable components
- * Xreturn kill thread
- * Xsimple(args) run command and wait
- * Xsub
- * Xsubshell{... Xexit} execute {} in a subshell and wait
- * Xtrue{...} execute {} if true
- * Xunlocal delete local variable
- * Xwastrue
- * Xword[string] push string
- * Xwrite(file)[fd] open file to write
- */
- void
- Xappend(void)
- {
- char *file;
- int f;
- switch(count(runq->argv->words)){
- default:
- Xerror1(">> requires singleton");
- return;
- case 0:
- Xerror1(">> requires file");
- return;
- case 1:
- break;
- }
- file = runq->argv->words->word;
- if((f = open(file, 1))<0 && (f = Creat(file))<0){
- pfmt(err, "%s: ", file);
- Xerror("can't open");
- return;
- }
- Seek(f, 0L, 2);
- pushredir(ROPEN, f, runq->code[runq->pc].i);
- runq->pc++;
- poplist();
- }
- void
- Xsettrue(void)
- {
- setstatus("");
- }
- void
- Xbang(void)
- {
- setstatus(truestatus()?"false":"");
- }
- void
- Xclose(void)
- {
- pushredir(RCLOSE, runq->code[runq->pc].i, 0);
- runq->pc++;
- }
- void
- Xdup(void)
- {
- pushredir(RDUP, runq->code[runq->pc].i, runq->code[runq->pc+1].i);
- runq->pc+=2;
- }
- void
- Xeflag(void)
- {
- if(eflagok && !truestatus()) Xexit();
- }
- void
- Xexit(void)
- {
- struct var *trapreq;
- struct word *starval;
- static int beenhere = 0;
- if(getpid()==mypid && !beenhere){
- trapreq = vlook("sigexit");
- if(trapreq->fn){
- beenhere = 1;
- --runq->pc;
- starval = vlook("*")->val;
- start(trapreq->fn, trapreq->pc, (struct var *)0);
- runq->local = newvar(strdup("*"), runq->local);
- runq->local->val = copywords(starval, (struct word *)0);
- runq->local->changed = 1;
- runq->redir = runq->startredir = 0;
- return;
- }
- }
- Exit(getstatus());
- }
- void
- Xfalse(void)
- {
- if(truestatus()) runq->pc = runq->code[runq->pc].i;
- else runq->pc++;
- }
- int ifnot; /* dynamic if not flag */
- void
- Xifnot(void)
- {
- if(ifnot)
- runq->pc++;
- else
- runq->pc = runq->code[runq->pc].i;
- }
- void
- Xjump(void)
- {
- runq->pc = runq->code[runq->pc].i;
- }
- void
- Xmark(void)
- {
- pushlist();
- }
- void
- Xpopm(void)
- {
- poplist();
- }
- void
- Xread(void)
- {
- char *file;
- int f;
- switch(count(runq->argv->words)){
- default:
- Xerror1("< requires singleton\n");
- return;
- case 0:
- Xerror1("< requires file\n");
- return;
- case 1:
- break;
- }
- file = runq->argv->words->word;
- if((f = open(file, 0))<0){
- pfmt(err, "%s: ", file);
- Xerror("can't open");
- return;
- }
- pushredir(ROPEN, f, runq->code[runq->pc].i);
- runq->pc++;
- poplist();
- }
- void
- Xrdwr(void)
- {
- char *file;
- int f;
- switch(count(runq->argv->words)){
- default:
- Xerror1("<> requires singleton\n");
- return;
- case 0:
- Xerror1("<> requires file\n");
- return;
- case 1:
- break;
- }
- file = runq->argv->words->word;
- if((f = open(file, ORDWR))<0){
- pfmt(err, "%s: ", file);
- Xerror("can't open");
- return;
- }
- pushredir(ROPEN, f, runq->code[runq->pc].i);
- runq->pc++;
- poplist();
- }
- void
- turfredir(void)
- {
- while(runq->redir!=runq->startredir)
- Xpopredir();
- }
- void
- Xpopredir(void)
- {
- struct redir *rp = runq->redir;
- if(rp==0)
- panic("turfredir null!", 0);
- runq->redir = rp->next;
- if(rp->type==ROPEN)
- close(rp->from);
- efree((char *)rp);
- }
- void
- Xreturn(void)
- {
- struct thread *p = runq;
- turfredir();
- while(p->argv) poplist();
- codefree(p->code);
- runq = p->ret;
- efree((char *)p);
- if(runq==0)
- Exit(getstatus());
- }
- void
- Xtrue(void)
- {
- if(truestatus()) runq->pc++;
- else runq->pc = runq->code[runq->pc].i;
- }
- void
- Xif(void)
- {
- ifnot = 1;
- if(truestatus()) runq->pc++;
- else runq->pc = runq->code[runq->pc].i;
- }
- void
- Xwastrue(void)
- {
- ifnot = 0;
- }
- void
- Xword(void)
- {
- pushword(runq->code[runq->pc++].s);
- }
- void
- Xwrite(void)
- {
- char *file;
- int f;
- switch(count(runq->argv->words)){
- default:
- Xerror1("> requires singleton\n");
- return;
- case 0:
- Xerror1("> requires file\n");
- return;
- case 1:
- break;
- }
- file = runq->argv->words->word;
- if((f = Creat(file))<0){
- pfmt(err, "%s: ", file);
- Xerror("can't open");
- return;
- }
- pushredir(ROPEN, f, runq->code[runq->pc].i);
- runq->pc++;
- 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);
- setstatus("no match");
- for(p = runq->argv->next->words;p;p = p->next)
- if(match(subject, p->word, '\0')){
- setstatus("");
- break;
- }
- efree(subject);
- poplist();
- poplist();
- }
- void
- Xcase(void)
- {
- word *p;
- char *s;
- int ok = 0;
- s = list2str(runq->argv->next->words);
- for(p = runq->argv->words;p;p = p->next){
- if(match(s, p->word, '\0')){
- ok = 1;
- break;
- }
- }
- efree(s);
- if(ok)
- runq->pc++;
- else
- runq->pc = runq->code[runq->pc].i;
- poplist();
- }
- word*
- conclist(word *lp, word *rp, word *tail)
- {
- char *buf;
- word *v;
- if(lp->next || rp->next)
- tail = conclist(lp->next==0? lp: lp->next,
- rp->next==0? rp: rp->next, tail);
- buf = emalloc(strlen(lp->word)+strlen((char *)rp->word)+1);
- strcpy(buf, lp->word);
- strcat(buf, rp->word);
- v = newword(buf, tail);
- efree(buf);
- return v;
- }
- void
- Xconc(void)
- {
- word *lp = runq->argv->words;
- word *rp = runq->argv->next->words;
- word *vp = runq->argv->next->next->words;
- int lc = count(lp), rc = count(rp);
- if(lc!=0 || rc!=0){
- if(lc==0 || rc==0){
- Xerror1("null list in concatenation");
- return;
- }
- if(lc!=1 && rc!=1 && lc!=rc){
- Xerror1("mismatched list lengths in concatenation");
- return;
- }
- vp = conclist(lp, rp, vp);
- }
- poplist();
- poplist();
- runq->argv->words = vp;
- }
- void
- Xassign(void)
- {
- var *v;
- if(count(runq->argv->words)!=1){
- Xerror1("variable name not singleton!");
- return;
- }
- deglob(runq->argv->words->word);
- v = vlook(runq->argv->words->word);
- poplist();
- globlist();
- freewords(v->val);
- v->val = runq->argv->words;
- 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;
- return v;
- }
- void
- Xdol(void)
- {
- word *a, *star;
- char *s, *t;
- int n;
- if(count(runq->argv->words)!=1){
- Xerror1("variable name not singleton!");
- return;
- }
- s = runq->argv->words->word;
- deglob(s);
- n = 0;
- for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0';
- a = runq->argv->next->words;
- if(n==0 || *t)
- a = copywords(vlook(s)->val, a);
- else{
- star = vlook("*")->val;
- if(star && 1<=n && n<=count(star)){
- while(--n) star = star->next;
- a = newword(star->word, a);
- }
- }
- poplist();
- runq->argv->words = a;
- }
- void
- Xqdol(void)
- {
- word *a, *p;
- char *s;
- int n;
- if(count(runq->argv->words)!=1){
- Xerror1("variable name not singleton!");
- return;
- }
- s = runq->argv->words->word;
- deglob(s);
- a = vlook(s)->val;
- poplist();
- n = count(a);
- if(n==0){
- pushword("");
- return;
- }
- for(p = a;p;p = p->next) n+=strlen(p->word);
- s = emalloc(n);
- if(a){
- strcpy(s, a->word);
- for(p = a->next;p;p = p->next){
- strcat(s, " ");
- strcat(s, p->word);
- }
- }
- else
- s[0]='\0';
- pushword(s);
- efree(s);
- }
- word*
- copynwords(word *a, word *tail, int n)
- {
- word *v, **end;
-
- v = 0;
- end = &v;
- while(n-- > 0){
- *end = newword(a->word, 0);
- end = &(*end)->next;
- a = a->next;
- }
- *end = tail;
- return v;
- }
- word*
- subwords(word *val, int len, word *sub, word *a)
- {
- int n, m;
- char *s;
- if(!sub)
- return a;
- a = subwords(val, len, sub->next, a);
- s = sub->word;
- deglob(s);
- m = 0;
- n = 0;
- while('0'<=*s && *s<='9')
- n = n*10+ *s++ -'0';
- if(*s == '-'){
- if(*++s == 0)
- m = len - n;
- else{
- while('0'<=*s && *s<='9')
- m = m*10+ *s++ -'0';
- m -= n;
- }
- }
- if(n<1 || n>len || m<0)
- return a;
- if(n+m>len)
- m = len-n;
- while(--n > 0)
- val = val->next;
- return copynwords(val, a, m+1);
- }
- void
- Xsub(void)
- {
- word *a, *v;
- char *s;
- if(count(runq->argv->next->words)!=1){
- Xerror1("variable name not singleton!");
- return;
- }
- s = runq->argv->next->words->word;
- deglob(s);
- a = runq->argv->next->next->words;
- v = vlook(s)->val;
- a = subwords(v, count(v), runq->argv->words, a);
- poplist();
- poplist();
- runq->argv->words = a;
- }
- void
- Xcount(void)
- {
- word *a;
- char *s, *t;
- int n;
- char num[12];
- if(count(runq->argv->words)!=1){
- Xerror1("variable name not singleton!");
- return;
- }
- s = runq->argv->words->word;
- deglob(s);
- n = 0;
- for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0';
- if(n==0 || *t){
- a = vlook(s)->val;
- inttoascii(num, count(a));
- }
- else{
- a = vlook("*")->val;
- inttoascii(num, a && 1<=n && n<=count(a)?1:0);
- }
- poplist();
- pushword(num);
- }
- void
- Xlocal(void)
- {
- if(count(runq->argv->words)!=1){
- Xerror1("variable name must be singleton\n");
- return;
- }
- deglob(runq->argv->words->word);
- runq->local = newvar(strdup(runq->argv->words->word), runq->local);
- poplist();
- globlist();
- runq->local->val = runq->argv->words;
- runq->local->changed = 1;
- runq->argv->words = 0;
- poplist();
- }
- void
- Xunlocal(void)
- {
- var *v = runq->local, *hid;
- if(v==0)
- panic("Xunlocal: no locals!", 0);
- runq->local = v->next;
- hid = vlook(v->name);
- hid->changed = 1;
- efree(v->name);
- freewords(v->val);
- efree((char *)v);
- }
- void
- freewords(word *w)
- {
- word *nw;
- while(w){
- efree(w->word);
- nw = w->next;
- efree((char *)w);
- w = nw;
- }
- }
- void
- Xfn(void)
- {
- var *v;
- word *a;
- int end;
- end = runq->code[runq->pc].i;
- globlist();
- 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->fnchanged = 1;
- }
- runq->pc = end;
- poplist();
- }
- void
- Xdelfn(void)
- {
- var *v;
- word *a;
- for(a = runq->argv->words;a;a = a->next){
- v = gvlook(a->word);
- if(v->fn)
- codefree(v->fn);
- v->fn = 0;
- v->fnchanged = 1;
- }
- poplist();
- }
- char*
- concstatus(char *s, char *t)
- {
- static char v[NSTATUS+1];
- int n = strlen(s);
- strncpy(v, s, NSTATUS);
- if(n<NSTATUS){
- v[n]='|';
- strncpy(v+n+1, t, NSTATUS-n-1);
- }
- v[NSTATUS]='\0';
- return v;
- }
- void
- Xpipewait(void)
- {
- char status[NSTATUS+1];
- if(runq->pid==-1)
- setstatus(concstatus(runq->status, getstatus()));
- else{
- strncpy(status, getstatus(), NSTATUS);
- status[NSTATUS]='\0';
- Waitfor(runq->pid, 1);
- runq->pid=-1;
- setstatus(concstatus(getstatus(), status));
- }
- }
- void
- Xrdcmds(void)
- {
- struct thread *p = runq;
- word *prompt;
- flush(err);
- nerror = 0;
- if(flag['s'] && !truestatus())
- pfmt(err, "status=%v\n", vlook("status")->val);
- if(runq->iflag){
- prompt = vlook("prompt")->val;
- if(prompt)
- promptstr = prompt->word;
- else
- promptstr="% ";
- }
- Noerror();
- if(yyparse()){
- if(!p->iflag || p->eof && !Eintr()){
- if(p->cmdfile)
- efree(p->cmdfile);
- closeio(p->cmdfd);
- Xreturn(); /* should this be omitted? */
- }
- else{
- if(Eintr()){
- pchr(err, '\n');
- p->eof = 0;
- }
- --p->pc; /* go back for next command */
- }
- }
- else{
- ntrap = 0; /* avoid double-interrupts during blocked writes */
- --p->pc; /* re-execute Xrdcmds after codebuf runs */
- start(codebuf, 1, runq->local);
- }
- freenodes();
- }
- void
- Xerror(char *s)
- {
- if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
- pfmt(err, "rc: %s: %r\n", s);
- else
- pfmt(err, "rc (%s): %s: %r\n", argv0, s);
- flush(err);
- setstatus("error");
- while(!runq->iflag) Xreturn();
- }
- void
- Xerror1(char *s)
- {
- if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
- pfmt(err, "rc: %s\n", s);
- else
- pfmt(err, "rc (%s): %s\n", argv0, s);
- flush(err);
- setstatus("error");
- while(!runq->iflag) Xreturn();
- }
- void
- setstatus(char *s)
- {
- setvar("status", newword(s, (word *)0));
- }
- char*
- getstatus(void)
- {
- var *status = vlook("status");
- return status->val?status->val->word:"";
- }
- int
- truestatus(void)
- {
- char *s;
- for(s = getstatus();*s;s++)
- if(*s!='|' && *s!='0')
- return 0;
- return 1;
- }
- void
- Xdelhere(void)
- {
- Unlink(runq->code[runq->pc++].s);
- }
- void
- Xfor(void)
- {
- if(runq->argv->words==0){
- poplist();
- runq->pc = runq->code[runq->pc].i;
- }
- else{
- freelist(runq->local->val);
- runq->local->val = runq->argv->words;
- runq->local->changed = 1;
- runq->argv->words = runq->argv->words->next;
- runq->local->val->next = 0;
- runq->pc++;
- }
- }
- void
- Xglob(void)
- {
- globlist();
- }
|