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/>.
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:
45 * lkeval.c contains no local/static variables
48 /*)Function a_uint eval()
50 * The function eval() evaluates a character string to a
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
61 * int c character from input string
62 * int v value of character in current radix
63 * a_uint n evaluation value
66 * int radix current number conversion radix
69 * int digit() lkeval.c
72 * VOID unget() lklex.c
75 * Input test is scanned and evaluated to a
87 while ((v
= digit(c
, radix
)) >= 0) {
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
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
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()
119 * char ctype[] array of character types, one per
121 * int lkerr error flag
122 * FILE * stderr c_library
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
134 * An expression is evaluated by scanning the input
145 while (ctype
[c
= getnb()] & BINOP
) {
146 if ((p
= oprio(c
)) <= n
)
148 if ((c
== '>' || c
== '<') && c
!= get()) {
149 fprintf(stderr
, "Invalid expression");
156 * X-Bit Unsigned Arithmetic
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
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
238 * char ctype[] array of character types, one per
240 * int lkerr error flag
243 * int digit() lkeval.c
244 * VOID expr() lkeval.c
245 * int fprintf() c_library
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
255 * An arithmetic term is evaluated by scanning input text.
267 if (c
== '#') { c
= getnb(); }
270 if (getnb() != ')') {
271 fprintf(stderr
, "Missing delimiter");
277 return(~expr(100)+1);
285 if (c
!= '\'') { unget(c
); }
290 v
= (getmap(-1)&0377)<<8;
291 v
|= getmap(-1)&0377;
294 v
|= (getmap(-1)&0377)<<8;
297 if (c
!= '\"') { unget(c
); }
300 if (c
== '>' || c
== '<') {
306 if (ctype
[c
] & DIGIT
) {
341 while ((n
= digit(c
, r
)) >= 0) {
348 if (ctype
[c
] & LETTER
) {
350 if ((sp
= lkpsym(id
, 0)) == NULL
) {
351 fprintf(stderr
, "Undefined symbol %s\n", id
);
358 fprintf(stderr
, "Unknown operator %c\n", c
);
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.
376 * char ctype[] array of character types, one per
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);
399 if (ctype
[c
] & RAD10
)
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.
436 if (c
== '*' || c
== '/' || c
== '%')
438 if (c
== '+' || c
== '-')
440 if (c
== '<' || c
== '>')