[comp.sources.misc] v18i089: zsh2.00 - The Z shell, Part06/15

pfalstad@phoenix.princeton.edu (Paul Falstad) (04/24/91)

Submitted-by: Paul Falstad <pfalstad@phoenix.princeton.edu>
Posting-number: Volume 18, Issue 89
Archive-name: zsh2.00/part06

#!/bin/sh
# this is zsh2.00.00.shar.06 (part 6 of zsh2.00.00)
# do not concatenate these parts, unpack them in order with /bin/sh
# file zsh2.00/src/glob.c continued
#
if test ! -r _shar_seq_.tmp; then
	echo 'Please unpack part 1 first!'
	exit 1
fi
(read Scheck
 if test "$Scheck" != 6; 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.00/src/glob.c'
else
echo 'x - continuing file zsh2.00/src/glob.c'
sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.00/src/glob.c' &&
X
X	for (; *c == *d && *c; c++,d++);
X	return ((int) (unsigned char) *c-(int) (unsigned char) *d);
X}
X
Xint forstrcmp(a,b) /**/
Xchar **a;char **b;
X{
Xchar *c = *b,*d = *a;
X
X	for (; *c == *d && *c; c++,d++);
X	return ((int) (unsigned char) *d-(int) (unsigned char) *c);
X}
X
X/* add a match to the list */
X
Xvoid insert(s) /**/
Xchar *s;
X{
Xstruct stat buf;
X
X	if (isset(MARKDIRS) && !lstat(s,&buf) && S_ISDIR(buf.st_mode)) /* grrr */
X		{
X		char *t;
X		int ll = strlen(s);
X
X		t = zalloc(ll+2);
X		strcpy(t,s);
X		t[ll] = '/';
X		t[ll+1] = '\0';
X		free(s);
X		s = t;
X		}
X	*matchptr++ = s;
X	if (++matchct == matchsz)
X		{
X		matchbuf = (char **) realloc((char *) matchbuf,
X			sizeof(char **)*(matchsz *= 2));
X		matchptr = matchbuf+matchct;
X		}
X}
X
X/* check to see if str is eligible for filename generation */
X
Xint haswilds(str) /**/
Xchar *str;
X{
X	if (!str[1] && (*str == Inbrack || *str == Outbrack))
X		return 0;
X	if (str[0] == '%')
X		return 0;
X	for (; *str; str++)
X		if (!strncmp(str,"..../",5))
X			return 1;
X		else if (*str == Pound || *str == Hat || *str == Star ||
X				*str == Bar || *str == Inbrack || *str == Inang ||
X				*str == Quest)
X			return 1;
X	return 0;
X}
X
X/* check to see if str is eligible for brace expansion */
X
Xint hasbraces(str) /**/
Xchar *str;
X{
Xint mb,bc,cmct1,cmct2;
Xchar *lbr = NULL;
X
X	if (str[0] == Inbrace && str[1] == Outbrace)
X		return 0;
X	for (mb = bc = cmct1 = cmct2 = 0; *str; str++)
X		{
X		if (*str == Inbrace)
X			{
X			if (!bc)
X				lbr = str;
X			bc++;
X			if (str[4] == Outbrace && str[2] == '-') /* {a-z} */
X				{
X				cmct1++;
X				if (bc == 1)
X					cmct2++;
X				}
X			}
X		else if (*str == Outbrace)
X			{
X			bc--;
X			if (!bc && !cmct2)
X				{
X				*lbr = '{';
X				*str = '}';
X				}
X			cmct2 = 0;
X			}
X		else if (*str == Comma && bc)
X			{
X			cmct1++;
X			if (bc == 1)
X				cmct2++;
X			}
X		if (bc > mb)
X			mb = bc;
X		if (bc < 0)
X			return 0;
X		}
X	return (mb && bc == 0 && cmct1);
X}
X
X/* expand stuff like >>*.c */
X
Xint xpandredir(fn,tab) /**/
Xstruct redir *fn;Lklist tab;
X{
XLklist fake;
Xchar *nam;
Xstruct redir *ff;
Xint ret = 0;
X
X	fake = newlist();
X	addnode(fake,fn->name);
X	prefork(fake);
X	if (!errflag)
X		postfork(fake,1);
X	if (errflag)
X		return 0;
X	if (full(fake) && !nextnode(firstnode(fake)))
X		{
X		fn->name = peekfirst(fake);
X		untokenize(fn->name);
X		}
X	else
X		while (nam = ugetnode(fake))
X			{
X			ff = alloc(sizeof *ff);
X			*ff = *fn;
X			ff->name = nam;
X			addnode(tab,ff);
X			ret = 1;
X			}
X	return ret;
X}
X
X/* concatenate s1 and s2 in dynamically allocated buffer */
X
Xchar *dyncat(s1,s2) /**/
Xchar *s1;char *s2;
X{
Xchar *ptr;
X 
X	ptr = ncalloc(strlen(s1)+strlen(s2)+1);
X	strcpy(ptr,s1);
X	strcat(ptr,s2);
X	return ptr;
X}
X
X/* concatenate s1, s2, and s3 in dynamically allocated buffer */
X
Xchar *tricat(s1,s2,s3) /**/
Xchar *s1;char *s2;char *s3;
X{
Xchar *ptr;
X
X	ptr = zalloc(strlen(s1)+strlen(s2)+strlen(s3)+1);
X	strcpy(ptr,s1);
X	strcat(ptr,s2);
X	strcat(ptr,s3);
X	return ptr;
X}
X
X/* brace expansion */
X
Xvoid xpandbraces(list,np) /**/
XLklist list;Lknode *np;
X{
XLknode node = (*np),last = prevnode(node);
Xchar *str = getdata(node),*str3 = str,*str2;
Xint prev;
X
X	for (; *str != Inbrace; str++);
X 	if (str[2] == '-' && str[4] == Outbrace)	 /* {a-z} */
X		{
X		char c1,c2;
X
X		uremnode(list,node);
X		chuck(str);
X		c1 = *str;
X		chuck(str);
X		chuck(str);
X		c2 = *str;
X		chuck(str);
X		if (itok(c1))
X			c1 = ztokens[c1-Pound];
X		if (itok(c2))
X			c2 = ztokens[c2-Pound];
X		if (c1 < c2)
X			for (; c2 >= c1; c2--)	/* {a-z} */
X				{
X				*str = c2;
X				insnode(list,last,strdup(str3));
X				}
X		else
X			for (; c2 <= c1; c2++)	/* {z-a} */
X				{
X				*str = c2;
X				insnode(list,last,strdup(str3));
X				}
X		*np = nextnode(last);
X		return;
X		}
X	prev = str-str3;
X	str2 = getparen(str++);
X	if (!str2)
X		{
X		zerr("how did you get this error?",NULL,0);
X		return;
X		}
X	uremnode(list,node);
X	node = last;
X	for(;;)
X		{
X		char *zz,*str4;
X		int cnt;
X		
X		for (str4 = str, cnt = 0; cnt || *str != Comma && *str !=
X				Outbrace; str++)
X			if (*str == Inbrace)
X				cnt++;
X			else if (*str == Outbrace)
X				cnt--;
X			else if (!*str)
X				exit(10);
X		zz = zalloc(prev+(str-str4)+strlen(str2)+1);
X		strncpy(zz,str3,prev);
X		zz[prev] = '\0';
X		strncat(zz,str4,str-str4);
X		strcat(zz,str2);
X		insnode(list,node,zz);
X		incnode(node);
X		if (*str != Outbrace)
X			str++;
X		else
X			break;
X		}
X	*np = nextnode(last);
X}
X
X/* get closing paren, given pointer to opening paren */
X
Xchar *getparen(str) /**/
Xchar *str;
X{
Xint cnt = 1;
Xchar typein = *str++,typeout = typein+1;
X
X	for (; *str && cnt; str++)
X		if (*str == typein)
X			cnt++;
X		else if (*str == typeout)
X			cnt--;
X	if (!str && cnt)
X		return NULL;
X	return str;
X}
X
X/* check to see if a matches b (b is not a filename pattern) */
X
Xint matchpat(a,b) /**/
Xchar *a;char *b;
X{
XComp c;
Xint val;
X
X	c = parsereg(b);
X	if (!c)
X		{
X		zerr("bad pattern: %s",b,0);
X		return 0;
X		}
X	val = domatch(a,c,0);
X	return val;
X}
X
X/* do the ${foo%%bar}, ${foo#bar} stuff */
X/* please do not laugh at this code. */
X
Xvoid getmatch(sp,pat,dd) /**/
Xchar **sp;char *pat;int dd;
X{
XComp c;
Xchar *t,*lng = NULL,cc,*s = *sp;
X
X	c = parsereg(pat);
X	if (!c)
X		{
X		zerr("bad pattern: %s",pat,0);
X		return;
X		}
X	if (!(dd & 2))
X		{
X		for (t = s; t==s || t[-1]; t++)
X			{
X			cc = *t;
X			*t = '\0';
X			if (domatch(s,c,0))
X				{
X				if (!(dd & 1))
X					{
X					*t = cc;
X					t = strdup(t);
X					*sp = t;
X					return;
X					}
X				lng = t;
X				}
X			*t = cc;
X			}
X		if (lng)
X			{
X			t = strdup(lng);
X			*sp = t;
X			return;
X			}
X		}
X	else
X		{
X		for (t = s+strlen(s); t >= s; t--)
X			{
X			if (domatch(t,c,0))
X				{
X				if (!(dd & 1))
X					{
X					*t = '\0';
X					return;
X					}
X				lng = t;
X				}
X			}
X		if (lng)
X			{
X			*lng = '\0';
X			return;
X			}
X		}
X}
X
X/* add a component to pathbuf */
X
Xvoid addpath(s) /**/
Xchar *s;
X{
X	while (pathbuf[pathpos++] = *s++);
X	pathbuf[pathpos-1] = '/';
X	pathbuf[pathpos] = '\0';
X}
X
Xchar *getfullpath(s) /**/
Xchar *s;
X{
Xstatic char buf[MAXPATHLEN];
X
X	strcpy(buf,pathbuf);
X	strcat(buf,s);
X	return buf;
X}
X
X/* do the globbing */
X
Xvoid scanner(q) /**/
XComplist q;
X{
XComp c;
Xint closure;
X
X	if (closure = q->closure)	/* (foo/)# */
X		if (q->closure == 2)		/* (foo/)## */
X			q->closure = 1;
X		else
X			scanner(q->next);
X	if (c = q->comp)
X		{
X		if (!(c->next || c->left) && !haswilds(c->str))
X			if (q->next)
X				{
X				int oppos = pathpos;
X
X				if (errflag)
X					return;
X				addpath(c->str);
X				if (!closure || exists(pathbuf))
X					scanner((q->closure) ? q : q->next);
X				pathbuf[pathpos = oppos] = '\0';
X				}
X			else
X				{
X				char *s;
X
X				if (exists(s = getfullpath(c->str)))
X					insert(strdup(s));
X				}
X		else
X			{
X			char *fn;
X			int dirs = !!q->next;
X			struct direct *de;
X			DIR *lock = opendir(pathbuf);
X			 
X			if (lock == NULL)
X				return;
X			readdir(lock); readdir(lock); 	/* skip . and .. */
X			while (de = readdir(lock))
X				{
X				if (errflag)
X					break;
X				fn = &de->d_name[0];
X				if (domatch(fn,c,unset(GLOBDOTS)))
X					{
X					int oppos = pathpos;
X
X					if (dirs)
X						{
X						if (closure)
X							{
X							int type3;
X							struct stat buf;
X
X					 		if (lstat(getfullpath(fn),&buf) == -1)
X								{
X								if (errno != ENOENT && errno != EINTR &&
X										errno != ENOTDIR)
X									{
X									zerr("%e: %s",fn,errno);
X									errflag = 0;
X									}
X								continue;
X								}
X							type3 = buf.st_mode & S_IFMT;
X							if (type3 != S_IFDIR)
X								continue;
X							}
X						addpath(fn);
X						scanner((q->closure) ? q : q->next); /* scan next level */
X						pathbuf[pathpos = oppos] = '\0';
X						}
X					else
X						{
X						if (qualct)	/* do the (X) (^X) stuff */
X							{
X							int (**fptr)DCLPROTO((struct stat *,long)) = qualfuncs;
X							int *sptr = qualsense;
X							long *lptr = qualdata;
X							struct stat buf;
X	
X							if (lstat(getfullpath(fn),&buf) == -1)
X								{
X								if (errno != ENOENT && errno != EINTR)
X									{
X									zerr("%e: %s",fn,errno);
X									errflag = 0;
X									}
X								continue;
X								}
X							while (*fptr)
X								if (!(!!((*fptr++)(&buf,*lptr++)) ^ *sptr++))
X									{
X									fptr = NULL;
X									break;
X									}
X							if (!fptr)
X								continue;
X							}
X						insert(dyncat(pathbuf,fn));
X						}
X					}
X				}
X			closedir(lock);
X			}
X		}
X	else
X		zerr("no idea how you got this error message.",NULL,0);
X}
X
X/* do the [..(foo)..] business */
X
Xint minimatch(pat,str) /**/
Xchar **pat;char **str;
X{
Xchar *pt = *pat+1,*s = *str;
X	
X	for (; *pt != Outpar; s++,pt++)
X		if ((*pt != Quest || !*s) && *pt != *s)
X			{
X			*pat = getparen(*pat)-1;
X			return 0;
X			}
X	*str = s-1;
X	return 1;
X}
X
Xstatic char *pptr;
Xstatic int first;
X
Xint domatch(str,c,fist) /**/
Xchar *str;Comp c;int fist;
X{
X	pptr = str;
X	first = fist;
X	return doesmatch(c);
X}
X
X/* see if current pattern matches c */
X
Xint doesmatch(c) /**/
XComp c;
X{
Xchar *pat = c->str;
X
X	if (c->closure)
X		{
X		char *saves = pptr;
X		int savei = first;
X
X		if (doesmatch(c->next))
X			return 1;
X		pptr = saves;
X		first = savei;
X		}
X	for(;;)
X		{
X		if (!pat || !*pat)
X			{
X			char *saves;
X			int savei;
X
X			if (errflag)
X				return 0;
X			saves = pptr;
X			savei = first;
X			if (c->left || c->right)
X				if (!doesmatch(c->left))
X					if (c->right)
X						{
X						pptr = saves;
X						first = savei;
X						if (!doesmatch(c->right))
X							return 0;
X						}
X					else
X						return 0;
X			if (c->closure)
X				return doesmatch(c);
X			if (!c->next)
X				return (!c->last || !*pptr);
X			return doesmatch(c->next);
X			}
X		if (first && *pptr == '.' && *pat != '.')
X			return 0;
X		if (*pat == Star)	/* final * is not expanded to ?#; returns success */
X			{
X			while (*pptr) pptr++;
X			return 1;
X			}
X		first = 0;
X		if (*pat == Quest && *pptr)
X			{
X			pptr++;
X			pat++;
X			continue;
X			}
X		if (*pat == Hat)
X			return 1-doesmatch(c->next);
X		if (*pat == Inbrack)
X			if (pat[1] == Hat)
X				{
X				for (pat += 2; *pat != Outbrack && *pat; pat++)
X					if (*pat == '-' && pat[-1] != Hat && pat[1] != Outbrack)
X						{
X						if (pat[-1] <= *pptr && pat[1] >= *pptr)
X							break;
X						}
X					else if (*pptr == *pat)
X						break;
X				if (!*pat)
X					{
X					zerr("something is very wrong.",NULL,0);
X					return 0;
X					}
X				if (*pat != Outbrack)
X					break;
X				pat++;
X				pptr++;
X				continue;
X				}
X			else
X				{
X				for (pat++; *pat != Outbrack && *pat; pat++)
X					if (*pat == Inpar)
X						{
X						if (minimatch(&pat,&pptr))
X							break;
X						}
X					else if (*pat == '-' && pat[-1] != Inbrack && pat[1] != Outbrack)
X						{
X						if (pat[-1] <= *pptr && pat[1] >= *pptr)
X							break;
X						}
X					else if (*pptr == *pat)
X						break;
X				if (!pat || !*pat)
X					{
X					zerr("oh dear.  that CAN'T be right.",NULL,0);
X					return 0;
X					}
X				if (*pat == Outbrack)
X					break;
X				for (pptr++; *pat != Outbrack; pat++);
X				pat++;
X				continue;
X				}
X		if (*pat == Inang)
X			{
X			int t1,t2,t3;
X			char *ptr;
X
X			if (*++pat == Outang)	/* handle <> case */
X				{
X				( void ) zstrtol(pptr,&ptr,10);
X				if (ptr == pptr)
X					break;
X				pptr = ptr;
X				pat++;
X				}
X			else
X				{
X				t1 = zstrtol(pptr,&ptr,10);
X				if (ptr == pptr)
X					break;
X				pptr = ptr;
X				t2 = zstrtol(pat,&ptr,10);
X				if (*ptr != '-')
X					exit(31);
X				t3 = zstrtol(ptr+1,&pat,10);
X				if (!t3)
X					t3 = INT_MAX;
X				if (*pat++ != Outang)
X					exit(21);
X				if (t1 < t2 || t1 > t3)
X					break;
X				}
X			continue;
X			}
X		if (*pptr == *pat)
X			{
X			pptr++;
X			pat++;
X			continue;
X			}
X		break;
X		}
X	return 0;
X}
X
XComplist parsepat(str) /**/
Xchar *str;
X{
X	mode = 0;
X	pptr = str;
X	return parsecomplist();
X}
X
XComp parsereg(str) /**/
Xchar *str;
X{
X	mode = 1;
X	pptr = str;
X	return parsecompsw();
X}
X
XComplist parsecomplist() /**/
X{
XComp c1;
XComplist p1;
X
X	if (pptr[0] == '.' && pptr[1] == '.' && pptr[2] == '.' && pptr[3] ==
X			'.' && pptr[4] == '/')
X		{
X		pptr[0] = Inpar;
X		pptr[1] = Star;
X		pptr[2] = '/';
X		pptr[3] = Outpar;
X		pptr[4] = Pound;	/* "..../" -> "( * /)#" */
X		}
X	if (*pptr == Inpar)
X		{
X		char *str;
X		int pars = 1;
X
X		for (str = pptr+1; *str && pars; str++)
X			if (*str == Inpar)
X				pars++;
X			else if (*str == Outpar)
X				pars--;
X		if (str[0] != Pound || str[-1] != Outpar || str[-2] != '/')
X			goto kludge;
X		pptr++;
X		if (!(c1 = parsecompsw()))
X			return NULL;
X		if (pptr[0] == '/' && pptr[1] == Outpar && pptr[2] == Pound)
X			{
X			int pdflag = 0;
X
X			pptr += 3;
X			if (*pptr == Pound)
X				{
X				pdflag = 1;
X				pptr++;
X				}
X			p1 = (Complist) alloc(sizeof *p1);
X			p1->comp = c1;
X			p1->closure = 1+pdflag;
X			p1->next = parsecomplist();
X			return (p1->comp) ? p1 : NULL;
X			}
X		}
X	else
X		{
Xkludge:
X		if (!(c1 = parsecompsw()))
X			return NULL;
X		if (*pptr == '/' || !*pptr)
X			{
X			int ef = *pptr == '/';
X
X			p1 = (Complist) alloc(sizeof *p1);
X			p1->comp = c1;
X			p1->closure = 0;
X			p1->next = (*pptr == '/') ? (pptr++,parsecomplist()) : NULL;
X			return (ef && !p1->next) ? NULL : p1;
X			}
X		}
X	errflag = 1;
X	return NULL;
X}
X
XComp parsecomp() /**/
X{
XComp c = (Comp) alloc(sizeof *c),c1,c2;
Xchar *s = c->str = alloc(MAXPATHLEN*2),*ls = NULL;
X
X	while (*pptr && (mode || *pptr != '/') && *pptr != Bar &&
X			*pptr != Outpar)
X		{
X		if (*pptr == Hat)
X			{
X			*s++ = Hat;
X			*s++ = '\0';
X			pptr++;
X			if (!(c->next = parsecomp()))
X				return NULL;
X			return c;
X			}
X		if (*pptr == Star && pptr[1] && (mode || pptr[1] != '/'))
X			{
X			*s++ = '\0';
X			pptr++;
X			c1 = (Comp) alloc(sizeof *c1);
X			*(c1->str = strdup("?")) = Quest;
X			c1->closure = 1;
X			c2 = parsecomp();
X			c1->next = c2;
X			c->next = c1;
X			return c;
X			}
X		if (*pptr == Inpar)
X			{
X			*s++ = '\0';
X			pptr++;
X			c->next = (Comp) alloc(sizeof *c);
X			c->next->left = c1 = parsecompsw();
X			if (*pptr != Outpar)
X				{
X				errflag = 1;
X				return NULL;
X				}
X			pptr++;
X			if (*pptr == Pound)
X				{
X				int dpnd = 1;
X
X				pptr++;
X				if (*pptr == Pound)
X					{
X					pptr++;
X					dpnd = 2;
X					}
X				c->next->closure = dpnd;
X				}
X			c2 = parsecomp();
X			if (!c2)
X				return NULL;
X			c->next->next = c2;
X			return c;
X			}
X		if (*pptr == Pound)
X			{
X			*s = '\0';
X			pptr++;
X			if (!ls)
X				return NULL;
X			c->next = c1 = (Comp) alloc(sizeof *c);
X			c1->str = strdup(ls);
X			c1->closure = 1;
X			c1->next = parsecomp();
X			if (!c1->next)
X				return NULL;
X			*ls++ = '\0';
X			return c;
X			}
X		ls = s;
X		if (*pptr == Inang)
X			{
X			int dshct;
X
X			dshct = (pptr[1] == Outang);
X			*s++ = *pptr++;
X			while (*pptr && (*s++ = *pptr++) != Outang)
X				if (s[-1] == '-')
X					dshct++;
X				else if (!idigit(s[-1]))
X					break;
X			if (s[-1] != Outang || dshct != 1)
X				return NULL;
X			}
X		else if (*pptr == Inbrack)
X			{
X			while (*pptr && (*s++ = *pptr++) != Outbrack);
X			if (s[-1] != Outbrack)
X				return NULL;
X			}
X		else if (itok(*pptr) && *pptr != Star && *pptr != Quest)
X			*s++ = ztokens[*pptr++-Pound];
X		else
X			*s++ = *pptr++;
X		}
X	if (*pptr == '/' || !*pptr)
X		c->last = 1;
X	*s++ = '\0';
X	return c;
X}
X
XComp parsecompsw() /**/
X{
XComp c1,c2,c3;
X
X	c1 = parsecomp();
X	if (!c1)
X		return NULL;
X	if (*pptr == Bar)
X		{
X		c2 = (Comp) alloc(sizeof *c2);
X		pptr++;
X		c3 = parsecompsw();
X		if (!c3)
X			return NULL;
X		c2->str = strdup("");
X		c2->left = c1;
X		c2->right = c3;
X		return c2;
X		}
X	return c1;
X}
X
X/* tokenize and see if ss matches tt */
X
Xint patmatch(ss,tt) /**/
Xchar *ss;char *tt;
X{
Xchar *s = ss,*t;
X
X	for (; *s; s++)
X		if (*s == '\\')
X			chuck(s);
X		else
X			for (t = ztokens; *t; t++)
X				if (*t == *s)
X					{
X					*s = (t-ztokens)+Pound;
X					break;
X					}
X	return matchpat(ss,tt);
X}
X
X/* remove unnecessary Nulargs */
X
Xvoid remnulargs(s) /**/
Xchar *s;
X{
Xint nl = *s;
Xchar *t = s;
X
X	while (*s)
X		if (*s == Nularg)
X			chuck(s);
X		else
X			s++;
X	if (!*t && nl)
X		{
X		t[0] = Nularg;
X		t[1] = '\0';
X		}
X}
X
X/* qualifier functions */
X
Xint qualdev(buf,dv) /**/
Xstruct stat *buf;long dv;
X{
X	return buf->st_dev == dv;
X}
X
Xint qualnlink(buf,ct) /**/
Xstruct stat *buf;long ct;
X{
X	return buf->st_nlink == ct;
X}
X
Xint qualuid(buf,uid) /**/
Xstruct stat *buf;long uid;
X{
X	return buf->st_uid == uid;
X}
X
Xint qualgid(buf,gid) /**/
Xstruct stat *buf;long gid;
X{
X	return buf->st_gid == gid;
X}
X
Xint qualisdev(buf,junk) /**/
Xstruct stat *buf;long junk;
X{
X	junk = buf->st_mode & S_IFMT;
X	return junk == S_IFBLK || junk == S_IFCHR;
X}
X
Xint qualmode(buf,mod) /**/
Xstruct stat *buf;long mod;
X{
X	return (buf->st_mode & S_IFMT) == mod;
X}
X
Xint qualflags(buf,mod) /**/
Xstruct stat *buf;long mod;
X{
X	return buf->st_mode & mod;
X}
SHAR_EOF
echo 'File zsh2.00/src/glob.c is complete' &&
chmod 0644 zsh2.00/src/glob.c ||
echo 'restore of zsh2.00/src/glob.c failed'
Wc_c="`wc -c < 'zsh2.00/src/glob.c'`"
test 21953 -eq "$Wc_c" ||
	echo 'zsh2.00/src/glob.c: original size 21953, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.00/src/glob.pro ==============
if test -f 'zsh2.00/src/glob.pro' -a X"$1" != X"-c"; then
	echo 'x - skipping zsh2.00/src/glob.pro (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting zsh2.00/src/glob.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.00/src/glob.pro' &&
Xvoid glob DCLPROTO((Lklist list,Lknode *np));
Xlong qgetnum DCLPROTO((char **s));
Xint notstrcmp DCLPROTO((char **a,char **b));
Xint forstrcmp DCLPROTO((char **a,char **b));
Xvoid insert DCLPROTO((char *s));
Xint haswilds DCLPROTO((char *str));
Xint hasbraces DCLPROTO((char *str));
Xint xpandredir DCLPROTO((struct redir *fn,Lklist tab));
Xchar *dyncat DCLPROTO((char *s1,char *s2));
Xchar *tricat DCLPROTO((char *s1,char *s2,char *s3));
Xvoid xpandbraces DCLPROTO((Lklist list,Lknode *np));
Xchar *getparen DCLPROTO((char *str));
Xint matchpat DCLPROTO((char *a,char *b));
Xvoid getmatch DCLPROTO((char **sp,char *pat,int dd));
Xvoid addpath DCLPROTO((char *s));
Xchar *getfullpath DCLPROTO((char *s));
Xvoid scanner DCLPROTO((Complist q));
Xint minimatch DCLPROTO((char **pat,char **str));
Xint domatch DCLPROTO((char *str,Comp c,int fist));
Xint doesmatch DCLPROTO((Comp c));
XComplist parsepat DCLPROTO((char *str));
XComp parsereg DCLPROTO((char *str));
XComplist parsecomplist DCLPROTO((void));
XComp parsecomp DCLPROTO((void));
XComp parsecompsw DCLPROTO((void));
Xint patmatch DCLPROTO((char *ss,char *tt));
Xvoid remnulargs DCLPROTO((char *s));
Xint qualdev DCLPROTO((struct stat *buf,long dv));
Xint qualnlink DCLPROTO((struct stat *buf,long ct));
Xint qualuid DCLPROTO((struct stat *buf,long uid));
Xint qualgid DCLPROTO((struct stat *buf,long gid));
Xint qualisdev DCLPROTO((struct stat *buf,long junk));
Xint qualmode DCLPROTO((struct stat *buf,long mod));
Xint qualflags DCLPROTO((struct stat *buf,long mod));
SHAR_EOF
chmod 0644 zsh2.00/src/glob.pro ||
echo 'restore of zsh2.00/src/glob.pro failed'
Wc_c="`wc -c < 'zsh2.00/src/glob.pro'`"
test 1492 -eq "$Wc_c" ||
	echo 'zsh2.00/src/glob.pro: original size 1492, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.00/src/hist.c ==============
if test -f 'zsh2.00/src/hist.c' -a X"$1" != X"-c"; then
	echo 'x - skipping zsh2.00/src/hist.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting zsh2.00/src/hist.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.00/src/hist.c' &&
X/*
X
X	hist.c - history expansion
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#include "funcs.h"
X
Xstatic int lastc;
X
X/* add a character to the current history word */
X
Xvoid hwaddc(c) /**/
Xint c;
X{
X	if (hlastw && hline && (!errflag || c == HISTSPACE))
X		{
X		if (c == EOF || c == HERR)
X			c = ' ';
X		*hptr++ = c;
X		if (hptr-hline >= hlinesz)
X			{
X			int ll,flag = 0;
X
X			ll = hptr-hlastw;
X			if (full(histlist) && getdata(lastnode(histlist)) == hline)
X				flag = 1;
X			hline = realloc(hline,hlinesz *= 4);
X			if (flag)
X				setdata(lastnode(histlist),hline);
X			hptr = hline+(hlinesz/4);
X			hlastw = hptr-ll;
X			}
X		}
X}
X
X#define habort() { errflag = 1; return HERR; }
X
X/* get a character after performing history substitution */
X
Xint hgetc() /**/
X{
Xint c,ev,farg,larg,argc,marg = -1,cflag = 0,bflag = 0;
Xchar buf[256],*ptr;
Xchar *sline,*eline;
X
Xtailrec:
X	c = hgetch();
X	if (stophist)
X		{
X		hwaddc(c);
X		return c;
X		}
X	if (isfirstch && c == hatchar)
X		{
X		isfirstch = 0;
X		hungets(":s^");
X		c = bangchar;
X		goto hatskip;
X		}
X	if (c != ' ')
X		isfirstch = 0;
X	if (c == '\\')
X		{
X		int g = hgetch();
X		
X		if (g != bangchar)
X			hungetch(g);
X		else
X			{
X			hwaddc(bangchar);
X			return bangchar;
X			}
X		}
X	if (c != bangchar)
X		{
X		hwaddc(c);
X		return c;
X		}
Xhatskip:
X	*hptr = '\0';
X	if ((c = hgetch()) == '{')
X		{
X			bflag = cflag = 1;
X			c = hgetch();
X			}
X		if (c == '\"')
X			{
X			stophist = 1;
X			goto tailrec;
X			}
X		if (!cflag && inblank(c) || c == '=' || c == '(' || c == EOF)
X			{
X			hungetch(c);
X			hwaddc(bangchar);
X			return bangchar;
X			}
X		cflag = 0;
X		ptr = buf;
X
X		/* get event number */
X
X		if (c == '?')
X			{
X			for(;;)
X				{
X				c = hgetch();
X				if (c == '?' || c == '\n' || c == -1)
X					break;
X				else
X					*ptr++ = c;
X				}
X			if (c != '\n' && c != -1)
X				c = hgetch();
X			*ptr = '\0';
X			ev = hconsearch(hsubl = ztrdup(buf),&marg);
X			if (ev == -1)
X				{
X				herrflush();
X				zerr("no such event: %s",buf,0);
X				habort();
X				}
X			}
X		else
X			{
X			int t0;
X	 
X			for (;;)
X				{
X				if (inblank(c) || c == ':' || c == '^' || c == '$' || c == '*'
X						|| c == '%' || c == '}' || c == -1)
X					break;
X				if (ptr != buf && c == '-')
X					break;
X				*ptr++ = c;
X				if (c == '#' || c == '!')
X					{
X					c = hgetch();
X					break;
X					}
X				c = hgetch();
X				}
X			*ptr = 0;
X			if (!*buf)
X				ev = defev;
X			else if (t0 = atoi(buf))
X				ev = (t0 < 0) ? curhist+t0 : t0;
X			else if (*buf == '!')
X				ev = curhist-1;
X			else if (*buf == '#')
X				ev = curhist;
X			else if ((ev = hcomsearch(buf)) == -1)
X				{
X				zerr("event not found: %s",buf,0);
X				while (c != '\n' && c != -1)
X					c = hgetch();
X				habort();
X				}
X			}
X
X		/* get the event */
X
X		if (!(eline = getevent(defev = ev)))
X			habort();
X
X		/* extract the relevant arguments */
X
X		argc = getargc(eline);
X		if (c == ':')
X			{
X			cflag = 1;
X			c = hgetch();
X			}
X		if (c == '*')
X			{
X			farg = 1;
X			larg = argc;
X			cflag = 0;
X			}
X		else
X			{
X			hungetch(c);
X			larg = farg = getargspec(argc,marg);
X			if (larg == -2)
X				habort();
X			if (farg != -1)
X				cflag = 0;
X			c = hgetch();
X			if (c == '*')
X				{
X				cflag = 0;
X				larg = argc;
X				}
X			else if (c == '-')
X				{
X				cflag = 0;
X				larg = getargspec(argc,marg);
X				if (larg == -2)
X					habort();
X				if (larg == -1)
X					larg = argc-1;
X				}
X			else
X				hungetch(c);
X			}
X		if (farg == -1)
X			farg = 0;
X		if (larg == -1)
X			larg = argc;
X		if (!(sline = getargs(eline,farg,larg)))
X			habort();
X
X		/* do the modifiers */
X
X		for(;;)
X			{
X			c = (cflag) ? ':' : hgetch();
X			cflag = 0;
X			if (c == ':')
X				{
X				int gbal = 0;
X			
X				if ((c = hgetch()) == 'g')
X					{
X					gbal = 1;
X					c = hgetch();
X					}
X				switch(c)
X					{
X					case 'p':
X						histdone = 2;
X						break;
X					case 'h':
X						if (!remtpath(&sline))
X							{
X							herrflush();
X							zerr("modifier failed: h",NULL,0);
X							habort();
X							}
X						break;
X					case 'e':
X						if (!rembutext(&sline))
X							{
X							herrflush();
X							zerr("modifier failed: e",NULL,0);
X							habort();
X							}
X						break;
X					case 'r':
X						if (!remtext(&sline))
X							{
X							herrflush();
X							zerr("modifier failed: r",NULL,0);
X							habort();
X							}
X						break;
X					case 't':
X						if (!remlpaths(&sline))
X							{
X							herrflush();
X							zerr("modifier failed: t",NULL,0);
X							habort();
X							}
X						break;
X					case 's':
X						{
X						int del;
X						char *ptr1,*ptr2;
X					
X						del = hgetch();
X						ptr1 = hdynread(del);
X						if (!ptr1)
X							habort();
X						ptr2 = hdynread2(del);
X						if (strlen(ptr1))
X							{
X							if (hsubl)
X								free(hsubl);
X							hsubl = ptr1;
X							}
X						if (hsubr)
X							free(hsubr);
X						hsubr = ptr2;
X						}
X					case '&':
X						if (hsubl && hsubr)
X							{
X							if (subst(&sline,hsubl,hsubr,gbal))
X								habort();
X							}
X						else
X							{
X							herrflush();
X							zerr("no previous substitution with &",NULL,0);
X							habort();
X							}
X						break;
X					case 'q':
X						quote(&sline);
X						break;
X					case 'x':
X						quotebreak(&sline);
X						break;
X					case 'l':
X						downcase(&sline);
X						break;
X					case 'u':
X						upcase(&sline);
X						break;
X					default:
X						herrflush();
X						zerr("illegal modifier: %c",NULL,c);
X					habort();
X					break;
X				}
X			}
X		else
X			{
X			if (c != '}' || !bflag)
X				hungetch(c);
X			if (c != '}' && bflag)
X				{
X				zerr("'}' expected",NULL,0);
X				habort();
X				}
X			break;
X			}
X		}
X	
X	/* stuff the resulting string in the input queue and start over */
X
X	if (alstackind != MAXAL)
X		{
X		hungets(HISTMARK);
X		alstack[alstackind++] = NULL;
X		}
X	hungets(sline);
X	histdone |= 1;
X	goto tailrec;
X}
X
X/* get a character without history expansion */
X
Xint hgetch() /**/
X{
Xchar *line,*pmpt,*pmpt2 = NULL;
Xint plen;
X
Xstart:
X	if (inbufct)
X		{
X		inbufct--;
X		if ((lastc = *inbufptr++) == ALPOP)
X			{
X			Alias ix;
X			char *t;
X
X			if (!alstackind)
X				{
X				zerr("alias stack underflow",NULL,0);
X				return lastc = HERR;
X				}
X			ix = alstack[--alstackind];
X			if (ix)
X				{
X				ix->inuse = 0;
X				t = ix->text;
X				if (*t && t[strlen(t)-1] == ' ')
X					alstat = ALSTAT_MORE;
X				else
X					alstat = ALSTAT_JUNK;
X				}
X			goto start;
X			}
X		return lastc;
X		}
X	if (strin)
X		return lastc = EOF;
X	if (errflag)
X		return lastc = HERR;
X	if (interact && isset(SHINSTDIN))
X		if (!isfirstln)
X			pmpt = putprompt(prompt2,&plen);
X		else
X			{
X			int foo;
X
X			pmpt = putprompt(prompt,&plen);
X			pmpt2 = (rprompt) ? putprompt(rprompt,&foo) : NULL;
X			}
X	if (!(interact && isset(SHINSTDIN) && SHTTY != -1) || unset(USEZLE))
X		{
X		if (interact && isset(SHINSTDIN))
X			write(2,pmpt,strlen(pmpt));
X		line = fgets(zalloc(256),256,bshin);
X		}
X	else
X		line = zleread(pmpt,pmpt2,plen);
X	if (!line)
X		return lastc = EOF;
X	if (interact && isset(SHINSTDIN))
X		{
X		char *s = getdata(lastnode(lithistlist));
X
X		if (!*s)
X			{
X			free(s);
X			setdata(lastnode(lithistlist),ztrdup(line));
X			}
X		else
X			{
X			char *t = zalloc(strlen(s)+strlen(line)+3);
X
X			strcpy(t,s);
X			strcat(t,line);
X			free(s);
X			setdata(lastnode(lithistlist),t);
X			}
X		}
X	if (isfirstln)
X		spaceflag = *line == ' ';
X	if (isset(VERBOSE))
X		{
X		fputs(line,stderr);
X		fflush(stderr);
X		}
X	if (line[strlen(line)-1] == '\n')
X		{
X		lineno++;
X		if (interact && isset(SUNKEYBOARDHACK) && isset(SHINSTDIN) && 
X				SHTTY != -1 && *line && line[1] && line[strlen(line)-2] == '`')
X			{
X			int ct;
X			char *ptr;
X
X			for (ct = 0, ptr = line; *ptr; ptr++)
X				if (*ptr == '`')
X					ct++;
X			if (ct & 1)
X				{
X				ptr[-2] = '\n';
X				ptr[-1] = '\0';
X				}
X			}
X		}
X	isfirstch = 1;
X	hungets(line);
X	free(line);
X	goto start;
X}
X
X/* put a string in the input queue */
X
Xvoid hungets(str) /**/
Xchar *str;
X{
Xint slen = strlen(str);
X
X/* shrink inbuf if it gets too big */
X
X	if (!inbufct && inbufsz > 65536)
X		{
X		free(inbuf);
X		inbuf = zalloc(inbufsz = 256);
X		inbufptr = inbuf+inbufsz;
X		inbufct = 0;
X		}
X	if (slen+inbufct > inbufsz)
X		{
X		char *x;
X
X		while (slen+inbufct > inbufsz)
X			inbufsz *= 4;
X		x = zalloc(inbufsz);
X		memcpy(x+inbufsz-inbufct,inbufptr,inbufct);
X		inbufptr = x+inbufsz-inbufct;
X		free(inbuf);
X		inbuf = x;
X		}
X	memcpy(inbufptr -= slen,str,slen);
X	inbufct += slen;
X}
X
X/* unget a char and remove it from hline */
X
Xvoid hungetc(c) /**/
Xint c;
X{
X	if (c == -1)
X		return;
X	if (hlastw)
X		{
X		if (hlastw == hptr)
X			zerr("hungetc attempted at buffer start",NULL,0);
X		else
X			hptr--;
X		}
X	hungetch(c);
X}
X
Xvoid hungetch(c) /**/
Xint c;
X{
X	if (c == -1)
X		return;
X	if (inbufct == inbufsz)
X		{
X		hungets(" ");
X		*inbufptr = c;
X		}
X	else
X		{
X		*--inbufptr = c;
X		inbufct++;
X		}
X}
X
X/* begin reading a string */
X
Xvoid strinbeg() /**/
X{
X	strin = 1;
X	hbegin();
X}
X
X/* done reading a string */
X
Xvoid strinend() /**/
X{
X	strin = 0;
X	isfirstch = 1;
X	histdone = 0;
X	hend();
X}
X
X/* stuff a whole file into the input queue and print it */
X
Xint stuff(fn) /**/
Xchar *fn;
X{
XFILE *in;
Xchar *buf;
Xint len;
X
X	if (!(in = fopen(fn,"r")))
X		{
X		zerr("can't open %s",fn,0);
X		return 1;
X		}
X	fseek(in,0,2);
X	len = ftell(in);
X	fseek(in,0,0);
X	buf = alloc(len+1);
X	if (!(fread(buf,len,1,in)))
X		{
X		zerr("read error on %s",fn,0);
X		fclose(in);
X		free(buf);
X		return 1;
X		}
X	fclose(in);
X	buf[len] = '\0';
X	fwrite(buf,len,1,stdout);
X	hungets(buf);
X	return 0;
X}
X
X/* flush input queue */
X
Xvoid hflush() /**/
X{
X	inbufptr += inbufct;
X	inbufct = 0;
X}
X
X/* initialize the history mechanism */
X
Xvoid hbegin() /**/
X{
X	isfirstln = isfirstch = 1;
X	histremmed = errflag = histdone = spaceflag = 0;
X	stophist = isset(NOBANGHIST);
X	lithist = isset(HISTLIT);
X	hline = hptr = zalloc(hlinesz = 32);
X	if (interact && isset(SHINSTDIN) && !strin)
X		{
X		inittty();
X		defev = curhist++;
X		while (curhist-firsthist >= histsiz)
X			{
X			free(getnode(histlist));
X			firsthist++;
X			}
X		while (curhist-firstlithist >= lithistsiz)
X			{
X			free(getnode(lithistlist));
X			firstlithist++;
X			}
X		permalloc();
X		addnode(histlist,hline);
X		addnode(lithistlist,ztrdup(""));
X		heapalloc();
X		}
X	else
X		histremmed = 1;
X}
X
Xvoid inittty() /**/
X{
X	attachtty(mypgrp);
X	settyinfo(&shttyinfo);
X}
X
X/* say we're done using the history mechanism */
X
Xint hend() /**/
X{
Xint flag,save = 1;
X
X	if (!hline)
X		return 1;
X	if (!interact || strin || unset(SHINSTDIN))
X		{
X		free(hline);
X		return 1;
X		}
X	flag = histdone;
X	histdone = 0;
X	if (hptr < hline+2)
X		save = 0;
X	else
X		{
X		char *s = getdata(lastnode(lithistlist));
X
X		if (*s)
X			s[strlen(s)-1] = '\0';
X		hptr[-1] = '\0';
X		if (hptr[-2] == '\n')
X			if (hline[1])
X				hptr[-3] = '\0';
X			else
X				save = 0;
X		if (!strcmp(hline,"\n") ||
X				(isset(HISTIGNOREDUPS) && firstnode(histlist) &&
X				nextnode(firstnode(histlist)) &&
X				!strcmp(hline,getdata(prevnode(lastnode(histlist))))) ||
X				(isset(HISTIGNORESPACE) && spaceflag) )
X			save = 0;
X		}
X	if (!save)
X		{
X		free(hline);
X		if (!histremmed)
X			{
X			remnode(histlist,lastnode(histlist));
X			free(remnode(lithistlist,lastnode(lithistlist)));
X			curhist--;
X			}
X		flag = 0;
X		}
X	if (flag)
X		{
X		char *ptr,*p;
X
X		p = ptr = ztrdup(hline);
X		for (;*p;p++)
X			if (*p == HISTSPACE)
X				*p = ' ';
X		fprintf(stderr,"%s\n",ptr);
X		fflush(stderr);
X		free(ptr);
X		}
X	hline = NULL;
X	return !(flag & 2 || errflag);
X}
X
X/* remove the current line from the history List */
X
Xvoid remhist() /**/
X{
X	if (!histremmed)
X		{
X		histremmed = 1;
X		free(remnode(histlist,lastnode(histlist)));
X		free(remnode(lithistlist,lastnode(lithistlist)));
X		curhist--;
X		}
X}
X
X/* begin a word */
X
Xvoid hwbegin() /**/
X{
X	hlastw = hptr;
X}
X
X/* add a word to the history List */
X
Xchar *hwadd() /**/
X{
Xchar *ret = hlastw;
X
X	if (hlastw && hline)
X		{
X		hwaddc(HISTSPACE);
X		if (alstackind || strin)
X			if (!(alstackind == 1 && !alstack[0]))
X				hptr = hlastw;
X		}
X	if (alstat == ALSTAT_JUNK)
X		alstat = 0;
X	return ret;
X}
X
X/* get an argument specification */
X
Xint getargspec(argc,marg) /**/
Xint argc;int marg;
X{
Xint c,ret = -1;
X 
X	if ((c = hgetch()) == '0')
X		return 0;
X	if (idigit(c))
X		{
X		ret = 0;
X		while (idigit(c))
X			{
X			ret = ret*10+c-'0';
X			c = hgetch();
X			}
X		hungetch(c);
X		}
X	else if (c == '^')
X		ret = 1;
X	else if (c == '$')
X		ret = argc;
X	else if (c == '%')
X		{
X		if (marg == -1)
X			{
X			herrflush();
X			zerr("%% with no previous word matched",NULL,0);
X			return -2;
X			}
X		ret = marg;
X		}
X	else
X		hungetch(c);
X	return ret;
X}
X
X/* do ?foo? search */
X
Xint hconsearch(str,marg) /**/
Xchar *str;int *marg;
X{
Xint t0,t1 = 0;
XLknode node;
Xchar *s;
X 
X	if (curhist-firsthist < 1)
X		return -1;
X	for (t0 = curhist-1,node = prevnode(lastnode(histlist));
X			t0 >= firsthist; t0--,node = prevnode(node))
X		if (s = strstr(getdata(node),str))
X			{
X			while (s != (char *) getdata(node))
X				if (*s-- == HISTSPACE)
X					t1++;
X			*marg = t1;
X			return t0;
X			}
X	return -1;
X}
X
X/* do !foo search */
X
Xint hcomsearch(str) /**/
Xchar *str;
X{
Xint t0;
XLknode node;
Xchar *s,*t;
X
X	if (curhist-firsthist < 1)
X		return -1;
X	for (t0 = curhist-1,node = prevnode(lastnode(histlist)); t0 >= firsthist;
X			t0--,node = prevnode(node))
X		{
X		for (s = getdata(node); *s; s++)
X			if (*s == HISTSPACE)
X				break;
X		t = strstr(getdata(node),str);
X		if (t && t < s)
X			return t0;
X		}
X	return -1;
X}
X
X/* various utilities for : modifiers */
X
Xint remtpath(junkptr) /**/
Xchar **junkptr;
X{
Xchar *str = *junkptr,*cut;
X 
X	if (cut = strrchr(str,'/'))
X		{
X		*cut = '\0';
X		return 1;
X		}
X	return 0;
X}
X 
Xint remtext(junkptr) /**/
Xchar **junkptr;
X{
Xchar *str = *junkptr,*cut;
X 
X	if ((cut = strrchr(str,'.')) && cut != str)
X		{
X		*cut = '\0';
X		return 1;
X		}
X	return 0;
X}
X 
Xint rembutext(junkptr) /**/
Xchar **junkptr;
X{
Xchar *str = *junkptr,*cut;
X 
X	if ((cut = strrchr(str,'.')) && cut != str)
X		{
X		*junkptr = strdup(cut+1);  /* .xx or xx? */
X		return 1;
X		}
X	return 0;
X}
X 
Xint remlpaths(junkptr) /**/
Xchar **junkptr;
X{
Xchar *str = *junkptr,*cut;
X 
X	if (cut = strrchr(str,'/'))
X		{
X		*cut = '\0';
X		*junkptr = strdup(cut+1);
X		return 1;
X		}
X	return 0;
X}
X
Xint makeuppercase(junkptr) /**/
Xchar **junkptr;
X{
Xchar *str = *junkptr;
X
X	for (; *str; str++)
X		*str = toupper(*str);
X	return 1;
X}
X
Xint makelowercase(junkptr) /**/
Xchar **junkptr;
X{
Xchar *str = *junkptr;
X
X	for (; *str; str++)
X		*str = tolower(*str);
X	return 1;
X}
X
Xint subst(strptr,in,out,gbal) /**/
Xchar **strptr;char *in;char *out;int gbal;
X{
Xchar *str = *strptr,*cut,*sptr;
Xint ret = 0,off;
X
Xconsidered_harmful:
X	if (cut = (char *) strstr(str,in))
X		{
X		*cut = '\0';
X		cut += strlen(in);
X		off = cut-*strptr;
X		*strptr = tricat(*strptr,sptr = convamps(out,in),cut);
X		if (gbal)
X			{
X			str = (char *) *strptr+off+strlen(sptr);
X			ret = 1;
X			goto considered_harmful;
X			}
X		return 0;
X		}
X	if (!ret)
X		{
X		herrflush();
X		zerr("string not found: %s",in,0);
X		return 1;
X		}
X	return 0;
X}
X 
Xchar *convamps(out,in) /**/
Xchar *out;char *in;
X{
Xchar *ptr,*ret,*pp;
Xint slen,inlen = strlen(in);
X 
X	for (ptr = out, slen = 0; *ptr; ptr++,slen++)
X		if (*ptr == '\\')
X			ptr++;
X		else if (*ptr == '&')
X			slen += inlen-1;
X	ret = pp = alloc(slen+1);
X	for (ptr = out; *ptr; ptr++)
X		if (*ptr == '\\')
X			*pp++ = *++ptr;
X		else if (*ptr == '&')
X			{
X			strcpy(pp,in);
X			pp += inlen;
X			}
X		else
X			*pp++ = *ptr;
X	*pp = '\0';
X	return ret;
X}
X
Xchar *makehstr(s) /**/
Xchar *s;
X{
Xchar *t;
X
X	t = s = strdup(s);
X	for (; *t; t++)
X		if (*t == HISTSPACE)
X			*t = ' ';
X	return s;
X}
X
Xchar *quietgetevent(ev) /**/
Xint ev;
X{
XLknode node;
X 
X	ev -= (lithist) ? firstlithist : firsthist;
X	if (ev < 0)
X		return NULL;
X	for (node = firstnode((lithist) ? lithistlist : histlist);
X			ev && node; incnode(node), ev--);
X	if (!node)
X		return NULL;
X	return getdata(node);
X}
X
Xchar *getevent(ev) /**/
Xint ev;
X{
XLknode node;
Xint oev = ev;
X 
X	ev -= firsthist;
X	for (node = firstnode(histlist); ev && node; incnode(node), ev--);
X	if (!node)
X		{
X		herrflush();
X		zerr("no such event: %d",NULL,oev);
X		return NULL;
X		}
X	return getdata(node);
X}
X 
Xint getargc(list) /**/
Xchar *list;
X{
Xint argc = 0;
X
X	for (; *list; list++)
X		if (*list == HISTSPACE)
X			argc++;
X	return argc;
X}
X 
Xchar *getargs(elist,arg1,arg2) /**/
Xchar *elist;int arg1;int arg2;
X{
Xchar *ret = elist,*retn;
Xint acnt = arg2-arg1+1;
X
X	while (arg1--)
X		while (*ret && *ret++ != HISTSPACE);
X	if (!*ret)
X		{
X		herrflush();
X		zerr("no such word in event",NULL,0);
X		return NULL;
X		}
X	retn = ret = strdup(ret);
X	while (acnt > 0)
X		{
X		while (*ret && *ret != HISTSPACE)
X			ret++;
X		if (*ret == HISTSPACE)
X			*ret = ' ';
X		else
X			break;
X		acnt--;
X		}
X	if (acnt > 1 && !*ret)
X		{
X		herrflush();
X		zerr("no such word in event",NULL,0);
X		return NULL;
X		}
X	*ret = '\0';
X	return retn;
X}
X
Xvoid upcase(x) /**/
Xchar **x;
X{
Xchar *pp = *(char **) x;
X
X	for (; *pp; pp++)
X		*pp = toupper(*pp);
X}
X
Xvoid downcase(x) /**/
Xchar **x;
X{
Xchar *pp = *(char **) x;
X
X	for (; *pp; pp++)
X		*pp = tolower(*pp);
X}
X
Xint quote(tr) /**/
Xchar **tr;
X{
Xchar *ptr,*rptr,**str = (char **) tr;
Xint len = 1;
X 
X	for (ptr = *str; *ptr; ptr++,len++)
X		if (*ptr == '\'')
X			len += 3;
X	ptr = *str;
X	*str = rptr = zalloc(len);
X	for (ptr = *str; *ptr; )
X		if (*ptr == '\'')
X			{
X			*rptr++ = '\''; *rptr++ = '\\'; *rptr++ = '\''; *rptr++ = '\'';
X			ptr++;
X			}
X		else
X			*rptr++ = *ptr++;
X	return 0;
X}
X 
Xint quotebreak(tr) /**/
Xchar **tr;
X{
Xchar *ptr,*rptr,**str = (char **) tr;
Xint len = 1;
X 
X	for (ptr = *str; *ptr; ptr++,len++)
X		if (*ptr == '\'')
X			len += 3;
X		else if (inblank(*ptr))
X			len += 2;
X	ptr = *str;
X	*str = rptr = zalloc(len);
X	for (ptr = *str; *ptr; )
X		if (*ptr == '\'')
X			{
X			*rptr++ = '\''; *rptr++ = '\\'; *rptr++ = '\''; *rptr++ = '\'';
X			ptr++;
X			}
X		else if (inblank(*ptr))
X			{
X			*rptr++ = '\''; *rptr++ = *ptr++; *rptr++ = '\'';
X			}
X		else
X			*rptr++ = *ptr++;
X	return 0;
X}
X
Xstatic char *bp;
Xstatic int lensb;
X
Xvoid stradd(d) /**/
Xchar *d;
X{
X	while (*bp++ = *d++);
X	bp--;
X}
X
Xint putstr(d) /**/
Xint d;
X{
X	*bp++ = d;
X	lensb++; return 0;
X}
X
X#define tstradd(X) \
X	if (termok && unset(SINGLELINEZLE)) { \
X		char tbuf[2048],*tptr = tbuf; \
X		if (tgetstr(X,&tptr)) \
X			tputs(tbuf,1,putstr); \
X	} \
X	break
X
X/* get a prompt string */
X
Xchar *putprompt(fm,lenp) /**/
Xchar *fm;int *lenp;
X{
Xchar *ss,*ttyname DCLPROTO((int)),*bl0;
Xstatic char buf1[256],buf2[256],*buf;
Xint t0;
Xstruct tm *tm = NULL;
Xtime_t timet;
X
X	lensb = 0;
X	if (!fm)
X		{
X		*lenp = 0;
X		return "";
X		}
X	/* kludge alert! */
X	buf = (buf == buf1) ? buf2 : buf1;
X	bp = bl0 = buf;
X	clearerr(stdin);
X	for(;*fm;fm++)
X		{
X		if (bp-buf >= 220)
X			break;
X		if (*fm == '%')
X			switch (*++fm)
X				{
X				case '~':
X					t0 = finddir(cwd);
X					if (t0 != -1)
X						{
X						*bp++ = '~';
X						stradd(usernames[t0]);
X						stradd(cwd+strlen(userdirs[t0]));
X						break;
X						}
X					if (!strncmp(cwd,home,t0 = strlen(home)))
X						{
X						*bp++ = '~';
X						stradd(cwd+t0);
X						break;
X						}
X				case 'd': case '/': stradd(cwd); break;
X				case 'c': case '.':
X					for (ss = cwd+strlen(cwd); ss > cwd; ss--)
X						if (*ss == '/')
X							{
X							ss++;
X							break;
X							}
X					stradd(ss);
X					break;
X				case 'h': case '!':
X					sprintf(bp,"%d",curhist);
X					bp += strlen(bp);
X					break;
X				case 'M': stradd(hostM); break;
X				case 'm': stradd(hostm); break;
X				case 'S': tstradd("so"); /* <- this is a macro */
X				case 's': tstradd("se");
X				case 'B': tstradd("md");
X				case 'b': tstradd("me");
X				case 'U': tstradd("us");
X				case 'u': tstradd("ue");
X				case 't': case '@':
X					timet = time(NULL);
X					tm = localtime(&timet);
X					ztrftime(bp,16,"%l:%M%p",tm);
X					if (*bp == ' ')
X						chuck(bp);
X					bp += strlen(bp);
X					break;
X				case 'T':
X					timet = time(NULL);
X					tm = localtime(&timet);
X					ztrftime(bp,16,"%k:%M",tm);
X					bp += strlen(bp);
X					break;
X				case '*':
X					timet = time(NULL);
X					tm = localtime(&timet);
X					ztrftime(bp,16,"%k:%M:%S",tm);
X					bp += strlen(bp);
X					break;
X				case 'n': stradd(username); break;
X				case 'w':
X					timet = time(NULL);
X					tm = localtime(&timet);
X					ztrftime(bp,16,"%a %e",tm);
X					bp += strlen(bp);
X					break;
X				case 'W':
X					timet = time(NULL);
X					tm = localtime(&timet);
X					ztrftime(bp,16,"%m/%d/%y",tm);
X					bp += strlen(bp);
X					break;
X				case 'D':
X					timet = time(NULL);
X					tm = localtime(&timet);
X					ztrftime(bp,16,"%y-%m-%d",tm);
X					bp += strlen(bp);
X					break;
X				case 'l':
X					if (ss = ttyname(SHTTY))
X						stradd((strncmp(ss,"/dev/tty",8) ? ss : ss+8));
X					else
X						stradd("()");
X					break;
X				case '?':
X					sprintf(bp,"%d",lastval);
X					bp += strlen(bp);
X					break;
X				case '%': *bp++ = '%'; break;
X				case '#': *bp++ = (geteuid()) ? '%' : '#'; break;
X				default: *bp++ = '%'; *bp++ = *fm; break;
X				}
X		else if (*fm == '!')
X			{
X			sprintf(bp,"%d",curhist);
X			bp += strlen(bp);
X			}
X		else
X			if ((*bp++ = *fm) == '\n')
X				bl0 = bp;
X		}
X	*lenp = (bp-bl0)-lensb;
X	if (columns)
X		*lenp %= columns;
X	if (*lenp == columns-1)
X		{
X		*lenp = 0;
X		*bp++ = ' ';
X		}
X	*bp = '\0';
X	return buf;
X}
X
Xvoid herrflush() /**/
X{
X	if (strin)
X		hflush();
X	else while (lastc != '\n' && lastc != HERR)
X		hgetch();
X}
X
X/* read an arbitrary amount of data into a buffer until stop is found */
X
Xchar *hdynread(stop) /**/
Xint stop;
X{
Xint bsiz = 256,ct = 0,c;
Xchar *buf = zalloc(bsiz),*ptr;
X 
X	ptr = buf;
X	while ((c = hgetch()) != stop && c != '\n' && c != EOF && c != HERR)
X		{
X		if (c == '\\')
X			c = hgetch();
X		*ptr++ = c;
X		if (++ct == bsiz)
X			{
X			buf = realloc(buf,bsiz *= 2);
X			ptr = buf+ct;
X			}
X		}
X	*ptr = 0;
X	if (c == '\n')
X		{
X		hungetch('\n');
X		zerr("delimiter expected",NULL,0);
X		free(buf);
X		return NULL;
X		}
X	return buf;
X}
X 
Xchar *hdynread2(stop) /**/
Xint stop;
X{
Xint bsiz = 256,ct = 0,c;
Xchar *buf = zalloc(bsiz),*ptr;
X 
X	ptr = buf;
X	while ((c = hgetch()) != stop && c != '\n' && c != EOF && c != HERR)
X		{
X		if (c == '\n')
X			{
X			hungetch(c);
X			break;
X			}
X		if (c == '\\')
X			c = hgetch();
X		*ptr++ = c;
X		if (++ct == bsiz)
X			{
X			buf = realloc(buf,bsiz *= 2);
X			ptr = buf+ct;
X			}
X		}
X	*ptr = 0;
X	if (c == '\n')
X		hungetch('\n');
X	return buf;
X}
X
X/* set cbreak mode, or the equivalent */
X
Xvoid setcbreak() /**/
X{
Xstruct ttyinfo ti;
X
X	ti = shttyinfo;
X#ifdef TERMIOS
X	ti.termios.c_lflag &= ~ICANON;
X	ti.termios.c_cc[VMIN] = 1;
X	ti.termios.c_cc[VTIME] = 0;
X#else
X#ifdef TERMIO
X	ti.termio.c_lflag &= ~ICANON;
X	ti.termio.c_cc[VMIN] = 1;
X	ti.termio.c_cc[VTIME] = 0;
X#else
X	ti.sgttyb.sg_flags |= CBREAK;
X#endif
X#endif
X	settyinfo(&ti);
X}
X
Xint getlineleng() /**/
X{
Xint z;
X
X	z = shttyinfo.winsize.ws_col;
X	return (z) ? z : 80;
X}
X
Xvoid unsetcbreak() /**/
X{
X	settyinfo(&shttyinfo);
X}
X
X/* give the tty to some process */
X
Xvoid attachtty(pgrp) /**/
Xlong pgrp;
X{
Xstatic int ep = 0;
Xint arg = pgrp;
X
X	if (jobbing)
X#ifdef TCSETPGRP
X		if (SHTTY != -1 && tcsetpgrp(SHTTY,pgrp) == -1 && !ep)
X#else
X		if (SHTTY != -1 && ioctl(SHTTY,TIOCSPGRP,&arg) == -1 && !ep)
X#endif
X			{
X			zerr("can't set tty pgrp: %e",NULL,errno);
X			fflush(stderr);
X			opts[MONITOR] = OPT_UNSET;
X			ep =1;
X			errflag = 0;
X			}
X}
X
SHAR_EOF
chmod 0644 zsh2.00/src/hist.c ||
echo 'restore of zsh2.00/src/hist.c failed'
Wc_c="`wc -c < 'zsh2.00/src/hist.c'`"
test 23645 -eq "$Wc_c" ||
	echo 'zsh2.00/src/hist.c: original size 23645, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.00/src/hist.pro ==============
