expr.c revision 1.2 1 1.2 glass /* File : expr.c
2 1.2 glass Authors: Mike Lutz & Bob Harper
3 1.2 glass Editors: Ozan Yigit & Richard A. O'Keefe
4 1.2 glass Updated: %G%
5 1.2 glass Purpose: arithmetic expression evaluator.
6 1.1 cgd
7 1.2 glass expr() performs a standard recursive descent parse to evaluate any
8 1.2 glass expression permitted byf the following grammar:
9 1.2 glass
10 1.2 glass expr : query EOS
11 1.2 glass query : lor
12 1.2 glass | lor "?" query ":" query
13 1.2 glass lor : land { "||" land } or OR, for Pascal
14 1.2 glass land : bor { "&&" bor } or AND, for Pascal
15 1.2 glass bor : bxor { "|" bxor }
16 1.2 glass bxor : band { "^" band }
17 1.2 glass band : eql { "&" eql }
18 1.2 glass eql : relat { eqrel relat }
19 1.2 glass relat : shift { rel shift }
20 1.2 glass shift : primary { shop primary }
21 1.2 glass primary : term { addop term }
22 1.2 glass term : unary { mulop unary }
23 1.2 glass unary : factor
24 1.2 glass | unop unary
25 1.2 glass factor : constant
26 1.2 glass | "(" query ")"
27 1.2 glass constant: num
28 1.2 glass | "'" CHAR "'" or '"' CHAR '"'
29 1.2 glass num : DIGIT full ANSI C syntax
30 1.2 glass | DIGIT num
31 1.2 glass shop : "<<"
32 1.2 glass | ">>"
33 1.2 glass eqlrel : "="
34 1.2 glass | "=="
35 1.2 glass | "!="
36 1.2 glass rel : "<" or <>, Pascal not-equal
37 1.2 glass | ">"
38 1.2 glass | "<=" or =<, for Prolog users.
39 1.2 glass | ">="
40 1.2 glass
41 1.2 glass This expression evaluator was lifted from a public-domain
42 1.2 glass C Pre-Processor included with the DECUS C Compiler distribution.
43 1.2 glass It has been hacked somewhat to be suitable for m4.
44 1.2 glass
45 1.2 glass 26-Mar-1993 Changed to work in any of EBCDIC, ASCII, DEC MNCS,
46 1.2 glass or ISO 8859/n.
47 1.2 glass
48 1.2 glass 26-Mar-1993 Changed to use "long int" rather than int, so that
49 1.2 glass we get the same 32-bit arithmetic on a PC as on a Sun.
50 1.2 glass It isn't fully portable, of course, but then on a 64-
51 1.2 glass bit machine we _want_ 64-bit arithmetic...
52 1.2 glass Shifting rewritten (using LONG_BIT) to give signed
53 1.2 glass shifts even when (long) >> (long) is unsigned.
54 1.2 glass
55 1.2 glass 26-Mar-1993 I finally got sick of the fact that &&, ||, and ?:
56 1.2 glass don't do conditional evaluation. What is the good
57 1.2 glass of having eval(0&&(1/0)) crash and dump core? Now
58 1.2 glass every function has a doit? argument.
59 1.2 glass
60 1.2 glass 26-Mar-1993 charcon() didn't actually accept 'abcd', which it
61 1.2 glass should have. Fixed it.
62 1.2 glass
63 1.2 glass 20-Apr-1993 eval(1/0) and eval(1%0) dumped core and crashed.
64 1.2 glass This is also true of the System V r 3.2 m4, but
65 1.2 glass it isn't good enough for ours! Changed it so that
66 1.2 glass x % 0 => x as per Concrete Mathematics
67 1.2 glass x / 0 => error and return 0 from expr().
68 1.2 glass */
69 1.2 glass
70 1.2 glass #define FALSE 0
71 1.2 glass #define TRUE 1
72 1.2 glass
73 1.2 glass #include <stdio.h>
74 1.1 cgd #include <setjmp.h>
75 1.2 glass static jmp_buf expjump; /* Error exit point for expr() */
76 1.2 glass
77 1.2 glass static unsigned char *nxtchr; /* Parser scan pointer */
78 1.2 glass
79 1.2 glass #define deblank0 while ((unsigned)(*nxtchr-1) < ' ') nxtchr++
80 1.2 glass #define deblank1 while ((unsigned)(*++nxtchr - 1) < ' ')
81 1.2 glass #define deblank2 nxtchr++; deblank1
82 1.2 glass
83 1.2 glass #include "ourlims.h"
84 1.2 glass static char digval[1+UCHAR_MAX];
85 1.2 glass
86 1.2 glass /* This file should work in any C implementation that doesn't have too
87 1.2 glass many characters to fit in one table. We use a table to convert
88 1.2 glass (unsigned) characters to numeric codes:
89 1.2 glass 0 to 9 for '0' to '9'
90 1.2 glass 10 to 35 for 'a' to 'z'
91 1.2 glass 10 to 35 for 'A' to 'Z'
92 1.2 glass 36 for '_'
93 1.2 glass Instead of asking whether tolower(c) == 'a' we ask whether
94 1.2 glass digval[c] == DIGIT_A, and so on. This essentially duplicates the
95 1.2 glass chtype[] table in main.c; we should use just one table.
96 1.2 glass */
97 1.2 glass #define DIGIT_A 10
98 1.2 glass #define DIGIT_B 11
99 1.2 glass #define DIGIT_C 12
100 1.2 glass #define DIGIT_D 13
101 1.2 glass #define DIGIT_E 14
102 1.2 glass #define DIGIT_F 15
103 1.2 glass #define DIGIT_G 16
104 1.2 glass #define DIGIT_H 17
105 1.2 glass #define DIGIT_I 18
106 1.2 glass #define DIGIT_J 19
107 1.2 glass #define DIGIT_K 20
108 1.2 glass #define DIGIT_L 21
109 1.2 glass #define DIGIT_M 22
110 1.2 glass #define DIGIT_N 23
111 1.2 glass #define DIGIT_O 24
112 1.2 glass #define DIGIT_P 25
113 1.2 glass #define DIGIT_Q 26
114 1.2 glass #define DIGIT_R 27
115 1.2 glass #define DIGIT_S 28
116 1.2 glass #define DIGIT_T 29
117 1.2 glass #define DIGIT_U 30
118 1.2 glass #define DIGIT_V 31
119 1.2 glass #define DIGIT_W 32
120 1.2 glass #define DIGIT_X 33
121 1.2 glass #define DIGIT_Y 34
122 1.2 glass #define DIGIT_Z 35
123 1.2 glass
124 1.2 glass
125 1.2 glass #ifdef __STDC__
126 1.2 glass static long int query(int);
127 1.2 glass #else
128 1.2 glass static long int query();
129 1.2 glass #endif
130 1.2 glass
131 1.2 glass
132 1.2 glass /* experr(msg)
133 1.2 glass prints an error message, resets environment to expr(), and
134 1.2 glass forces expr() to return FALSE.
135 1.2 glass */
136 1.2 glass void experr(msg)
137 1.2 glass char *msg;
138 1.2 glass {
139 1.2 glass (void) fprintf(stderr, "m4: %s\n", msg);
140 1.2 glass longjmp(expjump, -1); /* Force expr() to return FALSE */
141 1.2 glass }
142 1.2 glass
143 1.2 glass
144 1.2 glass /* <numcon> ::= '0x' <hex> | '0X' <hex> | '0' <oct> | <dec>
145 1.2 glass For ANSI C, an integer may be followed by u, l, ul, or lu,
146 1.2 glass in any mix of cases. We accept and ignore those letters;
147 1.2 glass all the numbers are treated as long.
148 1.2 glass */
149 1.2 glass static long int numcon(doit)
150 1.2 glass int doit;
151 1.2 glass {
152 1.2 glass register long int v; /* current value */
153 1.2 glass register int b; /* base (radix) */
154 1.2 glass register int c; /* character or digit value */
155 1.2 glass
156 1.2 glass if (!doit) {
157 1.2 glass do nxtchr++; while (digval[*nxtchr] <= 36);
158 1.2 glass deblank0;
159 1.2 glass return 0;
160 1.2 glass }
161 1.2 glass
162 1.2 glass v = digval[*nxtchr++]; /* We already know it's a digit */
163 1.2 glass if (v != 0) {
164 1.2 glass b = 10; /* decimal number */
165 1.2 glass } else
166 1.2 glass if (digval[*nxtchr] == DIGIT_X) {
167 1.2 glass nxtchr++;
168 1.2 glass b = 16; /* hexadecimal number */
169 1.2 glass } else {
170 1.2 glass b = 8; /* octal number */
171 1.2 glass }
172 1.2 glass do {
173 1.2 glass while (digval[c = *nxtchr++] < b) v = v*b + digval[c];
174 1.2 glass } while (c == '_');
175 1.2 glass while (digval[c] == DIGIT_L || digval[c] == DIGIT_U) c = *nxtchr++;
176 1.2 glass nxtchr--; /* unread c */
177 1.2 glass if ((unsigned)(c-1) < ' ') { deblank1; }
178 1.2 glass return v;
179 1.2 glass }
180 1.2 glass
181 1.2 glass
182 1.2 glass /* <charcon> ::= <qt> { <char> } <qt>
183 1.2 glass Note: multibyte constants are accepted.
184 1.2 glass Note: BEL (\a) and ESC (\e) have the same values in EBCDIC and ASCII.
185 1.2 glass */
186 1.2 glass static long int charcon(doit)
187 1.2 glass int doit;
188 1.2 glass {
189 1.2 glass register int i;
190 1.2 glass long int value;
191 1.2 glass register int c;
192 1.2 glass int q;
193 1.2 glass int v[sizeof value];
194 1.2 glass
195 1.2 glass q = *nxtchr++; /* the quote character */
196 1.2 glass for (i = 0; ; i++) {
197 1.2 glass c = *nxtchr++;
198 1.2 glass if (c == q) { /* end of literal, or doubled quote */
199 1.2 glass if (*nxtchr != c) break;
200 1.2 glass nxtchr++; /* doubled quote stands for one quote */
201 1.2 glass }
202 1.2 glass if (i == sizeof value) experr("Unterminated character constant");
203 1.2 glass if (c == '\\') {
204 1.2 glass switch (c = *nxtchr++) {
205 1.2 glass case '0': case '1': case '2': case '3':
206 1.2 glass case '4': case '5': case '6': case '7':
207 1.2 glass c -= '0';
208 1.2 glass if ((unsigned)(*nxtchr - '0') < 8)
209 1.2 glass c = (c << 3) | (*nxtchr++ - '0');
210 1.2 glass if ((unsigned)(*nxtchr - '0') < 8)
211 1.2 glass c = (c << 3) | (*nxtchr++ - '0');
212 1.2 glass break;
213 1.2 glass case 'n': case 'N': c = '\n'; break;
214 1.2 glass case 'r': case 'R': c = '\r'; break;
215 1.2 glass case 't': case 'T': c = '\t'; break;
216 1.2 glass case 'b': case 'B': c = '\b'; break;
217 1.2 glass case 'f': case 'F': c = '\f'; break;
218 1.2 glass case 'a': case 'A': c = 007; break;
219 1.2 glass case 'e': case 'E': c = 033; break;
220 1.2 glass #if ' ' == 64
221 1.2 glass case 'd': case 'D': c = 045; break; /*EBCDIC DEL */
222 1.2 glass #else
223 1.2 glass case 'd': case 'D': c = 127; break; /* ASCII DEL */
224 1.2 glass #endif
225 1.2 glass default : break;
226 1.2 glass }
227 1.2 glass }
228 1.2 glass v[i] = c;
229 1.2 glass }
230 1.2 glass deblank0;
231 1.2 glass if (!doit) return 0;
232 1.2 glass for (value = 0; --i >= 0; ) value = (value << CHAR_BIT) | v[i];
233 1.2 glass return value;
234 1.2 glass }
235 1.2 glass
236 1.2 glass
237 1.2 glass /* <unary> ::= <unop> <unary> | <factor>
238 1.2 glass <unop> ::= '!' || '~' | '-'
239 1.2 glass <factor> ::= '(' <query> ')' | <'> <char> <'> | <"> <char> <"> | <num>
240 1.2 glass */
241 1.2 glass static long int unary(doit)
242 1.2 glass int doit;
243 1.2 glass {
244 1.2 glass long int v;
245 1.2 glass
246 1.2 glass switch (nxtchr[0]) {
247 1.2 glass case 'n': case 'N':
248 1.2 glass if (digval[nxtchr[1]] != DIGIT_O
249 1.2 glass || digval[nxtchr[2]] != DIGIT_T)
250 1.2 glass experr("Bad 'not'");
251 1.2 glass nxtchr += 2;
252 1.2 glass case '!': deblank1; return !unary(doit);
253 1.2 glass case '~': deblank1; return ~unary(doit);
254 1.2 glass case '-': deblank1; return -unary(doit);
255 1.2 glass case '+': deblank1; return unary(doit);
256 1.2 glass case '(': deblank1; v = query(doit);
257 1.2 glass if (nxtchr[0] != ')') experr("Bad factor");
258 1.2 glass deblank1; return v;
259 1.2 glass case '\'':
260 1.2 glass case '\"': return charcon(doit);
261 1.2 glass case '0': case '1': case '2':
262 1.2 glass case '3': case '4': case '5':
263 1.2 glass case '6': case '7': case '8':
264 1.2 glass case '9': return numcon(doit);
265 1.2 glass default : experr("Bad constant");
266 1.2 glass }
267 1.2 glass return 0; /*NOTREACHED*/
268 1.2 glass }
269 1.2 glass
270 1.2 glass
271 1.2 glass /* <term> ::= <unary> { <mulop> <unary> }
272 1.2 glass <mulop> ::= '*' | '/' || '%'
273 1.2 glass */
274 1.2 glass static long int term(doit)
275 1.2 glass int doit;
276 1.2 glass {
277 1.2 glass register long int vl, vr;
278 1.2 glass
279 1.2 glass vl = unary(doit);
280 1.2 glass for (;;)
281 1.2 glass switch (nxtchr[0]) {
282 1.2 glass case '*':
283 1.2 glass deblank1;
284 1.2 glass vr = unary(doit);
285 1.2 glass if (doit) vl *= vr;
286 1.2 glass break;
287 1.2 glass case 'd': case 'D':
288 1.2 glass if (digval[nxtchr[1]] != DIGIT_I
289 1.2 glass || digval[nxtchr[2]] != DIGIT_V)
290 1.2 glass experr("Bad 'div'");
291 1.2 glass nxtchr += 2;
292 1.2 glass /*FALLTHROUGH*/
293 1.2 glass case '/':
294 1.2 glass deblank1;
295 1.2 glass vr = unary(doit);
296 1.2 glass if (doit) {
297 1.2 glass if (vr == 0) experr("Division by 0");
298 1.2 glass vl /= vr;
299 1.2 glass }
300 1.2 glass break;
301 1.2 glass case 'm': case 'M':
302 1.2 glass if (digval[nxtchr[1]] != DIGIT_O
303 1.2 glass || digval[nxtchr[2]] != DIGIT_D)
304 1.2 glass experr("Bad 'mod'");
305 1.2 glass nxtchr += 2;
306 1.2 glass /*FALLTHROUGH*/
307 1.2 glass case '%':
308 1.2 glass deblank1;
309 1.2 glass vr = unary(doit);
310 1.2 glass if (doit) {
311 1.2 glass if (vr != 0) vl %= vr;
312 1.2 glass }
313 1.2 glass break;
314 1.2 glass default:
315 1.2 glass return vl;
316 1.2 glass }
317 1.2 glass /*NOTREACHED*/
318 1.2 glass }
319 1.2 glass
320 1.2 glass /* <primary> ::= <term> { <addop> <term> }
321 1.2 glass <addop> ::= '+' | '-'
322 1.2 glass */
323 1.2 glass static long int primary(doit)
324 1.2 glass int doit;
325 1.2 glass {
326 1.2 glass register long int vl;
327 1.2 glass
328 1.2 glass vl = term(doit);
329 1.2 glass for (;;)
330 1.2 glass if (nxtchr[0] == '+') {
331 1.2 glass deblank1;
332 1.2 glass if (doit) vl += term(doit); else (void)term(doit);
333 1.2 glass } else
334 1.2 glass if (nxtchr[0] == '-') {
335 1.2 glass deblank1;
336 1.2 glass if (doit) vl -= term(doit); else (void)term(doit);
337 1.2 glass } else
338 1.2 glass return vl;
339 1.2 glass /*NOTREACHED*/
340 1.2 glass }
341 1.2 glass
342 1.2 glass
343 1.2 glass /* <shift> ::= <primary> { <shop> <primary> }
344 1.2 glass <shop> ::= '<<' | '>>'
345 1.2 glass */
346 1.2 glass static long int shift(doit)
347 1.2 glass int doit;
348 1.2 glass {
349 1.2 glass register long int vl, vr;
350 1.2 glass
351 1.2 glass vl = primary(doit);
352 1.2 glass for (;;) {
353 1.2 glass if (nxtchr[0] == '<' && nxtchr[1] == '<') {
354 1.2 glass deblank2;
355 1.2 glass vr = primary(doit);
356 1.2 glass } else
357 1.2 glass if (nxtchr[0] == '>' && nxtchr[1] == '>') {
358 1.2 glass deblank2;
359 1.2 glass vr = -primary(doit);
360 1.2 glass } else {
361 1.2 glass return vl;
362 1.2 glass }
363 1.2 glass /* The following code implements shifts portably */
364 1.2 glass /* Shifts are signed shifts, and the shift count */
365 1.2 glass /* acts like repeated one-bit shifts, not modulo anything */
366 1.2 glass if (doit) {
367 1.2 glass if (vr >= LONG_BIT) {
368 1.2 glass vl = 0;
369 1.2 glass } else
370 1.2 glass if (vr <= -LONG_BIT) {
371 1.2 glass vl = -(vl < 0);
372 1.2 glass } else
373 1.2 glass if (vr > 0) {
374 1.2 glass vl <<= vr;
375 1.2 glass } else
376 1.2 glass if (vr < 0) {
377 1.2 glass vl = (vl >> -vr) | (-(vl < 0) << (LONG_BIT + vr));
378 1.2 glass }
379 1.2 glass }
380 1.2 glass }
381 1.2 glass /*NOTREACHED*/
382 1.2 glass }
383 1.2 glass
384 1.2 glass
385 1.2 glass /* <relat> ::= <shift> { <rel> <shift> }
386 1.2 glass <rel> ::= '<=' | '>=' | '=<' | '=>' | '<' | '>'
387 1.2 glass Here I rely on the fact that '<<' and '>>' are swallowed by <shift>
388 1.2 glass */
389 1.2 glass static long int relat(doit)
390 1.2 glass int doit;
391 1.2 glass {
392 1.2 glass register long int vl;
393 1.2 glass
394 1.2 glass vl = shift(doit);
395 1.2 glass for (;;)
396 1.2 glass switch (nxtchr[0]) {
397 1.2 glass case '=':
398 1.2 glass switch (nxtchr[1]) {
399 1.2 glass case '<': /* =<, take as <= */
400 1.2 glass deblank2;
401 1.2 glass vl = vl <= shift(doit);
402 1.2 glass break;
403 1.2 glass case '>': /* =>, take as >= */
404 1.2 glass deblank2;
405 1.2 glass vl = vl >= shift(doit);
406 1.2 glass break;
407 1.2 glass default: /* == or =; OOPS */
408 1.2 glass return vl;
409 1.2 glass }
410 1.2 glass break;
411 1.2 glass case '<':
412 1.2 glass if (nxtchr[1] == '=') { /* <= */
413 1.2 glass deblank2;
414 1.2 glass vl = vl <= shift(doit);
415 1.2 glass } else
416 1.2 glass if (nxtchr[1] == '>') { /* <> (Pascal) */
417 1.2 glass deblank2;
418 1.2 glass vl = vl != shift(doit);
419 1.2 glass } else { /* < */
420 1.2 glass deblank1;
421 1.2 glass vl = vl < shift(doit);
422 1.2 glass }
423 1.2 glass break;
424 1.2 glass case '>':
425 1.2 glass if (nxtchr[1] == '=') { /* >= */
426 1.2 glass deblank2;
427 1.2 glass vl = vl >= shift(doit);
428 1.2 glass } else { /* > */
429 1.2 glass deblank1;
430 1.2 glass vl = vl > shift(doit);
431 1.2 glass }
432 1.2 glass break;
433 1.2 glass default:
434 1.2 glass return vl;
435 1.2 glass }
436 1.2 glass /*NOTREACHED*/
437 1.2 glass }
438 1.2 glass
439 1.2 glass
440 1.2 glass /* <eql> ::= <relat> { <eqrel> <relat> }
441 1.2 glass <eqlrel> ::= '!=' | '==' | '='
442 1.2 glass */
443 1.2 glass static long int eql(doit)
444 1.2 glass int doit;
445 1.2 glass {
446 1.2 glass register long int vl;
447 1.2 glass
448 1.2 glass vl = relat(doit);
449 1.2 glass for (;;)
450 1.2 glass if (nxtchr[0] == '!' && nxtchr[1] == '=') {
451 1.2 glass deblank2;
452 1.2 glass vl = vl != relat(doit);
453 1.2 glass } else
454 1.2 glass if (nxtchr[0] == '=' && nxtchr[1] == '=') {
455 1.2 glass deblank2;
456 1.2 glass vl = vl == relat(doit);
457 1.2 glass } else
458 1.2 glass if (nxtchr[0] == '=') {
459 1.2 glass deblank1;
460 1.2 glass vl = vl == relat(doit);
461 1.2 glass } else
462 1.2 glass return vl;
463 1.2 glass /*NOTREACHED*/
464 1.2 glass }
465 1.2 glass
466 1.2 glass
467 1.2 glass /* <band> ::= <eql> { '&' <eql> }
468 1.2 glass */
469 1.2 glass static long int band(doit)
470 1.2 glass int doit;
471 1.2 glass {
472 1.2 glass register long int vl;
473 1.2 glass
474 1.2 glass vl = eql(doit);
475 1.2 glass while (nxtchr[0] == '&' && nxtchr[1] != '&') {
476 1.2 glass deblank1;
477 1.2 glass if (doit) vl &= eql(doit); else (void)eql(doit);
478 1.2 glass }
479 1.2 glass return vl;
480 1.2 glass }
481 1.2 glass
482 1.2 glass
483 1.2 glass /* <bxor> ::= <band> { '^' <band> }
484 1.2 glass */
485 1.2 glass static long int bxor(doit)
486 1.2 glass int doit;
487 1.2 glass {
488 1.2 glass register long int vl;
489 1.2 glass
490 1.2 glass vl = band(doit);
491 1.2 glass while (nxtchr[0] == '^') {
492 1.2 glass deblank1;
493 1.2 glass if (doit) vl ^= band(doit); else (void)band(doit);
494 1.2 glass }
495 1.2 glass return vl;
496 1.2 glass }
497 1.2 glass
498 1.2 glass
499 1.2 glass /* <bor> ::= <bxor> { '|' <bxor> }
500 1.2 glass */
501 1.2 glass static long int bor(doit)
502 1.2 glass int doit;
503 1.2 glass {
504 1.2 glass register long int vl;
505 1.2 glass
506 1.2 glass vl = bxor(doit);
507 1.2 glass while (nxtchr[0] == '|' && nxtchr[1] != '|') {
508 1.2 glass deblank1;
509 1.2 glass if (doit) vl |= bxor(doit); else (void)bxor(doit);
510 1.2 glass }
511 1.2 glass return vl;
512 1.2 glass }
513 1.2 glass
514 1.2 glass
515 1.2 glass /* <land> ::= <bor> { '&&' <bor> }
516 1.2 glass */
517 1.2 glass static long int land(doit)
518 1.2 glass int doit;
519 1.2 glass {
520 1.2 glass register long int vl;
521 1.2 glass
522 1.2 glass vl = bor(doit);
523 1.2 glass for (;;) {
524 1.2 glass if (nxtchr[0] == '&') {
525 1.2 glass if (nxtchr[1] != '&') break;
526 1.2 glass deblank2;
527 1.2 glass } else
528 1.2 glass if (digval[nxtchr[0]] == DIGIT_A) {
529 1.2 glass if (digval[nxtchr[1]] != DIGIT_N) break;
530 1.2 glass if (digval[nxtchr[2]] != DIGIT_D) break;
531 1.2 glass nxtchr += 2; deblank1;
532 1.2 glass } else {
533 1.2 glass /* neither && nor and */
534 1.2 glass break;
535 1.2 glass }
536 1.2 glass vl = bor(doit && vl) != 0;
537 1.2 glass }
538 1.2 glass return vl;
539 1.2 glass }
540 1.2 glass
541 1.2 glass
542 1.2 glass /* <lor> ::= <land> { '||' <land> }
543 1.2 glass */
544 1.2 glass static long int lor(doit)
545 1.2 glass int doit;
546 1.2 glass {
547 1.2 glass register long int vl;
548 1.2 glass
549 1.2 glass vl = land(doit);
550 1.2 glass for (;;) {
551 1.2 glass if (nxtchr[0] == '|') {
552 1.2 glass if (nxtchr[1] != '|') break;
553 1.2 glass } else
554 1.2 glass if (digval[nxtchr[0]] == DIGIT_O) {
555 1.2 glass if (digval[nxtchr[1]] != DIGIT_R) break;
556 1.2 glass } else {
557 1.2 glass /* neither || nor or */
558 1.2 glass break;
559 1.2 glass }
560 1.2 glass deblank2;
561 1.2 glass vl = land(doit && !vl) != 0;
562 1.2 glass }
563 1.2 glass return vl;
564 1.2 glass }
565 1.2 glass
566 1.2 glass
567 1.2 glass /* <query> ::= <lor> [ '?' <query> ':' <query> ]
568 1.2 glass */
569 1.2 glass static long int query(doit)
570 1.2 glass int doit;
571 1.2 glass {
572 1.2 glass register long int bool, true_val, false_val;
573 1.2 glass
574 1.2 glass bool = lor(doit);
575 1.2 glass if (*nxtchr != '?') return bool;
576 1.2 glass deblank1;
577 1.2 glass true_val = query(doit && bool);
578 1.2 glass if (*nxtchr != ':') experr("Bad query");
579 1.2 glass deblank1;
580 1.2 glass false_val = query(doit && !bool);
581 1.2 glass return bool ? true_val : false_val;
582 1.2 glass }
583 1.2 glass
584 1.2 glass
585 1.2 glass static void initialise_digval()
586 1.2 glass {
587 1.2 glass register unsigned char *s;
588 1.2 glass register int c;
589 1.2 glass
590 1.2 glass for (c = 0; c <= UCHAR_MAX; c++) digval[c] = 99;
591 1.2 glass for (c = 0, s = (unsigned char *)"0123456789";
592 1.2 glass /*while*/ *s;
593 1.2 glass /*doing*/ digval[*s++] = c++) /* skip */;
594 1.2 glass for (c = 10, s = (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
595 1.2 glass /*while*/ *s;
596 1.2 glass /*doing*/ digval[*s++] = c++) /* skip */;
597 1.2 glass for (c = 10, s = (unsigned char *)"abcdefghijklmnopqrstuvwxyz";
598 1.2 glass /*while*/ *s;
599 1.2 glass /*doing*/ digval[*s++] = c++) /* skip */;
600 1.2 glass digval['_'] = 36;
601 1.2 glass }
602 1.2 glass
603 1.2 glass
604 1.2 glass long int expr(expbuf)
605 1.2 glass char *expbuf;
606 1.2 glass {
607 1.2 glass register int rval;
608 1.2 glass
609 1.2 glass if (digval['1'] == 0) initialise_digval();
610 1.2 glass nxtchr = (unsigned char *)expbuf;
611 1.2 glass deblank0;
612 1.2 glass if (setjmp(expjump) != 0) return FALSE;
613 1.2 glass rval = query(TRUE);
614 1.2 glass if (*nxtchr) experr("Ill-formed expression");
615 1.2 glass return rval;
616 1.2 glass }
617 1.1 cgd
618