home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_200 / 292_01 / asexpr.c < prev    next >
C/C++ Source or Header  |  1990-07-17  |  6KB  |  352 lines

  1. /* asexpr.c */
  2.  
  3. /*
  4.  * (C) Copyright 1989,1990
  5.  * All Rights Reserved
  6.  *
  7.  * Alan R. Baldwin
  8.  * 721 Berkeley St.
  9.  * Kent, Ohio  44240
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include <setjmp.h>
  14. #include <string.h>
  15. #include <alloc.h>
  16. #include "asm.h"
  17.  
  18. /*
  19.  * Read an expression. The value of the
  20.  * expression and its associated relocation
  21.  * information is stored into the `expr'
  22.  * structure supplied by the user. `N' is
  23.  * a firewall priority; all top level calls
  24.  * (from the user) should be made with `n'
  25.  * set to 0.
  26.  */
  27. VOID
  28. expr(esp, n)
  29. register struct expr *esp;
  30. {
  31.     register c, d, p;
  32.     struct area *ap;
  33.     struct expr re;
  34.  
  35.     term(esp);
  36.     while (ctype[c = getnb()] & BINOP) {
  37.         if ((p = oprio(c)) <= n)
  38.             break;
  39.         if ((c == '>' || c == '<') && c != get())
  40.             qerr();
  41.         expr(&re, p);
  42.         if (c == '+') {
  43.             if (esp->e_base.e_ap == NULL) {
  44.                 esp->e_flag = re.e_flag;
  45.                 esp->e_base.e_ap = re.e_base.e_ap;
  46.             } else
  47.             if (re.e_base.e_ap) {
  48.                 rerr();
  49.             }
  50.             esp->e_addr += re.e_addr;
  51.         } else
  52.         if (c == '-') {
  53.             if ((ap = re.e_base.e_ap) != NULL) {
  54.                 if (esp->e_base.e_ap == ap) {
  55.                     esp->e_base.e_ap = NULL;
  56.                 } else {
  57.                     rerr();
  58.                 }
  59.                 if (esp->e_flag || re.e_flag) {
  60.                     rerr();
  61.                 }
  62.             }
  63.             esp->e_addr -= re.e_addr;
  64.         } else {
  65.             abscheck(esp);
  66.             abscheck(&re);
  67.             switch (c) {
  68.  
  69.             case '*':
  70.                 esp->e_addr *= re.e_addr;
  71.                 break;
  72.  
  73.             case '/':
  74.                 esp->e_addr /= re.e_addr;
  75.                 break;
  76.  
  77.             case '&':
  78.                 esp->e_addr &= re.e_addr;
  79.                 break;
  80.  
  81.             case '|':
  82.                 esp->e_addr |= re.e_addr;
  83.                 break;
  84.  
  85.             case '%':
  86.                 esp->e_addr %= re.e_addr;
  87.                 break;
  88.  
  89.             case '^':
  90.                 esp->e_addr ^= re.e_addr;
  91.                 break;
  92.  
  93.             case '<':
  94.                 esp->e_addr <<= re.e_addr;
  95.                 break;
  96.  
  97.             case '>':
  98.                 esp->e_addr >>= re.e_addr;
  99.                 break;
  100.             }
  101.         }
  102.     }
  103.     unget(c);
  104. }
  105.  
  106. /*
  107.  * Read an absolute expression.
  108.  */
  109. addr_t
  110. absexpr()
  111. {
  112.     struct expr e;
  113.  
  114.     expr(&e, 0);
  115.     abscheck(&e);
  116.     return (e.e_addr);
  117. }
  118.  
  119. /*
  120.  * Read a term.
  121.  * Handles unary operators, brackets,
  122.  * constants in decimal, octal or hexadecimal
  123.  * and identifiers. This routine is also
  124.  * responsible for setting the relocation type
  125.  * to symbol based (e.flag != 0) on global
  126.  * references.
  127.  */
  128. VOID
  129. term(esp)
  130. register struct expr *esp;
  131. {
  132.     register c, n;
  133.     register char *jp;
  134.     char id[NCPS];
  135.     struct sym  *sp;
  136.     struct tsym *tp;
  137.     int r, v;
  138.  
  139.     c = getnb();
  140.     if (c == '#') { c = getnb(); }
  141.     if (c == LFTERM) {
  142.         expr(esp, 0);
  143.         if (getnb() != RTTERM)
  144.             qerr();
  145.         return;
  146.     }
  147.     if (c == '-') {
  148.         expr(esp, 100);
  149.         abscheck(esp);
  150.         esp->e_addr = -esp->e_addr;
  151.         return;
  152.     }
  153.     if (c == '~') {
  154.         expr(esp, 100);
  155.         abscheck(esp);
  156.         esp->e_addr = ~esp->e_addr;
  157.         return;
  158.     }
  159.     if (c == '\'') {
  160.         esp->e_mode = S_USER;
  161.         esp->e_flag = 0;
  162.         esp->e_base.e_ap = NULL;
  163.         esp->e_addr = getmap(-1);
  164.         return;
  165.     }
  166.     if (c == '\"') {
  167.         esp->e_mode = S_USER;
  168.         esp->e_flag = 0;
  169.         esp->e_base.e_ap = NULL;
  170.         if (hilo) {
  171.             esp->e_addr  = (getmap(-1)&0377)<<8;
  172.             esp->e_addr |= (getmap(-1)&0377);
  173.         } else {
  174.             esp->e_addr  = (getmap(-1)&0377);
  175.             esp->e_addr |= (getmap(-1)&0377)<<8;
  176.         }
  177.         return;
  178.     }
  179.     if (c == '>' || c == '<') {
  180.         expr(esp, 100);
  181.         abscheck(esp);
  182.         if (c == '>')
  183.             esp->e_addr >>= 8;
  184.         esp->e_addr &= 0377;
  185.         return;
  186.     }
  187.     if (ctype[c] & DIGIT) {
  188.         esp->e_mode = S_USER;
  189.         esp->e_flag = 0;
  190.         esp->e_base.e_ap = NULL;
  191.         jp = ip;
  192.         while (ctype[*jp] & RAD10) {
  193.             jp++;
  194.         }
  195.         if (*jp == '$') {
  196.             n = 0;
  197.             while ((v = digit(c, 10)) >= 0) {
  198.                 n = 10*n + v;
  199.                 c = get();
  200.             }
  201.             tp = symp->s_tsym;
  202.             while (tp) {
  203.                 if (n == tp->t_num) {
  204.                     esp->e_base.e_ap = tp->t_area;
  205.                     esp->e_addr = tp->t_addr;
  206.                     return;
  207.                 }
  208.                 tp = tp->t_lnk;
  209.             }
  210.             err('u');
  211.             esp->e_addr = 0;
  212.             return;
  213.         }
  214.         r = radix;
  215.         if (c == '0') {
  216.             c = get();
  217.             switch (c) {
  218.                 case 'b':
  219.                 case 'B':
  220.                     r = 2;
  221.                     c = get();
  222.                     break;
  223.                 case '@':
  224.                 case 'o':
  225.                 case 'O':
  226.                 case 'q':
  227.                 case 'Q':
  228.                     r = 8;
  229.                     c = get();
  230.                     break;
  231.                 case 'd':
  232.                 case 'D':
  233.                     r = 10;
  234.                     c = get();
  235.                     break;
  236.                 case 'h':
  237.                 case 'H':
  238.                 case 'x':
  239.                 case 'X':
  240.                     r = 16;
  241.                     c = get();
  242.                     break;
  243.                 default:
  244.                     break;
  245.             }
  246.         }
  247.         n = 0;
  248.         while ((v = digit(c, r)) >= 0) {
  249.             n = r*n + v;
  250.             c = get();
  251.         }
  252.         unget(c);
  253.         esp->e_addr = n;
  254.         return;
  255.     }
  256.     if (ctype[c] & LETTER) {
  257.         esp->e_mode = S_USER;
  258.         esp->e_flag = 0;
  259.         esp->e_base.e_ap = NULL;
  260.         esp->e_addr = 0;
  261.         getid(id, c);
  262.         sp = lookup(id);
  263.         if (sp->s_type == S_NEW) {
  264.             if (sp->s_flag&S_GBL) {
  265.                 esp->e_flag = 1;
  266.                 esp->e_base.e_sp = sp;
  267.                 return;
  268.             }
  269.             err('u');
  270.         } else {
  271.             esp->e_mode = sp->s_type;
  272.             esp->e_addr = sp->s_addr;
  273.             esp->e_base.e_ap = sp->s_area;
  274.         }
  275.         return;
  276.     }
  277.     qerr();
  278. }
  279.  
  280. /*
  281.  * If `c' is a legal radix `r' digit
  282.  * return its value; otherwise return
  283.  * -1.
  284.  */
  285. int
  286. digit(c, r)
  287. register c, r;
  288. {
  289.     if (r == 16) {
  290.         if (ctype[c] & RAD16) {
  291.             if (c >= 'A' && c <= 'F')
  292.                 return (c - 'A' + 10);
  293.             if (c >= 'a' && c <= 'f')
  294.                 return (c - 'a' + 10);
  295.             return (c - '0');
  296.         }
  297.     } else
  298.     if (r == 10) {
  299.         if (ctype[c] & RAD10)
  300.             return (c - '0');
  301.     } else
  302.     if (r == 8) {
  303.         if (ctype[c] & RAD8)
  304.             return (c - '0');
  305.     } else
  306.     if (r == 2) {
  307.         if (ctype[c] & RAD2)
  308.             return (c - '0');
  309.     }
  310.     return (-1);
  311. }
  312.  
  313. /*
  314.  * Check if the value of the supplied
  315.  * expression is absolute; if not give
  316.  * a relocation error and force the
  317.  * type to absolute.
  318.  */
  319. VOID
  320. abscheck(esp)
  321. register struct expr *esp;
  322. {
  323.     if (esp->e_flag || esp->e_base.e_ap) {
  324.         esp->e_flag = 0;
  325.         esp->e_base.e_ap = NULL;
  326.         rerr();
  327.     }
  328. }
  329.  
  330. /*
  331.  * Return the priority of the binary
  332.  * operator `c'.
  333.  */
  334. int
  335. oprio(c)
  336. register c;
  337. {
  338.     if (c == '*' || c == '/' || c == '%')
  339.         return (10);
  340.     if (c == '+' || c == '-')
  341.         return (7);
  342.     if (c == '<' || c == '>')
  343.         return (5);
  344.     if (c == '^')
  345.         return (4);
  346.     if (c == '&')
  347.         return (3);
  348.     if (c == '|')
  349.         return (1);
  350.     return (0);
  351. }
  352.