fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / rsc / source / rscpp / cpp5.c
blob92587fe91dae5fefaa6d551eeae0612417add3d2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <stdio.h>
21 #include <ctype.h>
22 #include "cppdef.h"
23 #include "cpp.h"
26 * Evaluate an #if expression.
29 static char *opname[] = { /* For debug and error messages */
30 "end of expression", "val", "id",
31 "+", "-", "*", "/", "%",
32 "<<", ">>", "&", "|", "^",
33 "==", "!=", "<", "<=", ">=", ">",
34 "&&", "||", "?", ":", ",",
35 "unary +", "unary -", "~", "!", "(", ")", "(none)",
39 * opdope[] has the operator precedence:
40 * Bits
41 * 7 Unused (so the value is always positive)
42 * 6-2 Precedence (000x .. 017x)
43 * 1-0 Binary op. flags:
44 * 01 The binop flag should be set/cleared when this op is seen.
45 * 10 The new value of the binop flag.
46 * Note: Expected, New binop
47 * constant 0 1 Binop, end, or ) should follow constants
48 * End of line 1 0 End may not be preceeded by an operator
49 * binary 1 0 Binary op follows a value, value follows.
50 * unary 0 0 Unary op doesn't follow a value, value follows
51 * ( 0 0 Doesn't follow value, value or unop follows
52 * ) 1 1 Follows value. Op follows.
55 static char opdope[OP_MAX] = {
56 0001, /* End of expression */
57 0002, /* Digit */
58 0000, /* Letter (identifier) */
59 0141, 0141, 0151, 0151, 0151, /* ADD, SUB, MUL, DIV, MOD */
60 0131, 0131, 0101, 0071, 0071, /* ASL, ASR, AND, OR, XOR */
61 0111, 0111, 0121, 0121, 0121, 0121, /* EQ, NE, LT, LE, GE, GT */
62 0061, 0051, 0041, 0041, 0031, /* ANA, ORO, QUE, COL, CMA */
64 * Unary op's follow
66 0160, 0160, 0160, 0160, /* NEG, PLU, COM, NOT */
67 0170, 0013, 0023, /* LPA, RPA, END */
70 * OP_QUE and OP_RPA have alternate precedences:
72 #define OP_RPA_PREC 0013
73 #define OP_QUE_PREC 0034
76 * S_ANDOR and S_QUEST signal "short-circuit" boolean evaluation, so that
77 * #if FOO != 0 && 10 / FOO ...
78 * doesn't generate an error message. They are stored in optab.skip.
80 #define S_ANDOR 2
81 #define S_QUEST 1
83 typedef struct optab {
84 char op; /* Operator */
85 char prec; /* Its precedence */
86 char skip; /* Short-circuit: TRUE to skip */
87 } OPTAB;
88 static int evalue; /* Current value from evallex() */
90 #ifdef nomacargs
91 FILE_LOCAL int
92 isbinary(op)
93 register int op;
95 return (op >= FIRST_BINOP && op <= LAST_BINOP);
97 #else
98 #define isbinary(op) (op >= FIRST_BINOP && op <= LAST_BINOP)
99 #endif
102 * The following definitions are used to specify basic variable sizes.
105 #ifndef S_CHAR
106 #define S_CHAR (sizeof (char))
107 #endif
108 #ifndef S_SINT
109 #define S_SINT (sizeof (short int))
110 #endif
111 #ifndef S_INT
112 #define S_INT (sizeof (int))
113 #endif
114 #ifndef S_LINT
115 #define S_LINT (sizeof (long int))
116 #endif
117 #ifndef S_FLOAT
118 #define S_FLOAT (sizeof (float))
119 #endif
120 #ifndef S_DOUBLE
121 #define S_DOUBLE (sizeof (double))
122 #endif
123 #ifndef S_PCHAR
124 #define S_PCHAR (sizeof (char *))
125 #endif
126 #ifndef S_PSINT
127 #define S_PSINT (sizeof (short int *))
128 #endif
129 #ifndef S_PINT
130 #define S_PINT (sizeof (int *))
131 #endif
132 #ifndef S_PLINT
133 #define S_PLINT (sizeof (long int *))
134 #endif
135 #ifndef S_PFLOAT
136 #define S_PFLOAT (sizeof (float *))
137 #endif
138 #ifndef S_PDOUBLE
139 #define S_PDOUBLE (sizeof (double *))
140 #endif
141 #ifndef S_PFPTR
142 #define S_PFPTR (sizeof (int (*)()))
143 #endif
145 typedef struct types {
146 short type; /* This is the bit if */
147 char *name; /* this is the token word */
148 } TYPES;
150 static TYPES basic_types[] = {
151 { T_CHAR, "char", },
152 { T_INT, "int", },
153 { T_FLOAT, "float", },
154 { T_DOUBLE, "double", },
155 { T_SHORT, "short", },
156 { T_LONG, "long", },
157 { T_SIGNED, "signed", },
158 { T_UNSIGNED, "unsigned", },
159 { 0, NULL, }, /* Signal end */
163 * Test_table[] is used to test for illegal combinations.
165 static short test_table[] = {
166 T_FLOAT | T_DOUBLE | T_LONG | T_SHORT,
167 T_FLOAT | T_DOUBLE | T_CHAR | T_INT,
168 T_FLOAT | T_DOUBLE | T_SIGNED | T_UNSIGNED,
169 T_LONG | T_SHORT | T_CHAR,
170 0 /* end marker */
174 * The order of this table is important -- it is also referenced by
175 * the command line processor to allow run-time overriding of the
176 * built-in size values. The order must not be changed:
177 * char, short, int, long, float, double (func pointer)
179 SIZES size_table[] = {
180 { T_CHAR, S_CHAR, S_PCHAR }, /* char */
181 { T_SHORT, S_SINT, S_PSINT }, /* short int */
182 { T_INT, S_INT, S_PINT }, /* int */
183 { T_LONG, S_LINT, S_PLINT }, /* long */
184 { T_FLOAT, S_FLOAT, S_PFLOAT }, /* float */
185 { T_DOUBLE, S_DOUBLE, S_PDOUBLE }, /* double */
186 { T_FPTR, 0, S_PFPTR }, /* int (*()) */
187 { 0, 0, 0 }, /* End of table */
190 void InitCpp5()
198 eval()
200 * Evaluate an expression. Straight-forward operator precedence.
201 * This is called from control() on encountering an #if statement.
202 * It calls the following routines:
203 * evallex Lexical analyser -- returns the type and value of
204 * the next input token.
205 * evaleval Evaluate the current operator, given the values on
206 * the value stack. Returns a pointer to the (new)
207 * value stack.
208 * For compatiblity with older cpp's, this return returns 1 (TRUE)
209 * if a syntax error is detected.
212 register int op; /* Current operator */
213 register int *valp; /* -> value vector */
214 register OPTAB *opp; /* Operator stack */
215 int prec; /* Op precedence */
216 int binop; /* Set if binary op. needed */
217 int op1; /* Operand from stack */
218 int skip; /* For short-circuit testing */
219 int value[NEXP]; /* Value stack */
220 OPTAB opstack[NEXP]; /* Operand stack */
221 extern int *evaleval(); /* Does actual evaluation */
222 valp = value;
223 opp = opstack;
224 opp->op = OP_END; /* Mark bottom of stack */
225 opp->prec = opdope[OP_END]; /* And its precedence */
226 opp->skip = 0; /* Not skipping now */
227 binop = 0;
228 again: ;
229 #ifdef DEBUG_EVAL
230 fprintf( pCppOut, "In #if at again: skip = %d, binop = %d, line is: %s",
231 opp->skip, binop, infile->bptr);
232 #endif
233 if ((op = evallex(opp->skip)) == OP_SUB && binop == 0)
234 op = OP_NEG; /* Unary minus */
235 else if (op == OP_ADD && binop == 0)
236 op = OP_PLU; /* Unary plus */
237 else if (op == OP_FAIL)
238 return (1); /* Error in evallex */
239 #ifdef DEBUG_EVAL
240 fprintf( pCppOut, "op = %s, opdope = %03o, binop = %d, skip = %d\n",
241 opname[op], opdope[op], binop, opp->skip);
242 #endif
243 if (op == DIG) { /* Value? */
244 if (binop != 0) {
245 cerror("misplaced constant in #if", NULLST);
246 return (1);
248 else if (valp >= &value[NEXP-1]) {
249 cerror("#if value stack overflow", NULLST);
250 return (1);
252 else {
253 #ifdef DEBUG_EVAL
254 fprintf( pCppOut, "pushing %d onto value stack[%d]\n",
255 evalue, valp - value);
256 #endif
257 *valp++ = evalue;
258 binop = 1;
260 goto again;
262 else if (op > OP_END) {
263 cerror("Illegal #if line", NULLST);
264 return (1);
266 prec = opdope[op];
267 if (binop != (prec & 1)) {
268 cerror("Operator %s in incorrect context", opname[op]);
269 return (1);
271 binop = (prec & 2) >> 1;
272 for (;;) {
273 #ifdef DEBUG_EVAL
274 fprintf( pCppOut, "op %s, prec %d., stacked op %s, prec %d, skip %d\n",
275 opname[op], prec, opname[opp->op], opp->prec, opp->skip);
276 #endif
277 if (prec > opp->prec) {
278 if (op == OP_LPA)
279 prec = OP_RPA_PREC;
280 else if (op == OP_QUE)
281 prec = OP_QUE_PREC;
282 op1 = opp->skip; /* Save skip for test */
284 * Push operator onto op. stack.
286 opp++;
287 if (opp >= &opstack[NEXP]) {
288 cerror("expression stack overflow at op \"%s\"",
289 opname[op]);
290 return (1);
292 opp->op = (char)op;
293 opp->prec = (char)prec;
294 skip = (valp[-1] != 0); /* Short-circuit tester */
296 * Do the short-circuit stuff here. Short-circuiting
297 * stops automagically when operators are evaluated.
299 if ((op == OP_ANA && !skip)
300 || (op == OP_ORO && skip))
301 opp->skip = S_ANDOR; /* And/or skip starts */
302 else if (op == OP_QUE) /* Start of ?: operator */
303 opp->skip = (char)((op1 & S_ANDOR) | ((!skip) ? S_QUEST : 0));
304 else if (op == OP_COL) { /* : inverts S_QUEST */
305 opp->skip = (char)((op1 & S_ANDOR)
306 | (((op1 & S_QUEST) != 0) ? 0 : S_QUEST));
308 else { /* Other ops leave */
309 opp->skip = (char)op1; /* skipping unchanged. */
311 #ifdef DEBUG_EVAL
312 fprintf( pCppOut, "stacking %s, valp[-1] == %d at %s",
313 opname[op], valp[-1], infile->bptr);
314 dumpstack(opstack, opp, value, valp);
315 #endif
316 goto again;
319 * Pop operator from op. stack and evaluate it.
320 * End of stack and '(' are specials.
322 skip = opp->skip; /* Remember skip value */
323 switch ((op1 = opp->op)) { /* Look at stacked op */
324 case OP_END: /* Stack end marker */
325 if (op == OP_EOE)
326 return (valp[-1]); /* Finished ok. */
327 goto again; /* Read another op. */
329 case OP_LPA: /* ( on stack */
330 if (op != OP_RPA) { /* Matches ) on input */
331 cerror("unbalanced paren's, op is \"%s\"", opname[op]);
332 return (1);
334 opp--; /* Unstack it */
335 /* goto again; -- Fall through */
337 case OP_QUE:
338 goto again; /* Evaluate true expr. */
340 case OP_COL: /* : on stack. */
341 opp--; /* Unstack : */
342 if (opp->op != OP_QUE) { /* Matches ? on stack? */
343 cerror("Misplaced '?' or ':', previous operator is %s",
344 opname[(int)opp->op]);
345 return (1);
348 * Evaluate op1.
350 default: /* Others: */
351 opp--; /* Unstack the operator */
352 #ifdef DEBUG_EVAL
353 fprintf( pCppOut, "Stack before evaluation of %s\n", opname[op1]);
354 dumpstack(opstack, opp, value, valp);
355 #endif
356 valp = evaleval(valp, op1, skip);
357 #ifdef DEBUG_EVAL
358 fprintf( pCppOut, "Stack after evaluation\n");
359 dumpstack(opstack, opp, value, valp);
360 #endif
361 } /* op1 switch end */
362 } /* Stack unwind loop */
365 FILE_LOCAL int
366 evallex(int skip)
368 * Return next eval operator or value. Called from eval(). It
369 * calls a special-purpose routines for 'char' strings and
370 * numeric values:
371 * evalchar called to evaluate 'x'
372 * evalnum called to evaluate numbers.
375 register int c, c1, t;
377 again: do { /* Collect the token */
378 c = skipws();
379 if ((c = macroid(c)) == EOF_CHAR || c == '\n') {
380 unget();
381 return (OP_EOE); /* End of expression */
383 } while ((t = type[c]) == LET && catenate());
384 if (t == INV) { /* Total nonsense */
385 if (!skip) {
386 if (isascii(c) && isprint(c))
387 cierror("illegal character '%c' in #if", c);
388 else
389 cierror("illegal character (%d decimal) in #if", c);
391 return (OP_FAIL);
393 else if (t == QUO) { /* ' or " */
394 if (c == '\'') { /* Character constant */
395 evalue = evalchar(skip); /* Somewhat messy */
396 #ifdef DEBUG_EVAL
397 fprintf( pCppOut, "evalchar returns %d.\n", evalue);
398 #endif
399 return (DIG); /* Return a value */
401 cerror("Can't use a string in an #if", NULLST);
402 return (OP_FAIL);
404 else if (t == LET) { /* ID must be a macro */
405 if (streq(token, "defined")) { /* Or defined name */
406 c1 = c = skipws();
407 if (c == '(') /* Allow defined(name) */
408 c = skipws();
409 if (type[c] == LET) {
410 evalue = (lookid(c) != NULL);
411 if (c1 != '(' /* Need to balance */
412 || skipws() == ')') /* Did we balance? */
413 return (DIG); /* Parsed ok */
415 cerror("Bad #if ... defined() syntax", NULLST);
416 return (OP_FAIL);
418 else if (streq(token, "sizeof")) /* New sizeof hackery */
419 return (dosizeof()); /* Gets own routine */
421 * The Draft ANSI C Standard says that an undefined symbol
422 * in an #if has the value zero. We are a bit pickier,
423 * warning except where the programmer was careful to write
424 * #if defined(foo) ? foo : 0
426 #ifdef STRICT_UNDEF
427 if (!skip)
428 cwarn("undefined symbol \"%s\" in #if, 0 used", token);
429 #endif
430 evalue = 0;
431 return (DIG);
433 else if (t == DIG) { /* Numbers are harder */
434 evalue = evalnum(c);
435 #ifdef DEBUG_EVAL
436 fprintf( pCppOut, "evalnum returns %d.\n", evalue);
437 #endif
439 else if (strchr("!=<>&|\\", c) != NULL) {
441 * Process a possible multi-byte lexeme.
443 c1 = cget(); /* Peek at next char */
444 switch (c) {
445 case '!':
446 if (c1 == '=')
447 return (OP_NE);
448 break;
450 case '=':
451 if (c1 != '=') { /* Can't say a=b in #if */
452 unget();
453 cerror("= not allowed in #if", NULLST);
454 return (OP_FAIL);
456 return (OP_EQ);
458 case '>':
459 case '<':
460 if (c1 == c)
461 return ((c == '<') ? OP_ASL : OP_ASR);
462 else if (c1 == '=')
463 return ((c == '<') ? OP_LE : OP_GE);
464 break;
466 case '|':
467 case '&':
468 if (c1 == c)
469 return ((c == '|') ? OP_ORO : OP_ANA);
470 break;
472 case '\\':
473 if (c1 == '\n') /* Multi-line if */
474 goto again;
475 cerror("Unexpected \\ in #if", NULLST);
476 return (OP_FAIL);
478 unget();
480 return (t);
483 FILE_LOCAL int
484 dosizeof()
486 * Process the sizeof (basic type) operation in an #if string.
487 * Sets evalue to the size and returns
488 * DIG success
489 * OP_FAIL bad parse or something.
492 register int c;
493 register TYPES *tp;
494 register SIZES *sizp;
495 register short *testp;
496 short typecode;
498 if ((c = skipws()) != '(')
499 goto nogood;
501 * Scan off the tokens.
503 typecode = 0;
504 while (0 != (c = skipws())) {
505 if ((c = macroid(c)) == EOF_CHAR || c == '\n')
506 goto nogood; /* End of line is a bug */
507 else if (c == '(') { /* thing (*)() func ptr */
508 if (skipws() == '*'
509 && skipws() == ')') { /* We found (*) */
510 if (skipws() != '(') /* Let () be optional */
511 unget();
512 else if (skipws() != ')')
513 goto nogood;
514 typecode |= T_FPTR; /* Function pointer */
516 else { /* Junk is a bug */
517 goto nogood;
520 else if (type[c] != LET) /* Exit if not a type */
521 break;
522 else if (!catenate()) { /* Maybe combine tokens */
524 * Look for this unexpandable token in basic_types.
525 * The code accepts "int long" as well as "long int"
526 * which is a minor bug as bugs go (and one shared with
527 * a lot of C compilers).
529 for (tp = basic_types; tp->name != NULLST; tp++) {
530 if (streq(token, tp->name))
531 break;
533 if (tp->name == NULLST) {
534 cerror("#if sizeof, unknown type \"%s\"", token);
535 return (OP_FAIL);
537 typecode |= tp->type; /* Or in the type bit */
541 * We are at the end of the type scan. Chew off '*' if necessary.
543 if (c == '*') {
544 typecode |= T_PTR;
545 c = skipws();
547 if (c == ')') { /* Last syntax check */
548 for (testp = test_table; *testp != 0; testp++) {
549 if (!bittest(typecode & *testp)) {
550 cerror("#if ... sizeof: illegal type combination", NULLST);
551 return (OP_FAIL);
555 * We assume that all function pointers are the same size:
556 * sizeof (int (*)()) == sizeof (float (*)())
557 * We assume that signed and unsigned don't change the size:
558 * sizeof (signed int) == (sizeof unsigned int)
560 if ((typecode & T_FPTR) != 0) /* Function pointer */
561 typecode = T_FPTR | T_PTR;
562 else { /* Var or var * datum */
563 typecode &= ~(T_SIGNED | T_UNSIGNED);
564 if ((typecode & (T_SHORT | T_LONG)) != 0)
565 typecode &= ~T_INT;
567 if ((typecode & ~T_PTR) == 0) {
568 cerror("#if sizeof() error, no type specified", NULLST);
569 return (OP_FAIL);
572 * Exactly one bit (and possibly T_PTR) may be set.
574 for (sizp = size_table; sizp->bits != 0; sizp++) {
575 if ((typecode & ~T_PTR) == sizp->bits) {
576 evalue = ((typecode & T_PTR) != 0)
577 ? sizp->psize : sizp->size;
578 return (DIG);
580 } /* We shouldn't fail */
581 cierror("#if ... sizeof: bug, unknown type code 0x%x", typecode);
582 return (OP_FAIL);
585 nogood: unget();
586 cerror("#if ... sizeof() syntax error", NULLST);
587 return (OP_FAIL);
590 FILE_LOCAL int
591 bittest(int value)
593 * TRUE if value is zero or exactly one bit is set in value.
596 #if (4096 & ~(-4096)) == 0
597 return ((value & ~(-value)) == 0);
598 #else
600 * Do it the hard way (for non 2's complement machines)
602 return (value == 0 || value ^ (value - 1) == (value * 2 - 1));
603 #endif
606 FILE_LOCAL int
607 evalnum(int c)
609 * Expand number for #if lexical analysis. Note: evalnum recognizes
610 * the unsigned suffix, but only returns a signed int value.
613 register int value;
614 register int base;
615 register int c1;
617 if (c != '0')
618 base = 10;
619 else if ((c = cget()) == 'x' || c == 'X') {
620 base = 16;
621 c = cget();
623 else base = 8;
624 value = 0;
625 for (;;) {
626 c1 = c;
627 if (isascii(c) && isupper(c1))
628 c1 = tolower(c1);
629 #ifdef EBCDIC
630 if (c1 <= 'f')
631 #else
632 if (c1 >= 'a')
633 #endif
634 c1 -= ('a' - 10);
635 else c1 -= '0';
636 if (c1 < 0 || c1 >= base)
637 break;
638 value *= base;
639 value += c1;
640 c = cget();
642 if (c == 'u' || c == 'U') /* Unsigned nonsense */
643 cget();
644 unget();
645 return (value);
648 FILE_LOCAL int
649 evalchar(int skip)
651 * Get a character constant
654 register int c;
655 register int value;
656 register int count;
658 instring = TRUE;
659 if ((c = cget()) == '\\') {
660 switch ((c = cget())) {
661 case 'a': /* New in Standard */
662 #if ('a' == '\a' || '\a' == ALERT)
663 value = ALERT; /* Use predefined value */
664 #else
665 value = '\a'; /* Use compiler's value */
666 #endif
667 break;
669 case 'b':
670 value = '\b';
671 break;
673 case 'f':
674 value = '\f';
675 break;
677 case 'n':
678 value = '\n';
679 break;
681 case 'r':
682 value = '\r';
683 break;
685 case 't':
686 value = '\t';
687 break;
689 case 'v': /* New in Standard */
690 #if ('v' == '\v' || '\v' == VT)
691 value = VT; /* Use predefined value */
692 #else
693 value = '\v'; /* Use compiler's value */
694 #endif
695 break;
697 case 'x': /* '\xFF' */
698 count = 3;
699 value = 0;
700 while ((((c = get()) >= '0' && c <= '9')
701 || (c >= 'a' && c <= 'f')
702 || (c >= 'A' && c <= 'F'))
703 && (--count >= 0)) {
704 value *= 16;
705 #ifdef EBCDIC
706 value += (c <= '9') ? (c - '0') : ((c & 0xF) + 9);
707 #else
708 value += (c >= '0') ? (c - '0') : ((c & 0xF) + 9);
709 #endif
711 unget();
712 break;
714 default:
715 if (c >= '0' && c <= '7') {
716 count = 3;
717 value = 0;
718 while (c >= '0' && c <= '7' && --count >= 0) {
719 value *= 8;
720 value += (c - '0');
721 c = get();
723 unget();
725 else value = c;
726 break;
729 else if (c == '\'')
730 value = 0;
731 else value = c;
733 * We warn on multi-byte constants and try to hack
734 * (big|little)endian machines.
736 while ((c = get()) != '\'' && c != EOF_CHAR && c != '\n') {
737 if (!skip)
738 ciwarn("multi-byte constant '%c' isn't portable", c);
739 value <<= BITS_CHAR;
740 value += c;
742 instring = FALSE;
743 return (value);
746 FILE_LOCAL int *
747 evaleval(int* valp, int op, int skip)
749 * Apply the argument operator to the data on the value stack.
750 * One or two values are popped from the value stack and the result
751 * is pushed onto the value stack.
753 * OP_COL is a special case.
755 * evaleval() returns the new pointer to the top of the value stack.
758 register int v1, v2 = 0;
760 if (isbinary(op))
761 v2 = *--valp;
762 v1 = *--valp;
763 #ifdef DEBUG_EVAL
764 fprintf( pCppOut, "%s op %s", (isbinary(op)) ? "binary" : "unary",
765 opname[op]);
766 if (isbinary(op))
767 fprintf( pCppOut, ", v2 = %d.", v2);
768 fprintf( pCppOut, ", v1 = %d.\n", v1);
769 #endif
770 switch (op) {
771 case OP_EOE:
772 break;
774 case OP_ADD:
775 v1 += v2;
776 break;
778 case OP_SUB:
779 v1 -= v2;
780 break;
782 case OP_MUL:
783 v1 *= v2;
784 break;
786 case OP_DIV:
787 case OP_MOD:
788 if (v2 == 0) {
789 if (!skip) {
790 cwarn("%s by zero in #if, zero result assumed",
791 (op == OP_DIV) ? "divide" : "mod");
793 v1 = 0;
795 else if (op == OP_DIV)
796 v1 /= v2;
797 else
798 v1 %= v2;
799 break;
801 case OP_ASL:
802 v1 <<= v2;
803 break;
805 case OP_ASR:
806 v1 >>= v2;
807 break;
809 case OP_AND:
810 v1 &= v2;
811 break;
813 case OP_OR:
814 v1 |= v2;
815 break;
817 case OP_XOR:
818 v1 ^= v2;
819 break;
821 case OP_EQ:
822 v1 = (v1 == v2);
823 break;
825 case OP_NE:
826 v1 = (v1 != v2);
827 break;
829 case OP_LT:
830 v1 = (v1 < v2);
831 break;
833 case OP_LE:
834 v1 = (v1 <= v2);
835 break;
837 case OP_GE:
838 v1 = (v1 >= v2);
839 break;
841 case OP_GT:
842 v1 = (v1 > v2);
843 break;
845 case OP_ANA:
846 v1 = (v1 && v2);
847 break;
849 case OP_ORO:
850 v1 = (v1 || v2);
851 break;
853 case OP_COL:
855 * v1 has the "true" value, v2 the "false" value.
856 * The top of the value stack has the test.
858 v1 = (*--valp) ? v1 : v2;
859 break;
861 case OP_NEG:
862 v1 = (-v1);
863 break;
865 case OP_PLU:
866 break;
868 case OP_COM:
869 v1 = ~v1;
870 break;
872 case OP_NOT:
873 v1 = !v1;
874 break;
876 default:
877 cierror("#if bug, operand = %d.", op);
878 v1 = 0;
880 *valp++ = v1;
881 return (valp);
884 #ifdef DEBUG_EVAL
885 dumpstack(opstack, opp, value, valp)
886 OPTAB opstack[NEXP]; /* Operand stack */
887 register OPTAB *opp; /* Operator stack */
888 int value[NEXP]; /* Value stack */
889 register int *valp; /* -> value vector */
891 fprintf( pCppOut, "index op prec skip name -- op stack at %s", infile->bptr);
892 while (opp > opstack) {
893 fprintf( pCppOut, " [%2d] %2d %03o %d %s\n", opp - opstack,
894 opp->op, opp->prec, opp->skip, opname[opp->op]);
895 opp--;
897 while (--valp >= value) {
898 fprintf( pCppOut, "value[%d] = %d\n", (valp - value), *valp);
901 #endif
903 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */