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