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