* asranlib/asranlib.c, link/lkar.h, link/lkar.c:
[fw/sdcc] / as / link / lkeval.c
index 230c40baed3b2164a946968c21ea12971ffd57b8..433edbcd057a4ec403995a8059643bdda5f052a0 100644 (file)
-/* lkeval.c */
+/* lkeval.c
 
-/*
- * (C) Copyright 1989-1995
- * All Rights Reserved
- *
- * Alan R. Baldwin
- * 721 Berkeley St.
- * Kent, Ohio  44240
- */
+   Copyright (C) 1989-1995 Alan R. Baldwin
+   721 Berkeley St., Kent, Ohio 44240
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include <stdio.h>
 #include <string.h>
 #include "aslink.h"
 
-/*)Module      lkeval.c
- *
- *     The module lkeval.c contains the routines to evaluate
- *     arithmetic/numerical expressions.  The functions in
- *     lkeval.c perform a recursive evaluation of the arithmetic
- *     expression read from the input text line.
- *     The expression may include binary/unary operators, brackets,
- *     symbols, labels, and constants in hexadecimal, decimal, octal
- *     and binary.  Arithmetic operations are prioritized and
- *     evaluated by normal arithmetic conventions.
- *
- *     lkeval.c contains the following functions:
- *             int     digit()
- *             Addr_T  eval()
- *             Addr_T  expr()
- *             int     oprio()
- *             Addr_T  term()
- *
- *     lkeval.c contains no local/static variables
+/*)Module       lkeval.c
+ *
+ *      The module lkeval.c contains the routines to evaluate
+ *      arithmetic/numerical expressions.  The functions in
+ *      lkeval.c perform a recursive evaluation of the arithmetic
+ *      expression read from the input text line.
+ *      The expression may include binary/unary operators, brackets,
+ *      symbols, labels, and constants in hexadecimal, decimal, octal
+ *      and binary.  Arithmetic operations are prioritized and
+ *      evaluated by normal arithmetic conventions.
+ *
+ *      lkeval.c contains the following functions:
+ *              int     digit()
+ *              Addr_T  eval()
+ *              Addr_T  expr()
+ *              int     oprio()
+ *              Addr_T  term()
+ *
+ *      lkeval.c contains no local/static variables
  */
 
-/*)Function    Addr_T  eval()
+/*)Function     Addr_T  eval()
  *
- *     The function eval() evaluates a character string to a
- *     numerical value.
+ *      The function eval() evaluates a character string to a
+ *      numerical value.
  *
- *     local variables:
- *             int     c               character from input string
- *             int     v               value of character in current radix
- *             Addr_T  n               evaluation value
+ *      local variables:
+ *              int     c               character from input string
+ *              int     v               value of character in current radix
+ *              Addr_T  n               evaluation value
  *
- *     global variables:
- *             int     radix           current number conversion radix
+ *      global variables:
+ *              int     radix           current number conversion radix
  *
- *     functions called:
- *             int     digit()         lkeval.c
- *             char    get()           lklex.c
- *             char    getnb()         lklex.c
- *             VOID    unget()         lklex.c
+ *      functions called:
+ *              int     digit()         lkeval.c
+ *              char    get()           lklex.c
+ *              char    getnb()         lklex.c
+ *              VOID    unget()         lklex.c
  *
- *     side effects:
- *             Input test is scanned and evaluated to a
- *             numerical value.
+ *      side effects:
+ *              Input test is scanned and evaluated to a
+ *              numerical value.
  */
 
 Addr_T
 eval()
 {
-       register int c, v;
-       register Addr_T n;
+        register int c, v;
+        register Addr_T n;
 
-       c = getnb();
-       n = 0;
-       while ((v = digit(c, radix)) >= 0) {
-               n = n*radix + v;
-               c = get();
-       }
-       unget(c);
-       return(n);
+        c = getnb();
+        n = 0;
+        while ((v = digit(c, radix)) >= 0) {
+                n = n*radix + v;
+                c = get();
+        }
+        unget(c);
+        return(n);
 }
 
