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 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* 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 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 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 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 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 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 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 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 115dc5a79c1SDavid du Colombier var* 116dc5a79c1SDavid du Colombier newvar(char *name, var *next) 1173e12c5d1SDavid du Colombier { 1183e12c5d1SDavid du Colombier var *v = new(var); 119c6df1444SDavid du Colombier 120c6df1444SDavid du Colombier assert(name != nil); 1213e12c5d1SDavid du Colombier v->name = name; 1223e12c5d1SDavid du Colombier v->val = 0; 1233e12c5d1SDavid du Colombier v->fn = 0; 1243e12c5d1SDavid du Colombier v->changed = 0; 1253e12c5d1SDavid du Colombier v->fnchanged = 0; 1263e12c5d1SDavid du Colombier v->next = next; 1273e12c5d1SDavid du Colombier return v; 1283e12c5d1SDavid du Colombier } 129c6df1444SDavid du Colombier 130c6df1444SDavid du Colombier /* fabricate bootstrap code (*=(argv);. /rc/lib/rcmain $*; exit) */ 131c6df1444SDavid du Colombier static void 132c6df1444SDavid du Colombier loadboot(code *base, int nel, char *rcmain) 133c6df1444SDavid du Colombier { 134c6df1444SDavid du Colombier code *bs; 135c6df1444SDavid du Colombier 136c6df1444SDavid du Colombier bs = base; 137c6df1444SDavid du Colombier bs++->i = 1; /* reference count */ 138c6df1444SDavid du Colombier bs++->f = Xmark; /* "* = $*" */ 139c6df1444SDavid du Colombier bs++->f = Xword; 140c6df1444SDavid du Colombier bs++->s="*"; 141c6df1444SDavid du Colombier bs++->f = Xassign; 142c6df1444SDavid du Colombier bs++->f = Xmark; 143c6df1444SDavid du Colombier bs++->f = Xmark; 144c6df1444SDavid du Colombier bs++->f = Xword; 145c6df1444SDavid du Colombier bs++->s="*"; 146c6df1444SDavid du Colombier bs++->f = Xdol; 147c6df1444SDavid du Colombier bs++->f = Xword; 148c6df1444SDavid du Colombier bs++->s = rcmain; /* ". /rc/lib/rcmain $*" */ 149c6df1444SDavid du Colombier bs++->f = Xword; 150c6df1444SDavid du Colombier bs++->s="."; 151c6df1444SDavid du Colombier bs++->f = Xsimple; 152c6df1444SDavid du Colombier bs++->f = Xexit; /* exit */ 153c6df1444SDavid du Colombier bs++->i = 0; /* not reached */ 154c6df1444SDavid du Colombier if (bs > base + nel) 155c6df1444SDavid du Colombier panic("bootstrap array too small", 0); 156c6df1444SDavid du Colombier } 157c6df1444SDavid du Colombier 158c6df1444SDavid du Colombier void 159c6df1444SDavid du Colombier usage(void) 160c6df1444SDavid du Colombier { 161c6df1444SDavid du Colombier pfmt(err, "Usage: rc [-srdiIlxepvV] [-c arg] [-m command] " 162c6df1444SDavid du Colombier "[file [arg ...]]\n"); 163c6df1444SDavid du Colombier Exit("bad flags"); 164c6df1444SDavid du Colombier } 165c6df1444SDavid du Colombier 1663e12c5d1SDavid du Colombier /* 1673e12c5d1SDavid du Colombier * get command line flags, initialize keywords & traps. 1683e12c5d1SDavid du Colombier * get values from environment. 1693e12c5d1SDavid du Colombier * set $pid, $cflag, $* 170c6df1444SDavid du Colombier * fabricate bootstrap code and start it 1713e12c5d1SDavid du Colombier * start interpreting code 1723e12c5d1SDavid du Colombier */ 173dc5a79c1SDavid du Colombier void 174dc5a79c1SDavid du Colombier main(int argc, char *argv[]) 1753e12c5d1SDavid du Colombier { 1763e12c5d1SDavid du Colombier code bootstrap[17]; 177c6df1444SDavid du Colombier char num[12]; 1783e12c5d1SDavid du Colombier int i; 179c6df1444SDavid du Colombier 180c6df1444SDavid du Colombier err = openfd(2); 181c6df1444SDavid du Colombier ARGBEGIN { 182c6df1444SDavid du Colombier case 'd': case 'e': case 'i': case 'l': 183c6df1444SDavid du Colombier case 'p': case 'r': case 's': case 'v': 184c6df1444SDavid du Colombier case 'x': case 'I': case 'V': 185c6df1444SDavid du Colombier flag[ARGC()] = flagset; 186c6df1444SDavid du Colombier break; 187c6df1444SDavid du Colombier case 'c': 188c6df1444SDavid du Colombier case 'm': 189c6df1444SDavid du Colombier if (flag[ARGC()]) 190c6df1444SDavid du Colombier usage(); 191c6df1444SDavid du Colombier flag[ARGC()] = EARGF(usage()); 192c6df1444SDavid du Colombier break; 193c6df1444SDavid du Colombier default: 194c6df1444SDavid du Colombier usage(); 195c6df1444SDavid du Colombier break; 196c6df1444SDavid du Colombier } ARGEND 197c6df1444SDavid du Colombier if(argc < 0) 198c6df1444SDavid du Colombier usage(); 199c6df1444SDavid du Colombier if(argv0 == nil) 200c6df1444SDavid du Colombier argv0 = "rc"; 201c6df1444SDavid du Colombier if(argv0[0]=='-') /* login shell? */ 202dc5a79c1SDavid du Colombier flag['l'] = flagset; 203dc5a79c1SDavid du Colombier if(flag['I']) 204dc5a79c1SDavid du Colombier flag['i'] = 0; 205c6df1444SDavid du Colombier else if(flag['i']==0 && argc==0 && Isatty(0)) 206c6df1444SDavid du Colombier flag['i'] = flagset; /* force interactive */ 207c6df1444SDavid du Colombier 2083e12c5d1SDavid du Colombier kinit(); 2093e12c5d1SDavid du Colombier Trapinit(); 2103e12c5d1SDavid du Colombier Vinit(); 211dc5a79c1SDavid du Colombier inttoascii(num, mypid = getpid()); 2123e12c5d1SDavid du Colombier setvar("pid", newword(num, (word *)0)); 213c6df1444SDavid du Colombier setvar("cflag", flag['c']? newword(flag['c'], (word *)0): (word *)0); 214c6df1444SDavid du Colombier setvar("rcname", newword(argv0, (word *)0)); 215c6df1444SDavid du Colombier 216c6df1444SDavid du Colombier loadboot(bootstrap, nelem(bootstrap), (flag['m']? flag['m']: Rcmain)); 2173e12c5d1SDavid du Colombier start(bootstrap, 1, (var *)0); 2183e12c5d1SDavid du Colombier /* prime bootstrap argv */ 2193e12c5d1SDavid du Colombier pushlist(); 220c6df1444SDavid du Colombier for(i = argc-1; i >= 0; --i) 221c6df1444SDavid du Colombier pushword(argv[i]); 2223e12c5d1SDavid du Colombier for(;;){ 223dc5a79c1SDavid du Colombier if(flag['r']) 224dc5a79c1SDavid du Colombier pfnc(err, runq); 2253e12c5d1SDavid du Colombier runq->pc++; 2263e12c5d1SDavid du Colombier (*runq->code[runq->pc-1].f)(); 227dc5a79c1SDavid du Colombier if(ntrap) 228dc5a79c1SDavid du Colombier dotrap(); 2293e12c5d1SDavid du Colombier } 2303e12c5d1SDavid du Colombier } 231c6df1444SDavid du Colombier 2323e12c5d1SDavid du Colombier /* 2333e12c5d1SDavid du Colombier * Opcode routines 2343e12c5d1SDavid du Colombier * Arguments on stack (...) 2353e12c5d1SDavid du Colombier * Arguments in line [...] 2363e12c5d1SDavid du Colombier * Code in line with jump around {...} 2373e12c5d1SDavid du Colombier * 2383e12c5d1SDavid du Colombier * Xappend(file)[fd] open file to append 2393e12c5d1SDavid du Colombier * Xassign(name, val) assign val to name 2403e12c5d1SDavid du Colombier * Xasync{... Xexit} make thread for {}, no wait 241*dbee7877SDavid du Colombier * Xbackq(split){... Xreturn} make thread for {}, push stdout 2423e12c5d1SDavid du Colombier * Xbang complement condition 2433e12c5d1SDavid du Colombier * Xcase(pat, value){...} exec code on match, leave (value) on 2443e12c5d1SDavid du Colombier * stack 2453e12c5d1SDavid du Colombier * Xclose[i] close file descriptor 2463e12c5d1SDavid du Colombier * Xconc(left, right) concatenate, push results 2473e12c5d1SDavid du Colombier * Xcount(name) push var count 2483e12c5d1SDavid du Colombier * Xdelfn(name) delete function definition 2494e3613abSDavid du Colombier * Xdelhere 2503e12c5d1SDavid du Colombier * Xdol(name) get variable value 2513e12c5d1SDavid du Colombier * Xdup[i j] dup file descriptor 2524e3613abSDavid du Colombier * Xeflag 2534e3613abSDavid du Colombier * Xerror 2543e12c5d1SDavid du Colombier * Xexit rc exits with status 2553e12c5d1SDavid du Colombier * Xfalse{...} execute {} if false 2563e12c5d1SDavid du Colombier * Xfn(name){... Xreturn} define function 2573e12c5d1SDavid du Colombier * Xfor(var, list){... Xreturn} for loop 2584e3613abSDavid du Colombier * Xglob 2594e3613abSDavid du Colombier * Xif 2604e3613abSDavid du Colombier * Xifnot 2613e12c5d1SDavid du Colombier * Xjump[addr] goto 2623e12c5d1SDavid du Colombier * Xlocal(name, val) create local variable, assign value 2633e12c5d1SDavid du Colombier * Xmark mark stack 2643e12c5d1SDavid du Colombier * Xmatch(pat, str) match pattern, set status 2653e12c5d1SDavid du Colombier * Xpipe[i j]{... Xreturn}{... Xreturn} construct a pipe between 2 new threads, 2663e12c5d1SDavid du Colombier * wait for both 2673e12c5d1SDavid du Colombier * Xpipefd[type]{... Xreturn} connect {} to pipe (input or output, 2683e12c5d1SDavid du Colombier * depending on type), push /dev/fd/?? 2694e3613abSDavid du Colombier * Xpipewait 2703e12c5d1SDavid du Colombier * Xpopm(value) pop value from stack 2714e3613abSDavid du Colombier * Xpopredir 272c6df1444SDavid du Colombier * Xqdol(name) concatenate variable components 2734e3613abSDavid du Colombier * Xrdcmds 2744e3613abSDavid du Colombier * Xrdfn 275119a69faSDavid du Colombier * Xrdwr(file)[fd] open file for reading and writing 2763e12c5d1SDavid du Colombier * Xread(file)[fd] open file to read 2773e12c5d1SDavid du Colombier * Xreturn kill thread 2784e3613abSDavid du Colombier * Xsimple(args) run command and wait 279c6df1444SDavid du Colombier * Xsettrue 2804e3613abSDavid du Colombier * Xsub 2813e12c5d1SDavid du Colombier * Xsubshell{... Xexit} execute {} in a subshell and wait 2823e12c5d1SDavid du Colombier * Xtrue{...} execute {} if true 2833e12c5d1SDavid du Colombier * Xunlocal delete local variable 2844e3613abSDavid du Colombier * Xwastrue 2853e12c5d1SDavid du Colombier * Xword[string] push string 2863e12c5d1SDavid du Colombier * Xwrite(file)[fd] open file to write 2873e12c5d1SDavid du Colombier */ 288dc5a79c1SDavid du Colombier 289dc5a79c1SDavid du Colombier void 290dc5a79c1SDavid du Colombier Xappend(void) 291dc5a79c1SDavid du Colombier { 2923e12c5d1SDavid du Colombier char *file; 2933e12c5d1SDavid du Colombier int f; 2943e12c5d1SDavid du Colombier switch(count(runq->argv->words)){ 295dc5a79c1SDavid du Colombier default: 296dc5a79c1SDavid du Colombier Xerror1(">> requires singleton"); 297dc5a79c1SDavid du Colombier return; 298dc5a79c1SDavid du Colombier case 0: 299dc5a79c1SDavid du Colombier Xerror1(">> requires file"); 300dc5a79c1SDavid du Colombier return; 301dc5a79c1SDavid du Colombier case 1: 302dc5a79c1SDavid du Colombier break; 3033e12c5d1SDavid du Colombier } 3043e12c5d1SDavid du Colombier file = runq->argv->words->word; 3053e12c5d1SDavid du Colombier if((f = open(file, 1))<0 && (f = Creat(file))<0){ 3067dd7cddfSDavid du Colombier pfmt(err, "%s: ", file); 3077dd7cddfSDavid du Colombier Xerror("can't open"); 3083e12c5d1SDavid du Colombier return; 3093e12c5d1SDavid du Colombier } 310c6df1444SDavid du Colombier seek(f, 0, 2); 3113e12c5d1SDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i); 3123e12c5d1SDavid du Colombier runq->pc++; 3133e12c5d1SDavid du Colombier poplist(); 3143e12c5d1SDavid du Colombier } 315dc5a79c1SDavid du Colombier 316dc5a79c1SDavid du Colombier void 317dc5a79c1SDavid du Colombier Xsettrue(void) 318dc5a79c1SDavid du Colombier { 319219b2ee8SDavid du Colombier setstatus(""); 320219b2ee8SDavid du Colombier } 321dc5a79c1SDavid du Colombier 322dc5a79c1SDavid du Colombier void 323dc5a79c1SDavid du Colombier Xbang(void) 324dc5a79c1SDavid du Colombier { 3253e12c5d1SDavid du Colombier setstatus(truestatus()?"false":""); 3263e12c5d1SDavid du Colombier } 327dc5a79c1SDavid du Colombier 328dc5a79c1SDavid du Colombier void 329dc5a79c1SDavid du Colombier Xclose(void) 330dc5a79c1SDavid du Colombier { 3313e12c5d1SDavid du Colombier pushredir(RCLOSE, runq->code[runq->pc].i, 0); 3323e12c5d1SDavid du Colombier runq->pc++; 3333e12c5d1SDavid du Colombier } 334dc5a79c1SDavid du Colombier 335dc5a79c1SDavid du Colombier void 336dc5a79c1SDavid du Colombier Xdup(void) 337dc5a79c1SDavid du Colombier { 3383e12c5d1SDavid du Colombier pushredir(RDUP, runq->code[runq->pc].i, runq->code[runq->pc+1].i); 3393e12c5d1SDavid du Colombier runq->pc+=2; 3403e12c5d1SDavid du Colombier } 341dc5a79c1SDavid du Colombier 342dc5a79c1SDavid du Colombier void 343dc5a79c1SDavid du Colombier Xeflag(void) 344dc5a79c1SDavid du Colombier { 345219b2ee8SDavid du Colombier if(eflagok && !truestatus()) Xexit(); 346219b2ee8SDavid du Colombier } 347dc5a79c1SDavid du Colombier 348dc5a79c1SDavid du Colombier void 349dc5a79c1SDavid du Colombier Xexit(void) 350dc5a79c1SDavid du Colombier { 3513e12c5d1SDavid du Colombier struct var *trapreq; 3523e12c5d1SDavid du Colombier struct word *starval; 3533e12c5d1SDavid du Colombier static int beenhere = 0; 3543e12c5d1SDavid du Colombier if(getpid()==mypid && !beenhere){ 3553e12c5d1SDavid du Colombier trapreq = vlook("sigexit"); 3563e12c5d1SDavid du Colombier if(trapreq->fn){ 3573e12c5d1SDavid du Colombier beenhere = 1; 3583e12c5d1SDavid du Colombier --runq->pc; 359219b2ee8SDavid du Colombier starval = vlook("*")->val; 3603e12c5d1SDavid du Colombier start(trapreq->fn, trapreq->pc, (struct var *)0); 3613e12c5d1SDavid du Colombier runq->local = newvar(strdup("*"), runq->local); 3623e12c5d1SDavid du Colombier runq->local->val = copywords(starval, (struct word *)0); 3633e12c5d1SDavid du Colombier runq->local->changed = 1; 3643e12c5d1SDavid du Colombier runq->redir = runq->startredir = 0; 3653e12c5d1SDavid du Colombier return; 3663e12c5d1SDavid du Colombier } 3673e12c5d1SDavid du Colombier } 3683e12c5d1SDavid du Colombier Exit(getstatus()); 3693e12c5d1SDavid du Colombier } 370dc5a79c1SDavid du Colombier 371dc5a79c1SDavid du Colombier void 372dc5a79c1SDavid du Colombier Xfalse(void) 373dc5a79c1SDavid du Colombier { 3743e12c5d1SDavid du Colombier if(truestatus()) runq->pc = runq->code[runq->pc].i; 3753e12c5d1SDavid du Colombier else runq->pc++; 3763e12c5d1SDavid du Colombier } 3773e12c5d1SDavid du Colombier int ifnot; /* dynamic if not flag */ 378dc5a79c1SDavid du Colombier 379dc5a79c1SDavid du Colombier void 380dc5a79c1SDavid du Colombier Xifnot(void) 381dc5a79c1SDavid du Colombier { 3823e12c5d1SDavid du Colombier if(ifnot) 3833e12c5d1SDavid du Colombier runq->pc++; 3843e12c5d1SDavid du Colombier else 3853e12c5d1SDavid du Colombier runq->pc = runq->code[runq->pc].i; 3863e12c5d1SDavid du Colombier } 387dc5a79c1SDavid du Colombier 388dc5a79c1SDavid du Colombier void 389dc5a79c1SDavid du Colombier Xjump(void) 390dc5a79c1SDavid du Colombier { 3913e12c5d1SDavid du Colombier runq->pc = runq->code[runq->pc].i; 3923e12c5d1SDavid du Colombier } 393dc5a79c1SDavid du Colombier 394dc5a79c1SDavid du Colombier void 395dc5a79c1SDavid du Colombier Xmark(void) 396dc5a79c1SDavid du Colombier { 3973e12c5d1SDavid du Colombier pushlist(); 3983e12c5d1SDavid du Colombier } 399dc5a79c1SDavid du Colombier 400dc5a79c1SDavid du Colombier void 401dc5a79c1SDavid du Colombier Xpopm(void) 402dc5a79c1SDavid du Colombier { 4033e12c5d1SDavid du Colombier poplist(); 4043e12c5d1SDavid du Colombier } 405dc5a79c1SDavid du Colombier 406dc5a79c1SDavid du Colombier void 407dc5a79c1SDavid du Colombier Xread(void) 408dc5a79c1SDavid du Colombier { 4093e12c5d1SDavid du Colombier char *file; 4103e12c5d1SDavid du Colombier int f; 4113e12c5d1SDavid du Colombier switch(count(runq->argv->words)){ 412dc5a79c1SDavid du Colombier default: 413dc5a79c1SDavid du Colombier Xerror1("< requires singleton\n"); 414dc5a79c1SDavid du Colombier return; 415dc5a79c1SDavid du Colombier case 0: 416dc5a79c1SDavid du Colombier Xerror1("< requires file\n"); 417dc5a79c1SDavid du Colombier return; 418dc5a79c1SDavid du Colombier case 1: 419dc5a79c1SDavid du Colombier break; 4203e12c5d1SDavid du Colombier } 4213e12c5d1SDavid du Colombier file = runq->argv->words->word; 4223e12c5d1SDavid du Colombier if((f = open(file, 0))<0){ 4237dd7cddfSDavid du Colombier pfmt(err, "%s: ", file); 4247dd7cddfSDavid du Colombier Xerror("can't open"); 4253e12c5d1SDavid du Colombier return; 4263e12c5d1SDavid du Colombier } 4273e12c5d1SDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i); 4283e12c5d1SDavid du Colombier runq->pc++; 4293e12c5d1SDavid du Colombier poplist(); 4303e12c5d1SDavid du Colombier } 431dc5a79c1SDavid du Colombier 432dc5a79c1SDavid du Colombier void 433119a69faSDavid du Colombier Xrdwr(void) 434119a69faSDavid du Colombier { 435119a69faSDavid du Colombier char *file; 436119a69faSDavid du Colombier int f; 437119a69faSDavid du Colombier 438119a69faSDavid du Colombier switch(count(runq->argv->words)){ 439119a69faSDavid du Colombier default: 440119a69faSDavid du Colombier Xerror1("<> requires singleton\n"); 441119a69faSDavid du Colombier return; 442119a69faSDavid du Colombier case 0: 443119a69faSDavid du Colombier Xerror1("<> requires file\n"); 444119a69faSDavid du Colombier return; 445119a69faSDavid du Colombier case 1: 446119a69faSDavid du Colombier break; 447119a69faSDavid du Colombier } 448119a69faSDavid du Colombier file = runq->argv->words->word; 449119a69faSDavid du Colombier if((f = open(file, ORDWR))<0){ 450119a69faSDavid du Colombier pfmt(err, "%s: ", file); 451119a69faSDavid du Colombier Xerror("can't open"); 452119a69faSDavid du Colombier return; 453119a69faSDavid du Colombier } 454119a69faSDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i); 455119a69faSDavid du Colombier runq->pc++; 456119a69faSDavid du Colombier poplist(); 457119a69faSDavid du Colombier } 458119a69faSDavid du Colombier 459119a69faSDavid du Colombier void 460dc5a79c1SDavid du Colombier turfredir(void) 461dc5a79c1SDavid du Colombier { 4623e12c5d1SDavid du Colombier while(runq->redir!=runq->startredir) 4633e12c5d1SDavid du Colombier Xpopredir(); 4643e12c5d1SDavid du Colombier } 465dc5a79c1SDavid du Colombier 466dc5a79c1SDavid du Colombier void 467dc5a79c1SDavid du Colombier Xpopredir(void) 468dc5a79c1SDavid du Colombier { 4693e12c5d1SDavid du Colombier struct redir *rp = runq->redir; 470dc5a79c1SDavid du Colombier if(rp==0) 471dc5a79c1SDavid du Colombier panic("turfredir null!", 0); 4723e12c5d1SDavid du Colombier runq->redir = rp->next; 473dc5a79c1SDavid du Colombier if(rp->type==ROPEN) 474dc5a79c1SDavid du Colombier close(rp->from); 4753e12c5d1SDavid du Colombier efree((char *)rp); 4763e12c5d1SDavid du Colombier } 477dc5a79c1SDavid du Colombier 478dc5a79c1SDavid du Colombier void 479dc5a79c1SDavid du Colombier Xreturn(void) 480dc5a79c1SDavid du Colombier { 4813e12c5d1SDavid du Colombier struct thread *p = runq; 4823e12c5d1SDavid du Colombier turfredir(); 4833e12c5d1SDavid du Colombier while(p->argv) poplist(); 4843e12c5d1SDavid du Colombier codefree(p->code); 4853e12c5d1SDavid du Colombier runq = p->ret; 4863e12c5d1SDavid du Colombier efree((char *)p); 487dc5a79c1SDavid du Colombier if(runq==0) 488dc5a79c1SDavid du Colombier Exit(getstatus()); 4893e12c5d1SDavid du Colombier } 490dc5a79c1SDavid du Colombier 491dc5a79c1SDavid du Colombier void 492dc5a79c1SDavid du Colombier Xtrue(void) 493dc5a79c1SDavid du Colombier { 4943e12c5d1SDavid du Colombier if(truestatus()) runq->pc++; 4953e12c5d1SDavid du Colombier else runq->pc = runq->code[runq->pc].i; 4963e12c5d1SDavid du Colombier } 497dc5a79c1SDavid du Colombier 498dc5a79c1SDavid du Colombier void 499dc5a79c1SDavid du Colombier Xif(void) 500dc5a79c1SDavid du Colombier { 5013e12c5d1SDavid du Colombier ifnot = 1; 5023e12c5d1SDavid du Colombier if(truestatus()) runq->pc++; 5033e12c5d1SDavid du Colombier else runq->pc = runq->code[runq->pc].i; 5043e12c5d1SDavid du Colombier } 505dc5a79c1SDavid du Colombier 506dc5a79c1SDavid du Colombier void 507dc5a79c1SDavid du Colombier Xwastrue(void) 508dc5a79c1SDavid du Colombier { 5093e12c5d1SDavid du Colombier ifnot = 0; 5103e12c5d1SDavid du Colombier } 511dc5a79c1SDavid du Colombier 512dc5a79c1SDavid du Colombier void 513dc5a79c1SDavid du Colombier Xword(void) 514dc5a79c1SDavid du Colombier { 5153e12c5d1SDavid du Colombier pushword(runq->code[runq->pc++].s); 5163e12c5d1SDavid du Colombier } 517dc5a79c1SDavid du Colombier 518dc5a79c1SDavid du Colombier void 519dc5a79c1SDavid du Colombier Xwrite(void) 520dc5a79c1SDavid du Colombier { 5213e12c5d1SDavid du Colombier char *file; 5223e12c5d1SDavid du Colombier int f; 5233e12c5d1SDavid du Colombier switch(count(runq->argv->words)){ 524dc5a79c1SDavid du Colombier default: 525dc5a79c1SDavid du Colombier Xerror1("> requires singleton\n"); 526dc5a79c1SDavid du Colombier return; 527dc5a79c1SDavid du Colombier case 0: 528dc5a79c1SDavid du Colombier Xerror1("> requires file\n"); 529dc5a79c1SDavid du Colombier return; 530dc5a79c1SDavid du Colombier case 1: 531dc5a79c1SDavid du Colombier break; 5323e12c5d1SDavid du Colombier } 5333e12c5d1SDavid du Colombier file = runq->argv->words->word; 5343e12c5d1SDavid du Colombier if((f = Creat(file))<0){ 5357dd7cddfSDavid du Colombier pfmt(err, "%s: ", file); 5367dd7cddfSDavid du Colombier Xerror("can't open"); 5373e12c5d1SDavid du Colombier return; 5383e12c5d1SDavid du Colombier } 5393e12c5d1SDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i); 5403e12c5d1SDavid du Colombier runq->pc++; 5413e12c5d1SDavid du Colombier poplist(); 5423e12c5d1SDavid du Colombier } 543dc5a79c1SDavid du Colombier 544dc5a79c1SDavid du Colombier char* 545dc5a79c1SDavid du Colombier list2str(word *words) 546dc5a79c1SDavid du Colombier { 5473e12c5d1SDavid du Colombier char *value, *s, *t; 5483e12c5d1SDavid du Colombier int len = 0; 5493e12c5d1SDavid du Colombier word *ap; 5503e12c5d1SDavid du Colombier for(ap = words;ap;ap = ap->next) 5513e12c5d1SDavid du Colombier len+=1+strlen(ap->word); 5523e12c5d1SDavid du Colombier value = emalloc(len+1); 5533e12c5d1SDavid du Colombier s = value; 5543e12c5d1SDavid du Colombier for(ap = words;ap;ap = ap->next){ 5553e12c5d1SDavid du Colombier for(t = ap->word;*t;) *s++=*t++; 5563e12c5d1SDavid du Colombier *s++=' '; 5573e12c5d1SDavid du Colombier } 558dc5a79c1SDavid du Colombier if(s==value) 559dc5a79c1SDavid du Colombier *s='\0'; 5603e12c5d1SDavid du Colombier else s[-1]='\0'; 5613e12c5d1SDavid du Colombier return value; 5623e12c5d1SDavid du Colombier } 563dc5a79c1SDavid du Colombier 564dc5a79c1SDavid du Colombier void 565dc5a79c1SDavid du Colombier Xmatch(void) 566dc5a79c1SDavid du Colombier { 5673e12c5d1SDavid du Colombier word *p; 5683e12c5d1SDavid du Colombier char *subject; 5693e12c5d1SDavid du Colombier subject = list2str(runq->argv->words); 5703e12c5d1SDavid du Colombier setstatus("no match"); 5713e12c5d1SDavid du Colombier for(p = runq->argv->next->words;p;p = p->next) 5723e12c5d1SDavid du Colombier if(match(subject, p->word, '\0')){ 5733e12c5d1SDavid du Colombier setstatus(""); 5743e12c5d1SDavid du Colombier break; 5753e12c5d1SDavid du Colombier } 5763e12c5d1SDavid du Colombier efree(subject); 5773e12c5d1SDavid du Colombier poplist(); 5783e12c5d1SDavid du Colombier poplist(); 5793e12c5d1SDavid du Colombier } 580dc5a79c1SDavid du Colombier 581dc5a79c1SDavid du Colombier void 582dc5a79c1SDavid du Colombier Xcase(void) 583dc5a79c1SDavid du Colombier { 5843e12c5d1SDavid du Colombier word *p; 5853e12c5d1SDavid du Colombier char *s; 5863e12c5d1SDavid du Colombier int ok = 0; 5873e12c5d1SDavid du Colombier s = list2str(runq->argv->next->words); 5883e12c5d1SDavid du Colombier for(p = runq->argv->words;p;p = p->next){ 5893e12c5d1SDavid du Colombier if(match(s, p->word, '\0')){ 5903e12c5d1SDavid du Colombier ok = 1; 5913e12c5d1SDavid du Colombier break; 5923e12c5d1SDavid du Colombier } 5933e12c5d1SDavid du Colombier } 5943e12c5d1SDavid du Colombier efree(s); 5953e12c5d1SDavid du Colombier if(ok) 5963e12c5d1SDavid du Colombier runq->pc++; 5973e12c5d1SDavid du Colombier else 5983e12c5d1SDavid du Colombier runq->pc = runq->code[runq->pc].i; 5993e12c5d1SDavid du Colombier poplist(); 6003e12c5d1SDavid du Colombier } 601dc5a79c1SDavid du Colombier 602dc5a79c1SDavid du Colombier word* 603dc5a79c1SDavid du Colombier conclist(word *lp, word *rp, word *tail) 6043e12c5d1SDavid du Colombier { 6053e12c5d1SDavid du Colombier char *buf; 6063e12c5d1SDavid du Colombier word *v; 6073e12c5d1SDavid du Colombier if(lp->next || rp->next) 608276e7d6dSDavid du Colombier tail = conclist(lp->next==0? lp: lp->next, 609276e7d6dSDavid du Colombier rp->next==0? rp: rp->next, tail); 610276e7d6dSDavid du Colombier buf = emalloc(strlen(lp->word)+strlen((char *)rp->word)+1); 6113e12c5d1SDavid du Colombier strcpy(buf, lp->word); 6123e12c5d1SDavid du Colombier strcat(buf, rp->word); 6133e12c5d1SDavid du Colombier v = newword(buf, tail); 6143e12c5d1SDavid du Colombier efree(buf); 6153e12c5d1SDavid du Colombier return v; 6163e12c5d1SDavid du Colombier } 617dc5a79c1SDavid du Colombier 618dc5a79c1SDavid du Colombier void 619dc5a79c1SDavid du Colombier Xconc(void) 620dc5a79c1SDavid du Colombier { 6213e12c5d1SDavid du Colombier word *lp = runq->argv->words; 6223e12c5d1SDavid du Colombier word *rp = runq->argv->next->words; 6233e12c5d1SDavid du Colombier word *vp = runq->argv->next->next->words; 6243e12c5d1SDavid du Colombier int lc = count(lp), rc = count(rp); 6253e12c5d1SDavid du Colombier if(lc!=0 || rc!=0){ 6263e12c5d1SDavid du Colombier if(lc==0 || rc==0){ 6279a747e4fSDavid du Colombier Xerror1("null list in concatenation"); 6283e12c5d1SDavid du Colombier return; 6293e12c5d1SDavid du Colombier } 6303e12c5d1SDavid du Colombier if(lc!=1 && rc!=1 && lc!=rc){ 6319a747e4fSDavid du Colombier Xerror1("mismatched list lengths in concatenation"); 6323e12c5d1SDavid du Colombier return; 6333e12c5d1SDavid du Colombier } 6343e12c5d1SDavid du Colombier vp = conclist(lp, rp, vp); 6353e12c5d1SDavid du Colombier } 6363e12c5d1SDavid du Colombier poplist(); 6373e12c5d1SDavid du Colombier poplist(); 6383e12c5d1SDavid du Colombier runq->argv->words = vp; 6393e12c5d1SDavid du Colombier } 640dc5a79c1SDavid du Colombier 641dc5a79c1SDavid du Colombier void 642dc5a79c1SDavid du Colombier Xassign(void) 643dc5a79c1SDavid du Colombier { 6443e12c5d1SDavid du Colombier var *v; 6453e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){ 6469a747e4fSDavid du Colombier Xerror1("variable name not singleton!"); 6473e12c5d1SDavid du Colombier return; 6483e12c5d1SDavid du Colombier } 6493e12c5d1SDavid du Colombier deglob(runq->argv->words->word); 6503e12c5d1SDavid du Colombier v = vlook(runq->argv->words->word); 6513e12c5d1SDavid du Colombier poplist(); 6523e12c5d1SDavid du Colombier globlist(); 6533e12c5d1SDavid du Colombier freewords(v->val); 6543e12c5d1SDavid du Colombier v->val = runq->argv->words; 6553e12c5d1SDavid du Colombier v->changed = 1; 6563e12c5d1SDavid du Colombier runq->argv->words = 0; 6573e12c5d1SDavid du Colombier poplist(); 6583e12c5d1SDavid du Colombier } 6593e12c5d1SDavid du Colombier /* 6603e12c5d1SDavid du Colombier * copy arglist a, adding the copy to the front of tail 6613e12c5d1SDavid du Colombier */ 662dc5a79c1SDavid du Colombier 663dc5a79c1SDavid du Colombier word* 664dc5a79c1SDavid du Colombier copywords(word *a, word *tail) 6653e12c5d1SDavid du Colombier { 6663e12c5d1SDavid du Colombier word *v = 0, **end; 6673e12c5d1SDavid du Colombier for(end=&v;a;a = a->next,end=&(*end)->next) 6683e12c5d1SDavid du Colombier *end = newword(a->word, 0); 6693e12c5d1SDavid du Colombier *end = tail; 6703e12c5d1SDavid du Colombier return v; 6713e12c5d1SDavid du Colombier } 672dc5a79c1SDavid du Colombier 673dc5a79c1SDavid du Colombier void 674dc5a79c1SDavid du Colombier Xdol(void) 675dc5a79c1SDavid du Colombier { 6763e12c5d1SDavid du Colombier word *a, *star; 6773e12c5d1SDavid du Colombier char *s, *t; 6783e12c5d1SDavid du Colombier int n; 6793e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){ 6809a747e4fSDavid du Colombier Xerror1("variable name not singleton!"); 6813e12c5d1SDavid du Colombier return; 6823e12c5d1SDavid du Colombier } 6833e12c5d1SDavid du Colombier s = runq->argv->words->word; 6843e12c5d1SDavid du Colombier deglob(s); 6853e12c5d1SDavid du Colombier n = 0; 68699eb86a7SDavid du Colombier for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0'; 6873e12c5d1SDavid du Colombier a = runq->argv->next->words; 6883e12c5d1SDavid du Colombier if(n==0 || *t) 6893e12c5d1SDavid du Colombier a = copywords(vlook(s)->val, a); 6903e12c5d1SDavid du Colombier else{ 6913e12c5d1SDavid du Colombier star = vlook("*")->val; 6923e12c5d1SDavid du Colombier if(star && 1<=n && n<=count(star)){ 69399eb86a7SDavid du Colombier while(--n) star = star->next; 6943e12c5d1SDavid du Colombier a = newword(star->word, a); 6953e12c5d1SDavid du Colombier } 6963e12c5d1SDavid du Colombier } 6973e12c5d1SDavid du Colombier poplist(); 6983e12c5d1SDavid du Colombier runq->argv->words = a; 6993e12c5d1SDavid du Colombier } 700dc5a79c1SDavid du Colombier 701dc5a79c1SDavid du Colombier void 702dc5a79c1SDavid du Colombier Xqdol(void) 703dc5a79c1SDavid du Colombier { 7043e12c5d1SDavid du Colombier word *a, *p; 7053e12c5d1SDavid du Colombier char *s; 7063e12c5d1SDavid du Colombier int n; 7073e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){ 7089a747e4fSDavid du Colombier Xerror1("variable name not singleton!"); 7093e12c5d1SDavid du Colombier return; 7103e12c5d1SDavid du Colombier } 7113e12c5d1SDavid du Colombier s = runq->argv->words->word; 7123e12c5d1SDavid du Colombier deglob(s); 7133e12c5d1SDavid du Colombier a = vlook(s)->val; 7143e12c5d1SDavid du Colombier poplist(); 7153e12c5d1SDavid du Colombier n = count(a); 7163e12c5d1SDavid du Colombier if(n==0){ 7173e12c5d1SDavid du Colombier pushword(""); 7183e12c5d1SDavid du Colombier return; 7193e12c5d1SDavid du Colombier } 7203e12c5d1SDavid du Colombier for(p = a;p;p = p->next) n+=strlen(p->word); 7213e12c5d1SDavid du Colombier s = emalloc(n); 7223e12c5d1SDavid du Colombier if(a){ 7233e12c5d1SDavid du Colombier strcpy(s, a->word); 7243e12c5d1SDavid du Colombier for(p = a->next;p;p = p->next){ 7253e12c5d1SDavid du Colombier strcat(s, " "); 7263e12c5d1SDavid du Colombier strcat(s, p->word); 7273e12c5d1SDavid du Colombier } 7283e12c5d1SDavid du Colombier } 7293e12c5d1SDavid du Colombier else 7303e12c5d1SDavid du Colombier s[0]='\0'; 7313e12c5d1SDavid du Colombier pushword(s); 7323e12c5d1SDavid du Colombier efree(s); 7333e12c5d1SDavid du Colombier } 734dc5a79c1SDavid du Colombier 735dc5a79c1SDavid du Colombier word* 7365e061cc0SDavid du Colombier copynwords(word *a, word *tail, int n) 7375e061cc0SDavid du Colombier { 7385e061cc0SDavid du Colombier word *v, **end; 7395e061cc0SDavid du Colombier 7405e061cc0SDavid du Colombier v = 0; 7415e061cc0SDavid du Colombier end = &v; 7425e061cc0SDavid du Colombier while(n-- > 0){ 7435e061cc0SDavid du Colombier *end = newword(a->word, 0); 7445e061cc0SDavid du Colombier end = &(*end)->next; 7455e061cc0SDavid du Colombier a = a->next; 7465e061cc0SDavid du Colombier } 7475e061cc0SDavid du Colombier *end = tail; 7485e061cc0SDavid du Colombier return v; 7495e061cc0SDavid du Colombier } 7505e061cc0SDavid du Colombier 7515e061cc0SDavid du Colombier word* 752dc5a79c1SDavid du Colombier subwords(word *val, int len, word *sub, word *a) 7533e12c5d1SDavid du Colombier { 7545e061cc0SDavid du Colombier int n, m; 7553e12c5d1SDavid du Colombier char *s; 756dc5a79c1SDavid du Colombier if(!sub) 757dc5a79c1SDavid du Colombier return a; 7583e12c5d1SDavid du Colombier a = subwords(val, len, sub->next, a); 7593e12c5d1SDavid du Colombier s = sub->word; 7603e12c5d1SDavid du Colombier deglob(s); 7615e061cc0SDavid du Colombier m = 0; 7623e12c5d1SDavid du Colombier n = 0; 7635e061cc0SDavid du Colombier while('0'<=*s && *s<='9') 7645e061cc0SDavid du Colombier n = n*10+ *s++ -'0'; 7655e061cc0SDavid du Colombier if(*s == '-'){ 7665e061cc0SDavid du Colombier if(*++s == 0) 7675e061cc0SDavid du Colombier m = len - n; 7685e061cc0SDavid du Colombier else{ 7695e061cc0SDavid du Colombier while('0'<=*s && *s<='9') 7705e061cc0SDavid du Colombier m = m*10+ *s++ -'0'; 7715e061cc0SDavid du Colombier m -= n; 7725e061cc0SDavid du Colombier } 7735e061cc0SDavid du Colombier } 7745e061cc0SDavid du Colombier if(n<1 || n>len || m<0) 775dc5a79c1SDavid du Colombier return a; 7765e061cc0SDavid du Colombier if(n+m>len) 7775e061cc0SDavid du Colombier m = len-n; 7785e061cc0SDavid du Colombier while(--n > 0) 7795e061cc0SDavid du Colombier val = val->next; 7805e061cc0SDavid du Colombier return copynwords(val, a, m+1); 7813e12c5d1SDavid du Colombier } 782dc5a79c1SDavid du Colombier 783dc5a79c1SDavid du Colombier void 784dc5a79c1SDavid du Colombier Xsub(void) 785dc5a79c1SDavid du Colombier { 7863e12c5d1SDavid du Colombier word *a, *v; 7873e12c5d1SDavid du Colombier char *s; 7883e12c5d1SDavid du Colombier if(count(runq->argv->next->words)!=1){ 7899a747e4fSDavid du Colombier Xerror1("variable name not singleton!"); 7903e12c5d1SDavid du Colombier return; 7913e12c5d1SDavid du Colombier } 7923e12c5d1SDavid du Colombier s = runq->argv->next->words->word; 7933e12c5d1SDavid du Colombier deglob(s); 7943e12c5d1SDavid du Colombier a = runq->argv->next->next->words; 7953e12c5d1SDavid du Colombier v = vlook(s)->val; 7963e12c5d1SDavid du Colombier a = subwords(v, count(v), runq->argv->words, a); 7973e12c5d1SDavid du Colombier poplist(); 7983e12c5d1SDavid du Colombier poplist(); 7993e12c5d1SDavid du Colombier runq->argv->words = a; 8003e12c5d1SDavid du Colombier } 801dc5a79c1SDavid du Colombier 802dc5a79c1SDavid du Colombier void 803dc5a79c1SDavid du Colombier Xcount(void) 804dc5a79c1SDavid du Colombier { 8053e12c5d1SDavid du Colombier word *a; 8063e12c5d1SDavid du Colombier char *s, *t; 8073e12c5d1SDavid du Colombier int n; 8083e12c5d1SDavid du Colombier char num[12]; 8093e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){ 8109a747e4fSDavid du Colombier Xerror1("variable name not singleton!"); 8113e12c5d1SDavid du Colombier return; 8123e12c5d1SDavid du Colombier } 8133e12c5d1SDavid du Colombier s = runq->argv->words->word; 8143e12c5d1SDavid du Colombier deglob(s); 8153e12c5d1SDavid du Colombier n = 0; 8163e12c5d1SDavid du Colombier for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0'; 8173e12c5d1SDavid du Colombier if(n==0 || *t){ 8183e12c5d1SDavid du Colombier a = vlook(s)->val; 819dc5a79c1SDavid du Colombier inttoascii(num, count(a)); 8203e12c5d1SDavid du Colombier } 8213e12c5d1SDavid du Colombier else{ 8223e12c5d1SDavid du Colombier a = vlook("*")->val; 823dc5a79c1SDavid du Colombier inttoascii(num, a && 1<=n && n<=count(a)?1:0); 8243e12c5d1SDavid du Colombier } 8253e12c5d1SDavid du Colombier poplist(); 8263e12c5d1SDavid du Colombier pushword(num); 8273e12c5d1SDavid du Colombier } 828dc5a79c1SDavid du Colombier 829dc5a79c1SDavid du Colombier void 830dc5a79c1SDavid du Colombier Xlocal(void) 831dc5a79c1SDavid du Colombier { 8323e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){ 8339a747e4fSDavid du Colombier Xerror1("variable name must be singleton\n"); 8343e12c5d1SDavid du Colombier return; 8353e12c5d1SDavid du Colombier } 8363e12c5d1SDavid du Colombier deglob(runq->argv->words->word); 8373e12c5d1SDavid du Colombier runq->local = newvar(strdup(runq->argv->words->word), runq->local); 8383e12c5d1SDavid du Colombier poplist(); 839fed0fa9eSDavid du Colombier globlist(); 840fed0fa9eSDavid du Colombier runq->local->val = runq->argv->words; 841fed0fa9eSDavid du Colombier runq->local->changed = 1; 842fed0fa9eSDavid du Colombier runq->argv->words = 0; 8433e12c5d1SDavid du Colombier poplist(); 8443e12c5d1SDavid du Colombier } 845dc5a79c1SDavid du Colombier 846dc5a79c1SDavid du Colombier void 847dc5a79c1SDavid du Colombier Xunlocal(void) 848dc5a79c1SDavid du Colombier { 8493e12c5d1SDavid du Colombier var *v = runq->local, *hid; 850dc5a79c1SDavid du Colombier if(v==0) 851dc5a79c1SDavid du Colombier panic("Xunlocal: no locals!", 0); 8523e12c5d1SDavid du Colombier runq->local = v->next; 8533e12c5d1SDavid du Colombier hid = vlook(v->name); 8543e12c5d1SDavid du Colombier hid->changed = 1; 8553e12c5d1SDavid du Colombier efree(v->name); 8563e12c5d1SDavid du Colombier freewords(v->val); 8573e12c5d1SDavid du Colombier efree((char *)v); 8583e12c5d1SDavid du Colombier } 859dc5a79c1SDavid du Colombier 860dc5a79c1SDavid du Colombier void 861dc5a79c1SDavid du Colombier freewords(word *w) 8623e12c5d1SDavid du Colombier { 8633e12c5d1SDavid du Colombier word *nw; 8643e12c5d1SDavid du Colombier while(w){ 8653e12c5d1SDavid du Colombier efree(w->word); 8663e12c5d1SDavid du Colombier nw = w->next; 8673e12c5d1SDavid du Colombier efree((char *)w); 8683e12c5d1SDavid du Colombier w = nw; 8693e12c5d1SDavid du Colombier } 8703e12c5d1SDavid du Colombier } 871dc5a79c1SDavid du Colombier 872dc5a79c1SDavid du Colombier void 873dc5a79c1SDavid du Colombier Xfn(void) 874dc5a79c1SDavid du Colombier { 8753e12c5d1SDavid du Colombier var *v; 8763e12c5d1SDavid du Colombier word *a; 8773e12c5d1SDavid du Colombier int end; 8783e12c5d1SDavid du Colombier end = runq->code[runq->pc].i; 879fed0fa9eSDavid du Colombier globlist(); 8803e12c5d1SDavid du Colombier for(a = runq->argv->words;a;a = a->next){ 8813e12c5d1SDavid du Colombier v = gvlook(a->word); 882dc5a79c1SDavid du Colombier if(v->fn) 883dc5a79c1SDavid du Colombier codefree(v->fn); 8843e12c5d1SDavid du Colombier v->fn = codecopy(runq->code); 8853e12c5d1SDavid du Colombier v->pc = runq->pc+2; 8863e12c5d1SDavid du Colombier v->fnchanged = 1; 8873e12c5d1SDavid du Colombier } 8883e12c5d1SDavid du Colombier runq->pc = end; 8893e12c5d1SDavid du Colombier poplist(); 8903e12c5d1SDavid du Colombier } 891dc5a79c1SDavid du Colombier 892dc5a79c1SDavid du Colombier void 893dc5a79c1SDavid du Colombier Xdelfn(void) 894dc5a79c1SDavid du Colombier { 8953e12c5d1SDavid du Colombier var *v; 8963e12c5d1SDavid du Colombier word *a; 8973e12c5d1SDavid du Colombier for(a = runq->argv->words;a;a = a->next){ 8983e12c5d1SDavid du Colombier v = gvlook(a->word); 899dc5a79c1SDavid du Colombier if(v->fn) 900dc5a79c1SDavid du Colombier codefree(v->fn); 9013e12c5d1SDavid du Colombier v->fn = 0; 9023e12c5d1SDavid du Colombier v->fnchanged = 1; 9033e12c5d1SDavid du Colombier } 9043e12c5d1SDavid du Colombier poplist(); 9053e12c5d1SDavid du Colombier } 906dc5a79c1SDavid du Colombier 907dc5a79c1SDavid du Colombier char* 908dc5a79c1SDavid du Colombier concstatus(char *s, char *t) 9093e12c5d1SDavid du Colombier { 9103e12c5d1SDavid du Colombier static char v[NSTATUS+1]; 9113e12c5d1SDavid du Colombier int n = strlen(s); 9123e12c5d1SDavid du Colombier strncpy(v, s, NSTATUS); 9133e12c5d1SDavid du Colombier if(n<NSTATUS){ 9143e12c5d1SDavid du Colombier v[n]='|'; 9153e12c5d1SDavid du Colombier strncpy(v+n+1, t, NSTATUS-n-1); 9163e12c5d1SDavid du Colombier } 9173e12c5d1SDavid du Colombier v[NSTATUS]='\0'; 9183e12c5d1SDavid du Colombier return v; 9193e12c5d1SDavid du Colombier } 920dc5a79c1SDavid du Colombier 921dc5a79c1SDavid du Colombier void 922dc5a79c1SDavid du Colombier Xpipewait(void) 923dc5a79c1SDavid du Colombier { 9243e12c5d1SDavid du Colombier char status[NSTATUS+1]; 9253e12c5d1SDavid du Colombier if(runq->pid==-1) 9263e12c5d1SDavid du Colombier setstatus(concstatus(runq->status, getstatus())); 9273e12c5d1SDavid du Colombier else{ 9283e12c5d1SDavid du Colombier strncpy(status, getstatus(), NSTATUS); 9293e12c5d1SDavid du Colombier status[NSTATUS]='\0'; 9303e12c5d1SDavid du Colombier Waitfor(runq->pid, 1); 9313e12c5d1SDavid du Colombier runq->pid=-1; 9323e12c5d1SDavid du Colombier setstatus(concstatus(getstatus(), status)); 9333e12c5d1SDavid du Colombier } 9343e12c5d1SDavid du Colombier } 935dc5a79c1SDavid du Colombier 936dc5a79c1SDavid du Colombier void 937dc5a79c1SDavid du Colombier Xrdcmds(void) 938dc5a79c1SDavid du Colombier { 9393e12c5d1SDavid du Colombier struct thread *p = runq; 9403e12c5d1SDavid du Colombier word *prompt; 9413e12c5d1SDavid du Colombier flush(err); 9423e12c5d1SDavid du Colombier nerror = 0; 9433e12c5d1SDavid du Colombier if(flag['s'] && !truestatus()) 9443e12c5d1SDavid du Colombier pfmt(err, "status=%v\n", vlook("status")->val); 9453e12c5d1SDavid du Colombier if(runq->iflag){ 9463e12c5d1SDavid du Colombier prompt = vlook("prompt")->val; 9473e12c5d1SDavid du Colombier if(prompt) 9483e12c5d1SDavid du Colombier promptstr = prompt->word; 9493e12c5d1SDavid du Colombier else 9503e12c5d1SDavid du Colombier promptstr="% "; 9513e12c5d1SDavid du Colombier } 9523e12c5d1SDavid du Colombier Noerror(); 9533e12c5d1SDavid du Colombier if(yyparse()){ 9543e12c5d1SDavid du Colombier if(!p->iflag || p->eof && !Eintr()){ 955dc5a79c1SDavid du Colombier if(p->cmdfile) 956dc5a79c1SDavid du Colombier efree(p->cmdfile); 9573e12c5d1SDavid du Colombier closeio(p->cmdfd); 9583e12c5d1SDavid du Colombier Xreturn(); /* should this be omitted? */ 9593e12c5d1SDavid du Colombier } 9603e12c5d1SDavid du Colombier else{ 9613e12c5d1SDavid du Colombier if(Eintr()){ 9623e12c5d1SDavid du Colombier pchr(err, '\n'); 9633e12c5d1SDavid du Colombier p->eof = 0; 9643e12c5d1SDavid du Colombier } 9653e12c5d1SDavid du Colombier --p->pc; /* go back for next command */ 9663e12c5d1SDavid du Colombier } 9673e12c5d1SDavid du Colombier } 9683e12c5d1SDavid du Colombier else{ 9697dd7cddfSDavid du Colombier ntrap = 0; /* avoid double-interrupts during blocked writes */ 9703e12c5d1SDavid du Colombier --p->pc; /* re-execute Xrdcmds after codebuf runs */ 9713e12c5d1SDavid du Colombier start(codebuf, 1, runq->local); 9723e12c5d1SDavid du Colombier } 9733e12c5d1SDavid du Colombier freenodes(); 9743e12c5d1SDavid du Colombier } 975dc5a79c1SDavid du Colombier 976dc5a79c1SDavid du Colombier void 977c6df1444SDavid du Colombier pargv0(io *f) 9783e12c5d1SDavid du Colombier { 9799a747e4fSDavid du Colombier if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0) 980c6df1444SDavid du Colombier pfmt(f, "rc: "); 9819a747e4fSDavid du Colombier else 982c6df1444SDavid du Colombier pfmt(f, "rc (%s): ", argv0); 983c6df1444SDavid du Colombier } 984c6df1444SDavid du Colombier 985c6df1444SDavid du Colombier void 986c6df1444SDavid du Colombier hisfault(io *f) 987c6df1444SDavid du Colombier { 988c6df1444SDavid du Colombier thread *t; 989c6df1444SDavid du Colombier 990c6df1444SDavid du Colombier for(t = runq; !t->cmdfile && t->ret != 0; t = t->ret) 991c6df1444SDavid du Colombier ; 992c6df1444SDavid du Colombier if(t->cmdfile && !t->iflag) 993c6df1444SDavid du Colombier pfmt(f, "%s:%d ", t->cmdfile, t->lineno); 994c6df1444SDavid du Colombier } 995c6df1444SDavid du Colombier 996c6df1444SDavid du Colombier void 997c6df1444SDavid du Colombier Xerror(char *s) 998c6df1444SDavid du Colombier { 999c6df1444SDavid du Colombier io *msg = openstr(); 1000c6df1444SDavid du Colombier 1001c6df1444SDavid du Colombier pargv0(msg); 1002c6df1444SDavid du Colombier hisfault(msg); /* capture errstr before another sys call */ 1003c6df1444SDavid du Colombier pfmt(err, "%s%s: %r\n", (char *)msg->strp, s); 1004c6df1444SDavid du Colombier closeio(msg); 10059a747e4fSDavid du Colombier flush(err); 1006d3907fe5SDavid du Colombier setstatus("error"); 10079a747e4fSDavid du Colombier while(!runq->iflag) Xreturn(); 10089a747e4fSDavid du Colombier } 1009dc5a79c1SDavid du Colombier 1010dc5a79c1SDavid du Colombier void 1011c6df1444SDavid du Colombier Xerror1(char *s) /* omit errstr */ 10129a747e4fSDavid du Colombier { 1013c6df1444SDavid du Colombier pargv0(err); 1014c6df1444SDavid du Colombier hisfault(err); 1015c6df1444SDavid du Colombier pfmt(err, "%s\n", s); 10163e12c5d1SDavid du Colombier flush(err); 1017d3907fe5SDavid du Colombier setstatus("error"); 10183e12c5d1SDavid du Colombier while(!runq->iflag) Xreturn(); 10193e12c5d1SDavid du Colombier } 1020dc5a79c1SDavid du Colombier 1021dc5a79c1SDavid du Colombier void 1022dc5a79c1SDavid du Colombier setstatus(char *s) 10233e12c5d1SDavid du Colombier { 10243e12c5d1SDavid du Colombier setvar("status", newword(s, (word *)0)); 10253e12c5d1SDavid du Colombier } 1026dc5a79c1SDavid du Colombier 1027dc5a79c1SDavid du Colombier char* 1028dc5a79c1SDavid du Colombier getstatus(void) 1029dc5a79c1SDavid du Colombier { 10303e12c5d1SDavid du Colombier var *status = vlook("status"); 10313e12c5d1SDavid du Colombier return status->val?status->val->word:""; 10323e12c5d1SDavid du Colombier } 1033dc5a79c1SDavid du Colombier 1034dc5a79c1SDavid du Colombier int 1035dc5a79c1SDavid du Colombier truestatus(void) 1036dc5a79c1SDavid du Colombier { 10373e12c5d1SDavid du Colombier char *s; 10383e12c5d1SDavid du Colombier for(s = getstatus();*s;s++) 1039dc5a79c1SDavid du Colombier if(*s!='|' && *s!='0') 1040dc5a79c1SDavid du Colombier return 0; 10413e12c5d1SDavid du Colombier return 1; 10423e12c5d1SDavid du Colombier } 1043dc5a79c1SDavid du Colombier 1044dc5a79c1SDavid du Colombier void 1045dc5a79c1SDavid du Colombier Xdelhere(void) 1046dc5a79c1SDavid du Colombier { 10473e12c5d1SDavid du Colombier Unlink(runq->code[runq->pc++].s); 10483e12c5d1SDavid du Colombier } 1049dc5a79c1SDavid du Colombier 1050dc5a79c1SDavid du Colombier void 1051dc5a79c1SDavid du Colombier Xfor(void) 1052dc5a79c1SDavid du Colombier { 10533e12c5d1SDavid du Colombier if(runq->argv->words==0){ 10543e12c5d1SDavid du Colombier poplist(); 10553e12c5d1SDavid du Colombier runq->pc = runq->code[runq->pc].i; 10563e12c5d1SDavid du Colombier } 10573e12c5d1SDavid du Colombier else{ 10583e12c5d1SDavid du Colombier freelist(runq->local->val); 10593e12c5d1SDavid du Colombier runq->local->val = runq->argv->words; 10603e12c5d1SDavid du Colombier runq->local->changed = 1; 10613e12c5d1SDavid du Colombier runq->argv->words = runq->argv->words->next; 10623e12c5d1SDavid du Colombier runq->local->val->next = 0; 10633e12c5d1SDavid du Colombier runq->pc++; 10643e12c5d1SDavid du Colombier } 10653e12c5d1SDavid du Colombier } 1066dc5a79c1SDavid du Colombier 1067dc5a79c1SDavid du Colombier void 1068dc5a79c1SDavid du Colombier Xglob(void) 1069dc5a79c1SDavid du Colombier { 10703e12c5d1SDavid du Colombier globlist(); 10713e12c5d1SDavid du Colombier } 1072