home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / CROSSASM / 68ASMSIM.ZIP / asmsrc / eval.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-09-07  |  10.8 KB  |  441 lines

  1. /***********************************************************************
  2.  *
  3.  *        EVAL.C
  4.  *        Expression Evaluator for 68000 Assembler
  5.  *
  6.  *    Function: eval()
  7.  *        Evaluates a constant expression. The p argument points
  8.  *        to the string to be evaluated, and the function returns
  9.  *        a pointer to the first character beyond the end of the
  10.  *        expression. The value of the expression and an error
  11.  *        code are returned via output arguments. The function 
  12.  *        handles errors according to the following table:
  13.  *
  14.  *                   Pass1        Pass1   Pass2         Pass2
  15.  *        Condition          Error        *refPtr Error         *refPtr
  16.  *        ----------------   ----------   -----   -----------   -----
  17.  *        Undefined symbol   INCOMPLETE   FALSE   UNDEFINED     FALSE
  18.  *        Division by zero   INCOMPLETE   FALSE   DIV_BY_ZERO   FALSE
  19.  *        Syntax error       SYNTAX      --      SYNTAX        --
  20.  *         Constant error     x_TOO_BIG    T/F     x_TOO_BIG     T/F
  21.  *        No error           OK           T/F     OK            T/F
  22.  *
  23.  *        The char pointed to by refPtr is set to TRUE if all the
  24.  *        symbols encountered in the expression are backwards
  25.  *        references or FALSE if at least one symbol is a forward
  26.  *        reference. 
  27.  *
  28.  *     Usage:    char *eval(p, valuePtr, refPtr, errorPtr)
  29.  *        char *p;
  30.  *        long    *valuePtr;
  31.  *        char *refPtr;
  32.  *        int *errorPtr;
  33.  *
  34.  *    Errors: ASCII_TOO_BIG
  35.  *        DIV_BY_ZERO
  36.  *        INCOMPLETE
  37.  *        NUMBER_TOO_BIG
  38.  *        REG_LIST_SPEC
  39.  *        SYNTAX
  40.  *        UNDEFINED
  41.  *
  42.  *      Author: Paul McKee
  43.  *        ECE492    North Carolina State University
  44.  *
  45.  *        Date:    9/24/86
  46.  *
  47.  ************************************************************************/
  48.  
  49.  
  50. #include <stdio.h>
  51. #include <ctype.h>
  52. #include "asm.h"
  53.  
  54. extern char pass2;
  55.  
  56. /* Largest number that can be represented in an unsigned int
  57.     - MACHINE DEPENDENT */
  58. #define INTLIMIT 0xFFFF
  59. #define LONGLIMIT 0xFFFFFFFF
  60.  
  61. #define STACKMAX 5
  62.  
  63. char    *eval(p, valuePtr, refPtr, errorPtr)
  64. char    *p;
  65. long    *valuePtr;
  66. char    *refPtr;
  67. int    *errorPtr;
  68. {
  69. long    valStack[STACKMAX];
  70. char    opStack[STACKMAX-1];
  71. int    valPtr = 0;
  72. int    opPtr = 0;
  73. long    t;
  74. int    prec;
  75. long    i;
  76. char    evaluate, backRef;
  77. int    status;
  78.  
  79. /*    printf("EVAL: Input string is \"%s\"\n", p); */
  80.     /* Assume that the expression is to be evaluated,
  81.        at least until an undefined symbol is found */
  82.     evaluate = TRUE;
  83.     /* Assume initially that all symbols are backwards references */
  84.     *refPtr = TRUE;
  85.     /* Loop until terminator character is found (loop is exited via return) */
  86.     while (TRUE) {
  87.         /************************************************
  88.          *                        *
  89.          *        EXPECT AN OPERAND        *
  90.          *                        *
  91.          ************************************************/
  92.         /* Use evalNumber to read in a number or symbol */
  93.         status = OK;
  94.         p = evalNumber(p, &t, &backRef, &status);
  95.         NEWERROR(*errorPtr, status);
  96.         if (!backRef && (status > ERROR || status == INCOMPLETE)) {
  97.             /* Stop evaluating the expression */
  98.             evaluate = FALSE;
  99.             *refPtr = FALSE;
  100.             }
  101.         else if (*errorPtr > SEVERE)
  102.             /* Pass any other error to the caller */
  103.             return NULL;
  104.         else {
  105.             /* If OK or WARNING, push the value on the stack */
  106.             if (evaluate)
  107.                 valStack[valPtr++] = t;
  108.             /* Set *refPtr to reflect the symbol just parsed */
  109.             *refPtr = (char) (*refPtr && backRef);
  110.             }
  111. /*        printf("Operand read - stack contains (bottom to top):\n");
  112.         for (i = 0; i < valPtr || i < opPtr; i++) {
  113.             printf("%2d: ", i);
  114.             if (i < valPtr)
  115.                 printf("%10d ", valStack[i]);
  116.             else
  117.                 printf("           ");
  118.             if (i < opPtr)
  119.                 putchar(opStack[i]);
  120.             putchar('\n');
  121.             } */
  122.  
  123.         /************************************************
  124.          *                        *
  125.          *        EXPECT AN OPERATOR        *
  126.          *                        *
  127.          ************************************************/
  128.         /* Handle the >> and << operators */
  129.         if (*p == '>' || *p == '<') {
  130.             p++;
  131.             if (*p != *(p-1)) {
  132.                 NEWERROR(*errorPtr, SYNTAX);
  133.                 return NULL;
  134.                 }
  135.             }
  136.         prec = precedence(*p);
  137.         /* Do all stacked operations that are of higher
  138.            precedence than the operator just examined. */
  139.         while (opPtr && evaluate && (prec <= precedence(opStack[opPtr-1]))) {
  140.             /* Pop operands and operator and do the operation */
  141.             t = valStack[--valPtr];
  142.             i = valStack[--valPtr];
  143.             status = doOp(i, t, opStack[--opPtr], &t);
  144.             if (status != OK) {
  145.                 /* Report error from doOp */
  146.                 if (pass2) {
  147.                     NEWERROR(*errorPtr, status);
  148.                     }
  149.                 else
  150.                     NEWERROR(*errorPtr, INCOMPLETE);
  151.                 evaluate = FALSE;
  152.                 *refPtr = FALSE;
  153.                 }
  154.             else
  155.                 /* Otherwise push result on the stack */
  156.                 valStack[valPtr++] = t;
  157.             }
  158.         if (prec) {
  159.             if (evaluate)
  160.                 /* If operator is valid, push it on the stack */
  161.  
  162.                 opStack[opPtr++] = *p;
  163.             p++;
  164.             }
  165.         else if (*p == ',' || *p == '(' || *p == ')' || !(*p) || isspace(*p)) {
  166.             /* If the character terminates the expression,
  167.                then return the various results needed. */
  168.             if (evaluate)
  169.                 *valuePtr = valStack[--valPtr];
  170.             else
  171.                 *valuePtr = 0;
  172. /*            printf("EVAL: The expression is \"");
  173.             while (start < p)
  174.                 putchar(*start++);
  175.             printf("\"\n"); */
  176.             return p;
  177.             }
  178.         else {
  179.             /* Otherwise report the syntax error */
  180.             NEWERROR(*errorPtr,  SYNTAX);
  181.             return NULL;
  182.             }
  183.  
  184. /*        printf("Operator processed - stack contains (bottom to top):\n")
  185. ;
  186.         for (i = 0; i < valPtr || i < opPtr; i++) {
  187.             printf("%2d: ", i);
  188.             if (i < valPtr)
  189.                 printf("%10d ", valStack[i]);
  190.             else
  191.                 printf("           ");
  192.             if (i < opPtr)
  193.                 putchar(opStack[i]);
  194.             putchar('\n');
  195.             } */
  196.         }
  197.  
  198.     return NORMAL;
  199.  
  200. }
  201.  
  202.  
  203.  
  204.  
  205. char    *evalNumber(p, numberPtr, refPtr, errorPtr)
  206. char    *p;
  207. long    *numberPtr;
  208. char    *refPtr;
  209. int    *errorPtr;
  210. {
  211. int    status;
  212. long    base;
  213. long    x;
  214. char    name[SIGCHARS+1];
  215. symbolDef *symbol, *lookup();
  216. int    i;
  217. char    endFlag;
  218.  
  219.     *refPtr = TRUE;
  220.     if (*p == '-') {
  221.         /* Evaluate unary minus operator recursively */
  222.         p = evalNumber(++p, &x, refPtr, errorPtr);
  223.         *numberPtr = -x;
  224.         return p;
  225.         }
  226.     else if (*p == '~') {
  227.         /* Evaluate one's complement operator recursively */
  228.         p = evalNumber(++p, &x, refPtr, errorPtr);
  229.         *numberPtr = ~x;
  230.         return p;
  231.         }
  232.     else if (*p == '(') {
  233.         /* Evaluate parenthesized expressions recursively */
  234.         p = eval(++p, &x, refPtr, errorPtr);
  235.         if (*errorPtr > SEVERE)
  236.             return NULL;
  237.         else if (*p != ')') {
  238.             NEWERROR(*errorPtr, SYNTAX);
  239.             return NULL;
  240.             }
  241.         else {
  242.             *numberPtr = x;
  243.             return ++p;
  244.             }
  245.         }
  246.     else if (*p == '$' && isxdigit(*(p+1))) {
  247.         /* Convert hex digits until another character is
  248.            found. (At least one hex digit is present.) */
  249.         x = 0;
  250.         while (isxdigit(*++p)) {
  251.             if ((unsigned long)x > (unsigned long)LONGLIMIT/16)
  252.                 NEWERROR(*errorPtr, NUMBER_TOO_BIG);
  253.             if (*p > '9')
  254.                 x = 16 * x + (*p - 'A' + 10);
  255.             else
  256.                 x = 16 * x + (*p - '0');
  257.             }
  258.         *numberPtr = x;
  259.         return p;
  260.         }
  261.     else if (*p == '%' || *p == '@' || isdigit(*p)) {
  262.         /* Convert digits in the appropriate base (binary, 
  263.            octal, or decimal) until an invalid digit is found. */
  264.         if (*p == '%') {
  265.             base = 2;
  266.             p++;
  267.             }
  268.         else if (*p == '@') {
  269.             base = 8;
  270.             p++;
  271.             }
  272.         else base = 10;
  273.         /* Check that at least one digit is present */
  274.         if (*p < '0' || *p >= '0' + base) {
  275.             NEWERROR(*errorPtr, SYNTAX);
  276.             return NULL;
  277.             }
  278.         x = 0;
  279.         /* Convert the digits into an integer */
  280.         while (*p >= '0' && *p < '0' + base) {
  281.             if (x > (LONGLIMIT - (*p - '0')) / base) {
  282.                 NEWERROR(*errorPtr, NUMBER_TOO_BIG);
  283.                 printf ("number is too big\n");
  284.                 }
  285.             x = (long) ( (long) ((long) base * x) + (long) (*p - '0') );
  286.             p++;
  287.             }
  288.         *numberPtr = x;
  289.         return p;
  290.         }
  291.     else if (*p == '\'') {
  292.         endFlag = FALSE;
  293.         i = 0;
  294.         x = 0;
  295.         p++;
  296.         while (!endFlag) {
  297.             if (*p == '\'') 
  298.                 if (*(p+1) == '\'') {
  299.                     x = (x << 8) + *p;
  300.                     i++;
  301.                     p++;
  302.                     }
  303.                 else
  304.                     endFlag = TRUE;
  305.             else {
  306.                 x = (x << 8) + *p;
  307.                 i++;
  308.                 }
  309.             p++;
  310.             }
  311.         if (i == 0) {
  312.             NEWERROR(*errorPtr, SYNTAX);
  313.             return NULL;
  314.             }
  315.         else if (i == 3)
  316.             x = x << 8;
  317.         else if (i > 4)
  318.             NEWERROR(*errorPtr, ASCII_TOO_BIG);
  319.         *numberPtr = x;
  320.         return p;
  321.         }
  322.     else if (isalpha(*p) || *p == '.') {
  323.         /* Determine the value of a symbol */
  324.         i = 0;
  325.         /* Collect characters of the symbol's name
  326.            (only SIGCHARS characters are significant) */
  327.         do {
  328.             if (i < SIGCHARS)
  329.                 name[i++] = *p;
  330.             p++;
  331.         } while (isalnum(*p) || *p == '.' || *p == '_' || *p == '$');
  332.         name[i] = '\0';
  333.         /* Look up the name in the symbol table, resulting
  334.            in a pointer to the symbol table entry */
  335.         status = OK;
  336.         symbol = lookup(name, FALSE, &status);
  337. /*        printf("EvalNumber: Status from lookup = %04X\n", status); */
  338.         if (status == OK)
  339.             /* If symbol was found, and it's not a register
  340.                list symbol, then return its value */
  341.             if (!(symbol->flags & REG_LIST_SYM)) {
  342.                 *numberPtr = symbol->value;
  343. /*                printf("The value of the symbol \"%s\" is %08lX\n",
  344.                     name, *numberPtr); */
  345.                 if (pass2)
  346.                     *refPtr = (symbol->flags & BACKREF);
  347.                 }
  348.             else {
  349.                 /* If it is a register list symbol, return error */
  350.                 *numberPtr = 0;
  351.                 NEWERROR(*errorPtr, REG_LIST_SPEC);
  352.                 }
  353.         else {
  354.             /* Otherwise return an error */
  355.             if (pass2) {
  356.                 NEWERROR(*errorPtr, UNDEFINED);
  357.                 }
  358.             else
  359.                 NEWERROR(*errorPtr, INCOMPLETE);
  360.             *refPtr = FALSE;
  361.             }
  362. /*        printf("The symbol \"%s\" is%s a backwards reference\n",
  363.             name, (*refPtr) ? "" : " not"); */
  364.         return p;
  365.          }
  366.     else {
  367.         /* Otherwise, the character was not a valid operand */
  368.         NEWERROR(*errorPtr, SYNTAX);
  369.         return NULL;
  370.         }
  371.  
  372.     return NORMAL;
  373.  
  374. }
  375.  
  376.  
  377.  
  378. int precedence(op)
  379. char op;
  380. {
  381.     /* Compute the precedence of an operator. Higher numbers indicate
  382.        higher precedence, e.g., precedence('*') > precedence('+').
  383.        Any character which is not a binary operator will be assigned
  384.        a precedence of zero. */
  385.     switch (op) {
  386.         case '+' :
  387.         case '-' : return 1;
  388.         case '&' :
  389.          case '!' : return 3;
  390.         case '>' :
  391.         case '<' : return 4;
  392.         case '*' :
  393.         case '/' : 
  394.         case '\\': return 2;
  395.         default  : return 0;
  396.         }
  397.  
  398.     return NORMAL;
  399.  
  400. }
  401.  
  402.  
  403.  
  404. int doOp(val1, val2, op, result)
  405. long    val1, val2;
  406. char    op;
  407. long    *result;
  408. {
  409.  
  410.     /* Performs the operation of the operator on the two operands.
  411.        Returns OK or DIV_BY_ZERO. */
  412.  
  413.     switch (op) {
  414.         case '+' : *result = val1 + val2;  return OK;
  415.         case '-' : *result = val1 - val2;  return OK;
  416.         case '&' : *result = val1 & val2;  return OK;
  417.         case '!' : *result = val1 | val2;  return OK;
  418.         case '>' : *result = val1 >> val2; return OK;
  419.         case '<' : *result = val1 << val2; return OK;
  420.         case '*' : *result = val1 * val2;  return OK;
  421.         case '/' : if (val2 != 0) {
  422.                    *result = val1 / val2;
  423.                    return OK;
  424.                    }
  425.                else
  426.                    return DIV_BY_ZERO;
  427.         case '\\': if (val2 != 0) {
  428.                    *result = val1 % val2;
  429.                    return OK;
  430.                    }
  431.                else
  432.                    return DIV_BY_ZERO;
  433.         default  : printf("DoOp: Operator error  op = '%c' val1 = %d val2 = %d\n", op, val1, val2);
  434.         }
  435.  
  436.     return NORMAL;
  437.  
  438. }
  439.  
  440.  
  441.