-/*)Function    Addr_T  expr(n)
- *
- *             int     n               a firewall priority; all top
- *                                     level calls (from the user)
- *                                     should be made with n set to 0.
- *
- *     The function expr() evaluates an expression and
- *     returns the value.
- *
- *     local variables:
- *             int     c               current input text character
- *             int     p               current operator priority
- *             Addr_T  v               value returned by term()
- *             Addr_T  ve              value returned by a
- *                                     recursive call to expr()
- *
- *     global variables:
- *             char    ctype[]         array of character types, one per
- *                                     ASCII character
- *             int     lkerr           error flag
- *             FILE *  stderr          c_library
- *
- *     functions called:
- *             VOID    expr()          lkeval.c
- *             int     fprintf()       c_library
- *             int     getnb()         lklex.c
- *             int     oprio()         lkeval.c
- *             VOID    term()          lkeval.c
- *             VOID    unget()         lklex.c
- *
- *
- *     side effects:
- *             An expression is evaluated by scanning the input
- *             text string.
+/*)Function     Addr_T  expr(n)
+ *
+ *              int     n               a firewall priority; all top
+ *                                      level calls (from the user)
+ *                                      should be made with n set to 0.
+ *
+ *      The function expr() evaluates an expression and
+ *      returns the value.
+ *
+ *      local variables:
+ *              int     c               current input text character
+ *              int     p               current operator priority
+ *              Addr_T  v               value returned by term()
+ *              Addr_T  ve              value returned by a
+ *                                      recursive call to expr()
+ *
+ *      global variables:
+ *              char    ctype[]         array of character types, one per
+ *                                      ASCII character
+ *              int     lkerr           error flag
+ *              FILE *  stderr          c_library
+ *
+ *      functions called:
+ *              VOID    expr()          lkeval.c
+ *              int     fprintf()       c_library
+ *              int     getnb()         lklex.c
+ *              int     oprio()         lkeval.c
+ *              VOID    term()          lkeval.c
+ *              VOID    unget()         lklex.c
+ *
+ *
+ *      side effects:
+ *              An expression is evaluated by scanning the input
+ *              text string.
  */
 
 Addr_T
 expr (n)
 {
-       register int c, p;
-       register Addr_T v, ve;
+        register int c, p;
+        register Addr_T v, ve;
 
-       v = term();
-       while (ctype[c = getnb()] & BINOP) {
-               if ((p = oprio(c)) <= n)
-                       break;
-               if ((c == '>' || c == '<') && c != get()) {
-                       fprintf(stderr, "Invalid expression");
-                       lkerr++;
-                       return(v);
-               }
-               ve = expr(p);
-               if (c == '+') {
-                       v += ve;
-               } else
-               if (c == '-') {
-                       v -= ve;
-               } else {
-                       switch (c) {
+        v = term();
+        while (ctype[c = getnb()] & BINOP) {
+                if ((p = oprio(c)) <= n)
+                        break;
+                if ((c == '>' || c == '<') && c != get()) {
+                        fprintf(stderr, "Invalid expression");
+                        lkerr++;
+                        return(v);
+                }
+                ve = expr(p);
+                if (c == '+') {
+                        v += ve;
+                } else
+                if (c == '-') {
+                        v -= ve;
+                } else {
+                        switch (c) {
 
-                       case '*':
-                               v *= ve;
-                               break;
+                        case '*':
+                                v *= ve;
+                                break;
 
-                       case '/':
-                               v /= ve;
-                               break;
+                        case '/':
+                                v /= ve;
+                                break;
 
-                       case '&':
-                               v &= ve;
-                               break;
+                        case '&':
+                                v &= ve;
+                                break;
 
-                       case '|':
-                               v |= ve;
-                               break;
+                        case '|':
+                                v |= ve;
+                                break;
 
-                       case '%':
-                               v %= ve;
-                               break;
+                        case '%':
+                                v %= ve;
+                                break;
 
-                       case '^':
-                               v ^= ve;
-                               break;
+                        case '^':
+                                v ^= ve;
+                                break;
 
-                       case '<':
-                               v <<= ve;
-                               break;
+                        case '<':
+                                v <<= ve;
+                                break;
 
-                       case '>':
-                               v >>= ve;
-                               break;
-                       }
-               }
-       }
-       unget(c);
-       return(v);
+                        case '>':
+                                v >>= ve;
+                                break;
+                        }
+                }
+        }
+        unget(c);
+        return(v);
 }
 
