📄 compiling.on.unix
字号:
X close(null);X Xerror("try again");X break;X case 0:X pushredir(ROPEN, null, 0);X start(runq->code, runq->pc+1, runq->local);X runq->ret = 0;X break;X default:X close(null);X runq->pc = runq->code[runq->pc].i;X inttoascii(npid, pid);X setvar("apid", newword(npid, (word *)0));X break;X }X}voidXXpipe(void)X{X struct thread *p = runq;X int pc = p->pc, forkid;X int lfd = p->code[pc++].i;X int rfd = p->code[pc++].i;X int pfd[2];X if(pipe(pfd)<0){X Xerror("can't get pipe");X return;X }X switch(forkid = fork()){X case -1:X Xerror("try again");X break;X case 0:X start(p->code, pc+2, runq->local);X runq->ret = 0;X close(pfd[PRD]);X pushredir(ROPEN, pfd[PWR], lfd);X break;X default:X start(p->code, p->code[pc].i, runq->local);X close(pfd[PWR]);X pushredir(ROPEN, pfd[PRD], rfd);X p->pc = p->code[pc+1].i;X p->pid = forkid;X break;X }X}X/*X * Who should wait for the exit from the fork?X */voidXXbackq(void)X{X char wd[8193];X int c;X char *s, *ewd=&wd[8192], *stop;X struct io *f;X var *ifs = vlook("ifs");X word *v, *nextv;X int pfd[2];X int pid;X stop = ifs->val?ifs->val->word:"";X if(pipe(pfd)<0){X Xerror("can't make pipe");X return;X }X switch(pid = fork()){X case -1:X Xerror("try again");X close(pfd[PRD]);X close(pfd[PWR]);X return;X case 0:X close(pfd[PRD]);X start(runq->code, runq->pc+1, runq->local);X pushredir(ROPEN, pfd[PWR], 1);X return;X default:X close(pfd[PWR]);X f = openfd(pfd[PRD]);X s = wd;X v = 0;X while((c = rchr(f))!=EOF){X if(strchr(stop, c) || s==ewd){X if(s!=wd){X *s='\0';X v = newword(wd, v);X s = wd;X }X }X else *s++=c;X }X if(s!=wd){X *s='\0';X v = newword(wd, v);X }X closeio(f);X Waitfor(pid, 0);X /* v points to reversed arglist -- reverse it onto argv */X while(v){X nextv = v->next;X v->next = runq->argv->words;X runq->argv->words = v;X v = nextv;X }X runq->pc = runq->code[runq->pc].i;X return;X }X}voidXXpipefd(void)X{X struct thread *p = runq;X int pc = p->pc;X char name[40];X int pfd[2];X int sidefd, mainfd;X if(pipe(pfd)<0){X Xerror("can't get pipe");X return;X }X if(p->code[pc].i==READ){X sidefd = pfd[PWR];X mainfd = pfd[PRD];X }X else{X sidefd = pfd[PRD];X mainfd = pfd[PWR];X }X switch(fork()){X case -1:X Xerror("try again");X break;X case 0:X start(p->code, pc+2, runq->local);X close(mainfd);X pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);X runq->ret = 0;X break;X default:X close(sidefd);X pushredir(ROPEN, mainfd, mainfd); /* isn't this a noop? */X strcpy(name, Fdprefix);X inttoascii(name+strlen(name), mainfd);X pushword(name);X p->pc = p->code[pc+1].i;X break;X }X}voidXXsubshell(void)X{X int pid;X switch(pid = fork()){X case -1:X Xerror("try again");X break;X case 0:X start(runq->code, runq->pc+1, runq->local);X runq->ret = 0;X break;X default:X Waitfor(pid, 1);X runq->pc = runq->code[runq->pc].i;X break;X }X}intexecforkexec(void)X{X int pid;X int n;X char buf[ERRMAX];X switch(pid = fork()){X case -1:X return -1;X case 0:X pushword("exec");X execexec();X strcpy(buf, "can't exec: ");X n = strlen(buf);X errstr(buf+n, ERRMAX-n);X Exit(buf);X }X return pid;X}!echo rc.hsed 's/^X//' >rc.h <<'!'X/*X * Plan9 is defined for plan 9X * V9 is defined for 9th editionX * Sun is defined for sun-osX * Please don't litter the code with ifdefs. The three below should be enough.X */X#define UnixX#ifdef Plan9X#include <u.h>X#include <libc.h>X#define NSIG 32X#define SIGINT 2X#define SIGQUIT 3X#endifX#ifdef UnixX#define _POSIX_SOURCEX#define _BSD_EXTENSIONX#include <stdlib.h>X#include <stdarg.h>X#include <string.h>X#include <unistd.h>X#include <fcntl.h>X#include <lib9.h>X#include <signal.h>X#endifX#ifndef ERRMAXX#define ERRMAX 128X#endifX#define YYMAXDEPTH 500X#ifndef PARENX#include "x.tab.h"X#endiftypedef struct tree tree;typedef struct word word;typedef struct io io;typedef union code code;typedef struct var var;typedef struct list list;typedef struct redir redir;typedef struct thread thread;typedef struct builtin builtin;struct tree{X int type;X int rtype, fd0, fd1; /* details of REDIR PIPE DUP tokens */X char *str;X int quoted;X int iskw;X tree *child[3];X tree *next;X};tree *newtree(void);tree *token(char*, int), *klook(char*), *tree1(int, tree*);tree *tree2(int, tree*, tree*), *tree3(int, tree*, tree*, tree*);tree *mung1(tree*, tree*), *mung2(tree*, tree*, tree*);tree *mung3(tree*, tree*, tree*, tree*), *epimung(tree*, tree*);tree *simplemung(tree*), *heredoc(tree*);void freetree(tree*);tree *cmdtree;X/*X * The first word of any code vector is a reference count.X * Always create a new reference to a code vector by calling codecopy(.).X * Always call codefree(.) when deleting a reference.X */union code{X void (*f)(void);X int i;X char *s;X};char *promptstr;int doprompt;X#define NTOK 8192char tok[NTOK];X#define APPEND 1X#define WRITE 2X#define READ 3X#define HERE 4X#define DUPFD 5X#define CLOSE 6struct var{X char *name; /* ascii name */X word *val; /* value */X int changed;X code *fn; /* pointer to function's code vector */X int fnchanged;X int pc; /* pc of start of function */X var *next; /* next on hash or local list */X};var *vlook(char*), *gvlook(char*), *newvar(char*, var*);X#define NVAR 521var *gvar[NVAR]; /* hash for globals */X#define new(type) ((type *)emalloc(sizeof(type)))char *emalloc(long);void *Malloc(ulong);void efree(char*);X#define NOFILE 128 /* should come from <param.h> */struct here{X tree *tag;X char *name;X struct here *next;X};int mypid;X/*X * Glob character escape in strings:X * In a string, GLOB must be followed by *?[ or GLOB.X * GLOB* matches any stringX * GLOB? matches any single characterX * GLOB[...] matches anything in the bracketsX * GLOBGLOB matches GLOBX */X#define GLOB ((char)0x01)X/*X * onebyte(c), twobyte(c), threebyte(c)X * Is c the first character of a one- two- or three-byte utf sequence?X */X#define onebyte(c) ((c&0x80)==0x00)X#define twobyte(c) ((c&0xe0)==0xc0)X#define threebyte(c) ((c&0xf0)==0xe0)char **argp;char **args;int nerror; /* number of errors encountered during compilation */int doprompt; /* is it time for a prompt? */X/*X * Which fds are the reading/writing end of a pipe?X * Unfortunately, this can vary from system to system.X * 9th edition Unix doesn't care, the following definesX * work on plan 9.X */X#define PRD 0X#define PWR 1char Rcmain[], Fdprefix[];X#define registerX/*X * How many dot commands have we executed?X * Used to ensure that -v flag doesn't print rcmain.X */int ndot;char *getstatus(void);int lastc;int lastword;!echo unix.csed 's/^X//' >unix.c <<'!'X/*X * Unix versions of system-specific functionsX * By convention, exported routines herein have names beginning with anX * upper case letter.X */X#include "rc.h"X#include "io.h"X#include "exec.h"X#include "getflags.h"X#include <errno.h>char Rcmain[]="/usr/lib/rcmain";char Fdprefix[]="/dev/fd/";void execfinit(void);struct builtin Builtin[] = {X "cd", execcd,X "whatis", execwhatis,X "eval", execeval,X "exec", execexec, /* but with popword first */X "exit", execexit,X "shift", execshift,X "wait", execwait,X "umask", execumask,X ".", execdot,X "finit", execfinit,X "flag", execflag,X 0X};X#define SEP '\1'char **environp;struct word*enval(s)register char *s;X{X char *t, c;X struct word *v;X for(t = s;*t && *t!=SEP;t++);X c=*t;X *t='\0';X v = newword(s, c=='\0'?(struct word *)0:enval(t+1));X *t = c;X return v;X}voidVinit(void)X{X extern char **environ;X char *s;X char **env = environ;X environp = env;X for(;*env;env++){X for(s=*env;*s && *s!='(' && *s!='=';s++);X switch(*s){X case '\0':X pfmt(err, "environment %q?\n", *env);X break;X case '=':X *s='\0';X setvar(*env, enval(s+1));X *s='=';X break;X case '(': /* ignore functions for now */X break;X }X }X}char **envp;voidXXrdfn(void)X{X char *s;X int len;X for(;*envp;envp++){X for(s=*envp;*s && *s!='(' && *s!='=';s++);X switch(*s){X case '\0':X pfmt(err, "environment %q?\n", *envp);X break;X case '=': /* ignore variables */X break;X case '(': /* Bourne again */X s=*envp+3;X envp++;X len = strlen(s);X s[len]='\n';X execcmds(opencore(s, len+1));X s[len]='\0';X return;X }X }X Xreturn();X}union code rdfns[4];voidexecfinit(void)X{X static int first = 1;X if(first){X rdfns[0].i = 1;X rdfns[1].f = Xrdfn;X rdfns[2].f = Xjump;X rdfns[3].i = 1;X first = 0;X }X Xpopm();X envp = environp;X start(rdfns, 1, runq->local);X}intcmpenv(const void *aa, const void *ab)X{X char **a = aa, **b = ab;X return strcmp(*a, *b);X}char **mkenv(void)X{X char **env, **ep, *p, *q;X struct var **h, *v;X struct word *a;X int nvar = 0, nchr = 0, sep;X /*X * Slightly kludgy loops look at locals then globals.X * locals no longer exist - geoffX */X for(h = gvar-1; h != &gvar[NVAR]; h++)X for(v = h >= gvar? *h: runq->local; v ;v = v->next){X if((v==vlook(v->name)) && v->val){X nvar++;X nchr+=strlen(v->name)+1;X for(a = v->val;a;a = a->next)X nchr+=strlen(a->word)+1;X }X if(v->fn){X nvar++;X nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8;X }X }X env = (char **)emalloc((nvar+1)*sizeof(char *)+nchr);X ep = env;X p = (char *)&env[nvar+1];X for(h = gvar-1; h != &gvar[NVAR]; h++)X for(v = h >= gvar? *h: runq->local;v;v = v->next){X if((v==vlook(v->name)) && v->val){X *ep++=p;X q = v->name;X while(*q) *p++=*q++;X sep='=';X for(a = v->val;a;a = a->next){X *p++=sep;X sep = SEP;X q = a->word;X while(*q) *p++=*q++;X }X *p++='\0';X }X if(v->fn){X *ep++=p;X *p++='#'; *p++='('; *p++=')'; /* to fool Bourne */X *p++='f'; *p++='n'; *p++=' ';X q = v->name;X while(*q) *p++=*q++;X *p++=' ';X q = v->fn[v->pc-1].s;X while(*q) *p++=*q++;X *p++='\0';X }X }X *ep = 0;X qsort((void *)env, nvar, sizeof ep[0], cmpenv);X return env; X}char *sigmsg[] = {X/* 0 normal */ 0,X/* 1 SIGHUP */ "Hangup",X/* 2 SIGINT */ 0,X/* 3 SIGQUIT */ "Quit",X/* 4 SIGILL */ "Illegal instruction",X/* 5 SIGTRAP */ "Trace/BPT trap",X/* 6 SIGIOT */ "abort",X/* 7 SIGEMT */ "EMT trap",X/* 8 SIGFPE */ "Floating exception",X/* 9 SIGKILL */ "Killed",X/* 10 SIGBUS */ "Bus error",X/* 11 SIGSEGV */ "Memory fault",X/* 12 SIGSYS */ "Bad system call",X/* 13 SIGPIPE */ 0,X/* 14 SIGALRM */ "Alarm call",X/* 15 SIGTERM */ "Terminated",X/* 16 unused */ "signal 16",X/* 17 SIGSTOP */ "Process stopped",X/* 18 unused */ "signal 18",X/* 19 SIGCONT */ "Process continued",X/* 20 SIGCHLD */ "Child death",X};voidWaitfor(int pid, int persist)X{X int wpid, sig;X struct thread *p;X int wstat;X char wstatstr[12];X for(;;){X errno = 0;X wpid = wait(&wstat);X if(errno==EINTR && persist)X continue;X if(wpid==-1)X break;X sig = wstat&0177;X if(sig==0177){X pfmt(err, "trace: ");X sig = (wstat>>8)&0177;X }X if(sig>(sizeof sigmsg/sizeof sigmsg[0]) || sigmsg[sig]){X if(pid!=wpid)X pfmt(err, "%d: ", wpid);X if(sig<=(sizeof sigmsg/sizeof sigmsg[0]))X pfmt(err, "%s", sigmsg[sig]);X else if(sig==0177) pfmt(err, "stopped by ptrace");X else pfmt(err, "signal %d", sig);X if(wstat&0200)pfmt(err, " -- core dumped");X pfmt(err, "\n");X }X wstat = sig?sig+1000:(wstat>>8)&0xFF;X if(wpid==pid){X inttoascii(wstatstr, wstat);X setstatus(wstatstr);X break;X }X else{X for(p = runq->ret;p;p = p->ret)X if(p->pid==wpid){X p->pid=-1;X inttoascii(p->status, wstat);X break;X }X }X }X}char **mkargv(a)register struct word *a;X{X char **argv = (char **)emalloc((count(a)+2)*sizeof(char *));X char **argp = argv+1; /* leave one at front for runcoms */X for(;a;a = a->next)X *argp++=a->word;X *argp = 0;X return argv;X}voidUpdenv(void)X{X}voidExecute(struct word *args, struct word *path)X{X char *msg="not found";X#ifdef ETXTBSYX int txtbusy = 0;X#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -