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 skip = 0;
244 again: ;
245 #ifdef DEBUG_EVAL
246 fprintf( pCppOut, "In #if at again: skip = %d, binop = %d, line is: %s",
247 opp->skip, binop, infile->bptr);
248 #endif
249 if ((op = evallex(opp->skip)) == OP_SUB && binop == 0)
250 op = OP_NEG; /* Unary minus */
251 else if (op == OP_ADD && binop == 0)
252 op = OP_PLU; /* Unary plus */
253 else if (op == OP_FAIL)
254 return (1); /* Error in evallex */
255 #ifdef DEBUG_EVAL
256 fprintf( pCppOut, "op = %s, opdope = %03o, binop = %d, skip = %d\n",
257 opname[op], opdope[op], binop, opp->skip);
258 #endif
259 if (op == DIG) { /* Value? */
260 if (binop != 0) {
261 cerror("misplaced constant in #if", NULLST);
262 return (1);
263 }
264 else if (valp >= &value[NEXP-1]) {
265 cerror("#if value stack overflow", NULLST);
266 return (1);
267 }
268 else {
269 #ifdef DEBUG_EVAL
270 fprintf( pCppOut, "pushing %d onto value stack[%d]\n",
271 evalue, valp - value);
272 #endif
273 *valp++ = evalue;
274 binop = 1;
275 }
276 goto again;
277 }
278 else if (op > OP_END) {
279 cerror("Illegal #if line", NULLST);
280 return (1);
281 }
282 prec = opdope[op];
283 if (binop != (prec & 1)) {
284 cerror("Operator %s in incorrect context", opname[op]);
285 return (1);
286 }
287 binop = (prec & 2) >> 1;
288 for (;;) {
289 #ifdef DEBUG_EVAL
290 fprintf( pCppOut, "op %s, prec %d., stacked op %s, prec %d, skip %d\n",
291 opname[op], prec, opname[opp->op], opp->prec, opp->skip);
292 #endif
293 if (prec > opp->prec) {
294 if (op == OP_LPA)
295 prec = OP_RPA_PREC;
296 else if (op == OP_QUE)
297 prec = OP_QUE_PREC;
298 op1 = opp->skip; /* Save skip for test */
299 /*
300 * Push operator onto op. stack.
301 */
302 opp++;
303 if (opp >= &opstack[NEXP]) {
304 cerror("expression stack overflow at op \"%s\"",
305 opname[op]);
306 return (1);
307 }
308 opp->op = (char)op;
309 opp->prec = (char)prec;
310 if (valp > value) {
311 skip = (valp[-1] != 0); /* Short-circuit tester */
312 }
313 /*
314 * Do the short-circuit stuff here. Short-circuiting
315 * stops automagically when operators are evaluated.
316 */
317 if ((op == OP_ANA && !skip)
318 || (op == OP_ORO && skip))
319 opp->skip = S_ANDOR; /* And/or skip starts */
320 else if (op == OP_QUE) /* Start of ?: operator */
321 opp->skip = (char)((op1 & S_ANDOR) | ((!skip) ? S_QUEST : 0));
322 else if (op == OP_COL) { /* : inverts S_QUEST */
323 opp->skip = (char)((op1 & S_ANDOR)
324 | (((op1 & S_QUEST) != 0) ? 0 : S_QUEST));
325 }
326 else { /* Other ops leave */
327 opp->skip = (char)op1; /* skipping unchanged. */
328 }
329 #ifdef DEBUG_EVAL
330 fprintf( pCppOut, "stacking %s, valp[-1] == %d at %s",
331 opname[op], valp[-1], infile->bptr);
332 dumpstack(opstack, opp, value, valp);
333 #endif
334 goto again;
335 }
336 /*
337 * Pop operator from op. stack and evaluate it.
338 * End of stack and '(' are specials.
339 */
340 skip = opp->skip; /* Remember skip value */
341 switch ((op1 = opp->op)) { /* Look at stacked op */
342 case OP_END: /* Stack end marker */
343 if (op == OP_EOE)
344 return (valp[-1]); /* Finished ok. */
345 goto again; /* Read another op. */
346
347 case OP_LPA: /* ( on stack */
348 if (op != OP_RPA) { /* Matches ) on input */
349 cerror("unbalanced paren's, op is \"%s\"", opname[op]);
350 return (1);
351 }
352 opp--; /* Unstack it */
353 /* goto again; -- Fall through */
354
355 case OP_QUE:
356 goto again; /* Evaluate true expr. */
357
358 case OP_COL: /* : on stack. */
359 opp--; /* Unstack : */
360 if (opp->op != OP_QUE) { /* Matches ? on stack? */
361 cerror("Misplaced '?' or ':', previous operator is %s",
362 opname[(int)opp->op]);
363 return (1);
364 }
365 /*
366 * Evaluate op1.
367 */
368 default: /* Others: */
369 opp--; /* Unstack the operator */
370 #ifdef DEBUG_EVAL
371 fprintf( pCppOut, "Stack before evaluation of %s\n", opname[op1]);
372 dumpstack(opstack, opp, value, valp);
373 #endif
374 valp = evaleval(valp, op1, skip);
375 #ifdef DEBUG_EVAL
376 fprintf( pCppOut, "Stack after evaluation\n");
377 dumpstack(opstack, opp, value, valp);
378 #endif
379 } /* op1 switch end */
380 } /* Stack unwind loop */
381 }
382
383 FILE_LOCAL int
evallex(int skip)384 evallex(int skip)
385 /*
386 * Return next eval operator or value. Called from eval(). It
387 * calls a special-purpose routines for 'char' strings and
388 * numeric values:
389 * evalchar called to evaluate 'x'
390 * evalnum called to evaluate numbers.
391 */
392 {
393 register int c, c1, t;
394
395 again: do { /* Collect the token */
396 c = skipws();
397 if ((c = macroid(c)) == EOF_CHAR || c == '\n') {
398 unget();
399 return (OP_EOE); /* End of expression */
400 }
401 } while ((t = type[c]) == LET && catenate());
402 if (t == INV) { /* Total nonsense */
403 if (!skip) {
404 if (isascii(c) && isprint(c))
405 cierror("illegal character '%c' in #if", c);
406 else
407 cierror("illegal character (%d decimal) in #if", c);
408 }
409 return (OP_FAIL);
410 }
411 else if (t == QUO) { /* ' or " */
412 if (c == '\'') { /* Character constant */
413 evalue = evalchar(skip); /* Somewhat messy */
414 #ifdef DEBUG_EVAL
415 fprintf( pCppOut, "evalchar returns %d.\n", evalue);
416 #endif
417 return (DIG); /* Return a value */
418 }
419 cerror("Can't use a string in an #if", NULLST);
420 return (OP_FAIL);
421 }
422 else if (t == LET) { /* ID must be a macro */
423 if (streq(token, "defined")) { /* Or defined name */
424 c1 = c = skipws();
425 if (c == '(') /* Allow defined(name) */
426 c = skipws();
427 if (type[c] == LET) {
428 evalue = (lookid(c) != NULL);
429 if (c1 != '(' /* Need to balance */
430 || skipws() == ')') /* Did we balance? */
431 return (DIG); /* Parsed ok */
432 }
433 cerror("Bad #if ... defined() syntax", NULLST);
434 return (OP_FAIL);
435 }
436 else if (streq(token, "sizeof")) /* New sizeof hackery */
437 return (dosizeof()); /* Gets own routine */
438 /*
439 * The Draft ANSI C Standard says that an undefined symbol
440 * in an #if has the value zero. We are a bit pickier,
441 * warning except where the programmer was careful to write
442 * #if defined(foo) ? foo : 0
443 */
444 #ifdef STRICT_UNDEF
445 if (!skip)
446 cwarn("undefined symbol \"%s\" in #if, 0 used", token);
447 #endif
448 evalue = 0;
449 return (DIG);
450 }
451 else if (t == DIG) { /* Numbers are harder */
452 evalue = evalnum(c);
453 #ifdef DEBUG_EVAL
454 fprintf( pCppOut, "evalnum returns %d.\n", evalue);
455 #endif
456 }
457 else if (strchr("!=<>&|\\", c) != NULL) {
458 /*
459 * Process a possible multi-byte lexeme.
460 */
461 c1 = cget(); /* Peek at next char */
462 switch (c) {
463 case '!':
464 if (c1 == '=')
465 return (OP_NE);
466 break;
467
468 case '=':
469 if (c1 != '=') { /* Can't say a=b in #if */
470 unget();
471 cerror("= not allowed in #if", NULLST);
472 return (OP_FAIL);
473 }
474 return (OP_EQ);
475
476 case '>':
477 case '<':
478 if (c1 == c)
479 return ((c == '<') ? OP_ASL : OP_ASR);
480 else if (c1 == '=')
481 return ((c == '<') ? OP_LE : OP_GE);
482 break;
483
484 case '|':
485 case '&':
486 if (c1 == c)
487 return ((c == '|') ? OP_ORO : OP_ANA);
488 break;
489
490 case '\\':
491 if (c1 == '\n') /* Multi-line if */
492 goto again;
493 cerror("Unexpected \\ in #if", NULLST);
494 return (OP_FAIL);
495 }
496 unget();
497 }
498 return (t);
499 }
500
501 FILE_LOCAL int
dosizeof()502 dosizeof()
503 /*
504 * Process the sizeof (basic type) operation in an #if string.
505 * Sets evalue to the size and returns
506 * DIG success
507 * OP_FAIL bad parse or something.
508 */
509 {
510 register int c;
511 register TYPES *tp;
512 register SIZES *sizp;
513 register short *testp;
514 short typecode;
515
516 if ((c = skipws()) != '(')
517 goto nogood;
518 /*
519 * Scan off the tokens.
520 */
521 typecode = 0;
522 while (0 != (c = skipws())) {
523 if ((c = macroid(c)) == EOF_CHAR || c == '\n')
524 goto nogood; /* End of line is a bug */
525 else if (c == '(') { /* thing (*)() func ptr */
526 if (skipws() == '*'
527 && skipws() == ')') { /* We found (*) */
528 if (skipws() != '(') /* Let () be optional */
529 unget();
530 else if (skipws() != ')')
531 goto nogood;
532 typecode |= T_FPTR; /* Function pointer */
533 }
534 else { /* Junk is a bug */
535 goto nogood;
536 }
537 }
538 else if (type[c] != LET) /* Exit if not a type */
539 break;
540 else if (!catenate()) { /* Maybe combine tokens */
541 /*
542 * Look for this unexpandable token in basic_types.
543 * The code accepts "int long" as well as "long int"
544 * which is a minor bug as bugs go (and one shared with
545 * a lot of C compilers).
546 */
547 for (tp = basic_types; tp->name != NULLST; tp++) {
548 if (streq(token, tp->name))
549 break;
550 }
551 if (tp->name == NULLST) {
552 cerror("#if sizeof, unknown type \"%s\"", token);
553 return (OP_FAIL);
554 }
555 typecode |= tp->type; /* Or in the type bit */
556 }
557 }
558 /*
559 * We are at the end of the type scan. Chew off '*' if necessary.
560 */
561 if (c == '*') {
562 typecode |= T_PTR;
563 c = skipws();
564 }
565 if (c == ')') { /* Last syntax check */
566 for (testp = test_table; *testp != 0; testp++) {
567 if (!bittest(typecode & *testp)) {
568 cerror("#if ... sizeof: illegal type combination", NULLST);
569 return (OP_FAIL);
570 }
571 }
572 /*
573 * We assume that all function pointers are the same size:
574 * sizeof (int (*)()) == sizeof (float (*)())
575 * We assume that signed and unsigned don't change the size:
576 * sizeof (signed int) == (sizeof unsigned int)
577 */
578 if ((typecode & T_FPTR) != 0) /* Function pointer */
579 typecode = T_FPTR | T_PTR;
580 else { /* Var or var * datum */
581 typecode &= ~(T_SIGNED | T_UNSIGNED);
582 if ((typecode & (T_SHORT | T_LONG)) != 0)
583 typecode &= ~T_INT;
584 }
585 if ((typecode & ~T_PTR) == 0) {
586 cerror("#if sizeof() error, no type specified", NULLST);
587 return (OP_FAIL);
588 }
589 /*
590 * Exactly one bit (and possibly T_PTR) may be set.
591 */
592 for (sizp = size_table; sizp->bits != 0; sizp++) {
593 if ((typecode & ~T_PTR) == sizp->bits) {
594 evalue = ((typecode & T_PTR) != 0)
595 ? sizp->psize : sizp->size;
596 return (DIG);
597 }
598 } /* We shouldn't fail */
599 cierror("#if ... sizeof: bug, unknown type code 0x%x", typecode);
600 return (OP_FAIL);
601 }
602
603 nogood: unget();
604 cerror("#if ... sizeof() syntax error", NULLST);
605 return (OP_FAIL);
606 }
607
608 FILE_LOCAL int
bittest(int value)609 bittest(int value)
610 /*
611 * TRUE if value is zero or exactly one bit is set in value.
612 */
613 {
614 #if (4096 & ~(-4096)) == 0
615 return ((value & ~(-value)) == 0);
616 #else
617 /*
618 * Do it the hard way (for non 2's complement machines)
619 */
620 return (value == 0 || value ^ (value - 1) == (value * 2 - 1));
621 #endif
622 }
623
624 FILE_LOCAL int
evalnum(int c)625 evalnum(int c)
626 /*
627 * Expand number for #if lexical analysis. Note: evalnum recognizes
628 * the unsigned suffix, but only returns a signed int value.
629 */
630 {
631 register int value;
632 register int base;
633 register int c1;
634
635 if (c != '0')
636 base = 10;
637 else if ((c = cget()) == 'x' || c == 'X') {
638 base = 16;
639 c = cget();
640 }
641 else base = 8;
642 value = 0;
643 for (;;) {
644 c1 = c;
645 if (isascii(c) && isupper(c1))
646 c1 = tolower(c1);
647 #ifdef EBCDIC
648 if (c1 <= 'f')
649 #else
650 if (c1 >= 'a')
651 #endif
652 c1 -= ('a' - 10);
653 else c1 -= '0';
654 if (c1 < 0 || c1 >= base)
655 break;
656 value *= base;
657 value += c1;
658 c = cget();
659 }
660 if (c == 'u' || c == 'U') /* Unsigned nonsense */
661 c = cget();
662 unget();
663 return (value);
664 }
665
666 FILE_LOCAL int
evalchar(int skip)667 evalchar(int skip)
668 /*
669 * Get a character constant
670 */
671 {
672 register int c;
673 register int value;
674 register int count;
675
676 instring = TRUE;
677 if ((c = cget()) == '\\') {
678 switch ((c = cget())) {
679 case 'a': /* New in Standard */
680 #if ('a' == '\a' || '\a' == ALERT)
681 value = ALERT; /* Use predefined value */
682 #else
683 value = '\a'; /* Use compiler's value */
684 #endif
685 break;
686
687 case 'b':
688 value = '\b';
689 break;
690
691 case 'f':
692 value = '\f';
693 break;
694
695 case 'n':
696 value = '\n';
697 break;
698
699 case 'r':
700 value = '\r';
701 break;
702
703 case 't':
704 value = '\t';
705 break;
706
707 case 'v': /* New in Standard */
708 #if ('v' == '\v' || '\v' == VT)
709 value = VT; /* Use predefined value */
710 #else
711 value = '\v'; /* Use compiler's value */
712 #endif
713 break;
714
715 case 'x': /* '\xFF' */
716 count = 3;
717 value = 0;
718 while ((((c = get()) >= '0' && c <= '9')
719 || (c >= 'a' && c <= 'f')
720 || (c >= 'A' && c <= 'F'))
721 && (--count >= 0)) {
722 value *= 16;
723 #ifdef EBCDIC
724 value += (c <= '9') ? (c - '0') : ((c & 0xF) + 9);
725 #else
726 value += (c >= '0') ? (c - '0') : ((c & 0xF) + 9);
727 #endif
728 }
729 unget();
730 break;
731
732 default:
733 if (c >= '0' && c <= '7') {
734 count = 3;
735 value = 0;
736 while (c >= '0' && c <= '7' && --count >= 0) {
737 value *= 8;
738 value += (c - '0');
739 c = get();
740 }
741 unget();
742 }
743 else value = c;
744 break;
745 }
746 }
747 else if (c == '\'')
748 value = 0;
749 else value = c;
750 /*
751 * We warn on multi-byte constants and try to hack
752 * (big|little)endian machines.
753 */
754 #if BIG_ENDIAN
755 count = 0;
756 #endif
757 while ((c = get()) != '\'' && c != EOF_CHAR && c != '\n') {
758 if (!skip)
759 ciwarn("multi-byte constant '%c' isn't portable", c);
760 #if BIG_ENDIAN
761 count += BITS_CHAR;
762 value += (c << count);
763 #else
764 value <<= BITS_CHAR;
765 value += c;
766 #endif
767 }
768 instring = FALSE;
769 return (value);
770 }
771
772 FILE_LOCAL int *
evaleval(int * valp,int op,int skip)773 evaleval(int* valp, int op, int skip)
774 /*
775 * Apply the argument operator to the data on the value stack.
776 * One or two values are popped from the value stack and the result
777 * is pushed onto the value stack.
778 *
779 * OP_COL is a special case.
780 *
781 * evaleval() returns the new pointer to the top of the value stack.
782 */
783 {
784 register int v1, v2 = 0;
785
786 if (isbinary(op))
787 v2 = *--valp;
788 v1 = *--valp;
789 #ifdef DEBUG_EVAL
790 fprintf( pCppOut, "%s op %s", (isbinary(op)) ? "binary" : "unary",
791 opname[op]);
792 if (isbinary(op))
793 fprintf( pCppOut, ", v2 = %d.", v2);
794 fprintf( pCppOut, ", v1 = %d.\n", v1);
795 #endif
796 switch (op) {
797 case OP_EOE:
798 break;
799
800 case OP_ADD:
801 v1 += v2;
802 break;
803
804 case OP_SUB:
805 v1 -= v2;
806 break;
807
808 case OP_MUL:
809 v1 *= v2;
810 break;
811
812 case OP_DIV:
813 case OP_MOD:
814 if (v2 == 0) {
815 if (!skip) {
816 cwarn("%s by zero in #if, zero result assumed",
817 (op == OP_DIV) ? "divide" : "mod");
818 }
819 v1 = 0;
820 }
821 else if (op == OP_DIV)
822 v1 /= v2;
823 else
824 v1 %= v2;
825 break;
826
827 case OP_ASL:
828 v1 <<= v2;
829 break;
830
831 case OP_ASR:
832 v1 >>= v2;
833 break;
834
835 case OP_AND:
836 v1 &= v2;
837 break;
838
839 case OP_OR:
840 v1 |= v2;
841 break;
842
843 case OP_XOR:
844 v1 ^= v2;
845 break;
846
847 case OP_EQ:
848 v1 = (v1 == v2);
849 break;
850
851 case OP_NE:
852 v1 = (v1 != v2);
853 break;
854
855 case OP_LT:
856 v1 = (v1 < v2);
857 break;
858
859 case OP_LE:
860 v1 = (v1 <= v2);
861 break;
862
863 case OP_GE:
864 v1 = (v1 >= v2);
865 break;
866
867 case OP_GT:
868 v1 = (v1 > v2);
869 break;
870
871 case OP_ANA:
872 v1 = (v1 && v2);
873 break;
874
875 case OP_ORO:
876 v1 = (v1 || v2);
877 break;
878
879 case OP_COL:
880 /*
881 * v1 has the "true" value, v2 the "false" value.
882 * The top of the value stack has the test.
883 */
884 v1 = (*--valp) ? v1 : v2;
885 break;
886
887 case OP_NEG:
888 v1 = (-v1);
889 break;
890
891 case OP_PLU:
892 break;
893
894 case OP_COM:
895 v1 = ~v1;
896 break;
897
898 case OP_NOT:
899 v1 = !v1;
900 break;
901
902 default:
903 cierror("#if bug, operand = %d.", op);
904 v1 = 0;
905 }
906 *valp++ = v1;
907 return (valp);
908 }
909
910 #ifdef DEBUG_EVAL
dumpstack(opstack,opp,value,valp)911 dumpstack(opstack, opp, value, valp)
912 OPTAB opstack[NEXP]; /* Operand stack */
913 register OPTAB *opp; /* Operator stack */
914 int value[NEXP]; /* Value stack */
915 register int *valp; /* -> value vector */
916 {
917 fprintf( pCppOut, "index op prec skip name -- op stack at %s", infile->bptr);
918 while (opp > opstack) {
919 fprintf( pCppOut, " [%2d] %2d %03o %d %s\n", opp - opstack,
920 opp->op, opp->prec, opp->skip, opname[opp->op]);
921 opp--;
922 }
923 while (--valp >= value) {
924 fprintf( pCppOut, "value[%d] = %d\n", (valp - value), *valp);
925 }
926 }
927 #endif
928
929