e4bfe1d525236ba00fc390e425c5cecb4d0b3bad
[fw/sdcc] / as / link / z80 / lkeval.c
1 /* lkeval.c */
2
3 /*
4  * (C) Copyright 1989-1995
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 <string.h>
14 //#include <alloc.h>
15 #include "aslink.h"
16
17 /*)Module       lkeval.c
18  *
19  *      The module lkeval.c contains the routines to evaluate
20  *      arithmetic/numerical expressions.  The functions in
21  *      lkeval.c perform a recursive evaluation of the arithmetic
22  *      expression read from the input text line.
23  *      The expression may include binary/unary operators, brackets,
24  *      symbols, labels, and constants in hexadecimal, decimal, octal
25  *      and binary.  Arithmetic operations are prioritized and
26  *      evaluated by normal arithmetic conventions.
27  *
28  *      lkeval.c contains the following functions:
29  *              int     digit()
30  *              Addr_T  eval()
31  *              Addr_T  expr()
32  *              int     oprio()
33  *              Addr_T  term()
34  *
35  *      lkeval.c contains no local/static variables
36  */
37
38 /*)Function     Addr_T  eval()
39  *
40  *      The function eval() evaluates a character string to a
41  *      numerical value.
42  *
43  *      local variables:
44  *              int     c               character from input string
45  *              int     v               value of character in current radix
46  *              Addr_T  n               evaluation value
47  *
48  *      global variables:
49  *              int     radix           current number conversion radix
50  *
51  *      functions called:
52  *              int     digit()         lkeval.c
53  *              char    get()           lklex.c
54  *              char    getnb()         lklex.c
55  *              VOID    unget()         lklex.c
56  *
57  *      side effects:
58  *              Input test is scanned and evaluated to a
59  *              numerical value.
60  */
61
62 Addr_T
63 eval()
64 {
65         register int c, v;
66         register Addr_T n;
67
68         c = getnb();
69         n = 0;
70         while ((v = digit(c, radix)) >= 0) {
71                 n = n*radix + v;
72                 c = get();
73         }
74         unget(c);
75         return(n);
76 }
77
78 /*)Function     Addr_T  expr(n)
79  *
80  *              int     n               a firewall priority; all top
81  *                                      level calls (from the user)
82  *                                      should be made with n set to 0.
83  *
84  *      The function expr() evaluates an expression and
85  *      returns the value.
86  *
87  *      local variables:
88  *              int     c               current input text character
89  *              int     p               current operator priority
90  *              Addr_T  v               value returned by term()
91  *              Addr_T  ve              value returned by a
92  *                                      recursive call to expr()
93  *
94  *      global variables:
95  *              char    ctype[]         array of character types, one per
96  *                                      ASCII character
97  *              int     lkerr           error flag
98  *              FILE *  stderr          c_library
99  *
100  *      functions called:
101  *              VOID    expr()          lkeval.c
102  *              int     fprintf()       c_library
103  *              int     getnb()         lklex.c
104  *              int     oprio()         lkeval.c
105  *              VOID    term()          lkeval.c
106  *              VOID    unget()         lklex.c
107  *
108  *
109  *      side effects:
110  *              An expression is evaluated by scanning the input
111  *              text string.
112  */
113
114 Addr_T
115 expr (n)
116 {
117         register int c, p;
118         register Addr_T v, ve;
119
120         v = term();
121         while (ctype[c = getnb()] & BINOP) {
122                 if ((p = oprio(c)) <= n)
123                         break;
124                 if ((c == '>' || c == '<') && c != get()) {
125                         fprintf(stderr, "Invalid expression");
126                         lkerr++;
127                         return(v);
128                 }
129                 ve = expr(p);
130                 if (c == '+') {
131                         v += ve;
132                 } else
133                 if (c == '-') {
134                         v -= ve;
135                 } else {
136                         switch (c) {
137
138                         case '*':
139                                 v *= ve;
140                                 break;
141
142                         case '/':
143                                 v /= ve;
144                                 break;
145
146                         case '&':
147                                 v &= ve;
148                                 break;
149
150                         case '|':
151                                 v |= ve;
152                                 break;
153
154                         case '%':
155                                 v %= ve;
156                                 break;
157
158                         case '^':
159                                 v ^= ve;
160                                 break;
161
162                         case '<':
163                                 v <<= ve;
164                                 break;
165
166                         case '>':
167                                 v >>= ve;
168                                 break;
169                         }
170                 }
171         }
172         unget(c);
173         return(v);
174 }
175
176 /*)Function     Addr_T  term()
177  *
178  *      The function term() evaluates a single constant
179  *      or symbol value prefaced by any unary operator
180  *      ( +, -, ~, ', ", >, or < ).
181  *
182  *      local variables:
183  *              int     c               current character
184  *              char    id[]            symbol name
185  *              int     n               value of digit in current radix
186  *              int     r               current evaluation radix
187  *              sym *   sp              pointer to a sym structure
188  *              Addr_T  v               evaluation value
189  *
190  *      global variables:
191  *              char    ctype[]         array of character types, one per
192  *                                      ASCII character
193  *              int     lkerr           error flag
194  *
195  *      functions called:
196  *              int     digit()         lkeval.c
197  *              VOID    expr()          lkeval.c
198  *              int     fprintf()       c_library
199  *              int     get()           lklex.c
200  *              VOID    getid()         lklex.c
201  *              int     getmap()        lklex.c
202  *              int     getnb()         lklex.c
203  *              sym *   lkpsym()        lksym.c
204  *              Addr_T  symval()        lksym.c
205  *              VOID    unget()         lklex.c
206  *
207  *      side effects:
208  *              An arithmetic term is evaluated by scanning input text.
209  */
210
211 Addr_T
212 term()
213 {
214         register int c, r, n;
215         register Addr_T v;
216         struct sym *sp;
217         char id[NCPS];
218
219         c = getnb();
220         if (c == '#') { c = getnb(); }
221         if (c == '(') {
222                 v = expr(0);
223                 if (getnb() != ')') {
224                         fprintf(stderr, "Missing delimiter");
225                         lkerr++;
226                 }
227                 return(v);
228         }
229         if (c == '-') {
230                 return(0-expr(100));
231         }
232         if (c == '~') {
233                 return(~expr(100));
234         }
235         if (c == '\'') {
236                 return(getmap(-1)&0377);
237         }
238         if (c == '\"') {
239                 if (hilo) {
240                         v  = (getmap(-1)&0377)<<8;
241                         v |=  getmap(-1)&0377;
242                 } else {
243                         v  =  getmap(-1)&0377;
244                         v |= (getmap(-1)&0377)<<8;
245                 }
246                 return(v);
247         }
248         if (c == '>' || c == '<') {
249                 v = expr(100);
250                 if (c == '>')
251                         v >>= 8;
252                 return(v&0377);
253         }
254         if (ctype[c] & DIGIT) {
255                 r = 10;
256                 if (c == '0') {
257                         c = get();
258                         switch (c) {
259                         case 'b':
260                         case 'B':
261                                 r = 2;
262                                 c = get();
263                                 break;
264                         case '@':
265                         case 'o':
266                         case 'O':
267                         case 'q':
268                         case 'Q':
269                                 r = 8;
270                                 c = get();
271                                 break;
272                         case 'd':
273                         case 'D':
274                                 r = 10;
275                                 c = get();
276                                 break;
277                         case 'h':
278                         case 'H':
279                         case 'x':
280                         case 'X':
281                                 r = 16;
282                                 c = get();
283                                 break;
284                         default:
285                                 break;
286                         }
287                 }
288                 v = 0;
289                 while ((n = digit(c, r)) >= 0) {
290                         v = r*v + n;
291                         c = get();
292                 }
293                 unget(c);
294                 return(v);
295         }
296         if (ctype[c] & LETTER) {
297                 getid(id, c);
298                 if ((sp = lkpsym(id, 0)) == NULL) {
299                         fprintf(stderr, "Undefined symbol %8s\n", id);
300                         lkerr++;
301                         return(0);
302                 } else {
303                         return(symval(sp));
304                 }
305         }
306         /* Shouldn't get here. */
307         return 0;
308 }
309
310 /*)Function     int     digit(c, r)
311  *
312  *              int     c               digit character
313  *              int     r               current radix
314  *
315  *      The function digit() returns the value of c
316  *      in the current radix r.  If the c value is not
317  *      a number of the current radix then a -1 is returned.
318  *
319  *      local variables:
320  *              none
321  *
322  *      global variables:
323  *              char    ctype[]         array of character types, one per
324  *                                      ASCII character
325  *
326  *      functions called:
327  *              none
328  *
329  *      side effects:
330  *              none
331  */
332
333 int
334 digit(c, r)
335 register int c, r;
336 {
337         if (r == 16) {
338                 if (ctype[c] & RAD16) {
339                         if (c >= 'A' && c <= 'F')
340                                 return (c - 'A' + 10);
341                         if (c >= 'a' && c <= 'f')
342                                 return (c - 'a' + 10);
343                         return (c - '0');
344                 }
345         } else
346         if (r == 10) {
347                 if (ctype[c] & RAD10)
348                         return (c - '0');
349         } else
350         if (r == 8) {
351                 if (ctype[c] & RAD8)
352                         return (c - '0');
353         } else
354         if (r == 2) {
355                 if (ctype[c] & RAD2)
356                         return (c - '0');
357         }
358         return (-1);
359 }
360
361 /*)Function     int     oprio(c)
362  *
363  *              int     c               operator character
364  *
365  *      The function oprio() returns a relative priority
366  *      for all valid unary and binary operators.
367  *
368  *      local variables:
369  *              none
370  *
371  *      global variables:
372  *              none
373  *
374  *      functions called:
375  *              none
376  *
377  *      side effects:
378  *              none
379  */
380  
381 int
382 oprio(c)
383 register int c;
384 {
385         if (c == '*' || c == '/' || c == '%')
386                 return (10);
387         if (c == '+' || c == '-')
388                 return (7);
389         if (c == '<' || c == '>')
390                 return (5);
391         if (c == '^')
392                 return (4);
393         if (c == '&')
394                 return (3);
395         if (c == '|')
396                 return (1);
397         return (0);
398 }