Fix a warning
[fw/sdcc] / as / mcs51 / 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(-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         return(0);
307 }
308
309 /*)Function     int     digit(c, r)
310  *
311  *              int     c               digit character
312  *              int     r               current radix
313  *
314  *      The function digit() returns the value of c
315  *      in the current radix r.  If the c value is not
316  *      a number of the current radix then a -1 is returned.
317  *
318  *      local variables:
319  *              none
320  *
321  *      global variables:
322  *              char    ctype[]         array of character types, one per
323  *                                      ASCII character
324  *
325  *      functions called:
326  *              none
327  *
328  *      side effects:
329  *              none
330  */
331
332 int
333 digit(c, r)
334 register int c, r;
335 {
336         if (r == 16) {
337                 if (ctype[c] & RAD16) {
338                         if (c >= 'A' && c <= 'F')
339                                 return (c - 'A' + 10);
340                         if (c >= 'a' && c <= 'f')
341                                 return (c - 'a' + 10);
342                         return (c - '0');
343                 }
344         } else
345         if (r == 10) {
346                 if (ctype[c] & RAD10)
347                         return (c - '0');
348         } else
349         if (r == 8) {
350                 if (ctype[c] & RAD8)
351                         return (c - '0');
352         } else
353         if (r == 2) {
354                 if (ctype[c] & RAD2)
355                         return (c - '0');
356         }
357         return (-1);
358 }
359
360 /*)Function     int     oprio(c)
361  *
362  *              int     c               operator character
363  *
364  *      The function oprio() returns a relative priority
365  *      for all valid unary and binary operators.
366  *
367  *      local variables:
368  *              none
369  *
370  *      global variables:
371  *              none
372  *
373  *      functions called:
374  *              none
375  *
376  *      side effects:
377  *              none
378  */
379  
380 int
381 oprio(c)
382 register int c;
383 {
384         if (c == '*' || c == '/' || c == '%')
385                 return (10);
386         if (c == '+' || c == '-')
387                 return (7);
388         if (c == '<' || c == '>')
389                 return (5);
390         if (c == '^')
391                 return (4);
392         if (c == '&')
393                 return (3);
394         if (c == '|')
395                 return (1);
396         return (0);
397 }