4 * (C) Copyright 1989-1995
16 #if !defined(_MSC_VER)
24 * The module asexpr.c contains the routines to evaluate
25 * arithmetic/numerical expressions. The functions in
26 * asexpr.c perform a recursive evaluation of the arithmetic
27 * expression read from the assembler-source text line.
28 * The expression may include binary/unary operators, brackets,
29 * symbols, labels, and constants in hexadecimal, decimal, octal
30 * and binary. Arithmetic operations are prioritized and
31 * evaluated by normal arithmetic conventions.
33 * asexpr.c contains the following functions:
42 * asexpr.c contains no local/static variables
45 /*)Function VOID expr(esp, n)
47 * expr * esp pointer to an expr structure
48 * int n a firewall priority; all top
49 * level calls (from the user)
50 * should be made with n set to 0.
52 * The function expr() evaluates an expression and
53 * stores its value and relocation information into
54 * the expr structure supplied by the user.
57 * int c current assembler-source
59 * int p current operator priority
60 * area * ap pointer to an area structure
61 * exp re internal expr structure
64 * char ctype[] array of character types, one per
68 * VOID abscheck() asexpr.c
69 * VOID clrexpr() asexpr.c
70 * VOID expr() asexpr.c
72 * int oprio() asexpr.c
73 * VOID qerr() assubr.c
74 * VOID rerr() assubr.c
75 * VOID term() asexpr.c
76 * VOID unget() aslex.c
80 * An expression is evaluated modifying the user supplied
81 * expr structure, a sym structure maybe created for an
82 * undefined symbol, and the parse of the expression may
83 * terminate if a 'q' error occurs.
88 register struct expr *esp;
96 while (ctype[c = getnb()] & BINOP) {
98 * Handle binary operators + - * / & | % ^ << >>
100 if ((p = oprio(c)) <= n)
102 if ((c == '>' || c == '<') && c != get())
106 esp->e_rlcf |= re.e_rlcf;
109 * esp + re, at least one must be absolute
111 if (esp->e_base.e_ap == NULL) {
113 * esp is absolute (constant),
116 esp->e_base.e_ap = re.e_base.e_ap;
118 if (re.e_base.e_ap) {
120 * re should be absolute (constant)
124 if (esp->e_flag && re.e_flag)
128 esp->e_addr += re.e_addr;
134 if ((ap = re.e_base.e_ap) != NULL) {
135 if (esp->e_base.e_ap == ap) {
136 esp->e_base.e_ap = NULL;
143 esp->e_addr -= re.e_addr;
146 * Both operands (esp and re) must be constants
153 esp->e_addr *= re.e_addr;
157 esp->e_addr /= re.e_addr;
161 esp->e_addr &= re.e_addr;
165 esp->e_addr |= re.e_addr;
169 esp->e_addr %= re.e_addr;
173 esp->e_addr ^= re.e_addr;
177 esp->e_addr <<= re.e_addr;
181 esp->e_addr >>= re.e_addr;
193 /*)Function Addr_T absexpr()
195 * The function absexpr() evaluates an expression, verifies it
196 * is absolute (i.e. not position dependent or relocatable), and
200 * expr e expr structure
206 * VOID abscheck() asexpr.c
207 * VOID clrexpr() asexpr.c
208 * VOID expr() asexpr.c
211 * If the expression is not absolute then
212 * a 'r' error is reported.
226 /*)Function VOID term(esp)
228 * expr * esp pointer to an expr structure
230 * The function term() evaluates a single constant
231 * or symbol value prefaced by any unary operator
232 * ( +, -, ~, ', ", >, or < ). This routine is also
233 * responsible for setting the relocation type to symbol
234 * based (e.flag != 0) on global references.
237 * int c current character
238 * char id[] symbol name
239 * char * jp pointer to assembler-source text
240 * int n constant evaluation running sum
241 * int r current evaluation radix
242 * sym * sp pointer to a sym structure
243 * tsym * tp pointer to a tsym structure
244 * int v current digit evaluation
247 * char ctype[] array of character types, one per
249 * sym * symp pointer to a symbol structure
252 * VOID abscheck() asexpr.c
253 * int digit() asexpr.c
254 * VOID err() assubr.c
255 * VOID expr() asexpr.c
256 * int is_abs() asexpr.c
258 * VOID getid() aslex.c
259 * int getmap() aslex.c
260 * int getnb() aslex.c
261 * sym * lookup() assym.c
262 * VOID qerr() assubr.c
263 * VOID unget() aslex.c
266 * An arithmetic term is evaluated, a symbol structure
267 * may be created, term evaluation may be terminated
273 register struct expr *esp;
284 * Discard the unary '+' at this point and
285 * also any reference to numerical arguments
286 * associated with the '#' prefix.
288 while (c == '+' || c == '#') { c = getnb(); }
290 * Evaluate all binary operators
291 * by recursively calling expr().
295 if (getnb() != RTTERM)
302 esp->e_addr = -esp->e_addr;
308 esp->e_addr = ~esp->e_addr;
312 esp->e_mode = S_USER;
313 esp->e_addr = getmap(-1)&0377;
317 esp->e_mode = S_USER;
319 esp->e_addr = (getmap(-1)&0377)<<8;
320 esp->e_addr |= (getmap(-1)&0377);
322 esp->e_addr = (getmap(-1)&0377);
323 esp->e_addr |= (getmap(-1)&0377)<<8;
327 if (c == '>' || c == '<') {
331 * evaluate msb/lsb directly
339 * let linker perform msb/lsb, lsb is default
341 esp->e_rlcf |= R_BYT2;
343 esp->e_rlcf |= R_MSB;
348 * Evaluate digit sequences as local symbols
349 * if followed by a '$' or as constants.
351 if (ctype[c] & DIGIT) {
352 esp->e_mode = S_USER;
354 while (ctype[*jp] & RAD10) {
359 while ((v = digit(c, 10)) >= 0) {
365 if (n == tp->t_num) {
366 esp->e_base.e_ap = tp->t_area;
367 esp->e_addr = tp->t_addr;
408 while ((v = digit(c, r)) >= 0) {
417 * Evaluate '$' sequences as a temporary radix
418 * if followed by a '%', '&', '#', or '$'.
422 if (c == '%' || c == '&' || c == '#' || c == '$') {
441 while ((v = digit(c, r)) >= 0) {
446 esp->e_mode = S_USER;
454 * Evaluate symbols and labels
456 if (ctype[c] & LETTER) {
457 esp->e_mode = S_USER;
460 if (sp->s_type == S_NEW) {
461 if (sp->s_flag&S_GBL) {
463 esp->e_base.e_sp = sp;
468 esp->e_mode = sp->s_type;
469 esp->e_addr = sp->s_addr;
470 esp->e_base.e_ap = sp->s_area;
480 /*)Function int digit(c, r)
482 * int c digit character
483 * int r current radix
485 * The function digit() returns the value of c
486 * in the current radix r. If the c value is not
487 * a number of the current radix then a -1 is returned.
493 * char ctype[] array of character types, one per
508 if (ctype[c] & RAD16) {
509 if (c >= 'A' && c <= 'F')
510 return (c - 'A' + 10);
511 if (c >= 'a' && c <= 'f')
512 return (c - 'a' + 10);
517 if (ctype[c] & RAD10)
531 /*)Function VOID abscheck(esp)
533 * expr * esp pointer to an expr structure
535 * The function abscheck() tests the evaluation of an
536 * expression to verify it is absolute. If the evaluation
537 * is relocatable then an 'r' error is noted and the expression
540 * Note: The area type (i.e. ABS) is not checked because
541 * the linker can be told to explicitly relocate an
551 * VOID rerr() assubr.c
554 * The expression may be changed to absolute and the
560 register struct expr *esp;
562 if (esp->e_flag || esp->e_base.e_ap) {
564 esp->e_base.e_ap = NULL;
569 /*)Function int is_abs(esp)
571 * expr * esp pointer to an expr structure
573 * The function is_abs() tests the evaluation of an
574 * expression to verify it is absolute. If the evaluation
575 * is absolute then 1 is returned, else 0 is returned.
577 * Note: The area type (i.e. ABS) is not checked because
578 * the linker can be told to explicitly relocate an
596 register struct expr *esp;
598 if (esp->e_flag || esp->e_base.e_ap) {
604 /*)Function int oprio(c)
606 * int c operator character
608 * The function oprio() returns a relative priority
609 * for all valid unary and binary operators.
628 if (c == '*' || c == '/' || c == '%')
630 if (c == '+' || c == '-')
632 if (c == '<' || c == '>')
643 /*)Function VOID clrexpr(esp)
645 * expr * esp pointer to expression structure
647 * The function clrexpr() clears the expression structure.
659 * expression structure cleared.
664 register struct expr *esp;
669 esp->e_base.e_ap = NULL;