struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / sdas / linksrc / lkeval.c
blobe4662c956d28c696625b70d4255cad68e9c6a2bd
1 /* lkeval.c */
3 /*
4 * Copyright (C) 1989-2009 Alan R. Baldwin
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * Alan R. Baldwin
21 * 721 Berkeley St.
22 * Kent, Ohio 44240
25 #include "aslink.h"
27 /*)Module lkeval.c
29 * The module lkeval.c contains the routines to evaluate
30 * arithmetic/numerical expressions. The functions in
31 * lkeval.c perform a recursive evaluation of the arithmetic
32 * expression read from the input text line.
33 * The expression may include binary/unary operators, brackets,
34 * symbols, labels, and constants in hexadecimal, decimal, octal
35 * and binary. Arithmetic operations are prioritized and
36 * evaluated by normal arithmetic conventions.
38 * lkeval.c contains the following functions:
39 * int digit()
40 * a_uint eval()
41 * a_uint expr()
42 * int oprio()
43 * a_uint term()
45 * lkeval.c contains no local/static variables
48 /*)Function a_uint eval()
50 * The function eval() evaluates a character string to a
51 * numerical value.
53 * Notes about the arithmetic:
54 * The coding emulates X-Bit unsigned
55 * arithmetic operations. This allows
56 * program compilation without regard to the
57 * intrinsic integer length of the host
58 * machine.
60 * local variables:
61 * int c character from input string
62 * int v value of character in current radix
63 * a_uint n evaluation value
65 * global variables:
66 * int radix current number conversion radix
68 * functions called:
69 * int digit() lkeval.c
70 * int get() lklex.c
71 * int getnb() lklex.c
72 * VOID unget() lklex.c
74 * side effects:
75 * Input test is scanned and evaluated to a
76 * numerical value.
79 a_uint
80 eval(void)
82 int c, v;
83 a_uint n;
85 c = getnb();
86 n = 0;
87 while ((v = digit(c, radix)) >= 0) {
88 n = n*radix + v;
89 c = get();
91 unget(c);
92 return (n & a_mask);
95 /*)Function a_uint expr(n)
97 * int n a firewall priority; all top
98 * level calls (from the user)
99 * should be made with n set to 0.
101 * The function expr() evaluates an expression and
102 * returns the value.
104 * Notes about the arithmetic:
105 * The coding emulates X-Bit unsigned
106 * arithmetic operations. This allows
107 * program compilation without regard to the
108 * intrinsic integer length of the host
109 * machine.
111 * local variables:
112 * int c current input text character
113 * int p current operator priority
114 * a_uint v value returned by term()
115 * a_uint ve value returned by a
116 * recursive call to expr()
118 * global variables:
119 * char ctype[] array of character types, one per
120 * ASCII character
121 * int lkerr error flag
122 * FILE * stderr c_library
124 * functions called:
125 * VOID expr() lkeval.c
126 * int fprintf() c_library
127 * int getnb() lklex.c
128 * int oprio() lkeval.c
129 * VOID term() lkeval.c
130 * VOID unget() lklex.c
133 * side effects:
134 * An expression is evaluated by scanning the input
135 * text string.
138 a_uint
139 expr (int n)
141 int c, p;
142 a_uint v, ve;
144 v = term();
145 while (ctype[c = getnb()] & BINOP) {
146 if ((p = oprio(c)) <= n)
147 break;
148 if ((c == '>' || c == '<') && c != get()) {
149 fprintf(stderr, "Invalid expression");
150 lkerr++;
151 return(v);
153 ve = expr(p);
156 * X-Bit Unsigned Arithmetic
158 v &= a_mask;
159 ve &= a_mask;
161 if (c == '+') {
162 v += ve;
163 } else
164 if (c == '-') {
165 v -= ve;
166 } else {
167 switch (c) {
169 case '*':
170 v *= ve;
171 break;
173 case '/':
174 if (ve == 0) {
175 v = 0;
176 } else {
177 v /= ve;
179 break;
181 case '&':
182 v &= ve;
183 break;
185 case '|':
186 v |= ve;
187 break;
189 case '%':
190 if (ve == 0) {
191 v = 0;
192 } else {
193 v %= ve;
195 break;
197 case '^':
198 v ^= ve;
199 break;
201 case '<':
202 v <<= ve;
203 break;
205 case '>':
206 v >>= ve;
207 break;
210 v = (v & a_mask);
212 unget(c);
213 return(v);
216 /*)Function a_uint term()
218 * The function term() evaluates a single constant
219 * or symbol value prefaced by any unary operator
220 * ( +, -, ~, ', ", >, or < ).
222 * Notes about the arithmetic:
223 * The coding emulates X-Bit unsigned
224 * arithmetic operations. This allows
225 * program compilation without regard to the
226 * intrinsic integer length of the host
227 * machine.
229 * local variables:
230 * int c current character
231 * char id[] symbol name
232 * int n value of digit in current radix
233 * int r current evaluation radix
234 * sym * sp pointer to a sym structure
235 * a_uint v evaluation value
237 * global variables:
238 * char ctype[] array of character types, one per
239 * ASCII character
240 * int lkerr error flag
242 * functions called:
243 * int digit() lkeval.c
244 * VOID expr() lkeval.c
245 * int fprintf() c_library
246 * int get() lklex.c
247 * VOID getid() lklex.c
248 * int getmap() lklex.c
249 * int getnb() lklex.c
250 * sym * lkpsym() lksym.c
251 * a_uint symval() lksym.c
252 * VOID unget() lklex.c
254 * side effects:
255 * An arithmetic term is evaluated by scanning input text.
258 a_uint
259 term(void)
261 int c, r, n;
262 a_uint v;
263 struct sym *sp;
264 char id[NCPS];
266 c = getnb();
267 if (c == '#') { c = getnb(); }
268 if (c == '(') {
269 v = expr(0);
270 if (getnb() != ')') {
271 fprintf(stderr, "Missing delimiter");
272 lkerr++;
274 return(v);
276 if (c == '-') {
277 return(~expr(100)+1);
279 if (c == '~') {
280 return(~expr(100));
282 if (c == '\'') {
283 v = getmap(-1)&0377;
284 c = get();
285 if (c != '\'') { unget(c); }
286 return(v);
288 if (c == '\"') {
289 if (hilo) {
290 v = (getmap(-1)&0377)<<8;
291 v |= getmap(-1)&0377;
292 } else {
293 v = getmap(-1)&0377;
294 v |= (getmap(-1)&0377)<<8;
296 c = get();
297 if (c != '\"') { unget(c); }
298 return(v & a_mask);
300 if (c == '>' || c == '<') {
301 v = expr(100);
302 if (c == '>')
303 v >>= 8;
304 return(v&0377);
306 if (ctype[c] & DIGIT) {
307 r = 10;
308 if (c == '0') {
309 c = get();
310 switch (c) {
311 case 'b':
312 case 'B':
313 r = 2;
314 c = get();
315 break;
316 case '@':
317 case 'o':
318 case 'O':
319 case 'q':
320 case 'Q':
321 r = 8;
322 c = get();
323 break;
324 case 'd':
325 case 'D':
326 r = 10;
327 c = get();
328 break;
329 case 'h':
330 case 'H':
331 case 'x':
332 case 'X':
333 r = 16;
334 c = get();
335 break;
336 default:
337 break;
340 v = 0;
341 while ((n = digit(c, r)) >= 0) {
342 v = r*v + n;
343 c = get();
345 unget(c);
346 return(v & a_mask);
348 if (ctype[c] & LETTER) {
349 getid(id, c);
350 if ((sp = lkpsym(id, 0)) == NULL) {
351 fprintf(stderr, "Undefined symbol %s\n", id);
352 lkerr++;
353 return(0);
354 } else {
355 return(symval(sp));
358 fprintf(stderr, "Unknown operator %c\n", c);
359 lkerr++;
360 return(0);
363 /*)Function int digit(c, r)
365 * int c digit character
366 * int r current radix
368 * The function digit() returns the value of c
369 * in the current radix r. If the c value is not
370 * a number of the current radix then a -1 is returned.
372 * local variables:
373 * none
375 * global variables:
376 * char ctype[] array of character types, one per
377 * ASCII character
379 * functions called:
380 * none
382 * side effects:
383 * none
387 digit(int c, int r)
389 if (r == 16) {
390 if (ctype[c] & RAD16) {
391 if (c >= 'A' && c <= 'F')
392 return (c - 'A' + 10);
393 if (c >= 'a' && c <= 'f')
394 return (c - 'a' + 10);
395 return (c - '0');
397 } else
398 if (r == 10) {
399 if (ctype[c] & RAD10)
400 return (c - '0');
401 } else
402 if (r == 8) {
403 if (ctype[c] & RAD8)
404 return (c - '0');
405 } else
406 if (r == 2) {
407 if (ctype[c] & RAD2)
408 return (c - '0');
410 return (-1);
413 /*)Function int oprio(c)
415 * int c operator character
417 * The function oprio() returns a relative priority
418 * for all valid unary and binary operators.
420 * local variables:
421 * none
423 * global variables:
424 * none
426 * functions called:
427 * none
429 * side effects:
430 * none
434 oprio(int c)
436 if (c == '*' || c == '/' || c == '%')
437 return (10);
438 if (c == '+' || c == '-')
439 return (7);
440 if (c == '<' || c == '>')
441 return (5);
442 if (c == '^')
443 return (4);
444 if (c == '&')
445 return (3);
446 if (c == '|')
447 return (1);
448 return (0);