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