home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / netsrcs / v7_test < prev    next >
Internet Message Format  |  1987-04-02  |  5KB

  1. From erikb@cs.vu.nl Fri Apr  3 01:06:13 1987
  2. Path: seismo!mcvax!botter!erikb
  3. From: erikb@cs.vu.nl (Erik Baalbergen)
  4. Newsgroups: comp.os.minix
  5. Subject: source for test(1)
  6. Keywords: test, shell script
  7. Message-ID: <1132@botter.cs.vu.nl>
  8. Date: 3 Apr 87 06:06:13 GMT
  9. Sender: remote@cs.vu.nl
  10. Reply-To: erikb@cs.vu.nl (Erik Baalbergen)
  11. Distribution: world
  12. Organization: V.U. Informatica, Amsterdam
  13. Lines: 244
  14.  
  15. Here's the source for a version 7-like test. (See UNIX v7 manual, test(1)).
  16. I wrote this program from scratch so there should be no copyright problems.
  17. It is tested on Minix. Compile with cc and see how it goes!
  18. Please report bugs and suggestions to erikb@cs.vu.nl.
  19.  
  20. Erik Baalbergen
  21. -- cut here --
  22. /* test(1); version 7-like  --  author Erik Baalbergen */
  23. #include <sys/types.h>
  24. #include <sys/stat.h>
  25.  
  26. /* test(1) accepts the following grammar:
  27.     expr    ::= bexpr | bexpr "-o" expr ;
  28.     bexpr    ::= primary | primary "-a" bexpr ;
  29.     primary    ::= unary-operator operand
  30.         | operand binary-operator operand
  31.         | operand
  32.         | "(" expr ")"
  33.         | "!" expr
  34.         ;
  35.     unary-operator ::= "-r"|"-w"|"-f"|"-d"|"-s"|"-t"|"-z"|"-n";
  36.     binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt";
  37.     operand ::= <any legal UNIX file name>
  38. */
  39.  
  40. #define EOI    0
  41. #define FILRD    1
  42. #define FILWR    2
  43. #define FILND    3
  44. #define FILID    4
  45. #define FILGZ    5
  46. #define FILTT    6
  47. #define STZER    7
  48. #define STNZE    8
  49. #define STEQL    9
  50. #define STNEQ    10
  51. #define INTEQ    11
  52. #define INTNE    12
  53. #define INTGE    13
  54. #define INTGT    14
  55. #define INTLE    15
  56. #define INTLT    16
  57. #define UNEGN    17
  58. #define BAND    18
  59. #define BOR    19
  60. #define LPAREN    20
  61. #define RPAREN    21
  62. #define OPERAND    22
  63.  
  64. #define UNOP    1
  65. #define BINOP    2
  66. #define BUNOP    3
  67. #define BBINOP    4
  68. #define PAREN    5
  69.  
  70. struct op {
  71.     char *op_text;
  72.     short op_num, op_type;
  73. } ops[] = {
  74.     {"-r", FILRD, UNOP},
  75.     {"-w", FILWR, UNOP},
  76.     {"-f", FILND, UNOP},
  77.     {"-d", FILID, UNOP},
  78.     {"-s", FILGZ, UNOP},
  79.     {"-t", FILTT, UNOP},
  80.     {"-z", STZER, UNOP},
  81.     {"-n", STNZE, UNOP},
  82.     {"=",  STEQL, BINOP},
  83.     {"!=", STNEQ, BINOP},
  84.     {"-eq", INTEQ, BINOP},
  85.     {"-ne", INTNE, BINOP},
  86.     {"-ge", INTGE, BINOP},
  87.     {"-gt", INTGT, BINOP},
  88.     {"-le", INTLE, BINOP},
  89.     {"-lt", INTLT, BINOP},
  90.     {"!", UNEGN, BUNOP},
  91.     {"-a", BAND, BBINOP},
  92.     {"-o", BOR, BBINOP},
  93.     {"(", LPAREN, PAREN},
  94.     {")", RPAREN, PAREN},
  95.     {0, 0, 0}
  96. };
  97.  
  98. long num();
  99. char **ip;
  100. char *prog;
  101. struct op *ip_op;
  102.  
  103. main(argc, argv)
  104.     char *argv[];
  105. {
  106.     prog = argv[0];
  107.     ip = &argv[1];
  108.     exit(!(expr(lex(*ip)) && *++ip == 0));
  109. }
  110.  
  111. expr(n)
  112. {
  113.     int res;
  114.  
  115.     if (n == EOI)
  116.         syntax();
  117.     res = bexpr(n);
  118.     if (lex(*++ip) == BOR)
  119.         return expr(lex(*++ip)) || res;
  120.     ip--;
  121.     return res;
  122. }
  123.  
  124. bexpr(n)
  125. {
  126.     int res;
  127.  
  128.     if (n == EOI)
  129.         syntax();
  130.     res = primary(n);
  131.     if (lex(*++ip) == BAND)
  132.         return bexpr(lex(*++ip)) && res;
  133.     ip--;
  134.     return res;
  135. }
  136.  
  137. primary(n)
  138. {
  139.     register char *opnd1, *opnd2;
  140.     int res;
  141.  
  142.     if (n == EOI)
  143.         syntax();
  144.     if (n == UNEGN)
  145.         return !expr(lex(*++ip));
  146.     if (n == LPAREN) {
  147.         res = expr(lex(*++ip));
  148.         if (lex(*++ip) != RPAREN)
  149.             syntax();
  150.         return res;
  151.     }
  152.     if (n == OPERAND) {
  153.         opnd1 = *ip;
  154.         (void) lex(*++ip);
  155.         if (ip_op && ip_op->op_type == BINOP) {
  156.             struct op *op = ip_op;
  157.  
  158.             if ((opnd2 = *++ip) == (char *)0)
  159.                 syntax();
  160.             
  161.             switch (op->op_num) {
  162.             case STEQL:
  163.                 return strcmp(opnd1, opnd2) == 0;
  164.             case STNEQ:
  165.                 return strcmp(opnd1, opnd2) != 0;
  166.             case INTEQ:
  167.                 return num(opnd1) == num(opnd2);
  168.             case INTNE:
  169.                 return num(opnd1) != num(opnd2);
  170.             case INTGE:
  171.                 return num(opnd1) >= num(opnd2);
  172.             case INTGT:
  173.                 return num(opnd1) > num(opnd2);
  174.             case INTLE:
  175.                 return num(opnd1) <= num(opnd2);
  176.             case INTLT:
  177.                 return num(opnd1) < num(opnd2);
  178.             }
  179.         }
  180.         ip--;
  181.         return strlen(opnd1) > 0;
  182.     }
  183.     /* unary expression */
  184.     if (ip_op->op_type != UNOP || *++ip == 0)
  185.         syntax();
  186.     if (n == STZER)
  187.         return strlen(*ip) == 0;
  188.     if (n == STNZE)
  189.         return strlen(*ip) != 0;
  190.     return filstat(*ip, n);
  191. }
  192.  
  193. filstat(nm, mode)
  194.     char *nm;
  195. {
  196.     struct stat s;
  197.     
  198.     switch (mode) {
  199.     case FILRD:
  200.         return access(nm, 4) == 0;
  201.     case FILWR:
  202.         return access(nm, 2) == 0;
  203.     case FILND:
  204.         return stat(nm, &s) == 0 && ((s.st_mode & S_IFMT) != S_IFDIR);
  205.     case FILID:
  206.         return stat(nm, &s) == 0 && ((s.st_mode & S_IFMT) == S_IFDIR);
  207.     case FILGZ:
  208.         return stat(nm, &s) == 0 && (s.st_size > 0L);
  209.     case FILTT: /* not implemented */
  210.         syntax();
  211.     }
  212. }
  213.  
  214. int
  215. lex(s)
  216.     register char *s;
  217. {
  218.     register struct op *op = ops;
  219.  
  220.     if (s == 0)
  221.         return EOI;
  222.     while (op->op_text) {
  223.         if (strcmp(s, op->op_text) == 0) {
  224.             ip_op = op;
  225.             return op->op_num;
  226.         }
  227.         op++;
  228.     }
  229.     ip_op = (struct op *)0;
  230.     return OPERAND;
  231. }
  232.  
  233. long
  234. num(s)
  235.     register char *s;
  236. {
  237.     long l = 0;
  238.     long sign = 1;
  239.  
  240.     if (*s == '\0')
  241.         syntax();
  242.     if (*s == '-') {
  243.         sign = -1;
  244.         s++;
  245.     }
  246.     while (*s >= '0' && *s <= '9')
  247.         l = l * 10 + *s++ - '0';
  248.     if (*s != '\0')
  249.         syntax();
  250.     return sign * l;
  251. }
  252.  
  253. syntax()
  254. {
  255.     write(2, prog, strlen(prog));
  256.     write(2, ": syntax error\n", 15);
  257.     exit(1);
  258. }
  259.  
  260.  
  261.