diff options
Diffstat (limited to 'contrib/tcsh/sh.glob.c')
| -rw-r--r-- | contrib/tcsh/sh.glob.c | 1145 |
1 files changed, 0 insertions, 1145 deletions
diff --git a/contrib/tcsh/sh.glob.c b/contrib/tcsh/sh.glob.c deleted file mode 100644 index 9bcd9790a335..000000000000 --- a/contrib/tcsh/sh.glob.c +++ /dev/null @@ -1,1145 +0,0 @@ -/* $Header: /src/pub/tcsh/sh.glob.c,v 3.44 2000/01/14 22:57:28 christos Exp $ */ -/* - * sh.glob.c: Regular expression expansion - */ -/*- - * Copyright (c) 1980, 1991 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -#include "sh.h" - -RCSID("$Id: sh.glob.c,v 3.44 2000/01/14 22:57:28 christos Exp $") - -#include "tc.h" - -#include "glob.h" - -static int noglob; -static int pargsiz, gargsiz; - -/* - * Values for gflag - */ -#define G_NONE 0 /* No globbing needed */ -#define G_GLOB 1 /* string contains *?[] characters */ -#define G_CSH 2 /* string contains ~`{ characters */ - -#define GLOBSPACE 100 /* Alloc increment */ -#define LONGBSIZE 10240 /* Backquote expansion buffer size */ - - -#define LBRC '{' -#define RBRC '}' -#define LBRK '[' -#define RBRK ']' -#define EOS '\0' - -Char **gargv = NULL; -int gargc = 0; -Char **pargv = NULL; -static int pargc = 0; - -/* - * globbing is now done in two stages. In the first pass we expand - * csh globbing idioms ~`{ and then we proceed doing the normal - * globbing if needed ?*[ - * - * Csh type globbing is handled in globexpand() and the rest is - * handled in glob() which is part of the 4.4BSD libc. - * - */ -static Char *globtilde __P((Char **, Char *)); -static Char *handleone __P((Char *, Char **, int)); -static Char **libglob __P((Char **)); -static Char **globexpand __P((Char **)); -static int globbrace __P((Char *, Char *, Char ***)); -static void expbrace __P((Char ***, Char ***, int)); -static int pmatch __P((Char *, Char *, Char **)); -static void pword __P((int)); -static void psave __P((int)); -static void backeval __P((Char *, bool)); - -static Char * -globtilde(nv, s) - Char **nv, *s; -{ - Char gbuf[BUFSIZE], *gstart, *b, *u, *e; -#ifdef apollo - int slash; -#endif - - gstart = gbuf; - *gstart++ = *s++; - u = s; - for (b = gstart, e = &gbuf[BUFSIZE - 1]; - *s && *s != '/' && *s != ':' && b < e; - *b++ = *s++) - continue; - *b = EOS; - if (gethdir(gstart)) { - if (adrof(STRnonomatch)) - return (--u); - blkfree(nv); - if (*gstart) - stderror(ERR_UNKUSER, short2str(gstart)); - else - stderror(ERR_NOHOME); - } - b = &gstart[Strlen(gstart)]; -#ifdef apollo - slash = gstart[0] == '/' && gstart[1] == '\0'; -#endif - while (*s) - *b++ = *s++; - *b = EOS; - --u; - xfree((ptr_t) u); -#ifdef apollo - if (slash && gstart[1] == '/') - gstart++; -#endif - return (Strsave(gstart)); -} - -Char * -globequal(new, old) - Char *new, *old; -{ - int dig; - Char *b, *d; - - /* - * kfk - 17 Jan 1984 - stack hack allows user to get at arbitrary dir names - * in stack. PWP: let =foobar pass through (for X windows) - */ - if (old[1] == '-' && (old[2] == '\0' || old[2] == '/')) { - /* =- */ - dig = -1; - b = &old[2]; - } - else if (Isdigit(old[1])) { - /* =<number> */ - dig = old[1] - '0'; - for (b = &old[2]; Isdigit(*b); b++) - dig = dig * 10 + (*b - '0'); - if (*b != '\0' && *b != '/') - /* =<number>foobar */ - return old; - } - else - /* =foobar */ - return old; - - if (!getstakd(new, dig)) - return NULL; - - /* Copy the rest of the string */ - for (d = &new[Strlen(new)]; - d < &new[BUFSIZE - 1] && (*d++ = *b++) != '\0';) - continue; - *d = '\0'; - - return new; -} - -static int -globbrace(s, p, bl) - Char *s, *p, ***bl; -{ - int i, len; - Char *pm, *pe, *lm, *pl; - Char **nv, **vl; - Char gbuf[BUFSIZE]; - int size = GLOBSPACE; - - nv = vl = (Char **) xmalloc((size_t) (sizeof(Char *) * size)); - *vl = NULL; - - len = 0; - /* copy part up to the brace */ - for (lm = gbuf, p = s; *p != LBRC; *lm++ = *p++) - continue; - - /* check for balanced braces */ - for (i = 0, pe = ++p; *pe; pe++) -#ifdef DSPMBYTE - if (Ismbyte1(*pe) && *(pe + 1) != EOS) - pe ++; - else -#endif /* DSPMBYTE */ - if (*pe == LBRK) { - /* Ignore everything between [] */ - for (++pe; *pe != RBRK && *pe != EOS; pe++) -#ifdef DSPMBYTE - if (Ismbyte1(*pe) && *(pe + 1) != EOS) - pe ++; - else -#endif /* DSPMBYTE */ - continue; - if (*pe == EOS) { - blkfree(nv); - return (-RBRK); - } - } - else if (*pe == LBRC) - i++; - else if (*pe == RBRC) { - if (i == 0) - break; - i--; - } - - if (i != 0 || *pe == '\0') { - blkfree(nv); - return (-RBRC); - } - - for (i = 0, pl = pm = p; pm <= pe; pm++) -#ifdef DSPMBYTE - if (Ismbyte1(*pm) && pm + 1 <= pe) - pm ++; - else -#endif /* DSPMBYTE */ - switch (*pm) { - case LBRK: - for (++pm; *pm != RBRK && *pm != EOS; pm++) -#ifdef DSPMBYTE - if (Ismbyte1(*pm) && *(pm + 1) != EOS) - pm ++; - else -#endif /* DSPMBYTE */ - continue; - if (*pm == EOS) { - *vl = NULL; - blkfree(nv); - return (-RBRK); - } - break; - case LBRC: - i++; - break; - case RBRC: - if (i) { - i--; - break; - } - /* FALLTHROUGH */ - case ',': - if (i && *pm == ',') - break; - else { - Char savec = *pm; - - *pm = EOS; - (void) Strcpy(lm, pl); - (void) Strcat(gbuf, pe + 1); - *pm = savec; - *vl++ = Strsave(gbuf); - len++; - pl = pm + 1; - if (vl == &nv[size]) { - size += GLOBSPACE; - nv = (Char **) xrealloc((ptr_t) nv, - (size_t) (size * sizeof(Char *))); - vl = &nv[size - GLOBSPACE]; - } - } - break; - default: - break; - } - *vl = NULL; - *bl = nv; - return (len); -} - - -static void -expbrace(nvp, elp, size) - Char ***nvp, ***elp; - int size; -{ - Char **vl, **el, **nv, *s; - - vl = nv = *nvp; - if (elp != NULL) - el = *elp; - else - for (el = vl; *el; el++) - continue; - - for (s = *vl; s; s = *++vl) { - Char *b; - Char **vp, **bp; - - /* leave {} untouched for find */ - if (s[0] == '{' && (s[1] == '\0' || (s[1] == '}' && s[2] == '\0'))) - continue; - if ((b = Strchr(s, '{')) != NULL) { - Char **bl; - int len; - -#if defined (DSPMBYTE) - if (b != s && Ismbyte2(*b) && Ismbyte1(*(b-1))) { - /* The "{" is the 2nd byte of a MB character */ - continue; - } -#endif /* DSPMBYTE */ - if ((len = globbrace(s, b, &bl)) < 0) { - xfree((ptr_t) nv); - stderror(ERR_MISSING, -len); - } - xfree((ptr_t) s); - if (len == 1) { - *vl-- = *bl; - xfree((ptr_t) bl); - continue; - } - if (&el[len] >= &nv[size]) { - int l, e; - l = (int) (&el[len] - &nv[size]); - size += GLOBSPACE > l ? GLOBSPACE : l; - l = (int) (vl - nv); - e = (int) (el - nv); - nv = (Char **) xrealloc((ptr_t) nv, - (size_t) (size * sizeof(Char *))); - vl = nv + l; - el = nv + e; - } - /* nv vl el bl - * | | | | - * -.--..-- x-- - * | len - * vp - */ - vp = vl--; - *vp = *bl; - len--; - for (bp = el; bp != vp; bp--) - bp[len] = *bp; - el += len; - /* nv vl el bl - * | | | | - * -.-x --- -- - * |len - * vp - */ - vp++; - for (bp = bl + 1; *bp; *vp++ = *bp++) - continue; - xfree((ptr_t) bl); - } - - } - if (elp != NULL) - *elp = el; - *nvp = nv; -} - -static Char ** -globexpand(v) - Char **v; -{ - Char *s; - Char **nv, **vl, **el; - int size = GLOBSPACE; - - - nv = vl = (Char **) xmalloc((size_t) (sizeof(Char *) * size)); - *vl = NULL; - - /* - * Step 1: expand backquotes. - */ - while ((s = *v++) != '\0') { - if (Strchr(s, '`')) { - int i; - - (void) dobackp(s, 0); - for (i = 0; i < pargc; i++) { - *vl++ = pargv[i]; - if (vl == &nv[size]) { - size += GLOBSPACE; - nv = (Char **) xrealloc((ptr_t) nv, - (size_t) (size * sizeof(Char *))); - vl = &nv[size - GLOBSPACE]; - } - } - xfree((ptr_t) pargv); - pargv = NULL; - } - else { - *vl++ = Strsave(s); - if (vl == &nv[size]) { - size += GLOBSPACE; - nv = (Char **) xrealloc((ptr_t) nv, - (size_t) (size * sizeof(Char *))); - vl = &nv[size - GLOBSPACE]; - } - } - } - *vl = NULL; - - if (noglob) - return (nv); - - /* - * Step 2: expand braces - */ - el = vl; - expbrace(&nv, &el, size); - - - /* - * Step 3: expand ~ = - */ - vl = nv; - for (s = *vl; s; s = *++vl) - switch (*s) { - Char gp[BUFSIZE], *ns; - case '~': - *vl = globtilde(nv, s); - break; - case '=': - if ((ns = globequal(gp, s)) == NULL) { - if (!adrof(STRnonomatch)) { - /* Error */ - blkfree(nv); - stderror(ERR_DEEP); - } - } - if (ns && ns != s) { - /* Expansion succeeded */ - xfree((ptr_t) s); - *vl = Strsave(gp); - } - break; - default: - break; - } - vl = nv; - - /* - * Step 4: expand .. if the variable symlinks==expand is set - */ - if ( symlinks == SYM_EXPAND ) - for (s = *vl; s; s = *++vl) { - *vl = dnormalize(s, 1); - xfree((ptr_t) s); - } - vl = nv; - - return (vl); -} - -static Char * -handleone(str, vl, action) - Char *str, **vl; - int action; -{ - - Char **vlp = vl; - int chars; - Char **t, *p, *strp; - - switch (action) { - case G_ERROR: - setname(short2str(str)); - blkfree(vl); - stderror(ERR_NAME | ERR_AMBIG); - break; - case G_APPEND: - chars = 0; - for (t = vlp; (p = *t++) != '\0'; chars++) - while (*p++) - chars++; - str = (Char *)xmalloc((size_t)(chars * sizeof(Char))); - for (t = vlp, strp = str; (p = *t++) != '\0'; chars++) { - while (*p) - *strp++ = *p++ & TRIM; - *strp++ = ' '; - } - *--strp = '\0'; - blkfree(vl); - break; - case G_IGNORE: - str = Strsave(strip(*vlp)); - blkfree(vl); - break; - default: - break; - } - return (str); -} - -static Char ** -libglob(vl) - Char **vl; -{ - int gflgs = GLOB_QUOTE | GLOB_NOMAGIC | GLOB_ALTNOT; - glob_t globv; - char *ptr; - int nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0; - - if (!vl || !vl[0]) - return(vl); - - globv.gl_offs = 0; - globv.gl_pathv = 0; - globv.gl_pathc = 0; - - if (nonomatch) - gflgs |= GLOB_NOCHECK; - - do { - ptr = short2qstr(*vl); - switch (glob(ptr, gflgs, 0, &globv)) { - case GLOB_ABEND: - globfree(&globv); - setname(ptr); - stderror(ERR_NAME | ERR_GLOB); - /* NOTREACHED */ - case GLOB_NOSPACE: - globfree(&globv); - stderror(ERR_NOMEM); - /* NOTREACHED */ - default: - break; - } - if (globv.gl_flags & GLOB_MAGCHAR) { - match |= (globv.gl_matchc != 0); - magic = 1; - } - gflgs |= GLOB_APPEND; - } - while (*++vl); - vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ? - NULL : blk2short(globv.gl_pathv); - globfree(&globv); - return (vl); -} - -Char * -globone(str, action) - Char *str; - int action; -{ - - Char *v[2], **vl, **vo; - int gflg; - - noglob = adrof(STRnoglob) != 0; - gflag = 0; - v[0] = str; - v[1] = 0; - tglob(v); - gflg = gflag; - if (gflg == G_NONE) - return (strip(Strsave(str))); - - if (gflg & G_CSH) { - /* - * Expand back-quote, tilde and brace - */ - vo = globexpand(v); - if (noglob || (gflg & G_GLOB) == 0) { - if (vo[0] == NULL) { - xfree((ptr_t) vo); - return (Strsave(STRNULL)); - } - if (vo[1] != NULL) - return (handleone(str, vo, action)); - else { - str = strip(vo[0]); - xfree((ptr_t) vo); - return (str); - } - } - } - else if (noglob || (gflg & G_GLOB) == 0) - return (strip(Strsave(str))); - else - vo = v; - - vl = libglob(vo); - if ((gflg & G_CSH) && vl != vo) - blkfree(vo); - if (vl == NULL) { - setname(short2str(str)); - stderror(ERR_NAME | ERR_NOMATCH); - } - if (vl[0] == NULL) { - xfree((ptr_t) vl); - return (Strsave(STRNULL)); - } - if (vl[1]) - return (handleone(str, vl, action)); - else { - str = strip(*vl); - xfree((ptr_t) vl); - return (str); - } -} - -Char ** -globall(v) - Char **v; -{ - Char **vl, **vo; - int gflg = gflag; - - if (!v || !v[0]) { - gargv = saveblk(v); - gargc = blklen(gargv); - return (gargv); - } - - noglob = adrof(STRnoglob) != 0; - - if (gflg & G_CSH) - /* - * Expand back-quote, tilde and brace - */ - vl = vo = globexpand(v); - else - vl = vo = saveblk(v); - - if (!noglob && (gflg & G_GLOB)) { - vl = libglob(vo); - if (vl != vo) - blkfree(vo); - } - else - trim(vl); - - gargc = vl ? blklen(vl) : 0; - return (gargv = vl); -} - -void -ginit() -{ - gargsiz = GLOBSPACE; - gargv = (Char **) xmalloc((size_t) (sizeof(Char *) * gargsiz)); - gargv[0] = 0; - gargc = 0; -} - -void -rscan(t, f) - register Char **t; - void (*f) __P((int)); -{ - register Char *p; - - while ((p = *t++) != '\0') - while (*p) - (*f) (*p++); -} - -void -trim(t) - register Char **t; -{ - register Char *p; - - while ((p = *t++) != '\0') - while (*p) - *p++ &= TRIM; -} - -void -tglob(t) - register Char **t; -{ - register Char *p, *c; - - while ((p = *t++) != '\0') { - if (*p == '~' || *p == '=') - gflag |= G_CSH; - else if (*p == '{' && - (p[1] == '\0' || (p[1] == '}' && p[2] == '\0'))) - continue; - /* - * The following line used to be *(c = p++), but hp broke their - * optimizer in 9.01, so we break the assignment into two pieces - * The careful reader here will note that *most* compiler workarounds - * in tcsh are either for apollo/DomainOS or hpux. Is it a coincidence? - */ - while ( *(c = p) != '\0') { - p++; - if (*c == '`') { - gflag |= G_CSH; -#ifdef notdef - /* - * We do want to expand echo `echo '*'`, so we don't\ - * use this piece of code anymore. - */ - while (*p && *p != '`') - if (*p++ == '\\') { - if (*p) /* Quoted chars */ - p++; - else - break; - } - if (*p) /* The matching ` */ - p++; - else - break; -#endif - } - else if (*c == '{') - gflag |= G_CSH; - else if (isglob(*c)) - gflag |= G_GLOB; - else if (symlinks == SYM_EXPAND && - *p && ISDOTDOT(c) && (c == *(t-1) || *(c-1) == '/') ) - gflag |= G_CSH; - } - } -} - -/* - * Command substitute cp. If literal, then this is a substitution from a - * << redirection, and so we should not crunch blanks and tabs, separating - * words only at newlines. - */ -Char ** -dobackp(cp, literal) - Char *cp; - bool literal; -{ - register Char *lp, *rp; - Char *ep, word[LONGBSIZE]; - - if (pargv) { -#ifdef notdef - abort(); -#endif - blkfree(pargv); - } - pargsiz = GLOBSPACE; - pargv = (Char **) xmalloc((size_t) (sizeof(Char *) * pargsiz)); - pargv[0] = NULL; - pargcp = pargs = word; - pargc = 0; - pnleft = LONGBSIZE - 4; - for (;;) { -#if defined(DSPMBYTE) - for (lp = cp;; lp++) { - if (*lp == '`' && - (lp-1 < cp || !Ismbyte2(*lp) || !Ismbyte1(*(lp-1)))) { - break; - } -#else /* DSPMBYTE */ - for (lp = cp; *lp != '`'; lp++) { -#endif /* DSPMBYTE */ - if (*lp == 0) { - if (pargcp != pargs) - pword(LONGBSIZE); - return (pargv); - } - psave(*lp); - } - lp++; - for (rp = lp; *rp && *rp != '`'; rp++) - if (*rp == '\\') { - rp++; - if (!*rp) - goto oops; - } - if (!*rp) - oops: stderror(ERR_UNMATCHED, '`'); - ep = Strsave(lp); - ep[rp - lp] = 0; - backeval(ep, literal); - cp = rp + 1; - } -} - - -static void -backeval(cp, literal) - Char *cp; - bool literal; -{ - register int icnt, c; - register Char *ip; - struct command faket; - bool hadnl; - int pvec[2], quoted; - Char *fakecom[2], ibuf[BUFSIZE]; - char tibuf[BUFSIZE]; - - hadnl = 0; - icnt = 0; - quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0; - faket.t_dtyp = NODE_COMMAND; - faket.t_dflg = F_BACKQ; - faket.t_dlef = 0; - faket.t_drit = 0; - faket.t_dspr = 0; - faket.t_dcom = fakecom; - fakecom[0] = STRfakecom1; - fakecom[1] = 0; - - /* - * We do the psave job to temporarily change the current job so that the - * following fork is considered a separate job. This is so that when - * backquotes are used in a builtin function that calls glob the "current - * job" is not corrupted. We only need one level of pushed jobs as long as - * we are sure to fork here. - */ - psavejob(); - - /* - * It would be nicer if we could integrate this redirection more with the - * routines in sh.sem.c by doing a fake execute on a builtin function that - * was piped out. - */ - mypipe(pvec); - if (pfork(&faket, -1) == 0) { - struct command *t; - - (void) close(pvec[0]); - (void) dmove(pvec[1], 1); - (void) dmove(SHDIAG, 2); - initdesc(); - /* - * Bugfix for nested backquotes by Michael Greim <greim@sbsvax.UUCP>, - * posted to comp.bugs.4bsd 12 Sep. 1989. - */ - if (pargv) /* mg, 21.dec.88 */ - blkfree(pargv), pargv = 0, pargsiz = 0; - /* mg, 21.dec.88 */ - arginp = cp; - while (*cp) - *cp++ &= TRIM; - - /* - * In the child ``forget'' everything about current aliases or - * eval vectors. - */ - alvec = NULL; - evalvec = NULL; - alvecp = NULL; - evalp = NULL; - (void) lex(¶ml); - if (seterr) - stderror(ERR_OLD); - alias(¶ml); - t = syntax(paraml.next, ¶ml, 0); - if (seterr) - stderror(ERR_OLD); - if (t) - t->t_dflg |= F_NOFORK; -#ifdef SIGTSTP - (void) sigignore(SIGTSTP); -#endif -#ifdef SIGTTIN - (void) sigignore(SIGTTIN); -#endif -#ifdef SIGTTOU - (void) sigignore(SIGTTOU); -#endif - execute(t, -1, NULL, NULL); - exitstat(); - } - xfree((ptr_t) cp); - (void) close(pvec[1]); - c = 0; - ip = NULL; - do { - int cnt = 0; - - for (;;) { - if (icnt == 0) { - int i; - - ip = ibuf; - do - icnt = read(pvec[0], tibuf, BUFSIZE); - while (icnt == -1 && errno == EINTR); - if (icnt <= 0) { - c = -1; - break; - } - for (i = 0; i < icnt; i++) - ip[i] = (unsigned char) tibuf[i]; - } - if (hadnl) - break; - --icnt; - c = (*ip++ & TRIM); - if (c == 0) - break; -#ifdef WINNT - if (c == '\r') - c = ' '; -#endif /* WINNT */ - if (c == '\n') { - /* - * Continue around the loop one more time, so that we can eat - * the last newline without terminating this word. - */ - hadnl = 1; - continue; - } - if (!quoted && (c == ' ' || c == '\t')) - break; - cnt++; - psave(c | quoted); - } - /* - * Unless at end-of-file, we will form a new word here if there were - * characters in the word, or in any case when we take text literally. - * If we didn't make empty words here when literal was set then we - * would lose blank lines. - */ - if (c != -1 && (cnt || literal)) - pword(BUFSIZE); - hadnl = 0; - } while (c >= 0); - (void) close(pvec[0]); - pwait(); - prestjob(); -} - -static void -psave(c) - int c; -{ - if (--pnleft <= 0) - stderror(ERR_WTOOLONG); - *pargcp++ = (Char) c; -} - -static void -pword(bufsiz) - int bufsiz; -{ - psave(0); - if (pargc == pargsiz - 1) { - pargsiz += GLOBSPACE; - pargv = (Char **) xrealloc((ptr_t) pargv, - (size_t) (pargsiz * sizeof(Char *))); - } - pargv[pargc++] = Strsave(pargs); - pargv[pargc] = NULL; - pargcp = pargs; - pnleft = bufsiz - 4; -} - -int -Gmatch(string, pattern) - Char *string, *pattern; -{ - return Gnmatch(string, pattern, NULL); -} - -int -Gnmatch(string, pattern, endstr) - Char *string, *pattern, **endstr; -{ - Char **blk, **p, *tstring = string; - int gpol = 1, gres = 0; - - if (*pattern == '^') { - gpol = 0; - pattern++; - } - - blk = (Char **) xmalloc((size_t) (GLOBSPACE * sizeof(Char *))); - blk[0] = Strsave(pattern); - blk[1] = NULL; - - expbrace(&blk, NULL, GLOBSPACE); - - if (endstr == NULL) - /* Exact matches only */ - for (p = blk; *p; p++) - gres |= pmatch(string, *p, &tstring) == 2 ? 1 : 0; - else { - /* partial matches */ - int minc = 0x7fffffff; - for (p = blk; *p; p++) - if (pmatch(string, *p, &tstring) != 0) { - int t = (int) (tstring - string); - gres |= 1; - if (minc == -1 || minc > t) - minc = t; - } - *endstr = string + minc; - } - - blkfree(blk); - return(gres == gpol); -} - -/* pmatch(): - * Return 2 on exact match, - * Return 1 on substring match. - * Return 0 on no match. - * *estr will point to the end of the longest exact or substring match. - */ -static int -pmatch(string, pattern, estr) - register Char *string, *pattern, **estr; -{ - register Char stringc, patternc; - int match, negate_range; - Char rangec, *oestr, *pestr; - - for (;; ++string) { - stringc = *string & TRIM; - /* - * apollo compiler bug: switch (patternc = *pattern++) dies - */ - patternc = *pattern++; - switch (patternc) { - case 0: - *estr = string; - return (stringc == 0 ? 2 : 1); - case '?': - if (stringc == 0) - return (0); - *estr = string; - break; - case '*': - if (!*pattern) { - while (*string) string++; - *estr = string; - return (2); - } - oestr = *estr; - pestr = NULL; - - do { - switch(pmatch(string, pattern, estr)) { - case 0: - break; - case 1: - pestr = *estr; - break; - case 2: - return 2; - default: - abort(); /* Cannot happen */ - } - *estr = string; - } - while (*string++); - - if (pestr) { - *estr = pestr; - return 1; - } - else { - *estr = oestr; - return 0; - } - - case '[': - match = 0; - if ((negate_range = (*pattern == '^')) != 0) - pattern++; - while ((rangec = *pattern++) != '\0') { - if (rangec == ']') - break; - if (match) - continue; - if (rangec == '-' && *(pattern-2) != '[' && *pattern != ']') { - match = (globcharcoll(stringc, *pattern & TRIM) <= 0 && - globcharcoll(*(pattern-2) & TRIM, stringc) <= 0); - pattern++; - } - else - match = (stringc == (rangec & TRIM)); - } - if (rangec == 0) - stderror(ERR_NAME | ERR_MISSING, ']'); - if (match == negate_range) - return (0); - *estr = string; - break; - default: - if ((patternc & TRIM) != stringc) - return (0); - *estr = string; - break; - } - } -} - -void -Gcat(s1, s2) - Char *s1, *s2; -{ - register Char *p, *q; - int n; - - for (p = s1; *p++;) - continue; - for (q = s2; *q++;) - continue; - n = (int) ((p - s1) + (q - s2) - 1); - if (++gargc >= gargsiz) { - gargsiz += GLOBSPACE; - gargv = (Char **) xrealloc((ptr_t) gargv, - (size_t) (gargsiz * sizeof(Char *))); - } - gargv[gargc] = 0; - p = gargv[gargc - 1] = (Char *) xmalloc((size_t) (n * sizeof(Char))); - for (q = s1; (*p++ = *q++) != '\0';) - continue; - for (p--, q = s2; (*p++ = *q++) != '\0';) - continue; -} - -#ifdef FILEC -int -sortscmp(a, b) - register Char **a, **b; -{ - if (!a) /* check for NULL */ - return (b ? 1 : 0); - if (!b) - return (-1); - - if (!*a) /* check for NULL */ - return (*b ? 1 : 0); - if (!*b) - return (-1); - - return (int) collate(*a, *b); -} - -#endif |
