Charles.Forsyth20060303644188019 years agoHistory
802 lines · 12.2 KB · C
RawDownload
#include "rc.h" extern	char	*argv0; int	ifnot;int	eflagok; /* * Opcode routines * Arguments on stack (...) * Arguments in line [...] * Code in line with jump around {...} * * Xappend(file)[fd]			open file to append * Xassign(name, val)			assign val to name * Xasync{... Xexit}			make thread for {}, no wait * Xbackq{... Xreturn}			make thread for {}, push stdout * Xbang				complement condition * Xcase(pat, value){...}		exec code on match, leave (value) on * 					stack * Xclose[i]				close file descriptor * Xconc(left, right)			concatenate, push results * Xcount(name)				push var count * Xdelfn(name)				delete function definition * Xdeltraps(names)			delete named traps * Xdol(name)				get variable value * Xqdol(name)				concatenate variable components * Xdup[i j]				dup file descriptor * Xexit				rc exits with status * Xfalse{...}				execute {} if false * Xfn(name){... Xreturn}			define function * Xfor(var, list){... Xreturn}		for loop * Xjump[addr]				goto * Xlocal(name, val)			create local variable, assign value * Xmark				mark stack * Xmatch(pat, str)			match pattern, set status * Xpipe[i j]{... Xreturn}{... Xreturn}	construct a pipe between 2 new threads, * 					wait for both * Xpipefd[type]{... Xreturn}		connect {} to pipe (input or output, * 					depending on type), push /dev/fd/?? * Xpopm(value)				pop value from stack * Xread(file)[fd]			open file to read * Xsettraps(names){... Xreturn}		define trap functions * Xshowtraps				print trap list * Xsimple(args)			run command and wait * Xreturn				kill thread * Xsubshell{... Xexit}			execute {} in a subshell and wait * Xtrue{...}				execute {} if true * Xunlocal				delete local variable * Xword[string]			push string * Xwrite(file)[fd]			open file to write */ static char **rcargv(char *s){	char *flags; 	if(flag['e'])		flags = "-Se";	else		flags = "-S";	return procargv(argv0, flags, "-c", s, vlook("*")->val);} voidXappend(void){	char *file;	int f; 	switch(count(runq->argv->words)){	default: Xerror(">> requires singleton"); return;	case 0: Xerror(">> requires file"); return;	case 1: break;	}	file=runq->argv->words->word;	if((f=open(file, 1))<0 && (f=create(file, 1, 0666))<0){		Xperror(file);		return;	}	seek(f, 0L, 2);	pushredir(ROPEN, f, runq->code[runq->pc].i);	runq->pc++;	poplist();} voidXassign(void){	Var *v; 	if(count(runq->argv->words)!=1){		Xerror("variable name not singleton!");		return;	}	deglob(runq->argv->words->word);	v=vlook(runq->argv->words->word);	poplist();	globlist();	freewords(v->val);	v->val=runq->argv->words;	v->changed=1;	runq->argv->words=0;	poplist();} voidXasync(void){	uint pid;	char buf[20], **argv; 	updenv(); 	argv = rcargv(runq->code[runq->pc].s);	pid = proc(argv, -1, 1, 2);	free(argv); 	if(pid == 0) {		Xerror("proc failed");		return;	} 	runq->pc++;	sprint(buf, "%d", pid);	setvar("apid", newword(buf, (Word *)0));} voidXbackq(void){	char wd[8193], **argv;	int c;	char *s, *ewd=&wd[8192], *stop;	Io *f;	Var *ifs=vlook("ifs");	Word *v, *nextv;	int pfd[2];	int pid; 	stop = ifs->val?ifs->val->word:"";	if(pipe(pfd)<0){		Xerror("can't make pipe");		return;	} 	updenv(); 	argv = rcargv(runq->code[runq->pc].s);	pid = proc(argv, -1, pfd[1], 2);	free(argv); 	close(pfd[1]); 	if(pid == 0) {		Xerror("proc failed");		close(pfd[0]);		return;	} 	f = openfd(pfd[0]);	s = wd;	v = 0;	while((c=rchr(f))!=EOF){		if(strchr(stop, c) || s==ewd){			if(s!=wd){				*s='\0';				v=newword(wd, v);				s=wd;			}		}		else *s++=c;	}	if(s!=wd){		*s='\0';		v=newword(wd, v);	}	closeio(f);	waitfor(pid);	/* v points to reversed arglist -- reverse it onto argv */	while(v){		nextv=v->next;		v->next=runq->argv->words;		runq->argv->words=v;		v=nextv;	}	runq->pc++;} voidXbang(void){	setstatus(truestatus()?"false":"");} voidXcase(void){	Word *p;	char *s;	int ok=0; 	s=list2str(runq->argv->next->words);	for(p=runq->argv->words;p;p=p->next){		if(match(s, p->word, '\0')){			ok=1;			break;		}	}	free(s);	if(ok)		runq->pc++;	else		runq->pc=runq->code[runq->pc].i;	poplist();} voidXclose(void){	pushredir(RCLOSE, runq->code[runq->pc].i, 0);	runq->pc++;} voidXconc(void){	Word *lp=runq->argv->words;	Word *rp=runq->argv->next->words;	Word *vp=runq->argv->next->next->words;	int lc=count(lp), rc=count(rp); 	if(lc!=0 || rc!=0){		if(lc==0 || rc==0){			Xerror("null list in concatenation");			return;		}		if(lc!=1 && rc!=1 && lc!=rc){			Xerror("mismatched list lengths in concatenation");			return;		}		vp=conclist(lp, rp, vp);	}	poplist();	poplist();	runq->argv->words=vp;} voidXcount(void){	Word *a;	char *s, *t;	int n;	char num[12]; 	if(count(runq->argv->words)!=1){		Xerror("variable name not singleton!");		return;	}	s=runq->argv->words->word;	deglob(s);	n=0;	for(t=s;'0'<=*t && *t<='9';t++) n=n*10+*t-'0';	if(n==0 || *t){		a=vlook(s)->val;		sprint(num, "%d", count(a));	}	else{		a=vlook("*")->val;		sprint(num, "%d", a && 1<=n && n<=count(a)?1:0);	}	poplist();	pushword(num);} voidXdelfn(void){	Var *v;	Word *a; 	for(a=runq->argv->words;a;a=a->next){		v=gvlook(a->word);		if(v->fn)			codefree(v->fn);		v->fn=0;		v->fnchanged=1;	}	poplist();} voidXdelhere(void){	Var *v;	Word *a; 	for(a=runq->argv->words;a;a=a->next){		v=gvlook(a->word);		if(v->fn) codefree(v->fn);		v->fn=0;		v->fnchanged=1;	}	poplist();} voidXdol(void){	Word *a, *star;	char *s, *t;	int n; 	if(count(runq->argv->words)!=1){		Xerror("variable name not singleton!");		return;	}	s=runq->argv->words->word;	deglob(s);	n=0;	for(t=s;'0'<=*t && *t<='9';t++) n=n*10+*t-'0';	a=runq->argv->next->words;	if(n==0 || *t)		a=copywords(vlook(s)->val, a);	else{		star=vlook("*")->val;		if(star && 1<=n && n<=count(star)){			while(--n) star=star->next;			a=newword(star->word, a);		}	}	poplist();	runq->argv->words=a;} voidXdup(void){	pushredir(RDUP, runq->code[runq->pc].i, runq->code[runq->pc+1].i);	runq->pc+=2;} voidXeflag(void){	if(eflagok && !truestatus())		Xexit();} voidXexit(void){	Var *trapreq;	Word *starval;	char *c;	static int beenhere=0; 	if(truestatus())		c = "";	else		c = getstatus(); 	if(flag['S'] || beenhere)		exits(c); 	trapreq=vlook("sigexit");	if(trapreq->fn){		beenhere=1;		--runq->pc;		starval=vlook("*")->val;		start(trapreq->fn, trapreq->pc, (Var*)0);		runq->local=newvar(strdup("*"), runq->local);		runq->local->val=copywords(starval, (Word*)0);		runq->local->changed=1;		runq->redir=runq->startredir=0;	} 	exits(c);} voidXfalse(void){	if(truestatus())		runq->pc=runq->code[runq->pc].i;	else		runq->pc++;} voidXfor(void){	if(runq->argv->words==0) {		poplist();		runq->pc=runq->code[runq->pc].i;	} else {		freelist(runq->local->val);		runq->local->val=runq->argv->words;		runq->local->changed=1;		runq->argv->words=runq->argv->words->next;		runq->local->val->next=0;		runq->pc++;	}} voidXfn(void){	Var *v;	Word *a;	int end; 	end=runq->code[runq->pc].i;	for(a=runq->argv->words;a;a=a->next){		v=gvlook(a->word);		if(v->fn)			codefree(v->fn);		v->fn=codecopy(runq->code);		v->pc=runq->pc+2;		v->fnchanged=1;	}	runq->pc=end;	poplist();} voidXglob(void){	globlist();} voidXif(void){	ifnot=1;	if(truestatus()) runq->pc++;	else runq->pc=runq->code[runq->pc].i;} voidXifnot(void){	if(ifnot)		runq->pc++;	else		runq->pc=runq->code[runq->pc].i;} voidXjump(void){	runq->pc=runq->code[runq->pc].i;}  voidXlocal(void){	if(count(runq->argv->words)!=1){		Xerror("variable name must be singleton\n");		return;	}	deglob(runq->argv->words->word);	runq->local=newvar(strdup(runq->argv->words->word), runq->local);	runq->local->val=copywords(runq->argv->next->words, 0);	runq->local->changed=1;	poplist();	poplist();}  void Xmark(void){	pushlist();} voidXmatch(void){	Word *p;	char *subject; 	subject=list2str(runq->argv->words);	setstatus("no match");	for(p=runq->argv->next->words;p;p=p->next) {		if(match(subject, p->word, '\0')){			setstatus("");			break;		}	}	free(subject);	poplist();	poplist();} voidXpipe(void)

Lines 1–500 of 802.