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