Bug Summary

File:workdir/unxlngi6.pro/CustomTarget/ucpp/source/eval.c
Location:line 609, column 5
Description:Value stored to 'tr' is never read

Annotated Source Code

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
38JMP_BUFjmp_buf eval_exceptionucpp_eval_exception;
39long eval_lineucpp_eval_line;
40static 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 */
46int *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)
68static void z_error(int type);
69
70#ifdef ARITHMETIC_CHECKS
71#define ARITH_WARNING(type)z_warn(type) z_warn(type)
72static void z_warn(int type);
73#endif
74
75#include "arith.c"
76
77static 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
101static 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
172typedef struct {
173 int sign;
174 union {
175 u_big uv;
176 s_big sv;
177 } u;
178} ppval;
179
180static 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 */
199static 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 }
225suffix_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
231static 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
301static 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 */
363unsigned 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
374static 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
405static 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
510static 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 */
569static 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
596eval_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
648trunc_err:
649 errorucpp_error(eval_lineucpp_eval_line, "truncated constant integral expression");
650 throw(eval_exception)longjmp((ucpp_eval_exception), 1);
651rogue_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);
655invalid_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 */
670unsigned 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);
696eval_err:
697 *ret = 1;
698 return 0;
699}