📄 exec.c
字号:
#include "rc.h"#include "getflags.h"#include "exec.h"#include "io.h"#include "fns.h"/* * Start executing the given code at the given pc with the given redirection */char *argv0="rc";voidstart(code *c, int pc, var *local){ struct thread *p = new(struct thread); p->code = codecopy(c); p->pc = pc; p->argv = 0; p->redir = p->startredir = runq?runq->redir:0; p->local = local; p->cmdfile = 0; p->cmdfd = 0; p->eof = 0; p->iflag = 0; p->lineno = 1; p->ret = runq; runq = p;}word*newword(char *wd, word *next){ word *p = new(word); p->word = strdup(wd); p->next = next; return p;}voidpushword(char *wd){ if(runq->argv==0) panic("pushword but no argv!", 0); runq->argv->words = newword(wd, runq->argv->words);}voidpopword(void){ word *p; if(runq->argv==0) panic("popword but no argv!", 0); p = runq->argv->words; if(p==0) panic("popword but no word!", 0); runq->argv->words = p->next; efree(p->word); efree((char *)p);}voidfreelist(word *w){ word *nw; while(w){ nw = w->next; efree(w->word); efree((char *)w); w = nw; }}voidpushlist(void){ list *p = new(list); p->next = runq->argv; p->words = 0; runq->argv = p;}voidpoplist(void){ list *p = runq->argv; if(p==0) panic("poplist but no argv", 0); freelist(p->words); runq->argv = p->next; efree((char *)p);}intcount(word *w){ int n; for(n = 0;w;n++) w = w->next; return n;}voidpushredir(int type, int from, int to){ redir * rp = new(redir); rp->type = type; rp->from = from; rp->to = to; rp->next = runq->redir; runq->redir = rp;}var*newvar(char *name, var *next){ var *v = new(var); v->name = name; v->val = 0; v->fn = 0; v->changed = 0; v->fnchanged = 0; v->next = next; return v;}/* * get command line flags, initialize keywords & traps. * get values from environment. * set $pid, $cflag, $* * fabricate bootstrap code and start it (*=(argv);. /usr/lib/rcmain $*) * start interpreting code */voidmain(int argc, char *argv[]){ code bootstrap[17]; char num[12], *rcmain; int i; argc = getflags(argc, argv, "SsrdiIlxepvVc:1m:1[command]", 1); if(argc==-1) usage("[file [arg ...]]"); if(argv[0][0]=='-') flag['l'] = flagset; if(flag['I']) flag['i'] = 0; else if(flag['i']==0 && argc==1 && Isatty(0)) flag['i'] = flagset; rcmain = flag['m']?flag['m'][0]:Rcmain; err = openfd(2); kinit(); Trapinit(); Vinit(); inttoascii(num, mypid = getpid()); setvar("pid", newword(num, (word *)0)); setvar("cflag", flag['c']?newword(flag['c'][0], (word *)0) :(word *)0); setvar("rcname", newword(argv[0], (word *)0)); i = 0; bootstrap[i++].i = 1; bootstrap[i++].f = Xmark; bootstrap[i++].f = Xword; bootstrap[i++].s="*"; bootstrap[i++].f = Xassign; bootstrap[i++].f = Xmark; bootstrap[i++].f = Xmark; bootstrap[i++].f = Xword; bootstrap[i++].s="*"; bootstrap[i++].f = Xdol; bootstrap[i++].f = Xword; bootstrap[i++].s = rcmain; bootstrap[i++].f = Xword; bootstrap[i++].s="."; bootstrap[i++].f = Xsimple; bootstrap[i++].f = Xexit; bootstrap[i].i = 0; start(bootstrap, 1, (var *)0); /* prime bootstrap argv */ pushlist(); argv0 = strdup(argv[0]); for(i = argc-1;i!=0;--i) pushword(argv[i]); for(;;){ if(flag['r']) pfnc(err, runq); runq->pc++; (*runq->code[runq->pc-1].f)(); if(ntrap) dotrap(); }}/* * 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 * Xrdwr(file)[fd] open file for reading and writing * 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 */voidXappend(void){ char *file; int f; switch(count(runq->argv->words)){ default: Xerror1(">> requires singleton"); return; case 0: Xerror1(">> requires file"); return; case 1: break; } file = runq->argv->words->word; if((f = open(file, 1))<0 && (f = Creat(file))<0){ pfmt(err, "%s: ", file); Xerror("can't open"); return; } Seek(f, 0L, 2); pushredir(ROPEN, f, runq->code[runq->pc].i); runq->pc++; poplist();}voidXsettrue(void){ setstatus("");}voidXbang(void){ setstatus(truestatus()?"false":"");}voidXclose(void){ pushredir(RCLOSE, runq->code[runq->pc].i, 0); runq->pc++;}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){ struct var *trapreq; struct word *starval; static int beenhere = 0; if(getpid()==mypid && !beenhere){ trapreq = vlook("sigexit"); if(trapreq->fn){ beenhere = 1; --runq->pc; starval = vlook("*")->val; start(trapreq->fn, trapreq->pc, (struct var *)0); runq->local = newvar(strdup("*"), runq->local); runq->local->val = copywords(starval, (struct word *)0); runq->local->changed = 1; runq->redir = runq->startredir = 0; return; } } Exit(getstatus());}voidXfalse(void){ if(truestatus()) runq->pc = runq->code[runq->pc].i; else runq->pc++;}int ifnot; /* dynamic if not flag */voidXifnot(void){ if(ifnot) runq->pc++; else runq->pc = runq->code[runq->pc].i;}voidXjump(void){ runq->pc = runq->code[runq->pc].i;}voidXmark(void){ pushlist();}voidXpopm(void){ poplist();}voidXread(void){ char *file; int f; switch(count(runq->argv->words)){ default: Xerror1("< requires singleton\n"); return; case 0: Xerror1("< requires file\n"); return; case 1: break; } file = runq->argv->words->word; if((f = open(file, 0))<0){ pfmt(err, "%s: ", file); Xerror("can't open"); return; } pushredir(ROPEN, f, runq->code[runq->pc].i); runq->pc++; poplist();}voidXrdwr(void){ char *file; int f; switch(count(runq->argv->words)){ default: Xerror1("<> requires singleton\n"); return; case 0: Xerror1("<> requires file\n"); return; case 1: break; } file = runq->argv->words->word; if((f = open(file, ORDWR))<0){ pfmt(err, "%s: ", file); Xerror("can't open"); return; } pushredir(ROPEN, f, runq->code[runq->pc].i); runq->pc++; poplist();}voidturfredir(void){ while(runq->redir!=runq->startredir) Xpopredir();}voidXpopredir(void){ struct redir *rp = runq->redir; if(rp==0) panic("turfredir null!", 0); runq->redir = rp->next; if(rp->type==ROPEN) close(rp->from); efree((char *)rp);}voidXreturn(void){ struct thread *p = runq; turfredir(); while(p->argv) poplist(); codefree(p->code); runq = p->ret; efree((char *)p); if(runq==0) Exit(getstatus());}voidXtrue(void){ if(truestatus()) runq->pc++; else runq->pc = runq->code[runq->pc].i;}voidXif(void){ ifnot = 1; if(truestatus()) runq->pc++; else runq->pc = runq->code[runq->pc].i;}voidXwastrue(void){ ifnot = 0;}voidXword(void){ pushword(runq->code[runq->pc++].s);}voidXwrite(void){ char *file; int f; switch(count(runq->argv->words)){ default: Xerror1("> requires singleton\n"); return; case 0: Xerror1("> requires file\n"); return; case 1: break; } file = runq->argv->words->word; if((f = Creat(file))<0){ pfmt(err, "%s: ", file);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -