home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / OS2MNX1.ZIP / EXPR.C < prev    next >
Text File  |  1989-12-27  |  6KB  |  256 lines

  1. /* expr(1)  --  author Erik Baalbergen */
  2. /* $Header: d:/rcs/D:/RCS/RCS/expr.c 1.2 89/12/27 02:49:00 RCA Exp $
  3.  * $Log:    expr.c $
  4.  * Revision 1.2  89/12/27  02:49:00  RCA
  5.  * "&" and "|" operators don't work.
  6.  * 
  7.  * Revision 1.1  89/12/27  02:41:48  RCA
  8.  * Initial revision
  9.  * 
  10.  */
  11. /*
  12.  * expr accepts the following grammar: expr ::= primary | primary
  13.  * operator expr ; primary ::= '(' expr ')' | signed-integer ;
  14.  * where the priority of the operators is taken care of. The
  15.  * resulting value is printed on stdout. Note that the
  16.  * ":"-operator is not implemented. 
  17.  */
  18.  
  19. #define EOI    0
  20. #define OR    1
  21. #define AND    2
  22. #define LT    3
  23. #define LE    4
  24. #define EQ    5
  25. #define NE    6
  26. #define GE    7
  27. #define GT    8
  28. #define PLUS    9
  29. #define MINUS    10
  30. #define TIMES    11
  31. #define DIV    12
  32. #define MOD    13
  33. #define COLON    14
  34. #define LPAREN    15
  35. #define RPAREN    16
  36. #define OPERAND    20
  37.  
  38. #define MAXPRIO    6
  39.  
  40. struct op
  41. {
  42.    char   *op_text;
  43.    short   op_num, op_prio;
  44. }       ops[] =
  45. {
  46.    {
  47.               "|", OR, 6
  48.    }      ,
  49.    {
  50.               "&", AND, 5
  51.    }      ,
  52.    {
  53.               "<", LT, 4
  54.    }      ,
  55.    {
  56.               "<=", LE, 4
  57.    }      ,
  58.    {
  59.               "=", EQ, 4
  60.    }      ,
  61.    {
  62.               "!=", NE, 4
  63.    }      ,
  64.    {
  65.               ">=", GE, 4
  66.    }      ,
  67.    {
  68.               ">", GT, 4
  69.    }      ,
  70.    {
  71.               "+", PLUS, 3
  72.    }      ,
  73.    {
  74.               "-", MINUS, 3
  75.    }      ,
  76.    {
  77.               "*", TIMES, 2
  78.    }      ,
  79.    {
  80.               "/", DIV, 2
  81.    }      ,
  82.    {
  83.               "%", MOD, 2
  84.    }      ,
  85. /* {":",    COLON,    1}, */
  86.    {
  87.               "(", LPAREN, -1
  88.    }      ,
  89.    {
  90.               ")", RPAREN, -1
  91.    }      ,
  92.    {
  93.               0, 0, 0
  94.    }
  95. };
  96.  
  97. long
  98. eval(), expr();
  99. char   *prog;
  100. char  **ip;
  101. struct op *ip_op;
  102. main(argc, argv)
  103.    char   *argv[];
  104. {
  105. long    res;
  106.     if (argc == 1)
  107.       {
  108.       printf ("\n █▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█");
  109.       printf ("\n █ EXPR     (Do simple math)               $Author: RCA $   █");
  110.       printf ("\n █          $Date: 89/12/27 02:49:00 $     $Revision: 1.2 $ █");
  111.       printf ("\n █ Usage:   EXPR num1 operator num2 ...                     █");
  112.       printf ("\n █          All arguments must be seperated by spaces.      █");
  113.       printf ("\n █ Examples: EXPR 2 + 2 - 1                                 █");
  114.       printf ("\n █           EXPR 4 * 9                                     █");
  115.       printf ("\n █           EXPR 4 * ( 9 + 9 )                             █");
  116.       printf ("\n █           EXPR 100 % 11 [modulo]                         █");
  117.       printf ("\n █           EXPR 7 > 9                                     █");
  118.       printf ("\n █           EXPR 7 < 9                                     █");
  119.       printf ("\n █           EXPR 7 = 9                                     █");
  120.       printf ("\n █           EXPR 7 >= 9                                    █");
  121.       printf ("\n █           EXPR 7 != 9                                    █");
  122.       printf ("\n █ Purpose: Do simple math from command line, without       █");
  123.       printf ("\n █          invoking a special environment.                 █");
  124.       printf ("\n █ OS:      Works under OS/2 or DOS.                        █");
  125.       printf ("\n █ Credits: Eric Baalbergen                                 █");
  126.       printf ("\n █▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█\n");
  127.       exit(1);
  128.       }
  129.    
  130.    prog = argv[0];
  131.    ip = &argv[1];
  132.    res = expr(lex(*ip), MAXPRIO);
  133.    if (*++ip != 0)
  134.       syntax();
  135.    printf("%d\n", res);
  136.    exit(0);
  137. }
  138. lex(s)
  139.    register char *s;
  140. {
  141. register struct op *op = ops;
  142.    if (s == 0)
  143.    {
  144.       ip_op = 0;
  145.       return EOI;
  146.    }
  147.    while (op->op_text)
  148.    {
  149.       if (strcmp(s, op->op_text) == 0)
  150.       {
  151.      ip_op = op;
  152.      return op->op_num;
  153.       }
  154.       op++;
  155.    }
  156.    ip_op = 0;
  157.    return OPERAND;
  158. }
  159.  
  160. long
  161. num(s)
  162.    register char *s;
  163. {
  164. long l = 0;
  165. long    sign = 1;
  166.    if (*s == '\0')
  167.       syntax();
  168.    if (*s == '-')
  169.    {
  170.       sign = -1;
  171.       s++;
  172.    }
  173.    while (*s >= '0' && *s <= '9')
  174. l = l *10 + *s++ - '0';
  175.    if (*s != '\0')
  176.       syntax();
  177. return sign * l;
  178. }
  179. syntax()
  180. {
  181.    write(2, prog, strlen(prog));
  182.    write(2, ": syntax error\n", 15);
  183.    exit(1);
  184. }
  185.  
  186. long
  187. expr(n, prio)
  188. {
  189. long    res;
  190.    if (n == EOI)
  191.       syntax();
  192.    if (n == LPAREN)
  193.    {
  194.       if (prio == 0)
  195.       {
  196.      res = expr(lex(*++ip), MAXPRIO);
  197.      if (lex(*++ip) != RPAREN)
  198.         syntax();
  199.       } else
  200.      res = expr(n, prio - 1);
  201.    } else
  202.    if (n == OPERAND)
  203.    {
  204.       if (prio == 0)
  205.      return num(*ip);
  206.       res = expr(n, prio - 1);
  207.    } else
  208.       syntax();
  209.    while ((n = lex(*++ip)) && ip_op && ip_op->op_prio == prio)
  210.       res = eval(res, n, expr(lex(*++ip), prio - 1));
  211.    ip--;
  212.    return res;
  213. }
  214.  
  215. long
  216. eval(l1, op, l2)
  217.    long    l1, l2;
  218. {
  219.    switch (op)
  220.    {
  221.    case OR:
  222.       return l1 ? l1 : l2;
  223.    case AND:
  224.       return (l1 && l2) ? l1 : 0;
  225.    case LT:
  226.       return l1 < l2;
  227.    case LE:
  228.       return l1 <= l2;
  229.    case EQ:
  230.       return l1 == l2;
  231.    case NE:
  232.       return l1 != l2;
  233.    case GE:
  234.       return l1 >= l2;
  235.    case GT:
  236.       return l1 > l2;
  237.    case PLUS:
  238.       return l1 + l2;
  239.    case MINUS:
  240.       return l1 - l2;
  241.    case TIMES:
  242.       return l1 * l2;
  243.    case DIV:
  244.       return l1 / l2;
  245.    case MOD:
  246.       return l1 % l2;
  247.    }
  248.    fatal();
  249. }
  250. fatal()
  251. {
  252.    write(2, "fatal\n", 6);
  253.    exit(1);
  254. }
  255. 
  256.