home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / Shells / tcsh / Source / sh.glob.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  21.6 KB  |  1,087 lines

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