home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume25 / tcsh-6.01 / part08 / sh.glob.c < prev    next >
C/C++ Source or Header  |  1991-12-19  |  19KB  |  911 lines

  1. /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.01/RCS/sh.glob.c,v 3.14 1991/12/19 22:34:14 christos 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. 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.  
  39. RCSID("$Id: sh.glob.c,v 3.14 1991/12/19 22:34:14 christos Exp $")
  40.  
  41. #include "tc.h"
  42.  
  43. #include "glob.h"
  44.  
  45. static int noglob;
  46. static 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            */
  56.  
  57. #define LBRC '{'
  58. #define RBRC '}'
  59. #define LBRK '['
  60. #define RBRK ']'
  61. #define EOS '\0'
  62.  
  63. Char  **gargv = NULL;
  64. long    gargc = 0;
  65. Char  **pargv = NULL;
  66. long    pargc = 0;
  67.  
  68. /*
  69.  * globbing is now done in two stages. In the first pass we expand
  70.  * csh globbing idioms ~`{ and then we proceed doing the normal
  71.  * globbing if needed ?*[
  72.  *
  73.  * Csh type globbing is handled in globexpand() and the rest is
  74.  * handled in glob() which is part of the 4.4BSD libc.
  75.  *
  76.  */
  77. static    Char     *globtilde    __P((Char **, Char *));
  78. static    Char     *globequal    __P((Char **, Char *));
  79. static    Char    **libglob    __P((Char **));
  80. static    Char    **globexpand    __P((Char **));
  81. static    int      globbrace    __P((Char *, Char *, Char ***));
  82. static    void      pword        __P((void));
  83. static    void      psave        __P((int));
  84. static    void      backeval    __P((Char *, bool));
  85.  
  86. static Char *
  87. globtilde(nv, s)
  88.     Char  **nv, *s;
  89. {
  90.     Char    gbuf[MAXPATHLEN], *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[MAXPATHLEN - 1]; 
  99.      *s && *s != '/' && *s != ':' && b < e;
  100.      *b++ = *s++);
  101.     *b = EOS;
  102.     if (gethdir(gstart)) {
  103.     blkfree(nv);
  104.     if (*gstart)
  105.         stderror(ERR_UNKUSER, short2str(gstart));
  106.     else
  107.         stderror(ERR_NOHOME);
  108.     }
  109.     b = &gstart[Strlen(gstart)];
  110. #ifdef apollo
  111.     slash = gstart[0] == '/' && gstart[1] == '\0';
  112. #endif
  113.     while (*s)
  114.     *b++ = *s++;
  115.     *b = EOS;
  116.     --u;
  117.     xfree((ptr_t) u);
  118. #ifdef apollo
  119.     if (slash && gstart[1] == '/')
  120.     gstart++;
  121. #endif
  122.     return (Strsave(gstart));
  123. }
  124.  
  125. static Char *
  126. globequal(nv, s)
  127.     Char  **nv, *s;
  128. {
  129.     int     dig;
  130.     Char    gp[MAXPATHLEN], *b, *d;
  131.  
  132.     /*
  133.      * kfk - 17 Jan 1984 - stack hack allows user to get at arbitrary dir names
  134.      * in stack. PWP: let =foobar pass through (for X windows)
  135.      */
  136.     if ((Isdigit(s[1]) || s[1] == '-') && (s[2] == '\0' || s[2] == '/')) {
  137.     dig = (s[1] == '-') ? -1 : s[1] - '0';
  138.     if (!getstakd(gp, dig)) {
  139.         blkfree(nv);
  140.         stderror(ERR_DEEP);
  141.     }
  142.     for (b = &s[2], d = &gp[Strlen(gp)]; *d++ = *b++;);
  143.     xfree((ptr_t) s);
  144.     return (Strsave(gp));
  145.     }
  146.     else
  147.     return (s);
  148. }
  149.  
  150. static int
  151. globbrace(s, p, bl)
  152.     Char   *s, *p, ***bl;
  153. {
  154.     int     i, len;
  155.     Char   *pm, *pe, *lm, *pl;
  156.     Char  **nv, **vl;
  157.     Char    gbuf[MAXPATHLEN];
  158.     int     size = GLOBSPACE;
  159.  
  160.     nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size);
  161.     *vl = NULL;
  162.  
  163.     len = 0;
  164.     /* copy part up to the brace */
  165.     for (lm = gbuf, p = s; *p != LBRC; *lm++ = *p++)
  166.     continue;
  167.  
  168.     /* check for balanced braces */
  169.     for (i = 0, pe = ++p; *pe; pe++)
  170.     if (*pe == LBRK) {
  171.         /* Ignore everything between [] */
  172.         for (++pe; *pe != RBRK && *pe != EOS; pe++)
  173.         continue;
  174.         if (*pe == EOS) {
  175.         blkfree(nv);
  176.         return (-RBRK);
  177.         }
  178.     }
  179.     else if (*pe == LBRC)
  180.         i++;
  181.     else if (*pe == RBRC) {
  182.         if (i == 0)
  183.         break;
  184.         i--;
  185.     }
  186.  
  187.     if (i != 0 || *pe == '\0') {
  188.     blkfree(nv);
  189.     return (-RBRC);
  190.     }
  191.  
  192.     for (i = 0, pl = pm = p; pm <= pe; pm++)
  193.     switch (*pm) {
  194.     case LBRK:
  195.         for (++pm; *pm != RBRK && *pm != EOS; pm++)
  196.         continue;
  197.         if (*pm == EOS) {
  198.         *vl = NULL;
  199.         blkfree(nv);
  200.         return (-RBRK);
  201.         }
  202.         break;
  203.     case LBRC:
  204.         i++;
  205.         break;
  206.     case RBRC:
  207.         if (i) {
  208.         i--;
  209.         break;
  210.         }
  211.         /* FALLTHROUGH */
  212.     case ',':
  213.         if (i && *pm == ',')
  214.         break;
  215.         else {
  216.         Char    savec = *pm;
  217.  
  218.         *pm = EOS;
  219.         (void) Strcpy(lm, pl);
  220.         (void) Strcat(gbuf, pe + 1);
  221.         *pm = savec;
  222.         *vl++ = Strsave(gbuf);
  223.         len++;
  224.         pl = pm + 1;
  225.         if (vl == &nv[size]) {
  226.             size += GLOBSPACE;
  227.             nv = (Char **) xrealloc((ptr_t) nv, (size_t)
  228.                         size * sizeof(Char *));
  229.             vl = &nv[size - GLOBSPACE];
  230.         }
  231.         }
  232.         break;
  233.     default:
  234.         break;
  235.     }
  236.     *vl = NULL;
  237.     *bl = nv;
  238.     return (len);
  239. }
  240.  
  241. static Char **
  242. globexpand(v)
  243.     Char  **v;
  244. {
  245.     Char   *s;
  246.     Char  **nv, **vl, **el;
  247.     int     size = GLOBSPACE;
  248.  
  249.  
  250.     nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size);
  251.     *vl = NULL;
  252.  
  253.     /*
  254.      * Step 1: expand backquotes.
  255.      */
  256.     while (s = *v++) {
  257.     if (Strchr(s, '`')) {
  258.         int     i;
  259.  
  260.         (void) dobackp(s, 0);
  261.         for (i = 0; i < pargc; i++) {
  262.         *vl++ = pargv[i];
  263.         if (vl == &nv[size]) {
  264.             size += GLOBSPACE;
  265.             nv = (Char **) xrealloc((ptr_t) nv,
  266.                         (size_t) size * sizeof(Char *));
  267.             vl = &nv[size - GLOBSPACE];
  268.         }
  269.         }
  270.         xfree((ptr_t) pargv);
  271.         pargv = NULL;
  272.     }
  273.     else {
  274.         *vl++ = Strsave(s);
  275.         if (vl == &nv[size]) {
  276.         size += GLOBSPACE;
  277.         nv = (Char **) xrealloc((ptr_t) nv, (size_t)
  278.                     size * sizeof(Char *));
  279.         vl = &nv[size - GLOBSPACE];
  280.         }
  281.     }
  282.     }
  283.     *vl = NULL;
  284.  
  285.     if (noglob)
  286.     return (nv);
  287.  
  288.     /*
  289.      * Step 2: expand braces
  290.      */
  291.     el = vl;
  292.     vl = nv;
  293.     for (s = *vl; s; s = *++vl) {
  294.     Char   *b;
  295.     Char  **vp, **bp;
  296.  
  297.     if ((b = Strchr(s, LBRC)) && b[1] != '\0' && b[1] != RBRC) {
  298.         Char  **bl;
  299.         int     len;
  300.  
  301.         if ((len = globbrace(s, b, &bl)) < 0) {
  302.         blkfree(nv);
  303.         stderror(ERR_MISSING, -len);
  304.         }
  305.         xfree((ptr_t) s);
  306.         if (len == 1) {
  307.         *vl-- = *bl;
  308.         xfree((ptr_t) bl);
  309.         continue;
  310.         }
  311.         len = blklen(bl);
  312.         if (&el[len] >= &nv[size]) {
  313.         int     l, e;
  314.  
  315.         l = &el[len] - &nv[size];
  316.         size += GLOBSPACE > l ? GLOBSPACE : l;
  317.         l = vl - nv;
  318.         e = el - nv;
  319.         nv = (Char **) xrealloc((ptr_t) nv, (size_t)
  320.                     size * sizeof(Char *));
  321.         vl = nv + l;
  322.         el = nv + e;
  323.         }
  324.         vp = vl--;
  325.         *vp = *bl;
  326.         len--;
  327.         for (bp = el; bp != vp; bp--)
  328.         bp[len] = *bp;
  329.         el += len;
  330.         vp++;
  331.         for (bp = bl + 1; *bp; *vp++ = *bp++)
  332.         continue;
  333.         xfree((ptr_t) bl);
  334.     }
  335.  
  336.     }
  337.  
  338.     /*
  339.      * Step 3: expand ~ =
  340.      */
  341.     vl = nv;
  342.     for (s = *vl; s; s = *++vl)
  343.     switch (*s) {
  344.     case '~':
  345.         *vl = globtilde(nv, s);
  346.         break;
  347.     case '=':
  348.         *vl = globequal(nv, s);
  349.         break;
  350.     default:
  351.         break;
  352.     }
  353.     vl = nv;
  354.     return (vl);
  355. }
  356.  
  357. static Char *
  358. handleone(str, vl, action)
  359.     Char   *str, **vl;
  360.     int     action;
  361. {
  362.  
  363.     Char   *cp, **vlp = vl;
  364.  
  365.     switch (action) {
  366.     case G_ERROR:
  367.     setname(short2str(str));
  368.     blkfree(vl);
  369.     stderror(ERR_NAME | ERR_AMBIG);
  370.     break;
  371.     case G_APPEND:
  372.     trim(vlp);
  373.     str = Strsave(*vlp++);
  374.     do {
  375.         cp = Strspl(str, STRspace);
  376.         xfree((ptr_t) str);
  377.         str = Strspl(cp, *vlp);
  378.         xfree((ptr_t) cp);
  379.     }
  380.     while (*++vlp);
  381.     blkfree(vl);
  382.     break;
  383.     case G_IGNORE:
  384.     str = Strsave(strip(*vlp));
  385.     blkfree(vl);
  386.     break;
  387.     default:
  388.     break;
  389.     }
  390.     return (str);
  391. }
  392.  
  393. static Char **
  394. libglob(vl)
  395.     Char  **vl;
  396. {
  397.     int     gflgs = GLOB_QUOTE | GLOB_NOMAGIC | GLOB_ALTNOT;
  398.     glob_t  globv;
  399.     char   *ptr;
  400.     int     nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0;
  401.  
  402.     if (!vl || !vl[0])
  403.     return(vl);
  404.  
  405.     globv.gl_offs = 0;
  406.     globv.gl_pathv = 0;
  407.     globv.gl_pathc = 0;
  408.  
  409.     if (nonomatch)
  410.     gflgs |= GLOB_NOCHECK;
  411.  
  412.     do {
  413.     ptr = short2qstr(*vl);
  414.     switch (glob(ptr, gflgs, 0, &globv)) {
  415.     case GLOB_ABEND:
  416.         setname(ptr);
  417.         stderror(ERR_NAME | ERR_GLOB);
  418.         /* NOTREACHED */
  419.     case GLOB_NOSPACE:
  420.         stderror(ERR_NOMEM);
  421.         /* NOTREACHED */
  422.     default:
  423.         break;
  424.     }
  425.     if (globv.gl_flags & GLOB_MAGCHAR) {
  426.         match |= (globv.gl_matchc != 0);
  427.         magic = 1;
  428.     }
  429.     gflgs |= GLOB_APPEND;
  430.     }
  431.     while (*++vl);
  432.     vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ? 
  433.     NULL : blk2short(globv.gl_pathv);
  434.     globfree(&globv);
  435.     return (vl);
  436. }
  437.  
  438. Char   *
  439. globone(str, action)
  440.     Char   *str;
  441.     int     action;
  442. {
  443.  
  444.     Char   *v[2], **vl, **vo;
  445.     int gflg;
  446.  
  447.     noglob = adrof(STRnoglob) != 0;
  448.     gflag = 0;
  449.     v[0] = str;
  450.     v[1] = 0;
  451.     tglob(v);
  452.     gflg = gflag;
  453.     if (gflg == G_NONE)
  454.     return (strip(Strsave(str)));
  455.  
  456.     if (gflg & G_CSH) {
  457.     /*
  458.      * Expand back-quote, tilde and brace
  459.      */
  460.     vo = globexpand(v);
  461.     if (noglob || (gflg & G_GLOB) == 0) {
  462.         if (vo[0] == NULL) {
  463.         xfree((ptr_t) vo);
  464.         return (Strsave(STRNULL));
  465.         }
  466.         if (vo[1] != NULL) 
  467.         return (handleone(str, vo, action));
  468.         else {
  469.         str = strip(vo[0]);
  470.         xfree((ptr_t) vo);
  471.         return (str);
  472.         }
  473.     }
  474.     }
  475.     else if (noglob || (gflg & G_GLOB) == 0)
  476.     return (strip(Strsave(str)));
  477.     else
  478.     vo = v;
  479.  
  480.     vl = libglob(vo);
  481.     if ((gflg & G_CSH) && vl != vo)
  482.     blkfree(vo);
  483.     if (vl == NULL) {
  484.     setname(short2str(str));
  485.     stderror(ERR_NAME | ERR_NOMATCH);
  486.     }
  487.     if (vl[0] == NULL) {
  488.     xfree((ptr_t) vl);
  489.     return (Strsave(STRNULL));
  490.     }
  491.     if (vl[1]) 
  492.     return (handleone(str, vl, action));
  493.     else {
  494.     str = strip(*vl);
  495.     xfree((ptr_t) vl);
  496.     return (str);
  497.     }
  498. }
  499.  
  500. Char  **
  501. globall(v)
  502.     Char  **v;
  503. {
  504.     Char  **vl, **vo;
  505.     int gflg = gflag;
  506.  
  507.     if (!v || !v[0]) {
  508.     gargv = saveblk(v);
  509.     gargc = blklen(gargv);
  510.     return (gargv);
  511.     }
  512.  
  513.     noglob = adrof(STRnoglob) != 0;
  514.  
  515.     if (gflg & G_CSH)
  516.     /*
  517.      * Expand back-quote, tilde and brace
  518.      */
  519.     vl = vo = globexpand(v);
  520.     else
  521.     vl = vo = saveblk(v);
  522.  
  523.     if (!noglob && (gflg & G_GLOB)) {
  524.     vl = libglob(vo);
  525.     if ((gflg & G_CSH) && vl != vo)
  526.         blkfree(vo);
  527.     }
  528.     else
  529.     trim(vl);
  530.  
  531.     gargc = vl ? blklen(vl) : 0;
  532.     return (gargv = vl);
  533. }
  534.  
  535. void
  536. ginit()
  537. {
  538.     gargsiz = GLOBSPACE;
  539.     gargv = (Char **) xmalloc((size_t) sizeof(Char *) * gargsiz);
  540.     gargv[0] = 0;
  541.     gargc = 0;
  542. }
  543.  
  544. void
  545. rscan(t, f)
  546.     register Char **t;
  547.     void    (*f) ();
  548. {
  549.     register Char *p;
  550.  
  551.     while (p = *t++)
  552.     while (*p)
  553.         (*f) (*p++);
  554. }
  555.  
  556. void
  557. trim(t)
  558.     register Char **t;
  559. {
  560.     register Char *p;
  561.  
  562.     while (p = *t++)
  563.     while (*p)
  564.         *p++ &= TRIM;
  565. }
  566.  
  567. void
  568. tglob(t)
  569.     register Char **t;
  570. {
  571.     register Char *p, c;
  572.  
  573.     while (p = *t++) {
  574.     if (*p == '~' || *p == '=')
  575.         gflag |= G_CSH;
  576.     else if (*p == '{' &&
  577.          (p[1] == '\0' || (p[1] == '}' && p[2] == '\0')))
  578.         continue;
  579.     while (c = *p++)
  580.         if (isglob(c))
  581.         gflag |= (c == '{' || c == '`') ? G_CSH : G_GLOB;
  582.     }
  583. }
  584.  
  585. /*
  586.  * Command substitute cp.  If literal, then this is a substitution from a
  587.  * << redirection, and so we should not crunch blanks and tabs, separating
  588.  * words only at newlines.
  589.  */
  590. Char  **
  591. dobackp(cp, literal)
  592.     Char   *cp;
  593.     bool    literal;
  594. {
  595.     register Char *lp, *rp;
  596.     Char   *ep, word[MAXPATHLEN];
  597.  
  598.     if (pargv) {
  599. #ifdef notdef
  600.     abort();
  601. #endif
  602.     blkfree(pargv);
  603.     }
  604.     pargsiz = GLOBSPACE;
  605.     pargv = (Char **) xmalloc((size_t) sizeof(Char *) * pargsiz);
  606.     pargv[0] = NULL;
  607.     pargcp = pargs = word;
  608.     pargc = 0;
  609.     pnleft = MAXPATHLEN - 4;
  610.     for (;;) {
  611.     for (lp = cp; *lp != '`'; lp++) {
  612.         if (*lp == 0) {
  613.         if (pargcp != pargs)
  614.             pword();
  615.         return (pargv);
  616.         }
  617.         psave(*lp);
  618.     }
  619.     lp++;
  620.     for (rp = lp; *rp && *rp != '`'; rp++)
  621.         if (*rp == '\\') {
  622.         rp++;
  623.         if (!*rp)
  624.             goto oops;
  625.         }
  626.     if (!*rp)
  627.     oops:  stderror(ERR_UNMATCHED, '`');
  628.     ep = Strsave(lp);
  629.     ep[rp - lp] = 0;
  630.     backeval(ep, literal);
  631.     cp = rp + 1;
  632.     }
  633. }
  634.  
  635. static void
  636. backeval(cp, literal)
  637.     Char   *cp;
  638.     bool    literal;
  639. {
  640.     register int icnt, c;
  641.     register Char *ip;
  642.     struct command faket;
  643.     bool    hadnl;
  644.     int     pvec[2], quoted;
  645.     Char   *fakecom[2], ibuf[BUFSIZE];
  646.     char    tibuf[BUFSIZE];
  647.  
  648.     hadnl = 0;
  649.     icnt = 0;
  650.     quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0;
  651.     faket.t_dtyp = NODE_COMMAND;
  652.     faket.t_dflg = 0;
  653.     faket.t_dlef = 0;
  654.     faket.t_drit = 0;
  655.     faket.t_dspr = 0;
  656.     faket.t_dcom = fakecom;
  657.     fakecom[0] = STRfakecom1;
  658.     fakecom[1] = 0;
  659.  
  660.     /*
  661.      * We do the psave job to temporarily change the current job so that the
  662.      * following fork is considered a separate job.  This is so that when
  663.      * backquotes are used in a builtin function that calls glob the "current
  664.      * job" is not corrupted.  We only need one level of pushed jobs as long as
  665.      * we are sure to fork here.
  666.      */
  667.     psavejob();
  668.  
  669.     /*
  670.      * It would be nicer if we could integrate this redirection more with the
  671.      * routines in sh.sem.c by doing a fake execute on a builtin function that
  672.      * was piped out.
  673.      */
  674.     mypipe(pvec);
  675.     if (pfork(&faket, -1) == 0) {
  676.     struct wordent paraml;
  677.     struct command *t;
  678.  
  679.     (void) close(pvec[0]);
  680.     (void) dmove(pvec[1], 1);
  681.     (void) dmove(SHDIAG, 2);
  682.     initdesc();
  683.     /*
  684.      * Bugfix for nested backquotes by Michael Greim <greim@sbsvax.UUCP>,
  685.      * posted to comp.bugs.4bsd 12 Sep. 1989.
  686.      */
  687.     if (pargv)        /* mg, 21.dec.88 */
  688.         blkfree(pargv), pargv = 0, pargsiz = 0;
  689.     /* mg, 21.dec.88 */
  690.     arginp = cp;
  691.     while (*cp)
  692.         *cp++ &= TRIM;
  693.  
  694.         /*
  695.      * In the child ``forget'' everything about current aliases or
  696.      * eval vectors.
  697.      */
  698.     alvec = NULL;
  699.     evalvec = NULL;
  700.     alvecp = NULL;
  701.     evalp = NULL;
  702.     (void) lex(¶ml);
  703.     if (seterr)
  704.         stderror(ERR_OLD);
  705.     alias(¶ml);
  706.     t = syntax(paraml.next, ¶ml, 0);
  707.     if (seterr)
  708.         stderror(ERR_OLD);
  709.     if (t)
  710.         t->t_dflg |= F_NOFORK;
  711. #ifdef SIGTSTP
  712.     (void) sigignore(SIGTSTP);
  713. #endif
  714. #ifdef SIGTTIN
  715.     (void) sigignore(SIGTTIN);
  716. #endif
  717. #ifdef SIGTTOU
  718.     (void) sigignore(SIGTTOU);
  719. #endif
  720.     execute(t, -1, NULL, NULL);
  721.     exitstat();
  722.     }
  723.     xfree((ptr_t) cp);
  724.     (void) close(pvec[1]);
  725.     c = 0;
  726.     ip = NULL;
  727.     do {
  728.     int     cnt = 0;
  729.  
  730.     for (;;) {
  731.         if (icnt == 0) {
  732.         int     i;
  733.  
  734.         ip = ibuf;
  735.         do
  736.             icnt = read(pvec[0], tibuf, BUFSIZE);
  737.         while (icnt == -1 && errno == EINTR);
  738.         if (icnt <= 0) {
  739.             c = -1;
  740.             break;
  741.         }
  742.         for (i = 0; i < icnt; i++)
  743.             ip[i] = (unsigned char) tibuf[i];
  744.         }
  745.         if (hadnl)
  746.         break;
  747.         --icnt;
  748.         c = (*ip++ & TRIM);
  749.         if (c == 0)
  750.         break;
  751.         if (c == '\n') {
  752.         /*
  753.          * Continue around the loop one more time, so that we can eat
  754.          * the last newline without terminating this word.
  755.          */
  756.         hadnl = 1;
  757.         continue;
  758.         }
  759.         if (!quoted && (c == ' ' || c == '\t'))
  760.         break;
  761.         cnt++;
  762.         psave(c | quoted);
  763.     }
  764.     /*
  765.      * Unless at end-of-file, we will form a new word here if there were
  766.      * characters in the word, or in any case when we take text literally.
  767.      * If we didn't make empty words here when literal was set then we
  768.      * would lose blank lines.
  769.      */
  770.     if (c != -1 && (cnt || literal))
  771.         pword();
  772.     hadnl = 0;
  773.     } while (c >= 0);
  774.     (void) close(pvec[0]);
  775.     pwait();
  776.     prestjob();
  777. }
  778.  
  779. static void
  780. psave(c)
  781.     int    c;
  782. {
  783.     if (--pnleft <= 0)
  784.     stderror(ERR_WTOOLONG);
  785.     *pargcp++ = c;
  786. }
  787.  
  788. static void
  789. pword()
  790. {
  791.     psave(0);
  792.     if (pargc == pargsiz - 1) {
  793.     pargsiz += GLOBSPACE;
  794.     pargv = (Char **) xrealloc((ptr_t) pargv,
  795.                    (size_t) pargsiz * sizeof(Char *));
  796.     }
  797.     pargv[pargc++] = Strsave(pargs);
  798.     pargv[pargc] = NULL;
  799.     pargcp = pargs;
  800.     pnleft = MAXPATHLEN - 4;
  801. }
  802.  
  803. int
  804. Gmatch(string, pattern)
  805.     register Char *string, *pattern;
  806. {
  807.     register Char stringc, patternc;
  808.     int     match;
  809.     Char    rangec;
  810.  
  811.     for (;; ++string) {
  812.     stringc = *string & TRIM;
  813.     /*
  814.      * apollo compiler bug: switch (patternc = *pattern++) { dies
  815.      */
  816.     patternc = *pattern++;
  817.     switch (patternc) {
  818.     case 0:
  819.         return (stringc == 0);
  820.     case '?':
  821.         if (stringc == 0)
  822.         return (0);
  823.         break;
  824.     case '*':
  825.         if (!*pattern)
  826.         return (1);
  827.         while (*string)
  828.         if (Gmatch(string++, pattern))
  829.             return (1);
  830.         return (0);
  831.     case '[':
  832.         match = 0;
  833.         while (rangec = *pattern++) {
  834.         if (rangec == ']')
  835.             if (match)
  836.             break;
  837.             else
  838.             return (0);
  839.         if (match)
  840.             continue;
  841.         if (rangec == '-' && *(pattern-2) != '[' && *pattern  != ']') {
  842.             match = (stringc <= (*pattern & TRIM) &&
  843.                   (*(pattern-2) & TRIM) <= stringc);
  844.             pattern++;
  845.         }
  846.         else 
  847.             match = (stringc == (rangec & TRIM));
  848.         }
  849.         if (rangec == 0)
  850.         stderror(ERR_NAME | ERR_MISSING, ']');
  851.         break;
  852.     default:
  853.         if ((patternc & TRIM) != stringc)
  854.         return (0);
  855.         break;
  856.  
  857.     }
  858.     }
  859. }
  860.  
  861. void
  862. Gcat(s1, s2)
  863.     Char   *s1, *s2;
  864. {
  865.     register Char *p, *q;
  866.     int     n;
  867.  
  868.     for (p = s1; *p++;);
  869.     for (q = s2; *q++;);
  870.     n = (p - s1) + (q - s2) - 1;
  871.     if (++gargc >= gargsiz) {
  872.     gargsiz += GLOBSPACE;
  873.     gargv = (Char **) xrealloc((ptr_t) gargv,
  874.                    (size_t) gargsiz * sizeof(Char *));
  875.     }
  876.     gargv[gargc] = 0;
  877.     p = gargv[gargc - 1] = (Char *) xmalloc((size_t) n * sizeof(Char));
  878.     for (q = s1; *p++ = *q++;);
  879.     for (p--, q = s2; *p++ = *q++;);
  880. }
  881.  
  882. #ifdef FILEC
  883. int
  884. sortscmp(a, b)
  885.     register Char **a, **b;
  886. {
  887. #if defined(NLS) && !defined(NOSTRCOLL)
  888.     char    buf[2048];
  889.  
  890. #endif
  891.  
  892.     if (!a)            /* check for NULL */
  893.     return (b ? 1 : 0);
  894.     if (!b)
  895.     return (-1);
  896.  
  897.     if (!*a)            /* check for NULL */
  898.     return (*b ? 1 : 0);
  899.     if (!*b)
  900.     return (-1);
  901.  
  902. #if defined(NLS) && !defined(NOSTRCOLL)
  903.     (void) strcpy(buf, short2str(*a));
  904.     return ((int) strcoll(buf, short2str(*b)));
  905. #else
  906.     return ((int) Strcmp(*a, *b));
  907. #endif
  908. }
  909.  
  910. #endif
  911.