bump product version to 5.0.4.1
[LibreOffice.git] / rsc / source / rscpp / cpp5.c
blob499219ba6e7f89f59a0af352190719c0143894fa
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 preceded 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
85 char op; /* Operator */
86 char prec; /* Its precedence */
87 char skip; /* Short-circuit: TRUE to skip */
88 } OPTAB;
89 static int evalue; /* Current value from evallex() */
91 #define isbinary(op) (op >= FIRST_BINOP && op <= LAST_BINOP)
94 * The following definitions are used to specify basic variable sizes.
97 #ifndef S_CHAR
98 #define S_CHAR (sizeof (char))
99 #endif
100 #ifndef S_SINT
101 #define S_SINT (sizeof (short int))
102 #endif
103 #ifndef S_INT
104 #define S_INT (sizeof (int))
105 #endif
106 #ifndef S_LINT
107 #define S_LINT (sizeof (long int))
108 #endif
109 #ifndef S_FLOAT
110 #define S_FLOAT (sizeof (float))
111 #endif
112 #ifndef S_DOUBLE
113 #define S_DOUBLE (sizeof (double))
114 #endif
115 #ifndef S_PCHAR
116 #define S_PCHAR (sizeof (char *))
117 #endif
118 #ifndef S_PSINT
119 #define S_PSINT (sizeof (short int *))
120 #endif
121 #ifndef S_PINT
122 #define S_PINT (sizeof (int *))
123 #endif
124 #ifndef S_PLINT
125 #define S_PLINT (sizeof (long int *))
126 #endif
127 #ifndef S_PFLOAT
128 #define S_PFLOAT (sizeof (float *))
129 #endif
130 #ifndef S_PDOUBLE
131 #define S_PDOUBLE (sizeof (double *))
132 #endif
133 #ifndef S_PFPTR
134 #define S_PFPTR (sizeof (int (*)(void)))
135 #endif
137 typedef struct types
139 short type; /* This is the bit if */
140 char *name; /* this is the token word */
141 } TYPES;
143 static TYPES basic_types[] = {
144 { T_CHAR, "char", },
145 { T_INT, "int", },
146 { T_FLOAT, "float", },
147 { T_DOUBLE, "double", },
148 { T_SHORT, "short", },
149 { T_LONG, "long", },
150 { T_SIGNED, "signed", },
151 { T_UNSIGNED, "unsigned", },
152 { 0, NULL, }, /* Signal end */
156 * Test_table[] is used to test for illegal combinations.
158 static short test_table[] = {
159 T_FLOAT | T_DOUBLE | T_LONG | T_SHORT,
160 T_FLOAT | T_DOUBLE | T_CHAR | T_INT,
161 T_FLOAT | T_DOUBLE | T_SIGNED | T_UNSIGNED,
162 T_LONG | T_SHORT | T_CHAR,
163 0 /* end marker */
167 * The order of this table is important -- it is also referenced by
168 * the command line processor to allow run-time overriding of the
169 * built-in size values. The order must not be changed:
170 * char, short, int, long, float, double (func pointer)
172 SIZES size_table[] = {
173 { T_CHAR, S_CHAR, S_PCHAR }, /* char */
174 { T_SHORT, S_SINT, S_PSINT }, /* short int */
175 { T_INT, S_INT, S_PINT }, /* int */
176 { T_LONG, S_LINT, S_PLINT }, /* long */
177 { T_FLOAT, S_FLOAT, S_PFLOAT }, /* float */
178 { T_DOUBLE, S_DOUBLE, S_PDOUBLE }, /* double */
179 { T_FPTR, 0, S_PFPTR }, /* int (*()) */
180 { 0, 0, 0 }, /* End of table */
184 * Evaluate an expression. Straight-forward operator precedence.
185 * This is called from control() on encountering an #if statement.
186 * It calls the following routines:
187 * evallex Lexical analyser -- returns the type and value of
188 * the next input token.
189 * evaleval Evaluate the current operator, given the values on
190 * the value stack. Returns a pointer to the (new)
191 * value stack.
192 * For compatibility with older cpp's, this return returns 1 (TRUE)
193 * if a syntax error is detected.
195 int eval()
197 int op; /* Current operator */
198 int* valp; /* -> value vector */
199 OPTAB* opp; /* Operator stack */
200 int prec; /* Op precedence */
201 int binop; /* Set if binary op. needed */
202 int op1; /* Operand from stack */
203 int skip; /* For short-circuit testing */
204 int value[NEXP]; /* Value stack */
205 OPTAB opstack[NEXP]; /* Operand stack */
207 valp = value;
208 opp = opstack;
209 opp->op = OP_END; /* Mark bottom of stack */
210 opp->prec = opdope[OP_END]; /* And its precedence */
211 opp->skip = 0; /* Not skipping now */
212 binop = 0;
214 again:
215 #ifdef DEBUG_EVAL
216 fprintf( pCppOut, "In #if at again: skip = %d, binop = %d, line is: %s",
217 opp->skip, binop, infile->bptr);
218 #endif
219 if ((op = evallex(opp->skip)) == OP_SUB && binop == 0)
220 op = OP_NEG; /* Unary minus */
221 else if (op == OP_ADD && binop == 0)
222 op = OP_PLU; /* Unary plus */
223 else if (op == OP_FAIL)
224 return 1; /* Error in evallex */
225 #ifdef DEBUG_EVAL
226 fprintf( pCppOut, "op = %s, opdope = %03o, binop = %d, skip = %d\n",
227 opname[op], opdope[op], binop, opp->skip);
228 #endif
229 if (op == DIG) /* Value? */
231 if (binop != 0)
233 cerror("misplaced constant in #if", NULLST);
234 return 1;
236 else if (valp >= &value[NEXP-1])
238 cerror("#if value stack overflow", NULLST);
239 return 1;
241 else
243 #ifdef DEBUG_EVAL
244 fprintf( pCppOut, "pushing %d onto value stack[%d]\n",
245 evalue, valp - value);
246 #endif
247 *valp++ = evalue;
248 binop = 1;
250 goto again;
252 else if (op > OP_END)
254 cerror("Illegal #if line", NULLST);
255 return 1;
257 prec = opdope[op];
258 if (binop != (prec & 1))
260 cerror("Operator %s in incorrect context", opname[op]);
261 return 1;
263 binop = (prec & 2) >> 1;
264 for (;;)
266 #ifdef DEBUG_EVAL
267 fprintf( pCppOut, "op %s, prec %d., stacked op %s, prec %d, skip %d\n",
268 opname[op], prec, opname[opp->op], opp->prec, opp->skip);
269 #endif
270 if (prec > opp->prec)
272 if (op == OP_LPA)
273 prec = OP_RPA_PREC;
274 else if (op == OP_QUE)
275 prec = OP_QUE_PREC;
276 op1 = opp->skip; /* Save skip for test */
278 * Push operator onto op. stack.
280 opp++;
281 if (opp >= &opstack[NEXP])
283 cerror("expression stack overflow at op \"%s\"",
284 opname[op]);
285 return 1;
287 opp->op = (char)op;
288 opp->prec = (char)prec;
290 * Do the short-circuit stuff here. Short-circuiting
291 * stops automagically when operators are evaluated.
293 if ((op == OP_ANA && valp[-1] == 0) ||
294 (op == OP_ORO && valp[-1] != 0))
296 opp->skip = S_ANDOR; /* And/or skip starts */
298 else if (op == OP_QUE) /* Start of ?: operator */
299 opp->skip = (char)((op1 & S_ANDOR) | ((valp[-1] == 0) ? S_QUEST : 0));
300 else if (op == OP_COL) /* : inverts S_QUEST */
302 opp->skip = (char)((op1 & S_ANDOR)
303 | (((op1 & S_QUEST) != 0) ? 0 : S_QUEST));
305 else /* Other ops leave */
307 opp->skip = (char)op1; /* skipping unchanged. */
309 #ifdef DEBUG_EVAL
310 fprintf( pCppOut, "stacking %s, valp[-1] == %d at %s",
311 opname[op], valp[-1], infile->bptr);
312 dumpstack(opstack, opp, value, valp);
313 #endif
314 goto again;
317 * Pop operator from op. stack and evaluate it.
318 * End of stack and '(' are specials.
320 skip = opp->skip; /* Remember skip value */
321 switch ((op1 = opp->op)) /* Look at stacked op */
323 case OP_END: /* Stack end marker */
324 if (op == OP_EOE)
325 return valp[-1]; /* Finished ok. */
326 goto again; /* Read another op. */
328 case OP_LPA: /* ( on stack */
329 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? */
344 cerror("Misplaced '?' or ':', previous operator is %s",
345 opname[(int)opp->op]);
346 return 1;
349 * Evaluate op1.
351 default: /* Others: */
352 opp--; /* Unstack the operator */
353 #ifdef DEBUG_EVAL
354 fprintf( pCppOut, "Stack before evaluation of %s\n", opname[op1]);
355 dumpstack(opstack, opp, value, valp);
356 #endif
357 valp = evaleval(valp, op1, skip);
358 #ifdef DEBUG_EVAL
359 fprintf( pCppOut, "Stack after evaluation\n");
360 dumpstack(opstack, opp, value, valp);
361 #endif
362 } /* op1 switch end */
363 } /* Stack unwind loop */
367 * Return next eval operator or value. Called from eval(). It
368 * calls a special-purpose routines for 'char' strings and
369 * numeric values:
370 * evalchar called to evaluate 'x'
371 * evalnum called to evaluate numbers.
373 FILE_LOCAL int evallex(int skip)
375 int c;
376 int c1;
377 int t;
379 again:
380 do /* Collect the token */
382 c = skipws();
383 if ((c = macroid(c)) == EOF_CHAR || c == '\n')
385 unget();
386 return OP_EOE; /* End of expression */
389 while ((t = type[c]) == LET && catenate());
390 if (t == INV) /* Total nonsense */
392 if (!skip)
394 if (isascii(c) && isprint(c))
395 cierror("illegal character '%c' in #if", c);
396 else
397 cierror("illegal character (%d decimal) in #if", c);
399 return OP_FAIL;
401 else if (t == QUO) /* ' or " */
403 if (c == '\'') /* Character constant */
405 evalue = evalchar(skip); /* Somewhat messy */
406 #ifdef DEBUG_EVAL
407 fprintf( pCppOut, "evalchar returns %d.\n", evalue);
408 #endif
409 return DIG; /* Return a value */
411 cerror("Can't use a string in an #if", NULLST);
412 return OP_FAIL;
414 else if (t == LET) /* ID must be a macro */
416 if (streq(token, "defined")) /* Or defined name */
418 c1 = c = skipws();
419 if (c == '(') /* Allow defined(name) */
420 c = skipws();
421 if (type[c] == LET)
423 evalue = (lookid(c) != NULL);
424 if (c1 != '(' || /* Need to balance */
425 skipws() == ')') /* Did we balance? */
427 return DIG; /* Parsed ok */
430 cerror("Bad #if ... defined() syntax", NULLST);
431 return OP_FAIL;
433 else if (streq(token, "sizeof")) /* New sizeof hackery */
434 return dosizeof(); /* Gets own routine */
436 * The Draft ANSI C Standard says that an undefined symbol
437 * in an #if has the value zero. We are a bit pickier,
438 * warning except where the programmer was careful to write
439 * #if defined(foo) ? foo : 0
441 #ifdef STRICT_UNDEF
442 if (!skip)
443 cwarn("undefined symbol \"%s\" in #if, 0 used", token);
444 #endif
445 evalue = 0;
446 return DIG;
448 else if (t == DIG) /* Numbers are harder */
450 evalue = evalnum(c);
451 #ifdef DEBUG_EVAL
452 fprintf( pCppOut, "evalnum returns %d.\n", evalue);
453 #endif
455 else if (strchr("!=<>&|\\", c) != NULL)
458 * Process a possible multi-byte lexeme.
460 c1 = cget(); /* Peek at next char */
461 switch (c)
463 case '!':
464 if (c1 == '=')
465 return OP_NE;
466 break;
468 case '=':
469 if (c1 != '=') /* Can't say a=b in #if */
471 unget();
472 cerror("= not allowed in #if", NULLST);
473 return OP_FAIL;
475 return OP_EQ;
477 case '>':
478 case '<':
479 if (c1 == c)
480 return ((c == '<') ? OP_ASL : OP_ASR);
481 else if (c1 == '=')
482 return ((c == '<') ? OP_LE : OP_GE);
483 break;
485 case '|':
486 case '&':
487 if (c1 == c)
488 return ((c == '|') ? OP_ORO : OP_ANA);
489 break;
491 case '\\':
492 if (c1 == '\n') /* Multi-line if */
493 goto again;
494 cerror("Unexpected \\ in #if", NULLST);
495 return OP_FAIL;
497 unget();
499 return t;
503 * Process the sizeof (basic type) operation in an #if string.
504 * Sets evalue to the size and returns
505 * DIG success
506 * OP_FAIL bad parse or something.
508 FILE_LOCAL int dosizeof()
510 int c;
511 TYPES* tp;
512 SIZES* sizp;
513 short* testp;
514 short typecode;
516 if ((c = skipws()) != '(')
517 goto nogood;
519 * Scan off the tokens.
521 typecode = 0;
522 while (0 != (c = skipws()))
524 if ((c = macroid(c)) == EOF_CHAR || c == '\n')
525 goto nogood; /* End of line is a bug */
526 else if (c == '(') /* thing (*)() func ptr */
528 if (skipws() == '*' && skipws() == ')')
529 { /* We found (*) */
530 if (skipws() != '(') /* Let () be optional */
531 unget();
532 else if (skipws() != ')')
533 goto nogood;
534 typecode |= T_FPTR; /* Function pointer */
536 else /* Junk is a bug */
537 goto nogood;
539 else if (type[c] != LET) /* Exit if not a type */
540 break;
541 else if (!catenate()) /* Maybe combine tokens */
544 * Look for this unexpandable token in basic_types.
545 * The code accepts "int long" as well as "long int"
546 * which is a minor bug as bugs go (and one shared with
547 * a lot of C compilers).
549 for (tp = basic_types; tp->name != NULLST; tp++)
551 if (streq(token, tp->name))
552 break;
554 if (tp->name == NULLST)
556 cerror("#if sizeof, unknown type \"%s\"", token);
557 return OP_FAIL;
559 typecode |= tp->type; /* Or in the type bit */
563 * We are at the end of the type scan. Chew off '*' if necessary.
565 if (c == '*')
567 typecode |= T_PTR;
568 c = skipws();
570 if (c == ')') /* Last syntax check */
572 for (testp = test_table; *testp != 0; testp++)
574 if (!bittest(typecode & *testp))
576 cerror("#if ... sizeof: illegal type combination", NULLST);
577 return OP_FAIL;
581 * We assume that all function pointers are the same size:
582 * sizeof (int (*)()) == sizeof (float (*)())
583 * We assume that signed and unsigned don't change the size:
584 * sizeof (signed int) == (sizeof unsigned int)
586 if ((typecode & T_FPTR) != 0) /* Function pointer */
587 typecode = T_FPTR | T_PTR;
588 else /* Var or var * datum */
590 typecode &= ~(T_SIGNED | T_UNSIGNED);
591 if ((typecode & (T_SHORT | T_LONG)) != 0)
592 typecode &= ~T_INT;
594 if ((typecode & ~T_PTR) == 0)
596 cerror("#if sizeof() error, no type specified", NULLST);
597 return OP_FAIL;
600 * Exactly one bit (and possibly T_PTR) may be set.
602 for (sizp = size_table; sizp->bits != 0; sizp++)
604 if ((typecode & ~T_PTR) == sizp->bits)
606 evalue = ((typecode & T_PTR) != 0)
607 ? sizp->psize : sizp->size;
608 return DIG;
610 } /* We shouldn't fail */
611 cierror("#if ... sizeof: bug, unknown type code 0x%x", typecode);
612 return OP_FAIL;
615 nogood:
616 unget();
617 cerror("#if ... sizeof() syntax error", NULLST);
618 return OP_FAIL;
622 * TRUE if value is zero or exactly one bit is set in value.
624 FILE_LOCAL int bittest(int value)
626 /* whoaa!! really worried about non 2's complement machines...
627 * but not at all about cross-compiling ?
629 #if (4096 & ~(-4096)) == 0
630 return ((value & ~(-value)) == 0);
631 #else
633 * Do it the hard way (for non 2's complement machines)
635 return (value == 0 || value ^ (value - 1) == (value * 2 - 1));
636 #endif
640 * Expand number for #if lexical analysis. Note: evalnum recognizes
641 * the unsigned suffix, but only returns a signed int value.
643 FILE_LOCAL int evalnum(int c)
645 int value;
646 int base;
647 int c1;
649 if (c != '0')
650 base = 10;
651 else if ((c = cget()) == 'x' || c == 'X')
653 base = 16;
654 c = cget();
656 else base = 8;
657 value = 0;
658 for (;;)
660 c1 = c;
661 if (isascii(c) && isupper(c1))
662 c1 = tolower(c1);
663 if (c1 >= 'a')
664 c1 -= ('a' - 10);
665 else
666 c1 -= '0';
667 if (c1 < 0 || c1 >= base)
668 break;
669 value *= base;
670 value += c1;
671 c = cget();
673 if (c == 'u' || c == 'U') /* Unsigned nonsense */
674 cget();
675 unget();
676 return value;
680 * Get a character constant
682 FILE_LOCAL int evalchar(int skip)
684 int c;
685 int value;
686 int count;
688 instring = TRUE;
689 if ((c = cget()) == '\\')
691 switch ((c = cget()))
693 case 'a': /* New in Standard */
694 #if ('a' == '\a' || '\a' == ALERT)
695 value = ALERT; /* Use predefined value */
696 #else
697 value = '\a'; /* Use compiler's value */
698 #endif
699 break;
701 case 'b':
702 value = '\b';
703 break;
705 case 'f':
706 value = '\f';
707 break;
709 case 'n':
710 value = '\n';
711 break;
713 case 'r':
714 value = '\r';
715 break;
717 case 't':
718 value = '\t';
719 break;
721 case 'v': /* New in Standard */
722 #if ('v' == '\v' || '\v' == VT)
723 value = VT; /* Use predefined value */
724 #else
725 value = '\v'; /* Use compiler's value */
726 #endif
727 break;
729 case 'x': /* '\xFF' */
730 count = 3;
731 value = 0;
732 while ((((c = get()) >= '0' && c <= '9') ||
733 (c >= 'a' && c <= 'f') ||
734 (c >= 'A' && c <= 'F')) &&
735 (--count >= 0))
737 value *= 16;
738 value += (c - '0');
740 unget();
741 break;
743 default:
744 if (c >= '0' && c <= '7')
746 count = 3;
747 value = 0;
748 while (c >= '0' && c <= '7' && --count >= 0)
750 value *= 8;
751 value += (c - '0');
752 c = get();
754 unget();
756 else value = c;
757 break;
760 else if (c == '\'')
761 value = 0;
762 else
763 value = c;
765 * We warn on multi-byte constants and try to hack
766 * (big|little)endian machines.
768 while ((c = get()) != '\'' && c != EOF_CHAR && c != '\n')
770 if (!skip)
771 ciwarn("multi-byte constant '%c' isn't portable", c);
772 value <<= BITS_CHAR;
773 value += c;
775 instring = FALSE;
776 return value;
780 * Apply the argument operator to the data on the value stack.
781 * One or two values are popped from the value stack and the result
782 * is pushed onto the value stack.
784 * OP_COL is a special case.
786 * evaleval() returns the new pointer to the top of the value stack.
788 FILE_LOCAL int * evaleval(int* valp, int op, int skip)
790 int v1;
791 int v2 = 0;
793 if (isbinary(op))
794 v2 = *--valp;
795 v1 = *--valp;
796 #ifdef DEBUG_EVAL
797 fprintf( pCppOut, "%s op %s", (isbinary(op)) ? "binary" : "unary",
798 opname[op]);
799 if (isbinary(op))
800 fprintf( pCppOut, ", v2 = %d.", v2);
801 fprintf( pCppOut, ", v1 = %d.\n", v1);
802 #endif
803 switch (op)
805 case OP_EOE:
806 break;
808 case OP_ADD:
809 v1 += v2;
810 break;
812 case OP_SUB:
813 v1 -= v2;
814 break;
816 case OP_MUL:
817 v1 *= v2;
818 break;
820 case OP_DIV:
821 case OP_MOD:
822 if (v2 == 0)
824 if (!skip)
826 cwarn("%s by zero in #if, zero result assumed",
827 (op == OP_DIV) ? "divide" : "mod");
829 v1 = 0;
831 else if (op == OP_DIV)
832 v1 /= v2;
833 else
834 v1 %= v2;
835 break;
837 case OP_ASL:
838 v1 <<= v2;
839 break;
841 case OP_ASR:
842 v1 >>= v2;
843 break;
845 case OP_AND:
846 v1 &= v2;
847 break;
849 case OP_OR:
850 v1 |= v2;
851 break;
853 case OP_XOR:
854 v1 ^= v2;
855 break;
857 case OP_EQ:
858 v1 = (v1 == v2);
859 break;
861 case OP_NE:
862 v1 = (v1 != v2);
863 break;
865 case OP_LT:
866 v1 = (v1 < v2);
867 break;
869 case OP_LE:
870 v1 = (v1 <= v2);
871 break;
873 case OP_GE:
874 v1 = (v1 >= v2);
875 break;
877 case OP_GT:
878 v1 = (v1 > v2);
879 break;
881 case OP_ANA:
882 v1 = (v1 && v2);
883 break;
885 case OP_ORO:
886 v1 = (v1 || v2);
887 break;
889 case OP_COL:
891 * v1 has the "true" value, v2 the "false" value.
892 * The top of the value stack has the test.
894 v1 = (*--valp) ? v1 : v2;
895 break;
897 case OP_NEG:
898 v1 = (-v1);
899 break;
901 case OP_PLU:
902 break;
904 case OP_COM:
905 v1 = ~v1;
906 break;
908 case OP_NOT:
909 v1 = !v1;
910 break;
912 default:
913 cierror("#if bug, operand = %d.", op);
914 v1 = 0;
916 *valp++ = v1;
917 return valp;
920 #ifdef DEBUG_EVAL
921 dumpstack(opstack, opp, value, valp)
922 OPTAB opstack[NEXP]; /* Operand stack */
923 OPTAB *opp; /* Operator stack */
924 int value[NEXP]; /* Value stack */
925 int *valp; /* -> value vector */
927 fprintf( pCppOut, "index op prec skip name -- op stack at %s", infile->bptr);
928 while (opp > opstack)
930 fprintf( pCppOut, " [%2d] %2d %03o %d %s\n", opp - opstack,
931 opp->op, opp->prec, opp->skip, opname[opp->op]);
932 opp--;
934 while (--valp >= value)
936 fprintf( pCppOut, "value[%d] = %d\n", (valp - value), *valp);
939 #endif
941 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */