Newsgroups: comp.sources.misc From: pfalstad@phoenix.Princeton.EDU (Paul Falstad) Subject: v24i008: zsh2.1 - The Z shell, Part08/19 Message-ID: <1991Oct24.190925.25848@sparky.imd.sterling.com> X-Md4-Signature: 45b7c4db263877d30de733d36d186705 Date: Thu, 24 Oct 1991 19:09:25 GMT Approved: kent@sparky.imd.sterling.com Submitted-by: pfalstad@phoenix.Princeton.EDU (Paul Falstad) Posting-number: Volume 24, Issue 8 Archive-name: zsh2.1/part08 Environment: BSD Supersedes: zsh2.00: Volume 18, Issue 84-98 #!/bin/sh # this is zshar.08 (part 8 of zsh2.1.0) # do not concatenate these parts, unpack them in order with /bin/sh # file zsh2.1/src/jobs.c continued # if test ! -r _shar_seq_.tmp; then echo 'Please unpack part 1 first!' exit 1 fi (read Scheck if test "$Scheck" != 8; then echo Please unpack part "$Scheck" next! exit 1 else exit 0 fi ) < _shar_seq_.tmp || exit 1 if test ! -f _shar_wnt_.tmp; then echo 'x - still skipping zsh2.1/src/jobs.c' else echo 'x - continuing file zsh2.1/src/jobs.c' sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.1/src/jobs.c' && X X zsh is distributed in the hope that it will be useful, but X WITHOUT ANY WARRANTY. No author or distributor accepts X responsibility to anyone for the consequences of using it or for X whether it serves any particular purpose or works at all, unless he X says so in writing. Refer to the GNU General Public License X for full details. X X Everyone is granted permission to copy, modify and redistribute X zsh, but only under the conditions described in the GNU General Public X License. A copy of this license is supposed to have been given to you X along with zsh so you can know your rights and responsibilities. X It should be in a file named COPYING. X X Among other things, the copyright notice and this notice must be X preserved on all copies. X X*/ X X#include "zsh.h" X#include X X/* != 0 means the handler is active */ X Xstatic int handling = 0; X X/* != 0 means the shell is waiting for a job to complete */ X Xstatic int waiting = 0; X X#ifdef INTHANDTYPE X#define RETURN return 0 X#else X#define RETURN return X#endif X X/* the signal handler */ X XHANDTYPE handler(sig,code) /**/ Xint sig;int code; X{ Xlong pid; Xint statusp; XJob jn; Xstruct process *pn; Xstruct rusage ru; X X#ifdef RESETHANDNEEDED X signal(sig,handler); X#endif X if (sig == SIGINT) X { X if (sigtrapped[SIGINT]) X dotrap(SIGINT); X else X errflag = 1; X RETURN; X } X#ifdef SIGWINCH X if (sig == SIGWINCH) X adjustwinsize(); X#endif X if (sig != SIGCHLD) X { X dotrap(sig); X if (sig == SIGALRM && !sigtrapped[SIGALRM]) X { X zerr("timeout",NULL,0); X exit(1); X } X RETURN; X } X for (;;) X { X#ifdef SYSV X pid = wait(&statusp); X#else X#if defined(RLIM_INFINITY) & ! defined(__hpux) X pid = wait3(&statusp,WNOHANG|WUNTRACED,&ru); X#else X pid = wait3(&statusp,WNOHANG|WUNTRACED,NULL); X#endif X#endif X if (pid == -1) X { X if (errno != ECHILD) X zerr("wait failed: %e",NULL,errno); X RETURN; X } X if (!pid) X RETURN; X findproc(pid,&jn,&pn); /* find the process of this pid */ X if (jn) X { X pn->statusp = statusp; X handling = 1; X pn->ru = ru; X pn->endtime = time(NULL); X updatestatus(jn); X handling = 0; X if (zleactive) X refresh(); X } X else if (WIFSTOPPED(SP(statusp))) X kill(pid,SIGKILL); /* kill stopped untraced children */ X } X RETURN; X} X X/* change job table entry from stopped to running */ X Xvoid makerunning(jn) /**/ XJob jn; X{ Xstruct process *pn; X X jn->stat &= ~STAT_STOPPED; X for (pn = jn->procs; pn; pn = pn->next) X if (WIFSTOPPED(SP(pn->statusp))) X pn->statusp = SP_RUNNING; X} X X/* update status of job, possibly printing it */ X Xvoid updatestatus(jn) /**/ XJob jn; X{ Xstruct process *pn; Xint notrunning = 1,alldone = 1,val,job = jn-jobtab,somestopped = 0; X X for (pn = jn->procs; pn; pn = pn->next) X { X if (pn->statusp == SP_RUNNING) X notrunning = 0; X if (pn->statusp == SP_RUNNING || WIFSTOPPED(SP(pn->statusp))) X alldone = 0; X if (WIFSTOPPED(SP(pn->statusp))) X somestopped = 1; X if (!pn->next && jn) X val = (WIFSIGNALED(SP(pn->statusp))) ? X 0200 | WTERMSIG(SP(pn->statusp)) : WEXITSTATUS(SP(pn->statusp)); X } X if (!notrunning) X return; X if (somestopped && (jn->stat & STAT_STOPPED)) X return; X jn->stat |= (alldone) ? STAT_CHANGED|STAT_DONE : X STAT_CHANGED|STAT_STOPPED; X if (alldone && job == thisjob) X { X if (!val) { X gettyinfo(&shttyinfo); X if (interact && isset(SHINSTDIN) && SHTTY != -1 && isset(USEZLE)) X sanetty(&shttyinfo); X#ifdef TIOCSWINSZ X if (!(columns = shttyinfo.winsize.ws_col)) X columns = 80; X lines = shttyinfo.winsize.ws_row; X#endif X } else X settyinfo(&shttyinfo); X lastval = val; X } X if ((jn->stat & (STAT_DONE|STAT_STOPPED)) == STAT_STOPPED) { X prevjob = curjob; X curjob = job; X } X if ((isset(NOTIFY) || job == thisjob) && jn->stat & STAT_LOCKED) X printjob(jn,!!isset(LONGLISTJOBS)); X if (sigtrapped[SIGCHLD] && job != thisjob) X dotrap(SIGCHLD); X} X X/* find process and job associated with pid */ X Xvoid findproc(pid,jptr,pptr) /**/ Xint pid;Job *jptr;struct process **pptr; X{ Xstruct process *pn; Xint jn; X X for (jn = 1; jn != MAXJOB; jn++) X for (pn = jobtab[jn].procs; pn; pn = pn->next) X if (pn->pid == pid) X { X *pptr = pn; X *jptr = jobtab+jn; X return; X } X *pptr = NULL; X *jptr = NULL; X} X X/* X lng = 0 means jobs X lng = 1 means jobs -l X lng = 2 means jobs -p X*/ X Xvoid printjob(jn,lng) /**/ XJob jn;int lng; X{ Xint job = jn-jobtab,len = 9,sig = -1,sflag = 0,llen,printed = 0; Xint conted = 0,lineleng = getlineleng(),skip = 0,doputnl = 0; Xstruct process *pn; X X if (lng < 0) X { X conted = 1; X lng = 0; X } X X /* find length of longest signame, check to see if we X really need to print this job */ X X for (pn = jn->procs; pn; pn = pn->next) X { X if (pn->statusp != SP_RUNNING) X if (WIFSIGNALED(SP(pn->statusp))) X { X sig = WTERMSIG(SP(pn->statusp)); X llen = strlen(sigmsg[sig]); X if (WCOREDUMPED(pn->statusp)) X llen += 14; X if (llen > len) X len = llen; X if (sig != SIGINT && sig != SIGPIPE) X sflag = 1; X else if (sig == SIGINT) X errflag = 1; X if (job == thisjob && sig == SIGINT) X doputnl = 1; X } X else if (WIFSTOPPED(SP(pn->statusp))) X { X sig = WSTOPSIG(SP(pn->statusp)); X if (strlen(sigmsg[sig]) > len) X len = strlen(sigmsg[sig]); X if (job == thisjob && sig == SIGTSTP) X doputnl = 1; X } X else if (isset(PRINTEXITVALUE) && WEXITSTATUS(SP(pn->statusp))) X sflag = 1; X } X X /* print if necessary */ X X if (interact && jobbing && ((jn->stat & STAT_STOPPED) || sflag || X job != thisjob)) X { X int len2,fline = 1; X struct process *qn; X X trashzle(); X if (doputnl) X putc('\n',stderr); X for (pn = jn->procs; pn;) X { X len2 = ((job == thisjob) ? 5 : 10)+len; /* 2 spaces */ X if (lng) X qn = pn->next; X else for (qn = pn->next; qn; qn = qn->next) X { X if (qn->statusp != pn->statusp) X break; X if (strlen(qn->text)+len2+((qn->next) ? 3 : 0) > lineleng) X break; X len2 += strlen(qn->text)+2; X } X if (job != thisjob) X if (fline) X fprintf(stderr,"[%d] %c ",jn-jobtab,(job == curjob) ? '+' : X (job == prevjob) ? '-' : ' '); X else X fprintf(stderr,(job > 9) ? " " : " "); X else X fprintf(stderr,"zsh: "); X if (lng) X if (lng == 1) X fprintf(stderr,"%d ",pn->pid); X else X { X int x = jn->gleader; X X fprintf(stderr,"%d ",x); X do skip++; while (x /= 10); X skip++; X lng = 0; X } X else X fprintf(stderr,"%*s",skip,""); X if (pn->statusp == SP_RUNNING) X if (!conted) X fprintf(stderr,"running%*s",len-7+2,""); X else X fprintf(stderr,"continued%*s",len-9+2,""); X else if (WIFEXITED(SP(pn->statusp))) X if (WEXITSTATUS(SP(pn->statusp))) X fprintf(stderr,"exit %-4d%*s",WEXITSTATUS(SP(pn->statusp)), X len-9+2,""); X else X fprintf(stderr,"done%*s",len-4+2,""); X else if (WIFSTOPPED(SP(pn->statusp))) X fprintf(stderr,"%-*s",len+2,sigmsg[WSTOPSIG(SP(pn->statusp))]); X else if (WCOREDUMPED(pn->statusp)) X fprintf(stderr,"%s (core dumped)%*s", X sigmsg[WTERMSIG(SP(pn->statusp))], X len-14+2-strlen(sigmsg[WTERMSIG(SP(pn->statusp))]),""); X else X fprintf(stderr,"%-*s",len+2,sigmsg[WTERMSIG(SP(pn->statusp))]); X for (; pn != qn; pn = pn->next) X fprintf(stderr,(pn->next) ? "%s | " : "%s",pn->text); X putc('\n',stderr); X fline = 0; X } X printed = 1; X } X else if (doputnl && interact) X putc('\n',stderr); X fflush(stderr); X X /* print "(pwd now: foo)" messages */ X X if (interact && job==thisjob && strcmp(jn->cwd,cwd)) X { X printf("(pwd now: "); X printdir(cwd); X printf(")\n"); X fflush(stdout); X } X X /* delete job if done */ X X if (jn->stat & STAT_DONE) X { X static struct job zero; X struct process *nx; X char *s; X X if (jn->stat & STAT_TIMED) X { X dumptime(jn); X printed = 1; X } X for (pn = jn->procs; pn; pn = nx) X { X nx = pn->next; X if (pn->text) X free(pn->text); X free(pn); X } X free(jn->cwd); X if (jn->filelist) X { X while (s = getnode(jn->filelist)) X { X unlink(s); X free(s); X } X free(jn->filelist); X } X *jn = zero; X if (job == curjob) X { X curjob = prevjob; X prevjob = job; X } X if (job == prevjob) X setprevjob(); X } X else X jn->stat &= ~STAT_CHANGED; X} X X/* set the previous job to something reasonable */ X Xvoid setprevjob() /**/ X{ Xint t0; X X for (t0 = MAXJOB-1; t0; t0--) X if ((jobtab[t0].stat & STAT_INUSE) && (jobtab[t0].stat & STAT_STOPPED) && X t0 != curjob && t0 != thisjob) X break; X if (!t0) X for (t0 = MAXJOB-1; t0; t0--) X if ((jobtab[t0].stat & STAT_INUSE) && t0 != curjob && t0 != thisjob) X break; X prevjob = (t0) ? t0 : -1; X} X X/* initialize a job table entry */ X Xvoid initjob() /**/ X{ X jobtab[thisjob].cwd = ztrdup(cwd); X jobtab[thisjob].stat = STAT_INUSE; X jobtab[thisjob].gleader = 0; X} X X/* add a process to the current job */ X Xstruct process *addproc(pid,text) /**/ Xlong pid;char *text; X{ Xstruct process *process; X X if (!jobtab[thisjob].gleader) X jobtab[thisjob].gleader = lastpid = pid; X lastpid = pid; X process = zcalloc(sizeof *process); X process->pid = pid; X process->text = text; X process->next = NULL; X process->statusp = SP_RUNNING; X process->bgtime = time(NULL); X if (jobtab[thisjob].procs) X { X struct process *n; X X for (n = jobtab[thisjob].procs; n->next && !n->next->lastfg; n = n->next); X process->next = n->next; X n->next = process; X } X else X jobtab[thisjob].procs = process; X return process; X} X X/* determine if it's all right to exec a command without X forking in last component of subshells; it's not ok if we have files X to delete */ X Xint execok() /**/ X{ XJob jn; X X if (!exiting) X return 0; X for (jn = jobtab+1; jn != jobtab+MAXJOB; jn++) X if (jn->stat && jn->filelist) X return 0; X return 1; X} X X/* wait for a job to finish */ X Xvoid waitjob(job) /**/ Xint job; X{ Xstatic struct job zero; XJob jn; X X if (jobtab[job].procs) /* if any forks were done */ X { X jobtab[job].stat |= STAT_LOCKED; X waiting = 1; X if (jobtab[job].stat & STAT_CHANGED) X printjob(jobtab+job,!!isset(LONGLISTJOBS)); X while (jobtab[job].stat && X !(jobtab[job].stat & (STAT_DONE|STAT_STOPPED))) X chldsuspend(); X waiting = 0; X } X else /* else do what printjob() usually does */ X { X char *s; X X jn = jobtab+job; X free(jn->cwd); X if (jn->filelist) X { X while (s = getnode(jn->filelist)) X { X unlink(s); X free(s); X } X free(jn->filelist); X } X *jn = zero; X } X} X X/* wait for running job to finish */ X Xvoid waitjobs() /**/ X{ X waitjob(thisjob); X thisjob = -1; X} X X/* clear job table when entering subshells */ X Xvoid clearjobtab() /**/ X{ Xstatic struct job zero; Xint t0; X X for (t0 = 1; t0 != MAXJOB; t0++) X jobtab[thisjob] = zero; X} X X/* get a free entry in the job table to use */ X Xint getfreejob() /**/ X{ Xint t0; X X for (t0 = 1; t0 != MAXJOB; t0++) X if (!jobtab[t0].stat) { X jobtab[t0].stat |= STAT_INUSE; X return t0; X } X zerr("job table full or recursion limit exceeded",NULL,0); X return -1; X} X X/* print pids for & */ X Xvoid spawnjob() /**/ X{ Xstruct process *pn; X X if (!subsh) X { X if (curjob == -1 || !(jobtab[curjob].stat & STAT_STOPPED)) X { X curjob = thisjob; X setprevjob(); X } X else if (prevjob == -1 || !(jobtab[prevjob].stat & STAT_STOPPED)) X prevjob = thisjob; X if (interact && jobbing && jobtab[thisjob].procs) X { X fprintf(stderr,"[%d]",thisjob); X for (pn = jobtab[thisjob].procs; pn; pn = pn->next) X fprintf(stderr," %d",pn->pid); X fprintf(stderr,"\n"); X fflush(stderr); X } X } X if (!jobtab[thisjob].procs) X { X char *s; X static struct job zero; X struct job *jn; X X jn = jobtab+thisjob; X free(jn->cwd); X if (jn->filelist) X { X while (s = getnode(jn->filelist)) X { X unlink(s); X free(s); X } X free(jn->filelist); X } X *jn = zero; X } X else X jobtab[thisjob].stat |= STAT_LOCKED; X thisjob = -1; X} X Xvoid fixsigs() /**/ X{ X unblockchld(); X} X Xvoid printtime(real,ru,desc) /**/ Xtime_t real;struct rusage *ru;char *desc; X{ Xchar *s; X X if (!desc) X desc = ""; X for (s = (timefmt) ? timefmt : DEFTIMEFMT; *s; s++) X if (*s == '%') X switch(s++,*s) X { X case 'E': fprintf(stderr,"%lds",real); break; X case 'U': fprintf(stderr,"%ld.%03lds", X ru->ru_utime.tv_sec,ru->ru_utime.tv_usec/1000); break; X case 'S': fprintf(stderr,"%ld.%03lds", X ru->ru_stime.tv_sec,ru->ru_stime.tv_usec/1000); break; X case 'P': X if (real) X fprintf(stderr,"%d%%", X (int) (100*ru->ru_utime.tv_sec+ru->ru_stime.tv_sec) X / real); X break; X case 'W': fprintf(stderr,"%ld",ru->ru_nswap); break; X case 'X': fprintf(stderr,"%ld",ru->ru_ixrss); break; X case 'D': fprintf(stderr,"%ld",ru->ru_idrss); break; X case 'K': fprintf(stderr,"%ld",ru->ru_ixrss+ru->ru_idrss); break; X case 'M': fprintf(stderr,"%ld",ru->ru_maxrss); break; X case 'F': fprintf(stderr,"%ld",ru->ru_majflt); break; X case 'R': fprintf(stderr,"%ld",ru->ru_minflt); break; X case 'I': fprintf(stderr,"%ld",ru->ru_inblock); break; X case 'O': fprintf(stderr,"%ld",ru->ru_oublock); break; X case 'r': fprintf(stderr,"%ld",ru->ru_msgrcv); break; X case 's': fprintf(stderr,"%ld",ru->ru_msgsnd); break; X case 'k': fprintf(stderr,"%ld",ru->ru_nsignals); break; X case 'w': fprintf(stderr,"%ld",ru->ru_nvcsw); break; X case 'c': fprintf(stderr,"%ld",ru->ru_nivcsw); break; X default: fprintf(stderr,"%%%c",s[-1]); break; X } X else X putc(*s,stderr); X putc('\n',stderr); X fflush(stderr); X} X Xvoid dumptime(jn) /**/ XJob jn; X{ Xstruct process *pn = jn->procs; X X if (!jn->procs) X return; X for (pn = jn->procs; pn; pn = pn->next) X printtime(pn->endtime-pn->bgtime,&pn->ru,pn->text); X} X X/* SIGHUP any jobs left running */ X Xvoid killrunjobs() /**/ X{ Xint t0,killed = 0; X X if (isset(NOHUP)) return; X for (t0 = 1; t0 != MAXJOB; t0++) X if (t0 != thisjob && jobtab[t0].stat && X !(jobtab[t0].stat & STAT_STOPPED)) X { X kill(-jobtab[t0].gleader,SIGHUP); X killed++; X } X if (killed) X zerr("warning: %d jobs SIGHUPed",NULL,killed); X} X X/* check to see if user has jobs running/stopped */ X Xvoid checkjobs() /**/ X{ Xint t0; X X for (t0 = 1; t0 != MAXJOB; t0++) X if (t0 != thisjob && jobtab[t0].stat) X break; X if (t0 != MAXJOB) X { X if (jobtab[t0].stat & STAT_STOPPED) X { X#ifdef USE_SUSPENDED X zerr("you have suspended jobs.",NULL,0); X#else X zerr("you have stopped jobs.",NULL,0); X#endif X } X else X zerr("you have running jobs.",NULL,0); X stopmsg = 1; X } X} X X/* send a signal to a job (simply involves kill if monitoring is on) */ X Xint killjb(jn,sig) /**/ XJob jn;int sig; X{ Xstruct process *pn; Xint err; X X if (jobbing) X return(kill(-jn->gleader,sig)); X for (pn = jn->procs; pn; pn = pn->next) X if ((err = kill(pn->pid,sig)) == -1 && errno != ESRCH) X return -1; X return err; X} X SHAR_EOF echo 'File zsh2.1/src/jobs.c is complete' && chmod 0644 zsh2.1/src/jobs.c || echo 'restore of zsh2.1/src/jobs.c failed' Wc_c="`wc -c < 'zsh2.1/src/jobs.c'`" test 14918 -eq "$Wc_c" || echo 'zsh2.1/src/jobs.c: original size 14918, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= zsh2.1/src/lex.c ============== if test -f 'zsh2.1/src/lex.c' -a X"$1" != X"-c"; then echo 'x - skipping zsh2.1/src/lex.c (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting zsh2.1/src/lex.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/lex.c' && X/* X X lex.c - lexical analysis X X This file is part of zsh, the Z shell. X X zsh is free software; no one can prevent you from reading the source X code, or giving it to someone else. X This file is copyrighted under the GNU General Public License, which X can be found in the file called COPYING. X X Copyright (C) 1990, 1991 Paul Falstad X X zsh is distributed in the hope that it will be useful, but X WITHOUT ANY WARRANTY. No author or distributor accepts X responsibility to anyone for the consequences of using it or for X whether it serves any particular purpose or works at all, unless he X says so in writing. Refer to the GNU General Public License X for full details. X X Everyone is granted permission to copy, modify and redistribute X zsh, but only under the conditions described in the GNU General Public X License. A copy of this license is supposed to have been given to you X along with zsh so you can know your rights and responsibilities. X It should be in a file named COPYING. X X Among other things, the copyright notice and this notice must be X preserved on all copies. X X*/ X X#include "zsh.h" X X/* lexical state */ X Xstatic int xincmdpos,xincond,xincasepat,dbparens,xdbparens,xalstat; Xstatic char *xhlastw; X Xstatic int xisfirstln, xisfirstch, xhistremmed, xhistdone, X xspaceflag, xstophist, xlithist, xalstackind,xhlinesz; Xstatic char *xhline, *xhptr; X X/* save the lexical state */ X X/* is this a hack or what? */ X Xvoid lexsave() /**/ X{ X xincmdpos = incmdpos; X xincond = incond; X xincasepat = incasepat; X xdbparens = dbparens; X xalstat = alstat; X xalstackind = alstackind; X xisfirstln = isfirstln; X xisfirstch = isfirstch; X xhistremmed = histremmed; X xhistdone = histdone; X xspaceflag = spaceflag; X xstophist = stophist; X xlithist = lithist; X xhline = hline; X xhptr = hptr; X xhlastw = hlastw; X xhlinesz = hlinesz; X} X X/* restore lexical state */ X Xvoid lexrestore() /**/ X{ X incmdpos = xincmdpos; X incond = xincond; X incasepat = xincasepat; X dbparens = xdbparens; X alstat = xalstat; X isfirstln = xisfirstln; X isfirstch = xisfirstch; X histremmed = xhistremmed; X histdone = xhistdone; X spaceflag = xspaceflag; X stophist = xstophist; X lithist = xlithist; X hline = xhline; X hptr = xhptr; X hlastw = xhlastw; X clearalstack(); X alstackind = xalstackind; X hlinesz = xhlinesz; X lexstop = errflag = 0; X} X Xvoid yylex() /**/ X{ X if (tok == LEXERR) return; X do X tok = gettok(); X while (tok != ENDINPUT && exalias()); X isnewlin = (tok == NEWLIN && !inbufct); X if (tok == SEMI || tok == NEWLIN) X tok = SEPER; X} X Xvoid ctxtlex() /**/ X{ Xstatic int oldpos,inredir = 0; X X yylex(); X switch (tok) { X case SEPER: case NEWLIN: case SEMI: case DSEMI: case AMPER: X case INPAR: case INBRACE: case DBAR: case DAMPER: case BAR: X case BARAMP: case INOUTPAR: case DO: case THEN: case ELIF: X case ELSE: incmdpos = 1; break; X case STRING: case ENVSTRING: case ENVARRAY: case OUTPAR: X case FOR: case SELECT: case FOREACH: case CASE: incmdpos = 0; break; X } X if (IS_REDIROP(tok)) { X inredir = 2; X oldpos = incmdpos; X incmdpos = 0; X } else if (inredir) { X if (!--inredir) incmdpos = oldpos; X else incmdpos = 0; X } X} X X#define LX1_BKSLASH 0 X#define LX1_COMMENT 1 X#define LX1_NEWLIN 2 X#define LX1_SEMI 3 X#define LX1_BANG 4 X#define LX1_AMPER 5 X#define LX1_BAR 6 X#define LX1_INPAR 7 X#define LX1_OUTPAR 8 X#define LX1_INBRACE 9 X#define LX1_OUTBRACE 10 X#define LX1_INBRACK 11 X#define LX1_OUTBRACK 12 X#define LX1_INANG 13 X#define LX1_OUTANG 14 X#define LX1_OTHER 15 X X#define LX2_BREAK 0 X#define LX2_OUTPAR 1 X#define LX2_BAR 2 X#define LX2_STRING 3 X#define LX2_INBRACK 4 X#define LX2_OUTBRACK 5 X#define LX2_TILDE 6 X#define LX2_INPAR 7 X#define LX2_INBRACE 8 X#define LX2_OUTBRACE 9 X#define LX2_OUTANG 10 X#define LX2_INANG 11 X#define LX2_EQUALS 12 X#define LX2_BKSLASH 13 X#define LX2_QUOTE 14 X#define LX2_DQUOTE 15 X#define LX2_BQUOTE 16 X#define LX2_OTHER 17 X Xunsigned char lexact1[256],lexact2[256],lextok2[256]; X Xvoid initlextabs() /**/ X{ Xint t0; Xstatic char *lx1 = "\\q\n;!&|(){}[]<>xx"; Xstatic char *lx2 = "x)|$[]~({}><=\\\'\"`x"; X X for (t0 = 0; t0 != 256; t0++) { X lexact1[t0] = LX1_OTHER; X lexact2[t0] = LX2_OTHER; X lextok2[t0] = t0; X } X for (t0 = 0; lx1[t0]; t0++) X if (lx1[t0] != 'x') X lexact1[lx1[t0]] = t0; X for (t0 = 0; lx2[t0]; t0++) X if (lx2[t0] != 'x') X lexact2[lx2[t0]] = t0; X lexact2[';'] = LX2_BREAK; X lexact2['&'] = LX2_BREAK; X lextok2[','] = Comma; X lextok2['*'] = Star; X lextok2['?'] = Quest; X lextok2['{'] = Inbrace; X lextok2['['] = Inbrack; X lextok2['$'] = String; X} X X/* initialize lexical state */ X Xvoid lexinit() /**/ X{ X incond = incasepat = nocorrect = X dbparens = alstat = lexstop = 0; X incmdpos = 1; X tok = ENDINPUT; X if (isset(EXTENDEDGLOB)) X { X lextok2['#'] = Pound; X lextok2['^'] = Hat; X } X else X { X lextok2['#'] = '#'; X lextok2['^'] = '^'; X } X} X Xint len = 0,bsiz = 256; Xchar *bptr; X X/* add a char to the string buffer */ X Xvoid add(c) /**/ Xint c; X{ X *bptr++ = c; X if (bsiz == ++len) X { X int newbsiz; X X newbsiz = bsiz * 8; X while (newbsiz < inbufct) X newbsiz *= 2; X bptr = len+(tokstr = hrealloc(tokstr,bsiz,newbsiz)); X bsiz = newbsiz; X } X} X Xstatic void unadd() X{ X bptr--; bsiz--; X} X Xint gettok() /**/ X{ Xint bct = 0,pct = 0,brct = 0; Xint c,d,intpos = 1; Xint peekfd = -1,peek; X Xbeginning: X hlastw = NULL; X tokstr = NULL; X parbegin = -1; X while (iblank(c = hgetc()) && !lexstop); X isfirstln = 0; X wordbeg = inbufct; X hwbegin(); X hwaddc(c); X if (dbparens) /* handle ((...)) */ X { X pct = 2; X peek = STRING; X len = dbparens = 0; X bptr = tokstr = ncalloc(bsiz = 256); X for (;;) X { X if (c == '(') X pct++; X else if (c == ')') X pct--; X else if (c == '\n') X { X zerr("parse error: )) expected",NULL,0); X peek = LEXERR; X return peek; X } X else if (c == '$') X c = Qstring; X if (pct >= 2) X add(c); X if (pct) X c = hgetc(); X else X break; X } X *bptr = '\0'; X return peek; X } X if (idigit(c)) /* handle 1< foo */ X { X d = hgetc(); X hungetc(d); X lexstop = 0; X if (d == '>' || d == '<') X { X peekfd = c-'0'; X c = hgetc(); X } X } X X /* chars in initial position in word */ X X if (c == hashchar && X (isset(INTERACTIVECOMMENTS) || X (!zleparse && (!interact || unset(SHINSTDIN) || strin)))) X { X /* changed hgetch to hgetc so comments appear in history */ X stophist = 1; X while ((c = hgetc()) != '\n' && !lexstop); X if (c == '\n') { X hwaddc('\n'); X peek = NEWLIN; X } else { X peek = (errflag) ? LEXERR : ENDINPUT; X errflag = 1; X } X return peek; X } X if (lexstop) X return (errflag) ? LEXERR : ENDINPUT; X switch (lexact1[(unsigned char) c]) X { X case LX1_BKSLASH: X d = hgetc(); X if (d == '\n') X goto beginning; X hungetc(d); X break; X case LX1_NEWLIN: return NEWLIN; X case LX1_SEMI: X d = hgetc(); X if (d != ';') X { X hungetc(d); X return SEMI; X } X return DSEMI; X case LX1_BANG: X d = hgetc(); X hungetc(d); X if (!inblank(d)) X break; X if (incmdpos || incond) X return BANG; X break; X case LX1_AMPER: X d = hgetc(); X if (d != '&') X { X hungetc(d); X return AMPER; X } X return DAMPER; X case LX1_BAR: X d = hgetc(); X if (d == '|') X return DBAR; X else if (d == '&') X return BARAMP; X hungetc(d); X return BAR; X case LX1_INPAR: X d = hgetc(); X if (d == '(' && incmdpos) X { X tokstr = strdup("let"); X dbparens = 1; X return STRING; X } X else if (d == ')') X return INOUTPAR; X hungetc(d); X if (!(incond || incmdpos)) X break; X return INPAR; X case LX1_OUTPAR: return OUTPAR; X case LX1_INBRACE: if (!incmdpos) break; return INBRACE; X case LX1_OUTBRACE: return OUTBRACE; X case LX1_INBRACK: X if (!incmdpos) X break; X d = hgetc(); X if (d == '[') X return DINBRACK; X hungetc(d); X break; X case LX1_OUTBRACK: X if (!incond) X break; X d = hgetc(); X if (d == ']') X return DOUTBRACK; X hungetc(d); X break; X case LX1_INANG: X d = hgetc(); X if ((!incmdpos && d == '(') || incasepat) { X hungetc(d); X break; X } else if (d == '<') { X int e = hgetc(); X X if (e == '(') { X hungetc(e); X hungetc(d); X peek = INANG; X } else if (e == '<') X peek = TRINANG; X else if (e == '-') X peek = DINANGDASH; X else { X hungetc(e); X peek = DINANG; X } X } else if (d == '&') X peek = INANGAMP; X else { X peek = INANG; X hungetc(d); X } X tokfd = peekfd; X return peek; X case LX1_OUTANG: X d = hgetc(); X if (d == '(') X { X hungetc(d); X break; X } X else if (d == '&') X { X d = hgetc(); X if (d == '!') X peek = OUTANGAMPBANG; X else X { X hungetc(d); X peek = OUTANGAMP; X } X } X else if (d == '!') X peek = OUTANGBANG; X else if (d == '>') X { X d = hgetc(); X if (d == '&') X { X d = hgetc(); X if (d == '!') X peek = DOUTANGAMPBANG; X else X { X hungetc(d); X peek = DOUTANGAMP; X } X } X else if (d == '!') X peek = DOUTANGBANG; X else if (d == '(') X { X hungetc(d); X hungetc('>'); X peek = OUTANG; X } X else X { X hungetc(d); X peek = DOUTANG; X if (isset(NOCLOBBER)) hwaddc('!'); X } X } X else X { X hungetc(d); X peek = OUTANG; X if (isset(NOCLOBBER)) hwaddc('!'); X } X tokfd = peekfd; X return peek; X } X X /* we've started a string, now get the rest of it, performing X tokenization */ X X peek = STRING; X len = 0; X bptr = tokstr = ncalloc(bsiz = 256); X for(;;) X { X int act; X int d; X X if (inblank(c)) X act = LX2_BREAK; X else X { X act = lexact2[(unsigned char) c]; X c = lextok2[(unsigned char) c]; X } X switch (act) X { X case LX2_BREAK: goto brk; X case LX2_OUTPAR: X if (!pct) X goto brk; X c = Outpar; X pct--; X break; X case LX2_BAR: X if (!pct && !incasepat) X goto brk; X c = Bar; X break; X case LX2_STRING: X d = hgetc(); X if (d == '[') X { X add(String); X add(Inbrack); X while ((c = hgetc()) != ']' && !lexstop) X add(c); X c = Outbrack; X } X else if (d == '(') X { X add(String); X if (skipcomm()) { peek = LEXERR; goto brk; } X c = Outpar; X } X else X hungetc(d); X break; X case LX2_INBRACK: brct++; break; X case LX2_OUTBRACK: X if (incond && !brct) X goto brk; X brct--; X c = Outbrack; X break; X case LX2_TILDE: /* if (intpos) */ c = Tilde; break; X case LX2_INPAR: X d = hgetc(); X hungetc(d); X if (d == ')' || incmdpos) X goto brk; X pct++; X c = Inpar; X break; X case LX2_INBRACE: bct++; break; X case LX2_OUTBRACE: X if (!bct) X goto brk; X bct--; X c = Outbrace; X break; X case LX2_OUTANG: X d = hgetc(); X if (d != '(') X { X hungetc(d); X goto brk; X } X add(Outang); X if (skipcomm()) { peek = LEXERR; goto brk; } X c = Outpar; X break; X case LX2_INANG: X d = hgetc(); X if (!(idigit(d) || d == '-' || d == '>' || d == '(' || d == ')')) X { X hungetc(d); X goto brk; X } X c = Inang; X if (d == '(') X { X add(c); X if (skipcomm()) { peek = LEXERR; goto brk; } X c = Outpar; X } X else if (d == ')') X hungetc(d); X else X { X add(c); X c = d; X while (c != '>' && !lexstop) X add(c),c = hgetc(); X c = Outang; X } X break; X case LX2_EQUALS: X if (intpos) X { X d = hgetc(); X if (d != '(') X { X hungetc(d); X c = Equals; X } X else X { X add(Equals); X if (skipcomm()) { peek = LEXERR; goto brk; } X c = Outpar; X } X } X else if (peek != ENVSTRING && incmdpos) X { X d = hgetc(); X if (d == '(' && incmdpos) X { X *bptr = '\0'; X return ENVARRAY; X } X hungetc(d); X peek = ENVSTRING; X intpos = 2; X } X break; X case LX2_BKSLASH: X c = hgetc(); X if (c == '\n') X { X c = hgetc(); X continue; X } X add(c); X c = hgetc(); X continue; X case LX2_QUOTE: X add(Nularg); X X /* we add the Nularg to prevent this: X X echo $PA'TH' X X from printing the path. */ X X for (;;) { X while ((c = hgetc()) != '\'' && !lexstop) { X if (isset(CSHJUNKIEQUOTES) && c == '\n') { X if (bptr[-1] == '\\') unadd(); else break; X } X add(c); X } X if (c != '\'') { X zerr("unmatched \'",NULL,0); X peek = LEXERR; X goto brk; X } X d = hgetc(); X if (d != '\'' || unset(RCQUOTES)) break; X add(c); X } X hungetc(d); X c = Nularg; X break; X case LX2_DQUOTE: X add(Nularg); X while ((c = hgetc()) != '\"' && !lexstop) X if (c == '\\') X { X c = hgetc(); X if (c != '\n') X { X if (c != '$' && c != '\\' && c != '\"' && c != '`') X add('\\'); X add(c); X } X } X else { X if (isset(CSHJUNKIEQUOTES) && c == '\n') { X if (bptr[-1] == '\\') unadd(); else break; X } X if (c == '$') { X d = hgetc(); X if (d == '(') { X add(Qstring); X if (skipcomm()) { peek = LEXERR; goto brk; } X c = Outpar; X } else if (d == '[') { X add(String); X add(Inbrack); X while ((c = hgetc()) != ']' && !lexstop) X add(c); X c = Outbrack; X } else { X c = Qstring; X hungetc(d); X } X } else if (c == '`') X c = Qtick; X add(c); X } X if (c != '\"') { X zerr("unmatched \"",NULL,0); X peek = LEXERR; X goto brk; X } X c = Nularg; X break; X case LX2_BQUOTE: X add(Tick); X parbegin = inbufct; X while ((c = hgetc()) != '`' && !lexstop) X if (c == '\\') X { X c = hgetc(); X if (c != '\n') X { X if (c != '`' && c != '\\' && c != '$') X add('\\'); X add(c); X } X } X else { X if (isset(CSHJUNKIEQUOTES) && c == '\n') { X if (bptr[-1] == '\\') unadd(); else break; X } X add(c); X } X if (c != '`') { X if (!zleparse) zerr("unmatched `",NULL,0); X peek = LEXERR; X goto brk; X } X c = Tick; X parbegin = -1; X break; X } X add(c); X c = hgetc(); X if (intpos) X intpos--; X if (lexstop) X break; X } Xbrk: X hungetc(c); X *bptr = '\0'; X return peek; X} X X/* expand aliases, perhaps */ X Xint exalias() /**/ X{ Xstruct alias *an; Xchar *s,*t; X X s = yytext = hwadd(); X for (t = s; *t && *t != HISTSPACE; t++); X if (!*t) X t = NULL; X else X *t = '\0'; X if (interact && isset(SHINSTDIN) && !strin && !incasepat && tok == STRING && X (isset(CORRECTALL) || (isset(CORRECT) && incmdpos)) && !nocorrect) X spckword(&tokstr,&s,&t,!incmdpos,1); X if (zleparse && !alstackind) X gotword(s); X an = gethnode(s,aliastab); X if (t) X *t = HISTSPACE; X if (alstackind != MAXAL && an && !an->inuse) X if (!(an->cmd && !incmdpos && alstat != ALSTAT_MORE)) X { X if (an->cmd < 0) X { X tok = DO-an->cmd-1; X return 0; X } X else X { X an->inuse = 1; X hungets(ALPOPS); X hungets((alstack[alstackind++] = an)->text); X alstat = 0; X /* remove from history if it begins with space */ X if (isset(HISTIGNORESPACE) && an->text[0] == ' ') X remhist(); X lexstop = 0; X return 1; X } X } X return 0; X} X X/* skip (...) */ X Xint skipcomm() /**/ X{ Xint pct = 1,c; X X parbegin = inbufct; X c = Inpar; X do X { X add(c); X c = hgetc(); X if (itok(c) || lexstop) X break; X else if (c == '(') pct++; X else if (c == ')') pct--; X else if (c == '\\') X { X add(c); X c = hgetc(); X } X else if (c == '\'') X { X add(c); X while ((c = hgetc()) != '\'' && !lexstop) X add(c); X } X else if (c == '\"') X { X add(c); X while ((c = hgetc()) != '\"' && !lexstop) X if (c == '\\') X { X add(c); X add(hgetc()); X } X else add(c); X } X else if (c == '`') X { X add(c); X while ((c = hgetc()) != '`' && !lexstop) X if (c == '\\') add(c), add(hgetc()); X else add(c); X } X } X while(pct); X if (!lexstop) parbegin = -1; X return lexstop; X} X SHAR_EOF chmod 0644 zsh2.1/src/lex.c || echo 'restore of zsh2.1/src/lex.c failed' Wc_c="`wc -c < 'zsh2.1/src/lex.c'`" test 15750 -eq "$Wc_c" || echo 'zsh2.1/src/lex.c: original size 15750, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= zsh2.1/src/loop.c ============== if test -f 'zsh2.1/src/loop.c' -a X"$1" != X"-c"; then echo 'x - skipping zsh2.1/src/loop.c (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting zsh2.1/src/loop.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/loop.c' && X/* X X loop.c - loop execution X X This file is part of zsh, the Z shell. X X zsh is free software; no one can prevent you from reading the source X code, or giving it to someone else. X This file is copyrighted under the GNU General Public License, which X can be found in the file called COPYING. X X Copyright (C) 1990, 1991 Paul Falstad X X zsh is distributed in the hope that it will be useful, but X WITHOUT ANY WARRANTY. No author or distributor accepts X responsibility to anyone for the consequences of using it or for X whether it serves any particular purpose or works at all, unless he X says so in writing. Refer to the GNU General Public License X for full details. X X Everyone is granted permission to copy, modify and redistribute X zsh, but only under the conditions described in the GNU General Public X License. A copy of this license is supposed to have been given to you X along with zsh so you can know your rights and responsibilities. X It should be in a file named COPYING. X X Among other things, the copyright notice and this notice must be X preserved on all copies. X X*/ X X#include "zsh.h" X Xint execfor(cmd) /**/ XCmd cmd; X{ XList list; Xstruct forcmd *node; Xchar *str; XLklist args; Xint cj = thisjob; X X loops++; X exiting = 0; X node = cmd->u.forcmd; X args = cmd->args; X if (!node->inflag) X { X char **x; X X args = newlist(); X for (x = pparams; *x; x++) X addnode(args,ztrdup(*x)); X } X pushheap(); X while (str = ugetnode(args)) X { X setsparam(node->name,ztrdup(str)); X list = dupstruct(node->list); X execlist(list); X if (breaks) X { X breaks--; X if (breaks || !contflag) X break; X contflag = 0; X } X if (errflag) X { X lastval = 1; X break; X } X freeheap(); X } X popheap(); X thisjob = cj; X return lastval; X} X Xint execselect(cmd) /**/ XCmd cmd; X{ XList list; Xstruct forcmd *node; Xchar *str,*s; XLklist args; XLknode n; Xint cj = thisjob,t0; X X loops++; X node = cmd->u.forcmd; X args = cmd->args; X if (!full(args)) X return 1; X exiting = 0; X pushheap(); X for (;;) X { X do X { X selectlist(args); X if (interact && SHTTY != -1 && isset(USEZLE)) X { X int pl; X X str = putprompt(prompt3,&pl); X str = zleread(str,NULL,pl); X } X else X str = fgets(zalloc(256),256,bshin); X if (!str || errflag) X { X fprintf(stderr,"\n"); X fflush(stderr); X goto done; X } X if (s = strchr(str,'\n')) X *s = '\0'; X } X while (!*str); X setsparam("REPLY",ztrdup(str)); X t0 = atoi(str); X if (!t0) X str = ""; X else X { X for (t0--,n = firstnode(args); n && t0; incnode(n),t0--); X if (n) X str = getdata(n); X else X str = ""; X } X setsparam(node->name,ztrdup(str)); X list = dupstruct(node->list); X execlist(list); X freeheap(); X if (breaks) X { X breaks--; X if (breaks || !contflag) X break; X contflag = 0; X } X if (errflag) X break; X } Xdone: X popheap(); X thisjob = cj; X return lastval; X} X Xint execwhile(cmd) /**/ XCmd cmd; X{ XList list; Xstruct whilecmd *node; Xint cj = thisjob; X X loops++; X node = cmd->u.whilecmd; X exiting = 0; X pushheap(); X for(;;) X { X list = dupstruct(node->cont); X execlist(list); X if (!((lastval == 0) ^ node->cond)) X break; X list = dupstruct(node->loop); X execlist(list); X if (breaks) X { X breaks--; X if (breaks || !contflag) X break; X contflag = 0; X } X freeheap(); X if (errflag) X { X lastval = 1; X break; X } X } X popheap(); X thisjob = cj; X return lastval; X} X Xint execrepeat(cmd) /**/ XCmd cmd; X{ XList list; Xint cj = thisjob,count; X X loops++; X exiting = 0; X if (!full(cmd->args) || nextnode(firstnode(cmd->args))) X { X zerr("bad argument for repeat",NULL,0); X return 1; X } X count = atoi(peekfirst(cmd->args)); X pushheap(); X while (count--) X { X list = dupstruct(cmd->u.list); X execlist(list); X freeheap(); X if (breaks) X { X breaks--; X if (breaks || !contflag) X break; X contflag = 0; X } X if (lastval) X break; X if (errflag) X { X lastval = 1; X break; X } X } X popheap(); X thisjob = cj; X return lastval; X} X Xint execif(cmd) /**/ XCmd cmd; X{ Xstruct ifcmd *node; Xint cj = thisjob; X X node = cmd->u.ifcmd; X exiting = 0; X while (node) X { X if (node->ifl) X { X execlist(node->ifl); X if (lastval) X { X node = node->next; X continue; X } X } X execlist(node->thenl); X break; X } X thisjob = cj; X return lastval; X} X Xint execcase(cmd) /**/ XCmd cmd; X{ Xstruct casecmd *node; Xchar *word; XLklist args; Xint cj = thisjob; X X node = cmd->u.casecmd; X args = cmd->args; X exiting = 0; X if (firstnode(args) && nextnode(firstnode(args))) X { X zerr("too many arguments to case",NULL,0); X errflag = 1; X return 1; X } X if (!full(args)) X word = strdup(""); X else X word = peekfirst(args); X while (node) X { X singsub(&(node->pat)); X if (matchpat(word,node->pat)) X break; X else X node = node->next; X } X if (node && node->list) X execlist(node->list); X thisjob = cj; X return lastval; X} SHAR_EOF chmod 0644 zsh2.1/src/loop.c || echo 'restore of zsh2.1/src/loop.c failed' Wc_c="`wc -c < 'zsh2.1/src/loop.c'`" test 4854 -eq "$Wc_c" || echo 'zsh2.1/src/loop.c: original size 4854, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= zsh2.1/src/math.c ============== if test -f 'zsh2.1/src/math.c' -a X"$1" != X"-c"; then echo 'x - skipping zsh2.1/src/math.c (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting zsh2.1/src/math.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/math.c' && X/* X X math.c - mathematical expression evaluation X X This file is part of zsh, the Z shell. X X zsh is free software; no one can prevent you from reading the source X code, or giving it to someone else. X X This file is copyrighted under the GNU General Public License, which X can be found in the file called COPYING. X X Copyright (C) 1990, 1991 Paul Falstad X X zsh is distributed in the hope that it will be useful, but X WITHOUT ANY WARRANTY. No author or distributor accepts X responsibility to anyone for the consequences of using it or for X whether it serves any particular purpose or works at all, unless he X says so in writing. Refer to the GNU General Public License X for full details. X X Everyone is granted permission to copy, modify and redistribute X zsh, but only under the conditions described in the GNU General Public X License. A copy of this license is supposed to have been given to you X along with zsh so you can know your rights and responsibilities. X It should be in a file named COPYING. X X Among other things, the copyright notice and this notice must be X preserved on all copies. X X*/ X X#include "zsh.h" X Xstatic char *ptr; X Xtypedef int LV; X Xstatic long yyval; Xstatic LV yylval; X X/* nonzero means we are not evaluating, just parsing */ X Xstatic int noeval = 0; X X/* != 0 means recognize unary plus, minus, etc. */ X Xstatic int unary = 1; X Xvoid mathparse DCLPROTO((int)); X X/* LR = left-to-right associativity X RL = right-to-left associativity X BOO = short-circuiting boolean */ X X#define LR 0 X#define RL 1 X#define BOOL 2 X X#define M_INPAR 0 X#define M_OUTPAR 1 X#define NOT 2 X#define COMP 3 X#define POSTPLUS 4 X#define POSTMINUS 5 X#define UPLUS 6 X#define UMINUS 7 X#define AND 8 X#define XOR 9 X#define OR 10 X#define MUL 11 X#define DIV 12 X#define MOD 13 X#define PLUS 14 X#define MINUS 15 X#define SHLEFT 16 X#define SHRIGHT 17 X#define LES 18 X#define LEQ 19 X#define GRE 20 X#define GEQ 21 X#define DEQ 22 X#define NEQ 23 X#define DAND 24 X#define DOR 25 X#define DXOR 26 X#define QUEST 27 X#define COLON 28 X#define EQ 29 X#define PLUSEQ 30 X#define MINUSEQ 31 X#define MULEQ 32 X#define DIVEQ 33 X#define MODEQ 34 X#define ANDEQ 35 X#define XOREQ 36 X#define OREQ 37 X#define SHLEFTEQ 38 X#define SHRIGHTEQ 39 X#define DANDEQ 40 X#define DOREQ 41 X#define DXOREQ 42 X#define COMMA 43 X#define EOI 44 X#define PREPLUS 45 X#define PREMINUS 46 X#define NUM 47 X#define ID 48 X#define TOKCOUNT 49 X X/* precedences */ X Xstatic int prec[TOKCOUNT] = { X 1,137,2,2,2, X 2,2,2,4,5, X 6,7,7,7,8, X 8,3,3,9,9, X 9,9,10,10,11, X 12,12,13,13,14, X 14,14,14,14,14, X 14,14,14,14,14, X 14,14,14,15,200, X 2,2,0,0, X}; X X#define TOPPREC 15 X#define ARGPREC (15-1) X Xstatic int type[TOKCOUNT] = { X LR,LR,RL,RL,RL, X RL,RL,RL,LR,LR, X LR,LR,LR,LR,LR, X LR,LR,LR,LR,LR, X LR,LR,LR,LR,BOOL, X BOOL,LR,RL,RL,RL, X RL,RL,RL,RL,RL, X RL,RL,RL,RL,RL, X BOOL,BOOL,RL,RL,RL, X RL,RL,LR,LR, X}; X X#define LVCOUNT 32 X X/* list of lvalues (variables) */ X Xstatic int lvc; Xstatic char *lvals[LVCOUNT]; X Xint zzlex() /**/ X{ X for(;;) X switch (*ptr++) X { X case '+': X if (*ptr == '+' && (unary || !ialnum(*ptr))) X { X ptr++; X return (unary) ? PREPLUS : POSTPLUS; X } X if (*ptr == '=') { unary = 1; ptr++; return PLUSEQ; } X return (unary) ? UPLUS : PLUS; X case '-': X if (*ptr == '-' && (unary || !ialnum(*ptr))) X { X ptr++; X return (unary) ? PREMINUS : POSTMINUS; X } X if (*ptr == '=') { unary = 1; ptr++; return MINUSEQ; } X return (unary) ? UMINUS : MINUS; X case '(': unary = 1; return M_INPAR; X case ')': return M_OUTPAR; X case '!': if (*ptr == '=') X { unary = 1; ptr++; return NEQ; } X return NOT; X case '~': return COMP; X case '&': unary = 1; X if (*ptr == '&') { if (*++ptr == '=') X { ptr++; return DANDEQ; } return DAND; } X else if (*ptr == '=') { ptr++; return ANDEQ; } return AND; X case '|': unary = 1; X if (*ptr == '|') { if (*++ptr == '=') X { ptr++; return DOREQ; } return DOR; } X else if (*ptr == '=') { ptr++; return OREQ; } return OR; X case '^': unary = 1; X if (*ptr == '^') { if (*++ptr == '=') X { ptr++; return DXOREQ; } return DXOR; } X else if (*ptr == '=') { ptr++; return XOREQ; } return XOR; X case '*': unary = 1; X if (*ptr == '=') { ptr++; return MULEQ; } return MUL; X case '/': unary = 1; X if (*ptr == '=') { ptr++; return DIVEQ; } return DIV; X case '%': unary = 1; X if (*ptr == '=') { ptr++; return MODEQ; } return MOD; X case '<': unary = 1; if (*ptr == '<') X { if (*++ptr == '=') { ptr++; return SHLEFTEQ; } return SHLEFT; } X else if (*ptr == '=') { ptr++; return LEQ; } return LES; X case '>': unary = 1; if (*ptr == '>') X { if (*++ptr == '=') { ptr++; return SHRIGHTEQ; } return SHRIGHT; } X else if (*ptr == '=') { ptr++; return GEQ; } return GRE; X case '=': unary = 1; if (*ptr == '=') { ptr++; return DEQ; } X return EQ; X case '?': unary = 1; return QUEST; X case ':': unary = 1; return COLON; X case ',': unary = 1; return COMMA; X case '\0': unary = 1; ptr--; return EOI; X case '[': unary = 0; X { int base = zstrtol(ptr,&ptr,10); X if (*ptr == ']') ptr++; X yyval = zstrtol(ptr,&ptr,lastbase = base); X return NUM; } X case ' ': case '\t': X break; X default: X if (idigit(*--ptr)) X { unary = 0; yyval = zstrtol(ptr,&ptr,10); return NUM; } X if (ialpha(*ptr) || *ptr == '$') X { X char *p,q; X X if (*ptr == '$') X ptr++; X p = ptr; X if (lvc == LVCOUNT) X { X zerr("too many identifiers (complain to author)",NULL,0); X return EOI; X } X unary = 0; X while(ialpha(*++ptr)); X q = *ptr; X *ptr = '\0'; X lvals[yylval = lvc++] = ztrdup(p); X *ptr = q; X return ID; X } X return EOI; X } X} X X/* the value stack */ X X#define STACKSZ 100 Xint mtok; /* last token */ Xint sp = -1; /* stack pointer */ Xstruct mathvalue { X LV lval; X long val; X } stack[STACKSZ]; X Xvoid push(val,lval) Xlong val;LV lval; X{ X if (sp == STACKSZ-1) X zerr("stack overflow",NULL,0); X else X sp++; X stack[sp].val = val; X stack[sp].lval = lval; X} X Xlong getvar(s) XLV s; X{ Xlong t; X X if (!(t = getiparam(lvals[s]))) X return 0; X return t; X} X Xlong setvar(s,v) XLV s;long v; X{ X if (s == -1 || s >= lvc) X { X zerr("lvalue required",NULL,0); X return 0; X } X if (noeval) X return v; X setiparam(lvals[s],v); X return v; X} X Xint notzero(a) /**/ Xint a; X{ X if (a == 0) X { X zerr("division by zero",NULL,0); X return 0; X } X return 1; X} X X#define pop2() { b = stack[sp--].val; a = stack[sp--].val; } X#define pop3() {c=stack[sp--].val;b=stack[sp--].val;a=stack[sp--].val;} X#define nolval() {stack[sp].lval= -1;} X#define pushv(X) { push(X,-1); } X#define pop2lv() { pop2() lv = stack[sp+1].lval; } X#define set(X) { push(setvar(lv,X),lv); } X Xvoid op(what) /**/ Xint what; X{ Xlong a,b,c; XLV lv; X X if (sp < 0) X { X zerr("bad math expression: stack empty",NULL,0); X return; X } X switch(what) { X case NOT: stack[sp].val = !stack[sp].val; nolval(); break; X case COMP: stack[sp].val = ~stack[sp].val; nolval(); break; X case POSTPLUS: ( void ) setvar(stack[sp].lval,stack[sp].val+1); break; X case POSTMINUS: ( void ) setvar(stack[sp].lval,stack[sp].val-1); break; X case UPLUS: nolval(); break; X case UMINUS: stack[sp].val = -stack[sp].val; nolval(); break; X case AND: pop2(); pushv(a&b); break; X case XOR: pop2(); pushv(a^b); break; X case OR: pop2(); pushv(a|b); break; X case MUL: pop2(); pushv(a*b); break; X case DIV: pop2(); if (notzero(b)) pushv(a/b); break; X case MOD: pop2(); if (notzero(b)) pushv(a%b); break; X case PLUS: pop2(); pushv(a+b); break; X case MINUS: pop2(); pushv(a-b); break; X case SHLEFT: pop2(); pushv(a<>b); break; X case LES: pop2(); pushv(ab); break; X case GEQ: pop2(); pushv(a>=b); break; X case DEQ: pop2(); pushv(a==b); break; X case NEQ: pop2(); pushv(a!=b); break; X case DAND: pop2(); pushv(a&&b); break; X case DOR: pop2(); pushv(a||b); break; X case DXOR: pop2(); pushv(a&&!b||!a&&b); break; X case QUEST: pop3(); pushv((a)?b:c); break; X case COLON: break; X case EQ: pop2lv(); set(b); break; X case PLUSEQ: pop2lv(); set(a+b); break; X case MINUSEQ: pop2lv(); set(a-b); break; X case MULEQ: pop2lv(); set(a*b); break; X case DIVEQ: pop2lv(); if (notzero(b)) set(a/b); break; X case MODEQ: pop2lv(); if (notzero(b)) set(a%b); break; X case ANDEQ: pop2lv(); set(a&b); break; X case XOREQ: pop2lv(); set(a^b); break; X case OREQ: pop2lv(); set(a|b); break; X case SHLEFTEQ: pop2lv(); set(a<>b); break; X case DANDEQ: pop2lv(); set(a&&b); break; X case DOREQ: pop2lv(); set(a||b); break; X case DXOREQ: pop2lv(); set(a&&!b||!a&&b); break; X case COMMA: pop2(); pushv(b); break; X case PREPLUS: stack[sp].val = setvar(stack[sp].lval, X stack[sp].val+1); break; SHAR_EOF true || echo 'restore of zsh2.1/src/math.c failed' fi echo 'End of zsh2.1.0 part 8' echo 'File zsh2.1/src/math.c is continued in part 9' echo 9 > _shar_seq_.tmp exit 0 exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.