13e12c5d1SDavid du Colombier #include "rc.h"
23e12c5d1SDavid du Colombier #include "exec.h"
33e12c5d1SDavid du Colombier #include "io.h"
43e12c5d1SDavid du Colombier #include "fns.h"
5c6df1444SDavid du Colombier
6c6df1444SDavid du Colombier char flagset[] = "<flag>"; /* anything non-nil will do */
7c6df1444SDavid du Colombier char *flag[NFLAG];
8c6df1444SDavid du Colombier
93e12c5d1SDavid du Colombier /*
103e12c5d1SDavid du Colombier * Start executing the given code at the given pc with the given redirection
113e12c5d1SDavid du Colombier */
12c6df1444SDavid du Colombier char *argv0;
13dc5a79c1SDavid du Colombier
14dc5a79c1SDavid du Colombier void
start(code * c,int pc,var * local)15dc5a79c1SDavid du Colombier start(code *c, int pc, var *local)
163e12c5d1SDavid du Colombier {
173e12c5d1SDavid du Colombier struct thread *p = new(struct thread);
18dc5a79c1SDavid du Colombier
193e12c5d1SDavid du Colombier p->code = codecopy(c);
203e12c5d1SDavid du Colombier p->pc = pc;
213e12c5d1SDavid du Colombier p->argv = 0;
223e12c5d1SDavid du Colombier p->redir = p->startredir = runq?runq->redir:0;
233e12c5d1SDavid du Colombier p->local = local;
243e12c5d1SDavid du Colombier p->cmdfile = 0;
253e12c5d1SDavid du Colombier p->cmdfd = 0;
263e12c5d1SDavid du Colombier p->eof = 0;
273e12c5d1SDavid du Colombier p->iflag = 0;
283e12c5d1SDavid du Colombier p->lineno = 1;
293e12c5d1SDavid du Colombier p->ret = runq;
303e12c5d1SDavid du Colombier runq = p;
313e12c5d1SDavid du Colombier }
32dc5a79c1SDavid du Colombier
33dc5a79c1SDavid du Colombier word*
newword(char * wd,word * next)34dc5a79c1SDavid du Colombier newword(char *wd, word *next)
353e12c5d1SDavid du Colombier {
363e12c5d1SDavid du Colombier word *p = new(word);
373e12c5d1SDavid du Colombier p->word = strdup(wd);
383e12c5d1SDavid du Colombier p->next = next;
393e12c5d1SDavid du Colombier return p;
403e12c5d1SDavid du Colombier }
41dc5a79c1SDavid du Colombier
42dc5a79c1SDavid du Colombier void
pushword(char * wd)43dc5a79c1SDavid du Colombier pushword(char *wd)
443e12c5d1SDavid du Colombier {
45dc5a79c1SDavid du Colombier if(runq->argv==0)
46dc5a79c1SDavid du Colombier panic("pushword but no argv!", 0);
473e12c5d1SDavid du Colombier runq->argv->words = newword(wd, runq->argv->words);
483e12c5d1SDavid du Colombier }
49dc5a79c1SDavid du Colombier
50dc5a79c1SDavid du Colombier void
popword(void)51dc5a79c1SDavid du Colombier popword(void)
52dc5a79c1SDavid du Colombier {
533e12c5d1SDavid du Colombier word *p;
54dc5a79c1SDavid du Colombier if(runq->argv==0)
55dc5a79c1SDavid du Colombier panic("popword but no argv!", 0);
563e12c5d1SDavid du Colombier p = runq->argv->words;
57dc5a79c1SDavid du Colombier if(p==0)
58dc5a79c1SDavid du Colombier panic("popword but no word!", 0);
593e12c5d1SDavid du Colombier runq->argv->words = p->next;
603e12c5d1SDavid du Colombier efree(p->word);
613e12c5d1SDavid du Colombier efree((char *)p);
623e12c5d1SDavid du Colombier }
63dc5a79c1SDavid du Colombier
64dc5a79c1SDavid du Colombier void
freelist(word * w)65dc5a79c1SDavid du Colombier freelist(word *w)
663e12c5d1SDavid du Colombier {
673e12c5d1SDavid du Colombier word *nw;
683e12c5d1SDavid du Colombier while(w){
693e12c5d1SDavid du Colombier nw = w->next;
703e12c5d1SDavid du Colombier efree(w->word);
713e12c5d1SDavid du Colombier efree((char *)w);
723e12c5d1SDavid du Colombier w = nw;
733e12c5d1SDavid du Colombier }
743e12c5d1SDavid du Colombier }
75dc5a79c1SDavid du Colombier
76dc5a79c1SDavid du Colombier void
pushlist(void)77dc5a79c1SDavid du Colombier pushlist(void)
78dc5a79c1SDavid du Colombier {
793e12c5d1SDavid du Colombier list *p = new(list);
803e12c5d1SDavid du Colombier p->next = runq->argv;
813e12c5d1SDavid du Colombier p->words = 0;
823e12c5d1SDavid du Colombier runq->argv = p;
833e12c5d1SDavid du Colombier }
84dc5a79c1SDavid du Colombier
85dc5a79c1SDavid du Colombier void
poplist(void)86dc5a79c1SDavid du Colombier poplist(void)
87dc5a79c1SDavid du Colombier {
883e12c5d1SDavid du Colombier list *p = runq->argv;
89dc5a79c1SDavid du Colombier if(p==0)
90dc5a79c1SDavid du Colombier panic("poplist but no argv", 0);
913e12c5d1SDavid du Colombier freelist(p->words);
923e12c5d1SDavid du Colombier runq->argv = p->next;
933e12c5d1SDavid du Colombier efree((char *)p);
943e12c5d1SDavid du Colombier }
95dc5a79c1SDavid du Colombier
96dc5a79c1SDavid du Colombier int
count(word * w)97dc5a79c1SDavid du Colombier count(word *w)
983e12c5d1SDavid du Colombier {
993e12c5d1SDavid du Colombier int n;
1003e12c5d1SDavid du Colombier for(n = 0;w;n++) w = w->next;
1013e12c5d1SDavid du Colombier return n;
1023e12c5d1SDavid du Colombier }
103dc5a79c1SDavid du Colombier
104dc5a79c1SDavid du Colombier void
pushredir(int type,int from,int to)105dc5a79c1SDavid du Colombier pushredir(int type, int from, int to)
106dc5a79c1SDavid du Colombier {
1073e12c5d1SDavid du Colombier redir * rp = new(redir);
1083e12c5d1SDavid du Colombier rp->type = type;
1093e12c5d1SDavid du Colombier rp->from = from;
1103e12c5d1SDavid du Colombier rp->to = to;
1113e12c5d1SDavid du Colombier rp->next = runq->redir;
1123e12c5d1SDavid du Colombier runq->redir = rp;
1133e12c5d1SDavid du Colombier }
114dc5a79c1SDavid du Colombier
115*4446a870SDavid du Colombier void
shuffleredir(void)116*4446a870SDavid du Colombier shuffleredir(void)
117*4446a870SDavid du Colombier {
118*4446a870SDavid du Colombier redir **rr, *rp;
119*4446a870SDavid du Colombier
120*4446a870SDavid du Colombier rp = runq->redir;
121*4446a870SDavid du Colombier if(rp==0)
122*4446a870SDavid du Colombier return;
123*4446a870SDavid du Colombier runq->redir = rp->next;
124*4446a870SDavid du Colombier rp->next = runq->startredir;
125*4446a870SDavid du Colombier for(rr = &runq->redir; *rr != rp->next; rr = &((*rr)->next))
126*4446a870SDavid du Colombier ;
127*4446a870SDavid du Colombier *rr = rp;
128*4446a870SDavid du Colombier }
129*4446a870SDavid du Colombier
130dc5a79c1SDavid du Colombier var*
newvar(char * name,var * next)131dc5a79c1SDavid du Colombier newvar(char *name, var *next)
1323e12c5d1SDavid du Colombier {
1333e12c5d1SDavid du Colombier var *v = new(var);
134c6df1444SDavid du Colombier
135c6df1444SDavid du Colombier assert(name != nil);
1363e12c5d1SDavid du Colombier v->name = name;
1373e12c5d1SDavid du Colombier v->val = 0;
1383e12c5d1SDavid du Colombier v->fn = 0;
1393e12c5d1SDavid du Colombier v->changed = 0;
1403e12c5d1SDavid du Colombier v->fnchanged = 0;
1413e12c5d1SDavid du Colombier v->next = next;
1423e12c5d1SDavid du Colombier return v;
1433e12c5d1SDavid du Colombier }
144c6df1444SDavid du Colombier
145c6df1444SDavid du Colombier /* fabricate bootstrap code (*=(argv);. /rc/lib/rcmain $*; exit) */
146c6df1444SDavid du Colombier static void
loadboot(code * base,int nel,char * rcmain)147c6df1444SDavid du Colombier loadboot(code *base, int nel, char *rcmain)
148c6df1444SDavid du Colombier {
149c6df1444SDavid du Colombier code *bs;
150c6df1444SDavid du Colombier
151c6df1444SDavid du Colombier bs = base;
152c6df1444SDavid du Colombier bs++->i = 1; /* reference count */
153c6df1444SDavid du Colombier bs++->f = Xmark; /* "* = $*" */
154c6df1444SDavid du Colombier bs++->f = Xword;
155c6df1444SDavid du Colombier bs++->s="*";
156c6df1444SDavid du Colombier bs++->f = Xassign;
157c6df1444SDavid du Colombier bs++->f = Xmark;
158c6df1444SDavid du Colombier bs++->f = Xmark;
159c6df1444SDavid du Colombier bs++->f = Xword;
160c6df1444SDavid du Colombier bs++->s="*";
161c6df1444SDavid du Colombier bs++->f = Xdol;
162c6df1444SDavid du Colombier bs++->f = Xword;
163c6df1444SDavid du Colombier bs++->s = rcmain; /* ". /rc/lib/rcmain $*" */
164c6df1444SDavid du Colombier bs++->f = Xword;
165c6df1444SDavid du Colombier bs++->s=".";
166c6df1444SDavid du Colombier bs++->f = Xsimple;
167c6df1444SDavid du Colombier bs++->f = Xexit; /* exit */
168c6df1444SDavid du Colombier bs++->i = 0; /* not reached */
169c6df1444SDavid du Colombier if (bs > base + nel)
170c6df1444SDavid du Colombier panic("bootstrap array too small", 0);
171c6df1444SDavid du Colombier }
172c6df1444SDavid du Colombier
173c6df1444SDavid du Colombier void
usage(void)174c6df1444SDavid du Colombier usage(void)
175c6df1444SDavid du Colombier {
176c6df1444SDavid du Colombier pfmt(err, "Usage: rc [-srdiIlxepvV] [-c arg] [-m command] "
177c6df1444SDavid du Colombier "[file [arg ...]]\n");
178c6df1444SDavid du Colombier Exit("bad flags");
179c6df1444SDavid du Colombier }
180c6df1444SDavid du Colombier
1813e12c5d1SDavid du Colombier /*
1823e12c5d1SDavid du Colombier * get command line flags, initialize keywords & traps.
1833e12c5d1SDavid du Colombier * get values from environment.
1843e12c5d1SDavid du Colombier * set $pid, $cflag, $*
185c6df1444SDavid du Colombier * fabricate bootstrap code and start it
1863e12c5d1SDavid du Colombier * start interpreting code
1873e12c5d1SDavid du Colombier */
188dc5a79c1SDavid du Colombier void
main(int argc,char * argv[])189dc5a79c1SDavid du Colombier main(int argc, char *argv[])
1903e12c5d1SDavid du Colombier {
1913e12c5d1SDavid du Colombier code bootstrap[17];
192c6df1444SDavid du Colombier char num[12];
1933e12c5d1SDavid du Colombier int i;
194c6df1444SDavid du Colombier
195c6df1444SDavid du Colombier err = openfd(2);
196c6df1444SDavid du Colombier ARGBEGIN {
197c6df1444SDavid du Colombier case 'd': case 'e': case 'i': case 'l':
198c6df1444SDavid du Colombier case 'p': case 'r': case 's': case 'v':
199c6df1444SDavid du Colombier case 'x': case 'I': case 'V':
200c6df1444SDavid du Colombier flag[ARGC()] = flagset;
201c6df1444SDavid du Colombier break;
202c6df1444SDavid du Colombier case 'c':
203c6df1444SDavid du Colombier case 'm':
204c6df1444SDavid du Colombier if (flag[ARGC()])
205c6df1444SDavid du Colombier usage();
206c6df1444SDavid du Colombier flag[ARGC()] = EARGF(usage());
207c6df1444SDavid du Colombier break;
208c6df1444SDavid du Colombier default:
209c6df1444SDavid du Colombier usage();
210c6df1444SDavid du Colombier break;
211c6df1444SDavid du Colombier } ARGEND
212c6df1444SDavid du Colombier if(argc < 0)
213c6df1444SDavid du Colombier usage();
214c6df1444SDavid du Colombier if(argv0 == nil)
215c6df1444SDavid du Colombier argv0 = "rc";
216c6df1444SDavid du Colombier if(argv0[0]=='-') /* login shell? */
217dc5a79c1SDavid du Colombier flag['l'] = flagset;
218dc5a79c1SDavid du Colombier if(flag['I'])
219dc5a79c1SDavid du Colombier flag['i'] = 0;
220c6df1444SDavid du Colombier else if(flag['i']==0 && argc==0 && Isatty(0))
221c6df1444SDavid du Colombier flag['i'] = flagset; /* force interactive */
222c6df1444SDavid du Colombier
2233e12c5d1SDavid du Colombier kinit();
2243e12c5d1SDavid du Colombier Trapinit();
2253e12c5d1SDavid du Colombier Vinit();
226dc5a79c1SDavid du Colombier inttoascii(num, mypid = getpid());
2273e12c5d1SDavid du Colombier setvar("pid", newword(num, (word *)0));
228c6df1444SDavid du Colombier setvar("cflag", flag['c']? newword(flag['c'], (word *)0): (word *)0);
229c6df1444SDavid du Colombier setvar("rcname", newword(argv0, (word *)0));
230c6df1444SDavid du Colombier
231c6df1444SDavid du Colombier loadboot(bootstrap, nelem(bootstrap), (flag['m']? flag['m']: Rcmain));
2323e12c5d1SDavid du Colombier start(bootstrap, 1, (var *)0);
2333e12c5d1SDavid du Colombier /* prime bootstrap argv */
2343e12c5d1SDavid du Colombier pushlist();
235c6df1444SDavid du Colombier for(i = argc-1; i >= 0; --i)
236c6df1444SDavid du Colombier pushword(argv[i]);
2373e12c5d1SDavid du Colombier for(;;){
238dc5a79c1SDavid du Colombier if(flag['r'])
239dc5a79c1SDavid du Colombier pfnc(err, runq);
2403e12c5d1SDavid du Colombier runq->pc++;
2413e12c5d1SDavid du Colombier (*runq->code[runq->pc-1].f)();
242dc5a79c1SDavid du Colombier if(ntrap)
243dc5a79c1SDavid du Colombier dotrap();
2443e12c5d1SDavid du Colombier }
2453e12c5d1SDavid du Colombier }
246c6df1444SDavid du Colombier
2473e12c5d1SDavid du Colombier /*
2483e12c5d1SDavid du Colombier * Opcode routines
2493e12c5d1SDavid du Colombier * Arguments on stack (...)
2503e12c5d1SDavid du Colombier * Arguments in line [...]
2513e12c5d1SDavid du Colombier * Code in line with jump around {...}
2523e12c5d1SDavid du Colombier *
2533e12c5d1SDavid du Colombier * Xappend(file)[fd] open file to append
2543e12c5d1SDavid du Colombier * Xassign(name, val) assign val to name
2553e12c5d1SDavid du Colombier * Xasync{... Xexit} make thread for {}, no wait
256dbee7877SDavid du Colombier * Xbackq(split){... Xreturn} make thread for {}, push stdout
2573e12c5d1SDavid du Colombier * Xbang complement condition
2583e12c5d1SDavid du Colombier * Xcase(pat, value){...} exec code on match, leave (value) on
2593e12c5d1SDavid du Colombier * stack
2603e12c5d1SDavid du Colombier * Xclose[i] close file descriptor
2613e12c5d1SDavid du Colombier * Xconc(left, right) concatenate, push results
2623e12c5d1SDavid du Colombier * Xcount(name) push var count
2633e12c5d1SDavid du Colombier * Xdelfn(name) delete function definition
2644e3613abSDavid du Colombier * Xdelhere
2653e12c5d1SDavid du Colombier * Xdol(name) get variable value
2663e12c5d1SDavid du Colombier * Xdup[i j] dup file descriptor
2674e3613abSDavid du Colombier * Xeflag
2684e3613abSDavid du Colombier * Xerror
2693e12c5d1SDavid du Colombier * Xexit rc exits with status
2703e12c5d1SDavid du Colombier * Xfalse{...} execute {} if false
2713e12c5d1SDavid du Colombier * Xfn(name){... Xreturn} define function
2723e12c5d1SDavid du Colombier * Xfor(var, list){... Xreturn} for loop
2734e3613abSDavid du Colombier * Xglob
2744e3613abSDavid du Colombier * Xif
2754e3613abSDavid du Colombier * Xifnot
2763e12c5d1SDavid du Colombier * Xjump[addr] goto
2773e12c5d1SDavid du Colombier * Xlocal(name, val) create local variable, assign value
2783e12c5d1SDavid du Colombier * Xmark mark stack
2793e12c5d1SDavid du Colombier * Xmatch(pat, str) match pattern, set status
2803e12c5d1SDavid du Colombier * Xpipe[i j]{... Xreturn}{... Xreturn} construct a pipe between 2 new threads,
2813e12c5d1SDavid du Colombier * wait for both
2823e12c5d1SDavid du Colombier * Xpipefd[type]{... Xreturn} connect {} to pipe (input or output,
2833e12c5d1SDavid du Colombier * depending on type), push /dev/fd/??
2844e3613abSDavid du Colombier * Xpipewait
2853e12c5d1SDavid du Colombier * Xpopm(value) pop value from stack
2864e3613abSDavid du Colombier * Xpopredir
287c6df1444SDavid du Colombier * Xqdol(name) concatenate variable components
2884e3613abSDavid du Colombier * Xrdcmds
2894e3613abSDavid du Colombier * Xrdfn
290119a69faSDavid du Colombier * Xrdwr(file)[fd] open file for reading and writing
2913e12c5d1SDavid du Colombier * Xread(file)[fd] open file to read
2923e12c5d1SDavid du Colombier * Xreturn kill thread
2934e3613abSDavid du Colombier * Xsimple(args) run command and wait
294c6df1444SDavid du Colombier * Xsettrue
2954e3613abSDavid du Colombier * Xsub
2963e12c5d1SDavid du Colombier * Xsubshell{... Xexit} execute {} in a subshell and wait
2973e12c5d1SDavid du Colombier * Xtrue{...} execute {} if true
2983e12c5d1SDavid du Colombier * Xunlocal delete local variable
2994e3613abSDavid du Colombier * Xwastrue
3003e12c5d1SDavid du Colombier * Xword[string] push string
3013e12c5d1SDavid du Colombier * Xwrite(file)[fd] open file to write
3023e12c5d1SDavid du Colombier */
303dc5a79c1SDavid du Colombier
304dc5a79c1SDavid du Colombier void
Xappend(void)305dc5a79c1SDavid du Colombier Xappend(void)
306dc5a79c1SDavid du Colombier {
3073e12c5d1SDavid du Colombier char *file;
3083e12c5d1SDavid du Colombier int f;
3093e12c5d1SDavid du Colombier switch(count(runq->argv->words)){
310dc5a79c1SDavid du Colombier default:
311dc5a79c1SDavid du Colombier Xerror1(">> requires singleton");
312dc5a79c1SDavid du Colombier return;
313dc5a79c1SDavid du Colombier case 0:
314dc5a79c1SDavid du Colombier Xerror1(">> requires file");
315dc5a79c1SDavid du Colombier return;
316dc5a79c1SDavid du Colombier case 1:
317dc5a79c1SDavid du Colombier break;
3183e12c5d1SDavid du Colombier }
3193e12c5d1SDavid du Colombier file = runq->argv->words->word;
3203e12c5d1SDavid du Colombier if((f = open(file, 1))<0 && (f = Creat(file))<0){
3217dd7cddfSDavid du Colombier pfmt(err, "%s: ", file);
3227dd7cddfSDavid du Colombier Xerror("can't open");
3233e12c5d1SDavid du Colombier return;
3243e12c5d1SDavid du Colombier }
325c6df1444SDavid du Colombier seek(f, 0, 2);
3263e12c5d1SDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i);
3273e12c5d1SDavid du Colombier runq->pc++;
3283e12c5d1SDavid du Colombier poplist();
3293e12c5d1SDavid du Colombier }
330dc5a79c1SDavid du Colombier
331dc5a79c1SDavid du Colombier void
Xsettrue(void)332dc5a79c1SDavid du Colombier Xsettrue(void)
333dc5a79c1SDavid du Colombier {
334219b2ee8SDavid du Colombier setstatus("");
335219b2ee8SDavid du Colombier }
336dc5a79c1SDavid du Colombier
337dc5a79c1SDavid du Colombier void
Xbang(void)338dc5a79c1SDavid du Colombier Xbang(void)
339dc5a79c1SDavid du Colombier {
3403e12c5d1SDavid du Colombier setstatus(truestatus()?"false":"");
3413e12c5d1SDavid du Colombier }
342dc5a79c1SDavid du Colombier
343dc5a79c1SDavid du Colombier void
Xclose(void)344dc5a79c1SDavid du Colombier Xclose(void)
345dc5a79c1SDavid du Colombier {
3463e12c5d1SDavid du Colombier pushredir(RCLOSE, runq->code[runq->pc].i, 0);
3473e12c5d1SDavid du Colombier runq->pc++;
3483e12c5d1SDavid du Colombier }
349dc5a79c1SDavid du Colombier
350dc5a79c1SDavid du Colombier void
Xdup(void)351dc5a79c1SDavid du Colombier Xdup(void)
352dc5a79c1SDavid du Colombier {
3533e12c5d1SDavid du Colombier pushredir(RDUP, runq->code[runq->pc].i, runq->code[runq->pc+1].i);
3543e12c5d1SDavid du Colombier runq->pc+=2;
3553e12c5d1SDavid du Colombier }
356dc5a79c1SDavid du Colombier
357dc5a79c1SDavid du Colombier void
Xeflag(void)358dc5a79c1SDavid du Colombier Xeflag(void)
359dc5a79c1SDavid du Colombier {
360219b2ee8SDavid du Colombier if(eflagok && !truestatus()) Xexit();
361219b2ee8SDavid du Colombier }
362dc5a79c1SDavid du Colombier
363dc5a79c1SDavid du Colombier void
Xexit(void)364dc5a79c1SDavid du Colombier Xexit(void)
365dc5a79c1SDavid du Colombier {
3663e12c5d1SDavid du Colombier struct var *trapreq;
3673e12c5d1SDavid du Colombier struct word *starval;
3683e12c5d1SDavid du Colombier static int beenhere = 0;
3693e12c5d1SDavid du Colombier if(getpid()==mypid && !beenhere){
3703e12c5d1SDavid du Colombier trapreq = vlook("sigexit");
3713e12c5d1SDavid du Colombier if(trapreq->fn){
3723e12c5d1SDavid du Colombier beenhere = 1;
3733e12c5d1SDavid du Colombier --runq->pc;
374219b2ee8SDavid du Colombier starval = vlook("*")->val;
3753e12c5d1SDavid du Colombier start(trapreq->fn, trapreq->pc, (struct var *)0);
3763e12c5d1SDavid du Colombier runq->local = newvar(strdup("*"), runq->local);
3773e12c5d1SDavid du Colombier runq->local->val = copywords(starval, (struct word *)0);
3783e12c5d1SDavid du Colombier runq->local->changed = 1;
3793e12c5d1SDavid du Colombier runq->redir = runq->startredir = 0;
3803e12c5d1SDavid du Colombier return;
3813e12c5d1SDavid du Colombier }
3823e12c5d1SDavid du Colombier }
3833e12c5d1SDavid du Colombier Exit(getstatus());
3843e12c5d1SDavid du Colombier }
385dc5a79c1SDavid du Colombier
386dc5a79c1SDavid du Colombier void
Xfalse(void)387dc5a79c1SDavid du Colombier Xfalse(void)
388dc5a79c1SDavid du Colombier {
3893e12c5d1SDavid du Colombier if(truestatus()) runq->pc = runq->code[runq->pc].i;
3903e12c5d1SDavid du Colombier else runq->pc++;
3913e12c5d1SDavid du Colombier }
3923e12c5d1SDavid du Colombier int ifnot; /* dynamic if not flag */
393dc5a79c1SDavid du Colombier
394dc5a79c1SDavid du Colombier void
Xifnot(void)395dc5a79c1SDavid du Colombier Xifnot(void)
396dc5a79c1SDavid du Colombier {
3973e12c5d1SDavid du Colombier if(ifnot)
3983e12c5d1SDavid du Colombier runq->pc++;
3993e12c5d1SDavid du Colombier else
4003e12c5d1SDavid du Colombier runq->pc = runq->code[runq->pc].i;
4013e12c5d1SDavid du Colombier }
402dc5a79c1SDavid du Colombier
403dc5a79c1SDavid du Colombier void
Xjump(void)404dc5a79c1SDavid du Colombier Xjump(void)
405dc5a79c1SDavid du Colombier {
4063e12c5d1SDavid du Colombier runq->pc = runq->code[runq->pc].i;
4073e12c5d1SDavid du Colombier }
408dc5a79c1SDavid du Colombier
409dc5a79c1SDavid du Colombier void
Xmark(void)410dc5a79c1SDavid du Colombier Xmark(void)
411dc5a79c1SDavid du Colombier {
4123e12c5d1SDavid du Colombier pushlist();
4133e12c5d1SDavid du Colombier }
414dc5a79c1SDavid du Colombier
415dc5a79c1SDavid du Colombier void
Xpopm(void)416dc5a79c1SDavid du Colombier Xpopm(void)
417dc5a79c1SDavid du Colombier {
4183e12c5d1SDavid du Colombier poplist();
4193e12c5d1SDavid du Colombier }
420dc5a79c1SDavid du Colombier
421dc5a79c1SDavid du Colombier void
Xread(void)422dc5a79c1SDavid du Colombier Xread(void)
423dc5a79c1SDavid du Colombier {
4243e12c5d1SDavid du Colombier char *file;
4253e12c5d1SDavid du Colombier int f;
4263e12c5d1SDavid du Colombier switch(count(runq->argv->words)){
427dc5a79c1SDavid du Colombier default:
428dc5a79c1SDavid du Colombier Xerror1("< requires singleton\n");
429dc5a79c1SDavid du Colombier return;
430dc5a79c1SDavid du Colombier case 0:
431dc5a79c1SDavid du Colombier Xerror1("< requires file\n");
432dc5a79c1SDavid du Colombier return;
433dc5a79c1SDavid du Colombier case 1:
434dc5a79c1SDavid du Colombier break;
4353e12c5d1SDavid du Colombier }
4363e12c5d1SDavid du Colombier file = runq->argv->words->word;
4373e12c5d1SDavid du Colombier if((f = open(file, 0))<0){
4387dd7cddfSDavid du Colombier pfmt(err, "%s: ", file);
4397dd7cddfSDavid du Colombier Xerror("can't open");
4403e12c5d1SDavid du Colombier return;
4413e12c5d1SDavid du Colombier }
4423e12c5d1SDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i);
4433e12c5d1SDavid du Colombier runq->pc++;
4443e12c5d1SDavid du Colombier poplist();
4453e12c5d1SDavid du Colombier }
446dc5a79c1SDavid du Colombier
447dc5a79c1SDavid du Colombier void
Xrdwr(void)448119a69faSDavid du Colombier Xrdwr(void)
449119a69faSDavid du Colombier {
450119a69faSDavid du Colombier char *file;
451119a69faSDavid du Colombier int f;
452119a69faSDavid du Colombier
453119a69faSDavid du Colombier switch(count(runq->argv->words)){
454119a69faSDavid du Colombier default:
455119a69faSDavid du Colombier Xerror1("<> requires singleton\n");
456119a69faSDavid du Colombier return;
457119a69faSDavid du Colombier case 0:
458119a69faSDavid du Colombier Xerror1("<> requires file\n");
459119a69faSDavid du Colombier return;
460119a69faSDavid du Colombier case 1:
461119a69faSDavid du Colombier break;
462119a69faSDavid du Colombier }
463119a69faSDavid du Colombier file = runq->argv->words->word;
464119a69faSDavid du Colombier if((f = open(file, ORDWR))<0){
465119a69faSDavid du Colombier pfmt(err, "%s: ", file);
466119a69faSDavid du Colombier Xerror("can't open");
467119a69faSDavid du Colombier return;
468119a69faSDavid du Colombier }
469119a69faSDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i);
470119a69faSDavid du Colombier runq->pc++;
471119a69faSDavid du Colombier poplist();
472119a69faSDavid du Colombier }
473119a69faSDavid du Colombier
474119a69faSDavid du Colombier void
turfredir(void)475dc5a79c1SDavid du Colombier turfredir(void)
476dc5a79c1SDavid du Colombier {
4773e12c5d1SDavid du Colombier while(runq->redir!=runq->startredir)
4783e12c5d1SDavid du Colombier Xpopredir();
4793e12c5d1SDavid du Colombier }
480dc5a79c1SDavid du Colombier
481dc5a79c1SDavid du Colombier void
Xpopredir(void)482dc5a79c1SDavid du Colombier Xpopredir(void)
483dc5a79c1SDavid du Colombier {
4843e12c5d1SDavid du Colombier struct redir *rp = runq->redir;
485dc5a79c1SDavid du Colombier if(rp==0)
486dc5a79c1SDavid du Colombier panic("turfredir null!", 0);
4873e12c5d1SDavid du Colombier runq->redir = rp->next;
488dc5a79c1SDavid du Colombier if(rp->type==ROPEN)
489dc5a79c1SDavid du Colombier close(rp->from);
4903e12c5d1SDavid du Colombier efree((char *)rp);
4913e12c5d1SDavid du Colombier }
492dc5a79c1SDavid du Colombier
493dc5a79c1SDavid du Colombier void
Xreturn(void)494dc5a79c1SDavid du Colombier Xreturn(void)
495dc5a79c1SDavid du Colombier {
4963e12c5d1SDavid du Colombier struct thread *p = runq;
4973e12c5d1SDavid du Colombier turfredir();
4983e12c5d1SDavid du Colombier while(p->argv) poplist();
4993e12c5d1SDavid du Colombier codefree(p->code);
5003e12c5d1SDavid du Colombier runq = p->ret;
5013e12c5d1SDavid du Colombier efree((char *)p);
502dc5a79c1SDavid du Colombier if(runq==0)
503dc5a79c1SDavid du Colombier Exit(getstatus());
5043e12c5d1SDavid du Colombier }
505dc5a79c1SDavid du Colombier
506dc5a79c1SDavid du Colombier void
Xtrue(void)507dc5a79c1SDavid du Colombier Xtrue(void)
508dc5a79c1SDavid du Colombier {
5093e12c5d1SDavid du Colombier if(truestatus()) runq->pc++;
5103e12c5d1SDavid du Colombier else runq->pc = runq->code[runq->pc].i;
5113e12c5d1SDavid du Colombier }
512dc5a79c1SDavid du Colombier
513dc5a79c1SDavid du Colombier void
Xif(void)514dc5a79c1SDavid du Colombier Xif(void)
515dc5a79c1SDavid du Colombier {
5163e12c5d1SDavid du Colombier ifnot = 1;
5173e12c5d1SDavid du Colombier if(truestatus()) runq->pc++;
5183e12c5d1SDavid du Colombier else runq->pc = runq->code[runq->pc].i;
5193e12c5d1SDavid du Colombier }
520dc5a79c1SDavid du Colombier
521dc5a79c1SDavid du Colombier void
Xwastrue(void)522dc5a79c1SDavid du Colombier Xwastrue(void)
523dc5a79c1SDavid du Colombier {
5243e12c5d1SDavid du Colombier ifnot = 0;
5253e12c5d1SDavid du Colombier }
526dc5a79c1SDavid du Colombier
527dc5a79c1SDavid du Colombier void
Xword(void)528dc5a79c1SDavid du Colombier Xword(void)
529dc5a79c1SDavid du Colombier {
5303e12c5d1SDavid du Colombier pushword(runq->code[runq->pc++].s);
5313e12c5d1SDavid du Colombier }
532dc5a79c1SDavid du Colombier
533dc5a79c1SDavid du Colombier void
Xwrite(void)534dc5a79c1SDavid du Colombier Xwrite(void)
535dc5a79c1SDavid du Colombier {
5363e12c5d1SDavid du Colombier char *file;
5373e12c5d1SDavid du Colombier int f;
5383e12c5d1SDavid du Colombier switch(count(runq->argv->words)){
539dc5a79c1SDavid du Colombier default:
540dc5a79c1SDavid du Colombier Xerror1("> requires singleton\n");
541dc5a79c1SDavid du Colombier return;
542dc5a79c1SDavid du Colombier case 0:
543dc5a79c1SDavid du Colombier Xerror1("> requires file\n");
544dc5a79c1SDavid du Colombier return;
545dc5a79c1SDavid du Colombier case 1:
546dc5a79c1SDavid du Colombier break;
5473e12c5d1SDavid du Colombier }
5483e12c5d1SDavid du Colombier file = runq->argv->words->word;
5493e12c5d1SDavid du Colombier if((f = Creat(file))<0){
5507dd7cddfSDavid du Colombier pfmt(err, "%s: ", file);
5517dd7cddfSDavid du Colombier Xerror("can't open");
5523e12c5d1SDavid du Colombier return;
5533e12c5d1SDavid du Colombier }
5543e12c5d1SDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i);
5553e12c5d1SDavid du Colombier runq->pc++;
5563e12c5d1SDavid du Colombier poplist();
5573e12c5d1SDavid du Colombier }
558dc5a79c1SDavid du Colombier
559dc5a79c1SDavid du Colombier char*
list2str(word * words)560dc5a79c1SDavid du Colombier list2str(word *words)
561dc5a79c1SDavid du Colombier {
5623e12c5d1SDavid du Colombier char *value, *s, *t;
5633e12c5d1SDavid du Colombier int len = 0;
5643e12c5d1SDavid du Colombier word *ap;
5653e12c5d1SDavid du Colombier for(ap = words;ap;ap = ap->next)
5663e12c5d1SDavid du Colombier len+=1+strlen(ap->word);
5673e12c5d1SDavid du Colombier value = emalloc(len+1);
5683e12c5d1SDavid du Colombier s = value;
5693e12c5d1SDavid du Colombier for(ap = words;ap;ap = ap->next){
5703e12c5d1SDavid du Colombier for(t = ap->word;*t;) *s++=*t++;
5713e12c5d1SDavid du Colombier *s++=' ';
5723e12c5d1SDavid du Colombier }
573dc5a79c1SDavid du Colombier if(s==value)
574dc5a79c1SDavid du Colombier *s='\0';
5753e12c5d1SDavid du Colombier else s[-1]='\0';
5763e12c5d1SDavid du Colombier return value;
5773e12c5d1SDavid du Colombier }
578dc5a79c1SDavid du Colombier
579dc5a79c1SDavid du Colombier void
Xmatch(void)580dc5a79c1SDavid du Colombier Xmatch(void)
581dc5a79c1SDavid du Colombier {
5823e12c5d1SDavid du Colombier word *p;
5833e12c5d1SDavid du Colombier char *subject;
5843e12c5d1SDavid du Colombier subject = list2str(runq->argv->words);
5853e12c5d1SDavid du Colombier setstatus("no match");
5863e12c5d1SDavid du Colombier for(p = runq->argv->next->words;p;p = p->next)
5873e12c5d1SDavid du Colombier if(match(subject, p->word, '\0')){
5883e12c5d1SDavid du Colombier setstatus("");
5893e12c5d1SDavid du Colombier break;
5903e12c5d1SDavid du Colombier }
5913e12c5d1SDavid du Colombier efree(subject);
5923e12c5d1SDavid du Colombier poplist();
5933e12c5d1SDavid du Colombier poplist();
5943e12c5d1SDavid du Colombier }
595dc5a79c1SDavid du Colombier
596dc5a79c1SDavid du Colombier void
Xcase(void)597dc5a79c1SDavid du Colombier Xcase(void)
598dc5a79c1SDavid du Colombier {
5993e12c5d1SDavid du Colombier word *p;
6003e12c5d1SDavid du Colombier char *s;
6013e12c5d1SDavid du Colombier int ok = 0;
6023e12c5d1SDavid du Colombier s = list2str(runq->argv->next->words);
6033e12c5d1SDavid du Colombier for(p = runq->argv->words;p;p = p->next){
6043e12c5d1SDavid du Colombier if(match(s, p->word, '\0')){
6053e12c5d1SDavid du Colombier ok = 1;
6063e12c5d1SDavid du Colombier break;
6073e12c5d1SDavid du Colombier }
6083e12c5d1SDavid du Colombier }
6093e12c5d1SDavid du Colombier efree(s);
6103e12c5d1SDavid du Colombier if(ok)
6113e12c5d1SDavid du Colombier runq->pc++;
6123e12c5d1SDavid du Colombier else
6133e12c5d1SDavid du Colombier runq->pc = runq->code[runq->pc].i;
6143e12c5d1SDavid du Colombier poplist();
6153e12c5d1SDavid du Colombier }
616dc5a79c1SDavid du Colombier
617dc5a79c1SDavid du Colombier word*
conclist(word * lp,word * rp,word * tail)618dc5a79c1SDavid du Colombier conclist(word *lp, word *rp, word *tail)
6193e12c5d1SDavid du Colombier {
6203e12c5d1SDavid du Colombier char *buf;
6213e12c5d1SDavid du Colombier word *v;
6223e12c5d1SDavid du Colombier if(lp->next || rp->next)
623276e7d6dSDavid du Colombier tail = conclist(lp->next==0? lp: lp->next,
624276e7d6dSDavid du Colombier rp->next==0? rp: rp->next, tail);
625276e7d6dSDavid du Colombier buf = emalloc(strlen(lp->word)+strlen((char *)rp->word)+1);
6263e12c5d1SDavid du Colombier strcpy(buf, lp->word);
6273e12c5d1SDavid du Colombier strcat(buf, rp->word);
6283e12c5d1SDavid du Colombier v = newword(buf, tail);
6293e12c5d1SDavid du Colombier efree(buf);
6303e12c5d1SDavid du Colombier return v;
6313e12c5d1SDavid du Colombier }
632dc5a79c1SDavid du Colombier
633dc5a79c1SDavid du Colombier void
Xconc(void)634dc5a79c1SDavid du Colombier Xconc(void)
635dc5a79c1SDavid du Colombier {
6363e12c5d1SDavid du Colombier word *lp = runq->argv->words;
6373e12c5d1SDavid du Colombier word *rp = runq->argv->next->words;
6383e12c5d1SDavid du Colombier word *vp = runq->argv->next->next->words;
6393e12c5d1SDavid du Colombier int lc = count(lp), rc = count(rp);
6403e12c5d1SDavid du Colombier if(lc!=0 || rc!=0){
6413e12c5d1SDavid du Colombier if(lc==0 || rc==0){
6429a747e4fSDavid du Colombier Xerror1("null list in concatenation");
6433e12c5d1SDavid du Colombier return;
6443e12c5d1SDavid du Colombier }
6453e12c5d1SDavid du Colombier if(lc!=1 && rc!=1 && lc!=rc){
6469a747e4fSDavid du Colombier Xerror1("mismatched list lengths in concatenation");
6473e12c5d1SDavid du Colombier return;
6483e12c5d1SDavid du Colombier }
6493e12c5d1SDavid du Colombier vp = conclist(lp, rp, vp);
6503e12c5d1SDavid du Colombier }
6513e12c5d1SDavid du Colombier poplist();
6523e12c5d1SDavid du Colombier poplist();
6533e12c5d1SDavid du Colombier runq->argv->words = vp;
6543e12c5d1SDavid du Colombier }
655dc5a79c1SDavid du Colombier
656dc5a79c1SDavid du Colombier void
Xassign(void)657dc5a79c1SDavid du Colombier Xassign(void)
658dc5a79c1SDavid du Colombier {
6593e12c5d1SDavid du Colombier var *v;
6603e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){
6619a747e4fSDavid du Colombier Xerror1("variable name not singleton!");
6623e12c5d1SDavid du Colombier return;
6633e12c5d1SDavid du Colombier }
6643e12c5d1SDavid du Colombier deglob(runq->argv->words->word);
6653e12c5d1SDavid du Colombier v = vlook(runq->argv->words->word);
6663e12c5d1SDavid du Colombier poplist();
6673e12c5d1SDavid du Colombier globlist();
6683e12c5d1SDavid du Colombier freewords(v->val);
6693e12c5d1SDavid du Colombier v->val = runq->argv->words;
6703e12c5d1SDavid du Colombier v->changed = 1;
6713e12c5d1SDavid du Colombier runq->argv->words = 0;
6723e12c5d1SDavid du Colombier poplist();
6733e12c5d1SDavid du Colombier }
6743e12c5d1SDavid du Colombier /*
6753e12c5d1SDavid du Colombier * copy arglist a, adding the copy to the front of tail
6763e12c5d1SDavid du Colombier */
677dc5a79c1SDavid du Colombier
678dc5a79c1SDavid du Colombier word*
copywords(word * a,word * tail)679dc5a79c1SDavid du Colombier copywords(word *a, word *tail)
6803e12c5d1SDavid du Colombier {
6813e12c5d1SDavid du Colombier word *v = 0, **end;
6823e12c5d1SDavid du Colombier for(end=&v;a;a = a->next,end=&(*end)->next)
6833e12c5d1SDavid du Colombier *end = newword(a->word, 0);
6843e12c5d1SDavid du Colombier *end = tail;
6853e12c5d1SDavid du Colombier return v;
6863e12c5d1SDavid du Colombier }
687dc5a79c1SDavid du Colombier
688dc5a79c1SDavid du Colombier void
Xdol(void)689dc5a79c1SDavid du Colombier Xdol(void)
690dc5a79c1SDavid du Colombier {
6913e12c5d1SDavid du Colombier word *a, *star;
6923e12c5d1SDavid du Colombier char *s, *t;
6933e12c5d1SDavid du Colombier int n;
6943e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){
6959a747e4fSDavid du Colombier Xerror1("variable name not singleton!");
6963e12c5d1SDavid du Colombier return;
6973e12c5d1SDavid du Colombier }
6983e12c5d1SDavid du Colombier s = runq->argv->words->word;
6993e12c5d1SDavid du Colombier deglob(s);
7003e12c5d1SDavid du Colombier n = 0;
70199eb86a7SDavid du Colombier for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0';
7023e12c5d1SDavid du Colombier a = runq->argv->next->words;
7033e12c5d1SDavid du Colombier if(n==0 || *t)
7043e12c5d1SDavid du Colombier a = copywords(vlook(s)->val, a);
7053e12c5d1SDavid du Colombier else{
7063e12c5d1SDavid du Colombier star = vlook("*")->val;
7073e12c5d1SDavid du Colombier if(star && 1<=n && n<=count(star)){
70899eb86a7SDavid du Colombier while(--n) star = star->next;
7093e12c5d1SDavid du Colombier a = newword(star->word, a);
7103e12c5d1SDavid du Colombier }
7113e12c5d1SDavid du Colombier }
7123e12c5d1SDavid du Colombier poplist();
7133e12c5d1SDavid du Colombier runq->argv->words = a;
7143e12c5d1SDavid du Colombier }
715dc5a79c1SDavid du Colombier
716dc5a79c1SDavid du Colombier void
Xqdol(void)717dc5a79c1SDavid du Colombier Xqdol(void)
718dc5a79c1SDavid du Colombier {
7193e12c5d1SDavid du Colombier word *a, *p;
7203e12c5d1SDavid du Colombier char *s;
7213e12c5d1SDavid du Colombier int n;
7223e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){
7239a747e4fSDavid du Colombier Xerror1("variable name not singleton!");
7243e12c5d1SDavid du Colombier return;
7253e12c5d1SDavid du Colombier }
7263e12c5d1SDavid du Colombier s = runq->argv->words->word;
7273e12c5d1SDavid du Colombier deglob(s);
7283e12c5d1SDavid du Colombier a = vlook(s)->val;
7293e12c5d1SDavid du Colombier poplist();
7303e12c5d1SDavid du Colombier n = count(a);
7313e12c5d1SDavid du Colombier if(n==0){
7323e12c5d1SDavid du Colombier pushword("");
7333e12c5d1SDavid du Colombier return;
7343e12c5d1SDavid du Colombier }
7353e12c5d1SDavid du Colombier for(p = a;p;p = p->next) n+=strlen(p->word);
7363e12c5d1SDavid du Colombier s = emalloc(n);
7373e12c5d1SDavid du Colombier if(a){
7383e12c5d1SDavid du Colombier strcpy(s, a->word);
7393e12c5d1SDavid du Colombier for(p = a->next;p;p = p->next){
7403e12c5d1SDavid du Colombier strcat(s, " ");
7413e12c5d1SDavid du Colombier strcat(s, p->word);
7423e12c5d1SDavid du Colombier }
7433e12c5d1SDavid du Colombier }
7443e12c5d1SDavid du Colombier else
7453e12c5d1SDavid du Colombier s[0]='\0';
7463e12c5d1SDavid du Colombier pushword(s);
7473e12c5d1SDavid du Colombier efree(s);
7483e12c5d1SDavid du Colombier }
749dc5a79c1SDavid du Colombier
750dc5a79c1SDavid du Colombier word*
copynwords(word * a,word * tail,int n)7515e061cc0SDavid du Colombier copynwords(word *a, word *tail, int n)
7525e061cc0SDavid du Colombier {
7535e061cc0SDavid du Colombier word *v, **end;
7545e061cc0SDavid du Colombier
7555e061cc0SDavid du Colombier v = 0;
7565e061cc0SDavid du Colombier end = &v;
7575e061cc0SDavid du Colombier while(n-- > 0){
7585e061cc0SDavid du Colombier *end = newword(a->word, 0);
7595e061cc0SDavid du Colombier end = &(*end)->next;
7605e061cc0SDavid du Colombier a = a->next;
7615e061cc0SDavid du Colombier }
7625e061cc0SDavid du Colombier *end = tail;
7635e061cc0SDavid du Colombier return v;
7645e061cc0SDavid du Colombier }
7655e061cc0SDavid du Colombier
7665e061cc0SDavid du Colombier word*
subwords(word * val,int len,word * sub,word * a)767dc5a79c1SDavid du Colombier subwords(word *val, int len, word *sub, word *a)
7683e12c5d1SDavid du Colombier {
7695e061cc0SDavid du Colombier int n, m;
7703e12c5d1SDavid du Colombier char *s;
771dc5a79c1SDavid du Colombier if(!sub)
772dc5a79c1SDavid du Colombier return a;
7733e12c5d1SDavid du Colombier a = subwords(val, len, sub->next, a);
7743e12c5d1SDavid du Colombier s = sub->word;
7753e12c5d1SDavid du Colombier deglob(s);
7765e061cc0SDavid du Colombier m = 0;
7773e12c5d1SDavid du Colombier n = 0;
7785e061cc0SDavid du Colombier while('0'<=*s && *s<='9')
7795e061cc0SDavid du Colombier n = n*10+ *s++ -'0';
7805e061cc0SDavid du Colombier if(*s == '-'){
7815e061cc0SDavid du Colombier if(*++s == 0)
7825e061cc0SDavid du Colombier m = len - n;
7835e061cc0SDavid du Colombier else{
7845e061cc0SDavid du Colombier while('0'<=*s && *s<='9')
7855e061cc0SDavid du Colombier m = m*10+ *s++ -'0';
7865e061cc0SDavid du Colombier m -= n;
7875e061cc0SDavid du Colombier }
7885e061cc0SDavid du Colombier }
7895e061cc0SDavid du Colombier if(n<1 || n>len || m<0)
790dc5a79c1SDavid du Colombier return a;
7915e061cc0SDavid du Colombier if(n+m>len)
7925e061cc0SDavid du Colombier m = len-n;
7935e061cc0SDavid du Colombier while(--n > 0)
7945e061cc0SDavid du Colombier val = val->next;
7955e061cc0SDavid du Colombier return copynwords(val, a, m+1);
7963e12c5d1SDavid du Colombier }
797dc5a79c1SDavid du Colombier
798dc5a79c1SDavid du Colombier void
Xsub(void)799dc5a79c1SDavid du Colombier Xsub(void)
800dc5a79c1SDavid du Colombier {
8013e12c5d1SDavid du Colombier word *a, *v;
8023e12c5d1SDavid du Colombier char *s;
8033e12c5d1SDavid du Colombier if(count(runq->argv->next->words)!=1){
8049a747e4fSDavid du Colombier Xerror1("variable name not singleton!");
8053e12c5d1SDavid du Colombier return;
8063e12c5d1SDavid du Colombier }
8073e12c5d1SDavid du Colombier s = runq->argv->next->words->word;
8083e12c5d1SDavid du Colombier deglob(s);
8093e12c5d1SDavid du Colombier a = runq->argv->next->next->words;
8103e12c5d1SDavid du Colombier v = vlook(s)->val;
8113e12c5d1SDavid du Colombier a = subwords(v, count(v), runq->argv->words, a);
8123e12c5d1SDavid du Colombier poplist();
8133e12c5d1SDavid du Colombier poplist();
8143e12c5d1SDavid du Colombier runq->argv->words = a;
8153e12c5d1SDavid du Colombier }
816dc5a79c1SDavid du Colombier
817dc5a79c1SDavid du Colombier void
Xcount(void)818dc5a79c1SDavid du Colombier Xcount(void)
819dc5a79c1SDavid du Colombier {
8203e12c5d1SDavid du Colombier word *a;
8213e12c5d1SDavid du Colombier char *s, *t;
8223e12c5d1SDavid du Colombier int n;
8233e12c5d1SDavid du Colombier char num[12];
8243e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){
8259a747e4fSDavid du Colombier Xerror1("variable name not singleton!");
8263e12c5d1SDavid du Colombier return;
8273e12c5d1SDavid du Colombier }
8283e12c5d1SDavid du Colombier s = runq->argv->words->word;
8293e12c5d1SDavid du Colombier deglob(s);
8303e12c5d1SDavid du Colombier n = 0;
8313e12c5d1SDavid du Colombier for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0';
8323e12c5d1SDavid du Colombier if(n==0 || *t){
8333e12c5d1SDavid du Colombier a = vlook(s)->val;
834dc5a79c1SDavid du Colombier inttoascii(num, count(a));
8353e12c5d1SDavid du Colombier }
8363e12c5d1SDavid du Colombier else{
8373e12c5d1SDavid du Colombier a = vlook("*")->val;
838dc5a79c1SDavid du Colombier inttoascii(num, a && 1<=n && n<=count(a)?1:0);
8393e12c5d1SDavid du Colombier }
8403e12c5d1SDavid du Colombier poplist();
8413e12c5d1SDavid du Colombier pushword(num);
8423e12c5d1SDavid du Colombier }
843dc5a79c1SDavid du Colombier
844dc5a79c1SDavid du Colombier void
Xlocal(void)845dc5a79c1SDavid du Colombier Xlocal(void)
846dc5a79c1SDavid du Colombier {
8473e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){
8489a747e4fSDavid du Colombier Xerror1("variable name must be singleton\n");
8493e12c5d1SDavid du Colombier return;
8503e12c5d1SDavid du Colombier }
8513e12c5d1SDavid du Colombier deglob(runq->argv->words->word);
8523e12c5d1SDavid du Colombier runq->local = newvar(strdup(runq->argv->words->word), runq->local);
8533e12c5d1SDavid du Colombier poplist();
854fed0fa9eSDavid du Colombier globlist();
855fed0fa9eSDavid du Colombier runq->local->val = runq->argv->words;
856fed0fa9eSDavid du Colombier runq->local->changed = 1;
857fed0fa9eSDavid du Colombier runq->argv->words = 0;
8583e12c5d1SDavid du Colombier poplist();
8593e12c5d1SDavid du Colombier }
860dc5a79c1SDavid du Colombier
861dc5a79c1SDavid du Colombier void
Xunlocal(void)862dc5a79c1SDavid du Colombier Xunlocal(void)
863dc5a79c1SDavid du Colombier {
8643e12c5d1SDavid du Colombier var *v = runq->local, *hid;
865dc5a79c1SDavid du Colombier if(v==0)
866dc5a79c1SDavid du Colombier panic("Xunlocal: no locals!", 0);
8673e12c5d1SDavid du Colombier runq->local = v->next;
8683e12c5d1SDavid du Colombier hid = vlook(v->name);
8693e12c5d1SDavid du Colombier hid->changed = 1;
8703e12c5d1SDavid du Colombier efree(v->name);
8713e12c5d1SDavid du Colombier freewords(v->val);
8723e12c5d1SDavid du Colombier efree((char *)v);
8733e12c5d1SDavid du Colombier }
874dc5a79c1SDavid du Colombier
875dc5a79c1SDavid du Colombier void
freewords(word * w)876dc5a79c1SDavid du Colombier freewords(word *w)
8773e12c5d1SDavid du Colombier {
8783e12c5d1SDavid du Colombier word *nw;
8793e12c5d1SDavid du Colombier while(w){
8803e12c5d1SDavid du Colombier efree(w->word);
8813e12c5d1SDavid du Colombier nw = w->next;
8823e12c5d1SDavid du Colombier efree((char *)w);
8833e12c5d1SDavid du Colombier w = nw;
8843e12c5d1SDavid du Colombier }
8853e12c5d1SDavid du Colombier }
886dc5a79c1SDavid du Colombier
887dc5a79c1SDavid du Colombier void
Xfn(void)888dc5a79c1SDavid du Colombier Xfn(void)
889dc5a79c1SDavid du Colombier {
8903e12c5d1SDavid du Colombier var *v;
8913e12c5d1SDavid du Colombier word *a;
8923e12c5d1SDavid du Colombier int end;
8933e12c5d1SDavid du Colombier end = runq->code[runq->pc].i;
894fed0fa9eSDavid du Colombier globlist();
8953e12c5d1SDavid du Colombier for(a = runq->argv->words;a;a = a->next){
8963e12c5d1SDavid du Colombier v = gvlook(a->word);
897dc5a79c1SDavid du Colombier if(v->fn)
898dc5a79c1SDavid du Colombier codefree(v->fn);
8993e12c5d1SDavid du Colombier v->fn = codecopy(runq->code);
9003e12c5d1SDavid du Colombier v->pc = runq->pc+2;
9013e12c5d1SDavid du Colombier v->fnchanged = 1;
9023e12c5d1SDavid du Colombier }
9033e12c5d1SDavid du Colombier runq->pc = end;
9043e12c5d1SDavid du Colombier poplist();
9053e12c5d1SDavid du Colombier }
906dc5a79c1SDavid du Colombier
907dc5a79c1SDavid du Colombier void
Xdelfn(void)908dc5a79c1SDavid du Colombier Xdelfn(void)
909dc5a79c1SDavid du Colombier {
9103e12c5d1SDavid du Colombier var *v;
9113e12c5d1SDavid du Colombier word *a;
9123e12c5d1SDavid du Colombier for(a = runq->argv->words;a;a = a->next){
9133e12c5d1SDavid du Colombier v = gvlook(a->word);
914dc5a79c1SDavid du Colombier if(v->fn)
915dc5a79c1SDavid du Colombier codefree(v->fn);
9163e12c5d1SDavid du Colombier v->fn = 0;
9173e12c5d1SDavid du Colombier v->fnchanged = 1;
9183e12c5d1SDavid du Colombier }
9193e12c5d1SDavid du Colombier poplist();
9203e12c5d1SDavid du Colombier }
921dc5a79c1SDavid du Colombier
922dc5a79c1SDavid du Colombier char*
concstatus(char * s,char * t)923dc5a79c1SDavid du Colombier concstatus(char *s, char *t)
9243e12c5d1SDavid du Colombier {
9253e12c5d1SDavid du Colombier static char v[NSTATUS+1];
9263e12c5d1SDavid du Colombier int n = strlen(s);
9273e12c5d1SDavid du Colombier strncpy(v, s, NSTATUS);
9283e12c5d1SDavid du Colombier if(n<NSTATUS){
9293e12c5d1SDavid du Colombier v[n]='|';
9303e12c5d1SDavid du Colombier strncpy(v+n+1, t, NSTATUS-n-1);
9313e12c5d1SDavid du Colombier }
9323e12c5d1SDavid du Colombier v[NSTATUS]='\0';
9333e12c5d1SDavid du Colombier return v;
9343e12c5d1SDavid du Colombier }
935dc5a79c1SDavid du Colombier
936dc5a79c1SDavid du Colombier void
Xpipewait(void)937dc5a79c1SDavid du Colombier Xpipewait(void)
938dc5a79c1SDavid du Colombier {
9393e12c5d1SDavid du Colombier char status[NSTATUS+1];
9403e12c5d1SDavid du Colombier if(runq->pid==-1)
9413e12c5d1SDavid du Colombier setstatus(concstatus(runq->status, getstatus()));
9423e12c5d1SDavid du Colombier else{
9433e12c5d1SDavid du Colombier strncpy(status, getstatus(), NSTATUS);
9443e12c5d1SDavid du Colombier status[NSTATUS]='\0';
9453e12c5d1SDavid du Colombier Waitfor(runq->pid, 1);
9463e12c5d1SDavid du Colombier runq->pid=-1;
9473e12c5d1SDavid du Colombier setstatus(concstatus(getstatus(), status));
9483e12c5d1SDavid du Colombier }
9493e12c5d1SDavid du Colombier }
950dc5a79c1SDavid du Colombier
951dc5a79c1SDavid du Colombier void
Xrdcmds(void)952dc5a79c1SDavid du Colombier Xrdcmds(void)
953dc5a79c1SDavid du Colombier {
9543e12c5d1SDavid du Colombier struct thread *p = runq;
9553e12c5d1SDavid du Colombier word *prompt;
9563e12c5d1SDavid du Colombier flush(err);
9573e12c5d1SDavid du Colombier nerror = 0;
9583e12c5d1SDavid du Colombier if(flag['s'] && !truestatus())
9593e12c5d1SDavid du Colombier pfmt(err, "status=%v\n", vlook("status")->val);
9603e12c5d1SDavid du Colombier if(runq->iflag){
9613e12c5d1SDavid du Colombier prompt = vlook("prompt")->val;
9623e12c5d1SDavid du Colombier if(prompt)
9633e12c5d1SDavid du Colombier promptstr = prompt->word;
9643e12c5d1SDavid du Colombier else
9653e12c5d1SDavid du Colombier promptstr="% ";
9663e12c5d1SDavid du Colombier }
9673e12c5d1SDavid du Colombier Noerror();
9683e12c5d1SDavid du Colombier if(yyparse()){
9693e12c5d1SDavid du Colombier if(!p->iflag || p->eof && !Eintr()){
970dc5a79c1SDavid du Colombier if(p->cmdfile)
971dc5a79c1SDavid du Colombier efree(p->cmdfile);
9723e12c5d1SDavid du Colombier closeio(p->cmdfd);
9733e12c5d1SDavid du Colombier Xreturn(); /* should this be omitted? */
9743e12c5d1SDavid du Colombier }
9753e12c5d1SDavid du Colombier else{
9763e12c5d1SDavid du Colombier if(Eintr()){
9773e12c5d1SDavid du Colombier pchr(err, '\n');
9783e12c5d1SDavid du Colombier p->eof = 0;
9793e12c5d1SDavid du Colombier }
9803e12c5d1SDavid du Colombier --p->pc; /* go back for next command */
9813e12c5d1SDavid du Colombier }
9823e12c5d1SDavid du Colombier }
9833e12c5d1SDavid du Colombier else{
9847dd7cddfSDavid du Colombier ntrap = 0; /* avoid double-interrupts during blocked writes */
9853e12c5d1SDavid du Colombier --p->pc; /* re-execute Xrdcmds after codebuf runs */
9863e12c5d1SDavid du Colombier start(codebuf, 1, runq->local);
9873e12c5d1SDavid du Colombier }
9883e12c5d1SDavid du Colombier freenodes();
9893e12c5d1SDavid du Colombier }
990dc5a79c1SDavid du Colombier
991dc5a79c1SDavid du Colombier void
pargv0(io * f)992c6df1444SDavid du Colombier pargv0(io *f)
9933e12c5d1SDavid du Colombier {
9949a747e4fSDavid du Colombier if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
995c6df1444SDavid du Colombier pfmt(f, "rc: ");
9969a747e4fSDavid du Colombier else
997c6df1444SDavid du Colombier pfmt(f, "rc (%s): ", argv0);
998c6df1444SDavid du Colombier }
999c6df1444SDavid du Colombier
1000c6df1444SDavid du Colombier void
hisfault(io * f)1001c6df1444SDavid du Colombier hisfault(io *f)
1002c6df1444SDavid du Colombier {
1003c6df1444SDavid du Colombier thread *t;
1004c6df1444SDavid du Colombier
1005c6df1444SDavid du Colombier for(t = runq; !t->cmdfile && t->ret != 0; t = t->ret)
1006c6df1444SDavid du Colombier ;
1007c6df1444SDavid du Colombier if(t->cmdfile && !t->iflag)
1008c6df1444SDavid du Colombier pfmt(f, "%s:%d ", t->cmdfile, t->lineno);
1009c6df1444SDavid du Colombier }
1010c6df1444SDavid du Colombier
1011c6df1444SDavid du Colombier void
Xerror(char * s)1012c6df1444SDavid du Colombier Xerror(char *s)
1013c6df1444SDavid du Colombier {
1014c6df1444SDavid du Colombier io *msg = openstr();
1015c6df1444SDavid du Colombier
1016c6df1444SDavid du Colombier pargv0(msg);
1017c6df1444SDavid du Colombier hisfault(msg); /* capture errstr before another sys call */
1018c6df1444SDavid du Colombier pfmt(err, "%s%s: %r\n", (char *)msg->strp, s);
1019c6df1444SDavid du Colombier closeio(msg);
10209a747e4fSDavid du Colombier flush(err);
1021d3907fe5SDavid du Colombier setstatus("error");
10229a747e4fSDavid du Colombier while(!runq->iflag) Xreturn();
10239a747e4fSDavid du Colombier }
1024dc5a79c1SDavid du Colombier
1025dc5a79c1SDavid du Colombier void
Xerror1(char * s)1026c6df1444SDavid du Colombier Xerror1(char *s) /* omit errstr */
10279a747e4fSDavid du Colombier {
1028c6df1444SDavid du Colombier pargv0(err);
1029c6df1444SDavid du Colombier hisfault(err);
1030c6df1444SDavid du Colombier pfmt(err, "%s\n", s);
10313e12c5d1SDavid du Colombier flush(err);
1032d3907fe5SDavid du Colombier setstatus("error");
10333e12c5d1SDavid du Colombier while(!runq->iflag) Xreturn();
10343e12c5d1SDavid du Colombier }
1035dc5a79c1SDavid du Colombier
1036dc5a79c1SDavid du Colombier void
setstatus(char * s)1037dc5a79c1SDavid du Colombier setstatus(char *s)
10383e12c5d1SDavid du Colombier {
10393e12c5d1SDavid du Colombier setvar("status", newword(s, (word *)0));
10403e12c5d1SDavid du Colombier }
1041dc5a79c1SDavid du Colombier
1042dc5a79c1SDavid du Colombier char*
getstatus(void)1043dc5a79c1SDavid du Colombier getstatus(void)
1044dc5a79c1SDavid du Colombier {
10453e12c5d1SDavid du Colombier var *status = vlook("status");
10463e12c5d1SDavid du Colombier return status->val?status->val->word:"";
10473e12c5d1SDavid du Colombier }
1048dc5a79c1SDavid du Colombier
1049dc5a79c1SDavid du Colombier int
truestatus(void)1050dc5a79c1SDavid du Colombier truestatus(void)
1051dc5a79c1SDavid du Colombier {
10523e12c5d1SDavid du Colombier char *s;
10533e12c5d1SDavid du Colombier for(s = getstatus();*s;s++)
1054dc5a79c1SDavid du Colombier if(*s!='|' && *s!='0')
1055dc5a79c1SDavid du Colombier return 0;
10563e12c5d1SDavid du Colombier return 1;
10573e12c5d1SDavid du Colombier }
1058dc5a79c1SDavid du Colombier
1059dc5a79c1SDavid du Colombier void
Xdelhere(void)1060dc5a79c1SDavid du Colombier Xdelhere(void)
1061dc5a79c1SDavid du Colombier {
10623e12c5d1SDavid du Colombier Unlink(runq->code[runq->pc++].s);
10633e12c5d1SDavid du Colombier }
1064dc5a79c1SDavid du Colombier
1065dc5a79c1SDavid du Colombier void
Xfor(void)1066dc5a79c1SDavid du Colombier Xfor(void)
1067dc5a79c1SDavid du Colombier {
10683e12c5d1SDavid du Colombier if(runq->argv->words==0){
10693e12c5d1SDavid du Colombier poplist();
10703e12c5d1SDavid du Colombier runq->pc = runq->code[runq->pc].i;
10713e12c5d1SDavid du Colombier }
10723e12c5d1SDavid du Colombier else{
10733e12c5d1SDavid du Colombier freelist(runq->local->val);
10743e12c5d1SDavid du Colombier runq->local->val = runq->argv->words;
10753e12c5d1SDavid du Colombier runq->local->changed = 1;
10763e12c5d1SDavid du Colombier runq->argv->words = runq->argv->words->next;
10773e12c5d1SDavid du Colombier runq->local->val->next = 0;
10783e12c5d1SDavid du Colombier runq->pc++;
10793e12c5d1SDavid du Colombier }
10803e12c5d1SDavid du Colombier }
1081dc5a79c1SDavid du Colombier
1082dc5a79c1SDavid du Colombier void
Xglob(void)1083dc5a79c1SDavid du Colombier Xglob(void)
1084dc5a79c1SDavid du Colombier {
10853e12c5d1SDavid du Colombier globlist();
10863e12c5d1SDavid du Colombier }
1087