home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / mbug / mbug103.arc / MAC3.C < prev    next >
Text File  |  1979-12-31  |  10KB  |  343 lines

  1. /*
  2. ** MAC3.C -- Small-Mac Assembler -- Part 3: Expression Analyzer
  3. **
  4. **                Copyright 1985 J. E. Hendrix
  5. **
  6. */
  7. #include <stdio.h>
  8. #include "mac.h"
  9. #include "rel.h"
  10. #include "ext.h"
  11.  
  12. #define NOCCARGC    /* no argument count passing */
  13.  
  14. #define OR     1    /* |  */
  15. #define XOR    2    /* ^  */
  16. #define AND    3    /* &  */
  17. #define EQ     4    /* == */
  18. #define NE     5    /* != */
  19. #define LE     6    /* <= */
  20. #define GE     7    /* >= */
  21. #define LT     8    /* <  */
  22. #define GT     9    /* >  */
  23. #define RSH   10    /* >> */
  24. #define LSH   11    /* << */
  25. #define PLUS  12    /* +  */
  26. #define MINUS 13    /* -  */
  27. #define MULT  14    /* *  */
  28. #define DIV   15    /* /  */
  29. #define MOD   16    /* %  */
  30. #define CPL   17    /* ~  */
  31. #define NOT   18    /* !  */
  32. #define LPN   19    /* (  */
  33. #define RPN   20    /* )  */
  34. #define LOC   21    /* $  */
  35. #define SYM   22    /* symbol */
  36. #define NUM   23    /* number */
  37. #define EOE   24    /* end of expr */
  38.  
  39. int
  40.   number,            /* value of numeric token */
  41.   iloc,                /* instruction location */
  42.   ct;                /* current token */
  43.  
  44. int                /* operators by precedence level */
  45.   l1ops[] = {OR, NULL},
  46.   l2ops[] = {XOR, NULL},
  47.   l3ops[] = {AND, NULL},
  48.   l4ops[] = {EQ, NE, NULL},
  49.   l5ops[] = {LE, GE, LT, GT, NULL},
  50.   l6ops[] = {LSH, RSH, NULL},
  51.   l7ops[] = {PLUS, MINUS, NULL},
  52.   l8ops[] = {MULT, DIV, MOD, NULL};
  53.  
  54. /*
  55. ** evaluate the next expression at ep
  56. ** caller must set ep
  57. */
  58. expr(value, type) int *value, *type; {
  59.   ct = NULL;                /* no current token */
  60.   if(token(EOE)) {
  61.     *value = 0; *type = ABS;        /* null expression */
  62.     return;
  63.     }
  64.   if(!level1(value, type) || ct != EOE) experr();
  65.   }
  66.  
  67. level1(v, t) int *v, *t; {return (down(l1ops, level2, v, t));}
  68. level2(v, t) int *v, *t; {return (down(l2ops, level3, v, t));}
  69. level3(v, t) int *v, *t; {return (down(l3ops, level4, v, t));}
  70. level4(v, t) int *v, *t; {return (down(l4ops, level5, v, t));}
  71. level5(v, t) int *v, *t; {return (down(l5ops, level6, v, t));}
  72. level6(v, t) int *v, *t; {return (down(l6ops, level7, v, t));}
  73. level7(v, t) int *v, *t; {return (down(l7ops, level8, v, t));}
  74. level8(v, t) int *v, *t; {return (down(l8ops,  unary, v, t));}
  75.  
  76. unary(v, t) int *v, *t;  {
  77.   if(token(CPL)) {            /* ~ */
  78.     if(!unary(v, t)) return (NO);
  79.     *v = ~*v;
  80.     goto check;
  81.     }
  82.   else if(token(NOT)) {            /* ! */
  83.     if(!unary(v ,t)) return (NO);
  84.     *v = !*v;
  85.     goto check;
  86.     }
  87.   else if(token(MINUS)) {        /* - */
  88.     if(!unary(v, t)) return (NO);
  89.     *v = -*v;
  90.     check:
  91.     if(*t & RELBITS) relerr();        /* can't be relocatable */
  92.     *t &= ~RELBITS;            /* force ABS */
  93.     return (YES);            /* lie about it */
  94.     }
  95.   else return (primary(v, t));
  96.   }
  97.  
  98. primary(v, t) int *v, *t; {
  99.   int ok;
  100.   if(token(LPN)) {                /* ( */
  101.     ok = level1(v, t);
  102.     if(token(RPN)) return(ok);
  103.     return (NO);
  104.     }
  105.   *t = ABS; *v = 0;                /* defaults */
  106.   if(token(NUM)) {                /* number */
  107.     *v = number;
  108.     return (YES);
  109.     }
  110.   else if(token(LOC)) {                /* $ */
  111.     *v = iloc;
  112.     *t = PREL;
  113.     return (YES);
  114.     }
  115.   else {
  116.     if(token(SYM)) {                /* symbol */
  117.       if(stfind()) {
  118.         *t = stptr[STFLAG];
  119.         if(!(stptr[STFLAG] & XRBIT)) {
  120.           if(gotxr) rederr();
  121.           *v = getint(stptr + STVALUE);
  122.           }
  123.         else goto doxr;                /* ext ref */
  124.         }
  125.       else if(gotxr) {                /* define new ext ref */
  126.         addsym();                /* symbol */
  127.         *t = XRBIT|ABS;                /* 1st ext ref is ABS 0 */
  128.         doxr:
  129.         prior = getint(stptr + STVALUE);    /* save prior ptr */
  130.         putint(stptr + STVALUE, loc);        /* this becomes prev */
  131.         stptr[STFLAG] |= XRBIT|PREL;        /* ext ref is relative */
  132.         }
  133.       else underr();                /* undefined */
  134.       return (YES);
  135.       }
  136.     }
  137.   return (NO);
  138.   }
  139.  
  140. /*
  141. ** drop to a lower level
  142. */
  143. down(ops, level, v, t) int *ops, (*level)(), *v, *t; {
  144.   int *op;
  145.   if(!(*level)(v, t)) return (NO);
  146.   op = --ops;
  147.   while(*++op) {
  148.     if(token(*op)) {
  149.       if(!down2(*op, level, v, t)) return (NO);
  150.       if(token(EOE)) return (YES);
  151.       op = ops;
  152.       }
  153.     }
  154.   return (YES);
  155.   }
  156.  
  157. /*
  158. ** binary drop to a lower level
  159. */
  160. down2(oper, level, v, t) int oper, (*level)(), *v, *t; {
  161.   int ok, vr, tr, tl;
  162.   ok = (*level)(&vr, &tr);
  163.   *v = binary(*v, oper, vr);            /* apply operator */
  164.   tl = *t & RELBITS;
  165.   *t = (*t | tr) & ~RELBITS;    /* merge flag bits & default to ABS */
  166.   tr &= RELBITS;
  167.   if(tl == ABS) {
  168.     if(tr == ABS) return (ok);            /* abs <oper> abs */
  169.     else {                    /* abs <oper> rel */
  170.       if(oper == PLUS) {*t |= PREL; return (ok);}
  171.       return (NO);
  172.       }
  173.     }
  174.   else {                    /* rel <oper> abs */
  175.     if(tr == ABS) {
  176.       switch(oper) {
  177.         case PLUS: case MINUS:
  178.         *t |= PREL;
  179.         return (ok);
  180.         }
  181.       return (NO);
  182.       }
  183.     else {                    /* rel <oper> rel */
  184.       if(*t & XRBIT) return (NO);
  185.       switch(oper) {
  186.         case MINUS:
  187.         case EQ: case LT: case LE:
  188.         case NE: case GT: case GE:
  189.         return (ok);
  190.         }
  191.       return (NO);
  192.       }
  193.     }
  194.   }
  195.  
  196. /*
  197. ** apply a binary operator
  198. */
  199. binary(left, oper, right) int left, oper, right; {
  200.   switch(oper) {
  201.     case OR:    return (left  |  right);
  202.     case XOR:   return (left  ^  right);
  203.     case AND:   return (left  &  right);
  204.     case EQ:    return (left  == right);
  205.     case NE:    return (left  != right);
  206.     case LE:    return (left  <= right);
  207.     case GE:    return (left  >= right);
  208.     case LT:    return (left  <  right);
  209.     case GT:    return (left  >  right);
  210.     case RSH:   return (left  >> right);
  211.     case LSH:   return (left  << right);
  212.     case PLUS:  return (left  +  right);
  213.     case MINUS: return (left  -  right);
  214.     case MULT:  return (left  *  right);
  215.     case DIV:   return (left  /  right);
  216.     case MOD:   return (left  %  right);
  217.     }
  218.   return (NULL);
  219.   }
  220.  
  221. /*
  222. ** scan for next token
  223. */
  224. token(want) int want; {
  225.   int len;
  226.   if(ct) return (found(want, ct));    /* already have a token */
  227.   while(isspace(*ep)) ++ep;
  228.   switch(*ep++) {
  229.     case '|': return (found(want, OR));
  230.     case '^': return (found(want, XOR));
  231.     case '&': return (found(want, AND));
  232.     case '+': return (found(want, PLUS));
  233.     case '-': return (found(want, MINUS));
  234.     case '*': return (found(want, MULT));
  235.     case '/': return (found(want, DIV));
  236.     case '%': return (found(want, MOD));
  237.     case '~': return (found(want, CPL));
  238.     case '(': return (found(want, LPN));
  239.     case ')': return (found(want, RPN));
  240.     case '$': return (found(want, LOC));
  241.     case ',': return (found(want, EOE));
  242.     case '!': if(*ep++ == '=') return (found(want, NE));  --ep;
  243.                                return (found(want, NOT));
  244.     case '<': if(*ep++ == '=') return (found(want, LE));  --ep;
  245.               if(*ep++ == '<') return (found(want, LSH)); --ep;
  246.                                return (found(want, LT));
  247.     case '>': if(*ep++ == '=') return (found(want, GE));  --ep;
  248.               if(*ep++ == '>') return (found(want, RSH)); --ep;
  249.                                return (found(want, GT));
  250.     case '=': if(*ep++ == '=') return (found(want, EQ));  --ep;
  251.     }
  252.   --ep;
  253.   ep = getsym(ep, YES); if(stsym[0]) {return (found(want, SYM));}
  254.   if(len = getnum(ep))    {ep += len; return (found(want, NUM));}
  255.   if(atend(*ep))                      return (found(want, EOE));
  256.   return (NO);
  257.   }
  258.  
  259. /*
  260. ** what was found?
  261. */
  262. found(want, have) int want, have; {
  263.   ct = have;                    /* new current token */
  264.   if(ct == want) {                /* was it sought? */
  265.     if(ct != EOE) ct = NULL;            /* yes, pass it by */
  266.     return (YES);                /* caller has a hit */
  267.     }
  268.   return (NO);                    /* sorry, no hit */
  269.   }
  270.  
  271. /*
  272. ** get hex, dec, or oct number as binary value in number
  273. ** return length of field processed, else zero
  274. */ 
  275. getnum(at) char *at; {
  276.   int bump, len; char *end, *cp;
  277.   cp = at;
  278.   if((*cp == '\'' || *cp == '"') && *cp == cp[2]) {    /* quoted char */
  279.     number = cp[1] & 255;
  280.     return (3);
  281.     }
  282.   switch(*cp) {
  283.     case '0': case '1': case '2': case '3': case '4':
  284.     case '5': case '6': case '7': case '8': case '9':
  285.     end = cp;
  286.     bump = 1;
  287.     while(YES) {
  288.       switch(toupper(*end)) {
  289.          default: if(isxdigit(*end)) {++end; continue;}
  290.                   bump = 0;
  291.                   len = utoi(cp, &number); break;
  292.         case 'Q':
  293.         case 'O': len = otoi(cp, &number); break;
  294.         case 'H': len = xtoi(cp, &number); break;
  295.         }
  296.       break;
  297.       }
  298.     if(len != (end - cp)) numerr();    /* bad number */
  299.     return ((end - at) + bump);
  300.     }
  301.   return (0);
  302.   }
  303.  
  304. /*
  305. ** get a symbol into stsym
  306. */
  307. getsym(at, ref) char *at; int ref; {
  308.   int j;
  309.   j = badsym = gotep = gotxr = gotlabel = 0;
  310.   if(!isdigit(*at)) {
  311.     while(YES) {
  312.       switch(toupper(*at)) {
  313.         case '#':
  314.           if(ref) {gotxr = YES; if(*++at == '#') ++at; break;}
  315.         default:
  316.           if(ref) break;
  317.           badsym = YES;
  318.         case 'A': case 'B': case 'C': case 'D': case 'E':
  319.         case 'F': case 'G': case 'H': case 'I': case 'J':
  320.         case 'K': case 'L': case 'M': case 'N': case 'O':
  321.         case 'P': case 'Q': case 'R': case 'S': case 'T':
  322.         case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
  323.         case '0': case '1': case '2': case '3': case '4':
  324.         case '5': case '6': case '7': case '8': case '9':
  325.         case '_': case '.': case '$': case '?': case '@':
  326.           if(j < MAXLAB) stsym[j++] = toupper(*at);
  327.           ++at;
  328.           continue;
  329.         case ':':
  330.           gotlabel = YES;
  331.           if(*++at == ':') {gotep = YES; ++at;}
  332.         case ' ': case '\t': case '\n':
  333.         case ',': case NULL: case COMMENT:
  334.         }
  335.       while(isspace(*at)) ++at;
  336.       break;
  337.       }
  338.     }
  339.   stsym[j] = NULL;
  340.   if(stsym[0] && !gotlabel) gotnam = YES; else gotnam = NO;
  341.   return (at);
  342.   }
  343.