if test -f 'zsh2.00/src/hist.pro' -a X"$1" != X"-c"; then
	echo 'x - skipping zsh2.00/src/hist.pro (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting zsh2.00/src/hist.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.00/src/hist.pro' &&
Xvoid hwaddc DCLPROTO((int c));
Xint hgetc DCLPROTO((void));
Xint hgetch DCLPROTO((void));
Xvoid hungets DCLPROTO((char *str));
Xvoid hungetc DCLPROTO((int c));
Xvoid hungetch DCLPROTO((int c));
Xvoid strinbeg DCLPROTO((void));
Xvoid strinend DCLPROTO((void));
Xint stuff DCLPROTO((char *fn));
Xvoid hflush DCLPROTO((void));
Xvoid hbegin DCLPROTO((void));
Xvoid inittty DCLPROTO((void));
Xint hend DCLPROTO((void));
Xvoid remhist DCLPROTO((void));
Xvoid hwbegin DCLPROTO((void));
Xchar *hwadd DCLPROTO((void));
Xint getargspec DCLPROTO((int argc,int marg));
Xint hconsearch DCLPROTO((char *str,int *marg));
Xint hcomsearch DCLPROTO((char *str));
Xint remtpath DCLPROTO((char **junkptr));
Xint remtext DCLPROTO((char **junkptr));
Xint rembutext DCLPROTO((char **junkptr));
Xint remlpaths DCLPROTO((char **junkptr));
Xint makeuppercase DCLPROTO((char **junkptr));
Xint makelowercase DCLPROTO((char **junkptr));
Xint subst DCLPROTO((char **strptr,char *in,char *out,int gbal));
Xchar *convamps DCLPROTO((char *out,char *in));
Xchar *makehstr DCLPROTO((char *s));
Xchar *quietgetevent DCLPROTO((int ev));
Xchar *getevent DCLPROTO((int ev));
Xint getargc DCLPROTO((char *list));
Xchar *getargs DCLPROTO((char *elist,int arg1,int arg2));
Xvoid upcase DCLPROTO((char **x));
Xvoid downcase DCLPROTO((char **x));
Xint quote DCLPROTO((char **tr));
Xint quotebreak DCLPROTO((char **tr));
Xvoid stradd DCLPROTO((char *d));
Xint putstr DCLPROTO((int d));
Xchar *putprompt DCLPROTO((char *fm,int *lenp));
Xvoid herrflush DCLPROTO((void));
Xchar *hdynread DCLPROTO((int stop));
Xchar *hdynread2 DCLPROTO((int stop));
Xvoid setcbreak DCLPROTO((void));
Xint getlineleng DCLPROTO((void));
Xvoid unsetcbreak DCLPROTO((void));
Xvoid attachtty DCLPROTO((long pgrp));
SHAR_EOF
chmod 0644 zsh2.00/src/hist.pro ||
echo 'restore of zsh2.00/src/hist.pro failed'
Wc_c="`wc -c < 'zsh2.00/src/hist.pro'`"
test 1700 -eq "$Wc_c" ||
	echo 'zsh2.00/src/hist.pro: original size 1700, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.00/src/init.c ==============
