expr.c (c44252b6e8da46f58fd1882b9e7305a0f9114c16) expr.c (e3d8671772982f3135d8d6997f3cd698cca4df19)
1/* $OpenBSD: expr.c,v 1.12 2002/02/16 21:27:48 millert Exp $ */
2/* $NetBSD: expr.c,v 1.7 1995/09/28 05:37:31 tls Exp $ */
3
1/*
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Ozan Yigit at York University.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 21 unchanged lines hidden (view full) ---

30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
4/*
5 * Copyright (c) 1989, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Ozan Yigit at York University.
10 *
11 * Redistribution and use in source and binary forms, with or without

--- 21 unchanged lines hidden (view full) ---

33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 */
39
40#ifndef lint
41#if 0
38static char sccsid[] = "@(#)expr.c 8.2 (Berkeley) 4/29/95";
42static char sccsid[] = "@(#)expr.c 8.2 (Berkeley) 4/29/95";
43#else
44static char rcsid[] = "$OpenBSD: expr.c,v 1.12 2002/02/16 21:27:48 millert Exp $";
45#endif
39#endif /* not lint */
40
41#include <sys/cdefs.h>
46#endif /* not lint */
47
48#include <sys/cdefs.h>
49#include <ctype.h>
50#include <err.h>
51#include <stddef.h>
42#include <stdio.h>
52#include <stdio.h>
53#include "mdef.h"
54#include "extern.h"
43
44/*
45 * expression evaluator: performs a standard recursive
46 * descent parse to evaluate any expression permissible
47 * within the following grammar:
48 *
49 * expr : query EOS
50 * query : lor

--- 29 unchanged lines hidden (view full) ---

80 * This expression evaluator is lifted from a public-domain
81 * C Pre-Processor included with the DECUS C Compiler distribution.
82 * It is hacked somewhat to be suitable for m4.
83 *
84 * Originally by: Mike Lutz
85 * Bob Harper
86 */
87
55
56/*
57 * expression evaluator: performs a standard recursive
58 * descent parse to evaluate any expression permissible
59 * within the following grammar:
60 *
61 * expr : query EOS
62 * query : lor

--- 29 unchanged lines hidden (view full) ---

92 * This expression evaluator is lifted from a public-domain
93 * C Pre-Processor included with the DECUS C Compiler distribution.
94 * It is hacked somewhat to be suitable for m4.
95 *
96 * Originally by: Mike Lutz
97 * Bob Harper
98 */
99
88#define TRUE 1
89#define FALSE 0
90#define EOS (char) 0
91#define EQL 0
92#define NEQ 1
93#define LSS 2
94#define LEQ 3
95#define GTR 4
96#define GEQ 5
97#define OCTAL 8
98#define DECIMAL 10
100#define EQL 0
101#define NEQ 1
102#define LSS 2
103#define LEQ 3
104#define GTR 4
105#define GEQ 5
106#define OCTAL 8
107#define DECIMAL 10
108#define HEX 16
99
109
100static char *nxtch; /* Parser scan pointer */
110static const char *nxtch; /* Parser scan pointer */
111static const char *where;
101
112
102static int query __P((void));
103static int lor __P((void));
104static int land __P((void));
105static int not __P((void));
106static int eqrel __P((void));
107static int shift __P((void));
108static int primary __P((void));
109static int term __P((void));
110static int exp __P((void));
111static int unary __P((void));
112static int factor __P((void));
113static int constant __P((void));
114static int num __P((void));
115static int geteqrel __P((void));
116static int skipws __P((void));
117static void experr __P((char *));
113static int query(void);
114static int lor(void);
115static int land(void);
116static int not(void);
117static int eqrel(void);
118static int shift(void);
119static int primary(void);
120static int term(void);
121static int exp(void);
122static int unary(void);
123static int factor(void);
124static int constant(void);
125static int num(void);
126static int geteqrel(void);
127static int skipws(void);
128static void experr(const char *);
118
119/*
120 * For longjmp
121 */
122#include <setjmp.h>
123static jmp_buf expjump;
124
125/*
126 * macros:
127 * ungetch - Put back the last character examined.
128 * getch - return the next character from expr string.
129 */
130#define ungetch() nxtch--
131#define getch() *nxtch++
132
133int
134expr(expbuf)
129
130/*
131 * For longjmp
132 */
133#include <setjmp.h>
134static jmp_buf expjump;
135
136/*
137 * macros:
138 * ungetch - Put back the last character examined.
139 * getch - return the next character from expr string.
140 */
141#define ungetch() nxtch--
142#define getch() *nxtch++
143
144int
145expr(expbuf)
135char *expbuf;
146 const char *expbuf;
136{
147{
137 register int rval;
148 int rval;
138
139 nxtch = expbuf;
149
150 nxtch = expbuf;
151 where = expbuf;
140 if (setjmp(expjump) != 0)
141 return FALSE;
142
143 rval = query();
144 if (skipws() == EOS)
145 return rval;
146
147 printf("m4: ill-formed expression.\n");
148 return FALSE;
149}
150
151/*
152 * query : lor | lor '?' query ':' query
153 */
154static int
155query()
156{
152 if (setjmp(expjump) != 0)
153 return FALSE;
154
155 rval = query();
156 if (skipws() == EOS)
157 return rval;
158
159 printf("m4: ill-formed expression.\n");
160 return FALSE;
161}
162
163/*
164 * query : lor | lor '?' query ':' query
165 */
166static int
167query()
168{
157 register int bool, true_val, false_val;
169 int bool, true_val, false_val;
158
159 bool = lor();
160 if (skipws() != '?') {
161 ungetch();
162 return bool;
163 }
164
165 true_val = query();

--- 5 unchanged lines hidden (view full) ---

171}
172
173/*
174 * lor : land { '||' land }
175 */
176static int
177lor()
178{
170
171 bool = lor();
172 if (skipws() != '?') {
173 ungetch();
174 return bool;
175 }
176
177 true_val = query();

--- 5 unchanged lines hidden (view full) ---

183}
184
185/*
186 * lor : land { '||' land }
187 */
188static int
189lor()
190{
179 register int c, vl, vr;
191 int c, vl, vr;
180
181 vl = land();
182 while ((c = skipws()) == '|') {
183 if (getch() != '|')
184 ungetch();
185 vr = land();
186 vl = vl || vr;
187 }
188
189 ungetch();
190 return vl;
191}
192
193/*
194 * land : not { '&&' not }
195 */
196static int
197land()
198{
192
193 vl = land();
194 while ((c = skipws()) == '|') {
195 if (getch() != '|')
196 ungetch();
197 vr = land();
198 vl = vl || vr;
199 }
200
201 ungetch();
202 return vl;
203}
204
205/*
206 * land : not { '&&' not }
207 */
208static int
209land()
210{
199 register int c, vl, vr;
211 int c, vl, vr;
200
201 vl = not();
202 while ((c = skipws()) == '&') {
203 if (getch() != '&')
204 ungetch();
205 vr = not();
206 vl = vl && vr;
207 }
208
209 ungetch();
210 return vl;
211}
212
213/*
214 * not : eqrel | '!' not
215 */
216static int
217not()
218{
212
213 vl = not();
214 while ((c = skipws()) == '&') {
215 if (getch() != '&')
216 ungetch();
217 vr = not();
218 vl = vl && vr;
219 }
220
221 ungetch();
222 return vl;
223}
224
225/*
226 * not : eqrel | '!' not
227 */
228static int
229not()
230{
219 register int val, c;
231 int val, c;
220
221 if ((c = skipws()) == '!' && getch() != '=') {
222 ungetch();
223 val = not();
224 return !val;
225 }
226
227 if (c == '!')
228 ungetch();
229 ungetch();
230 return eqrel();
231}
232
233/*
234 * eqrel : shift { eqrelop shift }
235 */
236static int
237eqrel()
238{
232
233 if ((c = skipws()) == '!' && getch() != '=') {
234 ungetch();
235 val = not();
236 return !val;
237 }
238
239 if (c == '!')
240 ungetch();
241 ungetch();
242 return eqrel();
243}
244
245/*
246 * eqrel : shift { eqrelop shift }
247 */
248static int
249eqrel()
250{
239 register int vl, vr, eqrel;
251 int vl, vr, eqrel;
240
241 vl = shift();
242 while ((eqrel = geteqrel()) != -1) {
243 vr = shift();
244
245 switch (eqrel) {
246
247 case EQL:

--- 21 unchanged lines hidden (view full) ---

269}
270
271/*
272 * shift : primary { shop primary }
273 */
274static int
275shift()
276{
252
253 vl = shift();
254 while ((eqrel = geteqrel()) != -1) {
255 vr = shift();
256
257 switch (eqrel) {
258
259 case EQL:

--- 21 unchanged lines hidden (view full) ---

281}
282
283/*
284 * shift : primary { shop primary }
285 */
286static int
287shift()
288{
277 register int vl, vr, c;
289 int vl, vr, c;
278
279 vl = primary();
280 while (((c = skipws()) == '<' || c == '>') && getch() == c) {
281 vr = primary();
282
283 if (c == '<')
284 vl <<= vr;
285 else

--- 7 unchanged lines hidden (view full) ---

293}
294
295/*
296 * primary : term { addop term }
297 */
298static int
299primary()
300{
290
291 vl = primary();
292 while (((c = skipws()) == '<' || c == '>') && getch() == c) {
293 vr = primary();
294
295 if (c == '<')
296 vl <<= vr;
297 else

--- 7 unchanged lines hidden (view full) ---

305}
306
307/*
308 * primary : term { addop term }
309 */
310static int
311primary()
312{
301 register int c, vl, vr;
313 int c, vl, vr;
302
303 vl = term();
304 while ((c = skipws()) == '+' || c == '-') {
305 vr = term();
306
307 if (c == '+')
308 vl += vr;
309 else

--- 5 unchanged lines hidden (view full) ---

315}
316
317/*
318 * <term> := <exp> { <mulop> <exp> }
319 */
320static int
321term()
322{
314
315 vl = term();
316 while ((c = skipws()) == '+' || c == '-') {
317 vr = term();
318
319 if (c == '+')
320 vl += vr;
321 else

--- 5 unchanged lines hidden (view full) ---

327}
328
329/*
330 * <term> := <exp> { <mulop> <exp> }
331 */
332static int
333term()
334{
323 register int c, vl, vr;
335 int c, vl, vr;
324
325 vl = exp();
326 while ((c = skipws()) == '*' || c == '/' || c == '%') {
327 vr = exp();
328
329 switch (c) {
330 case '*':
331 vl *= vr;
332 break;
333 case '/':
336
337 vl = exp();
338 while ((c = skipws()) == '*' || c == '/' || c == '%') {
339 vr = exp();
340
341 switch (c) {
342 case '*':
343 vl *= vr;
344 break;
345 case '/':
334 vl /= vr;
346 if (vr == 0)
347 errx(1, "division by zero in eval.");
348 else
349 vl /= vr;
335 break;
336 case '%':
350 break;
351 case '%':
337 vl %= vr;
352 if (vr == 0)
353 errx(1, "modulo zero in eval.");
354 else
355 vl %= vr;
338 break;
339 }
340 }
341 ungetch();
342 return vl;
343}
344
345/*
346 * <term> := <unary> { <expop> <unary> }
347 */
348static int
349exp()
350{
356 break;
357 }
358 }
359 ungetch();
360 return vl;
361}
362
363/*
364 * <term> := <unary> { <expop> <unary> }
365 */
366static int
367exp()
368{
351 register c, vl, vr, n;
369 int c, vl, vr, n;
352
353 vl = unary();
354 switch (c = skipws()) {
355
356 case '*':
357 if (getch() != '*') {
358 ungetch();
359 break;

--- 12 unchanged lines hidden (view full) ---

372}
373
374/*
375 * unary : factor | unop unary
376 */
377static int
378unary()
379{
370
371 vl = unary();
372 switch (c = skipws()) {
373
374 case '*':
375 if (getch() != '*') {
376 ungetch();
377 break;

--- 12 unchanged lines hidden (view full) ---

390}
391
392/*
393 * unary : factor | unop unary
394 */
395static int
396unary()
397{
380 register int val, c;
398 int val, c;
381
382 if ((c = skipws()) == '+' || c == '-' || c == '~') {
383 val = unary();
384
385 switch (c) {
386 case '+':
387 return val;
388 case '-':

--- 8 unchanged lines hidden (view full) ---

397}
398
399/*
400 * factor : constant | '(' query ')'
401 */
402static int
403factor()
404{
399
400 if ((c = skipws()) == '+' || c == '-' || c == '~') {
401 val = unary();
402
403 switch (c) {
404 case '+':
405 return val;
406 case '-':

--- 8 unchanged lines hidden (view full) ---

415}
416
417/*
418 * factor : constant | '(' query ')'
419 */
420static int
421factor()
422{
405 register int val;
423 int val;
406
407 if (skipws() == '(') {
408 val = query();
409 if (skipws() != ')')
410 experr("bad factor");
411 return val;
412 }
413
414 ungetch();
415 return constant();
416}
417
418/*
419 * constant: num | 'char'
420 * Note: constant() handles multi-byte constants
421 */
422static int
423constant()
424{
424
425 if (skipws() == '(') {
426 val = query();
427 if (skipws() != ')')
428 experr("bad factor");
429 return val;
430 }
431
432 ungetch();
433 return constant();
434}
435
436/*
437 * constant: num | 'char'
438 * Note: constant() handles multi-byte constants
439 */
440static int
441constant()
442{
425 register int i;
426 register int value;
427 register char c;
443 int i;
444 int value;
445 int c;
428 int v[sizeof(int)];
429
430 if (skipws() != '\'') {
431 ungetch();
432 return num();
433 }
434 for (i = 0; i < sizeof(int); i++) {
435 if ((c = getch()) == '\'') {

--- 42 unchanged lines hidden (view full) ---

478}
479
480/*
481 * num : digit | num digit
482 */
483static int
484num()
485{
446 int v[sizeof(int)];
447
448 if (skipws() != '\'') {
449 ungetch();
450 return num();
451 }
452 for (i = 0; i < sizeof(int); i++) {
453 if ((c = getch()) == '\'') {

--- 42 unchanged lines hidden (view full) ---

496}
497
498/*
499 * num : digit | num digit
500 */
501static int
502num()
503{
486 register int rval, c, base;
504 int rval, c, base;
487 int ndig;
488
505 int ndig;
506
489 base = ((c = skipws()) == '0') ? OCTAL : DECIMAL;
490 rval = 0;
491 ndig = 0;
507 rval = 0;
508 ndig = 0;
492 while (c >= '0' && c <= (base == OCTAL ? '7' : '9')) {
493 rval *= base;
494 rval += (c - '0');
509 c = skipws();
510 if (c == '0') {
511 c = skipws();
512 if (c == 'x' || c == 'X') {
513 base = HEX;
514 c = skipws();
515 } else {
516 base = OCTAL;
517 ndig++;
518 }
519 } else
520 base = DECIMAL;
521 for(;;) {
522 switch(c) {
523 case '8': case '9':
524 if (base == OCTAL)
525 goto bad_digit;
526 /*FALLTHRU*/
527 case '0': case '1': case '2': case '3':
528 case '4': case '5': case '6': case '7':
529 rval *= base;
530 rval += c - '0';
531 break;
532 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
533 c = tolower(c);
534 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
535 if (base == HEX) {
536 rval *= base;
537 rval += c - 'a' + 10;
538 break;
539 }
540 /*FALLTHRU*/
541 default:
542 goto bad_digit;
543 }
495 c = getch();
496 ndig++;
497 }
544 c = getch();
545 ndig++;
546 }
547bad_digit:
498 ungetch();
499
500 if (ndig == 0)
501 experr("bad constant");
502
503 return rval;
548 ungetch();
549
550 if (ndig == 0)
551 experr("bad constant");
552
553 return rval;
504
505}
506
507/*
508 * eqrel : '=' | '==' | '!=' | '<' | '>' | '<=' | '>='
509 */
510static int
511geteqrel()
512{
554}
555
556/*
557 * eqrel : '=' | '==' | '!=' | '<' | '>' | '<=' | '>='
558 */
559static int
560geteqrel()
561{
513 register int c1, c2;
562 int c1, c2;
514
515 c1 = skipws();
516 c2 = getch();
517
518 switch (c1) {
519
520 case '=':
521 if (c2 != '=')

--- 27 unchanged lines hidden (view full) ---

549}
550
551/*
552 * Skip over any white space and return terminating char.
553 */
554static int
555skipws()
556{
563
564 c1 = skipws();
565 c2 = getch();
566
567 switch (c1) {
568
569 case '=':
570 if (c2 != '=')

--- 27 unchanged lines hidden (view full) ---

598}
599
600/*
601 * Skip over any white space and return terminating char.
602 */
603static int
604skipws()
605{
557 register char c;
606 int c;
558
559 while ((c = getch()) <= ' ' && c > EOS)
560 ;
561 return c;
562}
563
564/*
565 * resets environment to eval(), prints an error
566 * and forces eval to return FALSE.
567 */
568static void
569experr(msg)
607
608 while ((c = getch()) <= ' ' && c > EOS)
609 ;
610 return c;
611}
612
613/*
614 * resets environment to eval(), prints an error
615 * and forces eval to return FALSE.
616 */
617static void
618experr(msg)
570char *msg;
619 const char *msg;
571{
620{
572 printf("m4: %s in expr.\n", msg);
621 printf("m4: %s in expr %s.\n", msg, where);
573 longjmp(expjump, -1);
574}
622 longjmp(expjump, -1);
623}