source: trunk/third/tcsh/sh.glob.c @ 12039

Revision 12039, 22.4 KB checked in by danw, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12038, which included commits to RCS files with non-trunk default branches.
RevLine 
[12038]1/* $Header: /afs/dev.mit.edu/source/repository/third/tcsh/sh.glob.c,v 1.1.1.2 1998-10-03 21:10:01 danw Exp $ */
[9005]2/*
3 * sh.glob.c: Regular expression expansion
4 */
5/*-
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *      This product includes software developed by the University of
20 *      California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 *    may be used to endorse or promote products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37#include "sh.h"
38
[12038]39RCSID("$Id: sh.glob.c,v 1.1.1.2 1998-10-03 21:10:01 danw Exp $")
[9005]40
41#include "tc.h"
42
43#include "glob.h"
44
45static int noglob;
46static int pargsiz, gargsiz;
47
48/*
49 * Values for gflag
50 */
51#define G_NONE  0               /* No globbing needed                   */
52#define G_GLOB  1               /* string contains *?[] characters      */
53#define G_CSH   2               /* string contains ~`{ characters       */
54
55#define GLOBSPACE       100     /* Alloc increment                      */
[12038]56#define LONGBSIZE       10240   /* Backquote expansion buffer size      */
[9005]57
[12038]58
[9005]59#define LBRC '{'
60#define RBRC '}'
61#define LBRK '['
62#define RBRK ']'
63#define EOS '\0'
64
65Char  **gargv = NULL;
[12038]66int     gargc = 0;
[9005]67Char  **pargv = NULL;
[12038]68static int pargc = 0;
[9005]69
70/*
71 * globbing is now done in two stages. In the first pass we expand
72 * csh globbing idioms ~`{ and then we proceed doing the normal
73 * globbing if needed ?*[
74 *
75 * Csh type globbing is handled in globexpand() and the rest is
76 * handled in glob() which is part of the 4.4BSD libc.
77 *
78 */
79static  Char     *globtilde     __P((Char **, Char *));
[12038]80static  Char     *handleone     __P((Char *, Char **, int));
[9005]81static  Char    **libglob       __P((Char **));
82static  Char    **globexpand    __P((Char **));
83static  int       globbrace     __P((Char *, Char *, Char ***));
84static  void      expbrace      __P((Char ***, Char ***, int));
85static  int       pmatch        __P((Char *, Char *, Char **));
[12038]86static  void      pword         __P((int));
[9005]87static  void      psave         __P((int));
88static  void      backeval      __P((Char *, bool));
89
90static Char *
91globtilde(nv, s)
92    Char  **nv, *s;
93{
94    Char    gbuf[BUFSIZE], *gstart, *b, *u, *e;
95#ifdef apollo
96    int slash;
97#endif
98
99    gstart = gbuf;
100    *gstart++ = *s++;
101    u = s;
102    for (b = gstart, e = &gbuf[BUFSIZE - 1];
103         *s && *s != '/' && *s != ':' && b < e;
104         *b++ = *s++)
105        continue;
106    *b = EOS;
107    if (gethdir(gstart)) {
[12038]108        if (adrof(STRnonomatch))
109            return (--u);
[9005]110        blkfree(nv);
111        if (*gstart)
112            stderror(ERR_UNKUSER, short2str(gstart));
113        else
114            stderror(ERR_NOHOME);
115    }
116    b = &gstart[Strlen(gstart)];
117#ifdef apollo
118    slash = gstart[0] == '/' && gstart[1] == '\0';
119#endif
120    while (*s)
121        *b++ = *s++;
122    *b = EOS;
123    --u;
124    xfree((ptr_t) u);
125#ifdef apollo
126    if (slash && gstart[1] == '/')
127        gstart++;
128#endif
129    return (Strsave(gstart));
130}
131
132Char *
133globequal(new, old)
134    Char *new, *old;
135{
136    int     dig;
137    Char    *b, *d;
138
139    /*
140     * kfk - 17 Jan 1984 - stack hack allows user to get at arbitrary dir names
141     * in stack. PWP: let =foobar pass through (for X windows)
142     */
143    if (old[1] == '-' && (old[2] == '\0' || old[2] == '/')) {
144        /* =- */
145        dig = -1;
146        b = &old[2];
147    }
148    else if (Isdigit(old[1])) {
149        /* =<number> */
150        dig = old[1] - '0';
151        for (b = &old[2]; Isdigit(*b); b++)
152            dig = dig * 10 + (*b - '0');
153        if (*b != '\0' && *b != '/')
154            /* =<number>foobar */
155            return old;
156    }
157    else
158        /* =foobar */
159        return old;
160
161    if (!getstakd(new, dig))
162        return NULL;
163
164    /* Copy the rest of the string */
165    for (d = &new[Strlen(new)];
166         d < &new[BUFSIZE - 1] && (*d++ = *b++) != '\0';)
167        continue;
168    *d = '\0';
169
170    return new;
171}
172
173static int
174globbrace(s, p, bl)
175    Char   *s, *p, ***bl;
176{
177    int     i, len;
178    Char   *pm, *pe, *lm, *pl;
179    Char  **nv, **vl;
180    Char    gbuf[BUFSIZE];
181    int     size = GLOBSPACE;
182
183    nv = vl = (Char **) xmalloc((size_t) (sizeof(Char *) * size));
184    *vl = NULL;
185
186    len = 0;
187    /* copy part up to the brace */
188    for (lm = gbuf, p = s; *p != LBRC; *lm++ = *p++)
189        continue;
190
191    /* check for balanced braces */
192    for (i = 0, pe = ++p; *pe; pe++)
193        if (*pe == LBRK) {
194            /* Ignore everything between [] */
195            for (++pe; *pe != RBRK && *pe != EOS; pe++)
196                continue;
197            if (*pe == EOS) {
198                blkfree(nv);
199                return (-RBRK);
200            }
201        }
202        else if (*pe == LBRC)
203            i++;
204        else if (*pe == RBRC) {
205            if (i == 0)
206                break;
207            i--;
208        }
209
210    if (i != 0 || *pe == '\0') {
211        blkfree(nv);
212        return (-RBRC);
213    }
214
215    for (i = 0, pl = pm = p; pm <= pe; pm++)
216        switch (*pm) {
217        case LBRK:
218            for (++pm; *pm != RBRK && *pm != EOS; pm++)
219                continue;
220            if (*pm == EOS) {
221                *vl = NULL;
222                blkfree(nv);
223                return (-RBRK);
224            }
225            break;
226        case LBRC:
227            i++;
228            break;
229        case RBRC:
230            if (i) {
231                i--;
232                break;
233            }
234            /* FALLTHROUGH */
235        case ',':
236            if (i && *pm == ',')
237                break;
238            else {
239                Char    savec = *pm;
240
241                *pm = EOS;
242                (void) Strcpy(lm, pl);
243                (void) Strcat(gbuf, pe + 1);
244                *pm = savec;
245                *vl++ = Strsave(gbuf);
246                len++;
247                pl = pm + 1;
248                if (vl == &nv[size]) {
249                    size += GLOBSPACE;
250                    nv = (Char **) xrealloc((ptr_t) nv,
251                                            (size_t) (size * sizeof(Char *)));
252                    vl = &nv[size - GLOBSPACE];
253                }
254            }
255            break;
256        default:
257            break;
258        }
259    *vl = NULL;
260    *bl = nv;
261    return (len);
262}
263
264
265static void
266expbrace(nvp, elp, size)
267    Char ***nvp, ***elp;
268    int size;
269{
270    Char **vl, **el, **nv, *s;
271
272    vl = nv = *nvp;
273    if (elp != NULL)
274        el = *elp;
275    else
276        for (el = vl; *el; el++)
277            continue;
278
279    for (s = *vl; s; s = *++vl) {
280        Char   *b;
281        Char  **vp, **bp;
282
283        /* leave {} untouched for find */
284        if (s[0] == '{' && (s[1] == '\0' || (s[1] == '}' && s[2] == '\0')))
285            continue;
286        if ((b = Strchr(s, '{')) != NULL) {
287            Char  **bl;
288            int     len;
289
290            if ((len = globbrace(s, b, &bl)) < 0) {
291                xfree((ptr_t) nv);
292                stderror(ERR_MISSING, -len);
293            }
294            xfree((ptr_t) s);
295            if (len == 1) {
296                *vl-- = *bl;
297                xfree((ptr_t) bl);
298                continue;
299            }
300            if (&el[len] >= &nv[size]) {
301                int     l, e;
302                l = &el[len] - &nv[size];
303                size += GLOBSPACE > l ? GLOBSPACE : l;
304                l = vl - nv;
305                e = el - nv;
306                nv = (Char **) xrealloc((ptr_t) nv,
307                                        (size_t) (size * sizeof(Char *)));
308                vl = nv + l;
309                el = nv + e;
310            }
311            /* nv vl   el     bl
312             * |  |    |      |
313             * -.--..--       x--
314             *   |            len
315             *   vp
316             */
317            vp = vl--;
318            *vp = *bl;
319            len--;
320            for (bp = el; bp != vp; bp--)
321                bp[len] = *bp;
322            el += len;
323            /* nv vl    el bl
324             * |  |     |  |
325             * -.-x  ---    --
326             *   |len
327             *   vp
328             */
329            vp++;
330            for (bp = bl + 1; *bp; *vp++ = *bp++)
331                continue;
332            xfree((ptr_t) bl);
333        }
334
335    }
336    if (elp != NULL)
337        *elp = el;
338    *nvp = nv;
339}
340
341static Char **
342globexpand(v)
343    Char  **v;
344{
345    Char   *s;
346    Char  **nv, **vl, **el;
347    int     size = GLOBSPACE;
348
349
350    nv = vl = (Char **) xmalloc((size_t) (sizeof(Char *) * size));
351    *vl = NULL;
352
353    /*
354     * Step 1: expand backquotes.
355     */
356    while ((s = *v++) != '\0') {
357        if (Strchr(s, '`')) {
358            int     i;
359
360            (void) dobackp(s, 0);
361            for (i = 0; i < pargc; i++) {
362                *vl++ = pargv[i];
363                if (vl == &nv[size]) {
364                    size += GLOBSPACE;
365                    nv = (Char **) xrealloc((ptr_t) nv,
366                                            (size_t) (size * sizeof(Char *)));
367                    vl = &nv[size - GLOBSPACE];
368                }
369            }
370            xfree((ptr_t) pargv);
371            pargv = NULL;
372        }
373        else {
374            *vl++ = Strsave(s);
375            if (vl == &nv[size]) {
376                size += GLOBSPACE;
377                nv = (Char **) xrealloc((ptr_t) nv,
378                                        (size_t) (size * sizeof(Char *)));
379                vl = &nv[size - GLOBSPACE];
380            }
381        }
382    }
383    *vl = NULL;
384
385    if (noglob)
386        return (nv);
387
388    /*
389     * Step 2: expand braces
390     */
391    el = vl;
392    expbrace(&nv, &el, size);
393
394
395    /*
396     * Step 3: expand ~ =
397     */
398    vl = nv;
399    for (s = *vl; s; s = *++vl)
400        switch (*s) {
401            Char gp[BUFSIZE], *ns;
402        case '~':
403            *vl = globtilde(nv, s);
404            break;
405        case '=':
406            if ((ns = globequal(gp, s)) == NULL) {
[12038]407                if (!adrof(STRnonomatch)) {
408                    /* Error */
409                    blkfree(nv);
410                    stderror(ERR_DEEP);
411                }
[9005]412            }
[12038]413            if (ns && ns != s) {
[9005]414                /* Expansion succeeded */
415                xfree((ptr_t) s);
416                *vl = Strsave(gp);
417            }
418            break;
419        default:
420            break;
421        }
422    vl = nv;
423
424    /*
425     * Step 4: expand .. if the variable symlinks==expand is set
426     */
427    if ( symlinks == SYM_EXPAND )
428        for (s = *vl; s; s = *++vl) {
429            *vl = dnormalize(s, 1);
430            xfree((ptr_t) s);
431        }
432    vl = nv;
433
434    return (vl);
435}
436
437static Char *
438handleone(str, vl, action)
439    Char   *str, **vl;
440    int     action;
441{
442
[12038]443    Char   **vlp = vl;
444    int chars;
445    Char **t, *p, *strp;
[9005]446
447    switch (action) {
448    case G_ERROR:
449        setname(short2str(str));
450        blkfree(vl);
451        stderror(ERR_NAME | ERR_AMBIG);
452        break;
453    case G_APPEND:
[12038]454        chars = 0;
455        for (t = vlp; (p = *t++) != '\0'; chars++)
456            while (*p++)
457                chars++;
458        str = (Char *)xmalloc((size_t)(chars * sizeof(Char)));
459        for (t = vlp, strp = str; (p = *t++) != '\0'; chars++) {
460            while (*p)
461                 *strp++ = *p++ & TRIM;
462            *strp++ = ' ';
[9005]463        }
[12038]464        *--strp = '\0';
[9005]465        blkfree(vl);
466        break;
467    case G_IGNORE:
468        str = Strsave(strip(*vlp));
469        blkfree(vl);
470        break;
471    default:
472        break;
473    }
474    return (str);
475}
476
477static Char **
478libglob(vl)
479    Char  **vl;
480{
481    int     gflgs = GLOB_QUOTE | GLOB_NOMAGIC | GLOB_ALTNOT;
482    glob_t  globv;
483    char   *ptr;
484    int     nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0;
485
486    if (!vl || !vl[0])
487        return(vl);
488
489    globv.gl_offs = 0;
490    globv.gl_pathv = 0;
491    globv.gl_pathc = 0;
492
493    if (nonomatch)
494        gflgs |= GLOB_NOCHECK;
495
496    do {
497        ptr = short2qstr(*vl);
498        switch (glob(ptr, gflgs, 0, &globv)) {
499        case GLOB_ABEND:
500            globfree(&globv);
501            setname(ptr);
502            stderror(ERR_NAME | ERR_GLOB);
503            /* NOTREACHED */
504        case GLOB_NOSPACE:
505            globfree(&globv);
506            stderror(ERR_NOMEM);
507            /* NOTREACHED */
508        default:
509            break;
510        }
511        if (globv.gl_flags & GLOB_MAGCHAR) {
512            match |= (globv.gl_matchc != 0);
513            magic = 1;
514        }
515        gflgs |= GLOB_APPEND;
516    }
517    while (*++vl);
518    vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ?
519        NULL : blk2short(globv.gl_pathv);
520    globfree(&globv);
521    return (vl);
522}
523
524Char   *
525globone(str, action)
526    Char   *str;
527    int     action;
528{
529
530    Char   *v[2], **vl, **vo;
531    int gflg;
532
533    noglob = adrof(STRnoglob) != 0;
534    gflag = 0;
535    v[0] = str;
536    v[1] = 0;
537    tglob(v);
538    gflg = gflag;
539    if (gflg == G_NONE)
540        return (strip(Strsave(str)));
541
542    if (gflg & G_CSH) {
543        /*
544         * Expand back-quote, tilde and brace
545         */
546        vo = globexpand(v);
547        if (noglob || (gflg & G_GLOB) == 0) {
548            if (vo[0] == NULL) {
549                xfree((ptr_t) vo);
550                return (Strsave(STRNULL));
551            }
552            if (vo[1] != NULL)
553                return (handleone(str, vo, action));
554            else {
555                str = strip(vo[0]);
556                xfree((ptr_t) vo);
557                return (str);
558            }
559        }
560    }
561    else if (noglob || (gflg & G_GLOB) == 0)
562        return (strip(Strsave(str)));
563    else
564        vo = v;
565
566    vl = libglob(vo);
567    if ((gflg & G_CSH) && vl != vo)
568        blkfree(vo);
569    if (vl == NULL) {
570        setname(short2str(str));
571        stderror(ERR_NAME | ERR_NOMATCH);
572    }
573    if (vl[0] == NULL) {
574        xfree((ptr_t) vl);
575        return (Strsave(STRNULL));
576    }
577    if (vl[1])
578        return (handleone(str, vl, action));
579    else {
580        str = strip(*vl);
581        xfree((ptr_t) vl);
582        return (str);
583    }
584}
585
586Char  **
587globall(v)
588    Char  **v;
589{
590    Char  **vl, **vo;
591    int gflg = gflag;
592
593    if (!v || !v[0]) {
594        gargv = saveblk(v);
595        gargc = blklen(gargv);
596        return (gargv);
597    }
598
599    noglob = adrof(STRnoglob) != 0;
600
601    if (gflg & G_CSH)
602        /*
603         * Expand back-quote, tilde and brace
604         */
605        vl = vo = globexpand(v);
606    else
607        vl = vo = saveblk(v);
608
609    if (!noglob && (gflg & G_GLOB)) {
610        vl = libglob(vo);
611        if (vl != vo)
612            blkfree(vo);
613    }
614    else
615        trim(vl);
616
617    gargc = vl ? blklen(vl) : 0;
618    return (gargv = vl);
619}
620
621void
622ginit()
623{
624    gargsiz = GLOBSPACE;
625    gargv = (Char **) xmalloc((size_t) (sizeof(Char *) * gargsiz));
626    gargv[0] = 0;
627    gargc = 0;
628}
629
630void
631rscan(t, f)
632    register Char **t;
[12038]633    void    (*f) __P((int));
[9005]634{
635    register Char *p;
636
637    while ((p = *t++) != '\0')
638        while (*p)
639            (*f) (*p++);
640}
641
642void
643trim(t)
644    register Char **t;
645{
646    register Char *p;
647
648    while ((p = *t++) != '\0')
649        while (*p)
650            *p++ &= TRIM;
651}
652
653void
654tglob(t)
655    register Char **t;
656{
657    register Char *p, *c;
658
659    while ((p = *t++) != '\0') {
660        if (*p == '~' || *p == '=')
661            gflag |= G_CSH;
662        else if (*p == '{' &&
663                 (p[1] == '\0' || (p[1] == '}' && p[2] == '\0')))
664            continue;
[12038]665        /*
666         * The following line used to be *(c = p++), but hp broke their
667         * optimizer in 9.01, so we break the assignment into two pieces
668         * The careful reader here will note that *most* compiler workarounds
669         * in tcsh are either for apollo/DomainOS or hpux. Is it a coincidence?
670         */
671        while ( *(c = p) != '\0') {
672            p++;
[9005]673            if (*c == '`') {
674                gflag |= G_CSH;
[12038]675#ifdef notdef
676                /*
677                 * We do want to expand echo `echo '*'`, so we don't\
678                 * use this piece of code anymore.
679                 */
[9005]680                while (*p && *p != '`')
681                    if (*p++ == '\\') {
682                        if (*p)         /* Quoted chars */
683                            p++;
684                        else
685                            break;
686                    }
687                if (*p)                 /* The matching ` */
688                    p++;
689                else
690                    break;
[12038]691#endif
[9005]692            }
693            else if (*c == '{')
694                gflag |= G_CSH;
695            else if (isglob(*c))
696                gflag |= G_GLOB;
697            else if (symlinks == SYM_EXPAND &&
698                *p && ISDOTDOT(c) && (c == *(t-1) || *(c-1) == '/') )
699                gflag |= G_CSH;
700        }
701    }
702}
703
704/*
705 * Command substitute cp.  If literal, then this is a substitution from a
706 * << redirection, and so we should not crunch blanks and tabs, separating
707 * words only at newlines.
708 */
709Char  **
710dobackp(cp, literal)
711    Char   *cp;
712    bool    literal;
713{
714    register Char *lp, *rp;
[12038]715    Char   *ep, word[LONGBSIZE];
[9005]716
717    if (pargv) {
718#ifdef notdef
719        abort();
720#endif
721        blkfree(pargv);
722    }
723    pargsiz = GLOBSPACE;
724    pargv = (Char **) xmalloc((size_t) (sizeof(Char *) * pargsiz));
725    pargv[0] = NULL;
726    pargcp = pargs = word;
727    pargc = 0;
[12038]728    pnleft = LONGBSIZE - 4;
[9005]729    for (;;) {
730        for (lp = cp; *lp != '`'; lp++) {
731            if (*lp == 0) {
732                if (pargcp != pargs)
[12038]733                    pword(LONGBSIZE);
[9005]734                return (pargv);
735            }
736            psave(*lp);
737        }
738        lp++;
739        for (rp = lp; *rp && *rp != '`'; rp++)
740            if (*rp == '\\') {
741                rp++;
742                if (!*rp)
743                    goto oops;
744            }
745        if (!*rp)
746    oops:  stderror(ERR_UNMATCHED, '`');
747        ep = Strsave(lp);
748        ep[rp - lp] = 0;
749        backeval(ep, literal);
750        cp = rp + 1;
751    }
752}
753
754
755static void
756backeval(cp, literal)
757    Char   *cp;
758    bool    literal;
759{
760    register int icnt, c;
761    register Char *ip;
762    struct command faket;
763    bool    hadnl;
764    int     pvec[2], quoted;
765    Char   *fakecom[2], ibuf[BUFSIZE];
766    char    tibuf[BUFSIZE];
767
768    hadnl = 0;
769    icnt = 0;
770    quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0;
771    faket.t_dtyp = NODE_COMMAND;
772    faket.t_dflg = F_BACKQ;
773    faket.t_dlef = 0;
774    faket.t_drit = 0;
775    faket.t_dspr = 0;
776    faket.t_dcom = fakecom;
777    fakecom[0] = STRfakecom1;
778    fakecom[1] = 0;
779
780    /*
781     * We do the psave job to temporarily change the current job so that the
782     * following fork is considered a separate job.  This is so that when
783     * backquotes are used in a builtin function that calls glob the "current
784     * job" is not corrupted.  We only need one level of pushed jobs as long as
785     * we are sure to fork here.
786     */
787    psavejob();
788
789    /*
790     * It would be nicer if we could integrate this redirection more with the
791     * routines in sh.sem.c by doing a fake execute on a builtin function that
792     * was piped out.
793     */
794    mypipe(pvec);
795    if (pfork(&faket, -1) == 0) {
796        struct command *t;
797
798        (void) close(pvec[0]);
799        (void) dmove(pvec[1], 1);
800        (void) dmove(SHDIAG,  2);
801        initdesc();
802        /*
803         * Bugfix for nested backquotes by Michael Greim <greim@sbsvax.UUCP>,
804         * posted to comp.bugs.4bsd 12 Sep. 1989.
805         */
806        if (pargv)              /* mg, 21.dec.88 */
807            blkfree(pargv), pargv = 0, pargsiz = 0;
808        /* mg, 21.dec.88 */
809        arginp = cp;
810        while (*cp)
811            *cp++ &= TRIM;
812
813        /*
814         * In the child ``forget'' everything about current aliases or
815         * eval vectors.
816         */
817        alvec = NULL;
818        evalvec = NULL;
819        alvecp = NULL;
820        evalp = NULL;
821        (void) lex(&paraml);
822        if (seterr)
823            stderror(ERR_OLD);
824        alias(&paraml);
825        t = syntax(paraml.next, &paraml, 0);
826        if (seterr)
827            stderror(ERR_OLD);
828        if (t)
829            t->t_dflg |= F_NOFORK;
830#ifdef SIGTSTP
831        (void) sigignore(SIGTSTP);
832#endif
833#ifdef SIGTTIN
834        (void) sigignore(SIGTTIN);
835#endif
836#ifdef SIGTTOU
837        (void) sigignore(SIGTTOU);
838#endif
839        execute(t, -1, NULL, NULL);
840        exitstat();
841    }
842    xfree((ptr_t) cp);
843    (void) close(pvec[1]);
844    c = 0;
845    ip = NULL;
846    do {
847        int     cnt = 0;
848
849        for (;;) {
850            if (icnt == 0) {
851                int     i;
852
853                ip = ibuf;
854                do
855                    icnt = read(pvec[0], tibuf, BUFSIZE);
856                while (icnt == -1 && errno == EINTR);
857                if (icnt <= 0) {
858                    c = -1;
859                    break;
860                }
861                for (i = 0; i < icnt; i++)
862                    ip[i] = (unsigned char) tibuf[i];
863            }
864            if (hadnl)
865                break;
866            --icnt;
867            c = (*ip++ & TRIM);
868            if (c == 0)
869                break;
[12038]870#ifdef WINNT
871            if (c == '\r')
872                c = ' ';
873#endif /* WINNT */
[9005]874            if (c == '\n') {
875                /*
876                 * Continue around the loop one more time, so that we can eat
877                 * the last newline without terminating this word.
878                 */
879                hadnl = 1;
880                continue;
881            }
882            if (!quoted && (c == ' ' || c == '\t'))
883                break;
884            cnt++;
885            psave(c | quoted);
886        }
887        /*
888         * Unless at end-of-file, we will form a new word here if there were
889         * characters in the word, or in any case when we take text literally.
890         * If we didn't make empty words here when literal was set then we
891         * would lose blank lines.
892         */
893        if (c != -1 && (cnt || literal))
[12038]894            pword(BUFSIZE);
[9005]895        hadnl = 0;
896    } while (c >= 0);
897    (void) close(pvec[0]);
898    pwait();
899    prestjob();
900}
901
902static void
903psave(c)
904    int    c;
905{
906    if (--pnleft <= 0)
907        stderror(ERR_WTOOLONG);
[12038]908    *pargcp++ = (Char) c;
[9005]909}
910
911static void
[12038]912pword(bufsiz)
913    int    bufsiz;
[9005]914{
915    psave(0);
916    if (pargc == pargsiz - 1) {
917        pargsiz += GLOBSPACE;
918        pargv = (Char **) xrealloc((ptr_t) pargv,
919                                   (size_t) (pargsiz * sizeof(Char *)));
920    }
921    pargv[pargc++] = Strsave(pargs);
922    pargv[pargc] = NULL;
923    pargcp = pargs;
[12038]924    pnleft = bufsiz - 4;
[9005]925}
926
927int
928Gmatch(string, pattern)
929    Char *string, *pattern;
930{
931    return Gnmatch(string, pattern, NULL);
932}
933
934int
935Gnmatch(string, pattern, endstr)
936    Char *string, *pattern, **endstr;
937{
938    Char **blk, **p, *tstring = string;
939    int    gpol = 1, gres = 0;
940
941    if (*pattern == '^') {
942        gpol = 0;
943        pattern++;
944    }
945
946    blk = (Char **) xmalloc((size_t) (GLOBSPACE * sizeof(Char *)));
947    blk[0] = Strsave(pattern);
948    blk[1] = NULL;
949
950    expbrace(&blk, NULL, GLOBSPACE);
951
952    if (endstr == NULL)
953        /* Exact matches only */
954        for (p = blk; *p; p++)
955            gres |= pmatch(string, *p, &tstring) == 2 ? 1 : 0;
956    else {
957        /* partial matches */
958        int minc = 0x7fffffff;
959        for (p = blk; *p; p++)
960            if (pmatch(string, *p, &tstring) != 0) {
961                int t = tstring - string;
962                gres |= 1;
963                if (minc == -1 || minc > t)
964                    minc = t;
965            }
966        *endstr = string + minc;
967    }
968
969    blkfree(blk);
970    return(gres == gpol);
971}
972
973/* pmatch():
974 *      Return 2 on exact match,       
975 *      Return 1 on substring match.
976 *      Return 0 on no match.
977 *      *estr will point to the end of the longest exact or substring match.
978 */
979static int
980pmatch(string, pattern, estr)
981    register Char *string, *pattern, **estr;
982{
983    register Char stringc, patternc;
984    int     match, negate_range;
985    Char    rangec, *oestr, *pestr;
986
987    for (;; ++string) {
988        stringc = *string & TRIM;
989        /*
990         * apollo compiler bug: switch (patternc = *pattern++) dies
991         */
992        patternc = *pattern++;
993        switch (patternc) {
994        case 0:
995            *estr = string;
996            return (stringc == 0 ? 2 : 1);
997        case '?':
998            if (stringc == 0)
999                return (0);
1000            *estr = string;
1001            break;
1002        case '*':
1003            if (!*pattern) {
1004                while (*string) string++;
1005                *estr = string;
1006                return (2);
1007            }
1008            oestr = *estr;
1009            pestr = NULL;
1010
1011            do {
1012                switch(pmatch(string, pattern, estr)) {
1013                case 0:
1014                    break;
1015                case 1:
1016                    pestr = *estr;
1017                    break;
1018                case 2:
1019                    return 2;
1020                default:
1021                    abort();    /* Cannot happen */
1022                }
1023                *estr = string;
1024            }
1025            while (*string++);
1026
1027            if (pestr) {
1028                *estr = pestr;
1029                return 1;
1030            }
1031            else {
1032                *estr = oestr;
1033                return 0;
1034            }
1035
1036        case '[':
1037            match = 0;
1038            if ((negate_range = (*pattern == '^')) != 0)
1039                pattern++;
1040            while ((rangec = *pattern++) != '\0') {
1041                if (rangec == ']')
1042                    break;
1043                if (match)
1044                    continue;
1045                if (rangec == '-' && *(pattern-2) != '[' && *pattern  != ']') {
[12038]1046                    match = (globcharcoll(stringc, *pattern & TRIM) <= 0 &&
1047                    globcharcoll(*(pattern-2) & TRIM, stringc) <= 0);
[9005]1048                    pattern++;
1049                }
1050                else
1051                    match = (stringc == (rangec & TRIM));
1052            }
1053            if (rangec == 0)
1054                stderror(ERR_NAME | ERR_MISSING, ']');
1055            if (match == negate_range)
1056                return (0);
1057            *estr = string;
1058            break;
1059        default:
1060            if ((patternc & TRIM) != stringc)
1061                return (0);
1062            *estr = string;
1063            break;
1064        }
1065    }
1066}
1067
1068void
1069Gcat(s1, s2)
1070    Char   *s1, *s2;
1071{
1072    register Char *p, *q;
1073    int     n;
1074
1075    for (p = s1; *p++;)
1076        continue;
1077    for (q = s2; *q++;)
1078        continue;
1079    n = (p - s1) + (q - s2) - 1;
1080    if (++gargc >= gargsiz) {
1081        gargsiz += GLOBSPACE;
1082        gargv = (Char **) xrealloc((ptr_t) gargv,
1083                                   (size_t) (gargsiz * sizeof(Char *)));
1084    }
1085    gargv[gargc] = 0;
1086    p = gargv[gargc - 1] = (Char *) xmalloc((size_t) (n * sizeof(Char)));
1087    for (q = s1; (*p++ = *q++) != '\0';)
1088        continue;
1089    for (p--, q = s2; (*p++ = *q++) != '\0';)
1090        continue;
1091}
1092
1093#ifdef FILEC
1094int
1095sortscmp(a, b)
1096    register Char **a, **b;
1097{
1098    if (!a)                     /* check for NULL */
1099        return (b ? 1 : 0);
1100    if (!b)
1101        return (-1);
1102
1103    if (!*a)                    /* check for NULL */
1104        return (*b ? 1 : 0);
1105    if (!*b)
1106        return (-1);
1107
[12038]1108    return (int) collate(*a, *b);
[9005]1109}
1110
1111#endif
Note: See TracBrowser for help on using the repository browser.