home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / spencer_2bsd.tar.gz / 2bsd.tar / src / csh / sh.glob.c < prev    next >
C/C++ Source or Header  |  1980-02-17  |  11KB  |  727 lines

  1. /* Copyright (c) 1979 Regents of the University of California */
  2. #include "sh.h"
  3.  
  4. /*
  5.  * C Shell
  6.  */
  7.  
  8. int    globcnt;
  9.  
  10. char    *globchars =    "`{[*?";
  11.  
  12. char    *gpath, *gpathp, *lastgpathp;
  13. int    globbed;
  14. bool    noglob;
  15. bool    nonomatch;
  16. char    *entp;
  17. char    **sortbas;
  18.  
  19. char **
  20. glob(v)
  21.     register char **v;
  22. {
  23.     char agpath[160];
  24.     char *agargv[GAVSIZ];
  25.  
  26.     gpath = agpath; gpathp = gpath; *gpathp = 0;
  27.     lastgpathp = &gpath[sizeof agpath - 2];
  28.     ginit(agargv); globcnt = 0;
  29. #ifdef GDEBUG
  30.     printf("glob entered: "); blkpr(v); printf("\n");
  31. #endif
  32.     noglob = adrof("noglob") != 0;
  33.     nonomatch = adrof("nonomatch") != 0;
  34.     globcnt = noglob | nonomatch;
  35.     while (*v)
  36.         collect(*v++);
  37. #ifdef GDEBUG
  38.     printf("glob done, globcnt=%d, gflag=%d: ", globcnt, gflag); blkpr(gargv); printf("\n");
  39. #endif
  40.     if (globcnt == 0 && (gflag&1)) {
  41.         blkfree(gargv), gargv = 0;
  42.         return (0);
  43.     } else
  44.         return (gargv = copyblk(gargv));
  45. }
  46.  
  47. ginit(agargv)
  48.     char **agargv;
  49. {
  50.  
  51.     agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0;
  52.     gnleft = NCARGS - 4;
  53. }
  54.  
  55. collect(as)
  56.     register char *as;
  57. {
  58.     register int i;
  59.  
  60.     if (any('`', as)) {
  61. #ifdef GDEBUG
  62.         printf("doing backp of %s\n", as);
  63. #endif
  64.         dobackp(as, 0);
  65. #ifdef GDEBUG
  66.         printf("backp done, acollect'ing\n");
  67. #endif
  68.         for (i = 0; i < pargc; i++)
  69.             if (noglob)
  70.                 Gcat(pargv[i], "");
  71.             else
  72.                 acollect(pargv[i]);
  73.         if (pargv)
  74.             blkfree(pargv), pargv = 0;
  75. #ifdef GDEBUG
  76.         printf("acollect done\n");
  77. #endif
  78.     } else if (noglob)
  79.         Gcat(as, "");
  80.     else
  81.         acollect(as);
  82. }
  83.  
  84. acollect(as)
  85.     register char *as;
  86. {
  87.     register int ogargc = gargc;
  88.  
  89.     gpathp = gpath; *gpathp = 0; globbed = 0;
  90.     expand(as);
  91.     if (gargc == ogargc) {
  92.         if (nonomatch)
  93.             Gcat(as, "");
  94.     } else
  95.         sort();
  96. }
  97.  
  98. sort()
  99. {
  100.     register char **p1, **p2, *c;
  101.     char **Gvp = &gargv[gargc];
  102.  
  103.     p1 = sortbas;
  104.     while (p1 < Gvp-1) {
  105.         p2 = p1;
  106.         while (++p2 < Gvp)
  107.             if (strcmp(*p1, *p2) > 0)
  108.                 c = *p1, *p1 = *p2, *p2 = c;
  109.         p1++;
  110.     }
  111.     sortbas = Gvp;
  112. }
  113.  
  114. expand(as)
  115.     char *as;
  116. {
  117.     register char *cs;
  118.     register char *sgpathp, *oldcs;
  119.     struct stat stb;
  120.  
  121.     sgpathp = gpathp;
  122.     cs = as;
  123.     if (*cs == '~' && gpathp == gpath) {
  124.         addpath('~');
  125.         for (cs++; letter(*cs) || digit(*cs) || *cs == '-';)
  126.             addpath(*cs++);
  127.         if (!*cs || *cs == '/') {
  128.             if (gpathp != gpath + 1) {
  129.                 *gpathp = 0;
  130.                 if (gethdir(gpath + 1))
  131.                     error("Unknown user: %s", gpath + 1);
  132.                 strcpy(gpath, gpath + 1);
  133.             } else
  134.                 strcpy(gpath, value("home"));
  135.             gpathp = strend(gpath);
  136.         }
  137.     }
  138.     while (!any(*cs, globchars)) {
  139.         if (*cs == 0) {
  140.             if (!globbed)
  141.                 Gcat(gpath, "");
  142.             else if (stat(gpath, &stb) >= 0) {
  143.                 Gcat(gpath, "");
  144.                 globcnt++;
  145.             }
  146.             goto endit;
  147.         }
  148.         addpath(*cs++);
  149.     }
  150.     oldcs = cs;
  151.     while (cs > as && *cs != '/')
  152.         cs--, gpathp--;
  153.     if (*cs == '/')
  154.         cs++, gpathp++;
  155.     *gpathp = 0;
  156.     if (*oldcs == '{') {
  157.         execbrc(cs, 0);
  158.         return;
  159.     }
  160.     matchdir(cs);
  161. endit:
  162.     gpathp = sgpathp;
  163.     *gpathp = 0;
  164. }
  165.  
  166. matchdir(pattern)
  167.     char *pattern;
  168. {
  169.     struct stat stb;
  170.     struct direct dirbuf[512 / sizeof (struct direct)];
  171.     char d_name[DIRSIZ+1];
  172.     register int dirf, cnt;
  173.  
  174.     dirf = open(gpath, 0);
  175.     if (dirf < 0) {
  176.         if (globbed)
  177.             return;
  178.         goto patherr;
  179.     }
  180.     if (fstat(dirf, &stb) < 0)
  181.         goto patherr;
  182.     if (!isdir(stb)) {
  183.         errno = ENOTDIR;
  184.         goto patherr;
  185.     }
  186.     while ((cnt = read(dirf, (char *) dirbuf, sizeof dirbuf)) >= sizeof dirbuf[0]) {
  187.         register struct direct *ep = dirbuf;
  188.  
  189.         for (cnt /= sizeof (struct direct); cnt > 0; cnt--, ep++) {
  190.             if (ep->d_ino == 0)
  191.                 continue;
  192.             copdent(d_name, ep->d_name);
  193.             if (match(d_name, pattern)) {
  194.                 Gcat(gpath, d_name);
  195.                 globcnt++;
  196.             }
  197.         }
  198.     }
  199.     close(dirf);
  200.     return;
  201.  
  202. patherr:
  203.     Perror(gpath);
  204. }
  205.  
  206. copdent(to, from)
  207.     register char *to, *from;
  208. {
  209.     register int cnt = DIRSIZ;
  210.  
  211.     do
  212.         *to++ = *from++;
  213.     while (--cnt);
  214.     *to = 0;
  215. }
  216.  
  217. execbrc(p, s)
  218.     char *p, *s;
  219. {
  220.     char restbuf[BUFSIZ + 2];
  221.     register char *pe, *pm, *pl;
  222.     int brclev = 0;
  223.     char *lm, savec, *sgpathp;
  224.  
  225.     for (lm = restbuf; *p != '{'; *lm++ = *p++)
  226.         continue;
  227.     for (pe = ++p; *pe; pe++)
  228.     switch (*pe) {
  229.  
  230.     case '{':
  231.         brclev++;
  232.         continue;
  233.     case '}':
  234.         if (brclev == 0)
  235.             goto pend;
  236.         brclev--;
  237.         continue;
  238.     case '[':
  239.         for (pe++; *pe && *pe != ']'; pe++)
  240.             continue;
  241.         if (!*pe)
  242.             error("Missing ]");
  243.         continue;
  244.  
  245.     }
  246. pend:
  247.     if (brclev || !*pe)
  248.         error("Missing }");
  249.     for (pl = pm = p; pm <= pe; pm++)
  250.     switch (*pm) {
  251.  
  252.     case '{':
  253.         brclev++;
  254.         continue;
  255.     case '}':
  256.         if (brclev) {
  257.             brclev--;
  258.             continue;
  259.         }
  260.         goto doit;
  261.     case ',':
  262.         if (brclev)
  263.             continue;
  264. doit:
  265.         savec = *pm;
  266.         *pm = 0;
  267.         strcpy(lm, pl);
  268.         strcat(restbuf, pe + 1);
  269.         *pm = savec;
  270.         if (s == 0) {
  271.             sgpathp = gpathp;
  272.             expand(restbuf);
  273.             gpathp = sgpathp;
  274.             *gpathp = 0;
  275.         } else if (amatch(s, restbuf))
  276.             return (1);
  277.         sort();
  278.         pl = pm + 1;
  279.         continue;
  280.     case '[':
  281.         for (pm++; *pm && *pm != ']'; pm++)
  282.             continue;
  283.         if (!*pm)
  284.             error("Missing ]");
  285.         continue;
  286.     }
  287.     return (0);
  288. }
  289.  
  290. match(s, p)
  291.     char *s, *p;
  292. {
  293.     register int c;
  294.     register char *sentp;
  295.     char sglobbed = globbed;
  296.  
  297.     if (*s == '.' && *p != '.')
  298.         return (0);
  299.     sentp = entp;
  300.     entp = s;
  301.     c = amatch(s, p);
  302.     entp = sentp;
  303.     globbed = sglobbed;
  304.     return (c);
  305. }
  306.  
  307. amatch(s, p)
  308.     register char *s, *p;
  309. {
  310.     register int scc;
  311.     int ok, lc;
  312.     char *sgpathp;
  313.     struct stat stb;
  314.     int c, cc;
  315.  
  316.     globbed = 1;
  317.     for (;;) {
  318.         scc = *s++ & TRIM;
  319.         switch (c = *p++) {
  320.  
  321.         case '{':
  322.             return (execbrc(p - 1, s - 1));
  323.  
  324.         case '[':
  325.             ok = 0;
  326.             lc = 077777;
  327.             while (cc = *p++) {
  328.                 if (cc == ']') {
  329.                     if (ok)
  330.                         break;
  331.                     return (0);
  332.                 }
  333.                 if (cc == '-') {
  334.                     if (lc <= scc && scc <= *p++)
  335.                         ok++;
  336.                 } else
  337.                     if (scc == (lc = cc))
  338.                         ok++;
  339.             }
  340.             if (cc == 0)
  341.                 error("Missing ]");
  342.             continue;
  343.  
  344.         case '*':
  345.             if (!*p)
  346.                 return (1);
  347.             if (*p == '/') {
  348.                 p++;
  349.                 goto slash;
  350.             }
  351.             for (s--; *s; s++)
  352.                 if (amatch(s, p))
  353.                     return (1);
  354.             return (0);
  355.  
  356.         case 0:
  357.             return (scc == 0);
  358.  
  359.         default:
  360.             if (c != scc)
  361.                 return (0);
  362.             continue;
  363.  
  364.         case '?':
  365.             if (scc == 0)
  366.                 return (0);
  367.             continue;
  368.  
  369.         case '/':
  370.             if (scc)
  371.                 return (0);
  372. slash:
  373.             s = entp;
  374.             sgpathp = gpathp;
  375.             while (*s)
  376.                 addpath(*s++);
  377.             addpath('/');
  378.             if (stat(gpath, &stb) == 0 && isdir(stb))
  379.                 if (*p == 0) {
  380.                     Gcat(gpath, "");
  381.                     globcnt++;
  382.                 } else
  383.                     expand(p);
  384.             gpathp = sgpathp;
  385.             *gpathp = 0;
  386.             return (0);
  387.         }
  388.     }
  389. }
  390.  
  391. Gmatch(s, p)
  392.     register char *s, *p;
  393. {
  394.     register int scc;
  395.     int ok, lc;
  396.     int c, cc;
  397.  
  398.     for (;;) {
  399.         scc = *s++ & TRIM;
  400.         switch (c = *p++) {
  401.  
  402.         case '[':
  403.             ok = 0;
  404.             lc = 077777;
  405.             while (cc = *p++) {
  406.                 if (cc == ']') {
  407.                     if (ok)
  408.                         break;
  409.                     return (0);
  410.                 }
  411.                 if (cc == '-') {
  412.                     if (lc <= scc && scc <= *p++)
  413.                         ok++;
  414.                 } else
  415.                     if (scc == (lc = cc))
  416.                         ok++;
  417.             }
  418.             if (cc == 0)
  419.                 bferr("Missing ]");
  420.             continue;
  421.  
  422.         case '*':
  423.             if (!*p)
  424.                 return (1);
  425.             for (s--; *s; s++)
  426.                 if (Gmatch(s, p))
  427.                     return (1);
  428.             return (0);
  429.  
  430.         case 0:
  431.             return (scc == 0);
  432.  
  433.         default:
  434.             if ((c & TRIM) != scc)
  435.                 return (0);
  436.             continue;
  437.  
  438.         case '?':
  439.             if (scc == 0)
  440.                 return (0);
  441.             continue;
  442.  
  443.         }
  444.     }
  445. }
  446.  
  447. Gcat(s1, s2)
  448.     register char *s1, *s2;
  449. {
  450.  
  451.     gnleft -= strlen(s1) + strlen(s2) + 1;
  452.     if (gnleft <= 0 || ++gargc >= GAVSIZ)
  453.         error("Arguments too long");
  454.     gargv[gargc] = 0;
  455.     gargv[gargc - 1] = strspl(s1, s2);
  456. }
  457.  
  458. addpath(c)
  459.     char c;
  460. {
  461.  
  462.     if (gpathp >= lastgpathp)
  463.         error("Pathname too long");
  464.     *gpathp++ = c;
  465.     *gpathp = 0;
  466. }
  467.  
  468. rscan(t, f)
  469.     register char **t;
  470.     int (*f)();
  471. {
  472.     register char *p, c;
  473.  
  474.     while (p = *t++) {
  475.         if (f == tglob)
  476.             if (*p == '~')
  477.                 gflag |= 2;
  478.             else if (eq(p, "{") || eq(p, "{}"))
  479.                 continue;
  480.         while (c = *p++)
  481.             (*f)(c);
  482.     }
  483. }
  484.  
  485. scan(t, f)
  486.     register char **t;
  487.     int (*f)();
  488. {
  489.     register char *p, c;
  490.  
  491.     while (p = *t++)
  492.         while (c = *p)
  493.             *p++ = (*f)(c);
  494. }
  495.  
  496. tglob(c)
  497.     register char c;
  498. {
  499.  
  500.     if (any(c, globchars))
  501.         gflag |= c == '{' ? 2 : 1;
  502.     return (c);
  503. }
  504.  
  505. trim(c)
  506.     char c;
  507. {
  508.  
  509.     return (c & TRIM);
  510. }
  511.  
  512. char *
  513. globone(str)
  514.     register char *str;
  515. {
  516.     char *gv[2];
  517.     register char **gvp;
  518.     register char *cp;
  519.  
  520.     gv[0] = str;
  521.     gv[1] = 0;
  522.     gflag = 0;
  523.     rscan(gv, tglob);
  524.     if (gflag) {
  525.         gvp = glob(gv);
  526.         if (gvp == 0) {
  527.             setname(str);
  528.             bferr("No match");
  529.         }
  530.         cp = *gvp++;
  531.         if (cp == 0)
  532.             cp = "";
  533.         else if (*gvp) {
  534.             setname(str);
  535.             bferr("Ambiguous");
  536.         }
  537. /*
  538.         if (cp == 0 || *gvp) {
  539.             setname(str);
  540.             bferr(cp ? "Ambiguous" : "No output");
  541.         }
  542. */
  543.         xfree(gargv); gargv = 0;
  544.     } else {
  545.         scan(gv, trim);
  546.         cp = savestr(gv[0]);
  547.     }
  548.     return (cp);
  549. }
  550.  
  551. /*
  552.  * Command substitute cp.  If literal, then this is
  553.  * a substitution from a << redirection, and so we should
  554.  * not crunch blanks and tabs, separating words only at newlines.
  555.  */
  556. char **
  557. dobackp(cp, literal)
  558.     char *cp;
  559.     bool literal;
  560. {
  561.     register char *lp, *rp;
  562.     char *ep;
  563.     char word[BUFSIZ];
  564.     char *apargv[GAVSIZ + 2];
  565.  
  566.     if (pargv) {
  567.         abort();
  568.         blkfree(pargv);
  569.     }
  570.     pargv = apargv;
  571.     pargv[0] = NOSTR;
  572.     pargcp = pargs = word;
  573.     pargc = 0;
  574.     pnleft = BUFSIZ - 4;
  575.     for (;;) {
  576.         for (lp = cp; *lp != '`'; lp++) {
  577.             if (*lp == 0) {
  578.                 if (pargcp != pargs)
  579.                     pword();
  580. #ifdef GDEBUG
  581.                 printf("leaving dobackp\n");
  582. #endif
  583.                 return (pargv = copyblk(pargv));
  584.             }
  585.             psave(*lp);
  586.         }
  587.         lp++;
  588.         for (rp = lp; *rp && *rp != '`'; rp++)
  589.             if (*rp == '\\') {
  590.                 rp++;
  591.                 if (!*rp)
  592.                     goto oops;
  593.             }
  594.         if (!*rp)
  595. oops:
  596.             error("Unmatched `");
  597.         ep = savestr(lp);
  598.         ep[rp - lp] = 0;
  599.         backeval(ep, literal);
  600. #ifdef GDEBUG
  601.         printf("back from backeval\n");
  602. #endif
  603.         cp = rp + 1;
  604.     }
  605. }
  606.  
  607. backeval(cp, literal)
  608.     char *cp;
  609.     bool literal;
  610. {
  611.     int pvec[2], pid;
  612.     int quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0;
  613.     int (*oldint)();
  614.     char ibuf[BUFSIZ];
  615.     register int icnt = 0, c;
  616.     register char *ip;
  617.     bool hadnl = 0;
  618.  
  619.     oldint = signal(SIGINT, SIG_IGN);
  620.     mypipe(pvec);
  621.     pid = fork();
  622.     if (pid < 0)
  623.         bferr("No more processes");
  624.     if (pid == 0) {
  625.         struct wordent paraml;
  626.         struct command *t;
  627.  
  628.         child++;
  629.         signal(SIGINT, oldint);
  630.         close(pvec[0]);
  631.         dmove(pvec[1], 1);
  632.         dmove(SHDIAG, 2);
  633.         initdesc();
  634.         arginp = cp;
  635.         while (*cp)
  636.             *cp++ &= TRIM;
  637.         lex(¶ml);
  638.         if (err)
  639.             error(err);
  640.         alias(¶ml);
  641.         t = syntax(paraml.next, ¶ml);
  642.         if (err)
  643.             error(err);
  644.         if (t)
  645.             t->t_dflg |= FPAR;
  646.         execute(t);
  647.         exitstat();
  648.     }
  649.     cadd(pid, "``");
  650.     xfree(cp);
  651.     signal(SIGINT, oldint);
  652.     close(pvec[1]);
  653.     do {
  654.         int cnt = 0;
  655.         for (;;) {
  656.             if (icnt == 0) {
  657.                 ip = ibuf;
  658.                 icnt = read(pvec[0], ip, BUFSIZ);
  659.                 if (icnt <= 0) {
  660.                     c = -1;
  661.                     break;
  662.                 }
  663.             }
  664.             if (hadnl)
  665.                 break;
  666.             --icnt;
  667.             c = (*ip++ & TRIM);
  668.             if (c == 0)
  669.                 break;
  670.             if (c == '\n') {
  671.                 /*
  672.                  * Continue around the loop one
  673.                  * more time, so that we can eat
  674.                  * the last newline without terminating
  675.                  * this word.
  676.                  */
  677.                 hadnl = 1;
  678.                 continue;
  679.             }
  680.             if (!quoted && (c == ' ' || c == '\t'))
  681.                 break;
  682.             cnt++;
  683.             psave(c | quoted);
  684.         }
  685.         /*
  686.          * Unless at end-of-file, we will form a new word
  687.          * here if there were characters in the word, or in
  688.          * any case when we take text literally.  If
  689.          * we didn't make empty words here when literal was
  690.          * set then we would lose blank lines.
  691.          */
  692.         if (c != -1 && (cnt || literal))
  693.             pword();
  694.         hadnl = 0;
  695.     } while (c >= 0);
  696. #ifdef GDEBUG
  697.     printf("done in backeval, pvec: %d %d\n", pvec[0], pvec[1]);
  698.     printf("also c = %c <%o>\n", c, c);
  699. #endif
  700.     close(pvec[0]);
  701.     pwait(pid);
  702. }
  703.  
  704. psave(c)
  705.     char c;
  706. {
  707.  
  708.     if (--pnleft <= 0)
  709.         error("Word too long");
  710.     *pargcp++ = c;
  711. }
  712.  
  713. pword()
  714. {
  715.  
  716.     psave(0);
  717.     if (pargc == GAVSIZ)
  718.         error("Too many words from ``");
  719.     pargv[pargc++] = savestr(pargs);
  720.     pargv[pargc] = NOSTR;
  721. #ifdef GDEBUG
  722.     printf("got word %s\n", pargv[pargc-1]);
  723. #endif
  724.     pargcp = pargs;
  725.     pnleft = BUFSIZ - 4;
  726. }
  727.