-/*)Function    Addr_T  term()
- *
- *     The function term() evaluates a single constant
- *     or symbol value prefaced by any unary operator
- *     ( +, -, ~, ', ", >, or < ).
- *
- *     local variables:
- *             int     c               current character
- *             char    id[]            symbol name
- *             int     n               value of digit in current radix
- *             int     r               current evaluation radix
- *             sym *   sp              pointer to a sym structure
- *             Addr_T  v               evaluation value
- *
- *     global variables:
- *             char    ctype[]         array of character types, one per
- *                                     ASCII character
- *             int     lkerr           error flag
- *
- *     functions called:
- *             int     digit()         lkeval.c
- *             VOID    expr()          lkeval.c
- *             int     fprintf()       c_library
- *             int     get()           lklex.c
- *             VOID    getid()         lklex.c
- *             int     getmap()        lklex.c
- *             int     getnb()         lklex.c
- *             sym *   lkpsym()        lksym.c
- *             Addr_T  symval()        lksym.c
- *             VOID    unget()         lklex.c
- *
- *     side effects:
- *             An arithmetic term is evaluated by scanning input text.
+/*)Function     Addr_T  term()
+ *
+ *      The function term() evaluates a single constant
+ *      or symbol value prefaced by any unary operator
+ *      ( +, -, ~, ', ", >, or < ).
+ *
+ *      local variables:
+ *              int     c               current character
+ *              char    id[]            symbol name
+ *              int     n               value of digit in current radix
+ *              int     r               current evaluation radix
+ *              sym *   sp              pointer to a sym structure
+ *              Addr_T  v               evaluation value
+ *
+ *      global variables:
+ *              char    ctype[]         array of character types, one per
+ *                                      ASCII character
+ *              int     lkerr           error flag
+ *
+ *      functions called:
+ *              int     digit()         lkeval.c
+ *              VOID    expr()          lkeval.c
+ *              int     fprintf()       c_library
+ *              int     get()           lklex.c
+ *              VOID    getid()         lklex.c
+ *              int     getmap()        lklex.c
+ *              int     getnb()         lklex.c
+ *              sym *   lkpsym()        lksym.c
+ *              Addr_T  symval()        lksym.c
+ *              VOID    unget()         lklex.c
+ *
+ *      side effects:
+ *              An arithmetic term is evaluated by scanning input text.
  */
 
 Addr_T
 term()
 {
-       register int c, r, n;
-       register Addr_T v;
-       struct sym *sp;
-       char id[NCPS];
+        register int c, r, n;
+        register Addr_T v;
+        struct sym *sp;
+        char id[NCPS];
 
-       c = getnb();
-       if (c == '#') { c = getnb(); }
-       if (c == '(') {
-               v = expr(0);
-               if (getnb() != ')') {
-                       fprintf(stderr, "Missing delimiter");
-                       lkerr++;
-               }
-               return(v);
-       }
-       if (c == '-') {
-               return(0-expr(100));
-       }
-       if (c == '~') {
-               return(~expr(100));
-       }
-       if (c == '\'') {
-               return(getmap(-1)&0377);
-       }
-       if (c == '\"') {
-               if (hilo) {
-                       v  = (getmap(-1)&0377)<<8;
-                       v |=  getmap(-1)&0377;
-               } else {
-                       v  =  getmap(-1)&0377;
-                       v |= (getmap(-1)&0377)<<8;
-               }
-               return(v);
-       }
-       if (c == '>' || c == '<') {
-               v = expr(100);
-               if (c == '>')
-                       v >>= 8;
-               return(v&0377);
-       }
-       if (ctype[c] & DIGIT) {
-               r = 10;
-               if (c == '0') {
-                       c = get();
-                       switch (c) {
-                       case 'b':
-                       case 'B':
-                               r = 2;
-                               c = get();
-                               break;
-                       case '@':
-                       case 'o':
-                       case 'O':
-                       case 'q':
-                       case 'Q':
-                               r = 8;
-                               c = get();
-                               break;
-                       case 'd':
-                       case 'D':
-                               r = 10;
-                               c = get();
-                               break;
-                       case 'h':
-                       case 'H':
-                       case 'x':
-                       case 'X':
-                               r = 16;
-                               c = get();
-                               break;
-                       default:
-                               break;
-                       }
-               }
-               v = 0;
-               while ((n = digit(c, r)) >= 0) {
-                       v = r*v + n;
-                       c = get();
-               }
-               unget(c);
-               return(v);
-       }
-       if (ctype[c] & LETTER) {
-               getid(id, c);
-               if ((sp = lkpsym(id, 0)) == NULL) {
-                       fprintf(stderr, "Undefined symbol %8s\n", id);
-                       lkerr++;
-                       return(0);
-               } else {
-                       return(symval(sp));
-               }
-       }
-       /* Shouldn't get here. */
-       return(0);
+        c = getnb();
+        if (c == '#') { c = getnb(); }
+        if (c == '(') {
+                v = expr(0);
+                if (getnb() != ')') {
+                        fprintf(stderr, "Missing delimiter");
+                        lkerr++;
+                }
+                return(v);
+        }
+        if (c == '-') {
+                return(0-expr(100));
+        }
+        if (c == '~') {
+                return(~expr(100));
+        }
+        if (c == '\'') {
+                return(getmap(-1)&0377);
+        }
+        if (c == '\"') {
+                if (hilo) {
+                        v  = (getmap(-1)&0377)<<8;
+                        v |=  getmap(-1)&0377;
+                } else {
+                        v  =  getmap(-1)&0377;
+                        v |= (getmap(-1)&0377)<<8;
+                }
+                return(v);
+        }
+        if (c == '>' || c == '<') {
+                v = expr(100);
+                if (c == '>')
+                        v >>= 8;
+                return(v&0377);
+        }
+        if (ctype[c] & DIGIT) {
+                r = 10;
+                if (c == '0') {
+                        c = get();
+                        switch (c) {
+                        case 'b':
+                        case 'B':
+                                r = 2;
+                                c = get();
+                                break;
+                        case '@':
+                        case 'o':
+                        case 'O':
+                        case 'q':
+                        case 'Q':
+                                r = 8;
+                                c = get();
+                                break;
+                        case 'd':
+                        case 'D':
+                                r = 10;
+                                c = get();
+                                break;
+                        case 'h':
+                        case 'H':
+                        case 'x':
+                        case 'X':
+                                r = 16;
+                                c = get();
+                                break;
+                        default:
+                                break;
+                        }
+                }
+                v = 0;
+                while ((n = digit(c, r)) >= 0) {
+                        v = r*v + n;
+                        c = get();
+                }
+                unget(c);
+                return(v);
+        }
+        if (ctype[c] & LETTER) {
+                getid(id, c);
+                if ((sp = lkpsym(id, 0)) == NULL) {
+                        fprintf(stderr, "Undefined symbol %8s\n", id);
+                        lkerr++;
+                        return(0);
+                } else {
+                        return(symval(sp));
+                }
+        }
+        /* Shouldn't get here. */
+        return(0);
 }
 
