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

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