home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
misc
/
volume35
/
zsh
/
part14
< prev
next >
Wrap
Text File
|
1993-02-20
|
56KB
|
2,786 lines
Newsgroups: comp.sources.misc
From: zsh-list@cs.uow.edu.au (The Zsh Mailing List)
Subject: v35i064: zsh - The Z Shell, version 2.3.1, Part14/22
Message-ID: <1993Feb20.212601.29047@sparky.imd.sterling.com>
X-Md4-Signature: 0a1bd731879202307d405b2ee7e5eabb
Date: Sat, 20 Feb 1993 21:26:01 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: zsh-list@cs.uow.edu.au (The Zsh Mailing List)
Posting-number: Volume 35, Issue 64
Archive-name: zsh/part14
Environment: UNIX
Supersedes: zsh2.2: Volume 29, Issue 97-113
#! /bin/sh
# This is a shell archive. Remove anything before this line, then feed it
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# Contents: help/case src/glob.c src/hist.c
# Wrapped by mattson@odin on Sat Feb 6 14:41:54 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo ' "shar: End of archive 14 (of 22)."'
if test -f 'help/case' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'help/case'\"
else
echo shar: Extracting \"'help/case'\" \(398 characters\)
sed "s/^X//" >'help/case' <<'END_OF_FILE'
X case word in [ pattern ) list ;; ] ... esac
X Execute the list associated with the first pattern
X that matches word, if any. The form of the pat-
X terns is the same as that used for filename gen-
X eration. See Filename Generation below.
X
X case word { [ pattern ) list ;; ] ... }
X Another form of case.
END_OF_FILE
if test 398 -ne `wc -c <'help/case'`; then
echo shar: \"'help/case'\" unpacked with wrong size!
fi
# end of 'help/case'
fi
if test -f 'src/glob.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/glob.c'\"
else
echo shar: Extracting \"'src/glob.c'\" \(26147 characters\)
sed "s/^X//" >'src/glob.c' <<'END_OF_FILE'
X/*
X *
X * glob.c - filename generation
X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#include "zsh.h"
X
X#include <sys/errno.h>
X
X#define exists(X) (access(X,0) == 0 || readlink(X,NULL,0) == 0)
X
Xstatic int mode; /* != 0 if we are parsing glob patterns */
Xstatic int pathpos; /* position in pathbuf */
Xstatic int matchsz; /* size of matchbuf */
Xstatic int matchct; /* number of matches found */
Xstatic char pathbuf[MAXPATHLEN]; /* pathname buffer */
Xstatic char **matchbuf; /* array of matches */
Xstatic char **matchptr; /* &matchbuf[matchct] */
Xstatic Comp exclude; /* pattern to exclude */
X#ifdef ULTRIX
Xtypedef struct stat *Statptr; /* This makes the Ultrix compiler happy. Go figure. */
X#endif
X
X/* max # of qualifiers */
X
X#define QUALCT 16
X
Xstatic int (*qualfuncs[QUALCT])DCLPROTO((struct stat *,long));
Xstatic long qualdata[QUALCT];
Xstatic int qualsense[QUALCT];
Xstatic int qualamc[QUALCT];
Xstatic int qualrange[QUALCT];
Xstatic int qualct;
Xstatic int range, amc;
Xstatic int gf_nullglob,gf_markdirs,gf_noglobdots;
X
X/* pathname component in filename patterns */
X
Xstruct complist {
X Complist next;
X Comp comp;
X int closure; /* 1 if this is a (foo/)# */
X };
Xstruct comp {
X Comp left,right,next;
X char *str;
X int closure,last;
X };
X
Xvoid glob(list,np) /**/
XLklist list;Lknode *np;
X{
XLknode node = prevnode(*np);
XLknode next = nextnode(*np);
Xchar *str; /* the pattern */
Xint sl; /* length of the pattern */
XComplist q; /* pattern after parsing */
Xchar *ostr = getdata(*np); /* the pattern before the parser chops it up */
X
X heapalloc();
X str = strdup(ostr);
X lastalloc();
X sl = strlen(str);
X uremnode(list,*np);
X qualct = 0;
X gf_nullglob = isset(NULLGLOB);
X gf_markdirs = isset(MARKDIRS);
X gf_noglobdots = unset(GLOBDOTS);
X if (str[sl-1] == Outpar) /* check for qualifiers */
X {
X char *s;
X int sense = 0;
X long data = 0;
X#ifdef ULTRIX
X int (*func) DCLPROTO((Statptr,long));
X#else
X int (*func) DCLPROTO((struct stat *,long));
X#endif
X
X for (s = str+sl-2; s != str; s--)
X if (*s == Bar || *s == Outpar || *s == Inpar)
X break;
X if (*s == Inpar)
X {
X *s++ = '\0';
X while (*s != Outpar)
X {
X#ifdef ULTRIX
X func = (int (*) DCLPROTO((Statptr,long))) 0;
X#else
X func = (int (*) DCLPROTO((struct stat *,long))) 0;
X#endif
X if (idigit(*s))
X {
X func = qualflags;
X data = 0;
X while (idigit(*s))
X data = data*010+(*s++-'0');
X }
X else switch ((int)(unsigned char)(*s++))
X {
X case (int)STOUC(Hat): case '^': sense = 1-sense; break;
X#ifdef S_IFLNK
X case '@': func = qualmode; data = S_IFLNK; break;
X#endif
X#ifdef S_IFSOCK
X case '=': func = qualmode; data = S_IFSOCK; break;
X#endif
X#ifdef S_IFIFO
X case 'p': func = qualmode; data = S_IFIFO; break;
X#endif
X case '/': func = qualmode; data = S_IFDIR; break;
X case '.': func = qualmode; data = S_IFREG; break;
X case '%': func = qualisdev; break;
X case (int)STOUC(Star): func = qualiscom; break;
X case 'R': func = qualflags; data = 0004; break;
X case 'W': func = qualflags; data = 0002; break;
X case 'X': func = qualflags; data = 0001; break;
X case 'r': func = qualflags; data = 0400; break;
X case 'w': func = qualflags; data = 0200; break;
X case 'x': func = qualflags; data = 0100; break;
X case 's': func = qualflags; data = 04000; break;
X case 'S': func = qualflags; data = 02000; break;
X case 'd': func = qualdev; data = qgetnum(&s); break;
X case 'l': func = qualnlink; data = qgetnum(&s); break;
X case 'U': func = qualuid; data = geteuid(); break;
X case 'G': func = qualgid; data = getegid(); break;
X case 'u': func = qualuid; data = qgetnum(&s); break;
X case 'g': func = qualgid; data = qgetnum(&s); break;
X case 'M': gf_markdirs = !sense; break;
X case 'N': gf_nullglob = !sense; break;
X case 'D': gf_noglobdots = sense; break;
X case 'a': amc = 0; func = qualtime; goto getrange;
X case 'm': amc = 1; func = qualtime; goto getrange;
X case 'c': amc = 2; func = qualtime; goto getrange;
X case 'L': func = qualsize;
Xgetrange:
X if (range = *s == '+' ? 1 : *s == '-' ? -1 : 0) ++s;
X data = qgetnum(&s);
X break;
X default: zerr("unknown file attribute",NULL,0); return;
X }
X if (func)
X {
X if (qualct == QUALCT-1)
X {
X zerr("too many qualifiers",NULL,0);
X return;
X }
X qualfuncs[qualct] = func;
X qualsense[qualct] = sense;
X qualdata[qualct] = data;
X qualrange[qualct] = range;
X qualamc[qualct] = amc;
X qualct++;
X }
X if (errflag)
X return;
X }
X }
X }
X else if ((str[sl-1] == '/') && !((str[sl-2] == Star)&&
X (str[sl-3] == Star)&&(str[sl-4] == Star)&&
X (str[sl-5]==Star))) /* foo/ == foo(/) */
X {
X str[sl-1] = '\0';
X qualfuncs[0] = qualmode;
X qualdata[0] = S_IFDIR;
X qualsense[0] = 0;
X qualct = 1;
X }
X#ifdef ULTRIX
X qualfuncs[qualct] = (int (*) DCLPROTO((Statptr,long))) 0;
X#else
X qualfuncs[qualct] = (int (*) DCLPROTO((struct stat *,long))) 0;
X#endif
X if (*str == '/') /* pattern has absolute path */
X {
X str++;
X pathbuf[0] = '/';
X pathbuf[pathpos = 1] = '\0';
X }
X else /* pattern is relative to pwd */
X pathbuf[pathpos = 0] = '\0';
X q = parsepat(str);
X if (!q || errflag) /* if parsing failed */
X {
X if (isset(NOBADPATTERN))
X {
X insnode(list,node,ostr);
X return;
X }
X errflag = 0;
X zerr("bad pattern: %s",ostr,0);
X return;
X }
X matchptr = matchbuf = (char **) zalloc((matchsz = 16)*sizeof(char *));
X matchct = 0;
X scanner(q); /* do the globbing */
X if (matchct)
X badcshglob |= 2;
X else if (!gf_nullglob)
X if (isset(CSHNULLGLOB)) {
X badcshglob |= 1;
X } else if (unset(NONOMATCH)) {
X zerr("no matches found: %s",ostr,0);
X free(matchbuf);
X return;
X } else {
X *matchptr++ = strdup(ostr);
X matchct = 1;
X }
X qsort((vptr)&matchbuf[0],matchct,sizeof(char *),
X (int (*) DCLPROTO((const void *, const void *)))notstrcmp);
X matchptr = matchbuf;
X while (matchct--) /* insert matches in the arg list */
X insnode(list,node,*matchptr++);
X free(matchbuf);
X *np = (next) ? prevnode(next) : lastnode(list);
X}
X
X/* get number after qualifier */
X
Xlong qgetnum(s) /**/
Xchar **s;
X{
Xlong v = 0;
X
X if (!idigit(**s))
X {
X zerr("number expected",NULL,0);
X return 0;
X }
X while (idigit(**s))
X v = v*10+*(*s)++-'0';
X return v;
X}
X
Xint notstrcmp(a,b) /**/
Xchar **a;char **b;
X{
Xchar *c = *b,*d = *a;
Xint x1,x2,cmp;
X
X for (; *c == *d && *c; c++,d++);
X cmp = (int) (unsigned char) *c-(int) (unsigned char) *d;
X if (isset(NUMERICGLOBSORT)) {
X for (; c > *b && idigit(c[-1]); c--,d--);
X if(idigit(*c) && idigit(*d)) {
X x1 = atoi(c); x2 = atoi(d);
X if(x1 != x2) return x1-x2;
X }
X }
X return cmp;
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;
Xint statted = 0;
X
X if (exclude && domatch(s,exclude,gf_noglobdots)) return;
X if (gf_markdirs && !lstat(s,&buf) && S_ISDIR(buf.st_mode)) {
X char *t;
X int ll = strlen(s);
X
X t = ncalloc(ll+2);
X strcpy(t,s);
X t[ll] = '/';
X t[ll+1] = '\0';
X s = t;
X statted = 1;
X }
X if (qualct) { /* do the (X) (^X) stuff */
X#ifdef ULTRIX
X int (**fptr)DCLPROTO((Statptr,long)) = qualfuncs;
X#else
X int (**fptr)DCLPROTO((struct stat *,long)) = qualfuncs;
X#endif
X int *sptr = qualsense;
X int *rptr = qualrange;
X int *aptr = qualamc;
X long *lptr = qualdata;
X
X if (statted || lstat(s,&buf) >= 0)
X while (*fptr) {
X range = *rptr++;
X amc = *aptr++;
X if (!(!!((*fptr++)(&buf,*lptr++)) ^ *sptr++))
X return;
X }
X }
X *matchptr++ = s;
X if (++matchct == matchsz) {
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 == Inbrack || *str == Outbrack) && !str[1]) return 0;
X if (str[0] == '%') return 0;
X for (; *str; str++)
X if (*str == Pound || *str == Hat || *str == Star ||
X *str == Bar || *str == Inbrack || *str == Inang ||
X *str == Quest) 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 if (isset(BRACECCL)) {
X for (mb = bc = 0; *str; ++str)
X if (*str == Inbrace) {
X if (++bc > mb)
X mb = bc;
X }
X else if (*str == Outbrace)
X if (--bc < 0)
X return(0);
X return(mb && bc == 0);
X }
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)
X {
X if (!cmct2)
X {
X *lbr = '{';
X *str = '}';
X }
X cmct2 = 0;
X }
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) return 0;
X if (full(fake) && !nextnode(firstnode(fake))) {
X fn->name = peekfirst(fake);
X untokenize(fn->name);
X } else
X while (nam = ugetnode(fake)) {
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, bc, comma;
X
X for (; *str != Inbrace; str++);
X for (str2 = str, bc = comma = 0; *str2; ++str2)
X if (*str2 == Inbrace)
X ++bc;
X else if (*str2 == Outbrace) {
X if (--bc == 0)
X break;
X }
X else if (bc == 1 && *str2 == Comma)
X ++comma;
X if (!comma && !bc && isset(BRACECCL)) { /* {a-mnop} */
X char ccl[256], *p;
X unsigned char c1,c2,lastch;
X
X uremnode(list,node);
X memset(ccl, 0, sizeof(ccl) / sizeof(ccl[0]));
X for (p = str + 1, lastch = 0; p < str2; ) {
X if (itok(c1 = *p++))
X c1 = ztokens[c1 - STOUC(Pound)];
X if (itok(c2 = *p))
X c2 = ztokens[c2 - STOUC(Pound)];
X if (c1 == '-' && lastch && p < str2 && lastch <= c2) {
X while (lastch < c2)
X ccl[lastch++] = 1;
X lastch = 0;
X }
X else
X ccl[lastch = c1] = 1;
X }
X strcpy(str + 1, str2 + 1);
X for (p = ccl+255; p-- > ccl; )
X if (*p) {
X *str = p - ccl;
X insnode(list, last, strdup(str3));
X }
X *np = nextnode(last);
X return;
X }
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 ztrncpy(zz,str3,prev);
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,len;
Xchar *b2;
X
X remnulargs(b);
X len = strlen(b);
X b2 = alloc(len+3);
X strcpy(b2+1,b);
X b2[0] = Inpar;
X b2[len+1] = Outpar;
X b2[len+2] = '\0';
X c = parsereg(b2);
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 remnulargs(pat);
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 cc = *t;
X *t = '\0';
X *sp = strdup(*sp);
X *t = cc;
X return;
X }
X lng = t;
X }
X }
X if (lng)
X {
X cc = *lng;
X *lng = '\0';
X *sp = strdup(*sp);
X *lng = cc;
X return;
X }
X }
X}
X
X/* add a component to pathbuf */
X
Xstatic int addpath(s)
Xchar *s;
X{
X if (strlen(s)+pathpos >= MAXPATHLEN) return 0;
X while (pathbuf[pathpos++] = *s++);
X pathbuf[pathpos-1] = '/';
X pathbuf[pathpos] = '\0';
X return 1;
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 if (q->closure && !strcmp(c->str,".")) return;
X if (!addpath(c->str)) return;
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) ? 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,gf_noglobdots))
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 if (addpath(fn))
X scanner((q->closure) ? q : q->next); /* scan next level */
X pathbuf[pathpos = oppos] = '\0';
X }
X else insert(dyncat(pathbuf,fn));
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 Comp tail = 0;
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 == 1) {
X char *saves = pptr;
X
X if (first && *pptr == '.') return 0;
X if (doesmatch(c->next)) return 1;
X pptr = saves;
X first = 0;
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 (!*pptr) break;
X if (pat[1] == Hat || pat[1] == '^') {
X pat[1] = Hat;
X for (pat += 2; *pat != Outbrack && *pat; pat++)
X if (*pat == '-' && pat[-1] != Hat && pat[1] != Outbrack) {
X if (pat[-1] <= *pptr && pat[1] >= *pptr)
X break;
X } else if (*pptr == *pat) break;
X if (!*pat) {
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 } else {
X for (pat++; *pat != Outbrack && *pat; pat++)
X if (*pat == Inpar) {
X if (minimatch(&pat,&pptr))
X break;
X } else if (*pat == '-' && pat[-1] != Inbrack &&
X pat[1] != Outbrack) {
X if (pat[-1] <= *pptr && pat[1] >= *pptr)
X break;
X } else if (*pptr == *pat) break;
X if (!pat || !*pat) {
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 }
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 = -1;
X if (*pat++ != Outang)
X exit(21);
X if (t1 < t2 || (t3 != -1 && 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{
Xchar *s;
X
X exclude = NULL;
X if (isset(EXTENDEDGLOB)) {
X s = str+strlen(str);
X while (s-- > str) {
X if (*s == Tilde && s[1]) {
X *s++ = '\0';
X exclude = parsereg(s);
X if (!exclude) return NULL;
X break;
X }
X }
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] == Star && pptr[1] == Star &&
X (pptr[2] == '/' ||
X (pptr[2] == Star && pptr[3] == Star && pptr[4] == '/'))) {
X pptr += 3;
X if (pptr[-1] == Star) pptr += 2;
X p1 = (Complist) alloc(sizeof *p1);
X p1->next = parsecomplist();
X p1->comp = (Comp) alloc(sizeof *p1->comp);
X p1->comp->last = 1;
X p1->comp->str = strdup("*");
X *p1->comp->str = Star;
X p1->closure = 1;
X return p1;
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 c->next = tail;
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 if (!(c2 = parsecomp())) return NULL;
X c1->next = c2;
X c->next = c1;
X return c;
X }
X if (*pptr == Inpar)
X {
X int pars = 1;
X char *startp = pptr, *endp;
X Comp stail = tail;
X int dpnd = 0;
X
X for (pptr = pptr+1; *pptr && pars; pptr++)
X if (*pptr == Inpar)
X pars++;
X else if (*pptr == Outpar)
X pars--;
X if (pptr[-1] != Outpar)
X {
X errflag = 1;
X return NULL;
X }
X if (*pptr == Pound)
X {
X dpnd = 1;
X pptr++;
X if (*pptr == Pound)
X {
X pptr++;
X dpnd = 2;
X }
X }
X if (!(c1 = parsecomp())) return NULL;
X tail = c1;
X endp = pptr;
X pptr = startp;
X pptr++;
X *s++ = '\0';
X c->next = (Comp) alloc(sizeof *c);
X c->next->left = parsecompsw();
X c->next->closure = dpnd;
X c->next->next = (Comp) alloc(sizeof *c);
X pptr = endp;
X tail = stail;
X return c;
X }
X if (*pptr == Pound)
X {
X *s = '\0';
X pptr++;
X if (!ls)
X return NULL;
X if (*pptr == Pound)
X {
X pptr++;
X c->next = c1 = (Comp) alloc(sizeof *c);
X c1->str = strdup(ls);
X }
X else
X c1 = c;
X c1->next = c2 = (Comp) alloc(sizeof *c);
X c2->str = strdup(ls);
X c2->closure = 1;
X c2->next = parsecomp();
X if (!c2->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 (INULL(*s))
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}
X
Xint qualiscom(buf,mod) /**/
Xstruct stat *buf;long mod;
X{
X return (buf->st_mode & (S_IFMT|S_IEXEC)) == (S_IFREG|S_IEXEC);
X}
X
Xint qualsize(buf,size) /**/
Xstruct stat *buf;long size;
X{
X return(range < 0 ? buf->st_size < size :
X range > 0 ? buf->st_size > size :
X buf->st_size == size);
X}
X
Xint qualtime(buf,days) /**/
Xstruct stat *buf;long days;
X{
X time_t now, diff;
X
X time(&now);
X diff = now - (amc == 0 ? buf->st_atime : amc == 1 ? buf->st_mtime :
X buf->st_ctime);
X diff /= 86400l;
X return(range < 0 ? diff < days :
X range > 0 ? diff > days :
X diff == days);
X}
END_OF_FILE
if test 26147 -ne `wc -c <'src/glob.c'`; then
echo shar: \"'src/glob.c'\" unpacked with wrong size!
fi
# end of 'src/glob.c'
fi
if test -f 'src/hist.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/hist.c'\"
else
echo shar: Extracting \"'src/hist.c'\" \(24223 characters\)
sed "s/^X//" >'src/hist.c' <<'END_OF_FILE'
X/*
X *
X * hist.c - history expansion
X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#include "zsh.h"
X
X#define HEAPSIZE 4096
X
Xstruct hp {
X Hp next;
X char *pool,*ptr;
X int free,histno;
X};
X
Xstatic Hp hp_lit, hp_lex;
Xstatic Histent curhistent;
X
Xstatic int lastc;
X
X/* add a character to the current history word */
X
Xvoid hwaddc(c) /**/
Xint c;
X{
X if (hlastw && chline && (!(errflag || lexstop) || c == HISTSPACE)) {
X if (c == '!' && unset(NOBANGHIST)) hwaddc('\\');
X *hptr++ = c;
X if (hptr-chline >= hlinesz) {
X int ll,flag = 0,oldsiz = hlinesz;
X
X ll = hptr-hlastw;
X if (curhistent->lex == chline) flag = 1;
X chline = hp_realloc(&hp_lex,chline,oldsiz,hlinesz = oldsiz+16);
X if (flag) curhistent->lex = chline;
X hptr = chline+oldsiz;
X hlastw = hptr-ll;
X }
X }
X}
X
X#define habort() { errflag = lexstop = 1; return ' '; }
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 || alstackind)
X {
X hwaddc(c);
X return c;
X }
X if (isfirstch && c == hatchar)
X {
X isfirstch = 0;
X hungetch(hatchar);
X hungets(":s");
X goto hatskip;
X }
X if (c != ' ')
X isfirstch = 0;
X if (c == '\\') {
X int g = hgetch();
X
X if (g != bangchar)
X hungetch(g);
X else {
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 == '(' || lexstop)
X {
X if (lexstop)
X lexstop = 0;
X else
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' || lexstop)
X break;
X else
X *ptr++ = c;
X }
X if (c != '\n' && !lexstop)
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 == '}' || lexstop)
X break;
X if (ptr != buf) {
X if (c == '-') break;
X if ((idigit(buf[0]) || buf[0] == '-') && !idigit(c)) break;
X }
X *ptr++ = c;
X if (c == '#' || c == bangchar)
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 ((unsigned) *buf == bangchar)
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' && !lexstop)
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 = HISTFLAG_DONE|HISTFLAG_NOEXEC;
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 = hdynread2(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 subst(&sline,hsubl,hsubr,gbal);
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 }
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 lexstop = 0;
X if (alstackind != MAXAL)
X {
X hungets(HISTMARK);
X alstack[alstackind++] = NULL;
X }
X for (ptr = sline; *ptr; ptr++) {
X if (ptr[0] == '\\' && ptr[1] == '!') chuck(ptr);
X }
X hungets(sline);
X histdone |= HISTFLAG_DONE;
X if (isset(HISTVERIFY)) histdone |= HISTFLAG_NOEXEC|HISTFLAG_RECALL;
X goto tailrec;
X}
X
X/* reset the alias stack for lexrestore () */
X
Xvoid clearalstack() /**/
X{
XAlias ix;
X
X while (alstackind)
X {
X ix = alstack[--alstackind];
X ix->inuse = 0;
X }
X}
X
X/* get a character without history expansion */
X
Xint hgetch() /**/
X{
Xunsigned char *line,*pmpt = NULL,*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 errflag = lexstop = 1;
X return lastc = ' ';
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 if (itok(lastc))
X goto start;
X return lastc;
X }
X if (strin || errflag)
X {
X lexstop = 1;
X return lastc = ' ';
X }
X if (interact && isset(SHINSTDIN))
X if (!isfirstln)
X pmpt = (unsigned char *)putprompt(prompt2,&plen,0);
X else
X {
X int foo;
X
X pmpt = (unsigned char *)putprompt(prompt,&plen,0);
X pmpt2 = (unsigned char *)((rprompt) ? putprompt(rprompt,&foo,0) : NULL);
X }
X if (!(interact && isset(SHINSTDIN) && SHTTY != -1 && isset(USEZLE))) {
X char *lbuf;
X if (interact && isset(SHINSTDIN))
X write(2,pmpt,strlen((char *) pmpt));
X line = (unsigned char *)fgets(lbuf = zalloc(256),256,bshin);
X if (!line) free(lbuf);
X } else
X line = zleread(pmpt,pmpt2,plen);
X if (!line) {
X lexstop = 1;
X return lastc = ' ';
X }
X if (errflag) {
X free(line);
X lexstop = errflag = 1;
X return lastc = ' ';
X }
X if (interact && isset(SHINSTDIN)) {
X char *s = curhistent->lit;
X curhistent->lit = hp_concat(s,(char*)line);
X }
X if (isfirstln) spaceflag = *line == ' ';
X if (isset(VERBOSE)) {
X fputs((char *) line,stderr);
X fflush(stderr);
X }
X if (*line && line[strlen((char *) line)-1] == '\n')
X {
X lineno++;
X if (interact && isset(SUNKEYBOARDHACK) && isset(SHINSTDIN) &&
X SHTTY != -1 && *line && line[1] &&
X line[strlen((char *) line)-2] == '`')
X {
X int ct;
X unsigned 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((char*)line);
X free(line);
X goto start;
X}
X
X/* Read one line of at most n-1 chars from the input queue */
X
Xchar *hgets(buf, n) /**/
Xchar *buf;int n;
X{
Xint l;
X
X for (l = 0; l < n-1; l++)
X if ((buf[l] = hgetch()) == '\n' || lexstop)
X break;
X buf[l+(lexstop?0:1)] = 0;
X
X return (!lexstop || l) ? buf : NULL;
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 chline */
X
Xvoid hungetc(c) /**/
Xint c;
X{
X if (lexstop)
X return;
X if (hlastw) {
X if (hlastw == hptr)
X zerr("hungetc attempted at buffer start",NULL,0);
X else {
X hptr--;
X if (*hptr == '!' && unset(NOBANGHIST)) hptr--;
X }
X }
X hungetch(c);
X}
X
Xvoid hungetch(c) /**/
Xint c;
X{
X if (lexstop)
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 lexinit();
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 = !interact || isset(NOBANGHIST) || unset(SHINSTDIN);
X lithist = isset(HISTLIT);
X chline = hptr = hp_alloc(&hp_lex,hlinesz = 16);
X curhistent = gethistent(curhist);
X if (!curhistent->ftim) curhistent->ftim = time(NULL);
X if (interact && isset(SHINSTDIN) && !strin) {
X inittty();
X defev = curhist++;
X if (curhist-histsiz >= 0) gethistent(curhist-histsiz)->lex = NULL;
X if (curhist-lithistsiz >= 0) gethistent(curhist-lithistsiz)->lit = NULL;
X curhistent = gethistent(curhist);
X hp_purge(hp_lex,curhist-histsiz);
X hp_purge(hp_lit,curhist-lithistsiz);
X curhistent->lex = chline;
X *(curhistent->lit = hp_alloc(&hp_lit,1)) = '\0';
X } else
X histremmed = 1;
X}
X
Xvoid inittty() /**/
X{
X attachtty(mypgrp);
X}
X
X/* say we're done using the history mechanism */
X
Xint hend() /**/
X{
Xint flag,save = 1;
XHistent he;
X
X if (!chline)
X return 1;
X if (!interact || strin || unset(SHINSTDIN)) {
X hp_free(hp_lex,chline,hlinesz);
X return 1;
X }
X flag = histdone;
X histdone = 0;
X if (hptr < chline+2)
X save = 0;
X else {
X char *s,*t;
X
X s = curhistent->lit;
X if (*s && *(t = s+strlen(s)-1) == HISTSPACE) *t = '\0';
X hptr[-1] = '\0';
X if (hptr[-2] == '\n')
X if (chline[1]) {
X if (hptr[-3] == HISTSPACE) hptr[-3] = '\0';
X } else save = 0;
X he = gethistent(curhist-1);
X if (!strcmp(chline,"\n") ||
X (isset(HISTIGNOREDUPS) && he->lex && !strcmp(he->lex,chline)) ||
X (isset(HISTIGNORESPACE) && spaceflag))
X save = 0;
X }
X if (flag & (HISTFLAG_DONE|HISTFLAG_RECALL)) {
X char *ptr,*p;
X p = ptr = ztrdup(chline);
X for (;*p;p++) if (*p == HISTSPACE) *p = ' ';
X if ((flag & (HISTFLAG_DONE|HISTFLAG_RECALL)) == HISTFLAG_DONE) {
X fprintf(stderr,"%s\n",ptr);
X fflush(stderr);
X }
X if (flag & HISTFLAG_RECALL) {
X permalloc();
X pushnode(bufstack,ptr);
X lastalloc();
X save = 0;
X } else free(ptr);
X }
X curhistent->stim = time(NULL);
X curhistent->ftim = 0L;
X curhistent->flags = 0;
X if (!save) remhist();
X if (chline && !curhistent->lex) hp_free(hp_lex,chline,hlinesz);
X chline = NULL;
X return !(flag & HISTFLAG_NOEXEC || errflag);
X}
X
X/* remove the current line from the history List */
X
Xvoid remhist() /**/
X{
X if (!histremmed) { histremmed = 1; curhist--; }
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 && chline)
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;
Xchar *s,*hs;
X
X for (t0 = curhist-1; hs = quietgetevent(t0); t0--)
X if (s = ztrstr(hs,str)) {
X while (s != hs) if (*s-- == HISTSPACE) 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;
Xchar *hs;
X
X for (t0 = curhist-1; hs = quietgetevent(t0); t0--)
X if (!strncmp(hs,str,strlen(str))) return t0;
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 if (str != cut) *cut = '\0';
X else str[1] = '\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 = tuupper(*str);
X return 1;
X}
X
Xint makelowercase(junkptr) /**/
Xchar **junkptr;
X{
Xchar *str = *junkptr;
X
X for (; *str; str++)
X *str = tulower(*str);
X return 1;
X}
X
Xvoid subst(strptr,in,out,gbal) /**/
Xchar **strptr;char *in;char *out;int gbal;
X{
Xchar *str = *strptr,*cut,*sptr;
Xint off;
X
X while (cut = (char *) ztrstr(str,in)) {
X *cut = '\0';
X sptr = convamps(out,in);
X off = cut-*strptr+strlen(sptr);
X cut += strlen(in);
X *strptr = tricat(*strptr,sptr,cut);
X if (gbal) {
X str = (char *) *strptr+off;
X continue;
X }
X break;
X }
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{
XHistent ent;
X
X if (ev < firsthist()) return NULL;
X ent = gethistent(ev);
X return (lithist) ? ent->lit : ent->lex;
X}
X
Xchar *getevent(ev) /**/
Xint ev;
X{
Xchar *ret;
X
X ret = quietgetevent(ev);
X if (!ret) {
X herrflush();
X zerr("no such event: %d",NULL,ev);
X }
X return ret;
X}
X
Xint getargc(list) /**/
Xchar *list;
X{
Xint argc = 0;
X
X for (; *list; list++) if (*list == HISTSPACE) 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 = tuupper(*pp);
X}
X
Xvoid downcase(x) /**/
Xchar **x;
X{
Xchar *pp = *(char **) x;
X
X for (; *pp; pp++)
X *pp = tulower(*pp);
X}
X
Xint quote(tr) /**/
Xchar **tr;
X{
Xchar *ptr,*rptr,**str = (char **) tr;
Xint len = 3;
X
X for (ptr = *str; *ptr; ptr++,len++)
X if (*ptr == '\'') len += 3;
X ptr = *str;
X *str = rptr = alloc(len);
X *rptr++ = '\'';
X for (; *ptr; ptr++)
X if (*ptr == '\'') {
X *rptr++ = '\''; *rptr++ = '\\'; *rptr++ = '\''; *rptr++ = '\'';
X } else
X *rptr++ = *ptr;
X *rptr++ = '\'';
X *rptr++ = 0;
X str[1] = NULL;
X return 0;
X}
X
Xint quotebreak(tr) /**/
Xchar **tr;
X{
Xchar *ptr,*rptr,**str = (char **) tr;
Xint len = 3;
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 = alloc(len);
X *rptr++ = '\'';
X for (; *ptr; )
X if (*ptr == '\'') {
X *rptr++ = '\''; *rptr++ = '\\'; *rptr++ = '\''; *rptr++ = '\'';
X ptr++;
X } else if (inblank(*ptr)) {
X *rptr++ = '\''; *rptr++ = *ptr++; *rptr++ = '\'';
X } else
X *rptr++ = *ptr++;
X *rptr++ = '\'';
X *rptr++ = '\0';
X return 0;
X}
X
Xvoid herrflush() /**/
X{
X if (strin)
X hflush();
X else while (lastc != '\n' && !lexstop)
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' && !lexstop)
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' && !lexstop)
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
Xvoid inithist() /**/
X{
X hp_lit = zcalloc(sizeof *hp_lit);
X hp_lit->next = NULL;
X hp_lit->ptr = hp_lit->pool = zcalloc(HEAPSIZE);
X hp_lit->free = HEAPSIZE;
X hp_lex = zcalloc(sizeof *hp_lex);
X hp_lex->next = NULL;
X hp_lex->ptr = hp_lex->pool = zcalloc(HEAPSIZE);
X hp_lex->free = HEAPSIZE;
X histentct = (lithistsiz > histsiz) ? lithistsiz : histsiz;
X histentarr = zcalloc(histentct*sizeof *histentarr);
X}
X
Xvoid resizehistents() /**/
X{
Xint newentct,t0,t1,firstlit,firstlex;
XHistent newarr;
X
X newentct = (lithistsiz > histsiz) ? lithistsiz : histsiz;
X newarr = zcalloc(newentct*sizeof *newarr);
X firstlex = curhist-histsiz+1;
X firstlit = curhist-lithistsiz+1;
X t0 = firsthist();
X if (t0 < curhist-newentct) t0 = curhist-newentct;
X t1 = t0 % newentct;
X for (; t0 <= curhist; t0++) {
X newarr[t1] = *gethistent(t0);
X if (t0 < firstlex) newarr[t1].lex = NULL;
X if (t0 < firstlit) newarr[t1].lit = NULL;
X t1++; if (t1 == newentct) t1 = 0;
X }
X free(histentarr);
X histentarr = newarr;
X histentct = newentct;
X}
X
Xchar *hp_alloc(hp,siz) /**/
XHp *hp; int siz;
X{
Xchar *ret;
XHp h = *hp;
X
X if (h->free >= siz) {
X ret = h->ptr;
X h->ptr += siz;
X h->free -= siz;
X return ret;
X }
X#ifdef MEMDEBUG
X fprintf(stderr,"new heap (siz = %d, curhist = %d)\n",siz,curhist);
X#endif
X permalloc();
X h = zalloc(sizeof *h);
X h->next = *hp;
X h->free = (siz > HEAPSIZE) ? siz : HEAPSIZE;
X h->ptr = h->pool = zalloc(h->free);
X h->histno = curhist;
X *hp = h;
X heapalloc();
X return hp_alloc(hp,siz);
X}
X
Xchar *hp_realloc(hp,ptr,oldsiz,newsiz) /**/
XHp *hp; char *ptr; int oldsiz; int newsiz;
X{
XHp h = *hp;
Xint delta = newsiz-oldsiz;
Xchar *ret;
X
X if (h->ptr-oldsiz == ptr && h->free >= delta) {
X h->free -= delta;
X h->ptr += delta;
X return ptr;
X }
X#ifdef MEMDEBUG
X fprintf(stderr,"realloc copy\n");
X#endif
X memcpy(ret = hp_alloc(hp,newsiz),ptr,oldsiz);
X return ret;
X}
X
Xvoid hp_free(h,ptr,siz) /**/
XHp h; char *ptr; int siz;
X{
X if (h->ptr-siz == ptr) {
X h->free += siz;
X h->ptr -= siz;
X }
X}
X
Xchar *hp_concat(old,new) /**/
Xchar *old; char *new;
X{
Xint oldlen,newlen;
X
X oldlen = strlen(old); newlen = strlen(new);
X old = hp_realloc(&hp_lit,old,oldlen+1,oldlen+newlen+1);
X strcpy(old+oldlen,new);
X return old;
X}
X
Xvoid hp_purge(h,lim) /**/
XHp h; int lim;
X{
XHp hlast;
X
X if (!h->next) return;
X while (h->next) { hlast = h; h = h->next; }
X if (hlast->histno <= lim) {
X#ifdef MEMDEBUG
X fprintf(stderr,"purging %d\n",lim);
X#endif
X free(h->pool);
X free(h);
X hlast->next = NULL;
X }
X}
X
Xvoid readhistfile(s,err) /**/
Xchar *s;int err;
X{
Xchar buf[1024];
XFILE *in;
XHistent ent;
Xtime_t tim = time(NULL);
X
X if (!s) return;
X if (in = fopen(s,"r")) {
X while (fgets(buf,sizeof(buf),in)) {
X int l = strlen(buf);
X char *pt = buf;
X
X while (l && buf[l-1] == '\n') {
X buf[l-1] = '\0';
X if (l > 1 && buf[l-2] == '\\') {
X buf[l-2] = '\n';
X fgets(buf+l-1,sizeof(buf)-(l-1),in);
X l = strlen(buf);
X } else break;
X }
X for (;*pt;pt++) if (*pt == ' ') *pt = HISTSPACE;
X
X ent = gethistent(++curhist);
X pt = buf;
X if (*pt == ':') {
X pt++;
X ent->stim = atol(pt);
X for(;*pt != ':' && *pt; pt++)
X ;
X if (*pt) {
X pt++;
X ent->ftim = atol(pt);
X for(;*pt != ':' && *pt; pt++)
X ;
X if (*pt) pt++;
X } else {
X ent->ftim = tim;
X }
X if (ent->stim == 0) ent->stim = tim;
X if (ent->ftim == 0) ent->ftim = tim;
X } else {
X ent->ftim = ent->stim = tim;
X }
X ent->lex = hp_alloc(&hp_lex,strlen(pt)+1);
X strcpy(ent->lex,pt);
X ent->lit = hp_alloc(&hp_lit,strlen(pt)+1);
X strcpy(ent->lit,pt);
X ent->flags = HIST_OLD;
X }
X fclose(in);
X } else if (err)
X zerr("can't read history file",s,0);
X}
X
Xvoid savehistfile(s,err,app) /**/
Xchar *s;int err;int app;
X{
Xchar *t;
XFILE *out;
Xint ev,flag;
XHistent ent;
X
X if (!s || !interact || savehist == 0) return;
X ev = curhist-savehist+1;
X flag = (app & 1) ? O_APPEND : O_TRUNC;
X if (ev < firsthist()) ev = firsthist();
X if (out = fdopen(open(s,O_CREAT|O_WRONLY|flag,0600),"w")) {
X for (; ev <= curhist; ev++) {
X ent = gethistent(ev);
X if (app & 2) {
X if (ent->flags & HIST_OLD) continue;
X ent->flags |= HIST_OLD;
X }
X t = ((lithist) ? ent->lit : ent->lex);
X if (isset(EXTENDEDHISTORY)) {
X fprintf(out, ":%d:%d:", ent->stim,
X ent->ftim);
X }
X for (; *t; t++)
X if (*t == HISTSPACE) fputc(' ',out);
X else {
X if (*t == '\n') fputc('\\',out);
X fputc(*t,out);
X }
X fputc('\n',out);
X }
X fclose(out);
X } else if (err) zerr("can't write history file: %s",s,0);
X}
X
Xint firsthist() /**/
X{
Xint ev;
XHistent ent;
X
X ev = curhist-histentct+1;
X if (ev < 1) ev = 1;
X do {
X ent = gethistent(ev);
X if ((lithist) ? ent->lit : ent->lex) break;
X ev++;
X } while (ev < curhist);
X return ev;
X}
END_OF_FILE
if test 24223 -ne `wc -c <'src/hist.c'`; then
echo shar: \"'src/hist.c'\" unpacked with wrong size!
fi
# end of 'src/hist.c'
fi
echo shar: End of archive 14 \(of 22\).
cp /dev/null ark14isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 22 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still must unpack the following archives:
echo " " ${MISSING}
fi
exit 0
exit 0 # Just in case...