File: | workdir/unxlngi6.pro/CustomTarget/ucpp/source/eval.c |
Location: | line 609, column 5 |
Description: | Value stored to 'tr' is never read |
1 | /* |
2 | * (c) Thomas Pornin 1999 - 2002 |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions |
6 | * are met: |
7 | * 1. Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. |
9 | * 2. Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * 4. The name of the authors may not be used to endorse or promote |
13 | * products derived from this software without specific prior written |
14 | * permission. |
15 | * |
16 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE |
20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
22 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
23 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
25 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
26 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | * |
28 | */ |
29 | |
30 | #include "tune.h" |
31 | #include <stdio.h> |
32 | #include <string.h> |
33 | #include <setjmp.h> |
34 | #include <limits.h> |
35 | #include "ucppi.h" |
36 | #include "mem.h" |
37 | |
38 | JMP_BUFjmp_buf eval_exceptionucpp_eval_exception; |
39 | long eval_lineucpp_eval_line; |
40 | static int emit_eval_warnings; |
41 | |
42 | /* |
43 | * If you want to hardcode a conversion table, define a static array |
44 | * of 256 int, and make transient_characters point to it. |
45 | */ |
46 | int *transient_characters = 0; |
47 | |
48 | #define OCTAL(x)((x) >= '0' && (x) <= '7') ((x) >= '0' && (x) <= '7') |
49 | #define DECIM(x)((x) >= '0' && (x) <= '9') ((x) >= '0' && (x) <= '9') |
50 | #define HEXAD(x)(((x) >= '0' && (x) <= '9') || (x) == 'a' || (x ) == 'b' || (x) == 'c' || (x) == 'd' || (x) == 'e' || (x) == 'f' || (x) == 'A' || (x) == 'B' || (x) == 'C' || (x) == 'D' || ( x) == 'E' || (x) == 'F') (DECIM(x)((x) >= '0' && (x) <= '9') \ |
51 | || (x) == 'a' || (x) == 'b' || (x) == 'c' \ |
52 | || (x) == 'd' || (x) == 'e' || (x) == 'f' \ |
53 | || (x) == 'A' || (x) == 'B' || (x) == 'C' \ |
54 | || (x) == 'D' || (x) == 'E' || (x) == 'F') |
55 | #define OVAL(x)((int)((x) - '0')) ((int)((x) - '0')) |
56 | #define DVAL(x)((int)((x) - '0')) ((int)((x) - '0')) |
57 | #define HVAL(x)(((x) >= '0' && (x) <= '9') ? ((int)((x) - '0') ) : (x) == 'a' || (x) == 'A' ? 10 : (x) == 'b' || (x) == 'B' ? 11 : (x) == 'c' || (x) == 'C' ? 12 : (x) == 'd' || (x) == 'D' ? 13 : (x) == 'e' || (x) == 'E' ? 14 : 15) (DECIM(x)((x) >= '0' && (x) <= '9') ? DVAL(x)((int)((x) - '0')) \ |
58 | : (x) == 'a' || (x) == 'A' ? 10 \ |
59 | : (x) == 'b' || (x) == 'B' ? 11 \ |
60 | : (x) == 'c' || (x) == 'C' ? 12 \ |
61 | : (x) == 'd' || (x) == 'D' ? 13 \ |
62 | : (x) == 'e' || (x) == 'E' ? 14 : 15) |
63 | |
64 | #define ARITH_TYPENAMEbig big |
65 | #define ARITH_FUNCTION_HEADERstatic inline static inline |
66 | |
67 | #define ARITH_ERROR(type)z_error(type) z_error(type) |
68 | static void z_error(int type); |
69 | |
70 | #ifdef ARITHMETIC_CHECKS |
71 | #define ARITH_WARNING(type)z_warn(type) z_warn(type) |
72 | static void z_warn(int type); |
73 | #endif |
74 | |
75 | #include "arith.c" |
76 | |
77 | static void z_error(int type) |
78 | { |
79 | switch (type) { |
80 | case ARITH_EXCEP_SLASH_D: |
81 | errorucpp_error(eval_lineucpp_eval_line, "division by 0"); |
82 | break; |
83 | case ARITH_EXCEP_SLASH_O: |
84 | errorucpp_error(eval_lineucpp_eval_line, "overflow on division"); |
85 | break; |
86 | case ARITH_EXCEP_PCT_D: |
87 | errorucpp_error(eval_lineucpp_eval_line, "division by 0 on modulus operator"); |
88 | break; |
89 | case ARITH_EXCEP_CONST_O: |
90 | errorucpp_error(eval_lineucpp_eval_line, "constant too large for destination type"); |
91 | break; |
92 | #ifdef AUDIT |
93 | default: |
94 | ouchucpp_ouch("erroneous integer error: %d", type); |
95 | #endif |
96 | } |
97 | throw(eval_exception)longjmp((ucpp_eval_exception), 1); |
98 | } |
99 | |
100 | #ifdef ARITHMETIC_CHECKS |
101 | static void z_warn(int type) |
102 | { |
103 | switch (type) { |
104 | case ARITH_EXCEP_CONV_O: |
105 | warningucpp_warning(eval_lineucpp_eval_line, "overflow on integer conversion"); |
106 | break; |
107 | case ARITH_EXCEP_NEG_O: |
108 | warningucpp_warning(eval_lineucpp_eval_line, "overflow on unary minus"); |
109 | break; |
110 | case ARITH_EXCEP_NOT_T: |
111 | warningucpp_warning(eval_lineucpp_eval_line, |
112 | "bitwise inversion yields trap representation"); |
113 | break; |
114 | case ARITH_EXCEP_PLUS_O: |
115 | warningucpp_warning(eval_lineucpp_eval_line, "overflow on addition"); |
116 | break; |
117 | case ARITH_EXCEP_PLUS_U: |
118 | warningucpp_warning(eval_lineucpp_eval_line, "underflow on addition"); |
119 | break; |
120 | case ARITH_EXCEP_MINUS_O: |
121 | warningucpp_warning(eval_lineucpp_eval_line, "overflow on subtraction"); |
122 | break; |
123 | case ARITH_EXCEP_MINUS_U: |
124 | warningucpp_warning(eval_lineucpp_eval_line, "underflow on subtraction"); |
125 | break; |
126 | case ARITH_EXCEP_AND_T: |
127 | warningucpp_warning(eval_lineucpp_eval_line, |
128 | "bitwise AND yields trap representation"); |
129 | break; |
130 | case ARITH_EXCEP_XOR_T: |
131 | warningucpp_warning(eval_lineucpp_eval_line, |
132 | "bitwise XOR yields trap representation"); |
133 | break; |
134 | case ARITH_EXCEP_OR_T: |
135 | warningucpp_warning(eval_lineucpp_eval_line, |
136 | "bitwise OR yields trap representation"); |
137 | break; |
138 | case ARITH_EXCEP_LSH_W: |
139 | warningucpp_warning(eval_lineucpp_eval_line, "left shift count greater than " |
140 | "or equal to type width"); |
141 | break; |
142 | case ARITH_EXCEP_LSH_C: |
143 | warningucpp_warning(eval_lineucpp_eval_line, "left shift count negative"); |
144 | break; |
145 | case ARITH_EXCEP_LSH_O: |
146 | warningucpp_warning(eval_lineucpp_eval_line, "overflow on left shift"); |
147 | break; |
148 | case ARITH_EXCEP_RSH_W: |
149 | warningucpp_warning(eval_lineucpp_eval_line, "right shift count greater than " |
150 | "or equal to type width"); |
151 | break; |
152 | case ARITH_EXCEP_RSH_C: |
153 | warningucpp_warning(eval_lineucpp_eval_line, "right shift count negative"); |
154 | break; |
155 | case ARITH_EXCEP_RSH_N: |
156 | warningucpp_warning(eval_lineucpp_eval_line, "right shift of negative value"); |
157 | break; |
158 | case ARITH_EXCEP_STAR_O: |
159 | warningucpp_warning(eval_lineucpp_eval_line, "overflow on multiplication"); |
160 | break; |
161 | case ARITH_EXCEP_STAR_U: |
162 | warningucpp_warning(eval_lineucpp_eval_line, "underflow on multiplication"); |
163 | break; |
164 | #ifdef AUDIT |
165 | default: |
166 | ouchucpp_ouch("erroneous integer warning: %d", type); |
167 | #endif |
168 | } |
169 | } |
170 | #endif |
171 | |
172 | typedef struct { |
173 | int sign; |
174 | union { |
175 | u_big uv; |
176 | s_big sv; |
177 | } u; |
178 | } ppval; |
179 | |
180 | static int boolval(ppval x) |
181 | { |
182 | return x.sign ? big_s_lval(x.u.sv) : big_u_lval(x.u.uv); |
183 | } |
184 | |
185 | #if !defined(WCHAR_SIGNEDNESS1) |
186 | # if CHAR_MIN(-127 -1) == 0 |
187 | # define WCHAR_SIGNEDNESS1 0 |
188 | # else |
189 | # define WCHAR_SIGNEDNESS1 1 |
190 | # endif |
191 | #endif |
192 | |
193 | /* |
194 | * Check the suffix, return 1 if it is signed, 0 otherwise. 1 is |
195 | * returned for a void suffix. Legal suffixes are: |
196 | * unsigned: u U ul uL Ul UL lu Lu lU LU ull uLL Ull ULL llu LLu llU LLU |
197 | * signed: l L ll LL |
198 | */ |
199 | static int pp_suffix(char *d, char *refc) |
200 | { |
201 | if (!*d) return 1; |
202 | if (*d == 'u' || *d == 'U') { |
203 | if (!*(++ d)) return 0; |
204 | if (*d == 'l' || *d == 'L') { |
205 | char *e = d + 1; |
206 | |
207 | if (*e && *e != *d) goto suffix_error; |
208 | if (!*e || !*(e + 1)) return 0; |
209 | goto suffix_error; |
210 | } |
211 | goto suffix_error; |
212 | } |
213 | if (*d == 'l' || *d == 'L') { |
214 | if (!*(++ d)) return 1; |
215 | if (*d == *(d - 1)) { |
216 | d ++; |
217 | if (!*d) return 1; |
218 | } |
219 | if (*d == 'u' || *d == 'U') { |
220 | d ++; |
221 | if (!*d) return 0; |
222 | } |
223 | goto suffix_error; |
224 | } |
225 | suffix_error: |
226 | errorucpp_error(eval_lineucpp_eval_line, "invalid integer constant '%s'", refc); |
227 | throw(eval_exception)longjmp((ucpp_eval_exception), 1); |
228 | return 666; |
229 | } |
230 | |
231 | static unsigned long pp_char(char *c, char *refc) |
232 | { |
233 | unsigned long r = 0; |
234 | |
235 | c ++; |
236 | if (*c == '\\') { |
237 | int i; |
238 | |
239 | c ++; |
240 | switch (*c) { |
241 | case 'n': r = '\n'; c ++; break; |
242 | case 't': r = '\t'; c ++; break; |
243 | case 'v': r = '\v'; c ++; break; |
244 | case 'b': r = '\b'; c ++; break; |
245 | case 'r': r = '\r'; c ++; break; |
246 | case 'f': r = '\f'; c ++; break; |
247 | case 'a': r = '\a'; c ++; break; |
248 | case '\\': r = '\\'; c ++; break; |
249 | case '\?': r = '\?'; c ++; break; |
250 | case '\'': r = '\''; c ++; break; |
251 | case '\"': r = '\"'; c ++; break; |
252 | case 'u': |
253 | for (i = 0, c ++; i < 4 && HEXAD(*c)(((*c) >= '0' && (*c) <= '9') || (*c) == 'a' || (*c) == 'b' || (*c) == 'c' || (*c) == 'd' || (*c) == 'e' || ( *c) == 'f' || (*c) == 'A' || (*c) == 'B' || (*c) == 'C' || (* c) == 'D' || (*c) == 'E' || (*c) == 'F'); i ++, c ++) { |
254 | r = (r * 16) + HVAL(*c)(((*c) >= '0' && (*c) <= '9') ? ((int)((*c) - '0' )) : (*c) == 'a' || (*c) == 'A' ? 10 : (*c) == 'b' || (*c) == 'B' ? 11 : (*c) == 'c' || (*c) == 'C' ? 12 : (*c) == 'd' || ( *c) == 'D' ? 13 : (*c) == 'e' || (*c) == 'E' ? 14 : 15); |
255 | } |
256 | if (i != 4) { |
257 | errorucpp_error(eval_lineucpp_eval_line, "malformed UCN in %s", refc); |
258 | throw(eval_exception)longjmp((ucpp_eval_exception), 1); |
259 | } |
260 | break; |
261 | case 'U': |
262 | for (i = 0, c ++; i < 8 && HEXAD(*c)(((*c) >= '0' && (*c) <= '9') || (*c) == 'a' || (*c) == 'b' || (*c) == 'c' || (*c) == 'd' || (*c) == 'e' || ( *c) == 'f' || (*c) == 'A' || (*c) == 'B' || (*c) == 'C' || (* c) == 'D' || (*c) == 'E' || (*c) == 'F'); i ++, c ++) { |
263 | r = (r * 16) + HVAL(*c)(((*c) >= '0' && (*c) <= '9') ? ((int)((*c) - '0' )) : (*c) == 'a' || (*c) == 'A' ? 10 : (*c) == 'b' || (*c) == 'B' ? 11 : (*c) == 'c' || (*c) == 'C' ? 12 : (*c) == 'd' || ( *c) == 'D' ? 13 : (*c) == 'e' || (*c) == 'E' ? 14 : 15); |
264 | } |
265 | if (i != 8) { |
266 | errorucpp_error(eval_lineucpp_eval_line, "malformed UCN in %s", refc); |
267 | throw(eval_exception)longjmp((ucpp_eval_exception), 1); |
268 | } |
269 | break; |
270 | case 'x': |
271 | for (c ++; HEXAD(*c)(((*c) >= '0' && (*c) <= '9') || (*c) == 'a' || (*c) == 'b' || (*c) == 'c' || (*c) == 'd' || (*c) == 'e' || ( *c) == 'f' || (*c) == 'A' || (*c) == 'B' || (*c) == 'C' || (* c) == 'D' || (*c) == 'E' || (*c) == 'F'); c ++) r = (r * 16) + HVAL(*c)(((*c) >= '0' && (*c) <= '9') ? ((int)((*c) - '0' )) : (*c) == 'a' || (*c) == 'A' ? 10 : (*c) == 'b' || (*c) == 'B' ? 11 : (*c) == 'c' || (*c) == 'C' ? 12 : (*c) == 'd' || ( *c) == 'D' ? 13 : (*c) == 'e' || (*c) == 'E' ? 14 : 15); |
272 | break; |
273 | default: |
274 | if (OCTAL(*c)((*c) >= '0' && (*c) <= '7')) { |
275 | r = OVAL(*(c ++))((int)((*(c ++)) - '0')); |
276 | if (OCTAL(*c)((*c) >= '0' && (*c) <= '7')) r = (r * 8) + OVAL(*(c ++))((int)((*(c ++)) - '0')); |
277 | if (OCTAL(*c)((*c) >= '0' && (*c) <= '7')) r = (r * 8) + OVAL(*(c ++))((int)((*(c ++)) - '0')); |
278 | } else { |
279 | errorucpp_error(eval_lineucpp_eval_line, "invalid escape sequence " |
280 | "'\\%c'", *c); |
281 | throw(eval_exception)longjmp((ucpp_eval_exception), 1); |
282 | } |
283 | } |
284 | } else if (*c == '\'') { |
285 | errorucpp_error(eval_lineucpp_eval_line, "empty character constant"); |
286 | throw(eval_exception)longjmp((ucpp_eval_exception), 1); |
287 | } else { |
288 | r = *((unsigned char *)(c ++)); |
289 | } |
290 | |
291 | if (transient_characters && r < 256) { |
292 | r = transient_characters[(size_t)r]; |
293 | } |
294 | |
295 | if (*c != '\'' && emit_eval_warnings) { |
296 | warningucpp_warning(eval_lineucpp_eval_line, "multicharacter constant"); |
297 | } |
298 | return r; |
299 | } |
300 | |
301 | static ppval pp_strtoconst(char *refc) |
302 | { |
303 | ppval q; |
304 | char *c = refc, *d; |
305 | u_big ru; |
306 | s_big rs; |
307 | int sp, dec; |
308 | |
309 | if (*c == '\'' || *c == 'L') { |
310 | q.sign = (*c == 'L') ? WCHAR_SIGNEDNESS1 : 1; |
311 | if (*c == 'L' && *(++ c) != '\'') { |
312 | errorucpp_error(eval_lineucpp_eval_line, |
313 | "invalid wide character constant: %s", refc); |
314 | throw(eval_exception)longjmp((ucpp_eval_exception), 1); |
315 | } |
316 | if (q.sign) { |
317 | q.u.sv = big_s_fromlong(pp_char(c, refc)); |
318 | } else { |
319 | q.u.uv = big_u_fromulong(pp_char(c, refc)); |
320 | } |
321 | return q; |
322 | } |
323 | if (*c == '0') { |
324 | /* octal or hexadecimal */ |
325 | dec = 0; |
326 | c ++; |
327 | if (*c == 'x' || *c == 'X') { |
328 | c ++; |
329 | d = big_u_hexconst(c, &ru, &rs, &sp); |
330 | } else { |
331 | d = big_u_octconst(c, &ru, &rs, &sp); |
332 | } |
333 | } else { |
334 | dec = 1; |
335 | d = big_u_decconst(c, &ru, &rs, &sp); |
336 | } |
337 | q.sign = pp_suffix(d, refc); |
338 | if (q.sign) { |
339 | if (!sp) { |
340 | if (dec) { |
341 | errorucpp_error(eval_lineucpp_eval_line, "constant too large " |
342 | "for destination type"); |
343 | throw(eval_exception)longjmp((ucpp_eval_exception), 1); |
344 | } else { |
345 | warningucpp_warning(eval_lineucpp_eval_line, "constant is so large " |
346 | "that it is unsigned"); |
347 | } |
348 | q.u.uv = ru; |
349 | q.sign = 0; |
350 | } else { |
351 | q.u.sv = rs; |
352 | } |
353 | } else { |
354 | q.u.uv = ru; |
355 | } |
356 | return q; |
357 | } |
358 | |
359 | /* |
360 | * Used by #line directives -- anything beyond what can be put in an |
361 | * unsigned long, is considered absurd. |
362 | */ |
363 | unsigned long strtoconstucpp_strtoconst(char *c) |
364 | { |
365 | ppval q = pp_strtoconst(c); |
366 | |
367 | if (q.sign) q.u.uv = big_s_to_u(q.u.sv); |
368 | return big_u_toulong(q.u.uv); |
369 | } |
370 | |
371 | #define OP_UN(x)((x) == LNOT || (x) == NOT || (x) == UPLUS || (x) == UMINUS) ((x) == LNOT || (x) == NOT || (x) == UPLUS \ |
372 | || (x) == UMINUS) |
373 | |
374 | static ppval eval_opun(int op, ppval v) |
375 | { |
376 | if (op == LNOT) { |
377 | v.sign = 1; |
378 | v.u.sv = big_s_fromint(big_s_lnot(v.u.sv)); |
379 | return v; |
380 | } |
381 | if (v.sign) { |
382 | switch (op) { |
383 | case NOT: v.u.sv = big_s_not(v.u.sv); break; |
384 | case UPLUS: break; |
385 | case UMINUS: v.u.sv = big_s_neg(v.u.sv); break; |
386 | } |
387 | } else { |
388 | switch (op) { |
389 | case NOT: v.u.uv = big_u_not(v.u.uv); break; |
390 | case UPLUS: break; |
391 | case UMINUS: v.u.uv = big_u_neg(v.u.uv); break; |
392 | } |
393 | } |
394 | return v; |
395 | } |
396 | |
397 | #define OP_BIN(x)((x) == STAR || (x) == SLASH || (x) == PCT || (x) == PLUS || ( x) == MINUS || (x) == LSH || (x) == RSH || (x) == LT || (x) == LEQ || (x) == GT || (x) == GEQ || (x) == SAME || (x) == NEQ || (x) == AND || (x) == CIRC || (x) == OR || (x) == LAND || (x) == LOR || (x) == COMMA) ((x) == STAR || (x) == SLASH || (x) == PCT \ |
398 | || (x) == PLUS || (x) == MINUS || (x) == LSH \ |
399 | || (x) == RSH || (x) == LT || (x) == LEQ \ |
400 | || (x) == GT || (x) == GEQ || (x) == SAME \ |
401 | || (x) == NEQ || (x) == AND || (x) == CIRC \ |
402 | || (x) == OR || (x) == LAND || (x) == LOR \ |
403 | || (x) == COMMA) |
404 | |
405 | static ppval eval_opbin(int op, ppval v1, ppval v2) |
406 | { |
407 | ppval r; |
408 | int iv2 = 0; |
409 | |
410 | switch (op) { |
411 | case STAR: case SLASH: case PCT: |
412 | case PLUS: case MINUS: case AND: |
413 | case CIRC: case OR: |
414 | /* promote operands, adjust signedness of result */ |
415 | if (!v1.sign || !v2.sign) { |
416 | if (v1.sign) { |
417 | v1.u.uv = big_s_to_u(v1.u.sv); |
418 | v1.sign = 0; |
419 | } else if (v2.sign) { |
420 | v2.u.uv = big_s_to_u(v2.u.sv); |
421 | v2.sign = 0; |
422 | } |
423 | r.sign = 0; |
424 | } else { |
425 | r.sign = 1; |
426 | } |
427 | break; |
428 | case LT: case LEQ: case GT: |
429 | case GEQ: case SAME: case NEQ: |
430 | /* promote operands */ |
431 | if (!v1.sign || !v2.sign) { |
432 | if (v1.sign) { |
433 | v1.u.uv = big_s_to_u(v1.u.sv); |
434 | v1.sign = 0; |
435 | } else if (v2.sign) { |
436 | v2.u.uv = big_s_to_u(v2.u.sv); |
437 | v2.sign = 0; |
438 | } |
439 | } |
440 | /* fall through */ |
441 | case LAND: |
442 | case LOR: |
443 | /* result is signed anyway */ |
444 | r.sign = 1; |
445 | break; |
446 | case LSH: |
447 | case RSH: |
448 | /* result is as signed as left operand; convert right |
449 | operand to int */ |
450 | r.sign = v1.sign; |
451 | if (v2.sign) { |
452 | iv2 = big_s_toint(v2.u.sv); |
453 | } else { |
454 | iv2 = big_u_toint(v2.u.uv); |
455 | } |
456 | break; |
457 | case COMMA: |
458 | if (emit_eval_warnings) { |
459 | warningucpp_warning(eval_lineucpp_eval_line, "ISO C forbids evaluated comma " |
460 | "operators in #if expressions"); |
461 | } |
462 | r.sign = v2.sign; |
463 | break; |
464 | #ifdef AUDIT |
465 | default: ouchucpp_ouch("a good operator is a dead operator"); |
466 | #endif |
467 | } |
468 | |
469 | #define SBINOP(x)if (r.sign) r.u.sv = big_s_x (v1.u.sv, v2.u.sv); else r.u.uv = big_u_x (v1.u.uv, v2.u.uv); if (r.sign) r.u.sv = big_s_ ## x (v1.u.sv, v2.u.sv); \ |
470 | else r.u.uv = big_u_ ## x (v1.u.uv, v2.u.uv); |
471 | |
472 | #define NSSBINOP(x)if (v1.sign) r.u.sv = big_s_fromint(big_s_x (v1.u.sv, v2.u.sv )); else r.u.sv = big_s_fromint( big_u_x (v1.u.uv, v2.u.uv)); if (v1.sign) r.u.sv = big_s_fromint(big_s_ ## x \ |
473 | (v1.u.sv, v2.u.sv)); else r.u.sv = big_s_fromint( \ |
474 | big_u_ ## x (v1.u.uv, v2.u.uv)); |
475 | |
476 | #define LBINOP(x)if (v1.sign) r.u.sv = big_s_fromint( big_s_lval(v1.u.sv) x big_s_lval (v2.u.sv)); else r.u.sv = big_s_fromint( big_u_lval(v1.u.uv) x big_u_lval(v2.u.uv)); if (v1.sign) r.u.sv = big_s_fromint( \ |
477 | big_s_lval(v1.u.sv) x big_s_lval(v2.u.sv)); \ |
478 | else r.u.sv = big_s_fromint( \ |
479 | big_u_lval(v1.u.uv) x big_u_lval(v2.u.uv)); |
480 | |
481 | #define ABINOP(x)if (r.sign) r.u.sv = big_s_x (v1.u.sv, iv2); else r.u.uv = big_u_x (v1.u.uv, iv2); if (r.sign) r.u.sv = big_s_ ## x (v1.u.sv, iv2); \ |
482 | else r.u.uv = big_u_ ## x (v1.u.uv, iv2); |
483 | |
484 | switch (op) { |
485 | case STAR: SBINOP(star)if (r.sign) r.u.sv = big_s_star (v1.u.sv, v2.u.sv); else r.u. uv = big_u_star (v1.u.uv, v2.u.uv);; break; |
486 | case SLASH: SBINOP(slash)if (r.sign) r.u.sv = big_s_slash (v1.u.sv, v2.u.sv); else r.u .uv = big_u_slash (v1.u.uv, v2.u.uv);; break; |
487 | case PCT: SBINOP(pct)if (r.sign) r.u.sv = big_s_pct (v1.u.sv, v2.u.sv); else r.u.uv = big_u_pct (v1.u.uv, v2.u.uv);; break; |
488 | case PLUS: SBINOP(plus)if (r.sign) r.u.sv = big_s_plus (v1.u.sv, v2.u.sv); else r.u. uv = big_u_plus (v1.u.uv, v2.u.uv);; break; |
489 | case MINUS: SBINOP(minus)if (r.sign) r.u.sv = big_s_minus (v1.u.sv, v2.u.sv); else r.u .uv = big_u_minus (v1.u.uv, v2.u.uv);; break; |
490 | case LSH: ABINOP(lsh)if (r.sign) r.u.sv = big_s_lsh (v1.u.sv, iv2); else r.u.uv = big_u_lsh (v1.u.uv, iv2);; break; |
491 | case RSH: ABINOP(rsh)if (r.sign) r.u.sv = big_s_rsh (v1.u.sv, iv2); else r.u.uv = big_u_rsh (v1.u.uv, iv2);; break; |
492 | case LT: NSSBINOP(lt)if (v1.sign) r.u.sv = big_s_fromint(big_s_lt (v1.u.sv, v2.u.sv )); else r.u.sv = big_s_fromint( big_u_lt (v1.u.uv, v2.u.uv)) ;; break; |
493 | case LEQ: NSSBINOP(leq)if (v1.sign) r.u.sv = big_s_fromint(big_s_leq (v1.u.sv, v2.u. sv)); else r.u.sv = big_s_fromint( big_u_leq (v1.u.uv, v2.u.uv ));; break; |
494 | case GT: NSSBINOP(gt)if (v1.sign) r.u.sv = big_s_fromint(big_s_gt (v1.u.sv, v2.u.sv )); else r.u.sv = big_s_fromint( big_u_gt (v1.u.uv, v2.u.uv)) ;; break; |
495 | case GEQ: NSSBINOP(geq)if (v1.sign) r.u.sv = big_s_fromint(big_s_geq (v1.u.sv, v2.u. sv)); else r.u.sv = big_s_fromint( big_u_geq (v1.u.uv, v2.u.uv ));; break; |
496 | case SAME: NSSBINOP(same)if (v1.sign) r.u.sv = big_s_fromint(big_s_same (v1.u.sv, v2.u .sv)); else r.u.sv = big_s_fromint( big_u_same (v1.u.uv, v2.u .uv));; break; |
497 | case NEQ: NSSBINOP(neq)if (v1.sign) r.u.sv = big_s_fromint(big_s_neq (v1.u.sv, v2.u. sv)); else r.u.sv = big_s_fromint( big_u_neq (v1.u.uv, v2.u.uv ));; break; |
498 | case AND: SBINOP(and)if (r.sign) r.u.sv = big_s_and (v1.u.sv, v2.u.sv); else r.u.uv = big_u_and (v1.u.uv, v2.u.uv);; break; |
499 | case CIRC: SBINOP(xor)if (r.sign) r.u.sv = big_s_xor (v1.u.sv, v2.u.sv); else r.u.uv = big_u_xor (v1.u.uv, v2.u.uv);; break; |
500 | case OR: SBINOP(or)if (r.sign) r.u.sv = big_s_or (v1.u.sv, v2.u.sv); else r.u.uv = big_u_or (v1.u.uv, v2.u.uv);; break; |
501 | case LAND: LBINOP(&&)if (v1.sign) r.u.sv = big_s_fromint( big_s_lval(v1.u.sv) && big_s_lval(v2.u.sv)); else r.u.sv = big_s_fromint( big_u_lval (v1.u.uv) && big_u_lval(v2.u.uv));; break; |
502 | case LOR: LBINOP(||)if (v1.sign) r.u.sv = big_s_fromint( big_s_lval(v1.u.sv) || big_s_lval (v2.u.sv)); else r.u.sv = big_s_fromint( big_u_lval(v1.u.uv) || big_u_lval(v2.u.uv));; break; |
503 | case COMMA: r = v2; break; |
504 | } |
505 | return r; |
506 | } |
507 | |
508 | #define ttOP(x)(((x) == LNOT || (x) == NOT || (x) == UPLUS || (x) == UMINUS) || ((x) == STAR || (x) == SLASH || (x) == PCT || (x) == PLUS || (x) == MINUS || (x) == LSH || (x) == RSH || (x) == LT || ( x) == LEQ || (x) == GT || (x) == GEQ || (x) == SAME || (x) == NEQ || (x) == AND || (x) == CIRC || (x) == OR || (x) == LAND || (x) == LOR || (x) == COMMA) || (x) == QUEST || (x) == COLON ) (OP_UN(x)((x) == LNOT || (x) == NOT || (x) == UPLUS || (x) == UMINUS) || OP_BIN(x)((x) == STAR || (x) == SLASH || (x) == PCT || (x) == PLUS || ( x) == MINUS || (x) == LSH || (x) == RSH || (x) == LT || (x) == LEQ || (x) == GT || (x) == GEQ || (x) == SAME || (x) == NEQ || (x) == AND || (x) == CIRC || (x) == OR || (x) == LAND || (x) == LOR || (x) == COMMA) || (x) == QUEST || (x) == COLON) |
509 | |
510 | static int op_prec(int op) |
511 | { |
512 | switch (op) { |
513 | case LNOT: |
514 | case NOT: |
515 | case UPLUS: |
516 | case UMINUS: |
517 | return 13; |
518 | case STAR: |
519 | case SLASH: |
520 | case PCT: |
521 | return 12; |
522 | case PLUS: |
523 | case MINUS: |
524 | return 11; |
525 | case LSH: |
526 | case RSH: |
527 | return 10; |
528 | case LT: |
529 | case LEQ: |
530 | case GT: |
531 | case GEQ: |
532 | return 9; |
533 | case SAME: |
534 | case NEQ: |
535 | return 8; |
536 | case AND: |
537 | return 7; |
538 | case CIRC: |
539 | return 6; |
540 | case OR: |
541 | return 5; |
542 | case LAND: |
543 | return 4; |
544 | case LOR: |
545 | return 3; |
546 | case QUEST: |
547 | return 2; |
548 | case COMMA: |
549 | return 1; |
550 | } |
551 | #ifdef AUDIT |
552 | ouchucpp_ouch("an unknown species should have a higher precedence"); |
553 | #endif |
554 | return 666; |
555 | } |
556 | |
557 | /* |
558 | * Perform the hard work of evaluation. |
559 | * |
560 | * This function works because: |
561 | * -- all unary operators are right to left associative, and with |
562 | * identical precedence |
563 | * -- all binary operators are left to right associative |
564 | * -- there is only one non-unary and non-binary operator: the quest-colon |
565 | * |
566 | * If do_eval is 0, the evaluation of operators is not done. This is |
567 | * for sequence point operators (&&, || and ?:). |
568 | */ |
569 | static ppval eval_shrd(struct token_fifo *tf, int minprec, int do_eval) |
570 | { |
571 | ppval top; |
572 | struct token *ct; |
573 | |
574 | top.sign = 1; |
575 | if (tf->art == tf->nt) goto trunc_err; |
576 | ct = tf->t + (tf->art ++); |
577 | if (ct->type == LPAR) { |
578 | top = eval_shrd(tf, 0, do_eval); |
579 | if (tf->art == tf->nt) goto trunc_err; |
580 | ct = tf->t + (tf->art ++); |
581 | if (ct->type != RPAR) { |
582 | errorucpp_error(eval_lineucpp_eval_line, "a right parenthesis was expected"); |
583 | throw(eval_exception)longjmp((ucpp_eval_exception), 1); |
584 | } |
585 | } else if (ct->type == NUMBER || ct->type == CHAR) { |
586 | top = pp_strtoconst(ct->name); |
587 | } else if (OP_UN(ct->type)((ct->type) == LNOT || (ct->type) == NOT || (ct->type ) == UPLUS || (ct->type) == UMINUS)) { |
588 | top = eval_opun(ct->type, eval_shrd(tf, |
589 | op_prec(ct->type), do_eval)); |
590 | goto eval_loop; |
591 | } else if (ttOP(ct->type)(((ct->type) == LNOT || (ct->type) == NOT || (ct->type ) == UPLUS || (ct->type) == UMINUS) || ((ct->type) == STAR || (ct->type) == SLASH || (ct->type) == PCT || (ct-> type) == PLUS || (ct->type) == MINUS || (ct->type) == LSH || (ct->type) == RSH || (ct->type) == LT || (ct->type ) == LEQ || (ct->type) == GT || (ct->type) == GEQ || (ct ->type) == SAME || (ct->type) == NEQ || (ct->type) == AND || (ct->type) == CIRC || (ct->type) == OR || (ct-> type) == LAND || (ct->type) == LOR || (ct->type) == COMMA ) || (ct->type) == QUEST || (ct->type) == COLON)) goto rogue_op_err; |
592 | else { |
593 | goto invalid_token_err; |
594 | } |
595 | |
596 | eval_loop: |
597 | if (tf->art == tf->nt) { |
598 | return top; |
599 | } |
600 | ct = tf->t + (tf->art ++); |
601 | if (OP_BIN(ct->type)((ct->type) == STAR || (ct->type) == SLASH || (ct->type ) == PCT || (ct->type) == PLUS || (ct->type) == MINUS || (ct->type) == LSH || (ct->type) == RSH || (ct->type ) == LT || (ct->type) == LEQ || (ct->type) == GT || (ct ->type) == GEQ || (ct->type) == SAME || (ct->type) == NEQ || (ct->type) == AND || (ct->type) == CIRC || (ct-> type) == OR || (ct->type) == LAND || (ct->type) == LOR || (ct->type) == COMMA)) { |
602 | int bp = op_prec(ct->type); |
603 | |
604 | if (bp > minprec) { |
605 | ppval tr; |
606 | |
607 | if ((ct->type == LOR && boolval(top)) |
608 | || (ct->type == LAND && !boolval(top))) { |
609 | tr = eval_shrd(tf, bp, 0); |
Value stored to 'tr' is never read | |
610 | if (do_eval) { |
611 | top.sign = 1; |
612 | if (ct->type == LOR) |
613 | top.u.sv = big_s_fromint(1); |
614 | if (ct->type == LAND) |
615 | top.u.sv = big_s_fromint(0); |
616 | } |
617 | } else { |
618 | tr = eval_shrd(tf, bp, do_eval); |
619 | if (do_eval) |
620 | top = eval_opbin(ct->type, top, tr); |
621 | } |
622 | goto eval_loop; |
623 | } |
624 | } else if (ct->type == QUEST) { |
625 | int bp = op_prec(QUEST); |
626 | ppval r1, r2; |
627 | |
628 | if (bp >= minprec) { |
629 | int qv = boolval(top); |
630 | |
631 | r1 = eval_shrd(tf, bp, qv ? do_eval : 0); |
632 | if (tf->art == tf->nt) goto trunc_err; |
633 | ct = tf->t + (tf->art ++); |
634 | if (ct->type != COLON) { |
635 | errorucpp_error(eval_lineucpp_eval_line, "a colon was expected"); |
636 | throw(eval_exception)longjmp((ucpp_eval_exception), 1); |
637 | } |
638 | r2 = eval_shrd(tf, bp, qv ? 0 : do_eval); |
639 | if (do_eval) { |
640 | if (qv) top = r1; else top = r2; |
641 | } |
642 | goto eval_loop; |
643 | } |
644 | } |
645 | tf->art --; |
646 | return top; |
647 | |
648 | trunc_err: |
649 | errorucpp_error(eval_lineucpp_eval_line, "truncated constant integral expression"); |
650 | throw(eval_exception)longjmp((ucpp_eval_exception), 1); |
651 | rogue_op_err: |
652 | errorucpp_error(eval_lineucpp_eval_line, "rogue operator '%s' in constant integral " |
653 | "expression", operators_name[ct->type]); |
654 | throw(eval_exception)longjmp((ucpp_eval_exception), 1); |
655 | invalid_token_err: |
656 | errorucpp_error(eval_lineucpp_eval_line, "invalid token in constant integral expression"); |
657 | throw(eval_exception)longjmp((ucpp_eval_exception), 1); |
658 | } |
659 | |
660 | #define UNARY(x)((x) != NUMBER && (x) != NAME && (x) != CHAR && (x) != RPAR) ((x) != NUMBER && (x) != NAME && (x) != CHAR \ |
661 | && (x) != RPAR) |
662 | |
663 | /* |
664 | * Evaluate the integer expression contained in the given token_fifo. |
665 | * Evaluation is made by precedence of operators, as described in the |
666 | * Dragon Book. The unary + and - are distinguished from their binary |
667 | * counterparts using the Fortran way: a + or a - is considered unary |
668 | * if it does not follow a constant, an identifier or a right parenthesis. |
669 | */ |
670 | unsigned long eval_exprucpp_eval_expr(struct token_fifo *tf, int *ret, int ew) |
671 | { |
672 | size_t sart; |
673 | ppval r; |
674 | |
675 | emit_eval_warnings = ew; |
676 | if (catch(eval_exception)_setjmp ((ucpp_eval_exception))) goto eval_err; |
677 | /* first, distinguish unary + and - from binary + and - */ |
678 | for (sart = tf->art; tf->art < tf->nt; tf->art ++) { |
679 | if (tf->t[tf->art].type == PLUS) { |
680 | if (sart == tf->art || UNARY(tf->t[tf->art - 1].type)((tf->t[tf->art - 1].type) != NUMBER && (tf-> t[tf->art - 1].type) != NAME && (tf->t[tf->art - 1].type) != CHAR && (tf->t[tf->art - 1].type ) != RPAR)) |
681 | tf->t[tf->art].type = UPLUS; |
682 | } else if (tf->t[tf->art].type == MINUS) { |
683 | if (sart == tf->art || UNARY(tf->t[tf->art - 1].type)((tf->t[tf->art - 1].type) != NUMBER && (tf-> t[tf->art - 1].type) != NAME && (tf->t[tf->art - 1].type) != CHAR && (tf->t[tf->art - 1].type ) != RPAR)) |
684 | tf->t[tf->art].type = UMINUS; |
685 | } |
686 | } |
687 | tf->art = sart; |
688 | r = eval_shrd(tf, 0, 1); |
689 | if (tf->art < tf->nt) { |
690 | errorucpp_error(eval_lineucpp_eval_line, "trailing garbage in constant integral " |
691 | "expression"); |
692 | goto eval_err; |
693 | } |
694 | *ret = 0; |
695 | return boolval(r); |
696 | eval_err: |
697 | *ret = 1; |
698 | return 0; |
699 | } |