Path: utzoo!utgpu!cs.utexas.edu!usc!wuarchive!udel!princeton!phoenix.Princeton.EDU From: pfalstad@phoenix.Princeton.EDU (Paul John Falstad) Newsgroups: alt.sources Subject: zsh - ksh/tcsh-like shell (part 4 of 8) Message-ID: <4745@idunno.Princeton.EDU> Date: 14 Dec 90 23:31:22 GMT Sender: news@idunno.Princeton.EDU Organization: Princeton University, Princeton, New Jersey Lines: 3407 ---cut here---cut here---cut here--- - case 'M': - stradd(&bp,hostM); - break; - case 'm': - stradd(&bp,hostm); - break; - case 'S': - if (tgetstr("so",&bp)) - bp--; - break; - case 's': - if (tgetstr("se",&bp)) - bp--; - break; - case 'B': - if (tgetstr("md",&bp)) - bp--; - break; - case 'b': - if (tgetstr("me",&bp)) - bp--; - break; - case 'U': - if (tgetstr("us",&bp)) - bp--; - break; - case 'u': - if (tgetstr("ue",&bp)) - bp--; - break; - case 't': - case '@': - timet = time(NULL); - tm = localtime(&timet); - strftime(bp,16,"%l:%M%p",tm); - if (*bp == ' ') - chuck(bp); - bp += strlen(bp); - break; - case 'T': - timet = time(NULL); - tm = localtime(&timet); - strftime(bp,16,"%k:%M",tm); - bp += strlen(bp); - break; - case '*': - timet = time(NULL); - tm = localtime(&timet); - strftime(bp,16,"%k:%M:%S",tm); - bp += strlen(bp); - break; - case 'n': - stradd(&bp,username); - break; - case 'w': - timet = time(NULL); - tm = localtime(&timet); - strftime(bp,16,"%a %e",tm); - bp += strlen(bp); - break; - case 'W': - timet = time(NULL); - tm = localtime(&timet); - strftime(bp,16,"%m/%d/%y",tm); - bp += strlen(bp); - break; - case 'D': - timet = time(NULL); - tm = localtime(&timet); - strftime(bp,16,"%y-%m-%d",tm); - bp += strlen(bp); - break; - case 'l': - if (ss = ttyname(SHTTY)) - stradd(&bp,ss+8); - else - stradd(&bp,"(none)"); - break; - case '%': - *bp++ = '%'; - break; - case '#': - *bp++ = (geteuid()) ? '%' : '#'; - break; - default: - *bp++ = '%'; - *bp++ = *fm; - break; - } - else - *bp++ = *fm; - } - *bp = '\0'; - return buf; -} - -void herrflush(void) -{ - if (strin) - hflush(); - else while (lastc != '\n' && lastc != HERR) - hgetch(); - if (magic) - putc('\n',stderr); -} - -/* read an arbitrary amount of data into a buffer until stop is found */ - -char *hdynread(char stop) -{ -int bsiz = 256,ct = 0,c; -char *buf = zalloc(bsiz),*ptr; - - ptr = buf; - while ((c = hgetch()) != stop && c != '\n') - { - if (c == '\\') - c = hgetch(); - *ptr++ = c; - if (++ct == bsiz) - { - buf = realloc(buf,bsiz *= 2); - ptr = buf+ct; - } - } - *ptr = 0; - if (c == '\n') - { - hungetch('\n'); - zerr("delimiter expected"); - errflag = 1; - free(buf); - return NULL; - } - return buf; -} - -char *hdynread2(char stop) -{ -int bsiz = 256,ct = 0,c; -char *buf = zalloc(bsiz),*ptr; - - ptr = buf; - while ((c = hgetch()) != stop && c != '\n') - { - if (c == '\n') - { - hungetch(c); - break; - } - if (c == '\\') - if ((c = hgetch()) == '&') - c = '&'; - *ptr++ = c; - if (++ct == bsiz) - { - buf = realloc(buf,bsiz *= 2); - ptr = buf+ct; - } - } - *ptr = 0; - if (c == '\n') - hungetch('\n'); - return buf; -} - -/* set cbreak mode, or the equivalent */ - -void setcbreak(void) -{ -struct ttyinfo ti; - - ti = shttyinfo; -#ifdef TERMIOS - ti.termios.c_lflag &= ~ICANON; - ti.termios.c_cc[VMIN] = 1; - ti.termios.c_cc[VTIME] = 0; -#else - ti.sgttyb.sg_flags |= CBREAK; -#endif - settyinfo(&ti); -} - -int getlineleng(void) -{ -int z; - - z = shttyinfo.winsize.ws_col; - return (z) ? z : 80; -} - -void unsetcbreak(void) -{ - settyinfo(&shttyinfo); -} - -/* give the tty to some process */ - -void attachtty(long pgrp) -{ -static int ep = 0; - - if (jobbing) -#ifdef BUGGY_GCC - if (SHTTY != -1 && ioctl(SHTTY,(0x80000000|((sizeof(int)&0xff)<<16)| - ('t'<<8)|118),&pgrp) == -1 && !ep) -#else - if (SHTTY != -1 && ioctl(SHTTY,TIOCSPGRP,&pgrp) == -1 && !ep) -#endif - { - zerr("can't set tty pgrp: %e",errno); - opts[MONITOR] = OPT_UNSET; - ep =1; - } -} - End of hist.c echo hist.pro 1>&2 sed 's/^-//' >hist.pro <<'End of hist.pro' -void hwaddc(int c); -int hgetc(void); -void strinbeg(void); -void strinend(void); -int stuff(char *fn); -int hgetch(void); -void hungetch(int c); -void hungetc(int c); -void hflush(void); -void hungets(char *str); -void hbegin(void); -void inittty(void); -int hend(void); -void remhist(void); -void hwbegin(void); -char *hwadd(void); -int getargspec(int argc,int marg); -int hconsearch(char *str,int *marg); -int hcomsearch(char *str); -int apply1(int gflag,int (*func)(void **),table list); -int remtpath(void **junkptr); -int remtext(void **junkptr); -int rembutext(void **junkptr); -int remlpaths(void **junkptr); -int subst(int gbal,table slist,char *ptr1,char *ptr2); -int subststr(void **strptr,char *in,char *out,int gbal); -char *convamps(char *out,char *in); -char *makehlist(table tab,int freeit); -table quietgetevent(int ev); -table getevent(int ev); -int getargc(table tab); -table getargs(table elist,int arg1,int arg2); -int quote(void **tr); -int quotebreak(void **tr); -void stradd(char **p,char *d); -char *putprompt(char *fm); -void herrflush(void); -char *hdynread(char stop); -char *hdynread2(char stop); -void setcbreak(void); -int getlineleng(void); -void unsetcbreak(void); -void attachtty(long pgrp); End of hist.pro echo init.c 1>&2 sed 's/^-//' >init.c <<'End of init.c' -/* - - init.c - initialization, main loop - - This file is part of zsh, the Z shell. - - zsh is free software; no one can prevent you from reading the source - code, or giving it to someone else. - This file is copyrighted under the GNU General Public License, which - can be found in the file called COPYING. - - Copyright (C) 1990 Paul Falstad - - zsh is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY. No author or distributor accepts - responsibility to anyone for the consequences of using it or for - whether it serves any particular purpose or works at all, unless he - says so in writing. Refer to the GNU General Public License - for full details. - - Everyone is granted permission to copy, modify and redistribute - zsh, but only under the conditions described in the GNU General Public - License. A copy of this license is supposed to have been given to you - along with zsh so you can know your rights and responsibilities. - It should be in a file named COPYING. - - Among other things, the copyright notice and this notice must be - preserved on all copies. - -*/ - -#include "zsh.h" -#include "funcs.h" -#include - -void main(int argc, char **argv) -{ -int notect = 0; - - setflags(); - parseargs(argv); - setmoreflags(); - setupvals(); - initialize(); - runscripts(); - FOREVER - { - do - loop(); - while (peek != EOF); - if (!(isset(IGNOREEOF) && interact)) - { - if (interact) - fputs(islogin ? "logout\n" : "exit\n",stderr); - zexit(NULL); - continue; - } - zerrnam("\nzsh",(!islogin) ? "use 'exit' to exit." - : "use 'logout' to logout."); - notect++; - if (notect == 10) - zexit(NULL); - } -} - -/* keep executing lists until EOF found */ - -void loop(void) -{ -list list; - - FOREVER - { - peek = EMPTY; - if (interact) - preprompt(); - hbegin(); /* init history mech */ - intr(); /* interrupts on */ - ainit(); /* init alias mech */ - if (!(list = parlist1(0))) - { /* if we couldn't parse a list */ - hend(); - if (!errflag) - if (peek == OUTPAR) - { - errflag = 1; - zerr("mismatched parenthesis"); - } - else if (peek == OUTBRACE) - { - errflag = 1; - zerr("mismatched brace"); - } - else if (peek != EOF && peek != EMPTY && peek != NEWLIN) - { - errflag = 1; - zerr("semicolon or newline expected"); - } - if (peek == EOF && !errflag) - return; - continue; - } - if (peek != EMPTY && peek != EOF) - { - if (peek == OUTPAR) - zerr("mismatched parenthesis"); - else if (peek == OUTBRACE) - zerr("mismatched brace"); - else - zerr("semicolon or newline expected"); - hend(); - errflag = 1; - } - else if (hend()) - { - if (stopmsg) /* unset 'you have stopped jobs' flag */ - stopmsg--; - execlist(list); - } - if (ferror(stderr)) - { - zerr("write error"); - clearerr(stderr); - } - if (subsh) /* how'd we get this far in a subshell? */ - exit(lastval); - if ((!interact && errflag) || retflag) - return; - if ((opts['t'] == OPT_SET) || (lastval && opts[ERREXIT] == OPT_SET)) - { - if (sigtrapped[SIGEXIT]) - dotrap(SIGEXIT); - exit(lastval); - } - } -} - -void setflags(void) -{ -int c; - - for (c = 0; c != 128; c++) - opts[c] = OPT_INVALID; - opts['a'] = opts['e'] = opts['f'] = opts['h'] = opts['k'] = opts['n'] = - opts['s'] = opts['t'] = opts['u'] = opts['v'] = opts['x'] = - opts['c'] = OPT_UNSET; - opts['i'] = (isatty(0)) ? OPT_SET : OPT_UNSET; - for (c = '0'; c <= '9'; c++) - opts[c] = OPT_UNSET; - for (c = 'A'; c <= 'K'; c++) - opts[c] = OPT_UNSET; - opts[BGNICE] = opts[NOTIFY] = OPT_SET; -} - -static char *cmd; - -void parseargs(char **argv) -{ -char *argv0 = *argv; -int bk = 0; - - islogin = **(argv++) == '-'; - SHIN = 0; - while (!bk && *argv && **argv == '-') - { - while (*++*argv) - { - if (opts[**argv] == OPT_INVALID) - { - zerr("bad option: -%c",**argv); - exit(1); - } - opts[**argv] = OPT_SET; - if (bk = **argv == 'b') - break; - if (**argv == 'c') /* -c command */ - { - argv++; - if (!*argv) - { - zerr("string expected after -c"); - exit(1); - } - cmd = strdup(*argv); - opts[INTERACTIVE] = OPT_UNSET; - break; - } - } - argv++; - } - pparms = newtable(); - if (*argv) - { - if (opts[SHINSTDIN] == OPT_UNSET) - { - SHIN = movefd(open(argv0 = *argv,O_RDONLY)); - if (SHIN == -1) - { - zerr("can't open input file: %s",*argv); - exit(1); - } - opts[INTERACTIVE] = OPT_UNSET; - argv++; - } - addnode(pparms,argv0); /* assign positional parameters */ - while (*argv) - addnode(pparms,strdup(*argv++)); - } - else - { - addnode(pparms,strdup(argv0)); - opts[SHINSTDIN] = OPT_SET; - } -} - -void setmoreflags(void) -{ - setlinebuf(stderr); - setlinebuf(stdout); - subsh = 0; - opts[MONITOR] = (interact) ? OPT_SET : OPT_UNSET; - if (jobbing) - { - SHTTY = movefd((isatty(0)) ? dup(0) : open("/dev/tty",O_RDWR)); - if (SHTTY == -1) - opts[MONITOR] = OPT_UNSET; - else - gettyinfo(&shttyinfo); /* get tty state */ - if ((shpgrp = getpgrp(0)) <= 0) - opts[MONITOR] = OPT_UNSET; - } - else - SHTTY = -1; -} - -void setupvals(void) -{ -struct passwd *pwd; -char *ptr; - - shtimer = time(NULL); /* init $SECONDS */ - /* build various hash tables; argument to newhtable is table size */ - alhtab = newhtable(37); - parmhtab = newhtable(17); - shfunchtab = newhtable(17); - if (interact) - { - if (!getparm("PROMPT")) - setparm(strdup("PROMPT"),strdup("%M%# "),0,0); - if (!getparm("PROMPT2")) - setparm(strdup("PROMPT2"),strdup("> "),0,0); - if (!getparm("PROMPT3")) - setparm(strdup("PROMPT3"),strdup("?# "),0,0); - } - if (!getparm("PATH")) - setparm(strdup("PATH"),strdup("/bin:/usr/bin:/usr/ucb"),1,0); - setparm(strdup("VERSION"),strdup(VERSIONSTR),1,0); - home = xsymlink(getparm("HOME")); - setparm(strdup("HOME"),strdup(home),0,0); - setiparm(strdup("UID"),getuid(),1); - setiparm(strdup("EUID"),geteuid(),1); - setiparm(strdup("PPID"),getppid(),1); - lineno = 0; - pwd = getpwuid(getuid()); - setparm(strdup("USERNAME"),strdup(pwd->pw_name),0,0); - username = strdup(pwd->pw_name); - setparm(strdup("HOSTTYPE"),strdup(HOSTTYP),0,0); - cwd = zgetwd(); - setparm(strdup("PWD"),strdup(cwd),0,0); - if (!getparm("IFS")) - { - ifs = strdup(" \t\n"); - setparm(strdup("IFS"),strdup(ifs),0,0); - } - hostM = alloc(512); /* get hostname, with and without .podunk.edu */ - hostm = hostM+256; - gethostname(hostm,256); - gethostname(hostM,256); - procnum = getpid(); - for (ptr = hostM; *ptr && *ptr != '.'; ptr++); - *ptr = '\0'; -} - -void initialize(void) -{ -int t0; - - breaks = loops = incmd = 0; - lastmailcheck = 0; - lastmailval = -1; - tfev = 1; - tevs = DEFAULT_HISTSIZE; - histlist = newtable(); - dirstack = newtable(); - ungots = ungotptr = NULL; - signal(SIGQUIT,SIG_IGN); - for (t0 = 0; t0 != RLIM_NLIMITS; t0++) - getrlimit(t0,limits+t0); - last = rast = NULL; - proclast = 0; - if (!interact || SHTTY == -1) - bshin = fdopen(SHIN,"r"); - signal(SIGCHLD,handler); - addreswords(); - addhnode(strdup("false"),mkanode(strdup("let 0"),1),alhtab,NULL); - addhnode(strdup("history"),mkanode(strdup("fc -l"),1),alhtab,NULL); - addhnode(strdup("nohup"),mkanode(strdup("nohup "),1),alhtab,NULL); - addhnode(strdup("r"),mkanode(strdup("fc -e -"),1),alhtab,NULL); - addhnode(strdup("true"),mkanode(strdup(":"),1),alhtab,NULL); - addhnode(strdup("pwd"),mkanode(strdup("echo $PWD"),1),alhtab,NULL); - parsepath(); - parsecdpath(); - if (jobbing) - { - signal(SIGTTOU,SIG_IGN); - signal(SIGTSTP,SIG_IGN); - signal(SIGTTIN,SIG_IGN); - signal(SIGPIPE,SIG_IGN); - attachtty(shpgrp); - } - if (interact) - { - signal(SIGTERM,SIG_IGN); - intr(); - } -} - -void addreswords(void) -{ -char *reswds[] = { - "do", "done", "esac", "then", "elif", "else", "fi", "for", "case", - "if", "while", "function", "repeat", "time", "until", "exec", "command", - "select", "coproc", NULL - }; -int t0; - - for (t0 = 0; reswds[t0]; t0++) - addhnode(strdup(reswds[t0]),mkanode(NULL,-1-t0),alhtab,NULL); -} - -void runscripts(void) -{ - if (interact) - checkfirstmail(); - if (opts[NORCS] == OPT_UNSET) - { -#ifdef GLOBALZSHRC - source(GLOBALZSHRC); -#endif - sourcehome(".zshrc"); - if (islogin) - { -#ifdef GLOBALZLOGIN - source(GLOBALZLOGIN); -#endif - sourcehome(".zlogin"); - } - } - if (opts['c'] == OPT_SET) - { - close(SHIN); - SHIN = movefd(open("/dev/null",O_RDONLY)); - hungets(cmd); - strinbeg(); - } -} - -void ainit(void) -{ - alix = 0; /* reset alias stack */ - alstat = 0; - firstln = 1; -} End of init.c echo init.pro 1>&2 sed 's/^-//' >init.pro <<'End of init.pro' -void main(int argc, char **argv); -void loop(void); -void setflags(void); -void parseargs(char **argv); -void setmoreflags(void); -void setupvals(void); -void initialize(void); -void addreswords(void); -void runscripts(void); -void ainit(void); End of init.pro echo jobs.c 1>&2 sed 's/^-//' >jobs.c <<'End of jobs.c' -/* - - jobs.c - job control - - This file is part of zsh, the Z shell. - - zsh is free software; no one can prevent you from reading the source - code, or giving it to someone else. - This file is copyrighted under the GNU General Public License, which - can be found in the file called COPYING. - - Copyright (C) 1990 Paul Falstad - - zsh is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY. No author or distributor accepts - responsibility to anyone for the consequences of using it or for - whether it serves any particular purpose or works at all, unless he - says so in writing. Refer to the GNU General Public License - for full details. - - Everyone is granted permission to copy, modify and redistribute - zsh, but only under the conditions described in the GNU General Public - License. A copy of this license is supposed to have been given to you - along with zsh so you can know your rights and responsibilities. - It should be in a file named COPYING. - - Among other things, the copyright notice and this notice must be - preserved on all copies. - -*/ - -#include "zsh.h" -#include "funcs.h" -#include - -#define WCOREDUMPED(x) ((x)&0x80) - -/* != 0 means the handler is active */ - -static int handling = 0; - -/* != 0 means the shell is waiting for a job to complete */ - -static int waiting = 0; - -/* != 0 means readline is active */ - -extern int rl_active; - -/* != 0 means readline is waiting for a keypress */ - -extern int rl_waiting; - -#ifdef INTHANDTYPE -#define RETURN return 0 -#else -#define RETURN return -#endif - -/* the signal handler */ - -HANDTYPE handler(int sig,int code) -{ -long pid; -int statusp; -struct jobnode *jn; -struct procnode *pn; -struct rusage ru; - - if (sig == SIGINT) - { - if (sigtrapped[SIGINT]) - dotrap(SIGINT); - else - errflag = 1; - RETURN; - } - if (sig != SIGCHLD) - { - dotrap(sig); - RETURN; - } - for (;;) - { - pid = wait3(&statusp,WNOHANG|WUNTRACED,&ru); - if (pid == -1) - { - if (errno != ECHILD) - zerr("%e",errno); - RETURN; - } - if (!pid) - RETURN; - findproc(pid,&jn,&pn); /* find the procnode of this pid */ - if (jn) - { - pn->statusp = statusp; - handling = 1; - pn->ru_utime = ru.ru_utime; - pn->ru_stime = ru.ru_stime; - pn->endtime = time(NULL); - updatestatus(jn); - handling = 0; - } - else if (WIFSTOPPED(SP(statusp))) - kill(pid,SIGKILL); /* kill stopped untraced children */ - } - if (rl_active) - rl_prep_terminal(); - RETURN; -} - -/* change job table entry from stopped to running */ - -void makerunning(struct jobnode *jn) -{ -struct procnode *pn; - - jn->stat &= ~STAT_STOPPED; - for (pn = jn->procs; pn; pn = pn->next) - if (WIFSTOPPED(SP(pn->statusp))) - pn->statusp = SP_RUNNING; -} - -/* update status of job, possibly printing it */ - -void updatestatus(struct jobnode *jn) -{ -struct procnode *pn; -int notrunning = 1,alldone = 1,val,job = jn-jobtab,somestopped = 0; - - for (pn = jn->procs; pn; pn = pn->next) - { - if (pn->statusp == SP_RUNNING) - notrunning = 0; - if (pn->statusp == SP_RUNNING || WIFSTOPPED(SP(pn->statusp))) - alldone = 0; - if (WIFSTOPPED(SP(pn->statusp))) - somestopped = 1; - if (!pn->next && jn) - val = (WIFSIGNALED(SP(pn->statusp))) ? - 0200 | WTERMSIG(SP(pn->statusp)) : WEXITSTATUS(SP(pn->statusp)); - } - if (!notrunning) - return; - if (somestopped && (jn->stat & STAT_STOPPED)) - return; - jn->stat |= (alldone) ? STAT_CHANGED|STAT_DONE : - STAT_CHANGED|STAT_STOPPED; - if (!alldone) - gettyinfo(&jn->ttyinfo); - if (job == curjob) - { - if (!val) - gettyinfo(&shttyinfo); - else - settyinfo(&shttyinfo); - lastval = val; - } - if (jn->stat & STAT_STOPPED) - { - prevjob = topjob; - topjob = job; - } - if ((isset(NOTIFY) || job == curjob) && jn->stat & STAT_LOCKED) - printjob(jn,0); - if (sigtrapped[SIGCHLD] && job != curjob) - dotrap(SIGCHLD); -} - -/* find procnode and jobnode associated with pid */ - -void findproc(int pid,struct jobnode **jptr,struct procnode **pptr) -{ -struct procnode *pn; -int jn; - - for (jn = 1; jn != MAXJOB; jn++) - for (pn = jobtab[jn].procs; pn; pn = pn->next) - if (pn->pid == pid) - { - *pptr = pn; - *jptr = jobtab+jn; - return; - } - *pptr = NULL; - *jptr = NULL; -} - -static char *sigmsg[32] = { - "done","hangup","interrupt","quit", - "illegal instruction","trace trap","IOT instruction","EMT instruction", - "floating exception","killed","bus error","segmentation fault", - "bad system call","broken pipe","SIGALRM","terminated", -#ifdef USE_SUSPENDED - "SIGURG","suspended (signal)","suspended","continued", - "SIGCHLD","suspended (tty input)","suspended (tty output)","SIGIO", -#else - "SIGURG","stopped (signal)","stopped","continued", - "SIGCHLD","stopped (tty input)","stopped (tty output)","SIGIO", -#endif - "CPU time limit exceeded","file size limit exceeded","SIGVTALRM","SIGPROF", - "window changed","resource lost","SIGUSR1","SIGUSR2" - }; - -/* lng = 0 means jobs - lng = 1 means jobs -l - lng = 2 means jobs -p -*/ - -void printjob(struct jobnode *jn,int lng) -{ -int job = jn-jobtab,len = 9,sig = -1,sflag = 0,llen,printed = 0; -int conted = 0,lineleng = getlineleng(),doputnl = 0; -struct procnode *pn; -extern void rl_on_new_line(void); - - if (lng < 0) - { - conted = 1; - lng = 0; - } - - /* find length of longest signame, check to see if we - really need to print this job */ - - for (pn = jn->procs; pn; pn = pn->next) - { - if (pn->statusp != SP_RUNNING) - if (WIFSIGNALED(SP(pn->statusp))) - { - sig = WTERMSIG(SP(pn->statusp)); - llen = strlen(sigmsg[sig]); - if (WCOREDUMPED(pn->statusp)) - llen += 14; - if (llen > len) - len = llen; - if (sig != SIGINT && sig != SIGPIPE) - sflag = 1; - if (sig == SIGINT && job == curjob && interact) - doputnl = 1; - } - else if (WIFSTOPPED(SP(pn->statusp))) - { - sig = WSTOPSIG(SP(pn->statusp)); - if (strlen(sigmsg[sig]) > len) - len = strlen(sigmsg[sig]); - } - else if (isset(PRINTEXITVALUE) && WEXITSTATUS(SP(pn->statusp))) - sflag = 1; - } - if (doputnl) - putc('\n',stderr); - - /* print if necessary */ - - if (interact && jobbing && ((jn->stat & STAT_STOPPED) || sflag || - job != curjob)) - { - int len2,fline = 1; - struct procnode *qn; - - if (handling && (!waiting || jn->stat & STAT_STOPPED)) - putc('\n',stderr); - for (pn = jn->procs; pn;) - { - len2 = ((job == curjob) ? 5 : 10)+len; /* 2 spaces */ - if (lng) - qn = pn->next; - else for (qn = pn->next; qn; qn = qn->next) - { - if (qn->statusp != pn->statusp) - break; - if (strlen(qn->text)+len2+((qn->next) ? 3 : 0) > lineleng) - break; - len2 += strlen(qn->text)+2; - } - if (job != curjob) - if (fline) - fprintf(stderr,"[%d] %c ",jn-jobtab,(job == topjob) ? '+' : - (job == prevjob) ? '-' : ' '); - else - fprintf(stderr,(job > 9) ? " " : " "); - else - fprintf(stderr,"zsh: "); - if (lng) - if (lng == 1) - fprintf(stderr,"%d ",pn->pid); - else - { - fprintf(stderr,"%d ",jn->gleader); - lng = 0; - } - if (pn->statusp == SP_RUNNING) - if (!conted) - fprintf(stderr,"running%*s",len-7+2,""); - else - fprintf(stderr,"continued%*s",len-9+2,""); - else if (WIFEXITED(SP(pn->statusp))) - if (WEXITSTATUS(SP(pn->statusp))) - fprintf(stderr,"exit %-4d%*s",WEXITSTATUS(SP(pn->statusp)), - len-9+2,""); - else - fprintf(stderr,"done%*s",len-4+2,""); - else if (WIFSTOPPED(SP(pn->statusp))) - fprintf(stderr,"%-*s",len+2,sigmsg[WSTOPSIG(SP(pn->statusp))]); - else if (WCOREDUMPED(pn->statusp)) - fprintf(stderr,"%s (core dumped)%*s", - sigmsg[WTERMSIG(SP(pn->statusp))], - len-14+2-strlen(sigmsg[WTERMSIG(SP(pn->statusp))]),""); - else - fprintf(stderr,"%-*s",len+2,sigmsg[WTERMSIG(SP(pn->statusp))]); - for (; pn != qn; pn = pn->next) - fprintf(stderr,(pn->next) ? "%s | " : "%s",pn->text); - putc('\n',stderr); - fline = 0; - } - printed = 1; - } - - /* print "(pwd now: foo)" messages */ - - if (interact && job==curjob && strcmp(jn->cwd,cwd)) - { - printf("(pwd now: "); - printdir(cwd); - printf(")\n"); - fflush(stdout); - } - - /* delete job if done */ - - if (jn->stat & STAT_DONE) - { - static struct jobnode zero; - struct procnode *nx; - char *s; - - if (jn->stat & STAT_TIMED) - { - dumptime(jn); - printed = 1; - } - for (pn = jn->procs; pn; pn = nx) - { - nx = pn->next; - if (pn->text) - free(pn->text); - free(pn); - } - free(jn->cwd); - if (jn->filelist) - { - while (s = getnode(jn->filelist)) - { - unlink(s); - free(s); - } - free(jn->filelist); - } - *jn = zero; - if (job == topjob) - { - topjob = prevjob; - prevjob = job; - } - if (job == prevjob) - setprevjob(); - } - else - jn->stat &= ~STAT_CHANGED; - if (printed && rl_active) - { - rl_on_new_line(); - if (rl_waiting) - rl_redisplay(); - } -} - -/* set the previous job to something reasonable */ - -void setprevjob(void) -{ -int t0; - - for (t0 = MAXJOB-1; t0; t0--) - if (jobtab[t0].stat && jobtab[t0].stat & STAT_STOPPED && - t0 != topjob && t0 != curjob) - break; - if (!t0) - for (t0 = MAXJOB-1; t0; t0--) - if (jobtab[t0].stat && t0 != topjob && t0 != curjob) - break; - prevjob = (t0) ? t0 : -1; -} - -/* initialize a job table entry */ - -void initjob(int flags) -{ - jobtab[curjob].cwd = strdup(cwd); - jobtab[curjob].stat = (flags & PFLAG_TIMED) | STAT_INUSE; - jobtab[curjob].ttyinfo = shttyinfo; - jobtab[curjob].gleader = 0; -} - -/* add a process to the current job */ - -struct procnode *addproc(long pid,char *text) -{ -struct procnode *procnode; - - if (!jobtab[curjob].gleader) - jobtab[curjob].gleader = proclast = pid; - proclast = pid; - procnode = alloc(sizeof(struct procnode)); - procnode->pid = pid; - procnode->text = text; - procnode->next = NULL; - procnode->statusp = SP_RUNNING; - procnode->bgtime = time(NULL); - if (jobtab[curjob].procs) - { - struct procnode *n; - - for (n = jobtab[curjob].procs; n->next && !n->next->lastfg; n = n->next); - procnode->next = n->next; - n->next = procnode; - } - else - jobtab[curjob].procs = procnode; - return procnode; -} - -/* determine if it's all right to exec a command without - forking in last component of subshells; it's not ok if we have files - to delete */ - -int execok(void) -{ -struct jobnode *jn; - - if (!exiting) - return 0; - for (jn = jobtab+1; jn != jobtab+MAXJOB; jn++) - if (jn->stat && jn->filelist) - return 0; - return 1; -} - -/* wait for a SIGCHLD, wait for the handler to execute, and return */ - -void chldsuspend(void) -{ -struct sigvec vec = { handler,sigmask(SIGCHLD),SV_INTERRUPT }; - - sigvec(SIGCHLD,&vec,NULL); - sigpause(0); - signal(SIGCHLD,handler); -} - -/* wait for the current job to finish */ - -void waitjobs(void) -{ -static struct jobnode zero; -struct jobnode *jn; - - if (jobtab[curjob].procs) /* if any forks were done */ - { - jobtab[curjob].stat |= STAT_LOCKED; - waiting = 1; - if (jobtab[curjob].stat & STAT_CHANGED) - printjob(jobtab+curjob,0); - while (jobtab[curjob].stat && - !(jobtab[curjob].stat & (STAT_DONE|STAT_STOPPED))) - chldsuspend(); - waiting = 0; - } - else /* else do what printjob() usually does */ - { - char *s; - - jn = jobtab+curjob; - free(jn->cwd); - if (jn->filelist) - { - while (s = getnode(jn->filelist)) - { - unlink(s); - free(s); - } - free(jn->filelist); - } - *jn = zero; - } - curjob = -1; -} - -/* clear jobtab when entering subshells */ - -void clearjobtab(void) -{ -static struct jobnode zero; -int t0; - - for (t0 = 1; t0 != MAXJOB; t0++) - jobtab[curjob] = zero; -} - -/* get a free entry in the job table to use */ - -int getfreejob(void) -{ -int mask,t0; - - FOREVER - { - mask = sigblock(sigmask(SIGCHLD)); - for (t0 = 1; t0 != MAXJOB; t0++) - if (!jobtab[t0].stat) - { - sigsetmask(mask); - jobtab[t0].stat |= STAT_INUSE; - return t0; - } - sigsetmask(mask); - sleep(1); - } -} - -/* print pids for & */ - -void spawnjob(void) -{ -struct procnode *pn; - - if (!subsh) - { - if (topjob == -1 || !(jobtab[topjob].stat & STAT_STOPPED)) - { - topjob = curjob; - setprevjob(); - } - else if (prevjob == -1 || !(jobtab[prevjob].stat & STAT_STOPPED)) - prevjob = curjob; - if (interact && jobbing) - { - fprintf(stderr,"[%d]",curjob); - for (pn = jobtab[curjob].procs; pn; pn = pn->next) - fprintf(stderr," %d",pn->pid); - fprintf(stderr,"\n"); - } - } - jobtab[curjob].stat |= STAT_LOCKED; - curjob = -1; -} - -void fixsigs(void) -{ - sigsetmask(0); -} - -/* timing */ - -static void addtimeval(struct timeval *s,struct timeval *t) -{ - s->tv_sec += t->tv_sec+(s->tv_usec+t->tv_usec)/1000000; - s->tv_usec = (s->tv_usec+t->tv_usec)%1000000; -} - -static void printtime(time_t real,struct timeval *u,struct timeval *s,char *desc) -{ - if (!desc) - desc = ""; - fprintf(stderr,"real: %lds user: %ld.%03lds sys: %ld.%03lds\n", - real,u->tv_sec,u->tv_usec/1000,s->tv_sec,s->tv_usec/1000); -} - -static void printheader(void) -{ - fprintf(stderr," real user system\n"); -} - -static void printtimes(time_t real,struct timeval *u,struct timeval *s,char *desc) -{ - if (!desc) - desc = ""; - fprintf(stderr,"% 8lds % 4d.%03lds % 4d.%03lds %s\n", - real,u->tv_sec,u->tv_usec/1000,s->tv_sec,s->tv_usec/1000,desc); -} - -void dumptime(struct jobnode *jn) -{ -struct procnode *pn = jn->procs; -struct timeval utot = { 0,0 },stot = { 0,0 }; -time_t maxend,minbeg; - - if (!jn->procs) - return; - if (!jn->procs->next) - printtime(pn->endtime-pn->bgtime,&pn->ru_utime,&pn->ru_stime,pn->text); - else - { - maxend = jn->procs->endtime; - minbeg = jn->procs->bgtime; - printheader(); - for (pn = jn->procs; pn; pn = pn->next) - { - printtimes(pn->endtime-pn->bgtime,&pn->ru_utime,&pn->ru_stime,pn->text); - addtimeval(&utot,&pn->ru_utime); - addtimeval(&stot,&pn->ru_stime); - if (pn->endtime > maxend) - maxend = pn->endtime; - if (pn->bgtime < minbeg) - minbeg = pn->bgtime; - } - printtimes(maxend-minbeg,&utot,&stot,"total"); - } -} - -/* SIGHUP any jobs left running */ - -void killrunjobs(void) -{ -int t0,killed = 0; - - for (t0 = 1; t0 != MAXJOB; t0++) - if (t0 != curjob && jobtab[t0].stat && - !(jobtab[t0].stat & STAT_STOPPED)) - { - killpg(jobtab[t0].gleader,SIGHUP); - killed++; - } - if (killed) - zerr("warning: %d jobs SIGHUPed",killed); -} - -/* check to see if user has jobs running/stopped */ - -void checkjobs(void) -{ -int t0; - - for (t0 = 1; t0 != MAXJOB; t0++) - if (t0 != curjob && jobtab[t0].stat) - break; - if (t0 != MAXJOB) - { - if (jobtab[t0].stat & STAT_STOPPED) - { -#ifdef USE_SUSPENDED - zerr("you have suspended jobs."); -#else - zerr("you have stopped jobs."); -#endif - } - else - zerr("you have running jobs."); - stopmsg = 1; - } -} - -/* send a signal to a job (simply involves killpg if monitoring is on) */ - -int killjb(struct jobnode *jn,int sig) -{ -struct procnode *pn; -int err; - - if (jobbing) - return(killpg(jn->gleader,sig)); - for (pn = jn->procs; pn; pn = pn->next) - if ((err = kill(pn->pid,sig)) == -1 && errno != ESRCH) - return -1; - return err; -} - End of jobs.c echo jobs.pro 1>&2 sed 's/^-//' >jobs.pro <<'End of jobs.pro' -HANDTYPE handler(int sig,int code); -void makerunning(struct jobnode *jn); -void updatestatus(struct jobnode *jn); -void findproc(int pid,struct jobnode **jptr,struct procnode **pptr); -void printjob(struct jobnode *jn,int lng); -void setprevjob(void); -void initjob(int flags); -struct procnode *addproc(long pid,char *text); -int execok(void); -void chldsuspend(void); -void waitjobs(void); -void clearjobtab(void); -int getfreejob(void); -void spawnjob(void); -void fixsigs(void); -void dumptime(struct jobnode *jn); -void killrunjobs(void); -void checkjobs(void); -int killjb(struct jobnode *jn,int sig); End of jobs.pro echo lex.c 1>&2 sed 's/^-//' >lex.c <<'End of lex.c' -/* - - lex.c - lexical analysis - - This file is part of zsh, the Z shell. - - zsh is free software; no one can prevent you from reading the source - code, or giving it to someone else. - This file is copyrighted under the GNU General Public License, which - can be found in the file called COPYING. - - Copyright (C) 1990 Paul Falstad - - zsh is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY. No author or distributor accepts - responsibility to anyone for the consequences of using it or for - whether it serves any particular purpose or works at all, unless he - says so in writing. Refer to the GNU General Public License - for full details. - - Everyone is granted permission to copy, modify and redistribute - zsh, but only under the conditions described in the GNU General Public - License. A copy of this license is supposed to have been given to you - along with zsh so you can know your rights and responsibilities. - It should be in a file named COPYING. - - Among other things, the copyright notice and this notice must be - preserved on all copies. - -*/ - -#include "zsh.h" -#include "funcs.h" - -/* match the current token and get another - (actually just get another) */ - -void matchit(void) -{ - do - gettok(); - while (exalias()); -} - -int len = 0,bsiz = 256; -char *bptr; - -/* add a char to the string buffer */ - -void add(int c) -{ - *bptr++ = c; - if (bsiz == ++len) - bptr = len+(tstr = realloc(tstr,bsiz *= 2)); -} - -/* get a token */ - -void gettok(void) -{ -int bct = 0,pct = 0; -int c,d,intpos = 1; -static int dbparens = 0; - -beginning: - hlastw = NULL; - tstr = NULL; - while (zspace(c = hgetc()) || c == '\t' || c == ' '); - firstln = 0; - hwbegin(); - hwaddc(c); - if (dbparens) /* handle ((...)) */ - { - int pct = 2; - - peek = STRING; - len = dbparens = 0; - bptr = tstr = zalloc(bsiz = 256); - for (;;) - { - if (c == '(') - pct++; - else if (c == ')') - pct--; - else if (c == '\n') - { - zerr("parse error: )) expected"); - peek = HERR; - free(tstr); - return; - } - else if (c == '$') - c = Qstring; - if (pct >= 2) - add(c); - if (pct) - c = hgetc(); - else - break; - } - *bptr = '\0'; - return; - } - peekfd = -1; - if (isdigit(c)) /* handle 1< foo */ - { - d = hgetc(); - hungetc(d); - if (d == '>' || d == '<') - { - peekfd = c-'0'; - c = hgetc(); - } - } - - /* chars in initial position in word */ - - switch (c) - { - case '\\': - d = hgetc(); - if (d == '\n') - goto beginning; - hungetc(d); - break; - case EOF: - peek = EOF; - return; - case HERR: - peek = HERR; - return; - case '\n': - peek = NEWLIN; - return; - case ';': - d = hgetc(); - if (d != ';') - { - hungetc(d); - peek = SEMI; - } - else - peek = DSEMI; - return; - case '!': - if (!incmd) - { - peek = BANG; - return; - } - break; - case '&': - d = hgetc(); - if (d != '&') - { - hungetc(d); - peek = AMPER; - } - else - peek = DAMPER; - return; - case '|': - d = hgetc(); - if (d == '|') - peek = DBAR; - else if (d == '&') - peek = BARAMP; - else - { - hungetc(d); - peek = BAR; - } - return; - case '(': - if (incmd) - break; - d = hgetc(); - if (d == '(') - { - peek = STRING; - tstr = strdup("let"); - dbparens = 1; - return; - } - hungetc(d); - peek = INPAR; - return; - case ')': - peek = OUTPAR; - return; - case '{': - if (incmd) - break; - peek = INBRACE; - return; - case '}': - peek = OUTBRACE; - return; - case '<': - d = hgetc(); - if (incmd && d == '(') - { - hungetc(d); - break; - } - else if (d == '<') - { - int e = hgetc(); - - hungetc(e); - if (e == '(') - { - hungetc(d); - peek = INANG; - } - else - peek = DINANG; - } - else if (d == '&') - peek = INANGAMP; - else - { - peek = INANG; - hungetc(d); - } - return; - case '>': - d = hgetc(); - if (d == '(') - { - hungetc(d); - break; - } - else if (d == '&') - { - d = hgetc(); - if (d == '!') - peek = OUTANGAMPBANG; - else - { - hungetc(d); - peek = OUTANGAMP; - } - } - else if (d == '!') - peek = OUTANGBANG; - else if (d == '>') - { - d = hgetc(); - if (d == '&') - { - d = hgetc(); - if (d == '!') - peek = DOUTANGAMPBANG; - else - { - hungetc(d); - peek = DOUTANGAMP; - } - } - else if (d == '!') - peek = DOUTANGBANG; - else if (d == '(') - { - hungetc(d); - hungetc('>'); - peek = OUTANG; - } - else - { - hungetc(d); - peek = DOUTANG; - } - } - else - { - hungetc(d); - peek = OUTANG; - } - return; - case '#': -#ifndef INTERACTIVE_COMMENTS - if (interact) - break; -#endif - while ((c = hgetch()) != '\n' && !istok(c) && c != EOF); - if (c == '\n') - peek = NEWLIN; - else - errflag = 1; - return; - } - - /* we've started a string, now get the rest of it, performing - tokenization */ - - peek = STRING; - len = 0; - bptr = tstr = zalloc(bsiz = 256); - for(;;) - { - if (c == ';' || c == '&' || c == EOF || - c == HERR || c == '\03' || c == '\n' || - c == ' ' || c == '\t' || znspace(c)) - break; - if (c == '#') - c = Pound; - else if (c == ')') - { - if (!pct) - break; - pct--; - c = Outpar; - } - else if (c == ',') - c = Comma; - else if (c == '|') - { - if (!pct) - break; - c = Bar; - } - else if (c == '$') - { - d = hgetc(); - - c = String; - if (d == '[') - { - add(String); - add(Inbrack); - while ((c = hgetc()) != ']' && !istok(c) && c != EOF) - add(c); - c = Outbrack; - } - else if (d == '(') - { - add(String); - skipcomm(); - c = Outpar; - } - else - hungetc(d); - } - else if (c == '^') - c = Hat; - else if (c == '[') - c = Inbrack; - else if (c == ']') - c = Outbrack; - else if (c == '*') - c = Star; - else if (intpos && c == '~') - c = Tilde; - else if (c == '?') - c = Quest; - else if (c == '(') - { - int d = hgetc(); - - hungetc(d); - if (!incmd) - break; -#if 0 - if (d != ')' && intpos) - { - add(Inang); - skipcomm(); - c = Outpar; - } - else -#endif - { - pct++; - c = Inpar; - } - } - else if (c == '{') - { - c = Inbrace; - bct++; - } - else if (c == '}') - { - if (!bct) - break; - c = Outbrace; - bct--; - } - else if (c == '>') - { - d = hgetc(); - if (d != '(') - { - hungetc(d); - break; - } - add(Outang); - skipcomm(); - c = Outpar; - } - else if (c == '<') - { - d = hgetc(); - if (!(isdigit(d) || d == '-' || d == '>' || d == '(' || d == ')')) - { - hungetc(d); - break; - } - c = Inang; - if (d == '(') - { - add(c); - skipcomm(); - c = Outpar; - } - else if (d == ')') - hungetc(d); - else - { - add(c); - c = d; - while (c != '>' && !istok(c) && c != EOF) - add(c),c = hgetc(); - if (c == EOF) - { - errflag = 1; - peek = EOF; - return; - } - c = Outang; - } - } - else if (c == '=') - { - if (intpos) - { - d = hgetc(); - if (d != '(') - { - hungetc(d); - c = Equals; - } - else - { - add(Equals); - skipcomm(); - c = Outpar; - } - } - else if (peek != ENVSTRING) - { - peek = ENVSTRING; - intpos = 2; - } - } - else if (c == '\\') - { - c = hgetc(); - - if (c == '\n') - { - c = hgetc(); - continue; - } - add(c); - c = hgetc(); - continue; - } - else if (c == '\'') - { - add(Nularg); - - /* we add the Nularg to prevent this: - - echo $PA'TH' - - from printing the path. */ - - while ((c = hgetc()) != '\'' && !istok(c) && c != EOF) - add(c); - if (c == EOF) - { - errflag = 1; - peek = EOF; - return; - } - c = Nularg; - } - else if (c == HQUOT) - { - add(Nularg); - while ((c = hgetc()) != HQUOT && !istok(c) && c != EOF) - add(c); - if (c == EOF) - { - errflag = 1; - peek = EOF; - return; - } - c = Nularg; - } - else if (c == '\"') - { - add(Nularg); - while ((c = hgetc()) != '\"' && !istok(c) && c != EOF) - if (c == '\\') - { - c = hgetc(); - if (c != '\n') - { - if (c != '$' && c != '\\' && c != '\"' && c != '`') - add('\\'); - add(c); - } - } - else - { - if (c == '$') - { - int d = hgetc(); - - if (d == '(') - { - add(Qstring); - skipcomm(); - c = Outpar; - } - else if (d == '[') - { - add(String); - add(Inbrack); - while ((c = hgetc()) != ']' && c != EOF) - add(c); - c = Outbrack; - } - else - { - c = Qstring; - hungetc(d); - } - } - else if (c == '`') - c = Qtick; - add(c); - } - if (c == EOF) - { - errflag = 1; - peek = EOF; - return; - } - c = Nularg; - } - else if (c == '`') - { - add(Tick); - while ((c = hgetc()) != '`' && !istok(c) && c != EOF) - if (c == '\\') - { - c = hgetc(); - if (c != '\n') - { - if (c != '`' && c != '\\' && c != '$') - add('\\'); - add(c); - } - } - else - { - if (c == '$') - c = String; - add(c); - } - if (c == EOF) - { - errflag = 1; - peek = EOF; - return; - } - c = Tick; - } - add(c); - c = hgetc(); - if (intpos) - intpos--; - } - if (c == HERR) - { - free(tstr); - peek = HERR; - return; - } - hungetc(c); - *bptr = '\0'; -} - -/* expand aliases, perhaps */ - -int exalias(void) -{ -struct anode *an; -char *s; - - s = hwadd(); - if (alix != MAXAL && (an = gethnode(s,alhtab)) && !an->inuse && - !(an->cmd && incmd && alstat != ALSTAT_MORE)) - { - if (an->cmd < 0) - { - peek = DO-an->cmd-1; - return 0; - } - an->inuse = 1; - hungets(strdup(ALPOPS)); - hungets(strdup((alstack[alix++] = an)->text)); - alstat = 0; - if (tstr) - free(tstr); - return 1; - } - return 0; -} - -/* != 0 if c is not a newline, but in IFS */ - -int zspace(int c) -{ - if (c == '\n') - return 0; - return znspace(c); -} - -/* != 0 if c is in IFS */ - -int znspace(int c) -{ -char *ptr = ifs; - - while (*ptr) - if (*ptr++ == c) - return 1; - return 0; -} - -/* skip (...) */ - -void skipcomm(void) -{ -int pct = 1,c; - - c = Inpar; - do - { - add(c); -reget: - c = hgetc(); - if (istok(c) || c == EOF) - break; - else if (c == '(') pct++; - else if (c == ')') pct--; - else if (c == '\\') - { - add(c); - c = hgetc(); - } - else if (c == '\'') - { - add(c); - while ((c = hgetc()) != '\'' && !istok(c) && c != EOF) - add(c); - } - else if (c == HQUOT) - { - while ((c = hgetc()) != HQUOT && !istok(c) && c != EOF) - add(c); - goto reget; - } - else if (c == '\"') - { - add(c); - while ((c = hgetc()) != '\"' && !istok(c) && c != EOF) - if (c == '\\') - { - add(c); - add(hgetc()); - } - else add(c); - } - else if (c == '`') - { - add(c); - while ((c = hgetc()) != '`' && c != HERR && c != EOF) - if (c == '\\') add(c), add(hgetc()); - else add(c); - } - } - while(pct); -} - End of lex.c echo lex.pro 1>&2 sed 's/^-//' >lex.pro <<'End of lex.pro' -void matchit(void); -void add(int c); -void gettok(void); -int exalias(void); -int zspace(int c); -int znspace(int c); -void skipcomm(void); End of lex.pro echo loop.c 1>&2 sed 's/^-//' >loop.c <<'End of loop.c' -/* - - loop.c - parsing and executing loop constructs - - This file is part of zsh, the Z shell. - - zsh is free software; no one can prevent you from reading the source - code, or giving it to someone else. - This file is copyrighted under the GNU General Public License, which - can be found in the file called COPYING. - - Copyright (C) 1990 Paul Falstad - - zsh is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY. No author or distributor accepts - responsibility to anyone for the consequences of using it or for - whether it serves any particular purpose or works at all, unless he - says so in writing. Refer to the GNU General Public License - for full details. - - Everyone is granted permission to copy, modify and redistribute - zsh, but only under the conditions described in the GNU General Public - License. A copy of this license is supposed to have been given to you - along with zsh so you can know your rights and responsibilities. - It should be in a file named COPYING. - - Among other things, the copyright notice and this notice must be - preserved on all copies. - -*/ - -#include "zsh.h" -#include "funcs.h" - -/* parse a for/select loop */ - -int parfor(comm comm,int isfor) -{ -struct fornode *node = alloc(sizeof(struct fornode)); -char *comnam = (isfor) ? "for" : "select"; - - comm->type = (isfor) ? CFOR : CSELECT; - comm->info = node; - if (peek != STRING) - { - zerr("parse error in %s: identifier expected",comnam); - errflag = 1; - return 0; - } - node->name = tstr; - matchit(); - node->list = NULL; - node->inflag = 0; - if (peek == STRING && !strcmp("in",tstr)) - { - node->inflag = 1; - free(tstr); - matchit(); - while (peek == STRING) - { - addnode(comm->args,tstr); - matchit(); - } - } - if (peek != NEWLIN && peek != SEMI) - { - zerr("parse error: bad token in '%s' list",comnam); - freecmd(comm); - return 1; - } - incmd = 0; - matchit(); - while (peek == NEWLIN) - matchit(); - if (peek != DO) - { - zerr("parse error: 'do' expected"); - freecmd(comm); - return 1; - } - matchit(); - if (!(node->list = parlist(1))) - { - freecmd(comm); - return 1; - } - if (peek != DONE) - { - zerr("parse error: 'done' expected"); - freecmd(comm); - return 1; - } - matchit(); - return 0; -} - -int parcase(comm comm) -{ -struct casenode *node = alloc(sizeof(struct casenode)),*last = NULL; -char *tok; /* add FREES to this function */ - - comm->type = CCASE; - comm->info = node; - if (peek != STRING) - { - zerr("parse error in case: identifier expected"); - errflag = 1; - return 0; - } - addnode(comm->args,tstr); - matchit(); - if (peek != STRING || strcmp(tstr,"in")) - { - zerr("parse error in case: `in' expected"); - errflag = 1; - return 0; - } - while (tok = getcasepat()) - { - node = alloc(sizeof(struct casenode)); - node->pat = tok; - if (last) - last->next = node; - else - comm->info = node; - (last = node)->list = parlist(1); - if (peek != DSEMI) - { - zerr("parse error: ;; expected"); - return 1; - } - } - if (!last) - { - zerr("null case construct"); - return 1; - } - return 0; -} - -/* get a case pattern: foo) */ - -char *getcasepat(void) -{ -int c,bsiz = 256,ct = 0,pct = 0,qt = 0; -char *buf = zalloc(bsiz),*ptr,*s; - - peek = EMPTY; - while (znspace(c = hgetc())) - { - if (c == '\n') - { - hwbegin(); - hwaddc('\n'); - hwadd(); - } - } - ptr = buf; - hwbegin(); - hwaddc(c); - while (c != ')' || pct) - { - for (s = tokens; *s; s++) - if (*s == c) - { - c = (s-tokens)+Pound; - break; - } - if (qt) - { - if (c == '\'') - { - qt = 0; - c = hgetc(); - continue; - } - if (c == EOF) - { - qt = 0; - continue; - } - } - else - { - if (c == '\\') - c = hgetc(); - if (c == '\'') - { - qt = 1; - c = hgetc(); - continue; - } - if (c == Inpar) - pct++; - if (c == Outpar) - pct--; - if (ct == 4 && (znspace(c)||c ==';'||c=='&') && !strncmp(buf,"esac",4)) - { - hungetc(c); - hwadd(); - free(buf); - matchit(); - return NULL; - } - if (c == '\n' || c == EOF) - { - free(buf); - zerr("parse error: 'esac' expected"); - return NULL; - } - } - if (c == HERR) - { - free(buf); - return NULL; - } - *ptr++ = c; - if (++ct == bsiz) - { - ptr = zalloc(bsiz *= 2); - memcpy(ptr,buf,ct); - free(buf); - buf = ptr; - ptr = buf+ct; - } - c = hgetc(); - } - *ptr = 0; - hwadd(); - return buf; -} - -int parif(comm comm) -{ -struct ifnode *node = alloc(sizeof(struct ifnode)); - - comm->type = CIF; - comm->info = node; -do_then: - node->next = NULL; - if (!(node->ifl = parlist(1))) - { - freecmd(comm); - return 1; - } - if (peek != THEN) - { - zerr("parse error: 'then' expected"); - freecmd(comm); - return 1; - } - matchit(); - if (!(node->thenl = parlist(1))) - { - freecmd(comm); - return 1; - } - if (peek == ELIF) - { - matchit(); - node = node->next = alloc(sizeof(struct ifnode)); - goto do_then; - } - else if (peek == ELSE) - { - matchit(); - node = node->next = alloc(sizeof(struct ifnode)); - node->next = NULL; - node->ifl = NULL; - if (!(node->thenl = parlist(1))) - { - freecmd(comm); - return 1; - } - } - if (peek != FI) - { - zerr("parse error: 'fi' expected"); - freecmd(comm); - return 1; - } - matchit(); - return 0; -} - -/* parse while or until */ - -int parwhile(comm comm,int cond) -{ -struct whilenode *node = alloc(sizeof (struct whilenode)); - - comm->type = CWHILE; - comm->info = node; - node->cond = cond; - node->loop = node->cont = NULL; - if (!(node->cont = parlist(1))) - { - freecmd(comm); - return NULL; - } - if (peek != DO) - { - zerr("parse error: 'do' expected"); - freecmd(comm); - return 1; - } - matchit(); - node->loop = parlist(1); - if (peek != DONE) - { - zerr("parse error: 'done' expected"); - freecmd(comm); - return 1; - } - matchit(); - return 0; -} - -int parrepeat(comm comm) -{ -struct repeatnode *node = alloc(sizeof (struct repeatnode)); - - comm->type = CREPEAT; - comm->info = node; - node->list = NULL; - if (peek != STRING || !isdigit(*tstr)) - { - zerr("parse error: number expected"); - freecmd(comm); - return 1; - } - node->count = atoi(tstr); - free(tstr); - incmd = 0; - do - matchit(); - while (peek == NEWLIN); - if (peek != DO) - { - zerr("parse error: 'do' expected"); - freecmd(comm); - return 1; - } - matchit(); - node->list = parlist(1); - if (peek != DONE) - { - zerr("parse error: 'done' expected"); - freecmd(comm); - return 1; - } - matchit(); - return 0; -} - -void execfor(comm comm) -{ -list list; -struct fornode *node; -char *str; -table args; -int cj = curjob; - - loops++; - exiting = 0; - node = comm->info; - args = comm->args; - if (!node->inflag) - { - args = duptable(pparms,dupstr); - freestr(getnode(args)); - } - while (str = getnode(args)) - { - setparm(strdup(node->name),str,0,0); - list = duplist(node->list); - execlist(list); - if (breaks) - { - breaks--; - if (breaks || !contflag) - break; - contflag = 0; - } - } - curjob = cj; -} - -void execselect(comm comm) -{ -list list; -struct fornode *node; -char *str,*s; -table args; -Node n; -int cj = curjob,t0; - - loops++; - node = comm->info; - args = comm->args; - exiting = 0; - for (;;) - { - do - { - for (t0 = 1,n = args->first; n; n=n->next,t0++) - fprintf(stderr,"%d %s\n",t0,n->dat); - if (interact && SHTTY != -1) - { - inittty(); - str = readline(putprompt("PROMPT3")); - } - else - str = fgets(zalloc(256),256,bshin); - if (!str || errflag) - { - fprintf(stderr,"\n"); - goto done; - } - if (s = strchr(str,'\n')) - *s = '\0'; - } - while (!*str); - setparm(strdup("REPLY"),str,0,0); - t0 = atoi(str); - if (!t0) - str = ""; - else - { - for (t0--,n = args->first; n && t0; n=n->next,t0--); - if (n) - str = n->dat; - else - str = ""; - } - setparm(strdup(node->name),strdup(str),0,0); - list = duplist(node->list); - execlist(list); - if (breaks) - { - breaks--; - if (breaks || !contflag) - break; - contflag = 0; - } - if (errflag) - break; - } -done: - curjob = cj; -} - -void execwhile(comm comm) -{ -list list; -struct whilenode *node; -int cj = curjob; - - loops++; - node = comm->info; - exiting = 0; - FOREVER - { - list = duplist(node->cont); - execlist(list); - if (!((lastval == 0) ^ node->cond)) - break; - if (breaks) - { - breaks--; - if (breaks || !contflag) - break; - contflag = 0; - } - list = duplist(node->loop); - execlist(list); - } - curjob = cj; -} - -void execrepeat(comm comm) -{ -list list; -struct repeatnode *node; -int cj = curjob; - - loops++; - node = comm->info; - exiting = 0; - while (node->count--) - { - list = duplist(node->list); - execlist(list); - if (breaks) - { - breaks--; - if (breaks || !contflag) - break; - contflag = 0; - } - if (lastval) - break; - } - curjob = cj; -} - -void execif(comm comm) -{ -list list; -struct ifnode *node; -int cj = curjob; - - node = comm->info; - exiting = 0; - while (node) - { - if (node->ifl) - { - list = duplist(node->ifl); - execlist(list); - if (lastval) - { - node = node->next; - continue; - } - } - list = duplist(node->thenl); - execlist(list); - break; - } - curjob = cj; -} - -void execcase(comm comm) -{ -list list; -struct casenode *node; -char *word; -table args; -int cj = curjob; - - node = comm->info; - args = comm->args; - exiting = 0; - if (!args->first || args->first->next) - { - zerr("bad case statement"); - errflag = 1; - return; - } - word = args->first->dat; - while (node) - if (matchpat(word,node->pat)) - break; - else - node = node->next; - if (node) - { - list = duplist(node->list); - execlist(list); - } - curjob = cj; -} - -list duplist(list xlist) -{ -list nlist; - - if (!xlist) - return NULL; - nlist = alloc(sizeof(struct lnode)); - nlist->left = duplist2(xlist->left); - nlist->right = duplist(xlist->right); - nlist->type = xlist->type; - return nlist; -} - -void freelist(list xlist) -{ - if (xlist) - { - freelist2(xlist->left); - freelist(xlist->right); - free(xlist); - } -} - -list2 duplist2(list2 x) -{ -list2 y; - - if (!x) - return NULL; - y = alloc(sizeof(struct l2node)); - *y = *x; - y->left = duppline(x->left); - y->right = duplist2(x->right); - return y; -} - -void freelist2(list2 x) -{ - if (x) - { - freepline(x->left); - freelist2(x->right); - free(x); - } -} - -pline duppline(pline xpline) -{ -pline npline; - - if (!xpline) - return NULL; - npline = alloc(sizeof(struct pnode)); - npline->left = dupcomm(xpline->left); - npline->right = duppline(xpline->right); - npline->type = xpline->type; - return npline; -} - -void freepline(pline x) -{ - if (x) - { - freecmd(x->left); - freepline(x->right); - free(x); - } -} - -comm dupcomm(comm xcomm) -{ -comm ncomm; -void *(*duprs[])(void *) = {dupfor,dupwhile,duprepeat,dupif,dupcase}; -int type; - - if (!xcomm) - return NULL; - ncomm = alloc(sizeof(struct cnode)); - ncomm->left = duplist(xcomm->left); - ncomm->cmd = dupstr(xcomm->cmd); - ncomm->args = duptable(xcomm->args,dupstr); - ncomm->redir = duptable(xcomm->redir,dupfnode); - ncomm->vars = (xcomm->vars) ? duptable(xcomm->vars,dupstr) : NULL; - ncomm->type = type = xcomm->type; - if (type >= CFOR && type <= CCASE) - ncomm->info = (duprs[type-CFOR])(xcomm->info); - return ncomm; -} - -void freecmd(comm x) -{ - if (x) - { - freelist(x->left); - if (x->cmd) - free(x->cmd); - if (x->args) - freetable(x->args,freestr); - if (x->redir) - freetable(x->redir,freeredir); - if (x->vars) - freetable(x->vars,freestr); -/* if (x->info) - freeinfo(x->info);*/ - free(x); - } -} - -void *dupstr(void *str) -{ - if (!str) - return NULL; - return strdup(str); -} - -void *dupfnode(void *i) -{ -struct fnode *fn = i,*nfn = alloc(sizeof(struct fnode)); - - if (!i) - return NULL; - *nfn = *fn; - if (nfn->type < HEREDOC) - nfn->u.name = strdup(fn->u.name); - return nfn; -} - -void *dupfor(void *i) -{ -struct fornode *nnode,*node = i; - - nnode = alloc(sizeof(struct fornode)); - *nnode = *(struct fornode *) i; - nnode->name = strdup(node->name); - nnode->list = duplist(node->list); - return nnode; -} - -void *dupcase(void *i) -{ -struct casenode *nnode,*node = i; - - if (!i) - return NULL; - nnode = alloc(sizeof(struct casenode)); - nnode->next = dupcase(node->next); - nnode->list = duplist(node->list); - nnode->pat = strdup(node->pat); - return nnode; -} - -void *dupif(void *i) -{ -struct ifnode *nnode,*node = i; - - if (!i) - return NULL; - nnode = alloc(sizeof(struct ifnode)); - nnode->next = dupif(node->next); - nnode->ifl = duplist(node->ifl); - nnode->thenl = duplist(node->thenl); - return nnode; -} - -void *dupwhile(void *i) -{ -struct whilenode *nnode,*node = i; - - if (!i) - return NULL; - nnode = alloc(sizeof(struct whilenode)); - nnode->cond = node->cond; - nnode->cont = duplist(node->cont); - nnode->loop = duplist(node->loop); - return nnode; -} - -void *duprepeat(void *i) -{ -struct repeatnode *nnode,*node = i; - - if (!i) - return NULL; - nnode = alloc(sizeof(struct repeatnode)); - nnode->count = node->count; - nnode->list = duplist(node->list); - return nnode; -} - -table duptable(table tab,void *(*func)(void *)) -{ -table ret; -Node node; - - ret = newtable(); - for (node = tab->first; node; node = node->next) - addnode(ret,func(node->dat)); - return ret; -} End of loop.c echo loop.pro 1>&2 sed 's/^-//' >loop.pro <<'End of loop.pro' -int parfor(comm comm,int isfor); -int parcase(comm comm); -char *getcasepat(void); -int parif(comm comm); -int parwhile(comm comm,int cond); -int parrepeat(comm comm); -void execfor(comm comm); -void execselect(comm comm); -void execwhile(comm comm); -void execrepeat(comm comm); -void execif(comm comm); -void execcase(comm comm); -list duplist(list xlist); -void freelist(list xlist); -list2 duplist2(list2 x); -void freelist2(list2 x); -pline duppline(pline xpline); -void freepline(pline x); -comm dupcomm(comm xcomm); -void freecmd(comm x); -void *dupstr(void *str); -void *dupfnode(void *i); -void *dupfor(void *i); -void *dupcase(void *i); -void *dupif(void *i); -void *dupwhile(void *i); -void *duprepeat(void *i); -table duptable(table tab,void *(*func)(void *)); End of loop.pro echo math.c 1>&2 sed 's/^-//' >math.c <<'End of math.c' -/* - - math.c - evaluating arithmetic expressions - - This file is part of zsh, the Z shell. - - zsh is free software; no one can prevent you from reading the source - code, or giving it to someone else. - This file is copyrighted under the GNU General Public License, which - can be found in the file called COPYING. - - Copyright (C) 1990 Paul Falstad - - zsh is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY. No author or distributor accepts - responsibility to anyone for the consequences of using it or for - whether it serves any particular purpose or works at all, unless he - says so in writing. Refer to the GNU General Public License - for full details. - - Everyone is granted permission to copy, modify and redistribute - zsh, but only under the conditions described in the GNU General Public - License. A copy of this license is supposed to have been given to you - along with zsh so you can know your rights and responsibilities. - It should be in a file named COPYING. - - Among other things, the copyright notice and this notice must be - preserved on all copies. - -*/ - -#include -#include -#include -#include -#include - -extern int errflag; -extern char *setiparm(char *,long,int); -extern long getiparm(char *); -extern void zerr(char *,...); -extern char *strdup(char *); - -char *ptr; - -typedef int LV; - -long yyval; -LV yylval; - -/* nonzero means we are not evaluating, just parsing */ - -int noeval = 0; - -/* != 0 means recognize unary plus, minus, etc. - The parser was originally written in lex, hence the name. */ - -int initial = 1; - -void mathparse(int); - -/* LR = left-to-right associativity - RL = right-to-left associativity - BOO = short-circuiting boolean */ - -enum xtyp { LR,RL,BOO }; - -enum xtok { -INPAR, OUTPAR, NOT, COMP, POSTPLUS, -POSTMINUS, UPLUS, UMINUS, AND, XOR, -OR, MUL, DIV, MOD, PLUS, -MINUS, SHLEFT, SHRIGHT, LES, LEQ, -GRE, GEQ, DEQ, NEQ, DAND, -DOR, DXOR, QUEST, COLON, EQ, -PLUSEQ, MINUSEQ, MULEQ, DIVEQ, MODEQ, -ANDEQ, XOREQ, OREQ, SHLEFTEQ, SHRIGHTEQ, -DANDEQ, DOREQ, DXOREQ, COMMA, EOI, -PREPLUS, PREMINUS, NUM, ID, TOKCOUNT -}; - -/* precedences */ - -int prec[TOKCOUNT] = { -1,200,2,2,2, -2,2,2,3,4, -5,6,6,6,7, -7,8,8,9,9, -9,9,10,10,11, -12,12,13,13,14, -14,14,14,14,14, -14,14,14,14,14, -14,14,14,15,200, -2,2,0,0, -}; - -#define TOPPREC 15 - -int type[TOKCOUNT] = { -LR,LR,RL,RL,RL, -RL,RL,RL,LR,LR, -LR,LR,LR,LR,LR, -LR,LR,LR,LR,LR, -LR,LR,LR,LR,BOO, -BOO,LR,RL,RL,RL, -RL,RL,RL,RL,RL, -RL,RL,RL,RL,RL, -BOO,BOO,RL,RL,RL, -RL,RL,LR,LR, -}; - -#define LVCOUNT 32 - -/* table of lvalues (variables) */ - -int lvc; -char *lvals[LVCOUNT]; - -int yylex(void) -{ - for(;;) - switch (*ptr++) - { - case '+': - if (*ptr == '+' && (initial || !isalnum(*ptr))) - { - ptr++; - return (initial) ? PREPLUS : POSTPLUS; - } - if (*ptr == '=') { initial = 1; ptr++; return PLUSEQ; } - return (initial) ? UPLUS : PLUS; - case '-': - if (*ptr == '-' && (initial || !isalnum(*ptr))) - { - ptr++; - return (initial) ? PREMINUS : POSTMINUS; - } - if (*ptr == '=') { initial = 1; ptr++; return MINUSEQ; } - return (initial) ? UMINUS : MINUS; - case '(': initial = 1; return INPAR; - case ')': return OUTPAR; - case '!': if (*ptr == '=') - { initial = 1; ptr++; return NEQ; } - return NOT; - case '~': return COMP; - case '&': initial = 1; - if (*ptr == '&') { if (*++ptr == '=') - { ptr++; return DANDEQ; } return DAND; } - else if (*ptr == '=') { ptr++; return ANDEQ; } return AND; - case '|': initial = 1; - if (*ptr == '|') { if (*++ptr == '=') - { ptr++; return DOREQ; } return DOR; } - else if (*ptr == '=') { ptr++; return OREQ; } return OR; - case '^': initial = 1; - if (*ptr == '^') { if (*++ptr == '=') - { ptr++; return DXOREQ; } return DXOR; } - else if (*ptr == '=') { ptr++; return XOREQ; } return XOR; - case '*': initial = 1; - if (*ptr == '=') { ptr++; return MULEQ; } return MUL; - case '/': initial = 1; - if (*ptr == '=') { ptr++; return DIVEQ; } return DIV; - case '%': initial = 1; - if (*ptr == '=') { ptr++; return MODEQ; } return MOD; - case '<': initial = 1; if (*ptr == '<') - { if (*++ptr == '=') { ptr++; return SHLEFTEQ; } return SHLEFT; } - else if (*ptr == '=') { ptr++; return LEQ; } return LES; - case '>': initial = 1; if (*ptr == '>') - { if (*++ptr == '=') { ptr++; return SHRIGHTEQ; } return SHRIGHT; } - else if (*ptr == '=') { ptr++; return GEQ; } return GRE; - case '=': initial = 1; if (*ptr == '=') { ptr++; return DEQ; } - return EQ; - case '?': initial = 1; return QUEST; - case ':': initial = 1; return COLON; - case ',': initial = 1; return COMMA; - case '\0': initial = 1; ptr--; return EOI; - case '[': initial = 0; - { int base = strtol(ptr,&ptr,10); - yyval = strtol(ptr+1,&ptr,base); return NUM; } - case ' ': case '\t': - break; - default: - if (isdigit(*--ptr)) - { initial = 0; yyval = strtol(ptr,&ptr,10); return NUM; } - if (isalpha(*ptr) || *ptr == '$') - { - char *p,q; - - if (*ptr == '$') - ptr++; - p = ptr; - if (lvc == LVCOUNT) - { - zerr("too many identifiers in expression"); - errflag = 1; - return EOI; - } - initial = 0; - while(isalpha(*++ptr)); - q = *ptr; - *ptr = '\0'; - lvals[yylval = lvc++] = strdup(p); - *ptr = q; - return ID; - } - zerr("illegal character: %c",*ptr); - errflag = 1; - return EOI; - } -} - -/* the value stack */ - -#define STACKSZ 1000 -int tok; /* last token */ -int sp = -1; /* stack pointer */ -struct value { - LV lval; - long val; - } stack[STACKSZ]; - -void push(long val,LV lval) -{ - sp++; - stack[sp].val = val; - stack[sp].lval = lval; -} - -long getvar(LV s) -{ -long t; - - if (!(t = getiparm(lvals[s]))) - return 0; - return t; -} - -long setvar(LV s,long v) -{ - if (s == -1) - { - zerr("lvalue required"); - errflag = 1; - return 0; - } - if (noeval) - return v; - setiparm(strdup(lvals[s]),v,0); - return v; -} - -int notzero(int a) -{ - if (a == 0) - { - errflag = 1; - zerr("division by zero"); - return 0; - } - return 1; -} - -#define pop2() { b = stack[sp--].val; a = stack[sp--].val; } -#define pop3() {c=stack[sp--].val;b=stack[sp--].val;a=stack[sp--].val;} -#define nolval() {stack[sp].lval=-1;} -#define pushv(X) { push(X,-1); } -#define pop2lv() { pop2() lv = stack[sp+1].lval; } -#define set(X) { push(setvar(lv,X),lv); } - -void op(int what) -{ -long a,b,c; -LV lv; - - switch(what) { - case NOT: stack[sp].val = !stack[sp].val; nolval(); break; - case COMP: stack[sp].val = ~stack[sp].val; nolval(); break; - case POSTPLUS: (void) setvar(stack[sp].lval,stack[sp].val+1); break; - case POSTMINUS: (void) setvar(stack[sp].lval,stack[sp].val-1); break; - case UPLUS: nolval(); break; - case UMINUS: stack[sp].val = -stack[sp].val; nolval(); break; - case AND: pop2(); pushv(a&b); break; - case XOR: pop2(); pushv(a^b); break; - case OR: pop2(); pushv(a|b); break; - case MUL: pop2(); pushv(a*b); break; - case DIV: pop2(); if (notzero(b)) pushv(a/b); break; - case MOD: pop2(); if (notzero(b)) pushv(a%b); break; - case PLUS: pop2(); pushv(a+b); break; - case MINUS: pop2(); pushv(a-b); break; - case SHLEFT: pop2(); pushv(a<>b); break; - case LES: pop2(); pushv(ab); break; - case GEQ: pop2(); pushv(a>=b); break; - case DEQ: pop2(); pushv(a==b); break; - case NEQ: pop2(); pushv(a!=b); break; - case DAND: pop2(); pushv(a&&b); break; - case DOR: pop2(); pushv(a||b); break; - case DXOR: pop2(); pushv(a&&!b||!a&&b); break; - case QUEST: pop3(); pushv((a)?b:c); break; - case COLON: break; - case EQ: pop2lv(); set(b); break; - case PLUSEQ: pop2lv(); set(a+b); break; - case MINUSEQ: pop2lv(); set(a-b); break; - case MULEQ: pop2lv(); set(a*b); break; - case DIVEQ: pop2lv(); if (notzero(b)) set(a/b); break; - case MODEQ: pop2lv(); if (notzero(b)) set(a%b); break; - case ANDEQ: pop2lv(); set(a&b); break; - case XOREQ: pop2lv(); set(a^b); break; - case OREQ: pop2lv(); set(a|b); break; - case SHLEFTEQ: pop2lv(); set(a<>b); break; - case DANDEQ: pop2lv(); set(a&&b); break; - case DOREQ: pop2lv(); set(a||b); break; - case DXOREQ: pop2lv(); set(a&&!b||!a&&b); break; - case COMMA: pop2(); pushv(b); break; - case PREPLUS: stack[sp].val = setvar(stack[sp].lval, - stack[sp].val+1); break; - case PREMINUS: stack[sp].val = setvar(stack[sp].lval, - stack[sp].val-1); break; - default: fprintf(stderr,"whoops.\n"); exit(1); - } -} - -void bop(int tok) -{ - switch (tok) { - case DAND: case DANDEQ: if (!stack[sp].val) noeval++; break; - case DOR: case DOREQ: if (stack[sp].val) noeval++; break; - }; -} - -long matheval(char *s) -{ -int t0; - - for (t0 = 0; t0 != LVCOUNT; t0++) - lvals[t0] = NULL; - lvc = 0; - ptr = s; - sp = -1; - mathparse(TOPPREC); - if (!errflag && sp) - zerr("arithmetic error: unbalanced stack"); - for (t0 = 0; t0 != lvc; t0++) - free(lvals[t0]); - return stack[0].val; -} - -/* operator-precedence parse the string and execute */ - -void mathparse(int pc) -{ - if (errflag) - return; - tok = yylex(); - while (prec[tok] <= pc) - { - if (errflag) - return; - if (tok == NUM) - push(yyval,-1); - else if (tok == ID) - push(getvar(yylval),yylval); - else if (tok == INPAR) - { - mathparse(TOPPREC); - if (tok != OUTPAR) - exit(1); - } - else if (tok == QUEST) - { - int q = stack[sp].val; - if (!q) noeval++; - mathparse(prec[QUEST]-1); - if (!q) noeval--; else noeval++; - mathparse(prec[QUEST]); - if (q) noeval--; - op(QUEST); - continue; - } - else - { - int otok = tok,onoeval = noeval; - - if (type[otok] == BOO) - bop(otok); - mathparse(prec[otok]-(type[otok] != RL)); - noeval = onoeval; - op(otok); - continue; - } - tok = yylex(); - } -} - End of math.c echo math.pro 1>&2 sed 's/^-//' >math.pro <<'End of math.pro' -INPAR, OUTPAR, NOT, COMP, POSTPLUS,; -POSTMINUS, UPLUS, UMINUS, AND, XOR,; -OR, MUL, DIV, MOD, PLUS,; -MINUS, SHLEFT, SHRIGHT, LES, LEQ,; -GRE, GEQ, DEQ, NEQ, DAND,; -DOR, DXOR, QUEST, COLON, EQ,; -PLUSEQ, MINUSEQ, MULEQ, DIVEQ, MODEQ,; -ANDEQ, XOREQ, OREQ, SHLEFTEQ, SHRIGHTEQ,; -DANDEQ, DOREQ, DXOREQ, COMMA, EOI,; -PREPLUS, PREMINUS, NUM, ID, TOKCOUNT; -LR,LR,RL,RL,RL,; -RL,RL,RL,LR,LR,; -LR,LR,LR,LR,LR,; -LR,LR,LR,LR,LR,; -LR,LR,LR,LR,BOO,; -BOO,LR,RL,RL,RL,; -RL,RL,RL,RL,RL,; -RL,RL,RL,RL,RL,; -BOO,BOO,RL,RL,RL,; -RL,RL,LR,LR,; -int yylex(void); -void push(long val,LV lval); -long getvar(LV s); -long setvar(LV s,long v); -int notzero(int a); -void op(int what); -void bop(int tok); -long matheval(char *s); -void mathparse(int pc); End of math.pro echo parse.c 1>&2 sed 's/^-//' >parse.c <<'End of parse.c' -/* - - parse.c - parsing - - This file is part of zsh, the Z shell. - - zsh is free software; no one can prevent you from reading the source - code, or giving it to someone else. - This file is copyrighted under the GNU General Public License, which - can be found in the file called COPYING. - - Copyright (C) 1990 Paul Falstad - - zsh is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY. No author or distributor accepts - responsibility to anyone for the consequences of using it or for - whether it serves any particular purpose or works at all, unless he - says so in writing. Refer to the GNU General Public License - for full details. - - Everyone is granted permission to copy, modify and redistribute - zsh, but only under the conditions described in the GNU General Public - License. A copy of this license is supposed to have been given to you - along with zsh so you can know your rights and responsibilities. - It should be in a file named COPYING. - - Among other things, the copyright notice and this notice must be - preserved on all copies. - -*/ - -#include "zsh.h" -#include "funcs.h" - -/* parse a list, but return : instead of NULL */ - -list parlist(int nest) -{ -list l1; -list2 l2; -pline p; -comm c; - - if (l1 = parlist1(nest)) - return l1; - if (errflag) - return NULL; - c = alloc(sizeof *c); - c->cmd = strdup(""); - c->args = newtable(); - c->redir = newtable(); - c->type = SIMPLE; - p = alloc(sizeof *p); - p->left = c; - p->type = END; - l2 = alloc(sizeof *l2); - l2->left = p; - l2->type = END; - l1 = alloc(sizeof *l1); - l1->left = l2; - l1->type = SYNC; - return l1; -} - -/* parse a list */ - -list parlist1(int nest) -{ -list l1 = (list) alloc(sizeof *l1); -int isnl; - - incmd = 0; - if (peek == EMPTY) - matchit(); - if (nest) - while (peek == NEWLIN || peek == SEMI) - matchit(); - if (!(l1->left = parlist2())) - { - free(l1); - return NULL; - } - l1->type = (peek == AMPER) ? ASYNC : SYNC; - if ((isnl = peek == NEWLIN) || peek == SEMI || peek == AMPER) - peek = EMPTY; - if ((nest || !isnl) && peek == EMPTY) - { - if (!(l1->right = parlist1(nest))) - { - if (!errflag) - { - if (peek == NEWLIN) - peek = EMPTY; - return l1; - } - freelist2(l1->left); - free(l1); - return NULL; - } - } - else - l1->right = NULL; - return l1; -} - -/* parse a sublist */ - -list2 parlist2(void) ---cut here---cut here---cut here---