home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / bin / csh / exp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-06  |  13.7 KB  |  712 lines

  1. /*-
  2.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. 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.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)exp.c    5.15 (Berkeley) 11/6/91";
  36. #endif /* not lint */
  37.  
  38. #include <sys/types.h>
  39. #include <sys/stat.h>
  40. #include <stdlib.h>
  41. #include <unistd.h>
  42. #ifndef SHORT_STRINGS
  43. #include <string.h>
  44. #endif /* SHORT_STRINGS */
  45. #if __STDC__
  46. # include <stdarg.h>
  47. #else
  48. # include <varargs.h>
  49. #endif
  50.  
  51. #include "csh.h"
  52. #include "extern.h"
  53.  
  54. #define IGNORE    1    /* in ignore, it means to ignore value, just parse */
  55. #define NOGLOB    2    /* in ignore, it means not to globone */
  56.  
  57. #define    ADDOP    1
  58. #define    MULOP    2
  59. #define    EQOP    4
  60. #define    RELOP    8
  61. #define    RESTOP    16
  62. #define    ANYOP    31
  63.  
  64. #define    EQEQ    1
  65. #define    GTR    2
  66. #define    LSS    4
  67. #define    NOTEQ    6
  68. #define EQMATCH 7
  69. #define NOTEQMATCH 8
  70.  
  71. static int    exp1    __P((Char ***, bool));
  72. static int    exp2    __P((Char ***, bool));
  73. static int    exp2a    __P((Char ***, bool));
  74. static int    exp2b    __P((Char ***, bool));
  75. static int    exp2c    __P((Char ***, bool));
  76. static Char *    exp3    __P((Char ***, bool));
  77. static Char *    exp3a    __P((Char ***, bool));
  78. static Char *    exp4    __P((Char ***, bool));
  79. static Char *    exp5    __P((Char ***, bool));
  80. static Char *    exp6    __P((Char ***, bool));
  81. static void    evalav    __P((Char **));
  82. static int    isa    __P((Char *, int));
  83. static int    egetn    __P((Char *));
  84.  
  85. #ifdef EDEBUG
  86. static void    etracc    __P((char *, Char *, Char ***));
  87. static void    etraci    __P((char *, int, Char ***));
  88. #endif
  89.  
  90. int
  91. expr(vp)
  92.     register Char ***vp;
  93. {
  94.     return (exp0(vp, 0));
  95. }
  96.  
  97. int
  98. exp0(vp, ignore)
  99.     register Char ***vp;
  100.     bool    ignore;
  101. {
  102.     register int p1 = exp1(vp, ignore);
  103.  
  104. #ifdef EDEBUG
  105.     etraci("exp0 p1", p1, vp);
  106. #endif
  107.     if (**vp && eq(**vp, STRor2)) {
  108.     register int p2;
  109.  
  110.     (*vp)++;
  111.     p2 = exp0(vp, (ignore & IGNORE) || p1);
  112. #ifdef EDEBUG
  113.     etraci("exp0 p2", p2, vp);
  114. #endif
  115.     return (p1 || p2);
  116.     }
  117.     return (p1);
  118. }
  119.  
  120. static int
  121. exp1(vp, ignore)
  122.     register Char ***vp;
  123.     bool    ignore;
  124. {
  125.     register int p1 = exp2(vp, ignore);
  126.  
  127. #ifdef EDEBUG
  128.     etraci("exp1 p1", p1, vp);
  129. #endif
  130.     if (**vp && eq(**vp, STRand2)) {
  131.     register int p2;
  132.  
  133.     (*vp)++;
  134.     p2 = exp1(vp, (ignore & IGNORE) || !p1);
  135. #ifdef EDEBUG
  136.     etraci("exp1 p2", p2, vp);
  137. #endif
  138.     return (p1 && p2);
  139.     }
  140.     return (p1);
  141. }
  142.  
  143. static int
  144. exp2(vp, ignore)
  145.     register Char ***vp;
  146.     bool    ignore;
  147. {
  148.     register int p1 = exp2a(vp, ignore);
  149.  
  150. #ifdef EDEBUG
  151.     etraci("exp3 p1", p1, vp);
  152. #endif
  153.     if (**vp && eq(**vp, STRor)) {
  154.     register int p2;
  155.  
  156.     (*vp)++;
  157.     p2 = exp2(vp, ignore);
  158. #ifdef EDEBUG
  159.     etraci("exp3 p2", p2, vp);
  160. #endif
  161.     return (p1 | p2);
  162.     }
  163.     return (p1);
  164. }
  165.  
  166. static int
  167. exp2a(vp, ignore)
  168.     register Char ***vp;
  169.     bool    ignore;
  170. {
  171.     register int p1 = exp2b(vp, ignore);
  172.  
  173. #ifdef EDEBUG
  174.     etraci("exp2a p1", p1, vp);
  175. #endif
  176.     if (**vp && eq(**vp, STRcaret)) {
  177.     register int p2;
  178.  
  179.     (*vp)++;
  180.     p2 = exp2a(vp, ignore);
  181. #ifdef EDEBUG
  182.     etraci("exp2a p2", p2, vp);
  183. #endif
  184.     return (p1 ^ p2);
  185.     }
  186.     return (p1);
  187. }
  188.  
  189. static int
  190. exp2b(vp, ignore)
  191.     register Char ***vp;
  192.     bool    ignore;
  193. {
  194.     register int p1 = exp2c(vp, ignore);
  195.  
  196. #ifdef EDEBUG
  197.     etraci("exp2b p1", p1, vp);
  198. #endif
  199.     if (**vp && eq(**vp, STRand)) {
  200.     register int p2;
  201.  
  202.     (*vp)++;
  203.     p2 = exp2b(vp, ignore);
  204. #ifdef EDEBUG
  205.     etraci("exp2b p2", p2, vp);
  206. #endif
  207.     return (p1 & p2);
  208.     }
  209.     return (p1);
  210. }
  211.  
  212. static int
  213. exp2c(vp, ignore)
  214.     register Char ***vp;
  215.     bool    ignore;
  216. {
  217.     register Char *p1 = exp3(vp, ignore);
  218.     register Char *p2;
  219.     register int i;
  220.  
  221. #ifdef EDEBUG
  222.     etracc("exp2c p1", p1, vp);
  223. #endif
  224.     if (i = isa(**vp, EQOP)) {
  225.     (*vp)++;
  226.     if (i == EQMATCH || i == NOTEQMATCH)
  227.         ignore |= NOGLOB;
  228.     p2 = exp3(vp, ignore);
  229. #ifdef EDEBUG
  230.     etracc("exp2c p2", p2, vp);
  231. #endif
  232.     if (!(ignore & IGNORE))
  233.         switch (i) {
  234.  
  235.         case EQEQ:
  236.         i = eq(p1, p2);
  237.         break;
  238.  
  239.         case NOTEQ:
  240.         i = !eq(p1, p2);
  241.         break;
  242.  
  243.         case EQMATCH:
  244.         i = Gmatch(p1, p2);
  245.         break;
  246.  
  247.         case NOTEQMATCH:
  248.         i = !Gmatch(p1, p2);
  249.         break;
  250.         }
  251.     xfree((ptr_t) p1);
  252.     xfree((ptr_t) p2);
  253.     return (i);
  254.     }
  255.     i = egetn(p1);
  256.     xfree((ptr_t) p1);
  257.     return (i);
  258. }
  259.  
  260. static Char *
  261. exp3(vp, ignore)
  262.     register Char ***vp;
  263.     bool    ignore;
  264. {
  265.     register Char *p1, *p2;
  266.     register int i;
  267.  
  268.     p1 = exp3a(vp, ignore);
  269. #ifdef EDEBUG
  270.     etracc("exp3 p1", p1, vp);
  271. #endif
  272.     if (i = isa(**vp, RELOP)) {
  273.     (*vp)++;
  274.     if (**vp && eq(**vp, STRequal))
  275.         i |= 1, (*vp)++;
  276.     p2 = exp3(vp, ignore);
  277. #ifdef EDEBUG
  278.     etracc("exp3 p2", p2, vp);
  279. #endif
  280.     if (!(ignore & IGNORE))
  281.         switch (i) {
  282.  
  283.         case GTR:
  284.         i = egetn(p1) > egetn(p2);
  285.         break;
  286.  
  287.         case GTR | 1:
  288.         i = egetn(p1) >= egetn(p2);
  289.         break;
  290.  
  291.         case LSS:
  292.         i = egetn(p1) < egetn(p2);
  293.         break;
  294.  
  295.         case LSS | 1:
  296.         i = egetn(p1) <= egetn(p2);
  297.         break;
  298.         }
  299.     xfree((ptr_t) p1);
  300.     xfree((ptr_t) p2);
  301.     return (putn(i));
  302.     }
  303.     return (p1);
  304. }
  305.  
  306. static Char *
  307. exp3a(vp, ignore)
  308.     register Char ***vp;
  309.     bool    ignore;
  310. {
  311.     register Char *p1, *p2, *op;
  312.     register int i;
  313.  
  314.     p1 = exp4(vp, ignore);
  315. #ifdef EDEBUG
  316.     etracc("exp3a p1", p1, vp);
  317. #endif
  318.     op = **vp;
  319.     if (op && any("<>", op[0]) && op[0] == op[1]) {
  320.     (*vp)++;
  321.     p2 = exp3a(vp, ignore);
  322. #ifdef EDEBUG
  323.     etracc("exp3a p2", p2, vp);
  324. #endif
  325.     if (op[0] == '<')
  326.         i = egetn(p1) << egetn(p2);
  327.     else
  328.         i = egetn(p1) >> egetn(p2);
  329.     xfree((ptr_t) p1);
  330.     xfree((ptr_t) p2);
  331.     return (putn(i));
  332.     }
  333.     return (p1);
  334. }
  335.  
  336. static Char *
  337. exp4(vp, ignore)
  338.     register Char ***vp;
  339.     bool    ignore;
  340. {
  341.     register Char *p1, *p2;
  342.     register int i = 0;
  343.  
  344.     p1 = exp5(vp, ignore);
  345. #ifdef EDEBUG
  346.     etracc("exp4 p1", p1, vp);
  347. #endif
  348.     if (isa(**vp, ADDOP)) {
  349.     register Char *op = *(*vp)++;
  350.  
  351.     p2 = exp4(vp, ignore);
  352. #ifdef EDEBUG
  353.     etracc("exp4 p2", p2, vp);
  354. #endif
  355.     if (!(ignore & IGNORE))
  356.         switch (op[0]) {
  357.  
  358.         case '+':
  359.         i = egetn(p1) + egetn(p2);
  360.         break;
  361.  
  362.         case '-':
  363.         i = egetn(p1) - egetn(p2);
  364.         break;
  365.         }
  366.     xfree((ptr_t) p1);
  367.     xfree((ptr_t) p2);
  368.     return (putn(i));
  369.     }
  370.     return (p1);
  371. }
  372.  
  373. static Char *
  374. exp5(vp, ignore)
  375.     register Char ***vp;
  376.     bool    ignore;
  377. {
  378.     register Char *p1, *p2;
  379.     register int i = 0;
  380.  
  381.     p1 = exp6(vp, ignore);
  382. #ifdef EDEBUG
  383.     etracc("exp5 p1", p1, vp);
  384. #endif
  385.     if (isa(**vp, MULOP)) {
  386.     register Char *op = *(*vp)++;
  387.  
  388.     p2 = exp5(vp, ignore);
  389. #ifdef EDEBUG
  390.     etracc("exp5 p2", p2, vp);
  391. #endif
  392.     if (!(ignore & IGNORE))
  393.         switch (op[0]) {
  394.  
  395.         case '*':
  396.         i = egetn(p1) * egetn(p2);
  397.         break;
  398.  
  399.         case '/':
  400.         i = egetn(p2);
  401.         if (i == 0)
  402.             stderror(ERR_DIV0);
  403.         i = egetn(p1) / i;
  404.         break;
  405.  
  406.         case '%':
  407.         i = egetn(p2);
  408.         if (i == 0)
  409.             stderror(ERR_MOD0);
  410.         i = egetn(p1) % i;
  411.         break;
  412.         }
  413.     xfree((ptr_t) p1);
  414.     xfree((ptr_t) p2);
  415.     return (putn(i));
  416.     }
  417.     return (p1);
  418. }
  419.  
  420. static Char *
  421. exp6(vp, ignore)
  422.     register Char ***vp;
  423.     bool    ignore;
  424. {
  425.     int     ccode, i = 0;
  426.     register Char *cp, *dp, *ep;
  427.  
  428.     if (**vp == 0)
  429.     stderror(ERR_NAME | ERR_EXPRESSION);
  430.     if (eq(**vp, STRbang)) {
  431.     (*vp)++;
  432.     cp = exp6(vp, ignore);
  433. #ifdef EDEBUG
  434.     etracc("exp6 ! cp", cp, vp);
  435. #endif
  436.     i = egetn(cp);
  437.     xfree((ptr_t) cp);
  438.     return (putn(!i));
  439.     }
  440.     if (eq(**vp, STRtilde)) {
  441.     (*vp)++;
  442.     cp = exp6(vp, ignore);
  443. #ifdef EDEBUG
  444.     etracc("exp6 ~ cp", cp, vp);
  445. #endif
  446.     i = egetn(cp);
  447.     xfree((ptr_t) cp);
  448.     return (putn(~i));
  449.     }
  450.     if (eq(**vp, STRLparen)) {
  451.     (*vp)++;
  452.     ccode = exp0(vp, ignore);
  453. #ifdef EDEBUG
  454.     etraci("exp6 () ccode", ccode, vp);
  455. #endif
  456.     if (*vp == 0 || **vp == 0 || ***vp != ')')
  457.         stderror(ERR_NAME | ERR_EXPRESSION);
  458.     (*vp)++;
  459.     return (putn(ccode));
  460.     }
  461.     if (eq(**vp, STRLbrace)) {
  462.     register Char **v;
  463.     struct command faket;
  464.     Char   *fakecom[2];
  465.  
  466.     faket.t_dtyp = NODE_COMMAND;
  467.     faket.t_dflg = 0;
  468.     faket.t_dcar = faket.t_dcdr = faket.t_dspr = NULL;
  469.     faket.t_dcom = fakecom;
  470.     fakecom[0] = STRfakecom;
  471.     fakecom[1] = NULL;
  472.     (*vp)++;
  473.     v = *vp;
  474.     for (;;) {
  475.         if (!**vp)
  476.         stderror(ERR_NAME | ERR_MISSING, '}');
  477.         if (eq(*(*vp)++, STRRbrace))
  478.         break;
  479.     }
  480.     if (ignore & IGNORE)
  481.         return (Strsave(STRNULL));
  482.     psavejob();
  483.     if (pfork(&faket, -1) == 0) {
  484.         *--(*vp) = 0;
  485.         evalav(v);
  486.         exitstat();
  487.     }
  488.     pwait();
  489.     prestjob();
  490. #ifdef EDEBUG
  491.     etraci("exp6 {} status", egetn(value(STRstatus)), vp);
  492. #endif
  493.     return (putn(egetn(value(STRstatus)) == 0));
  494.     }
  495.     if (isa(**vp, ANYOP))
  496.     return (Strsave(STRNULL));
  497.     cp = *(*vp)++;
  498.     if (*cp == '-' && any("erwxfdzopls", cp[1])) {
  499.     struct stat stb;
  500.  
  501.     if (cp[2] != '\0')
  502.         stderror(ERR_NAME | ERR_FILEINQ);
  503.     /*
  504.      * Detect missing file names by checking for operator in the file name
  505.      * position.  However, if an operator name appears there, we must make
  506.      * sure that there's no file by that name (e.g., "/") before announcing
  507.      * an error.  Even this check isn't quite right, since it doesn't take
  508.      * globbing into account.
  509.      */
  510.     if (isa(**vp, ANYOP) && stat(short2str(**vp), &stb))
  511.         stderror(ERR_NAME | ERR_FILENAME);
  512.  
  513.     dp = *(*vp)++;
  514.     if (ignore & IGNORE)
  515.         return (Strsave(STRNULL));
  516.     ep = globone(dp, G_ERROR);
  517.     switch (cp[1]) {
  518.  
  519.     case 'r':
  520.         i = !access(short2str(ep), R_OK);
  521.         break;
  522.  
  523.     case 'w':
  524.         i = !access(short2str(ep), W_OK);
  525.         break;
  526.  
  527.     case 'x':
  528.         i = !access(short2str(ep), X_OK);
  529.         break;
  530.  
  531.     default:
  532.         if (
  533. #ifdef S_IFLNK
  534.         cp[1] == 'l' ? lstat(short2str(ep), &stb) :
  535. #endif
  536.         stat(short2str(ep), &stb)) {
  537.         xfree((ptr_t) ep);
  538.         return (Strsave(STR0));
  539.         }
  540.         switch (cp[1]) {
  541.  
  542.         case 'f':
  543.         i = S_ISREG(stb.st_mode);
  544.         break;
  545.  
  546.         case 'd':
  547.         i = S_ISDIR(stb.st_mode);
  548.         break;
  549.  
  550.         case 'p':
  551. #ifdef S_ISFIFO
  552.         i = S_ISFIFO(stb.st_mode);
  553. #else
  554.         i = 0;
  555. #endif
  556.         break;
  557.  
  558.         case 'l':
  559. #ifdef S_ISLNK
  560.         i = S_ISLNK(stb.st_mode);
  561. #else
  562.         i = 0;
  563. #endif
  564.         break;
  565.  
  566.         case 's':
  567. #ifdef S_ISSOCK
  568.         i = S_ISSOCK(stb.st_mode);
  569. #else
  570.         i = 0;
  571. #endif
  572.         break;
  573.  
  574.         case 'z':
  575.         i = stb.st_size == 0;
  576.         break;
  577.  
  578.         case 'e':
  579.         i = 1;
  580.         break;
  581.  
  582.         case 'o':
  583.         i = stb.st_uid == uid;
  584.         break;
  585.         }
  586.     }
  587. #ifdef EDEBUG
  588.     etraci("exp6 -? i", i, vp);
  589. #endif
  590.     xfree((ptr_t) ep);
  591.     return (putn(i));
  592.     }
  593. #ifdef EDEBUG
  594.     etracc("exp6 default", cp, vp);
  595. #endif
  596.     return (ignore & NOGLOB ? Strsave(cp) : globone(cp, G_ERROR));
  597. }
  598.  
  599. static void
  600. evalav(v)
  601.     register Char **v;
  602. {
  603.     struct wordent paraml1;
  604.     register struct wordent *hp = ¶ml1;
  605.     struct command *t;
  606.     register struct wordent *wdp = hp;
  607.  
  608.     set(STRstatus, Strsave(STR0));
  609.     hp->prev = hp->next = hp;
  610.     hp->word = STRNULL;
  611.     while (*v) {
  612.     register struct wordent *new =
  613.     (struct wordent *) xcalloc(1, sizeof *wdp);
  614.  
  615.     new->prev = wdp;
  616.     new->next = hp;
  617.     wdp->next = new;
  618.     wdp = new;
  619.     wdp->word = Strsave(*v++);
  620.     }
  621.     hp->prev = wdp;
  622.     alias(¶ml1);
  623.     t = syntax(paraml1.next, ¶ml1, 0);
  624.     if (seterr)
  625.     stderror(ERR_OLD);
  626.     execute(t, -1, NULL, NULL);
  627.     freelex(¶ml1), freesyn(t);
  628. }
  629.  
  630. static int
  631. isa(cp, what)
  632.     register Char *cp;
  633.     register int what;
  634. {
  635.     if (cp == 0)
  636.     return ((what & RESTOP) != 0);
  637.     if (cp[1] == 0) {
  638.     if (what & ADDOP && (*cp == '+' || *cp == '-'))
  639.         return (1);
  640.     if (what & MULOP && (*cp == '*' || *cp == '/' || *cp == '%'))
  641.         return (1);
  642.     if (what & RESTOP && (*cp == '(' || *cp == ')' || *cp == '!' ||
  643.                   *cp == '~' || *cp == '^' || *cp == '"'))
  644.         return (1);
  645.     }
  646.     else if (cp[2] == 0) {
  647.     if (what & RESTOP) {
  648.         if (cp[0] == '|' && cp[1] == '&')
  649.         return (1);
  650.         if (cp[0] == '<' && cp[1] == '<')
  651.         return (1);
  652.         if (cp[0] == '>' && cp[1] == '>')
  653.         return (1);
  654.     }
  655.     if (what & EQOP) {
  656.         if (cp[0] == '=') {
  657.         if (cp[1] == '=')
  658.             return (EQEQ);
  659.         if (cp[1] == '~')
  660.             return (EQMATCH);
  661.         }
  662.         else if (cp[0] == '!') {
  663.         if (cp[1] == '=')
  664.             return (NOTEQ);
  665.         if (cp[1] == '~')
  666.             return (NOTEQMATCH);
  667.         }
  668.     }
  669.     }
  670.     if (what & RELOP) {
  671.     if (*cp == '<')
  672.         return (LSS);
  673.     if (*cp == '>')
  674.         return (GTR);
  675.     }
  676.     return (0);
  677. }
  678.  
  679. static int
  680. egetn(cp)
  681.     register Char *cp;
  682. {
  683.     if (*cp && *cp != '-' && !Isdigit(*cp))
  684.     stderror(ERR_NAME | ERR_EXPRESSION);
  685.     return (getn(cp));
  686. }
  687.  
  688. /* Phew! */
  689.  
  690. #ifdef EDEBUG
  691. static void
  692. etraci(str, i, vp)
  693.     char   *str;
  694.     int     i;
  695.     Char ***vp;
  696. {
  697.     (void) fprintf(csherr, "%s=%d\t", str, i);
  698.     blkpr(csherr, *vp);
  699.     (void) fprintf(csherr, "\n");
  700. }
  701. static void
  702. etracc(str, cp, vp)
  703.     char   *str;
  704.     Char   *cp;
  705.     Char ***vp;
  706. {
  707.     (void) fprintf(csherr, "%s=%s\t", str, vis_str(cp));
  708.     blkpr(csherr, *vp);
  709.     (void) fprintf(csherr, "\n");
  710. }
  711. #endif
  712.