13e12c5d1SDavid du Colombier #include "rc.h" 23e12c5d1SDavid du Colombier #include "getflags.h" 33e12c5d1SDavid du Colombier #include "exec.h" 43e12c5d1SDavid du Colombier #include "io.h" 53e12c5d1SDavid du Colombier #include "fns.h" 63e12c5d1SDavid du Colombier /* 73e12c5d1SDavid du Colombier * Start executing the given code at the given pc with the given redirection 83e12c5d1SDavid du Colombier */ 99a747e4fSDavid du Colombier char *argv0="rc"; 10dc5a79c1SDavid du Colombier 11dc5a79c1SDavid du Colombier void 12dc5a79c1SDavid du Colombier start(code *c, int pc, var *local) 133e12c5d1SDavid du Colombier { 143e12c5d1SDavid du Colombier struct thread *p = new(struct thread); 15dc5a79c1SDavid du Colombier 163e12c5d1SDavid du Colombier p->code = codecopy(c); 173e12c5d1SDavid du Colombier p->pc = pc; 183e12c5d1SDavid du Colombier p->argv = 0; 193e12c5d1SDavid du Colombier p->redir = p->startredir = runq?runq->redir:0; 203e12c5d1SDavid du Colombier p->local = local; 213e12c5d1SDavid du Colombier p->cmdfile = 0; 223e12c5d1SDavid du Colombier p->cmdfd = 0; 233e12c5d1SDavid du Colombier p->eof = 0; 243e12c5d1SDavid du Colombier p->iflag = 0; 253e12c5d1SDavid du Colombier p->lineno = 1; 263e12c5d1SDavid du Colombier p->ret = runq; 273e12c5d1SDavid du Colombier runq = p; 283e12c5d1SDavid du Colombier } 29dc5a79c1SDavid du Colombier 30dc5a79c1SDavid du Colombier word* 31dc5a79c1SDavid du Colombier newword(char *wd, word *next) 323e12c5d1SDavid du Colombier { 333e12c5d1SDavid du Colombier word *p = new(word); 343e12c5d1SDavid du Colombier p->word = strdup(wd); 353e12c5d1SDavid du Colombier p->next = next; 363e12c5d1SDavid du Colombier return p; 373e12c5d1SDavid du Colombier } 38dc5a79c1SDavid du Colombier 39dc5a79c1SDavid du Colombier void 40dc5a79c1SDavid du Colombier pushword(char *wd) 413e12c5d1SDavid du Colombier { 42dc5a79c1SDavid du Colombier if(runq->argv==0) 43dc5a79c1SDavid du Colombier panic("pushword but no argv!", 0); 443e12c5d1SDavid du Colombier runq->argv->words = newword(wd, runq->argv->words); 453e12c5d1SDavid du Colombier } 46dc5a79c1SDavid du Colombier 47dc5a79c1SDavid du Colombier void 48dc5a79c1SDavid du Colombier popword(void) 49dc5a79c1SDavid du Colombier { 503e12c5d1SDavid du Colombier word *p; 51dc5a79c1SDavid du Colombier if(runq->argv==0) 52dc5a79c1SDavid du Colombier panic("popword but no argv!", 0); 533e12c5d1SDavid du Colombier p = runq->argv->words; 54dc5a79c1SDavid du Colombier if(p==0) 55dc5a79c1SDavid du Colombier panic("popword but no word!", 0); 563e12c5d1SDavid du Colombier runq->argv->words = p->next; 573e12c5d1SDavid du Colombier efree(p->word); 583e12c5d1SDavid du Colombier efree((char *)p); 593e12c5d1SDavid du Colombier } 60dc5a79c1SDavid du Colombier 61dc5a79c1SDavid du Colombier void 62dc5a79c1SDavid du Colombier freelist(word *w) 633e12c5d1SDavid du Colombier { 643e12c5d1SDavid du Colombier word *nw; 653e12c5d1SDavid du Colombier while(w){ 663e12c5d1SDavid du Colombier nw = w->next; 673e12c5d1SDavid du Colombier efree(w->word); 683e12c5d1SDavid du Colombier efree((char *)w); 693e12c5d1SDavid du Colombier w = nw; 703e12c5d1SDavid du Colombier } 713e12c5d1SDavid du Colombier } 72dc5a79c1SDavid du Colombier 73dc5a79c1SDavid du Colombier void 74dc5a79c1SDavid du Colombier pushlist(void) 75dc5a79c1SDavid du Colombier { 763e12c5d1SDavid du Colombier list *p = new(list); 773e12c5d1SDavid du Colombier p->next = runq->argv; 783e12c5d1SDavid du Colombier p->words = 0; 793e12c5d1SDavid du Colombier runq->argv = p; 803e12c5d1SDavid du Colombier } 81dc5a79c1SDavid du Colombier 82dc5a79c1SDavid du Colombier void 83dc5a79c1SDavid du Colombier poplist(void) 84dc5a79c1SDavid du Colombier { 853e12c5d1SDavid du Colombier list *p = runq->argv; 86dc5a79c1SDavid du Colombier if(p==0) 87dc5a79c1SDavid du Colombier panic("poplist but no argv", 0); 883e12c5d1SDavid du Colombier freelist(p->words); 893e12c5d1SDavid du Colombier runq->argv = p->next; 903e12c5d1SDavid du Colombier efree((char *)p); 913e12c5d1SDavid du Colombier } 92dc5a79c1SDavid du Colombier 93dc5a79c1SDavid du Colombier int 94dc5a79c1SDavid du Colombier count(word *w) 953e12c5d1SDavid du Colombier { 963e12c5d1SDavid du Colombier int n; 973e12c5d1SDavid du Colombier for(n = 0;w;n++) w = w->next; 983e12c5d1SDavid du Colombier return n; 993e12c5d1SDavid du Colombier } 100dc5a79c1SDavid du Colombier 101dc5a79c1SDavid du Colombier void 102dc5a79c1SDavid du Colombier pushredir(int type, int from, int to) 103dc5a79c1SDavid du Colombier { 1043e12c5d1SDavid du Colombier redir * rp = new(redir); 1053e12c5d1SDavid du Colombier rp->type = type; 1063e12c5d1SDavid du Colombier rp->from = from; 1073e12c5d1SDavid du Colombier rp->to = to; 1083e12c5d1SDavid du Colombier rp->next = runq->redir; 1093e12c5d1SDavid du Colombier runq->redir = rp; 1103e12c5d1SDavid du Colombier } 111dc5a79c1SDavid du Colombier 112dc5a79c1SDavid du Colombier var* 113dc5a79c1SDavid du Colombier newvar(char *name, var *next) 1143e12c5d1SDavid du Colombier { 1153e12c5d1SDavid du Colombier var *v = new(var); 1163e12c5d1SDavid du Colombier v->name = name; 1173e12c5d1SDavid du Colombier v->val = 0; 1183e12c5d1SDavid du Colombier v->fn = 0; 1193e12c5d1SDavid du Colombier v->changed = 0; 1203e12c5d1SDavid du Colombier v->fnchanged = 0; 1213e12c5d1SDavid du Colombier v->next = next; 1223e12c5d1SDavid du Colombier return v; 1233e12c5d1SDavid du Colombier } 1243e12c5d1SDavid du Colombier /* 1253e12c5d1SDavid du Colombier * get command line flags, initialize keywords & traps. 1263e12c5d1SDavid du Colombier * get values from environment. 1273e12c5d1SDavid du Colombier * set $pid, $cflag, $* 1283e12c5d1SDavid du Colombier * fabricate bootstrap code and start it (*=(argv);. /usr/lib/rcmain $*) 1293e12c5d1SDavid du Colombier * start interpreting code 1303e12c5d1SDavid du Colombier */ 131dc5a79c1SDavid du Colombier 132dc5a79c1SDavid du Colombier void 133dc5a79c1SDavid du Colombier main(int argc, char *argv[]) 1343e12c5d1SDavid du Colombier { 1353e12c5d1SDavid du Colombier code bootstrap[17]; 1369a747e4fSDavid du Colombier char num[12], *rcmain; 1373e12c5d1SDavid du Colombier int i; 138dc5a79c1SDavid du Colombier argc = getflags(argc, argv, "SsrdiIlxepvVc:1m:1[command]", 1); 139dc5a79c1SDavid du Colombier if(argc==-1) 140dc5a79c1SDavid du Colombier usage("[file [arg ...]]"); 141dc5a79c1SDavid du Colombier if(argv[0][0]=='-') 142dc5a79c1SDavid du Colombier flag['l'] = flagset; 143dc5a79c1SDavid du Colombier if(flag['I']) 144dc5a79c1SDavid du Colombier flag['i'] = 0; 1457dd7cddfSDavid du Colombier else if(flag['i']==0 && argc==1 && Isatty(0)) flag['i'] = flagset; 1469a747e4fSDavid du Colombier rcmain = flag['m']?flag['m'][0]:Rcmain; 1473e12c5d1SDavid du Colombier err = openfd(2); 1483e12c5d1SDavid du Colombier kinit(); 1493e12c5d1SDavid du Colombier Trapinit(); 1503e12c5d1SDavid du Colombier Vinit(); 151dc5a79c1SDavid du Colombier inttoascii(num, mypid = getpid()); 1523e12c5d1SDavid du Colombier setvar("pid", newword(num, (word *)0)); 1533e12c5d1SDavid du Colombier setvar("cflag", flag['c']?newword(flag['c'][0], (word *)0) 1543e12c5d1SDavid du Colombier :(word *)0); 155219b2ee8SDavid du Colombier setvar("rcname", newword(argv[0], (word *)0)); 1563e12c5d1SDavid du Colombier i = 0; 1573e12c5d1SDavid du Colombier bootstrap[i++].i = 1; 1583e12c5d1SDavid du Colombier bootstrap[i++].f = Xmark; 1593e12c5d1SDavid du Colombier bootstrap[i++].f = Xword; 1603e12c5d1SDavid du Colombier bootstrap[i++].s="*"; 1613e12c5d1SDavid du Colombier bootstrap[i++].f = Xassign; 1623e12c5d1SDavid du Colombier bootstrap[i++].f = Xmark; 1633e12c5d1SDavid du Colombier bootstrap[i++].f = Xmark; 1643e12c5d1SDavid du Colombier bootstrap[i++].f = Xword; 1653e12c5d1SDavid du Colombier bootstrap[i++].s="*"; 1663e12c5d1SDavid du Colombier bootstrap[i++].f = Xdol; 1673e12c5d1SDavid du Colombier bootstrap[i++].f = Xword; 1689a747e4fSDavid du Colombier bootstrap[i++].s = rcmain; 1693e12c5d1SDavid du Colombier bootstrap[i++].f = Xword; 1703e12c5d1SDavid du Colombier bootstrap[i++].s="."; 1713e12c5d1SDavid du Colombier bootstrap[i++].f = Xsimple; 1723e12c5d1SDavid du Colombier bootstrap[i++].f = Xexit; 1733e12c5d1SDavid du Colombier bootstrap[i].i = 0; 1743e12c5d1SDavid du Colombier start(bootstrap, 1, (var *)0); 1753e12c5d1SDavid du Colombier /* prime bootstrap argv */ 1763e12c5d1SDavid du Colombier pushlist(); 1779a747e4fSDavid du Colombier argv0 = strdup(argv[0]); 1783e12c5d1SDavid du Colombier for(i = argc-1;i!=0;--i) pushword(argv[i]); 1793e12c5d1SDavid du Colombier for(;;){ 180dc5a79c1SDavid du Colombier if(flag['r']) 181dc5a79c1SDavid du Colombier pfnc(err, runq); 1823e12c5d1SDavid du Colombier runq->pc++; 1833e12c5d1SDavid du Colombier (*runq->code[runq->pc-1].f)(); 184dc5a79c1SDavid du Colombier if(ntrap) 185dc5a79c1SDavid du Colombier dotrap(); 1863e12c5d1SDavid du Colombier } 1873e12c5d1SDavid du Colombier } 1883e12c5d1SDavid du Colombier /* 1893e12c5d1SDavid du Colombier * Opcode routines 1903e12c5d1SDavid du Colombier * Arguments on stack (...) 1913e12c5d1SDavid du Colombier * Arguments in line [...] 1923e12c5d1SDavid du Colombier * Code in line with jump around {...} 1933e12c5d1SDavid du Colombier * 1943e12c5d1SDavid du Colombier * Xappend(file)[fd] open file to append 1953e12c5d1SDavid du Colombier * Xassign(name, val) assign val to name 1963e12c5d1SDavid du Colombier * Xasync{... Xexit} make thread for {}, no wait 1973e12c5d1SDavid du Colombier * Xbackq{... Xreturn} make thread for {}, push stdout 1983e12c5d1SDavid du Colombier * Xbang complement condition 1993e12c5d1SDavid du Colombier * Xcase(pat, value){...} exec code on match, leave (value) on 2003e12c5d1SDavid du Colombier * stack 2013e12c5d1SDavid du Colombier * Xclose[i] close file descriptor 2023e12c5d1SDavid du Colombier * Xconc(left, right) concatenate, push results 2033e12c5d1SDavid du Colombier * Xcount(name) push var count 2043e12c5d1SDavid du Colombier * Xdelfn(name) delete function definition 2053e12c5d1SDavid du Colombier * Xdeltraps(names) delete named traps 2063e12c5d1SDavid du Colombier * Xdol(name) get variable value 2073e12c5d1SDavid du Colombier * Xqdol(name) concatenate variable components 2083e12c5d1SDavid du Colombier * Xdup[i j] dup file descriptor 2093e12c5d1SDavid du Colombier * Xexit rc exits with status 2103e12c5d1SDavid du Colombier * Xfalse{...} execute {} if false 2113e12c5d1SDavid du Colombier * Xfn(name){... Xreturn} define function 2123e12c5d1SDavid du Colombier * Xfor(var, list){... Xreturn} for loop 2133e12c5d1SDavid du Colombier * Xjump[addr] goto 2143e12c5d1SDavid du Colombier * Xlocal(name, val) create local variable, assign value 2153e12c5d1SDavid du Colombier * Xmark mark stack 2163e12c5d1SDavid du Colombier * Xmatch(pat, str) match pattern, set status 2173e12c5d1SDavid du Colombier * Xpipe[i j]{... Xreturn}{... Xreturn} construct a pipe between 2 new threads, 2183e12c5d1SDavid du Colombier * wait for both 2193e12c5d1SDavid du Colombier * Xpipefd[type]{... Xreturn} connect {} to pipe (input or output, 2203e12c5d1SDavid du Colombier * depending on type), push /dev/fd/?? 2213e12c5d1SDavid du Colombier * Xpopm(value) pop value from stack 222119a69faSDavid du Colombier * Xrdwr(file)[fd] open file for reading and writing 2233e12c5d1SDavid du Colombier * Xread(file)[fd] open file to read 2243e12c5d1SDavid du Colombier * Xsettraps(names){... Xreturn} define trap functions 2253e12c5d1SDavid du Colombier * Xshowtraps print trap list 2263e12c5d1SDavid du Colombier * Xsimple(args) run command and wait 2273e12c5d1SDavid du Colombier * Xreturn kill thread 2283e12c5d1SDavid du Colombier * Xsubshell{... Xexit} execute {} in a subshell and wait 2293e12c5d1SDavid du Colombier * Xtrue{...} execute {} if true 2303e12c5d1SDavid du Colombier * Xunlocal delete local variable 2313e12c5d1SDavid du Colombier * Xword[string] push string 2323e12c5d1SDavid du Colombier * Xwrite(file)[fd] open file to write 2333e12c5d1SDavid du Colombier */ 234dc5a79c1SDavid du Colombier 235dc5a79c1SDavid du Colombier void 236dc5a79c1SDavid du Colombier Xappend(void) 237dc5a79c1SDavid du Colombier { 2383e12c5d1SDavid du Colombier char *file; 2393e12c5d1SDavid du Colombier int f; 2403e12c5d1SDavid du Colombier switch(count(runq->argv->words)){ 241dc5a79c1SDavid du Colombier default: 242dc5a79c1SDavid du Colombier Xerror1(">> requires singleton"); 243dc5a79c1SDavid du Colombier return; 244dc5a79c1SDavid du Colombier case 0: 245dc5a79c1SDavid du Colombier Xerror1(">> requires file"); 246dc5a79c1SDavid du Colombier return; 247dc5a79c1SDavid du Colombier case 1: 248dc5a79c1SDavid du Colombier break; 2493e12c5d1SDavid du Colombier } 2503e12c5d1SDavid du Colombier file = runq->argv->words->word; 2513e12c5d1SDavid du Colombier if((f = open(file, 1))<0 && (f = Creat(file))<0){ 2527dd7cddfSDavid du Colombier pfmt(err, "%s: ", file); 2537dd7cddfSDavid du Colombier Xerror("can't open"); 2543e12c5d1SDavid du Colombier return; 2553e12c5d1SDavid du Colombier } 2563e12c5d1SDavid du Colombier Seek(f, 0L, 2); 2573e12c5d1SDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i); 2583e12c5d1SDavid du Colombier runq->pc++; 2593e12c5d1SDavid du Colombier poplist(); 2603e12c5d1SDavid du Colombier } 261dc5a79c1SDavid du Colombier 262dc5a79c1SDavid du Colombier void 263dc5a79c1SDavid du Colombier Xsettrue(void) 264dc5a79c1SDavid du Colombier { 265219b2ee8SDavid du Colombier setstatus(""); 266219b2ee8SDavid du Colombier } 267dc5a79c1SDavid du Colombier 268dc5a79c1SDavid du Colombier void 269dc5a79c1SDavid du Colombier Xbang(void) 270dc5a79c1SDavid du Colombier { 2713e12c5d1SDavid du Colombier setstatus(truestatus()?"false":""); 2723e12c5d1SDavid du Colombier } 273dc5a79c1SDavid du Colombier 274dc5a79c1SDavid du Colombier void 275dc5a79c1SDavid du Colombier Xclose(void) 276dc5a79c1SDavid du Colombier { 2773e12c5d1SDavid du Colombier pushredir(RCLOSE, runq->code[runq->pc].i, 0); 2783e12c5d1SDavid du Colombier runq->pc++; 2793e12c5d1SDavid du Colombier } 280dc5a79c1SDavid du Colombier 281dc5a79c1SDavid du Colombier void 282dc5a79c1SDavid du Colombier Xdup(void) 283dc5a79c1SDavid du Colombier { 2843e12c5d1SDavid du Colombier pushredir(RDUP, runq->code[runq->pc].i, runq->code[runq->pc+1].i); 2853e12c5d1SDavid du Colombier runq->pc+=2; 2863e12c5d1SDavid du Colombier } 287dc5a79c1SDavid du Colombier 288dc5a79c1SDavid du Colombier void 289dc5a79c1SDavid du Colombier Xeflag(void) 290dc5a79c1SDavid du Colombier { 291219b2ee8SDavid du Colombier if(eflagok && !truestatus()) Xexit(); 292219b2ee8SDavid du Colombier } 293dc5a79c1SDavid du Colombier 294dc5a79c1SDavid du Colombier void 295dc5a79c1SDavid du Colombier Xexit(void) 296dc5a79c1SDavid du Colombier { 2973e12c5d1SDavid du Colombier struct var *trapreq; 2983e12c5d1SDavid du Colombier struct word *starval; 2993e12c5d1SDavid du Colombier static int beenhere = 0; 3003e12c5d1SDavid du Colombier if(getpid()==mypid && !beenhere){ 3013e12c5d1SDavid du Colombier trapreq = vlook("sigexit"); 3023e12c5d1SDavid du Colombier if(trapreq->fn){ 3033e12c5d1SDavid du Colombier beenhere = 1; 3043e12c5d1SDavid du Colombier --runq->pc; 305219b2ee8SDavid du Colombier starval = vlook("*")->val; 3063e12c5d1SDavid du Colombier start(trapreq->fn, trapreq->pc, (struct var *)0); 3073e12c5d1SDavid du Colombier runq->local = newvar(strdup("*"), runq->local); 3083e12c5d1SDavid du Colombier runq->local->val = copywords(starval, (struct word *)0); 3093e12c5d1SDavid du Colombier runq->local->changed = 1; 3103e12c5d1SDavid du Colombier runq->redir = runq->startredir = 0; 3113e12c5d1SDavid du Colombier return; 3123e12c5d1SDavid du Colombier } 3133e12c5d1SDavid du Colombier } 3143e12c5d1SDavid du Colombier Exit(getstatus()); 3153e12c5d1SDavid du Colombier } 316dc5a79c1SDavid du Colombier 317dc5a79c1SDavid du Colombier void 318dc5a79c1SDavid du Colombier Xfalse(void) 319dc5a79c1SDavid du Colombier { 3203e12c5d1SDavid du Colombier if(truestatus()) runq->pc = runq->code[runq->pc].i; 3213e12c5d1SDavid du Colombier else runq->pc++; 3223e12c5d1SDavid du Colombier } 3233e12c5d1SDavid du Colombier int ifnot; /* dynamic if not flag */ 324dc5a79c1SDavid du Colombier 325dc5a79c1SDavid du Colombier void 326dc5a79c1SDavid du Colombier Xifnot(void) 327dc5a79c1SDavid du Colombier { 3283e12c5d1SDavid du Colombier if(ifnot) 3293e12c5d1SDavid du Colombier runq->pc++; 3303e12c5d1SDavid du Colombier else 3313e12c5d1SDavid du Colombier runq->pc = runq->code[runq->pc].i; 3323e12c5d1SDavid du Colombier } 333dc5a79c1SDavid du Colombier 334dc5a79c1SDavid du Colombier void 335dc5a79c1SDavid du Colombier Xjump(void) 336dc5a79c1SDavid du Colombier { 3373e12c5d1SDavid du Colombier runq->pc = runq->code[runq->pc].i; 3383e12c5d1SDavid du Colombier } 339dc5a79c1SDavid du Colombier 340dc5a79c1SDavid du Colombier void 341dc5a79c1SDavid du Colombier Xmark(void) 342dc5a79c1SDavid du Colombier { 3433e12c5d1SDavid du Colombier pushlist(); 3443e12c5d1SDavid du Colombier } 345dc5a79c1SDavid du Colombier 346dc5a79c1SDavid du Colombier void 347dc5a79c1SDavid du Colombier Xpopm(void) 348dc5a79c1SDavid du Colombier { 3493e12c5d1SDavid du Colombier poplist(); 3503e12c5d1SDavid du Colombier } 351dc5a79c1SDavid du Colombier 352dc5a79c1SDavid du Colombier void 353dc5a79c1SDavid du Colombier Xread(void) 354dc5a79c1SDavid du Colombier { 3553e12c5d1SDavid du Colombier char *file; 3563e12c5d1SDavid du Colombier int f; 3573e12c5d1SDavid du Colombier switch(count(runq->argv->words)){ 358dc5a79c1SDavid du Colombier default: 359dc5a79c1SDavid du Colombier Xerror1("< requires singleton\n"); 360dc5a79c1SDavid du Colombier return; 361dc5a79c1SDavid du Colombier case 0: 362dc5a79c1SDavid du Colombier Xerror1("< requires file\n"); 363dc5a79c1SDavid du Colombier return; 364dc5a79c1SDavid du Colombier case 1: 365dc5a79c1SDavid du Colombier break; 3663e12c5d1SDavid du Colombier } 3673e12c5d1SDavid du Colombier file = runq->argv->words->word; 3683e12c5d1SDavid du Colombier if((f = open(file, 0))<0){ 3697dd7cddfSDavid du Colombier pfmt(err, "%s: ", file); 3707dd7cddfSDavid du Colombier Xerror("can't open"); 3713e12c5d1SDavid du Colombier return; 3723e12c5d1SDavid du Colombier } 3733e12c5d1SDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i); 3743e12c5d1SDavid du Colombier runq->pc++; 3753e12c5d1SDavid du Colombier poplist(); 3763e12c5d1SDavid du Colombier } 377dc5a79c1SDavid du Colombier 378dc5a79c1SDavid du Colombier void 379119a69faSDavid du Colombier Xrdwr(void) 380119a69faSDavid du Colombier { 381119a69faSDavid du Colombier char *file; 382119a69faSDavid du Colombier int f; 383119a69faSDavid du Colombier 384119a69faSDavid du Colombier switch(count(runq->argv->words)){ 385119a69faSDavid du Colombier default: 386119a69faSDavid du Colombier Xerror1("<> requires singleton\n"); 387119a69faSDavid du Colombier return; 388119a69faSDavid du Colombier case 0: 389119a69faSDavid du Colombier Xerror1("<> requires file\n"); 390119a69faSDavid du Colombier return; 391119a69faSDavid du Colombier case 1: 392119a69faSDavid du Colombier break; 393119a69faSDavid du Colombier } 394119a69faSDavid du Colombier file = runq->argv->words->word; 395119a69faSDavid du Colombier if((f = open(file, ORDWR))<0){ 396119a69faSDavid du Colombier pfmt(err, "%s: ", file); 397119a69faSDavid du Colombier Xerror("can't open"); 398119a69faSDavid du Colombier return; 399119a69faSDavid du Colombier } 400119a69faSDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i); 401119a69faSDavid du Colombier runq->pc++; 402119a69faSDavid du Colombier poplist(); 403119a69faSDavid du Colombier } 404119a69faSDavid du Colombier 405119a69faSDavid du Colombier void 406dc5a79c1SDavid du Colombier turfredir(void) 407dc5a79c1SDavid du Colombier { 4083e12c5d1SDavid du Colombier while(runq->redir!=runq->startredir) 4093e12c5d1SDavid du Colombier Xpopredir(); 4103e12c5d1SDavid du Colombier } 411dc5a79c1SDavid du Colombier 412dc5a79c1SDavid du Colombier void 413dc5a79c1SDavid du Colombier Xpopredir(void) 414dc5a79c1SDavid du Colombier { 4153e12c5d1SDavid du Colombier struct redir *rp = runq->redir; 416dc5a79c1SDavid du Colombier if(rp==0) 417dc5a79c1SDavid du Colombier panic("turfredir null!", 0); 4183e12c5d1SDavid du Colombier runq->redir = rp->next; 419dc5a79c1SDavid du Colombier if(rp->type==ROPEN) 420dc5a79c1SDavid du Colombier close(rp->from); 4213e12c5d1SDavid du Colombier efree((char *)rp); 4223e12c5d1SDavid du Colombier } 423dc5a79c1SDavid du Colombier 424dc5a79c1SDavid du Colombier void 425dc5a79c1SDavid du Colombier Xreturn(void) 426dc5a79c1SDavid du Colombier { 4273e12c5d1SDavid du Colombier struct thread *p = runq; 4283e12c5d1SDavid du Colombier turfredir(); 4293e12c5d1SDavid du Colombier while(p->argv) poplist(); 4303e12c5d1SDavid du Colombier codefree(p->code); 4313e12c5d1SDavid du Colombier runq = p->ret; 4323e12c5d1SDavid du Colombier efree((char *)p); 433dc5a79c1SDavid du Colombier if(runq==0) 434dc5a79c1SDavid du Colombier Exit(getstatus()); 4353e12c5d1SDavid du Colombier } 436dc5a79c1SDavid du Colombier 437dc5a79c1SDavid du Colombier void 438dc5a79c1SDavid du Colombier Xtrue(void) 439dc5a79c1SDavid du Colombier { 4403e12c5d1SDavid du Colombier if(truestatus()) runq->pc++; 4413e12c5d1SDavid du Colombier else runq->pc = runq->code[runq->pc].i; 4423e12c5d1SDavid du Colombier } 443dc5a79c1SDavid du Colombier 444dc5a79c1SDavid du Colombier void 445dc5a79c1SDavid du Colombier Xif(void) 446dc5a79c1SDavid du Colombier { 4473e12c5d1SDavid du Colombier ifnot = 1; 4483e12c5d1SDavid du Colombier if(truestatus()) runq->pc++; 4493e12c5d1SDavid du Colombier else runq->pc = runq->code[runq->pc].i; 4503e12c5d1SDavid du Colombier } 451dc5a79c1SDavid du Colombier 452dc5a79c1SDavid du Colombier void 453dc5a79c1SDavid du Colombier Xwastrue(void) 454dc5a79c1SDavid du Colombier { 4553e12c5d1SDavid du Colombier ifnot = 0; 4563e12c5d1SDavid du Colombier } 457dc5a79c1SDavid du Colombier 458dc5a79c1SDavid du Colombier void 459dc5a79c1SDavid du Colombier Xword(void) 460dc5a79c1SDavid du Colombier { 4613e12c5d1SDavid du Colombier pushword(runq->code[runq->pc++].s); 4623e12c5d1SDavid du Colombier } 463dc5a79c1SDavid du Colombier 464dc5a79c1SDavid du Colombier void 465dc5a79c1SDavid du Colombier Xwrite(void) 466dc5a79c1SDavid du Colombier { 4673e12c5d1SDavid du Colombier char *file; 4683e12c5d1SDavid du Colombier int f; 4693e12c5d1SDavid du Colombier switch(count(runq->argv->words)){ 470dc5a79c1SDavid du Colombier default: 471dc5a79c1SDavid du Colombier Xerror1("> requires singleton\n"); 472dc5a79c1SDavid du Colombier return; 473dc5a79c1SDavid du Colombier case 0: 474dc5a79c1SDavid du Colombier Xerror1("> requires file\n"); 475dc5a79c1SDavid du Colombier return; 476dc5a79c1SDavid du Colombier case 1: 477dc5a79c1SDavid du Colombier break; 4783e12c5d1SDavid du Colombier } 4793e12c5d1SDavid du Colombier file = runq->argv->words->word; 4803e12c5d1SDavid du Colombier if((f = Creat(file))<0){ 4817dd7cddfSDavid du Colombier pfmt(err, "%s: ", file); 4827dd7cddfSDavid du Colombier Xerror("can't open"); 4833e12c5d1SDavid du Colombier return; 4843e12c5d1SDavid du Colombier } 4853e12c5d1SDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i); 4863e12c5d1SDavid du Colombier runq->pc++; 4873e12c5d1SDavid du Colombier poplist(); 4883e12c5d1SDavid du Colombier } 489dc5a79c1SDavid du Colombier 490dc5a79c1SDavid du Colombier char* 491dc5a79c1SDavid du Colombier list2str(word *words) 492dc5a79c1SDavid du Colombier { 4933e12c5d1SDavid du Colombier char *value, *s, *t; 4943e12c5d1SDavid du Colombier int len = 0; 4953e12c5d1SDavid du Colombier word *ap; 4963e12c5d1SDavid du Colombier for(ap = words;ap;ap = ap->next) 4973e12c5d1SDavid du Colombier len+=1+strlen(ap->word); 4983e12c5d1SDavid du Colombier value = emalloc(len+1); 4993e12c5d1SDavid du Colombier s = value; 5003e12c5d1SDavid du Colombier for(ap = words;ap;ap = ap->next){ 5013e12c5d1SDavid du Colombier for(t = ap->word;*t;) *s++=*t++; 5023e12c5d1SDavid du Colombier *s++=' '; 5033e12c5d1SDavid du Colombier } 504dc5a79c1SDavid du Colombier if(s==value) 505dc5a79c1SDavid du Colombier *s='\0'; 5063e12c5d1SDavid du Colombier else s[-1]='\0'; 5073e12c5d1SDavid du Colombier return value; 5083e12c5d1SDavid du Colombier } 509dc5a79c1SDavid du Colombier 510dc5a79c1SDavid du Colombier void 511dc5a79c1SDavid du Colombier Xmatch(void) 512dc5a79c1SDavid du Colombier { 5133e12c5d1SDavid du Colombier word *p; 5143e12c5d1SDavid du Colombier char *subject; 5153e12c5d1SDavid du Colombier subject = list2str(runq->argv->words); 5163e12c5d1SDavid du Colombier setstatus("no match"); 5173e12c5d1SDavid du Colombier for(p = runq->argv->next->words;p;p = p->next) 5183e12c5d1SDavid du Colombier if(match(subject, p->word, '\0')){ 5193e12c5d1SDavid du Colombier setstatus(""); 5203e12c5d1SDavid du Colombier break; 5213e12c5d1SDavid du Colombier } 5223e12c5d1SDavid du Colombier efree(subject); 5233e12c5d1SDavid du Colombier poplist(); 5243e12c5d1SDavid du Colombier poplist(); 5253e12c5d1SDavid du Colombier } 526dc5a79c1SDavid du Colombier 527dc5a79c1SDavid du Colombier void 528dc5a79c1SDavid du Colombier Xcase(void) 529dc5a79c1SDavid du Colombier { 5303e12c5d1SDavid du Colombier word *p; 5313e12c5d1SDavid du Colombier char *s; 5323e12c5d1SDavid du Colombier int ok = 0; 5333e12c5d1SDavid du Colombier s = list2str(runq->argv->next->words); 5343e12c5d1SDavid du Colombier for(p = runq->argv->words;p;p = p->next){ 5353e12c5d1SDavid du Colombier if(match(s, p->word, '\0')){ 5363e12c5d1SDavid du Colombier ok = 1; 5373e12c5d1SDavid du Colombier break; 5383e12c5d1SDavid du Colombier } 5393e12c5d1SDavid du Colombier } 5403e12c5d1SDavid du Colombier efree(s); 5413e12c5d1SDavid du Colombier if(ok) 5423e12c5d1SDavid du Colombier runq->pc++; 5433e12c5d1SDavid du Colombier else 5443e12c5d1SDavid du Colombier runq->pc = runq->code[runq->pc].i; 5453e12c5d1SDavid du Colombier poplist(); 5463e12c5d1SDavid du Colombier } 547dc5a79c1SDavid du Colombier 548dc5a79c1SDavid du Colombier word* 549dc5a79c1SDavid du Colombier conclist(word *lp, word *rp, word *tail) 5503e12c5d1SDavid du Colombier { 5513e12c5d1SDavid du Colombier char *buf; 5523e12c5d1SDavid du Colombier word *v; 5533e12c5d1SDavid du Colombier if(lp->next || rp->next) 554276e7d6dSDavid du Colombier tail = conclist(lp->next==0? lp: lp->next, 555276e7d6dSDavid du Colombier rp->next==0? rp: rp->next, tail); 556276e7d6dSDavid du Colombier buf = emalloc(strlen(lp->word)+strlen((char *)rp->word)+1); 5573e12c5d1SDavid du Colombier strcpy(buf, lp->word); 5583e12c5d1SDavid du Colombier strcat(buf, rp->word); 5593e12c5d1SDavid du Colombier v = newword(buf, tail); 5603e12c5d1SDavid du Colombier efree(buf); 5613e12c5d1SDavid du Colombier return v; 5623e12c5d1SDavid du Colombier } 563dc5a79c1SDavid du Colombier 564dc5a79c1SDavid du Colombier void 565dc5a79c1SDavid du Colombier Xconc(void) 566dc5a79c1SDavid du Colombier { 5673e12c5d1SDavid du Colombier word *lp = runq->argv->words; 5683e12c5d1SDavid du Colombier word *rp = runq->argv->next->words; 5693e12c5d1SDavid du Colombier word *vp = runq->argv->next->next->words; 5703e12c5d1SDavid du Colombier int lc = count(lp), rc = count(rp); 5713e12c5d1SDavid du Colombier if(lc!=0 || rc!=0){ 5723e12c5d1SDavid du Colombier if(lc==0 || rc==0){ 5739a747e4fSDavid du Colombier Xerror1("null list in concatenation"); 5743e12c5d1SDavid du Colombier return; 5753e12c5d1SDavid du Colombier } 5763e12c5d1SDavid du Colombier if(lc!=1 && rc!=1 && lc!=rc){ 5779a747e4fSDavid du Colombier Xerror1("mismatched list lengths in concatenation"); 5783e12c5d1SDavid du Colombier return; 5793e12c5d1SDavid du Colombier } 5803e12c5d1SDavid du Colombier vp = conclist(lp, rp, vp); 5813e12c5d1SDavid du Colombier } 5823e12c5d1SDavid du Colombier poplist(); 5833e12c5d1SDavid du Colombier poplist(); 5843e12c5d1SDavid du Colombier runq->argv->words = vp; 5853e12c5d1SDavid du Colombier } 586dc5a79c1SDavid du Colombier 587dc5a79c1SDavid du Colombier void 588dc5a79c1SDavid du Colombier Xassign(void) 589dc5a79c1SDavid du Colombier { 5903e12c5d1SDavid du Colombier var *v; 5913e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){ 5929a747e4fSDavid du Colombier Xerror1("variable name not singleton!"); 5933e12c5d1SDavid du Colombier return; 5943e12c5d1SDavid du Colombier } 5953e12c5d1SDavid du Colombier deglob(runq->argv->words->word); 5963e12c5d1SDavid du Colombier v = vlook(runq->argv->words->word); 5973e12c5d1SDavid du Colombier poplist(); 5983e12c5d1SDavid du Colombier globlist(); 5993e12c5d1SDavid du Colombier freewords(v->val); 6003e12c5d1SDavid du Colombier v->val = runq->argv->words; 6013e12c5d1SDavid du Colombier v->changed = 1; 6023e12c5d1SDavid du Colombier runq->argv->words = 0; 6033e12c5d1SDavid du Colombier poplist(); 6043e12c5d1SDavid du Colombier } 6053e12c5d1SDavid du Colombier /* 6063e12c5d1SDavid du Colombier * copy arglist a, adding the copy to the front of tail 6073e12c5d1SDavid du Colombier */ 608dc5a79c1SDavid du Colombier 609dc5a79c1SDavid du Colombier word* 610dc5a79c1SDavid du Colombier copywords(word *a, word *tail) 6113e12c5d1SDavid du Colombier { 6123e12c5d1SDavid du Colombier word *v = 0, **end; 6133e12c5d1SDavid du Colombier for(end=&v;a;a = a->next,end=&(*end)->next) 6143e12c5d1SDavid du Colombier *end = newword(a->word, 0); 6153e12c5d1SDavid du Colombier *end = tail; 6163e12c5d1SDavid du Colombier return v; 6173e12c5d1SDavid du Colombier } 618dc5a79c1SDavid du Colombier 619dc5a79c1SDavid du Colombier void 620dc5a79c1SDavid du Colombier Xdol(void) 621dc5a79c1SDavid du Colombier { 6223e12c5d1SDavid du Colombier word *a, *star; 6233e12c5d1SDavid du Colombier char *s, *t; 6243e12c5d1SDavid du Colombier int n; 6253e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){ 6269a747e4fSDavid du Colombier Xerror1("variable name not singleton!"); 6273e12c5d1SDavid du Colombier return; 6283e12c5d1SDavid du Colombier } 6293e12c5d1SDavid du Colombier s = runq->argv->words->word; 6303e12c5d1SDavid du Colombier deglob(s); 6313e12c5d1SDavid du Colombier n = 0; 63299eb86a7SDavid du Colombier for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0'; 6333e12c5d1SDavid du Colombier a = runq->argv->next->words; 6343e12c5d1SDavid du Colombier if(n==0 || *t) 6353e12c5d1SDavid du Colombier a = copywords(vlook(s)->val, a); 6363e12c5d1SDavid du Colombier else{ 6373e12c5d1SDavid du Colombier star = vlook("*")->val; 6383e12c5d1SDavid du Colombier if(star && 1<=n && n<=count(star)){ 63999eb86a7SDavid du Colombier while(--n) star = star->next; 6403e12c5d1SDavid du Colombier a = newword(star->word, a); 6413e12c5d1SDavid du Colombier } 6423e12c5d1SDavid du Colombier } 6433e12c5d1SDavid du Colombier poplist(); 6443e12c5d1SDavid du Colombier runq->argv->words = a; 6453e12c5d1SDavid du Colombier } 646dc5a79c1SDavid du Colombier 647dc5a79c1SDavid du Colombier void 648dc5a79c1SDavid du Colombier Xqdol(void) 649dc5a79c1SDavid du Colombier { 6503e12c5d1SDavid du Colombier word *a, *p; 6513e12c5d1SDavid du Colombier char *s; 6523e12c5d1SDavid du Colombier int n; 6533e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){ 6549a747e4fSDavid du Colombier Xerror1("variable name not singleton!"); 6553e12c5d1SDavid du Colombier return; 6563e12c5d1SDavid du Colombier } 6573e12c5d1SDavid du Colombier s = runq->argv->words->word; 6583e12c5d1SDavid du Colombier deglob(s); 6593e12c5d1SDavid du Colombier a = vlook(s)->val; 6603e12c5d1SDavid du Colombier poplist(); 6613e12c5d1SDavid du Colombier n = count(a); 6623e12c5d1SDavid du Colombier if(n==0){ 6633e12c5d1SDavid du Colombier pushword(""); 6643e12c5d1SDavid du Colombier return; 6653e12c5d1SDavid du Colombier } 6663e12c5d1SDavid du Colombier for(p = a;p;p = p->next) n+=strlen(p->word); 6673e12c5d1SDavid du Colombier s = emalloc(n); 6683e12c5d1SDavid du Colombier if(a){ 6693e12c5d1SDavid du Colombier strcpy(s, a->word); 6703e12c5d1SDavid du Colombier for(p = a->next;p;p = p->next){ 6713e12c5d1SDavid du Colombier strcat(s, " "); 6723e12c5d1SDavid du Colombier strcat(s, p->word); 6733e12c5d1SDavid du Colombier } 6743e12c5d1SDavid du Colombier } 6753e12c5d1SDavid du Colombier else 6763e12c5d1SDavid du Colombier s[0]='\0'; 6773e12c5d1SDavid du Colombier pushword(s); 6783e12c5d1SDavid du Colombier efree(s); 6793e12c5d1SDavid du Colombier } 680dc5a79c1SDavid du Colombier 681dc5a79c1SDavid du Colombier word* 682dc5a79c1SDavid du Colombier subwords(word *val, int len, word *sub, word *a) 6833e12c5d1SDavid du Colombier { 6843e12c5d1SDavid du Colombier int n; 6853e12c5d1SDavid du Colombier char *s; 686dc5a79c1SDavid du Colombier if(!sub) 687dc5a79c1SDavid du Colombier return a; 6883e12c5d1SDavid du Colombier a = subwords(val, len, sub->next, a); 6893e12c5d1SDavid du Colombier s = sub->word; 6903e12c5d1SDavid du Colombier deglob(s); 6913e12c5d1SDavid du Colombier n = 0; 69299eb86a7SDavid du Colombier while('0'<=*s && *s<='9') n = n*10+ *s++ -'0'; 693dc5a79c1SDavid du Colombier if(n<1 || len<n) 694dc5a79c1SDavid du Colombier return a; 69599eb86a7SDavid du Colombier for(;n!=1;--n) val = val->next; 6963e12c5d1SDavid du Colombier return newword(val->word, a); 6973e12c5d1SDavid du Colombier } 698dc5a79c1SDavid du Colombier 699dc5a79c1SDavid du Colombier void 700dc5a79c1SDavid du Colombier Xsub(void) 701dc5a79c1SDavid du Colombier { 7023e12c5d1SDavid du Colombier word *a, *v; 7033e12c5d1SDavid du Colombier char *s; 7043e12c5d1SDavid du Colombier if(count(runq->argv->next->words)!=1){ 7059a747e4fSDavid du Colombier Xerror1("variable name not singleton!"); 7063e12c5d1SDavid du Colombier return; 7073e12c5d1SDavid du Colombier } 7083e12c5d1SDavid du Colombier s = runq->argv->next->words->word; 7093e12c5d1SDavid du Colombier deglob(s); 7103e12c5d1SDavid du Colombier a = runq->argv->next->next->words; 7113e12c5d1SDavid du Colombier v = vlook(s)->val; 7123e12c5d1SDavid du Colombier a = subwords(v, count(v), runq->argv->words, a); 7133e12c5d1SDavid du Colombier poplist(); 7143e12c5d1SDavid du Colombier poplist(); 7153e12c5d1SDavid du Colombier runq->argv->words = a; 7163e12c5d1SDavid du Colombier } 717dc5a79c1SDavid du Colombier 718dc5a79c1SDavid du Colombier void 719dc5a79c1SDavid du Colombier Xcount(void) 720dc5a79c1SDavid du Colombier { 7213e12c5d1SDavid du Colombier word *a; 7223e12c5d1SDavid du Colombier char *s, *t; 7233e12c5d1SDavid du Colombier int n; 7243e12c5d1SDavid du Colombier char num[12]; 7253e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){ 7269a747e4fSDavid du Colombier Xerror1("variable name not singleton!"); 7273e12c5d1SDavid du Colombier return; 7283e12c5d1SDavid du Colombier } 7293e12c5d1SDavid du Colombier s = runq->argv->words->word; 7303e12c5d1SDavid du Colombier deglob(s); 7313e12c5d1SDavid du Colombier n = 0; 7323e12c5d1SDavid du Colombier for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0'; 7333e12c5d1SDavid du Colombier if(n==0 || *t){ 7343e12c5d1SDavid du Colombier a = vlook(s)->val; 735dc5a79c1SDavid du Colombier inttoascii(num, count(a)); 7363e12c5d1SDavid du Colombier } 7373e12c5d1SDavid du Colombier else{ 7383e12c5d1SDavid du Colombier a = vlook("*")->val; 739dc5a79c1SDavid du Colombier inttoascii(num, a && 1<=n && n<=count(a)?1:0); 7403e12c5d1SDavid du Colombier } 7413e12c5d1SDavid du Colombier poplist(); 7423e12c5d1SDavid du Colombier pushword(num); 7433e12c5d1SDavid du Colombier } 744dc5a79c1SDavid du Colombier 745dc5a79c1SDavid du Colombier void 746dc5a79c1SDavid du Colombier Xlocal(void) 747dc5a79c1SDavid du Colombier { 7483e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){ 7499a747e4fSDavid du Colombier Xerror1("variable name must be singleton\n"); 7503e12c5d1SDavid du Colombier return; 7513e12c5d1SDavid du Colombier } 7523e12c5d1SDavid du Colombier deglob(runq->argv->words->word); 7533e12c5d1SDavid du Colombier runq->local = newvar(strdup(runq->argv->words->word), runq->local); 7543e12c5d1SDavid du Colombier poplist(); 755*fed0fa9eSDavid du Colombier globlist(); 756*fed0fa9eSDavid du Colombier runq->local->val = runq->argv->words; 757*fed0fa9eSDavid du Colombier runq->local->changed = 1; 758*fed0fa9eSDavid du Colombier runq->argv->words = 0; 7593e12c5d1SDavid du Colombier poplist(); 7603e12c5d1SDavid du Colombier } 761dc5a79c1SDavid du Colombier 762dc5a79c1SDavid du Colombier void 763dc5a79c1SDavid du Colombier Xunlocal(void) 764dc5a79c1SDavid du Colombier { 7653e12c5d1SDavid du Colombier var *v = runq->local, *hid; 766dc5a79c1SDavid du Colombier if(v==0) 767dc5a79c1SDavid du Colombier panic("Xunlocal: no locals!", 0); 7683e12c5d1SDavid du Colombier runq->local = v->next; 7693e12c5d1SDavid du Colombier hid = vlook(v->name); 7703e12c5d1SDavid du Colombier hid->changed = 1; 7713e12c5d1SDavid du Colombier efree(v->name); 7723e12c5d1SDavid du Colombier freewords(v->val); 7733e12c5d1SDavid du Colombier efree((char *)v); 7743e12c5d1SDavid du Colombier } 775dc5a79c1SDavid du Colombier 776dc5a79c1SDavid du Colombier void 777dc5a79c1SDavid du Colombier freewords(word *w) 7783e12c5d1SDavid du Colombier { 7793e12c5d1SDavid du Colombier word *nw; 7803e12c5d1SDavid du Colombier while(w){ 7813e12c5d1SDavid du Colombier efree(w->word); 7823e12c5d1SDavid du Colombier nw = w->next; 7833e12c5d1SDavid du Colombier efree((char *)w); 7843e12c5d1SDavid du Colombier w = nw; 7853e12c5d1SDavid du Colombier } 7863e12c5d1SDavid du Colombier } 787dc5a79c1SDavid du Colombier 788dc5a79c1SDavid du Colombier void 789dc5a79c1SDavid du Colombier Xfn(void) 790dc5a79c1SDavid du Colombier { 7913e12c5d1SDavid du Colombier var *v; 7923e12c5d1SDavid du Colombier word *a; 7933e12c5d1SDavid du Colombier int end; 7943e12c5d1SDavid du Colombier end = runq->code[runq->pc].i; 795*fed0fa9eSDavid du Colombier globlist(); 7963e12c5d1SDavid du Colombier for(a = runq->argv->words;a;a = a->next){ 7973e12c5d1SDavid du Colombier v = gvlook(a->word); 798dc5a79c1SDavid du Colombier if(v->fn) 799dc5a79c1SDavid du Colombier codefree(v->fn); 8003e12c5d1SDavid du Colombier v->fn = codecopy(runq->code); 8013e12c5d1SDavid du Colombier v->pc = runq->pc+2; 8023e12c5d1SDavid du Colombier v->fnchanged = 1; 8033e12c5d1SDavid du Colombier } 8043e12c5d1SDavid du Colombier runq->pc = end; 8053e12c5d1SDavid du Colombier poplist(); 8063e12c5d1SDavid du Colombier } 807dc5a79c1SDavid du Colombier 808dc5a79c1SDavid du Colombier void 809dc5a79c1SDavid du Colombier Xdelfn(void) 810dc5a79c1SDavid du Colombier { 8113e12c5d1SDavid du Colombier var *v; 8123e12c5d1SDavid du Colombier word *a; 8133e12c5d1SDavid du Colombier for(a = runq->argv->words;a;a = a->next){ 8143e12c5d1SDavid du Colombier v = gvlook(a->word); 815dc5a79c1SDavid du Colombier if(v->fn) 816dc5a79c1SDavid du Colombier codefree(v->fn); 8173e12c5d1SDavid du Colombier v->fn = 0; 8183e12c5d1SDavid du Colombier v->fnchanged = 1; 8193e12c5d1SDavid du Colombier } 8203e12c5d1SDavid du Colombier poplist(); 8213e12c5d1SDavid du Colombier } 822dc5a79c1SDavid du Colombier 823dc5a79c1SDavid du Colombier char* 824dc5a79c1SDavid du Colombier concstatus(char *s, char *t) 8253e12c5d1SDavid du Colombier { 8263e12c5d1SDavid du Colombier static char v[NSTATUS+1]; 8273e12c5d1SDavid du Colombier int n = strlen(s); 8283e12c5d1SDavid du Colombier strncpy(v, s, NSTATUS); 8293e12c5d1SDavid du Colombier if(n<NSTATUS){ 8303e12c5d1SDavid du Colombier v[n]='|'; 8313e12c5d1SDavid du Colombier strncpy(v+n+1, t, NSTATUS-n-1); 8323e12c5d1SDavid du Colombier } 8333e12c5d1SDavid du Colombier v[NSTATUS]='\0'; 8343e12c5d1SDavid du Colombier return v; 8353e12c5d1SDavid du Colombier } 836dc5a79c1SDavid du Colombier 837dc5a79c1SDavid du Colombier void 838dc5a79c1SDavid du Colombier Xpipewait(void) 839dc5a79c1SDavid du Colombier { 8403e12c5d1SDavid du Colombier char status[NSTATUS+1]; 8413e12c5d1SDavid du Colombier if(runq->pid==-1) 8423e12c5d1SDavid du Colombier setstatus(concstatus(runq->status, getstatus())); 8433e12c5d1SDavid du Colombier else{ 8443e12c5d1SDavid du Colombier strncpy(status, getstatus(), NSTATUS); 8453e12c5d1SDavid du Colombier status[NSTATUS]='\0'; 8463e12c5d1SDavid du Colombier Waitfor(runq->pid, 1); 8473e12c5d1SDavid du Colombier runq->pid=-1; 8483e12c5d1SDavid du Colombier setstatus(concstatus(getstatus(), status)); 8493e12c5d1SDavid du Colombier } 8503e12c5d1SDavid du Colombier } 851dc5a79c1SDavid du Colombier 852dc5a79c1SDavid du Colombier void 853dc5a79c1SDavid du Colombier Xrdcmds(void) 854dc5a79c1SDavid du Colombier { 8553e12c5d1SDavid du Colombier struct thread *p = runq; 8563e12c5d1SDavid du Colombier word *prompt; 8573e12c5d1SDavid du Colombier flush(err); 8583e12c5d1SDavid du Colombier nerror = 0; 8593e12c5d1SDavid du Colombier if(flag['s'] && !truestatus()) 8603e12c5d1SDavid du Colombier pfmt(err, "status=%v\n", vlook("status")->val); 8613e12c5d1SDavid du Colombier if(runq->iflag){ 8623e12c5d1SDavid du Colombier prompt = vlook("prompt")->val; 8633e12c5d1SDavid du Colombier if(prompt) 8643e12c5d1SDavid du Colombier promptstr = prompt->word; 8653e12c5d1SDavid du Colombier else 8663e12c5d1SDavid du Colombier promptstr="% "; 8673e12c5d1SDavid du Colombier } 8683e12c5d1SDavid du Colombier Noerror(); 8693e12c5d1SDavid du Colombier if(yyparse()){ 8703e12c5d1SDavid du Colombier if(!p->iflag || p->eof && !Eintr()){ 871dc5a79c1SDavid du Colombier if(p->cmdfile) 872dc5a79c1SDavid du Colombier efree(p->cmdfile); 8733e12c5d1SDavid du Colombier closeio(p->cmdfd); 8743e12c5d1SDavid du Colombier Xreturn(); /* should this be omitted? */ 8753e12c5d1SDavid du Colombier } 8763e12c5d1SDavid du Colombier else{ 8773e12c5d1SDavid du Colombier if(Eintr()){ 8783e12c5d1SDavid du Colombier pchr(err, '\n'); 8793e12c5d1SDavid du Colombier p->eof = 0; 8803e12c5d1SDavid du Colombier } 8813e12c5d1SDavid du Colombier --p->pc; /* go back for next command */ 8823e12c5d1SDavid du Colombier } 8833e12c5d1SDavid du Colombier } 8843e12c5d1SDavid du Colombier else{ 8857dd7cddfSDavid du Colombier ntrap = 0; /* avoid double-interrupts during blocked writes */ 8863e12c5d1SDavid du Colombier --p->pc; /* re-execute Xrdcmds after codebuf runs */ 8873e12c5d1SDavid du Colombier start(codebuf, 1, runq->local); 8883e12c5d1SDavid du Colombier } 8893e12c5d1SDavid du Colombier freenodes(); 8903e12c5d1SDavid du Colombier } 891dc5a79c1SDavid du Colombier 892dc5a79c1SDavid du Colombier void 893dc5a79c1SDavid du Colombier Xerror(char *s) 8943e12c5d1SDavid du Colombier { 8959a747e4fSDavid du Colombier if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0) 8969a747e4fSDavid du Colombier pfmt(err, "rc: %s: %r\n", s); 8979a747e4fSDavid du Colombier else 8989a747e4fSDavid du Colombier pfmt(err, "rc (%s): %s: %r\n", argv0, s); 8999a747e4fSDavid du Colombier flush(err); 900d3907fe5SDavid du Colombier setstatus("error"); 9019a747e4fSDavid du Colombier while(!runq->iflag) Xreturn(); 9029a747e4fSDavid du Colombier } 903dc5a79c1SDavid du Colombier 904dc5a79c1SDavid du Colombier void 905dc5a79c1SDavid du Colombier Xerror1(char *s) 9069a747e4fSDavid du Colombier { 9079a747e4fSDavid du Colombier if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0) 9083e12c5d1SDavid du Colombier pfmt(err, "rc: %s\n", s); 9099a747e4fSDavid du Colombier else 9109a747e4fSDavid du Colombier pfmt(err, "rc (%s): %s\n", argv0, s); 9113e12c5d1SDavid du Colombier flush(err); 912d3907fe5SDavid du Colombier setstatus("error"); 9133e12c5d1SDavid du Colombier while(!runq->iflag) Xreturn(); 9143e12c5d1SDavid du Colombier } 915dc5a79c1SDavid du Colombier 916dc5a79c1SDavid du Colombier void 917dc5a79c1SDavid du Colombier setstatus(char *s) 9183e12c5d1SDavid du Colombier { 9193e12c5d1SDavid du Colombier setvar("status", newword(s, (word *)0)); 9203e12c5d1SDavid du Colombier } 921dc5a79c1SDavid du Colombier 922dc5a79c1SDavid du Colombier char* 923dc5a79c1SDavid du Colombier getstatus(void) 924dc5a79c1SDavid du Colombier { 9253e12c5d1SDavid du Colombier var *status = vlook("status"); 9263e12c5d1SDavid du Colombier return status->val?status->val->word:""; 9273e12c5d1SDavid du Colombier } 928dc5a79c1SDavid du Colombier 929dc5a79c1SDavid du Colombier int 930dc5a79c1SDavid du Colombier truestatus(void) 931dc5a79c1SDavid du Colombier { 9323e12c5d1SDavid du Colombier char *s; 9333e12c5d1SDavid du Colombier for(s = getstatus();*s;s++) 934dc5a79c1SDavid du Colombier if(*s!='|' && *s!='0') 935dc5a79c1SDavid du Colombier return 0; 9363e12c5d1SDavid du Colombier return 1; 9373e12c5d1SDavid du Colombier } 938dc5a79c1SDavid du Colombier 939dc5a79c1SDavid du Colombier void 940dc5a79c1SDavid du Colombier Xdelhere(void) 941dc5a79c1SDavid du Colombier { 9423e12c5d1SDavid du Colombier Unlink(runq->code[runq->pc++].s); 9433e12c5d1SDavid du Colombier } 944dc5a79c1SDavid du Colombier 945dc5a79c1SDavid du Colombier void 946dc5a79c1SDavid du Colombier Xfor(void) 947dc5a79c1SDavid du Colombier { 9483e12c5d1SDavid du Colombier if(runq->argv->words==0){ 9493e12c5d1SDavid du Colombier poplist(); 9503e12c5d1SDavid du Colombier runq->pc = runq->code[runq->pc].i; 9513e12c5d1SDavid du Colombier } 9523e12c5d1SDavid du Colombier else{ 9533e12c5d1SDavid du Colombier freelist(runq->local->val); 9543e12c5d1SDavid du Colombier runq->local->val = runq->argv->words; 9553e12c5d1SDavid du Colombier runq->local->changed = 1; 9563e12c5d1SDavid du Colombier runq->argv->words = runq->argv->words->next; 9573e12c5d1SDavid du Colombier runq->local->val->next = 0; 9583e12c5d1SDavid du Colombier runq->pc++; 9593e12c5d1SDavid du Colombier } 9603e12c5d1SDavid du Colombier } 961dc5a79c1SDavid du Colombier 962dc5a79c1SDavid du Colombier void 963dc5a79c1SDavid du Colombier Xglob(void) 964dc5a79c1SDavid du Colombier { 9653e12c5d1SDavid du Colombier globlist(); 9663e12c5d1SDavid du Colombier } 967