Sync to wine-0.9.61: Oooops, forgot to add these files!!
[reactos.git] / reactos / tools / widl / expr.c
1 /*
2 * Expression Abstract Syntax Tree Functions
3 *
4 * Copyright 2002 Ove Kaaven
5 * Copyright 2006-2008 Robert Shearman
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "config.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <assert.h>
28 #include <ctype.h>
29 #include <string.h>
30
31 #include "widl.h"
32 #include "utils.h"
33 #include "expr.h"
34 #include "header.h"
35
36 expr_t *make_expr(enum expr_type type)
37 {
38 expr_t *e = xmalloc(sizeof(expr_t));
39 e->type = type;
40 e->ref = NULL;
41 e->u.lval = 0;
42 e->is_const = FALSE;
43 e->cval = 0;
44 return e;
45 }
46
47 expr_t *make_exprl(enum expr_type type, long val)
48 {
49 expr_t *e = xmalloc(sizeof(expr_t));
50 e->type = type;
51 e->ref = NULL;
52 e->u.lval = val;
53 e->is_const = FALSE;
54 /* check for numeric constant */
55 if (type == EXPR_NUM || type == EXPR_HEXNUM || type == EXPR_TRUEFALSE)
56 {
57 /* make sure true/false value is valid */
58 assert(type != EXPR_TRUEFALSE || val == 0 || val == 1);
59 e->is_const = TRUE;
60 e->cval = val;
61 }
62 return e;
63 }
64
65 expr_t *make_exprd(enum expr_type type, double val)
66 {
67 expr_t *e = xmalloc(sizeof(expr_t));
68 e->type = type;
69 e->ref = NULL;
70 e->u.dval = val;
71 e->is_const = TRUE;
72 e->cval = val;
73 return e;
74 }
75
76 expr_t *make_exprs(enum expr_type type, char *val)
77 {
78 expr_t *e;
79 e = xmalloc(sizeof(expr_t));
80 e->type = type;
81 e->ref = NULL;
82 e->u.sval = val;
83 e->is_const = FALSE;
84 /* check for predefined constants */
85 if (type == EXPR_IDENTIFIER)
86 {
87 var_t *c = find_const(val, 0);
88 if (c)
89 {
90 e->u.sval = c->name;
91 free(val);
92 e->is_const = TRUE;
93 e->cval = c->eval->cval;
94 }
95 }
96 return e;
97 }
98
99 expr_t *make_exprt(enum expr_type type, type_t *tref, expr_t *expr)
100 {
101 expr_t *e;
102 e = xmalloc(sizeof(expr_t));
103 e->type = type;
104 e->ref = expr;
105 e->u.tref = tref;
106 e->is_const = FALSE;
107 /* check for cast of constant expression */
108 if (type == EXPR_SIZEOF)
109 {
110 switch (tref->type)
111 {
112 case RPC_FC_BYTE:
113 case RPC_FC_CHAR:
114 case RPC_FC_SMALL:
115 case RPC_FC_USMALL:
116 e->is_const = TRUE;
117 e->cval = 1;
118 break;
119 case RPC_FC_WCHAR:
120 case RPC_FC_USHORT:
121 case RPC_FC_SHORT:
122 e->is_const = TRUE;
123 e->cval = 2;
124 break;
125 case RPC_FC_LONG:
126 case RPC_FC_ULONG:
127 case RPC_FC_FLOAT:
128 case RPC_FC_ERROR_STATUS_T:
129 e->is_const = TRUE;
130 e->cval = 4;
131 break;
132 case RPC_FC_HYPER:
133 case RPC_FC_DOUBLE:
134 e->is_const = TRUE;
135 e->cval = 8;
136 break;
137 }
138 }
139 if (type == EXPR_CAST && expr->is_const)
140 {
141 e->is_const = TRUE;
142 e->cval = expr->cval;
143 }
144 return e;
145 }
146
147 expr_t *make_expr1(enum expr_type type, expr_t *expr)
148 {
149 expr_t *e;
150 e = xmalloc(sizeof(expr_t));
151 e->type = type;
152 e->ref = expr;
153 e->u.lval = 0;
154 e->is_const = FALSE;
155 /* check for compile-time optimization */
156 if (expr->is_const)
157 {
158 e->is_const = TRUE;
159 switch (type)
160 {
161 case EXPR_LOGNOT:
162 e->cval = !expr->cval;
163 break;
164 case EXPR_POS:
165 e->cval = +expr->cval;
166 break;
167 case EXPR_NEG:
168 e->cval = -expr->cval;
169 break;
170 case EXPR_NOT:
171 e->cval = ~expr->cval;
172 break;
173 default:
174 e->is_const = FALSE;
175 break;
176 }
177 }
178 return e;
179 }
180
181 expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2)
182 {
183 expr_t *e;
184 e = xmalloc(sizeof(expr_t));
185 e->type = type;
186 e->ref = expr1;
187 e->u.ext = expr2;
188 e->is_const = FALSE;
189 /* check for compile-time optimization */
190 if (expr1->is_const && expr2->is_const)
191 {
192 e->is_const = TRUE;
193 switch (type)
194 {
195 case EXPR_ADD:
196 e->cval = expr1->cval + expr2->cval;
197 break;
198 case EXPR_SUB:
199 e->cval = expr1->cval - expr2->cval;
200 break;
201 case EXPR_MOD:
202 if (expr2->cval == 0)
203 {
204 error_loc("divide by zero in expression\n");
205 e->cval = 0;
206 }
207 else
208 e->cval = expr1->cval % expr2->cval;
209 break;
210 case EXPR_MUL:
211 e->cval = expr1->cval * expr2->cval;
212 break;
213 case EXPR_DIV:
214 if (expr2->cval == 0)
215 {
216 error_loc("divide by zero in expression\n");
217 e->cval = 0;
218 }
219 else
220 e->cval = expr1->cval / expr2->cval;
221 break;
222 case EXPR_OR:
223 e->cval = expr1->cval | expr2->cval;
224 break;
225 case EXPR_AND:
226 e->cval = expr1->cval & expr2->cval;
227 break;
228 case EXPR_SHL:
229 e->cval = expr1->cval << expr2->cval;
230 break;
231 case EXPR_SHR:
232 e->cval = expr1->cval >> expr2->cval;
233 break;
234 case EXPR_LOGOR:
235 e->cval = expr1->cval || expr2->cval;
236 break;
237 case EXPR_LOGAND:
238 e->cval = expr1->cval && expr2->cval;
239 break;
240 case EXPR_XOR:
241 e->cval = expr1->cval ^ expr2->cval;
242 break;
243 case EXPR_EQUALITY:
244 e->cval = expr1->cval == expr2->cval;
245 break;
246 case EXPR_INEQUALITY:
247 e->cval = expr1->cval != expr2->cval;
248 break;
249 case EXPR_GTR:
250 e->cval = expr1->cval > expr2->cval;
251 break;
252 case EXPR_LESS:
253 e->cval = expr1->cval < expr2->cval;
254 break;
255 case EXPR_GTREQL:
256 e->cval = expr1->cval >= expr2->cval;
257 break;
258 case EXPR_LESSEQL:
259 e->cval = expr1->cval <= expr2->cval;
260 break;
261 default:
262 e->is_const = FALSE;
263 break;
264 }
265 }
266 return e;
267 }
268
269 expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3)
270 {
271 expr_t *e;
272 e = xmalloc(sizeof(expr_t));
273 e->type = type;
274 e->ref = expr1;
275 e->u.ext = expr2;
276 e->ext2 = expr3;
277 e->is_const = FALSE;
278 /* check for compile-time optimization */
279 if (expr1->is_const && expr2->is_const && expr3->is_const)
280 {
281 e->is_const = TRUE;
282 switch (type)
283 {
284 case EXPR_COND:
285 e->cval = expr1->cval ? expr2->cval : expr3->cval;
286 break;
287 default:
288 e->is_const = FALSE;
289 break;
290 }
291 }
292 return e;
293 }
294
295 struct expression_type
296 {
297 int is_variable; /* is the expression resolved to a variable? */
298 int is_temporary; /* should the type be freed? */
299 type_t *type;
300 };
301
302 static int is_integer_type(const type_t *type)
303 {
304 switch (type->type)
305 {
306 case RPC_FC_BYTE:
307 case RPC_FC_CHAR:
308 case RPC_FC_SMALL:
309 case RPC_FC_USMALL:
310 case RPC_FC_WCHAR:
311 case RPC_FC_SHORT:
312 case RPC_FC_USHORT:
313 case RPC_FC_LONG:
314 case RPC_FC_ULONG:
315 case RPC_FC_INT3264:
316 case RPC_FC_UINT3264:
317 case RPC_FC_HYPER:
318 case RPC_FC_ENUM16:
319 case RPC_FC_ENUM32:
320 return TRUE;
321 default:
322 return FALSE;
323 }
324 }
325
326 static void check_scalar_type(const struct expr_loc *expr_loc,
327 const type_t *cont_type, const type_t *type)
328 {
329 if (!cont_type || (!is_integer_type(type) && !is_ptr(type) &&
330 type->type != RPC_FC_FLOAT &&
331 type->type != RPC_FC_DOUBLE))
332 error_loc_info(&expr_loc->v->loc_info, "scalar type required in expression%s%s\n",
333 expr_loc->attr ? " for attribute " : "",
334 expr_loc->attr ? expr_loc->attr : "");
335 }
336
337 static void check_arithmetic_type(const struct expr_loc *expr_loc,
338 const type_t *cont_type, const type_t *type)
339 {
340 if (!cont_type || (!is_integer_type(type) &&
341 type->type != RPC_FC_FLOAT &&
342 type->type != RPC_FC_DOUBLE))
343 error_loc_info(&expr_loc->v->loc_info, "arithmetic type required in expression%s%s\n",
344 expr_loc->attr ? " for attribute " : "",
345 expr_loc->attr ? expr_loc->attr : "");
346 }
347
348 static void check_integer_type(const struct expr_loc *expr_loc,
349 const type_t *cont_type, const type_t *type)
350 {
351 if (!cont_type || !is_integer_type(type))
352 error_loc_info(&expr_loc->v->loc_info, "integer type required in expression%s%s\n",
353 expr_loc->attr ? " for attribute " : "",
354 expr_loc->attr ? expr_loc->attr : "");
355 }
356
357 static type_t *find_identifier(const char *identifier, const type_t *cont_type, int *found_in_cont_type)
358 {
359 type_t *type = NULL;
360 const var_t *field;
361 const var_list_t *fields = NULL;
362
363 *found_in_cont_type = 0;
364
365 if (cont_type && (cont_type->type == RPC_FC_FUNCTION || is_struct(cont_type->type)))
366 fields = cont_type->fields_or_args;
367 else if (cont_type && is_union(cont_type->type))
368 {
369 if (cont_type->type == RPC_FC_ENCAPSULATED_UNION)
370 {
371 const var_t *uv = LIST_ENTRY(list_tail(cont_type->fields_or_args), const var_t, entry);
372 fields = uv->type->fields_or_args;
373 }
374 else
375 fields = cont_type->fields_or_args;
376 }
377
378 if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
379 if (field->name && !strcmp(identifier, field->name))
380 {
381 type = field->type;
382 *found_in_cont_type = 1;
383 break;
384 }
385
386 if (!type)
387 {
388 var_t *const_var = find_const(identifier, 0);
389 if (const_var) type = const_var->type;
390 }
391
392 return type;
393 }
394
395 static struct expression_type resolve_expression(const struct expr_loc *expr_loc,
396 const type_t *cont_type,
397 const expr_t *e)
398 {
399 struct expression_type result;
400 result.is_variable = FALSE;
401 result.is_temporary = FALSE;
402 result.type = NULL;
403 switch (e->type)
404 {
405 case EXPR_VOID:
406 break;
407 case EXPR_HEXNUM:
408 case EXPR_NUM:
409 case EXPR_TRUEFALSE:
410 result.is_variable = FALSE;
411 result.is_temporary = FALSE;
412 result.type = find_type("int", 0);
413 break;
414 case EXPR_STRLIT:
415 result.is_variable = FALSE;
416 result.is_temporary = TRUE;
417 result.type = make_type(RPC_FC_RP, find_type("char", 0));
418 break;
419 case EXPR_WSTRLIT:
420 result.is_variable = FALSE;
421 result.is_temporary = TRUE;
422 result.type = make_type(RPC_FC_RP, find_type("wchar_t", 0));
423 break;
424 case EXPR_DOUBLE:
425 result.is_variable = FALSE;
426 result.is_temporary = FALSE;
427 result.type = find_type("double", 0);
428 break;
429 case EXPR_IDENTIFIER:
430 {
431 int found_in_cont_type;
432 result.is_variable = TRUE;
433 result.is_temporary = FALSE;
434 result.type = find_identifier(e->u.sval, cont_type, &found_in_cont_type);
435 if (!result.type)
436 {
437 error_loc_info(&expr_loc->v->loc_info, "identifier %s cannot be resolved in expression%s%s\n",
438 e->u.sval, expr_loc->attr ? " for attribute " : "",
439 expr_loc->attr ? expr_loc->attr : "");
440 }
441 break;
442 }
443 case EXPR_LOGNOT:
444 result = resolve_expression(expr_loc, cont_type, e->ref);
445 check_scalar_type(expr_loc, cont_type, result.type);
446 result.is_variable = FALSE;
447 result.is_temporary = FALSE;
448 result.type = find_type("int", 0);
449 break;
450 case EXPR_NOT:
451 result = resolve_expression(expr_loc, cont_type, e->ref);
452 check_integer_type(expr_loc, cont_type, result.type);
453 result.is_variable = FALSE;
454 break;
455 case EXPR_POS:
456 case EXPR_NEG:
457 result = resolve_expression(expr_loc, cont_type, e->ref);
458 check_arithmetic_type(expr_loc, cont_type, result.type);
459 result.is_variable = FALSE;
460 break;
461 case EXPR_ADDRESSOF:
462 result = resolve_expression(expr_loc, cont_type, e->ref);
463 if (!result.is_variable)
464 error_loc_info(&expr_loc->v->loc_info, "address-of operator applied to non-variable type in expression%s%s\n",
465 expr_loc->attr ? " for attribute " : "",
466 expr_loc->attr ? expr_loc->attr : "");
467 result.is_variable = FALSE;
468 result.is_temporary = TRUE;
469 result.type = make_type(RPC_FC_RP, result.type);
470 break;
471 case EXPR_PPTR:
472 result = resolve_expression(expr_loc, cont_type, e->ref);
473 if (result.type && is_ptr(result.type))
474 result.type = result.type->ref;
475 else
476 error_loc_info(&expr_loc->v->loc_info, "dereference operator applied to non-pointer type in expression%s%s\n",
477 expr_loc->attr ? " for attribute " : "",
478 expr_loc->attr ? expr_loc->attr : "");
479 break;
480 case EXPR_CAST:
481 result = resolve_expression(expr_loc, cont_type, e->ref);
482 result.type = e->u.tref;
483 break;
484 case EXPR_SIZEOF:
485 result.is_variable = FALSE;
486 result.is_temporary = FALSE;
487 result.type = find_type("int", 0);
488 break;
489 case EXPR_SHL:
490 case EXPR_SHR:
491 case EXPR_MOD:
492 case EXPR_MUL:
493 case EXPR_DIV:
494 case EXPR_ADD:
495 case EXPR_SUB:
496 case EXPR_AND:
497 case EXPR_OR:
498 case EXPR_XOR:
499 {
500 struct expression_type result_right;
501 result = resolve_expression(expr_loc, cont_type, e->ref);
502 result.is_variable = FALSE;
503 result_right = resolve_expression(expr_loc, cont_type, e->u.ext);
504 /* FIXME: these checks aren't strict enough for some of the operators */
505 check_scalar_type(expr_loc, cont_type, result.type);
506 check_scalar_type(expr_loc, cont_type, result_right.type);
507 break;
508 }
509 case EXPR_LOGOR:
510 case EXPR_LOGAND:
511 case EXPR_EQUALITY:
512 case EXPR_INEQUALITY:
513 case EXPR_GTR:
514 case EXPR_LESS:
515 case EXPR_GTREQL:
516 case EXPR_LESSEQL:
517 {
518 struct expression_type result_left, result_right;
519 result_left = resolve_expression(expr_loc, cont_type, e->ref);
520 result_right = resolve_expression(expr_loc, cont_type, e->u.ext);
521 check_scalar_type(expr_loc, cont_type, result_left.type);
522 check_scalar_type(expr_loc, cont_type, result_right.type);
523 result.is_variable = FALSE;
524 result.is_temporary = FALSE;
525 result.type = find_type("int", 0);
526 break;
527 }
528 case EXPR_MEMBER:
529 result = resolve_expression(expr_loc, cont_type, e->ref);
530 if (result.type && (is_struct(result.type->type) || is_union(result.type->type) || result.type->type == RPC_FC_ENUM16 || result.type->type == RPC_FC_ENUM32))
531 result = resolve_expression(expr_loc, result.type, e->u.ext);
532 else
533 error_loc_info(&expr_loc->v->loc_info, "'.' or '->' operator applied to a type that isn't a structure, union or enumeration in expression%s%s\n",
534 expr_loc->attr ? " for attribute " : "",
535 expr_loc->attr ? expr_loc->attr : "");
536 break;
537 case EXPR_COND:
538 {
539 struct expression_type result_first, result_second, result_third;
540 result_first = resolve_expression(expr_loc, cont_type, e->ref);
541 check_scalar_type(expr_loc, cont_type, result_first.type);
542 result_second = resolve_expression(expr_loc, cont_type, e->u.ext);
543 result_third = resolve_expression(expr_loc, cont_type, e->ext2);
544 /* FIXME: determine the correct return type */
545 result = result_second;
546 result.is_variable = FALSE;
547 break;
548 }
549 case EXPR_ARRAY:
550 result = resolve_expression(expr_loc, cont_type, e->ref);
551 if (result.type && is_array(result.type))
552 {
553 struct expression_type index_result;
554 result.type = result.type->ref;
555 index_result = resolve_expression(expr_loc, cont_type /* FIXME */, e->u.ext);
556 if (!index_result.type || !is_integer_type(index_result.type))
557 error_loc_info(&expr_loc->v->loc_info, "array subscript not of integral type in expression%s%s\n",
558 expr_loc->attr ? " for attribute " : "",
559 expr_loc->attr ? expr_loc->attr : "");
560 }
561 else
562 error_loc_info(&expr_loc->v->loc_info, "array subscript operator applied to non-array type in expression%s%s\n",
563 expr_loc->attr ? " for attribute " : "",
564 expr_loc->attr ? expr_loc->attr : "");
565 break;
566 }
567 return result;
568 }
569
570 const type_t *expr_resolve_type(const struct expr_loc *expr_loc, const type_t *cont_type, const expr_t *expr)
571 {
572 struct expression_type expr_type;
573 expr_type = resolve_expression(expr_loc, cont_type, expr);
574 return expr_type.type;
575 }
576
577 void write_expr(FILE *h, const expr_t *e, int brackets,
578 int toplevel, const char *toplevel_prefix,
579 const type_t *cont_type)
580 {
581 switch (e->type)
582 {
583 case EXPR_VOID:
584 break;
585 case EXPR_NUM:
586 fprintf(h, "%lu", e->u.lval);
587 break;
588 case EXPR_HEXNUM:
589 fprintf(h, "0x%lx", e->u.lval);
590 break;
591 case EXPR_DOUBLE:
592 fprintf(h, "%#.15g", e->u.dval);
593 break;
594 case EXPR_TRUEFALSE:
595 if (e->u.lval == 0)
596 fprintf(h, "FALSE");
597 else
598 fprintf(h, "TRUE");
599 break;
600 case EXPR_IDENTIFIER:
601 if (toplevel && toplevel_prefix && cont_type)
602 {
603 int found_in_cont_type;
604 find_identifier(e->u.sval, cont_type, &found_in_cont_type);
605 if (found_in_cont_type) fprintf(h, "%s", toplevel_prefix);
606 }
607 fprintf(h, "%s", e->u.sval);
608 break;
609 case EXPR_STRLIT:
610 fprintf(h, "\"%s\"", e->u.sval);
611 break;
612 case EXPR_WSTRLIT:
613 fprintf(h, "L\"%s\"", e->u.sval);
614 break;
615 case EXPR_LOGNOT:
616 fprintf(h, "!");
617 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
618 break;
619 case EXPR_NOT:
620 fprintf(h, "~");
621 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
622 break;
623 case EXPR_POS:
624 fprintf(h, "+");
625 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
626 break;
627 case EXPR_NEG:
628 fprintf(h, "-");
629 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
630 break;
631 case EXPR_ADDRESSOF:
632 fprintf(h, "&");
633 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
634 break;
635 case EXPR_PPTR:
636 fprintf(h, "*");
637 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
638 break;
639 case EXPR_CAST:
640 fprintf(h, "(");
641 write_type_decl(h, e->u.tref, NULL);
642 fprintf(h, ")");
643 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
644 break;
645 case EXPR_SIZEOF:
646 fprintf(h, "sizeof(");
647 write_type_decl(h, e->u.tref, NULL);
648 fprintf(h, ")");
649 break;
650 case EXPR_SHL:
651 case EXPR_SHR:
652 case EXPR_MOD:
653 case EXPR_MUL:
654 case EXPR_DIV:
655 case EXPR_ADD:
656 case EXPR_SUB:
657 case EXPR_AND:
658 case EXPR_OR:
659 case EXPR_LOGOR:
660 case EXPR_LOGAND:
661 case EXPR_XOR:
662 case EXPR_EQUALITY:
663 case EXPR_INEQUALITY:
664 case EXPR_GTR:
665 case EXPR_LESS:
666 case EXPR_GTREQL:
667 case EXPR_LESSEQL:
668 if (brackets) fprintf(h, "(");
669 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
670 switch (e->type)
671 {
672 case EXPR_SHL: fprintf(h, " << "); break;
673 case EXPR_SHR: fprintf(h, " >> "); break;
674 case EXPR_MOD: fprintf(h, " %% "); break;
675 case EXPR_MUL: fprintf(h, " * "); break;
676 case EXPR_DIV: fprintf(h, " / "); break;
677 case EXPR_ADD: fprintf(h, " + "); break;
678 case EXPR_SUB: fprintf(h, " - "); break;
679 case EXPR_AND: fprintf(h, " & "); break;
680 case EXPR_OR: fprintf(h, " | "); break;
681 case EXPR_LOGOR: fprintf(h, " || "); break;
682 case EXPR_LOGAND: fprintf(h, " && "); break;
683 case EXPR_XOR: fprintf(h, " ^ "); break;
684 case EXPR_EQUALITY: fprintf(h, " == "); break;
685 case EXPR_INEQUALITY: fprintf(h, " != "); break;
686 case EXPR_GTR: fprintf(h, " > "); break;
687 case EXPR_LESS: fprintf(h, " < "); break;
688 case EXPR_GTREQL: fprintf(h, " >= "); break;
689 case EXPR_LESSEQL: fprintf(h, " <= "); break;
690 default: break;
691 }
692 write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type);
693 if (brackets) fprintf(h, ")");
694 break;
695 case EXPR_MEMBER:
696 if (brackets) fprintf(h, "(");
697 if (e->ref->type == EXPR_PPTR)
698 {
699 write_expr(h, e->ref->ref, 1, toplevel, toplevel_prefix, cont_type);
700 fprintf(h, "->");
701 }
702 else
703 {
704 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
705 fprintf(h, ".");
706 }
707 write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type);
708 if (brackets) fprintf(h, ")");
709 break;
710 case EXPR_COND:
711 if (brackets) fprintf(h, "(");
712 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
713 fprintf(h, " ? ");
714 write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type);
715 fprintf(h, " : ");
716 write_expr(h, e->ext2, 1, toplevel, toplevel_prefix, cont_type);
717 if (brackets) fprintf(h, ")");
718 break;
719 case EXPR_ARRAY:
720 if (brackets) fprintf(h, "(");
721 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type);
722 fprintf(h, "[");
723 write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type);
724 fprintf(h, "]");
725 if (brackets) fprintf(h, ")");
726 break;
727 }
728 }
729
730 /* This is actually fairly involved to implement precisely, due to the
731 effects attributes may have and things like that. Right now this is
732 only used for optimization, so just check for a very small set of
733 criteria that guarantee the types are equivalent; assume every thing
734 else is different. */
735 static int compare_type(const type_t *a, const type_t *b)
736 {
737 if (a == b
738 || (a->name
739 && b->name
740 && strcmp(a->name, b->name) == 0))
741 return 0;
742 /* Ordering doesn't need to be implemented yet. */
743 return 1;
744 }
745
746 int compare_expr(const expr_t *a, const expr_t *b)
747 {
748 int ret;
749
750 if (a->type != b->type)
751 return a->type - b->type;
752
753 switch (a->type)
754 {
755 case EXPR_NUM:
756 case EXPR_HEXNUM:
757 case EXPR_TRUEFALSE:
758 return a->u.lval - b->u.lval;
759 case EXPR_DOUBLE:
760 return a->u.dval - b->u.dval;
761 case EXPR_IDENTIFIER:
762 case EXPR_STRLIT:
763 case EXPR_WSTRLIT:
764 return strcmp(a->u.sval, b->u.sval);
765 case EXPR_COND:
766 ret = compare_expr(a->ref, b->ref);
767 if (ret != 0)
768 return ret;
769 ret = compare_expr(a->u.ext, b->u.ext);
770 if (ret != 0)
771 return ret;
772 return compare_expr(a->ext2, b->ext2);
773 case EXPR_OR:
774 case EXPR_AND:
775 case EXPR_ADD:
776 case EXPR_SUB:
777 case EXPR_MOD:
778 case EXPR_MUL:
779 case EXPR_DIV:
780 case EXPR_SHL:
781 case EXPR_SHR:
782 case EXPR_MEMBER:
783 case EXPR_ARRAY:
784 case EXPR_LOGOR:
785 case EXPR_LOGAND:
786 case EXPR_XOR:
787 case EXPR_EQUALITY:
788 case EXPR_INEQUALITY:
789 case EXPR_GTR:
790 case EXPR_LESS:
791 case EXPR_GTREQL:
792 case EXPR_LESSEQL:
793 ret = compare_expr(a->ref, b->ref);
794 if (ret != 0)
795 return ret;
796 return compare_expr(a->u.ext, b->u.ext);
797 case EXPR_CAST:
798 ret = compare_type(a->u.tref, b->u.tref);
799 if (ret != 0)
800 return ret;
801 /* Fall through. */
802 case EXPR_NOT:
803 case EXPR_NEG:
804 case EXPR_PPTR:
805 case EXPR_ADDRESSOF:
806 case EXPR_LOGNOT:
807 case EXPR_POS:
808 return compare_expr(a->ref, b->ref);
809 case EXPR_SIZEOF:
810 return compare_type(a->u.tref, b->u.tref);
811 case EXPR_VOID:
812 return 0;
813 }
814 return -1;
815 }