13e12c5d1SDavid du Colombier #include "rc.h"
23e12c5d1SDavid du Colombier #include "getflags.h"
33e12c5d1SDavid du Colombier #include "exec.h"
43e12c5d1SDavid du Colombier #include "io.h"
53e12c5d1SDavid du Colombier #include "fns.h"
63e12c5d1SDavid du Colombier /*
73e12c5d1SDavid du Colombier * Start executing the given code at the given pc with the given redirection
83e12c5d1SDavid du Colombier */
99a747e4fSDavid du Colombier char *argv0="rc";
10dc5a79c1SDavid du Colombier
11dc5a79c1SDavid du Colombier void
start(code * c,int pc,var * local)12dc5a79c1SDavid du Colombier start(code *c, int pc, var *local)
133e12c5d1SDavid du Colombier {
143e12c5d1SDavid du Colombier struct thread *p = new(struct thread);
15dc5a79c1SDavid du Colombier
163e12c5d1SDavid du Colombier p->code = codecopy(c);
173e12c5d1SDavid du Colombier p->pc = pc;
183e12c5d1SDavid du Colombier p->argv = 0;
193e12c5d1SDavid du Colombier p->redir = p->startredir = runq?runq->redir:0;
203e12c5d1SDavid du Colombier p->local = local;
213e12c5d1SDavid du Colombier p->cmdfile = 0;
223e12c5d1SDavid du Colombier p->cmdfd = 0;
233e12c5d1SDavid du Colombier p->eof = 0;
243e12c5d1SDavid du Colombier p->iflag = 0;
253e12c5d1SDavid du Colombier p->lineno = 1;
263e12c5d1SDavid du Colombier p->ret = runq;
273e12c5d1SDavid du Colombier runq = p;
283e12c5d1SDavid du Colombier }
29dc5a79c1SDavid du Colombier
30dc5a79c1SDavid du Colombier word*
newword(char * wd,word * next)31dc5a79c1SDavid du Colombier newword(char *wd, word *next)
323e12c5d1SDavid du Colombier {
333e12c5d1SDavid du Colombier word *p = new(word);
343e12c5d1SDavid du Colombier p->word = strdup(wd);
353e12c5d1SDavid du Colombier p->next = next;
363e12c5d1SDavid du Colombier return p;
373e12c5d1SDavid du Colombier }
38dc5a79c1SDavid du Colombier
39dc5a79c1SDavid du Colombier void
pushword(char * wd)40dc5a79c1SDavid du Colombier pushword(char *wd)
413e12c5d1SDavid du Colombier {
42dc5a79c1SDavid du Colombier if(runq->argv==0)
43dc5a79c1SDavid du Colombier panic("pushword but no argv!", 0);
443e12c5d1SDavid du Colombier runq->argv->words = newword(wd, runq->argv->words);
453e12c5d1SDavid du Colombier }
46dc5a79c1SDavid du Colombier
47dc5a79c1SDavid du Colombier void
popword(void)48dc5a79c1SDavid du Colombier popword(void)
49dc5a79c1SDavid du Colombier {
503e12c5d1SDavid du Colombier word *p;
51dc5a79c1SDavid du Colombier if(runq->argv==0)
52dc5a79c1SDavid du Colombier panic("popword but no argv!", 0);
533e12c5d1SDavid du Colombier p = runq->argv->words;
54dc5a79c1SDavid du Colombier if(p==0)
55dc5a79c1SDavid du Colombier panic("popword but no word!", 0);
563e12c5d1SDavid du Colombier runq->argv->words = p->next;
573e12c5d1SDavid du Colombier efree(p->word);
583e12c5d1SDavid du Colombier efree((char *)p);
593e12c5d1SDavid du Colombier }
60dc5a79c1SDavid du Colombier
61dc5a79c1SDavid du Colombier void
freelist(word * w)62dc5a79c1SDavid du Colombier freelist(word *w)
633e12c5d1SDavid du Colombier {
643e12c5d1SDavid du Colombier word *nw;
653e12c5d1SDavid du Colombier while(w){
663e12c5d1SDavid du Colombier nw = w->next;
673e12c5d1SDavid du Colombier efree(w->word);
683e12c5d1SDavid du Colombier efree((char *)w);
693e12c5d1SDavid du Colombier w = nw;
703e12c5d1SDavid du Colombier }
713e12c5d1SDavid du Colombier }
72dc5a79c1SDavid du Colombier
73dc5a79c1SDavid du Colombier void
pushlist(void)74dc5a79c1SDavid du Colombier pushlist(void)
75dc5a79c1SDavid du Colombier {
763e12c5d1SDavid du Colombier list *p = new(list);
773e12c5d1SDavid du Colombier p->next = runq->argv;
783e12c5d1SDavid du Colombier p->words = 0;
793e12c5d1SDavid du Colombier runq->argv = p;
803e12c5d1SDavid du Colombier }
81dc5a79c1SDavid du Colombier
82dc5a79c1SDavid du Colombier void
poplist(void)83dc5a79c1SDavid du Colombier poplist(void)
84dc5a79c1SDavid du Colombier {
853e12c5d1SDavid du Colombier list *p = runq->argv;
86dc5a79c1SDavid du Colombier if(p==0)
87dc5a79c1SDavid du Colombier panic("poplist but no argv", 0);
883e12c5d1SDavid du Colombier freelist(p->words);
893e12c5d1SDavid du Colombier runq->argv = p->next;
903e12c5d1SDavid du Colombier efree((char *)p);
913e12c5d1SDavid du Colombier }
92dc5a79c1SDavid du Colombier
93dc5a79c1SDavid du Colombier int
count(word * w)94dc5a79c1SDavid du Colombier count(word *w)
953e12c5d1SDavid du Colombier {
963e12c5d1SDavid du Colombier int n;
973e12c5d1SDavid du Colombier for(n = 0;w;n++) w = w->next;
983e12c5d1SDavid du Colombier return n;
993e12c5d1SDavid du Colombier }
100dc5a79c1SDavid du Colombier
101dc5a79c1SDavid du Colombier void
pushredir(int type,int from,int to)102dc5a79c1SDavid du Colombier pushredir(int type, int from, int to)
103dc5a79c1SDavid du Colombier {
1043e12c5d1SDavid du Colombier redir * rp = new(redir);
1053e12c5d1SDavid du Colombier rp->type = type;
1063e12c5d1SDavid du Colombier rp->from = from;
1073e12c5d1SDavid du Colombier rp->to = to;
1083e12c5d1SDavid du Colombier rp->next = runq->redir;
1093e12c5d1SDavid du Colombier runq->redir = rp;
1103e12c5d1SDavid du Colombier }
111dc5a79c1SDavid du Colombier
112dc5a79c1SDavid du Colombier var*
newvar(char * name,var * next)113dc5a79c1SDavid du Colombier newvar(char *name, var *next)
1143e12c5d1SDavid du Colombier {
1153e12c5d1SDavid du Colombier var *v = new(var);
1163e12c5d1SDavid du Colombier v->name = name;
1173e12c5d1SDavid du Colombier v->val = 0;
1183e12c5d1SDavid du Colombier v->fn = 0;
1193e12c5d1SDavid du Colombier v->changed = 0;
1203e12c5d1SDavid du Colombier v->fnchanged = 0;
1213e12c5d1SDavid du Colombier v->next = next;
1223e12c5d1SDavid du Colombier return v;
1233e12c5d1SDavid du Colombier }
1243e12c5d1SDavid du Colombier /*
1253e12c5d1SDavid du Colombier * get command line flags, initialize keywords & traps.
1263e12c5d1SDavid du Colombier * get values from environment.
1273e12c5d1SDavid du Colombier * set $pid, $cflag, $*
1283e12c5d1SDavid du Colombier * fabricate bootstrap code and start it (*=(argv);. /usr/lib/rcmain $*)
1293e12c5d1SDavid du Colombier * start interpreting code
1303e12c5d1SDavid du Colombier */
131dc5a79c1SDavid du Colombier
132dc5a79c1SDavid du Colombier void
main(int argc,char * argv[])133dc5a79c1SDavid du Colombier main(int argc, char *argv[])
1343e12c5d1SDavid du Colombier {
1353e12c5d1SDavid du Colombier code bootstrap[17];
1369a747e4fSDavid du Colombier char num[12], *rcmain;
1373e12c5d1SDavid du Colombier int i;
138dc5a79c1SDavid du Colombier argc = getflags(argc, argv, "SsrdiIlxepvVc:1m:1[command]", 1);
139dc5a79c1SDavid du Colombier if(argc==-1)
140dc5a79c1SDavid du Colombier usage("[file [arg ...]]");
141dc5a79c1SDavid du Colombier if(argv[0][0]=='-')
142dc5a79c1SDavid du Colombier flag['l'] = flagset;
143dc5a79c1SDavid du Colombier if(flag['I'])
144dc5a79c1SDavid du Colombier flag['i'] = 0;
1457dd7cddfSDavid du Colombier else if(flag['i']==0 && argc==1 && Isatty(0)) flag['i'] = flagset;
1469a747e4fSDavid du Colombier rcmain = flag['m']?flag['m'][0]:Rcmain;
1473e12c5d1SDavid du Colombier err = openfd(2);
1483e12c5d1SDavid du Colombier kinit();
1493e12c5d1SDavid du Colombier Trapinit();
1503e12c5d1SDavid du Colombier Vinit();
151dc5a79c1SDavid du Colombier inttoascii(num, mypid = getpid());
1523e12c5d1SDavid du Colombier setvar("pid", newword(num, (word *)0));
1533e12c5d1SDavid du Colombier setvar("cflag", flag['c']?newword(flag['c'][0], (word *)0)
1543e12c5d1SDavid du Colombier :(word *)0);
155219b2ee8SDavid du Colombier setvar("rcname", newword(argv[0], (word *)0));
1563e12c5d1SDavid du Colombier i = 0;
157*4e3613abSDavid du Colombier memset(bootstrap, 0, sizeof bootstrap);
1583e12c5d1SDavid du Colombier bootstrap[i++].i = 1;
1593e12c5d1SDavid du Colombier bootstrap[i++].f = Xmark;
1603e12c5d1SDavid du Colombier bootstrap[i++].f = Xword;
1613e12c5d1SDavid du Colombier bootstrap[i++].s="*";
1623e12c5d1SDavid du Colombier bootstrap[i++].f = Xassign;
1633e12c5d1SDavid du Colombier bootstrap[i++].f = Xmark;
1643e12c5d1SDavid du Colombier bootstrap[i++].f = Xmark;
1653e12c5d1SDavid du Colombier bootstrap[i++].f = Xword;
1663e12c5d1SDavid du Colombier bootstrap[i++].s="*";
1673e12c5d1SDavid du Colombier bootstrap[i++].f = Xdol;
1683e12c5d1SDavid du Colombier bootstrap[i++].f = Xword;
1699a747e4fSDavid du Colombier bootstrap[i++].s = rcmain;
1703e12c5d1SDavid du Colombier bootstrap[i++].f = Xword;
1713e12c5d1SDavid du Colombier bootstrap[i++].s=".";
1723e12c5d1SDavid du Colombier bootstrap[i++].f = Xsimple;
1733e12c5d1SDavid du Colombier bootstrap[i++].f = Xexit;
1743e12c5d1SDavid du Colombier bootstrap[i].i = 0;
1753e12c5d1SDavid du Colombier start(bootstrap, 1, (var *)0);
1763e12c5d1SDavid du Colombier /* prime bootstrap argv */
1773e12c5d1SDavid du Colombier pushlist();
1789a747e4fSDavid du Colombier argv0 = strdup(argv[0]);
1793e12c5d1SDavid du Colombier for(i = argc-1;i!=0;--i) pushword(argv[i]);
1803e12c5d1SDavid du Colombier for(;;){
181dc5a79c1SDavid du Colombier if(flag['r'])
182dc5a79c1SDavid du Colombier pfnc(err, runq);
1833e12c5d1SDavid du Colombier runq->pc++;
1843e12c5d1SDavid du Colombier (*runq->code[runq->pc-1].f)();
185dc5a79c1SDavid du Colombier if(ntrap)
186dc5a79c1SDavid du Colombier dotrap();
1873e12c5d1SDavid du Colombier }
1883e12c5d1SDavid du Colombier }
1893e12c5d1SDavid du Colombier /*
1903e12c5d1SDavid du Colombier * Opcode routines
1913e12c5d1SDavid du Colombier * Arguments on stack (...)
1923e12c5d1SDavid du Colombier * Arguments in line [...]
1933e12c5d1SDavid du Colombier * Code in line with jump around {...}
1943e12c5d1SDavid du Colombier *
1953e12c5d1SDavid du Colombier * Xappend(file)[fd] open file to append
1963e12c5d1SDavid du Colombier * Xassign(name, val) assign val to name
1973e12c5d1SDavid du Colombier * Xasync{... Xexit} make thread for {}, no wait
1983e12c5d1SDavid du Colombier * Xbackq{... Xreturn} make thread for {}, push stdout
1993e12c5d1SDavid du Colombier * Xbang complement condition
2003e12c5d1SDavid du Colombier * Xcase(pat, value){...} exec code on match, leave (value) on
2013e12c5d1SDavid du Colombier * stack
2023e12c5d1SDavid du Colombier * Xclose[i] close file descriptor
2033e12c5d1SDavid du Colombier * Xconc(left, right) concatenate, push results
2043e12c5d1SDavid du Colombier * Xcount(name) push var count
2053e12c5d1SDavid du Colombier * Xdelfn(name) delete function definition
206*4e3613abSDavid du Colombier * Xdelhere
2073e12c5d1SDavid du Colombier * Xdol(name) get variable value
2083e12c5d1SDavid du Colombier * Xdup[i j] dup file descriptor
209*4e3613abSDavid du Colombier * Xeflag
210*4e3613abSDavid du Colombier * Xerror
2113e12c5d1SDavid du Colombier * Xexit rc exits with status
2123e12c5d1SDavid du Colombier * Xfalse{...} execute {} if false
2133e12c5d1SDavid du Colombier * Xfn(name){... Xreturn} define function
2143e12c5d1SDavid du Colombier * Xfor(var, list){... Xreturn} for loop
215*4e3613abSDavid du Colombier * Xglob
216*4e3613abSDavid du Colombier * Xif
217*4e3613abSDavid du Colombier * Xifnot
2183e12c5d1SDavid du Colombier * Xjump[addr] goto
2193e12c5d1SDavid du Colombier * Xlocal(name, val) create local variable, assign value
2203e12c5d1SDavid du Colombier * Xmark mark stack
2213e12c5d1SDavid du Colombier * Xmatch(pat, str) match pattern, set status
2223e12c5d1SDavid du Colombier * Xpipe[i j]{... Xreturn}{... Xreturn} construct a pipe between 2 new threads,
2233e12c5d1SDavid du Colombier * wait for both
2243e12c5d1SDavid du Colombier * Xpipefd[type]{... Xreturn} connect {} to pipe (input or output,
2253e12c5d1SDavid du Colombier * depending on type), push /dev/fd/??
226*4e3613abSDavid du Colombier * Xpipewait
2273e12c5d1SDavid du Colombier * Xpopm(value) pop value from stack
228*4e3613abSDavid du Colombier * Xpopredir
229*4e3613abSDavid du Colombier * Xrdcmds
230*4e3613abSDavid du Colombier * Xrdfn
231119a69faSDavid du Colombier * Xrdwr(file)[fd] open file for reading and writing
2323e12c5d1SDavid du Colombier * Xread(file)[fd] open file to read
233*4e3613abSDavid du Colombier * Xqdol(name) concatenate variable components
2343e12c5d1SDavid du Colombier * Xreturn kill thread
235*4e3613abSDavid du Colombier * Xsimple(args) run command and wait
236*4e3613abSDavid du Colombier * Xsub
2373e12c5d1SDavid du Colombier * Xsubshell{... Xexit} execute {} in a subshell and wait
2383e12c5d1SDavid du Colombier * Xtrue{...} execute {} if true
2393e12c5d1SDavid du Colombier * Xunlocal delete local variable
240*4e3613abSDavid du Colombier * Xwastrue
2413e12c5d1SDavid du Colombier * Xword[string] push string
2423e12c5d1SDavid du Colombier * Xwrite(file)[fd] open file to write
2433e12c5d1SDavid du Colombier */
244dc5a79c1SDavid du Colombier
245dc5a79c1SDavid du Colombier void
Xappend(void)246dc5a79c1SDavid du Colombier Xappend(void)
247dc5a79c1SDavid du Colombier {
2483e12c5d1SDavid du Colombier char *file;
2493e12c5d1SDavid du Colombier int f;
2503e12c5d1SDavid du Colombier switch(count(runq->argv->words)){
251dc5a79c1SDavid du Colombier default:
252dc5a79c1SDavid du Colombier Xerror1(">> requires singleton");
253dc5a79c1SDavid du Colombier return;
254dc5a79c1SDavid du Colombier case 0:
255dc5a79c1SDavid du Colombier Xerror1(">> requires file");
256dc5a79c1SDavid du Colombier return;
257dc5a79c1SDavid du Colombier case 1:
258dc5a79c1SDavid du Colombier break;
2593e12c5d1SDavid du Colombier }
2603e12c5d1SDavid du Colombier file = runq->argv->words->word;
2613e12c5d1SDavid du Colombier if((f = open(file, 1))<0 && (f = Creat(file))<0){
2627dd7cddfSDavid du Colombier pfmt(err, "%s: ", file);
2637dd7cddfSDavid du Colombier Xerror("can't open");
2643e12c5d1SDavid du Colombier return;
2653e12c5d1SDavid du Colombier }
2663e12c5d1SDavid du Colombier Seek(f, 0L, 2);
2673e12c5d1SDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i);
2683e12c5d1SDavid du Colombier runq->pc++;
2693e12c5d1SDavid du Colombier poplist();
2703e12c5d1SDavid du Colombier }
271dc5a79c1SDavid du Colombier
272dc5a79c1SDavid du Colombier void
Xsettrue(void)273dc5a79c1SDavid du Colombier Xsettrue(void)
274dc5a79c1SDavid du Colombier {
275219b2ee8SDavid du Colombier setstatus("");
276219b2ee8SDavid du Colombier }
277dc5a79c1SDavid du Colombier
278dc5a79c1SDavid du Colombier void
Xbang(void)279dc5a79c1SDavid du Colombier Xbang(void)
280dc5a79c1SDavid du Colombier {
2813e12c5d1SDavid du Colombier setstatus(truestatus()?"false":"");
2823e12c5d1SDavid du Colombier }
283dc5a79c1SDavid du Colombier
284dc5a79c1SDavid du Colombier void
Xclose(void)285dc5a79c1SDavid du Colombier Xclose(void)
286dc5a79c1SDavid du Colombier {
2873e12c5d1SDavid du Colombier pushredir(RCLOSE, runq->code[runq->pc].i, 0);
2883e12c5d1SDavid du Colombier runq->pc++;
2893e12c5d1SDavid du Colombier }
290dc5a79c1SDavid du Colombier
291dc5a79c1SDavid du Colombier void
Xdup(void)292dc5a79c1SDavid du Colombier Xdup(void)
293dc5a79c1SDavid du Colombier {
2943e12c5d1SDavid du Colombier pushredir(RDUP, runq->code[runq->pc].i, runq->code[runq->pc+1].i);
2953e12c5d1SDavid du Colombier runq->pc+=2;
2963e12c5d1SDavid du Colombier }
297dc5a79c1SDavid du Colombier
298dc5a79c1SDavid du Colombier void
Xeflag(void)299dc5a79c1SDavid du Colombier Xeflag(void)
300dc5a79c1SDavid du Colombier {
301219b2ee8SDavid du Colombier if(eflagok && !truestatus()) Xexit();
302219b2ee8SDavid du Colombier }
303dc5a79c1SDavid du Colombier
304dc5a79c1SDavid du Colombier void
Xexit(void)305dc5a79c1SDavid du Colombier Xexit(void)
306dc5a79c1SDavid du Colombier {
3073e12c5d1SDavid du Colombier struct var *trapreq;
3083e12c5d1SDavid du Colombier struct word *starval;
3093e12c5d1SDavid du Colombier static int beenhere = 0;
3103e12c5d1SDavid du Colombier if(getpid()==mypid && !beenhere){
3113e12c5d1SDavid du Colombier trapreq = vlook("sigexit");
3123e12c5d1SDavid du Colombier if(trapreq->fn){
3133e12c5d1SDavid du Colombier beenhere = 1;
3143e12c5d1SDavid du Colombier --runq->pc;
315219b2ee8SDavid du Colombier starval = vlook("*")->val;
3163e12c5d1SDavid du Colombier start(trapreq->fn, trapreq->pc, (struct var *)0);
3173e12c5d1SDavid du Colombier runq->local = newvar(strdup("*"), runq->local);
3183e12c5d1SDavid du Colombier runq->local->val = copywords(starval, (struct word *)0);
3193e12c5d1SDavid du Colombier runq->local->changed = 1;
3203e12c5d1SDavid du Colombier runq->redir = runq->startredir = 0;
3213e12c5d1SDavid du Colombier return;
3223e12c5d1SDavid du Colombier }
3233e12c5d1SDavid du Colombier }
3243e12c5d1SDavid du Colombier Exit(getstatus());
3253e12c5d1SDavid du Colombier }
326dc5a79c1SDavid du Colombier
327dc5a79c1SDavid du Colombier void
Xfalse(void)328dc5a79c1SDavid du Colombier Xfalse(void)
329dc5a79c1SDavid du Colombier {
3303e12c5d1SDavid du Colombier if(truestatus()) runq->pc = runq->code[runq->pc].i;
3313e12c5d1SDavid du Colombier else runq->pc++;
3323e12c5d1SDavid du Colombier }
3333e12c5d1SDavid du Colombier int ifnot; /* dynamic if not flag */
334dc5a79c1SDavid du Colombier
335dc5a79c1SDavid du Colombier void
Xifnot(void)336dc5a79c1SDavid du Colombier Xifnot(void)
337dc5a79c1SDavid du Colombier {
3383e12c5d1SDavid du Colombier if(ifnot)
3393e12c5d1SDavid du Colombier runq->pc++;
3403e12c5d1SDavid du Colombier else
3413e12c5d1SDavid du Colombier runq->pc = runq->code[runq->pc].i;
3423e12c5d1SDavid du Colombier }
343dc5a79c1SDavid du Colombier
344dc5a79c1SDavid du Colombier void
Xjump(void)345dc5a79c1SDavid du Colombier Xjump(void)
346dc5a79c1SDavid du Colombier {
3473e12c5d1SDavid du Colombier runq->pc = runq->code[runq->pc].i;
3483e12c5d1SDavid du Colombier }
349dc5a79c1SDavid du Colombier
350dc5a79c1SDavid du Colombier void
Xmark(void)351dc5a79c1SDavid du Colombier Xmark(void)
352dc5a79c1SDavid du Colombier {
3533e12c5d1SDavid du Colombier pushlist();
3543e12c5d1SDavid du Colombier }
355dc5a79c1SDavid du Colombier
356dc5a79c1SDavid du Colombier void
Xpopm(void)357dc5a79c1SDavid du Colombier Xpopm(void)
358dc5a79c1SDavid du Colombier {
3593e12c5d1SDavid du Colombier poplist();
3603e12c5d1SDavid du Colombier }
361dc5a79c1SDavid du Colombier
362dc5a79c1SDavid du Colombier void
Xread(void)363dc5a79c1SDavid du Colombier Xread(void)
364dc5a79c1SDavid du Colombier {
3653e12c5d1SDavid du Colombier char *file;
3663e12c5d1SDavid du Colombier int f;
3673e12c5d1SDavid du Colombier switch(count(runq->argv->words)){
368dc5a79c1SDavid du Colombier default:
369dc5a79c1SDavid du Colombier Xerror1("< requires singleton\n");
370dc5a79c1SDavid du Colombier return;
371dc5a79c1SDavid du Colombier case 0:
372dc5a79c1SDavid du Colombier Xerror1("< requires file\n");
373dc5a79c1SDavid du Colombier return;
374dc5a79c1SDavid du Colombier case 1:
375dc5a79c1SDavid du Colombier break;
3763e12c5d1SDavid du Colombier }
3773e12c5d1SDavid du Colombier file = runq->argv->words->word;
3783e12c5d1SDavid du Colombier if((f = open(file, 0))<0){
3797dd7cddfSDavid du Colombier pfmt(err, "%s: ", file);
3807dd7cddfSDavid du Colombier Xerror("can't open");
3813e12c5d1SDavid du Colombier return;
3823e12c5d1SDavid du Colombier }
3833e12c5d1SDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i);
3843e12c5d1SDavid du Colombier runq->pc++;
3853e12c5d1SDavid du Colombier poplist();
3863e12c5d1SDavid du Colombier }
387dc5a79c1SDavid du Colombier
388dc5a79c1SDavid du Colombier void
Xrdwr(void)389119a69faSDavid du Colombier Xrdwr(void)
390119a69faSDavid du Colombier {
391119a69faSDavid du Colombier char *file;
392119a69faSDavid du Colombier int f;
393119a69faSDavid du Colombier
394119a69faSDavid du Colombier switch(count(runq->argv->words)){
395119a69faSDavid du Colombier default:
396119a69faSDavid du Colombier Xerror1("<> requires singleton\n");
397119a69faSDavid du Colombier return;
398119a69faSDavid du Colombier case 0:
399119a69faSDavid du Colombier Xerror1("<> requires file\n");
400119a69faSDavid du Colombier return;
401119a69faSDavid du Colombier case 1:
402119a69faSDavid du Colombier break;
403119a69faSDavid du Colombier }
404119a69faSDavid du Colombier file = runq->argv->words->word;
405119a69faSDavid du Colombier if((f = open(file, ORDWR))<0){
406119a69faSDavid du Colombier pfmt(err, "%s: ", file);
407119a69faSDavid du Colombier Xerror("can't open");
408119a69faSDavid du Colombier return;
409119a69faSDavid du Colombier }
410119a69faSDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i);
411119a69faSDavid du Colombier runq->pc++;
412119a69faSDavid du Colombier poplist();
413119a69faSDavid du Colombier }
414119a69faSDavid du Colombier
415119a69faSDavid du Colombier void
turfredir(void)416dc5a79c1SDavid du Colombier turfredir(void)
417dc5a79c1SDavid du Colombier {
4183e12c5d1SDavid du Colombier while(runq->redir!=runq->startredir)
4193e12c5d1SDavid du Colombier Xpopredir();
4203e12c5d1SDavid du Colombier }
421dc5a79c1SDavid du Colombier
422dc5a79c1SDavid du Colombier void
Xpopredir(void)423dc5a79c1SDavid du Colombier Xpopredir(void)
424dc5a79c1SDavid du Colombier {
4253e12c5d1SDavid du Colombier struct redir *rp = runq->redir;
426dc5a79c1SDavid du Colombier if(rp==0)
427dc5a79c1SDavid du Colombier panic("turfredir null!", 0);
4283e12c5d1SDavid du Colombier runq->redir = rp->next;
429dc5a79c1SDavid du Colombier if(rp->type==ROPEN)
430dc5a79c1SDavid du Colombier close(rp->from);
4313e12c5d1SDavid du Colombier efree((char *)rp);
4323e12c5d1SDavid du Colombier }
433dc5a79c1SDavid du Colombier
434dc5a79c1SDavid du Colombier void
Xreturn(void)435dc5a79c1SDavid du Colombier Xreturn(void)
436dc5a79c1SDavid du Colombier {
4373e12c5d1SDavid du Colombier struct thread *p = runq;
4383e12c5d1SDavid du Colombier turfredir();
4393e12c5d1SDavid du Colombier while(p->argv) poplist();
4403e12c5d1SDavid du Colombier codefree(p->code);
4413e12c5d1SDavid du Colombier runq = p->ret;
4423e12c5d1SDavid du Colombier efree((char *)p);
443dc5a79c1SDavid du Colombier if(runq==0)
444dc5a79c1SDavid du Colombier Exit(getstatus());
4453e12c5d1SDavid du Colombier }
446dc5a79c1SDavid du Colombier
447dc5a79c1SDavid du Colombier void
Xtrue(void)448dc5a79c1SDavid du Colombier Xtrue(void)
449dc5a79c1SDavid du Colombier {
4503e12c5d1SDavid du Colombier if(truestatus()) runq->pc++;
4513e12c5d1SDavid du Colombier else runq->pc = runq->code[runq->pc].i;
4523e12c5d1SDavid du Colombier }
453dc5a79c1SDavid du Colombier
454dc5a79c1SDavid du Colombier void
Xif(void)455dc5a79c1SDavid du Colombier Xif(void)
456dc5a79c1SDavid du Colombier {
4573e12c5d1SDavid du Colombier ifnot = 1;
4583e12c5d1SDavid du Colombier if(truestatus()) runq->pc++;
4593e12c5d1SDavid du Colombier else runq->pc = runq->code[runq->pc].i;
4603e12c5d1SDavid du Colombier }
461dc5a79c1SDavid du Colombier
462dc5a79c1SDavid du Colombier void
Xwastrue(void)463dc5a79c1SDavid du Colombier Xwastrue(void)
464dc5a79c1SDavid du Colombier {
4653e12c5d1SDavid du Colombier ifnot = 0;
4663e12c5d1SDavid du Colombier }
467dc5a79c1SDavid du Colombier
468dc5a79c1SDavid du Colombier void
Xword(void)469dc5a79c1SDavid du Colombier Xword(void)
470dc5a79c1SDavid du Colombier {
4713e12c5d1SDavid du Colombier pushword(runq->code[runq->pc++].s);
4723e12c5d1SDavid du Colombier }
473dc5a79c1SDavid du Colombier
474dc5a79c1SDavid du Colombier void
Xwrite(void)475dc5a79c1SDavid du Colombier Xwrite(void)
476dc5a79c1SDavid du Colombier {
4773e12c5d1SDavid du Colombier char *file;
4783e12c5d1SDavid du Colombier int f;
4793e12c5d1SDavid du Colombier switch(count(runq->argv->words)){
480dc5a79c1SDavid du Colombier default:
481dc5a79c1SDavid du Colombier Xerror1("> requires singleton\n");
482dc5a79c1SDavid du Colombier return;
483dc5a79c1SDavid du Colombier case 0:
484dc5a79c1SDavid du Colombier Xerror1("> requires file\n");
485dc5a79c1SDavid du Colombier return;
486dc5a79c1SDavid du Colombier case 1:
487dc5a79c1SDavid du Colombier break;
4883e12c5d1SDavid du Colombier }
4893e12c5d1SDavid du Colombier file = runq->argv->words->word;
4903e12c5d1SDavid du Colombier if((f = Creat(file))<0){
4917dd7cddfSDavid du Colombier pfmt(err, "%s: ", file);
4927dd7cddfSDavid du Colombier Xerror("can't open");
4933e12c5d1SDavid du Colombier return;
4943e12c5d1SDavid du Colombier }
4953e12c5d1SDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i);
4963e12c5d1SDavid du Colombier runq->pc++;
4973e12c5d1SDavid du Colombier poplist();
4983e12c5d1SDavid du Colombier }
499dc5a79c1SDavid du Colombier
500dc5a79c1SDavid du Colombier char*
list2str(word * words)501dc5a79c1SDavid du Colombier list2str(word *words)
502dc5a79c1SDavid du Colombier {
5033e12c5d1SDavid du Colombier char *value, *s, *t;
5043e12c5d1SDavid du Colombier int len = 0;
5053e12c5d1SDavid du Colombier word *ap;
5063e12c5d1SDavid du Colombier for(ap = words;ap;ap = ap->next)
5073e12c5d1SDavid du Colombier len+=1+strlen(ap->word);
5083e12c5d1SDavid du Colombier value = emalloc(len+1);
5093e12c5d1SDavid du Colombier s = value;
5103e12c5d1SDavid du Colombier for(ap = words;ap;ap = ap->next){
5113e12c5d1SDavid du Colombier for(t = ap->word;*t;) *s++=*t++;
5123e12c5d1SDavid du Colombier *s++=' ';
5133e12c5d1SDavid du Colombier }
514dc5a79c1SDavid du Colombier if(s==value)
515dc5a79c1SDavid du Colombier *s='\0';
5163e12c5d1SDavid du Colombier else s[-1]='\0';
5173e12c5d1SDavid du Colombier return value;
5183e12c5d1SDavid du Colombier }
519dc5a79c1SDavid du Colombier
520dc5a79c1SDavid du Colombier void
Xmatch(void)521dc5a79c1SDavid du Colombier Xmatch(void)
522dc5a79c1SDavid du Colombier {
5233e12c5d1SDavid du Colombier word *p;
5243e12c5d1SDavid du Colombier char *subject;
5253e12c5d1SDavid du Colombier subject = list2str(runq->argv->words);
5263e12c5d1SDavid du Colombier setstatus("no match");
5273e12c5d1SDavid du Colombier for(p = runq->argv->next->words;p;p = p->next)
5283e12c5d1SDavid du Colombier if(match(subject, p->word, '\0')){
5293e12c5d1SDavid du Colombier setstatus("");
5303e12c5d1SDavid du Colombier break;
5313e12c5d1SDavid du Colombier }
5323e12c5d1SDavid du Colombier efree(subject);
5333e12c5d1SDavid du Colombier poplist();
5343e12c5d1SDavid du Colombier poplist();
5353e12c5d1SDavid du Colombier }
536dc5a79c1SDavid du Colombier
537dc5a79c1SDavid du Colombier void
Xcase(void)538dc5a79c1SDavid du Colombier Xcase(void)
539dc5a79c1SDavid du Colombier {
5403e12c5d1SDavid du Colombier word *p;
5413e12c5d1SDavid du Colombier char *s;
5423e12c5d1SDavid du Colombier int ok = 0;
5433e12c5d1SDavid du Colombier s = list2str(runq->argv->next->words);
5443e12c5d1SDavid du Colombier for(p = runq->argv->words;p;p = p->next){
5453e12c5d1SDavid du Colombier if(match(s, p->word, '\0')){
5463e12c5d1SDavid du Colombier ok = 1;
5473e12c5d1SDavid du Colombier break;
5483e12c5d1SDavid du Colombier }
5493e12c5d1SDavid du Colombier }
5503e12c5d1SDavid du Colombier efree(s);
5513e12c5d1SDavid du Colombier if(ok)
5523e12c5d1SDavid du Colombier runq->pc++;
5533e12c5d1SDavid du Colombier else
5543e12c5d1SDavid du Colombier runq->pc = runq->code[runq->pc].i;
5553e12c5d1SDavid du Colombier poplist();
5563e12c5d1SDavid du Colombier }
557dc5a79c1SDavid du Colombier
558dc5a79c1SDavid du Colombier word*
conclist(word * lp,word * rp,word * tail)559dc5a79c1SDavid du Colombier conclist(word *lp, word *rp, word *tail)
5603e12c5d1SDavid du Colombier {
5613e12c5d1SDavid du Colombier char *buf;
5623e12c5d1SDavid du Colombier word *v;
5633e12c5d1SDavid du Colombier if(lp->next || rp->next)
564276e7d6dSDavid du Colombier tail = conclist(lp->next==0? lp: lp->next,
565276e7d6dSDavid du Colombier rp->next==0? rp: rp->next, tail);
566276e7d6dSDavid du Colombier buf = emalloc(strlen(lp->word)+strlen((char *)rp->word)+1);
5673e12c5d1SDavid du Colombier strcpy(buf, lp->word);
5683e12c5d1SDavid du Colombier strcat(buf, rp->word);
5693e12c5d1SDavid du Colombier v = newword(buf, tail);
5703e12c5d1SDavid du Colombier efree(buf);
5713e12c5d1SDavid du Colombier return v;
5723e12c5d1SDavid du Colombier }
573dc5a79c1SDavid du Colombier
574dc5a79c1SDavid du Colombier void
Xconc(void)575dc5a79c1SDavid du Colombier Xconc(void)
576dc5a79c1SDavid du Colombier {
5773e12c5d1SDavid du Colombier word *lp = runq->argv->words;
5783e12c5d1SDavid du Colombier word *rp = runq->argv->next->words;
5793e12c5d1SDavid du Colombier word *vp = runq->argv->next->next->words;
5803e12c5d1SDavid du Colombier int lc = count(lp), rc = count(rp);
5813e12c5d1SDavid du Colombier if(lc!=0 || rc!=0){
5823e12c5d1SDavid du Colombier if(lc==0 || rc==0){
5839a747e4fSDavid du Colombier Xerror1("null list in concatenation");
5843e12c5d1SDavid du Colombier return;
5853e12c5d1SDavid du Colombier }
5863e12c5d1SDavid du Colombier if(lc!=1 && rc!=1 && lc!=rc){
5879a747e4fSDavid du Colombier Xerror1("mismatched list lengths in concatenation");
5883e12c5d1SDavid du Colombier return;
5893e12c5d1SDavid du Colombier }
5903e12c5d1SDavid du Colombier vp = conclist(lp, rp, vp);
5913e12c5d1SDavid du Colombier }
5923e12c5d1SDavid du Colombier poplist();
5933e12c5d1SDavid du Colombier poplist();
5943e12c5d1SDavid du Colombier runq->argv->words = vp;
5953e12c5d1SDavid du Colombier }
596dc5a79c1SDavid du Colombier
597dc5a79c1SDavid du Colombier void
Xassign(void)598dc5a79c1SDavid du Colombier Xassign(void)
599dc5a79c1SDavid du Colombier {
6003e12c5d1SDavid du Colombier var *v;
6013e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){
6029a747e4fSDavid du Colombier Xerror1("variable name not singleton!");
6033e12c5d1SDavid du Colombier return;
6043e12c5d1SDavid du Colombier }
6053e12c5d1SDavid du Colombier deglob(runq->argv->words->word);
6063e12c5d1SDavid du Colombier v = vlook(runq->argv->words->word);
6073e12c5d1SDavid du Colombier poplist();
6083e12c5d1SDavid du Colombier globlist();
6093e12c5d1SDavid du Colombier freewords(v->val);
6103e12c5d1SDavid du Colombier v->val = runq->argv->words;
6113e12c5d1SDavid du Colombier v->changed = 1;
6123e12c5d1SDavid du Colombier runq->argv->words = 0;
6133e12c5d1SDavid du Colombier poplist();
6143e12c5d1SDavid du Colombier }
6153e12c5d1SDavid du Colombier /*
6163e12c5d1SDavid du Colombier * copy arglist a, adding the copy to the front of tail
6173e12c5d1SDavid du Colombier */
618dc5a79c1SDavid du Colombier
619dc5a79c1SDavid du Colombier word*
copywords(word * a,word * tail)620dc5a79c1SDavid du Colombier copywords(word *a, word *tail)
6213e12c5d1SDavid du Colombier {
6223e12c5d1SDavid du Colombier word *v = 0, **end;
6233e12c5d1SDavid du Colombier for(end=&v;a;a = a->next,end=&(*end)->next)
6243e12c5d1SDavid du Colombier *end = newword(a->word, 0);
6253e12c5d1SDavid du Colombier *end = tail;
6263e12c5d1SDavid du Colombier return v;
6273e12c5d1SDavid du Colombier }
628dc5a79c1SDavid du Colombier
629dc5a79c1SDavid du Colombier void
Xdol(void)630dc5a79c1SDavid du Colombier Xdol(void)
631dc5a79c1SDavid du Colombier {
6323e12c5d1SDavid du Colombier word *a, *star;
6333e12c5d1SDavid du Colombier char *s, *t;
6343e12c5d1SDavid du Colombier int n;
6353e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){
6369a747e4fSDavid du Colombier Xerror1("variable name not singleton!");
6373e12c5d1SDavid du Colombier return;
6383e12c5d1SDavid du Colombier }
6393e12c5d1SDavid du Colombier s = runq->argv->words->word;
6403e12c5d1SDavid du Colombier deglob(s);
6413e12c5d1SDavid du Colombier n = 0;
64299eb86a7SDavid du Colombier for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0';
6433e12c5d1SDavid du Colombier a = runq->argv->next->words;
6443e12c5d1SDavid du Colombier if(n==0 || *t)
6453e12c5d1SDavid du Colombier a = copywords(vlook(s)->val, a);
6463e12c5d1SDavid du Colombier else{
6473e12c5d1SDavid du Colombier star = vlook("*")->val;
6483e12c5d1SDavid du Colombier if(star && 1<=n && n<=count(star)){
64999eb86a7SDavid du Colombier while(--n) star = star->next;
6503e12c5d1SDavid du Colombier a = newword(star->word, a);
6513e12c5d1SDavid du Colombier }
6523e12c5d1SDavid du Colombier }
6533e12c5d1SDavid du Colombier poplist();
6543e12c5d1SDavid du Colombier runq->argv->words = a;
6553e12c5d1SDavid du Colombier }
656dc5a79c1SDavid du Colombier
657dc5a79c1SDavid du Colombier void
Xqdol(void)658dc5a79c1SDavid du Colombier Xqdol(void)
659dc5a79c1SDavid du Colombier {
6603e12c5d1SDavid du Colombier word *a, *p;
6613e12c5d1SDavid du Colombier char *s;
6623e12c5d1SDavid du Colombier int n;
6633e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){
6649a747e4fSDavid du Colombier Xerror1("variable name not singleton!");
6653e12c5d1SDavid du Colombier return;
6663e12c5d1SDavid du Colombier }
6673e12c5d1SDavid du Colombier s = runq->argv->words->word;
6683e12c5d1SDavid du Colombier deglob(s);
6693e12c5d1SDavid du Colombier a = vlook(s)->val;
6703e12c5d1SDavid du Colombier poplist();
6713e12c5d1SDavid du Colombier n = count(a);
6723e12c5d1SDavid du Colombier if(n==0){
6733e12c5d1SDavid du Colombier pushword("");
6743e12c5d1SDavid du Colombier return;
6753e12c5d1SDavid du Colombier }
6763e12c5d1SDavid du Colombier for(p = a;p;p = p->next) n+=strlen(p->word);
6773e12c5d1SDavid du Colombier s = emalloc(n);
6783e12c5d1SDavid du Colombier if(a){
6793e12c5d1SDavid du Colombier strcpy(s, a->word);
6803e12c5d1SDavid du Colombier for(p = a->next;p;p = p->next){
6813e12c5d1SDavid du Colombier strcat(s, " ");
6823e12c5d1SDavid du Colombier strcat(s, p->word);
6833e12c5d1SDavid du Colombier }
6843e12c5d1SDavid du Colombier }
6853e12c5d1SDavid du Colombier else
6863e12c5d1SDavid du Colombier s[0]='\0';
6873e12c5d1SDavid du Colombier pushword(s);
6883e12c5d1SDavid du Colombier efree(s);
6893e12c5d1SDavid du Colombier }
690dc5a79c1SDavid du Colombier
691dc5a79c1SDavid du Colombier word*
copynwords(word * a,word * tail,int n)6925e061cc0SDavid du Colombier copynwords(word *a, word *tail, int n)
6935e061cc0SDavid du Colombier {
6945e061cc0SDavid du Colombier word *v, **end;
6955e061cc0SDavid du Colombier
6965e061cc0SDavid du Colombier v = 0;
6975e061cc0SDavid du Colombier end = &v;
6985e061cc0SDavid du Colombier while(n-- > 0){
6995e061cc0SDavid du Colombier *end = newword(a->word, 0);
7005e061cc0SDavid du Colombier end = &(*end)->next;
7015e061cc0SDavid du Colombier a = a->next;
7025e061cc0SDavid du Colombier }
7035e061cc0SDavid du Colombier *end = tail;
7045e061cc0SDavid du Colombier return v;
7055e061cc0SDavid du Colombier }
7065e061cc0SDavid du Colombier
7075e061cc0SDavid du Colombier word*
subwords(word * val,int len,word * sub,word * a)708dc5a79c1SDavid du Colombier subwords(word *val, int len, word *sub, word *a)
7093e12c5d1SDavid du Colombier {
7105e061cc0SDavid du Colombier int n, m;
7113e12c5d1SDavid du Colombier char *s;
712dc5a79c1SDavid du Colombier if(!sub)
713dc5a79c1SDavid du Colombier return a;
7143e12c5d1SDavid du Colombier a = subwords(val, len, sub->next, a);
7153e12c5d1SDavid du Colombier s = sub->word;
7163e12c5d1SDavid du Colombier deglob(s);
7175e061cc0SDavid du Colombier m = 0;
7183e12c5d1SDavid du Colombier n = 0;
7195e061cc0SDavid du Colombier while('0'<=*s && *s<='9')
7205e061cc0SDavid du Colombier n = n*10+ *s++ -'0';
7215e061cc0SDavid du Colombier if(*s == '-'){
7225e061cc0SDavid du Colombier if(*++s == 0)
7235e061cc0SDavid du Colombier m = len - n;
7245e061cc0SDavid du Colombier else{
7255e061cc0SDavid du Colombier while('0'<=*s && *s<='9')
7265e061cc0SDavid du Colombier m = m*10+ *s++ -'0';
7275e061cc0SDavid du Colombier m -= n;
7285e061cc0SDavid du Colombier }
7295e061cc0SDavid du Colombier }
7305e061cc0SDavid du Colombier if(n<1 || n>len || m<0)
731dc5a79c1SDavid du Colombier return a;
7325e061cc0SDavid du Colombier if(n+m>len)
7335e061cc0SDavid du Colombier m = len-n;
7345e061cc0SDavid du Colombier while(--n > 0)
7355e061cc0SDavid du Colombier val = val->next;
7365e061cc0SDavid du Colombier return copynwords(val, a, m+1);
7373e12c5d1SDavid du Colombier }
738dc5a79c1SDavid du Colombier
739dc5a79c1SDavid du Colombier void
Xsub(void)740dc5a79c1SDavid du Colombier Xsub(void)
741dc5a79c1SDavid du Colombier {
7423e12c5d1SDavid du Colombier word *a, *v;
7433e12c5d1SDavid du Colombier char *s;
7443e12c5d1SDavid du Colombier if(count(runq->argv->next->words)!=1){
7459a747e4fSDavid du Colombier Xerror1("variable name not singleton!");
7463e12c5d1SDavid du Colombier return;
7473e12c5d1SDavid du Colombier }
7483e12c5d1SDavid du Colombier s = runq->argv->next->words->word;
7493e12c5d1SDavid du Colombier deglob(s);
7503e12c5d1SDavid du Colombier a = runq->argv->next->next->words;
7513e12c5d1SDavid du Colombier v = vlook(s)->val;
7523e12c5d1SDavid du Colombier a = subwords(v, count(v), runq->argv->words, a);
7533e12c5d1SDavid du Colombier poplist();
7543e12c5d1SDavid du Colombier poplist();
7553e12c5d1SDavid du Colombier runq->argv->words = a;
7563e12c5d1SDavid du Colombier }
757dc5a79c1SDavid du Colombier
758dc5a79c1SDavid du Colombier void
Xcount(void)759dc5a79c1SDavid du Colombier Xcount(void)
760dc5a79c1SDavid du Colombier {
7613e12c5d1SDavid du Colombier word *a;
7623e12c5d1SDavid du Colombier char *s, *t;
7633e12c5d1SDavid du Colombier int n;
7643e12c5d1SDavid du Colombier char num[12];
7653e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){
7669a747e4fSDavid du Colombier Xerror1("variable name not singleton!");
7673e12c5d1SDavid du Colombier return;
7683e12c5d1SDavid du Colombier }
7693e12c5d1SDavid du Colombier s = runq->argv->words->word;
7703e12c5d1SDavid du Colombier deglob(s);
7713e12c5d1SDavid du Colombier n = 0;
7723e12c5d1SDavid du Colombier for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0';
7733e12c5d1SDavid du Colombier if(n==0 || *t){
7743e12c5d1SDavid du Colombier a = vlook(s)->val;
775dc5a79c1SDavid du Colombier inttoascii(num, count(a));
7763e12c5d1SDavid du Colombier }
7773e12c5d1SDavid du Colombier else{
7783e12c5d1SDavid du Colombier a = vlook("*")->val;
779dc5a79c1SDavid du Colombier inttoascii(num, a && 1<=n && n<=count(a)?1:0);
7803e12c5d1SDavid du Colombier }
7813e12c5d1SDavid du Colombier poplist();
7823e12c5d1SDavid du Colombier pushword(num);
7833e12c5d1SDavid du Colombier }
784dc5a79c1SDavid du Colombier
785dc5a79c1SDavid du Colombier void
Xlocal(void)786dc5a79c1SDavid du Colombier Xlocal(void)
787dc5a79c1SDavid du Colombier {
7883e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){
7899a747e4fSDavid du Colombier Xerror1("variable name must be singleton\n");
7903e12c5d1SDavid du Colombier return;
7913e12c5d1SDavid du Colombier }
7923e12c5d1SDavid du Colombier deglob(runq->argv->words->word);
7933e12c5d1SDavid du Colombier runq->local = newvar(strdup(runq->argv->words->word), runq->local);
7943e12c5d1SDavid du Colombier poplist();
795fed0fa9eSDavid du Colombier globlist();
796fed0fa9eSDavid du Colombier runq->local->val = runq->argv->words;
797fed0fa9eSDavid du Colombier runq->local->changed = 1;
798fed0fa9eSDavid du Colombier runq->argv->words = 0;
7993e12c5d1SDavid du Colombier poplist();
8003e12c5d1SDavid du Colombier }
801dc5a79c1SDavid du Colombier
802dc5a79c1SDavid du Colombier void
Xunlocal(void)803dc5a79c1SDavid du Colombier Xunlocal(void)
804dc5a79c1SDavid du Colombier {
8053e12c5d1SDavid du Colombier var *v = runq->local, *hid;
806dc5a79c1SDavid du Colombier if(v==0)
807dc5a79c1SDavid du Colombier panic("Xunlocal: no locals!", 0);
8083e12c5d1SDavid du Colombier runq->local = v->next;
8093e12c5d1SDavid du Colombier hid = vlook(v->name);
8103e12c5d1SDavid du Colombier hid->changed = 1;
8113e12c5d1SDavid du Colombier efree(v->name);
8123e12c5d1SDavid du Colombier freewords(v->val);
8133e12c5d1SDavid du Colombier efree((char *)v);
8143e12c5d1SDavid du Colombier }
815dc5a79c1SDavid du Colombier
816dc5a79c1SDavid du Colombier void
freewords(word * w)817dc5a79c1SDavid du Colombier freewords(word *w)
8183e12c5d1SDavid du Colombier {
8193e12c5d1SDavid du Colombier word *nw;
8203e12c5d1SDavid du Colombier while(w){
8213e12c5d1SDavid du Colombier efree(w->word);
8223e12c5d1SDavid du Colombier nw = w->next;
8233e12c5d1SDavid du Colombier efree((char *)w);
8243e12c5d1SDavid du Colombier w = nw;
8253e12c5d1SDavid du Colombier }
8263e12c5d1SDavid du Colombier }
827dc5a79c1SDavid du Colombier
828dc5a79c1SDavid du Colombier void
Xfn(void)829dc5a79c1SDavid du Colombier Xfn(void)
830dc5a79c1SDavid du Colombier {
8313e12c5d1SDavid du Colombier var *v;
8323e12c5d1SDavid du Colombier word *a;
8333e12c5d1SDavid du Colombier int end;
8343e12c5d1SDavid du Colombier end = runq->code[runq->pc].i;
835fed0fa9eSDavid du Colombier globlist();
8363e12c5d1SDavid du Colombier for(a = runq->argv->words;a;a = a->next){
8373e12c5d1SDavid du Colombier v = gvlook(a->word);
838dc5a79c1SDavid du Colombier if(v->fn)
839dc5a79c1SDavid du Colombier codefree(v->fn);
8403e12c5d1SDavid du Colombier v->fn = codecopy(runq->code);
8413e12c5d1SDavid du Colombier v->pc = runq->pc+2;
8423e12c5d1SDavid du Colombier v->fnchanged = 1;
8433e12c5d1SDavid du Colombier }
8443e12c5d1SDavid du Colombier runq->pc = end;
8453e12c5d1SDavid du Colombier poplist();
8463e12c5d1SDavid du Colombier }
847dc5a79c1SDavid du Colombier
848dc5a79c1SDavid du Colombier void
Xdelfn(void)849dc5a79c1SDavid du Colombier Xdelfn(void)
850dc5a79c1SDavid du Colombier {
8513e12c5d1SDavid du Colombier var *v;
8523e12c5d1SDavid du Colombier word *a;
8533e12c5d1SDavid du Colombier for(a = runq->argv->words;a;a = a->next){
8543e12c5d1SDavid du Colombier v = gvlook(a->word);
855dc5a79c1SDavid du Colombier if(v->fn)
856dc5a79c1SDavid du Colombier codefree(v->fn);
8573e12c5d1SDavid du Colombier v->fn = 0;
8583e12c5d1SDavid du Colombier v->fnchanged = 1;
8593e12c5d1SDavid du Colombier }
8603e12c5d1SDavid du Colombier poplist();
8613e12c5d1SDavid du Colombier }
862dc5a79c1SDavid du Colombier
863dc5a79c1SDavid du Colombier char*
concstatus(char * s,char * t)864dc5a79c1SDavid du Colombier concstatus(char *s, char *t)
8653e12c5d1SDavid du Colombier {
8663e12c5d1SDavid du Colombier static char v[NSTATUS+1];
8673e12c5d1SDavid du Colombier int n = strlen(s);
8683e12c5d1SDavid du Colombier strncpy(v, s, NSTATUS);
8693e12c5d1SDavid du Colombier if(n<NSTATUS){
8703e12c5d1SDavid du Colombier v[n]='|';
8713e12c5d1SDavid du Colombier strncpy(v+n+1, t, NSTATUS-n-1);
8723e12c5d1SDavid du Colombier }
8733e12c5d1SDavid du Colombier v[NSTATUS]='\0';
8743e12c5d1SDavid du Colombier return v;
8753e12c5d1SDavid du Colombier }
876dc5a79c1SDavid du Colombier
877dc5a79c1SDavid du Colombier void
Xpipewait(void)878dc5a79c1SDavid du Colombier Xpipewait(void)
879dc5a79c1SDavid du Colombier {
8803e12c5d1SDavid du Colombier char status[NSTATUS+1];
8813e12c5d1SDavid du Colombier if(runq->pid==-1)
8823e12c5d1SDavid du Colombier setstatus(concstatus(runq->status, getstatus()));
8833e12c5d1SDavid du Colombier else{
8843e12c5d1SDavid du Colombier strncpy(status, getstatus(), NSTATUS);
8853e12c5d1SDavid du Colombier status[NSTATUS]='\0';
8863e12c5d1SDavid du Colombier Waitfor(runq->pid, 1);
8873e12c5d1SDavid du Colombier runq->pid=-1;
8883e12c5d1SDavid du Colombier setstatus(concstatus(getstatus(), status));
8893e12c5d1SDavid du Colombier }
8903e12c5d1SDavid du Colombier }
891dc5a79c1SDavid du Colombier
892dc5a79c1SDavid du Colombier void
Xrdcmds(void)893dc5a79c1SDavid du Colombier Xrdcmds(void)
894dc5a79c1SDavid du Colombier {
8953e12c5d1SDavid du Colombier struct thread *p = runq;
8963e12c5d1SDavid du Colombier word *prompt;
8973e12c5d1SDavid du Colombier flush(err);
8983e12c5d1SDavid du Colombier nerror = 0;
8993e12c5d1SDavid du Colombier if(flag['s'] && !truestatus())
9003e12c5d1SDavid du Colombier pfmt(err, "status=%v\n", vlook("status")->val);
9013e12c5d1SDavid du Colombier if(runq->iflag){
9023e12c5d1SDavid du Colombier prompt = vlook("prompt")->val;
9033e12c5d1SDavid du Colombier if(prompt)
9043e12c5d1SDavid du Colombier promptstr = prompt->word;
9053e12c5d1SDavid du Colombier else
9063e12c5d1SDavid du Colombier promptstr="% ";
9073e12c5d1SDavid du Colombier }
9083e12c5d1SDavid du Colombier Noerror();
9093e12c5d1SDavid du Colombier if(yyparse()){
9103e12c5d1SDavid du Colombier if(!p->iflag || p->eof && !Eintr()){
911dc5a79c1SDavid du Colombier if(p->cmdfile)
912dc5a79c1SDavid du Colombier efree(p->cmdfile);
9133e12c5d1SDavid du Colombier closeio(p->cmdfd);
9143e12c5d1SDavid du Colombier Xreturn(); /* should this be omitted? */
9153e12c5d1SDavid du Colombier }
9163e12c5d1SDavid du Colombier else{
9173e12c5d1SDavid du Colombier if(Eintr()){
9183e12c5d1SDavid du Colombier pchr(err, '\n');
9193e12c5d1SDavid du Colombier p->eof = 0;
9203e12c5d1SDavid du Colombier }
9213e12c5d1SDavid du Colombier --p->pc; /* go back for next command */
9223e12c5d1SDavid du Colombier }
9233e12c5d1SDavid du Colombier }
9243e12c5d1SDavid du Colombier else{
9257dd7cddfSDavid du Colombier ntrap = 0; /* avoid double-interrupts during blocked writes */
9263e12c5d1SDavid du Colombier --p->pc; /* re-execute Xrdcmds after codebuf runs */
9273e12c5d1SDavid du Colombier start(codebuf, 1, runq->local);
9283e12c5d1SDavid du Colombier }
9293e12c5d1SDavid du Colombier freenodes();
9303e12c5d1SDavid du Colombier }
931dc5a79c1SDavid du Colombier
932dc5a79c1SDavid du Colombier void
Xerror(char * s)933dc5a79c1SDavid du Colombier Xerror(char *s)
9343e12c5d1SDavid du Colombier {
9359a747e4fSDavid du Colombier if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
9369a747e4fSDavid du Colombier pfmt(err, "rc: %s: %r\n", s);
9379a747e4fSDavid du Colombier else
9389a747e4fSDavid du Colombier pfmt(err, "rc (%s): %s: %r\n", argv0, s);
9399a747e4fSDavid du Colombier flush(err);
940d3907fe5SDavid du Colombier setstatus("error");
9419a747e4fSDavid du Colombier while(!runq->iflag) Xreturn();
9429a747e4fSDavid du Colombier }
943dc5a79c1SDavid du Colombier
944dc5a79c1SDavid du Colombier void
Xerror1(char * s)945dc5a79c1SDavid du Colombier Xerror1(char *s)
9469a747e4fSDavid du Colombier {
9479a747e4fSDavid du Colombier if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
9483e12c5d1SDavid du Colombier pfmt(err, "rc: %s\n", s);
9499a747e4fSDavid du Colombier else
9509a747e4fSDavid du Colombier pfmt(err, "rc (%s): %s\n", argv0, s);
9513e12c5d1SDavid du Colombier flush(err);
952d3907fe5SDavid du Colombier setstatus("error");
9533e12c5d1SDavid du Colombier while(!runq->iflag) Xreturn();
9543e12c5d1SDavid du Colombier }
955dc5a79c1SDavid du Colombier
956dc5a79c1SDavid du Colombier void
setstatus(char * s)957dc5a79c1SDavid du Colombier setstatus(char *s)
9583e12c5d1SDavid du Colombier {
9593e12c5d1SDavid du Colombier setvar("status", newword(s, (word *)0));
9603e12c5d1SDavid du Colombier }
961dc5a79c1SDavid du Colombier
962dc5a79c1SDavid du Colombier char*
getstatus(void)963dc5a79c1SDavid du Colombier getstatus(void)
964dc5a79c1SDavid du Colombier {
9653e12c5d1SDavid du Colombier var *status = vlook("status");
9663e12c5d1SDavid du Colombier return status->val?status->val->word:"";
9673e12c5d1SDavid du Colombier }
968dc5a79c1SDavid du Colombier
969dc5a79c1SDavid du Colombier int
truestatus(void)970dc5a79c1SDavid du Colombier truestatus(void)
971dc5a79c1SDavid du Colombier {
9723e12c5d1SDavid du Colombier char *s;
9733e12c5d1SDavid du Colombier for(s = getstatus();*s;s++)
974dc5a79c1SDavid du Colombier if(*s!='|' && *s!='0')
975dc5a79c1SDavid du Colombier return 0;
9763e12c5d1SDavid du Colombier return 1;
9773e12c5d1SDavid du Colombier }
978dc5a79c1SDavid du Colombier
979dc5a79c1SDavid du Colombier void
Xdelhere(void)980dc5a79c1SDavid du Colombier Xdelhere(void)
981dc5a79c1SDavid du Colombier {
9823e12c5d1SDavid du Colombier Unlink(runq->code[runq->pc++].s);
9833e12c5d1SDavid du Colombier }
984dc5a79c1SDavid du Colombier
985dc5a79c1SDavid du Colombier void
Xfor(void)986dc5a79c1SDavid du Colombier Xfor(void)
987dc5a79c1SDavid du Colombier {
9883e12c5d1SDavid du Colombier if(runq->argv->words==0){
9893e12c5d1SDavid du Colombier poplist();
9903e12c5d1SDavid du Colombier runq->pc = runq->code[runq->pc].i;
9913e12c5d1SDavid du Colombier }
9923e12c5d1SDavid du Colombier else{
9933e12c5d1SDavid du Colombier freelist(runq->local->val);
9943e12c5d1SDavid du Colombier runq->local->val = runq->argv->words;
9953e12c5d1SDavid du Colombier runq->local->changed = 1;
9963e12c5d1SDavid du Colombier runq->argv->words = runq->argv->words->next;
9973e12c5d1SDavid du Colombier runq->local->val->next = 0;
9983e12c5d1SDavid du Colombier runq->pc++;
9993e12c5d1SDavid du Colombier }
10003e12c5d1SDavid du Colombier }
1001dc5a79c1SDavid du Colombier
1002dc5a79c1SDavid du Colombier void
Xglob(void)1003dc5a79c1SDavid du Colombier Xglob(void)
1004dc5a79c1SDavid du Colombier {
10053e12c5d1SDavid du Colombier globlist();
10063e12c5d1SDavid du Colombier }
1007