-/*)Function    int     digit(c, r)
+/*)Function     int     digit(c, r)
  *
- *             int     c               digit character
- *             int     r               current radix
+ *              int     c               digit character
+ *              int     r               current radix
  *
- *     The function digit() returns the value of c
- *     in the current radix r.  If the c value is not
- *     a number of the current radix then a -1 is returned.
+ *      The function digit() returns the value of c
+ *      in the current radix r.  If the c value is not
+ *      a number of the current radix then a -1 is returned.
  *
- *     local variables:
- *             none
+ *      local variables:
+ *              none
  *
- *     global variables:
- *             char    ctype[]         array of character types, one per
- *                                     ASCII character
+ *      global variables:
+ *              char    ctype[]         array of character types, one per
+ *                                      ASCII character
  *
- *     functions called:
- *             none
+ *      functions called:
+ *              none
  *
- *     side effects:
- *             none
+ *      side effects:
+ *              none
  */
 
 int
 digit(c, r)
 register int c, r;
 {
-       if (r == 16) {
-               if (ctype[c] & RAD16) {
-                       if (c >= 'A' && c <= 'F')
-                               return (c - 'A' + 10);
-                       if (c >= 'a' && c <= 'f')
-                               return (c - 'a' + 10);
-                       return (c - '0');
-               }
-       } else
-       if (r == 10) {
-               if (ctype[c] & RAD10)
-                       return (c - '0');
-       } else
-       if (r == 8) {
-               if (ctype[c] & RAD8)
-                       return (c - '0');
-       } else
-       if (r == 2) {
-               if (ctype[c] & RAD2)
-                       return (c - '0');
-       }
-       return (-1);
+        if (r == 16) {
+                if (ctype[c] & RAD16) {
+                        if (c >= 'A' && c <= 'F')
+                                return (c - 'A' + 10);
+                        if (c >= 'a' && c <= 'f')
+                                return (c - 'a' + 10);
+                        return (c - '0');
+                }
+        } else
+        if (r == 10) {
+                if (ctype[c] & RAD10)
+                        return (c - '0');
+        } else
+        if (r == 8) {
+                if (ctype[c] & RAD8)
+                        return (c - '0');
+        } else
+        if (r == 2) {
+                if (ctype[c] & RAD2)
+                        return (c - '0');
+        }
+        return (-1);
 }
 
-/*)Function    int     oprio(c)
+/*)Function     int     oprio(c)
  *
- *             int     c               operator character
+ *              int     c               operator character
  *
- *     The function oprio() returns a relative priority
- *     for all valid unary and binary operators.
+ *      The function oprio() returns a relative priority
+ *      for all valid unary and binary operators.
  *
- *     local variables:
- *             none
+ *      local variables:
+ *              none
  *
- *     global variables:
- *             none
+ *      global variables:
+ *              none
  *
- *     functions called:
- *             none
+ *      functions called:
+ *              none
  *
- *     side effects:
- *             none
+ *      side effects:
+ *              none
  */
+
 int
 oprio(c)
 register int c;
 {
-       if (c == '*' || c == '/' || c == '%')
-               return (10);
-       if (c == '+' || c == '-')
-               return (7);
-       if (c == '<' || c == '>')
-               return (5);
-       if (c == '^')
-               return (4);
-       if (c == '&')
-               return (3);
-       if (c == '|')
-               return (1);
-       return (0);
+        if (c == '*' || c == '/' || c == '%')
+                return (10);
+        if (c == '+' || c == '-')
+                return (7);
+        if (c == '<' || c == '>')
+                return (5);
+        if (c == '^')
+                return (4);
+        if (c == '&')
+                return (3);
+        if (c == '|')
+                return (1);
+        return (0);
 }