if test -f 'zsh2.00/src/init.c' -a X"$1" != X"-c"; then
	echo 'x - skipping zsh2.00/src/init.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting zsh2.00/src/init.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.00/src/init.c' &&
X/*
X
X	init.c - main loop and initialization routines
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#define GLOBALS
X#include "zsh.h"
X#include "funcs.h"
X#include <pwd.h>
X
Xextern int yydebug;
X
Xvoid main(argc,argv,envp) /**/
Xint argc; char **argv; char **envp;
X{
Xint notect = 0;
X
X	environ = envp;
X	pathsuppress = 1;
X	meminit();
X	setflags();
X	parseargs(argv);
X	setmoreflags();
X	setupvals();
X	initialize();
X	heapalloc();
X	runscripts();
X	if (interact)
X		{
X		pathsuppress = 0;
X		newcmdnamtab();
X		}
X	for(;;)
X		{
X		do
X			loop();
X		while (!eofseen);
X		if (!(isset(IGNOREEOF) && interact))
X			{
X#if 0
X			if (interact)
X				fputs(islogin ? "logout\n" : "exit\n",stderr);
X#endif
X			zexit(NULL);
X			continue;
X			}
X		zerrnam("\nzsh",(!islogin) ? "use 'exit' to exit."
X			: "use 'logout' to logout.",NULL,0);
X		notect++;
X		if (notect == 10)
X			zexit(NULL);
X		}
X}
X
X/* keep executing lists until EOF found */
X
Xvoid loop() /**/
X{
XList list;
X
X	pushheap();
X	for(;;)
X		{
X		freeheap();
X		if (interact && isset(SHINSTDIN))
X			preprompt();
X		hbegin();		/* init history mech */
SHAR_EOF
true || echo 'restore of zsh2.00/src/init.c failed'
fi
echo 'End of zsh2.00.00 part 6'
echo 'File zsh2.00/src/init.c is continued in part 7'
echo 7 > _shar_seq_.tmp
exit 0
--
              Paul Falstad  pfalstad@phoenix.princeton.edu
         And on the roads, too, vicious gangs of KEEP LEFT signs!
     If Princeton knew my opinions, they'd have expelled me long ago.

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.