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