zsh - ksh/tcsh-like shell (part 4 of 8)
Paul John Falstad
pfalstad at phoenix.Princeton.EDU
Sat Dec 15 10:31:22 AEST 1990
---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 <pwd.h>
-
-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 <sys/errno.h>
-
-#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 <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#include <math.h>
-#include <assert.h>
-
-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 SHRIGHT: pop2(); pushv(a>>b); break;
- case LES: pop2(); pushv(a<b); break;
- case LEQ: pop2(); pushv(a<=b); break;
- case GRE: pop2(); pushv(a>b); 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 SHRIGHTEQ: 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---
More information about the Alt.sources
mailing list