home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2870 / expr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-28  |  4.3 KB  |  269 lines

  1. /*
  2.  * Copyright 1991, John F. Haugh II
  3.  * All rights reserved.
  4.  *
  5.  * Permission is granted to copy and create derivative works for any
  6.  * non-commercial purpose, provided this copyright notice is preserved
  7.  * in all copies of source code, or included in human readable form
  8.  * and conspicuously displayed on all copies of object code or
  9.  * distribution media.
  10.  */
  11.  
  12. #ifndef lint
  13. static    char    sccsid[] = "@(#)expr.c    2.2    09:26:00    2/27/91";
  14. #endif
  15.  
  16. #include <ctype.h>
  17.  
  18. /*
  19.  * number - parse numbers
  20.  */
  21.  
  22. static int
  23. number (cpp, result)
  24. char    **cpp;
  25. long    *result;
  26. {
  27.     char    *cp = *cpp;
  28.     char    *ep;
  29.     char    buf[101];
  30.     int    i;
  31.     int    base;
  32.     long    value;
  33.  
  34.     if (! isdigit (*cp))
  35.         return -1;
  36.  
  37.     if (*cp == '0' && *(cp + 1) == 'x') {
  38.         base = 16;
  39.         cp += 2;
  40.         for (i = 0;*cp && isxdigit (*cp);)
  41.             buf[i++] = *cp++;
  42.     } else if (*cp == '0') {
  43.         base = 8;
  44.         cp += 1;
  45.         for (i = 0;*cp && *cp >= '0' && *cp <= '7';)
  46.             buf[i++] = *cp++;
  47.     } else {
  48.         base = 10;
  49.         for (i = 0;*cp && isdigit (*cp);)
  50.             buf[i++] = *cp++;
  51.     }
  52.     buf[i] = '\0';
  53.     *result = strtol (buf, &ep, base);
  54.     if (*ep) {
  55.         *cpp = *cpp + (ep - buf);
  56.         return -1;
  57.     }
  58.     *cpp = cp;
  59.     return 0;
  60. }
  61.  
  62. /*
  63.  * symbol - lookup symbol names
  64.  */
  65.  
  66. static int
  67. symbol (cpp, result)
  68. char    **cpp;
  69. long    *result;
  70. {
  71.     char    *cp = *cpp;
  72.     char    buf[101];    /* yes, the longest symbol is 100 characters */
  73.     int    i;
  74.  
  75.     buf[0] = '_'; i = 1;
  76.  
  77.     if (*cp != '_' && ! isalpha (*cp))
  78.         return -1;
  79.  
  80.     while (i < 100 && (*cp == '_' || isalpha (*cp) || isdigit (*cp)))
  81.         buf[i++] = *cp++;
  82.  
  83.     if (i == 100) {
  84.         *cpp = cp;
  85.         return -1;
  86.     }
  87.     buf[i++] = '\0';
  88.  
  89.     if ((*result = sym2addr (buf + 1, 0)) == -1 &&
  90.             (*result = sym2addr (buf, 0)) == -1)
  91.         return -1;
  92.  
  93.     *cpp = cp;
  94.     return 0;
  95. }
  96.  
  97. /*
  98.  * term - parse terms
  99.  *
  100.  *    <term> ::= '(' <expr> ')' | <number> | <symbol> | '-' <number
  101.  */
  102.  
  103. static int
  104. term (cpp, result)
  105. char    **cpp;
  106. long    *result;
  107. {
  108.     char    *cp = *cpp;
  109.  
  110.     while (*cp && isspace (*cp))
  111.         cp++;
  112.  
  113.     if (isdigit (*cp)) {
  114.         if (number (&cp, result)) {
  115.             *cpp = cp;
  116.             return -1;
  117.         }
  118.     } else if (*cp == '_' || isalpha (*cp)) {
  119.         if (symbol (&cp, result)) {
  120.             *cpp = cp;
  121.             return -1;
  122.         }
  123.     } else if (*cp == '(') {
  124.         cp++;
  125.         if (expr (&cp, result)) {
  126.             *cpp = cp;
  127.             return -1;
  128.         }
  129.         while (*cp && isspace (*cp))
  130.             cp++;
  131.  
  132.         if (*cp != ')') {
  133.             *cpp = cp;
  134.             return -1;
  135.         }
  136.         cp++;
  137.     } else if (*cp == '-') {
  138.         cp++;
  139.         if (number (&cp, result)) {
  140.             *cpp = cp;
  141.             return -1;
  142.         }
  143.         *result = - *result;
  144.     } else
  145.         return -1;
  146.  
  147.     *cpp = cp;
  148.     return 0;
  149. }
  150.  
  151. /*
  152.  * prod - parse expressions
  153.  *
  154.  *    <prod> ::= <prod> ('*' | '/' | '%' | '&') <term> | <term>
  155.  */
  156.  
  157. static int
  158. prod (cpp, result)
  159. char    **cpp;
  160. long    *result;
  161. {
  162.     long    left, right;
  163.     enum { star, slash, percent, ampersand } op;
  164.     char    *cp = *cpp;
  165.  
  166.     while (*cp && isspace (*cp))
  167.         cp++;
  168.  
  169.     if (term (&cp, &left)) {
  170.         *cpp = cp;
  171.         return -1;
  172.     }
  173.     while (*cp) {
  174.         while (*cp && isspace (*cp))
  175.             cp++;
  176.  
  177.         if (! *cp)
  178.             break;
  179.  
  180.         switch (*cp) {
  181.             case '+':
  182.             case '-':
  183.             case '|':
  184.             case '^':
  185.             case ')':    *cpp = cp;
  186.                     *result = left;
  187.                     return 0;
  188.             case '*':    op = star; break;
  189.             case '/':    op = slash; break;
  190.             case '%':    op = percent; break;
  191.             case '&':    op = ampersand; break;
  192.             default:    *cpp = cp;
  193.                     return -1;
  194.         }
  195.         cp++;
  196.         if (term (&cp, &right)) {
  197.             *cpp = cp;
  198.             return -1;
  199.         }
  200.         switch (op) {
  201.             case star:    left *= right; break;
  202.             case slash:    if (right == 0)
  203.                         return -1;
  204.                     left /= right; break;
  205.             case percent:    if (right == 0)
  206.                         return -1;
  207.                     left %= right; break;
  208.             case ampersand:    left &= right; break;
  209.         }
  210.     }
  211.     *result = left;
  212.     *cpp = cp;
  213.     return 0;
  214. }
  215.  
  216. /*
  217.  * expr - parse expressions
  218.  *
  219.  *    <expr> ::= <expr> ('+' | '-' | '|' | '^') <prod> | <prod>
  220.  */
  221.  
  222. int
  223. expr (cpp, result)
  224. char    **cpp;
  225. long    *result;
  226. {
  227.     long    left, right;
  228.     enum { plus, minus, pipe, caret } op;
  229.     char    *cp = *cpp;
  230.  
  231.     while (*cp && isspace (*cp))
  232.         cp++;
  233.  
  234.     if (prod (&cp, &left)) {
  235.         *cpp = cp;
  236.         return -1;
  237.     }
  238.     while (*cp) {
  239.         while (*cp && isspace (*cp))
  240.             cp++;
  241.  
  242.         if (! *cp)
  243.             break;
  244.  
  245.         switch (*cp) {
  246.             case '+':    op = plus; break;
  247.             case '-':    op = minus; break;
  248.             case '|':    op = pipe; break;
  249.             case '^':    op = caret; break;
  250.             default:    *cpp = cp;
  251.                     return -1;
  252.         }
  253.         cp++;
  254.         if (prod (&cp, &right)) {
  255.             *cpp = cp;
  256.             return -1;
  257.         }
  258.         switch (op) {
  259.             case plus:    left += right; break;
  260.             case minus:    left -= right; break;
  261.             case pipe:    left |= right; break;
  262.             case caret:    left ^= right; break;
  263.         }
  264.     }
  265.     *result = left;
  266.     *cpp = cp;
  267.     return 0;
  268. }
  269.