xref: /aoo41x/main/soltools/cpp/_eval.c (revision 7ce20373)
1*7ce20373SAndrew Rist /**************************************************************
2*7ce20373SAndrew Rist  *
3*7ce20373SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*7ce20373SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*7ce20373SAndrew Rist  * distributed with this work for additional information
6*7ce20373SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*7ce20373SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*7ce20373SAndrew Rist  * "License"); you may not use this file except in compliance
9*7ce20373SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*7ce20373SAndrew Rist  *
11*7ce20373SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*7ce20373SAndrew Rist  *
13*7ce20373SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*7ce20373SAndrew Rist  * software distributed under the License is distributed on an
15*7ce20373SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*7ce20373SAndrew Rist  * KIND, either express or implied.  See the License for the
17*7ce20373SAndrew Rist  * specific language governing permissions and limitations
18*7ce20373SAndrew Rist  * under the License.
19*7ce20373SAndrew Rist  *
20*7ce20373SAndrew Rist  *************************************************************/
21*7ce20373SAndrew Rist 
22cdf0e10cSrcweir #include "cpp.h"
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include <stdlib.h>
25cdf0e10cSrcweir #include <string.h>
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #define	NSTAK	32
28cdf0e10cSrcweir #define	SGN	0
29cdf0e10cSrcweir #define	UNS	1
30cdf0e10cSrcweir #define	UND	2
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #define	UNSMARK	0x1000
33cdf0e10cSrcweir 
34cdf0e10cSrcweir struct value
35cdf0e10cSrcweir {
36cdf0e10cSrcweir     long val;
37cdf0e10cSrcweir     int type;
38cdf0e10cSrcweir };
39cdf0e10cSrcweir 
40cdf0e10cSrcweir /* conversion types */
41cdf0e10cSrcweir #define	RELAT	1
42cdf0e10cSrcweir #define	ARITH	2
43cdf0e10cSrcweir #define	LOGIC	3
44cdf0e10cSrcweir #define	SPCL	4
45cdf0e10cSrcweir #define	SHIFT	5
46cdf0e10cSrcweir #define	UNARY	6
47cdf0e10cSrcweir 
48cdf0e10cSrcweir /* operator priority, arity, and conversion type, indexed by tokentype */
49cdf0e10cSrcweir struct pri
50cdf0e10cSrcweir {
51cdf0e10cSrcweir     char pri;
52cdf0e10cSrcweir     char arity;
53cdf0e10cSrcweir     char ctype;
54cdf0e10cSrcweir }   priority[] =
55cdf0e10cSrcweir 
56cdf0e10cSrcweir {
57cdf0e10cSrcweir     {
58cdf0e10cSrcweir         0, 0, 0
59cdf0e10cSrcweir     },                                  /* END */
60cdf0e10cSrcweir     {
61cdf0e10cSrcweir         0, 0, 0
62cdf0e10cSrcweir     },                                  /* UNCLASS */
63cdf0e10cSrcweir     {
64cdf0e10cSrcweir         0, 0, 0
65cdf0e10cSrcweir     },                                  /* NAME */
66cdf0e10cSrcweir     {
67cdf0e10cSrcweir         0, 0, 0
68cdf0e10cSrcweir     },                                  /* NUMBER */
69cdf0e10cSrcweir     {
70cdf0e10cSrcweir         0, 0, 0
71cdf0e10cSrcweir     },                                  /* STRING */
72cdf0e10cSrcweir     {
73cdf0e10cSrcweir         0, 0, 0
74cdf0e10cSrcweir     },                                  /* CCON */
75cdf0e10cSrcweir     {
76cdf0e10cSrcweir         0, 0, 0
77cdf0e10cSrcweir     },                                  /* NL */
78cdf0e10cSrcweir     {
79cdf0e10cSrcweir         0, 0, 0
80cdf0e10cSrcweir     },                                  /* WS */
81cdf0e10cSrcweir     {
82cdf0e10cSrcweir         0, 0, 0
83cdf0e10cSrcweir     },                                  /* DSHARP */
84cdf0e10cSrcweir     {
85cdf0e10cSrcweir         11, 2, RELAT
86cdf0e10cSrcweir     },                                  /* EQ */
87cdf0e10cSrcweir     {
88cdf0e10cSrcweir         11, 2, RELAT
89cdf0e10cSrcweir     },                                  /* NEQ */
90cdf0e10cSrcweir     {
91cdf0e10cSrcweir         12, 2, RELAT
92cdf0e10cSrcweir     },                                  /* LEQ */
93cdf0e10cSrcweir     {
94cdf0e10cSrcweir         12, 2, RELAT
95cdf0e10cSrcweir     },                                  /* GEQ */
96cdf0e10cSrcweir     {
97cdf0e10cSrcweir         13, 2, SHIFT
98cdf0e10cSrcweir     },                                  /* LSH */
99cdf0e10cSrcweir     {
100cdf0e10cSrcweir         13, 2, SHIFT
101cdf0e10cSrcweir     },                                  /* RSH */
102cdf0e10cSrcweir     {
103cdf0e10cSrcweir         7, 2, LOGIC
104cdf0e10cSrcweir     },                                  /* LAND */
105cdf0e10cSrcweir     {
106cdf0e10cSrcweir         6, 2, LOGIC
107cdf0e10cSrcweir     },                                  /* LOR */
108cdf0e10cSrcweir     {
109cdf0e10cSrcweir         0, 0, 0
110cdf0e10cSrcweir     },                                  /* PPLUS */
111cdf0e10cSrcweir     {
112cdf0e10cSrcweir         0, 0, 0
113cdf0e10cSrcweir     },                                  /* MMINUS */
114cdf0e10cSrcweir     {
115cdf0e10cSrcweir         0, 0, 0
116cdf0e10cSrcweir     },                                  /* ARROW */
117cdf0e10cSrcweir     {
118cdf0e10cSrcweir         0, 0, 0
119cdf0e10cSrcweir     },                                  /* SBRA */
120cdf0e10cSrcweir     {
121cdf0e10cSrcweir         0, 0, 0
122cdf0e10cSrcweir     },                                  /* SKET */
123cdf0e10cSrcweir     {
124cdf0e10cSrcweir         3, 0, 0
125cdf0e10cSrcweir     },                                  /* LP */
126cdf0e10cSrcweir     {
127cdf0e10cSrcweir         3, 0, 0
128cdf0e10cSrcweir     },                                  /* RP */
129cdf0e10cSrcweir     {
130cdf0e10cSrcweir         0, 0, 0
131cdf0e10cSrcweir     },                                  /* DOT */
132cdf0e10cSrcweir     {
133cdf0e10cSrcweir         10, 2, ARITH
134cdf0e10cSrcweir     },                                  /* AND */
135cdf0e10cSrcweir     {
136cdf0e10cSrcweir         15, 2, ARITH
137cdf0e10cSrcweir     },                                  /* STAR */
138cdf0e10cSrcweir     {
139cdf0e10cSrcweir         14, 2, ARITH
140cdf0e10cSrcweir     },                                  /* PLUS */
141cdf0e10cSrcweir     {
142cdf0e10cSrcweir         14, 2, ARITH
143cdf0e10cSrcweir     },                                  /* MINUS */
144cdf0e10cSrcweir     {
145cdf0e10cSrcweir         16, 1, UNARY
146cdf0e10cSrcweir     },                                  /* TILDE */
147cdf0e10cSrcweir     {
148cdf0e10cSrcweir         16, 1, UNARY
149cdf0e10cSrcweir     },                                  /* NOT */
150cdf0e10cSrcweir     {
151cdf0e10cSrcweir         15, 2, ARITH
152cdf0e10cSrcweir     },                                  /* SLASH */
153cdf0e10cSrcweir     {
154cdf0e10cSrcweir         15, 2, ARITH
155cdf0e10cSrcweir     },                                  /* PCT */
156cdf0e10cSrcweir     {
157cdf0e10cSrcweir         12, 2, RELAT
158cdf0e10cSrcweir     },                                  /* LT */
159cdf0e10cSrcweir     {
160cdf0e10cSrcweir         12, 2, RELAT
161cdf0e10cSrcweir     },                                  /* GT */
162cdf0e10cSrcweir     {
163cdf0e10cSrcweir         9, 2, ARITH
164cdf0e10cSrcweir     },                                  /* CIRC */
165cdf0e10cSrcweir     {
166cdf0e10cSrcweir         8, 2, ARITH
167cdf0e10cSrcweir     },                                  /* OR */
168cdf0e10cSrcweir     {
169cdf0e10cSrcweir         5, 2, SPCL
170cdf0e10cSrcweir     },                                  /* QUEST */
171cdf0e10cSrcweir     {
172cdf0e10cSrcweir         5, 2, SPCL
173cdf0e10cSrcweir     },                                  /* COLON */
174cdf0e10cSrcweir     {
175cdf0e10cSrcweir         0, 0, 0
176cdf0e10cSrcweir     },                                  /* ASGN */
177cdf0e10cSrcweir     {
178cdf0e10cSrcweir         4, 2, 0
179cdf0e10cSrcweir     },                                  /* COMMA */
180cdf0e10cSrcweir     {
181cdf0e10cSrcweir         0, 0, 0
182cdf0e10cSrcweir     },                                  /* SHARP */
183cdf0e10cSrcweir     {
184cdf0e10cSrcweir         0, 0, 0
185cdf0e10cSrcweir     },                                  /* SEMIC */
186cdf0e10cSrcweir     {
187cdf0e10cSrcweir         0, 0, 0
188cdf0e10cSrcweir     },                                  /* CBRA */
189cdf0e10cSrcweir     {
190cdf0e10cSrcweir         0, 0, 0
191cdf0e10cSrcweir     },                                  /* CKET */
192cdf0e10cSrcweir     {
193cdf0e10cSrcweir         0, 0, 0
194cdf0e10cSrcweir     },                                  /* ASPLUS */
195cdf0e10cSrcweir     {
196cdf0e10cSrcweir         0, 0, 0
197cdf0e10cSrcweir     },                                  /* ASMINUS */
198cdf0e10cSrcweir     {
199cdf0e10cSrcweir         0, 0, 0
200cdf0e10cSrcweir     },                                  /* ASSTAR */
201cdf0e10cSrcweir     {
202cdf0e10cSrcweir         0, 0, 0
203cdf0e10cSrcweir     },                                  /* ASSLASH */
204cdf0e10cSrcweir     {
205cdf0e10cSrcweir         0, 0, 0
206cdf0e10cSrcweir     },                                  /* ASPCT */
207cdf0e10cSrcweir     {
208cdf0e10cSrcweir         0, 0, 0
209cdf0e10cSrcweir     },                                  /* ASCIRC */
210cdf0e10cSrcweir     {
211cdf0e10cSrcweir         0, 0, 0
212cdf0e10cSrcweir     },                                  /* ASLSH */
213cdf0e10cSrcweir     {
214cdf0e10cSrcweir         0, 0, 0
215cdf0e10cSrcweir     },                                  /* ASRSH */
216cdf0e10cSrcweir     {
217cdf0e10cSrcweir         0, 0, 0
218cdf0e10cSrcweir     },                                  /* ASOR */
219cdf0e10cSrcweir     {
220cdf0e10cSrcweir         0, 0, 0
221cdf0e10cSrcweir     },                                  /* ASAND */
222cdf0e10cSrcweir     {
223cdf0e10cSrcweir         0, 0, 0
224cdf0e10cSrcweir     },                                  /* ELLIPS */
225cdf0e10cSrcweir     {
226cdf0e10cSrcweir         0, 0, 0
227cdf0e10cSrcweir     },                                  /* DSHARP1 */
228cdf0e10cSrcweir     {
229cdf0e10cSrcweir         0, 0, 0
230cdf0e10cSrcweir     },                                  /* NAME1 */
231cdf0e10cSrcweir     {
232cdf0e10cSrcweir         0, 0, 0
233cdf0e10cSrcweir     },                                  /* NAME2 */
234cdf0e10cSrcweir     {
235cdf0e10cSrcweir         16, 1, UNARY
236cdf0e10cSrcweir     },                                  /* DEFINED */
237cdf0e10cSrcweir     {
238cdf0e10cSrcweir         16, 0, UNARY
239cdf0e10cSrcweir     },                                  /* UMINUS */
240cdf0e10cSrcweir     {
241cdf0e10cSrcweir         16, 1, UNARY
242cdf0e10cSrcweir     },                                  /* ARCHITECTURE */
243cdf0e10cSrcweir };
244cdf0e10cSrcweir 
245cdf0e10cSrcweir int evalop(struct pri);
246cdf0e10cSrcweir struct value tokval(Token *);
247cdf0e10cSrcweir struct value vals[NSTAK], *vp;
248cdf0e10cSrcweir enum toktype ops[NSTAK], *op;
249cdf0e10cSrcweir 
250cdf0e10cSrcweir /*
251cdf0e10cSrcweir  * Evaluate an #if #elif #ifdef #ifndef line.  trp->tp points to the keyword.
252cdf0e10cSrcweir  */
253cdf0e10cSrcweir long
eval(Tokenrow * trp,int kw)254cdf0e10cSrcweir     eval(Tokenrow * trp, int kw)
255cdf0e10cSrcweir {
256cdf0e10cSrcweir     Token *tp;
257cdf0e10cSrcweir     Nlist *np;
258cdf0e10cSrcweir     int ntok, rnd;
259cdf0e10cSrcweir 
260cdf0e10cSrcweir     trp->tp++;
261cdf0e10cSrcweir     if (kw == KIFDEF || kw == KIFNDEF)
262cdf0e10cSrcweir     {
263cdf0e10cSrcweir         if (trp->lp - trp->bp != 4 || trp->tp->type != NAME)
264cdf0e10cSrcweir         {
265cdf0e10cSrcweir             error(ERROR, "Syntax error in #ifdef/#ifndef");
266cdf0e10cSrcweir             return 0;
267cdf0e10cSrcweir         }
268cdf0e10cSrcweir         np = lookup(trp->tp, 0);
269cdf0e10cSrcweir         return (kw == KIFDEF) == (np && np->flag & (ISDEFINED | ISMAC));
270cdf0e10cSrcweir     }
271cdf0e10cSrcweir     ntok = trp->tp - trp->bp;
272cdf0e10cSrcweir     kwdefined->val = KDEFINED;          /* activate special meaning of
273cdf0e10cSrcweir                                          * defined */
274cdf0e10cSrcweir     expandrow(trp, "<if>");
275cdf0e10cSrcweir     kwdefined->val = NAME;
276cdf0e10cSrcweir     vp = vals;
277cdf0e10cSrcweir     op = ops;
278cdf0e10cSrcweir     *op++ = END;
279cdf0e10cSrcweir     for (rnd = 0, tp = trp->bp + ntok; tp < trp->lp; tp++)
280cdf0e10cSrcweir     {
281cdf0e10cSrcweir         switch (tp->type)
282cdf0e10cSrcweir         {
283cdf0e10cSrcweir             case WS:
284cdf0e10cSrcweir             case NL:
285cdf0e10cSrcweir                 continue;
286cdf0e10cSrcweir 
287cdf0e10cSrcweir                 /* nilary */
288cdf0e10cSrcweir             case NAME:
289cdf0e10cSrcweir             case NAME1:
290cdf0e10cSrcweir             case NAME2:
291cdf0e10cSrcweir             case NUMBER:
292cdf0e10cSrcweir             case CCON:
293cdf0e10cSrcweir             case STRING:
294cdf0e10cSrcweir                 if (rnd)
295cdf0e10cSrcweir                     goto syntax;
296cdf0e10cSrcweir                 *vp++ = tokval(tp);
297cdf0e10cSrcweir                 rnd = 1;
298cdf0e10cSrcweir                 continue;
299cdf0e10cSrcweir 
300cdf0e10cSrcweir                 /* unary */
301cdf0e10cSrcweir             case DEFINED:
302cdf0e10cSrcweir             case TILDE:
303cdf0e10cSrcweir             case NOT:
304cdf0e10cSrcweir                 if (rnd)
305cdf0e10cSrcweir                     goto syntax;
306cdf0e10cSrcweir                 *op++ = tp->type;
307cdf0e10cSrcweir                 continue;
308cdf0e10cSrcweir 
309cdf0e10cSrcweir                 /* unary-binary */
310cdf0e10cSrcweir             case PLUS:
311cdf0e10cSrcweir             case MINUS:
312cdf0e10cSrcweir             case STAR:
313cdf0e10cSrcweir             case AND:
314cdf0e10cSrcweir                 if (rnd == 0)
315cdf0e10cSrcweir                 {
316cdf0e10cSrcweir                     if (tp->type == MINUS)
317cdf0e10cSrcweir                         *op++ = UMINUS;
318cdf0e10cSrcweir                     if (tp->type == STAR || tp->type == AND)
319cdf0e10cSrcweir                     {
320cdf0e10cSrcweir                         error(ERROR, "Illegal operator * or & in #if/#elsif");
321cdf0e10cSrcweir                         return 0;
322cdf0e10cSrcweir                     }
323cdf0e10cSrcweir                     continue;
324cdf0e10cSrcweir                 }
325cdf0e10cSrcweir                 /* flow through */
326cdf0e10cSrcweir 
327cdf0e10cSrcweir                 /* plain binary */
328cdf0e10cSrcweir             case EQ:
329cdf0e10cSrcweir             case NEQ:
330cdf0e10cSrcweir             case LEQ:
331cdf0e10cSrcweir             case GEQ:
332cdf0e10cSrcweir             case LSH:
333cdf0e10cSrcweir             case RSH:
334cdf0e10cSrcweir             case LAND:
335cdf0e10cSrcweir             case LOR:
336cdf0e10cSrcweir             case SLASH:
337cdf0e10cSrcweir             case PCT:
338cdf0e10cSrcweir             case LT:
339cdf0e10cSrcweir             case GT:
340cdf0e10cSrcweir             case CIRC:
341cdf0e10cSrcweir             case OR:
342cdf0e10cSrcweir             case QUEST:
343cdf0e10cSrcweir             case COLON:
344cdf0e10cSrcweir             case COMMA:
345cdf0e10cSrcweir                 if (rnd == 0)
346cdf0e10cSrcweir                     goto syntax;
347cdf0e10cSrcweir                 if (evalop(priority[tp->type]) != 0)
348cdf0e10cSrcweir                     return 0;
349cdf0e10cSrcweir                 *op++ = tp->type;
350cdf0e10cSrcweir                 rnd = 0;
351cdf0e10cSrcweir                 continue;
352cdf0e10cSrcweir 
353cdf0e10cSrcweir             case LP:
354cdf0e10cSrcweir                 if (rnd)
355cdf0e10cSrcweir                     goto syntax;
356cdf0e10cSrcweir                 *op++ = LP;
357cdf0e10cSrcweir                 continue;
358cdf0e10cSrcweir 
359cdf0e10cSrcweir             case RP:
360cdf0e10cSrcweir                 if (!rnd)
361cdf0e10cSrcweir                     goto syntax;
362cdf0e10cSrcweir                 if (evalop(priority[RP]) != 0)
363cdf0e10cSrcweir                     return 0;
364cdf0e10cSrcweir                 if (op <= ops || op[-1] != LP)
365cdf0e10cSrcweir                 {
366cdf0e10cSrcweir                     goto syntax;
367cdf0e10cSrcweir                 }
368cdf0e10cSrcweir                 op--;
369cdf0e10cSrcweir                 continue;
370cdf0e10cSrcweir 
371cdf0e10cSrcweir             case SHARP:
372cdf0e10cSrcweir                 if ((tp + 1) < trp->lp)
373cdf0e10cSrcweir                 {
374cdf0e10cSrcweir                     np = lookup(tp + 1, 0);
375cdf0e10cSrcweir                     if (np && (np->val == KMACHINE))
376cdf0e10cSrcweir                     {
377cdf0e10cSrcweir                         tp++;
378cdf0e10cSrcweir                         if (rnd)
379cdf0e10cSrcweir                             goto syntax;
380cdf0e10cSrcweir                         *op++ = ARCHITECTURE;
381cdf0e10cSrcweir                         continue;
382cdf0e10cSrcweir                     }
383cdf0e10cSrcweir                 }
384cdf0e10cSrcweir                 /* fall through */
385cdf0e10cSrcweir 
386cdf0e10cSrcweir             default:
387cdf0e10cSrcweir                 error(ERROR, "Bad operator (%t) in #if/#elsif", tp);
388cdf0e10cSrcweir                 return 0;
389cdf0e10cSrcweir         }
390cdf0e10cSrcweir     }
391cdf0e10cSrcweir     if (rnd == 0)
392cdf0e10cSrcweir         goto syntax;
393cdf0e10cSrcweir     if (evalop(priority[END]) != 0)
394cdf0e10cSrcweir         return 0;
395cdf0e10cSrcweir     if (op != &ops[1] || vp != &vals[1])
396cdf0e10cSrcweir     {
397cdf0e10cSrcweir         error(ERROR, "Botch in #if/#elsif");
398cdf0e10cSrcweir         return 0;
399cdf0e10cSrcweir     }
400cdf0e10cSrcweir     if (vals[0].type == UND)
401cdf0e10cSrcweir         error(ERROR, "Undefined expression value");
402cdf0e10cSrcweir     return vals[0].val;
403cdf0e10cSrcweir syntax:
404cdf0e10cSrcweir     error(ERROR, "Syntax error in #if/#elsif");
405cdf0e10cSrcweir     return 0;
406cdf0e10cSrcweir }
407cdf0e10cSrcweir 
408cdf0e10cSrcweir int
evalop(struct pri pri)409cdf0e10cSrcweir     evalop(struct pri pri)
410cdf0e10cSrcweir {
411cdf0e10cSrcweir     struct value v1;
412cdf0e10cSrcweir     struct value v2 = { 0, UND };
413cdf0e10cSrcweir     long rv1, rv2;
414cdf0e10cSrcweir     int rtype, oper;
415cdf0e10cSrcweir 
416cdf0e10cSrcweir     rv2 = 0;
417cdf0e10cSrcweir     rtype = 0;
418cdf0e10cSrcweir     while (pri.pri < priority[op[-1]].pri)
419cdf0e10cSrcweir     {
420cdf0e10cSrcweir         oper = *--op;
421cdf0e10cSrcweir         if (priority[oper].arity == 2)
422cdf0e10cSrcweir         {
423cdf0e10cSrcweir             v2 = *--vp;
424cdf0e10cSrcweir             rv2 = v2.val;
425cdf0e10cSrcweir         }
426cdf0e10cSrcweir         v1 = *--vp;
427cdf0e10cSrcweir         rv1 = v1.val;
428cdf0e10cSrcweir /*lint -e574 -e644 */
429cdf0e10cSrcweir         switch (priority[oper].ctype)
430cdf0e10cSrcweir         {
431cdf0e10cSrcweir             case 0:
432cdf0e10cSrcweir             default:
433cdf0e10cSrcweir                 error(WARNING, "Syntax error in #if/#endif");
434cdf0e10cSrcweir                 return 1;
435cdf0e10cSrcweir             case ARITH:
436cdf0e10cSrcweir             case RELAT:
437cdf0e10cSrcweir                 if (v1.type == UNS || v2.type == UNS)
438cdf0e10cSrcweir                     rtype = UNS;
439cdf0e10cSrcweir                 else
440cdf0e10cSrcweir                     rtype = SGN;
441cdf0e10cSrcweir                 if (v1.type == UND || v2.type == UND)
442cdf0e10cSrcweir                     rtype = UND;
443cdf0e10cSrcweir                 if (priority[oper].ctype == RELAT && rtype == UNS)
444cdf0e10cSrcweir                 {
445cdf0e10cSrcweir                     oper |= UNSMARK;
446cdf0e10cSrcweir                     rtype = SGN;
447cdf0e10cSrcweir                 }
448cdf0e10cSrcweir                 break;
449cdf0e10cSrcweir             case SHIFT:
450cdf0e10cSrcweir                 if (v1.type == UND || v2.type == UND)
451cdf0e10cSrcweir                     rtype = UND;
452cdf0e10cSrcweir                 else
453cdf0e10cSrcweir                     rtype = v1.type;
454cdf0e10cSrcweir                 if (rtype == UNS)
455cdf0e10cSrcweir                     oper |= UNSMARK;
456cdf0e10cSrcweir                 break;
457cdf0e10cSrcweir             case UNARY:
458cdf0e10cSrcweir                 rtype = v1.type;
459cdf0e10cSrcweir                 break;
460cdf0e10cSrcweir             case LOGIC:
461cdf0e10cSrcweir             case SPCL:
462cdf0e10cSrcweir                 break;
463cdf0e10cSrcweir         }
464cdf0e10cSrcweir         switch (oper)
465cdf0e10cSrcweir         {
466cdf0e10cSrcweir             case EQ:
467cdf0e10cSrcweir             case EQ | UNSMARK:
468cdf0e10cSrcweir                 rv1 = rv1 == rv2;
469cdf0e10cSrcweir                 break;
470cdf0e10cSrcweir             case NEQ:
471cdf0e10cSrcweir             case NEQ | UNSMARK:
472cdf0e10cSrcweir                 rv1 = rv1 != rv2;
473cdf0e10cSrcweir                 break;
474cdf0e10cSrcweir             case LEQ:
475cdf0e10cSrcweir                 rv1 = rv1 <= rv2;
476cdf0e10cSrcweir                 break;
477cdf0e10cSrcweir             case GEQ:
478cdf0e10cSrcweir                 rv1 = rv1 >= rv2;
479cdf0e10cSrcweir                 break;
480cdf0e10cSrcweir             case LT:
481cdf0e10cSrcweir                 rv1 = rv1 < rv2;
482cdf0e10cSrcweir                 break;
483cdf0e10cSrcweir             case GT:
484cdf0e10cSrcweir                 rv1 = rv1 > rv2;
485cdf0e10cSrcweir                 break;
486cdf0e10cSrcweir             case LEQ | UNSMARK:
487cdf0e10cSrcweir                 rv1 = (unsigned long)rv1 <= (unsigned long)rv2;
488cdf0e10cSrcweir                 break;
489cdf0e10cSrcweir             case GEQ | UNSMARK:
490cdf0e10cSrcweir                 rv1 = (unsigned long)rv1 >= (unsigned long)rv2;
491cdf0e10cSrcweir                 break;
492cdf0e10cSrcweir             case LT | UNSMARK:
493cdf0e10cSrcweir                 rv1 = (unsigned long)rv1 < (unsigned long)rv2;
494cdf0e10cSrcweir                 break;
495cdf0e10cSrcweir             case GT | UNSMARK:
496cdf0e10cSrcweir                 rv1 = (unsigned long)rv1 > (unsigned long)rv2;
497cdf0e10cSrcweir                 break;
498cdf0e10cSrcweir             case LSH:
499cdf0e10cSrcweir                 rv1 <<= rv2;
500cdf0e10cSrcweir                 break;
501cdf0e10cSrcweir             case LSH | UNSMARK:
502cdf0e10cSrcweir                 rv1 = (unsigned long) rv1 << rv2;
503cdf0e10cSrcweir                 break;
504cdf0e10cSrcweir             case RSH:
505cdf0e10cSrcweir                 rv1 >>= rv2;
506cdf0e10cSrcweir                 break;
507cdf0e10cSrcweir             case RSH | UNSMARK:
508cdf0e10cSrcweir                 rv1 = (unsigned long) rv1 >> rv2;
509cdf0e10cSrcweir                 break;
510cdf0e10cSrcweir             case LAND:
511cdf0e10cSrcweir                 rtype = UND;
512cdf0e10cSrcweir                 if (v1.type == UND)
513cdf0e10cSrcweir                     break;
514cdf0e10cSrcweir                 if (rv1 != 0)
515cdf0e10cSrcweir                 {
516cdf0e10cSrcweir                     if (v2.type == UND)
517cdf0e10cSrcweir                         break;
518cdf0e10cSrcweir                     rv1 = rv2 != 0;
519cdf0e10cSrcweir                 }
520cdf0e10cSrcweir                 else
521cdf0e10cSrcweir                     rv1 = 0;
522cdf0e10cSrcweir                 rtype = SGN;
523cdf0e10cSrcweir                 break;
524cdf0e10cSrcweir             case LOR:
525cdf0e10cSrcweir                 rtype = UND;
526cdf0e10cSrcweir                 if (v1.type == UND)
527cdf0e10cSrcweir                     break;
528cdf0e10cSrcweir                 if (rv1 == 0)
529cdf0e10cSrcweir                 {
530cdf0e10cSrcweir                     if (v2.type == UND)
531cdf0e10cSrcweir                         break;
532cdf0e10cSrcweir                     rv1 = rv2 != 0;
533cdf0e10cSrcweir                 }
534cdf0e10cSrcweir                 else
535cdf0e10cSrcweir                     rv1 = 1;
536cdf0e10cSrcweir                 rtype = SGN;
537cdf0e10cSrcweir                 break;
538cdf0e10cSrcweir             case AND:
539cdf0e10cSrcweir                 rv1 &= rv2;
540cdf0e10cSrcweir                 break;
541cdf0e10cSrcweir             case STAR:
542cdf0e10cSrcweir                 rv1 *= rv2;
543cdf0e10cSrcweir                 break;
544cdf0e10cSrcweir             case PLUS:
545cdf0e10cSrcweir                 rv1 += rv2;
546cdf0e10cSrcweir                 break;
547cdf0e10cSrcweir             case MINUS:
548cdf0e10cSrcweir                 rv1 -= rv2;
549cdf0e10cSrcweir                 break;
550cdf0e10cSrcweir             case UMINUS:
551cdf0e10cSrcweir                 if (v1.type == UND)
552cdf0e10cSrcweir                     rtype = UND;
553cdf0e10cSrcweir                 rv1 = -rv1;
554cdf0e10cSrcweir                 break;
555cdf0e10cSrcweir             case OR:
556cdf0e10cSrcweir                 rv1 |= rv2;
557cdf0e10cSrcweir                 break;
558cdf0e10cSrcweir             case CIRC:
559cdf0e10cSrcweir                 rv1 ^= rv2;
560cdf0e10cSrcweir                 break;
561cdf0e10cSrcweir             case TILDE:
562cdf0e10cSrcweir                 rv1 = ~rv1;
563cdf0e10cSrcweir                 break;
564cdf0e10cSrcweir             case NOT:
565cdf0e10cSrcweir                 rv1 = !rv1;
566cdf0e10cSrcweir                 if (rtype != UND)
567cdf0e10cSrcweir                     rtype = SGN;
568cdf0e10cSrcweir                 break;
569cdf0e10cSrcweir             case SLASH:
570cdf0e10cSrcweir                 if (rv2 == 0)
571cdf0e10cSrcweir                 {
572cdf0e10cSrcweir                     rtype = UND;
573cdf0e10cSrcweir                     break;
574cdf0e10cSrcweir                 }
575cdf0e10cSrcweir                 if (rtype == UNS)
576cdf0e10cSrcweir                     rv1 /= (unsigned long) rv2;
577cdf0e10cSrcweir                 else
578cdf0e10cSrcweir                     rv1 /= rv2;
579cdf0e10cSrcweir                 break;
580cdf0e10cSrcweir             case PCT:
581cdf0e10cSrcweir                 if (rv2 == 0)
582cdf0e10cSrcweir                 {
583cdf0e10cSrcweir                     rtype = UND;
584cdf0e10cSrcweir                     break;
585cdf0e10cSrcweir                 }
586cdf0e10cSrcweir                 if (rtype == UNS)
587cdf0e10cSrcweir                     rv1 %= (unsigned long) rv2;
588cdf0e10cSrcweir                 else
589cdf0e10cSrcweir                     rv1 %= rv2;
590cdf0e10cSrcweir                 break;
591cdf0e10cSrcweir             case COLON:
592cdf0e10cSrcweir                 if (op[-1] != QUEST)
593cdf0e10cSrcweir                     error(ERROR, "Bad ?: in #if/endif");
594cdf0e10cSrcweir                 else
595cdf0e10cSrcweir                 {
596cdf0e10cSrcweir                     op--;
597cdf0e10cSrcweir                     if ((--vp)->val == 0)
598cdf0e10cSrcweir                         v1 = v2;
599cdf0e10cSrcweir                     rtype = v1.type;
600cdf0e10cSrcweir                     rv1 = v1.val;
601cdf0e10cSrcweir                 }
602cdf0e10cSrcweir                 break;
603cdf0e10cSrcweir 
604cdf0e10cSrcweir             case DEFINED:
605cdf0e10cSrcweir             case ARCHITECTURE:
606cdf0e10cSrcweir                 break;
607cdf0e10cSrcweir 
608cdf0e10cSrcweir             default:
609cdf0e10cSrcweir                 error(ERROR, "Eval botch (unknown operator)");
610cdf0e10cSrcweir                 return 1;
611cdf0e10cSrcweir         }
612cdf0e10cSrcweir /*lint +e574 +e644 */
613cdf0e10cSrcweir         v1.val = rv1;
614cdf0e10cSrcweir         v1.type = rtype;
615cdf0e10cSrcweir         *vp++ = v1;
616cdf0e10cSrcweir     }
617cdf0e10cSrcweir     return 0;
618cdf0e10cSrcweir }
619cdf0e10cSrcweir 
620cdf0e10cSrcweir struct value
tokval(Token * tp)621cdf0e10cSrcweir     tokval(Token * tp)
622cdf0e10cSrcweir {
623cdf0e10cSrcweir     struct value v;
624cdf0e10cSrcweir     Nlist *np;
625cdf0e10cSrcweir     int i, base;
626cdf0e10cSrcweir     unsigned long n;
627cdf0e10cSrcweir     uchar *p, c;
628cdf0e10cSrcweir 
629cdf0e10cSrcweir     v.type = SGN;
630cdf0e10cSrcweir     v.val = 0;
631cdf0e10cSrcweir     switch (tp->type)
632cdf0e10cSrcweir     {
633cdf0e10cSrcweir 
634cdf0e10cSrcweir         case NAME:
635cdf0e10cSrcweir             v.val = 0;
636cdf0e10cSrcweir             break;
637cdf0e10cSrcweir 
638cdf0e10cSrcweir         case NAME1:
639cdf0e10cSrcweir             if ((np = lookup(tp, 0)) != NULL && np->flag & (ISDEFINED | ISMAC))
640cdf0e10cSrcweir                 v.val = 1;
641cdf0e10cSrcweir             break;
642cdf0e10cSrcweir 
643cdf0e10cSrcweir         case NAME2:
644cdf0e10cSrcweir             if ((np = lookup(tp, 0)) != NULL && np->flag & (ISARCHITECTURE))
645cdf0e10cSrcweir                 v.val = 1;
646cdf0e10cSrcweir             break;
647cdf0e10cSrcweir 
648cdf0e10cSrcweir         case NUMBER:
649cdf0e10cSrcweir             n = 0;
650cdf0e10cSrcweir             base = 10;
651cdf0e10cSrcweir             p = tp->t;
652cdf0e10cSrcweir             c = p[tp->len];
653cdf0e10cSrcweir             p[tp->len] = '\0';
654cdf0e10cSrcweir             if (*p == '0')
655cdf0e10cSrcweir             {
656cdf0e10cSrcweir                 base = 8;
657cdf0e10cSrcweir                 if (p[1] == 'x' || p[1] == 'X')
658cdf0e10cSrcweir                 {
659cdf0e10cSrcweir                     base = 16;
660cdf0e10cSrcweir                     p++;
661cdf0e10cSrcweir                 }
662cdf0e10cSrcweir                 p++;
663cdf0e10cSrcweir             }
664cdf0e10cSrcweir             for (;; p++)
665cdf0e10cSrcweir             {
666cdf0e10cSrcweir                 if ((i = digit(*p)) < 0)
667cdf0e10cSrcweir                     break;
668cdf0e10cSrcweir                 if (i >= base)
669cdf0e10cSrcweir                     error(WARNING,
670cdf0e10cSrcweir                           "Bad digit in number %t", tp);
671cdf0e10cSrcweir                 n *= base;
672cdf0e10cSrcweir                 n += i;
673cdf0e10cSrcweir             }
674cdf0e10cSrcweir             if (n >= 0x80000000 && base != 10)
675cdf0e10cSrcweir                 v.type = UNS;
676cdf0e10cSrcweir             for (; *p; p++)
677cdf0e10cSrcweir             {
678cdf0e10cSrcweir                 if (*p == 'u' || *p == 'U')
679cdf0e10cSrcweir                     v.type = UNS;
680cdf0e10cSrcweir                 else
681cdf0e10cSrcweir                     if (*p == 'l' || *p == 'L')
682cdf0e10cSrcweir                         ;
683cdf0e10cSrcweir                     else
684cdf0e10cSrcweir                     {
685cdf0e10cSrcweir                         error(ERROR,
686cdf0e10cSrcweir                               "Bad number %t in #if/#elsif", tp);
687cdf0e10cSrcweir                         break;
688cdf0e10cSrcweir                     }
689cdf0e10cSrcweir             }
690cdf0e10cSrcweir             v.val = n;
691cdf0e10cSrcweir             tp->t[tp->len] = c;
692cdf0e10cSrcweir             break;
693cdf0e10cSrcweir 
694cdf0e10cSrcweir         case CCON:
695cdf0e10cSrcweir             n = 0;
696cdf0e10cSrcweir             p = tp->t;
697cdf0e10cSrcweir             if (*p == 'L')
698cdf0e10cSrcweir             {
699cdf0e10cSrcweir                 p += 1;
700cdf0e10cSrcweir                 error(WARNING, "Wide char constant value undefined");
701cdf0e10cSrcweir             }
702cdf0e10cSrcweir             p += 1;
703cdf0e10cSrcweir             if (*p == '\\')
704cdf0e10cSrcweir             {
705cdf0e10cSrcweir                 p += 1;
706cdf0e10cSrcweir                 if ((i = digit(*p)) >= 0 && i <= 7)
707cdf0e10cSrcweir                 {
708cdf0e10cSrcweir                     n = i;
709cdf0e10cSrcweir                     p += 1;
710cdf0e10cSrcweir                     if ((i = digit(*p)) >= 0 && i <= 7)
711cdf0e10cSrcweir                     {
712cdf0e10cSrcweir                         p += 1;
713cdf0e10cSrcweir                         n <<= 3;
714cdf0e10cSrcweir                         n += i;
715cdf0e10cSrcweir                         if ((i = digit(*p)) >= 0 && i <= 7)
716cdf0e10cSrcweir                         {
717cdf0e10cSrcweir                             p += 1;
718cdf0e10cSrcweir                             n <<= 3;
719cdf0e10cSrcweir                             n += i;
720cdf0e10cSrcweir                         }
721cdf0e10cSrcweir                     }
722cdf0e10cSrcweir                 }
723cdf0e10cSrcweir                 else
724cdf0e10cSrcweir                     if (*p == 'x')
725cdf0e10cSrcweir                     {
726cdf0e10cSrcweir                         p += 1;
727cdf0e10cSrcweir                         while ((i = digit(*p)) >= 0 && i <= 15)
728cdf0e10cSrcweir                         {
729cdf0e10cSrcweir                             p += 1;
730cdf0e10cSrcweir                             n <<= 4;
731cdf0e10cSrcweir                             n += i;
732cdf0e10cSrcweir                         }
733cdf0e10cSrcweir                     }
734cdf0e10cSrcweir                     else
735cdf0e10cSrcweir                     {
736cdf0e10cSrcweir                         static char cvcon[] = "b\bf\fn\nr\rt\tv\v''\"\"??\\\\";
737cdf0e10cSrcweir                         static size_t cvlen = sizeof(cvcon) - 1;
738cdf0e10cSrcweir 
739cdf0e10cSrcweir                         size_t j;
740cdf0e10cSrcweir                         for (j = 0; j < cvlen; j += 2)
741cdf0e10cSrcweir                         {
742cdf0e10cSrcweir                             if (*p == cvcon[j])
743cdf0e10cSrcweir                             {
744cdf0e10cSrcweir                                 n = cvcon[j + 1];
745cdf0e10cSrcweir                                 break;
746cdf0e10cSrcweir                             }
747cdf0e10cSrcweir                         }
748cdf0e10cSrcweir                         p += 1;
749cdf0e10cSrcweir                         if (j >= cvlen)
750cdf0e10cSrcweir                             error(WARNING,
751cdf0e10cSrcweir                                "Undefined escape in character constant");
752cdf0e10cSrcweir                     }
753cdf0e10cSrcweir             }
754cdf0e10cSrcweir             else
755cdf0e10cSrcweir                 if (*p == '\'')
756cdf0e10cSrcweir                     error(ERROR, "Empty character constant");
757cdf0e10cSrcweir                 else
758cdf0e10cSrcweir                     n = *p++;
759cdf0e10cSrcweir             if (*p != '\'')
760cdf0e10cSrcweir                 error(WARNING, "Multibyte character constant undefined");
761cdf0e10cSrcweir             else
762cdf0e10cSrcweir                 if (n > 127)
763cdf0e10cSrcweir                     error(WARNING, "Character constant taken as not signed");
764cdf0e10cSrcweir             v.val = n;
765cdf0e10cSrcweir             break;
766cdf0e10cSrcweir 
767cdf0e10cSrcweir         case STRING:
768cdf0e10cSrcweir             error(ERROR, "String in #if/#elsif");
769cdf0e10cSrcweir             break;
770cdf0e10cSrcweir     }
771cdf0e10cSrcweir     return v;
772cdf0e10cSrcweir }
773cdf0e10cSrcweir 
774cdf0e10cSrcweir int
digit(int i)775cdf0e10cSrcweir     digit(int i)
776cdf0e10cSrcweir {
777cdf0e10cSrcweir     if ('0' <= i && i <= '9')
778cdf0e10cSrcweir         i -= '0';
779cdf0e10cSrcweir     else
780cdf0e10cSrcweir         if ('a' <= i && i <= 'f')
781cdf0e10cSrcweir             i -= 'a' - 10;
782cdf0e10cSrcweir         else
783cdf0e10cSrcweir             if ('A' <= i && i <= 'F')
784cdf0e10cSrcweir                 i -= 'A' - 10;
785cdf0e10cSrcweir             else
786cdf0e10cSrcweir                 i = -1;
787cdf0e10cSrcweir     return i;
788cdf0e10cSrcweir }
789