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