push 8724397e7ede0f147b6e05994a72142d44d4fecc
[wine/hacks.git] / tools / widl / expr.c
blob58d7a5b60ca17af84b038cca9e73bb719dba2dbe
1 /*
2 * Expression Abstract Syntax Tree Functions
4 * Copyright 2002 Ove Kaaven
5 * Copyright 2006-2008 Robert Shearman
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.
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.
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
22 #include "config.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <assert.h>
28 #include <ctype.h>
29 #include <string.h>
31 #include "widl.h"
32 #include "utils.h"
33 #include "expr.h"
34 #include "header.h"
35 #include "typetree.h"
36 #include "typegen.h"
38 static int is_integer_type(const type_t *type);
39 static int is_float_type(const type_t *type);
41 expr_t *make_expr(enum expr_type type)
43 expr_t *e = xmalloc(sizeof(expr_t));
44 e->type = type;
45 e->ref = NULL;
46 e->u.lval = 0;
47 e->is_const = FALSE;
48 e->cval = 0;
49 return e;
52 expr_t *make_exprl(enum expr_type type, long val)
54 expr_t *e = xmalloc(sizeof(expr_t));
55 e->type = type;
56 e->ref = NULL;
57 e->u.lval = val;
58 e->is_const = FALSE;
59 /* check for numeric constant */
60 if (type == EXPR_NUM || type == EXPR_HEXNUM || type == EXPR_TRUEFALSE)
62 /* make sure true/false value is valid */
63 assert(type != EXPR_TRUEFALSE || val == 0 || val == 1);
64 e->is_const = TRUE;
65 e->cval = val;
67 return e;
70 expr_t *make_exprd(enum expr_type type, double val)
72 expr_t *e = xmalloc(sizeof(expr_t));
73 e->type = type;
74 e->ref = NULL;
75 e->u.dval = val;
76 e->is_const = TRUE;
77 e->cval = val;
78 return e;
81 expr_t *make_exprs(enum expr_type type, char *val)
83 expr_t *e;
84 e = xmalloc(sizeof(expr_t));
85 e->type = type;
86 e->ref = NULL;
87 e->u.sval = val;
88 e->is_const = FALSE;
89 /* check for predefined constants */
90 if (type == EXPR_IDENTIFIER)
92 var_t *c = find_const(val, 0);
93 if (c)
95 e->u.sval = c->name;
96 free(val);
97 e->is_const = TRUE;
98 e->cval = c->eval->cval;
101 return e;
104 expr_t *make_exprt(enum expr_type type, type_t *tref, expr_t *expr)
106 expr_t *e;
107 e = xmalloc(sizeof(expr_t));
108 e->type = type;
109 e->ref = expr;
110 e->u.tref = tref;
111 e->is_const = FALSE;
112 if (type == EXPR_SIZEOF)
114 /* only do this for types that should be the same on all platforms */
115 if (is_integer_type(tref) || is_float_type(tref))
117 unsigned int align = 0;
118 e->is_const = TRUE;
119 e->cval = type_memsize(tref, &align);
122 /* check for cast of constant expression */
123 if (type == EXPR_CAST && expr->is_const)
125 e->is_const = TRUE;
126 e->cval = expr->cval;
128 return e;
131 expr_t *make_expr1(enum expr_type type, expr_t *expr)
133 expr_t *e;
134 e = xmalloc(sizeof(expr_t));
135 e->type = type;
136 e->ref = expr;
137 e->u.lval = 0;
138 e->is_const = FALSE;
139 /* check for compile-time optimization */
140 if (expr->is_const)
142 e->is_const = TRUE;
143 switch (type)
145 case EXPR_LOGNOT:
146 e->cval = !expr->cval;
147 break;
148 case EXPR_POS:
149 e->cval = +expr->cval;
150 break;
151 case EXPR_NEG:
152 e->cval = -expr->cval;
153 break;
154 case EXPR_NOT:
155 e->cval = ~expr->cval;
156 break;
157 default:
158 e->is_const = FALSE;
159 break;
162 return e;
165 expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2)
167 expr_t *e;
168 e = xmalloc(sizeof(expr_t));
169 e->type = type;
170 e->ref = expr1;
171 e->u.ext = expr2;
172 e->is_const = FALSE;
173 /* check for compile-time optimization */
174 if (expr1->is_const && expr2->is_const)
176 e->is_const = TRUE;
177 switch (type)
179 case EXPR_ADD:
180 e->cval = expr1->cval + expr2->cval;
181 break;
182 case EXPR_SUB:
183 e->cval = expr1->cval - expr2->cval;
184 break;
185 case EXPR_MOD:
186 if (expr2->cval == 0)
188 error_loc("divide by zero in expression\n");
189 e->cval = 0;
191 else
192 e->cval = expr1->cval % expr2->cval;
193 break;
194 case EXPR_MUL:
195 e->cval = expr1->cval * expr2->cval;
196 break;
197 case EXPR_DIV:
198 if (expr2->cval == 0)
200 error_loc("divide by zero in expression\n");
201 e->cval = 0;
203 else
204 e->cval = expr1->cval / expr2->cval;
205 break;
206 case EXPR_OR:
207 e->cval = expr1->cval | expr2->cval;
208 break;
209 case EXPR_AND:
210 e->cval = expr1->cval & expr2->cval;
211 break;
212 case EXPR_SHL:
213 e->cval = expr1->cval << expr2->cval;
214 break;
215 case EXPR_SHR:
216 e->cval = expr1->cval >> expr2->cval;
217 break;
218 case EXPR_LOGOR:
219 e->cval = expr1->cval || expr2->cval;
220 break;
221 case EXPR_LOGAND:
222 e->cval = expr1->cval && expr2->cval;
223 break;
224 case EXPR_XOR:
225 e->cval = expr1->cval ^ expr2->cval;
226 break;
227 case EXPR_EQUALITY:
228 e->cval = expr1->cval == expr2->cval;
229 break;
230 case EXPR_INEQUALITY:
231 e->cval = expr1->cval != expr2->cval;
232 break;
233 case EXPR_GTR:
234 e->cval = expr1->cval > expr2->cval;
235 break;
236 case EXPR_LESS:
237 e->cval = expr1->cval < expr2->cval;
238 break;
239 case EXPR_GTREQL:
240 e->cval = expr1->cval >= expr2->cval;
241 break;
242 case EXPR_LESSEQL:
243 e->cval = expr1->cval <= expr2->cval;
244 break;
245 default:
246 e->is_const = FALSE;
247 break;
250 return e;
253 expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3)
255 expr_t *e;
256 e = xmalloc(sizeof(expr_t));
257 e->type = type;
258 e->ref = expr1;
259 e->u.ext = expr2;
260 e->ext2 = expr3;
261 e->is_const = FALSE;
262 /* check for compile-time optimization */
263 if (expr1->is_const && expr2->is_const && expr3->is_const)
265 e->is_const = TRUE;
266 switch (type)
268 case EXPR_COND:
269 e->cval = expr1->cval ? expr2->cval : expr3->cval;
270 break;
271 default:
272 e->is_const = FALSE;
273 break;
276 return e;
279 struct expression_type
281 int is_variable; /* is the expression resolved to a variable? */
282 int is_temporary; /* should the type be freed? */
283 type_t *type;
286 static int is_integer_type(const type_t *type)
288 switch (type_get_type(type))
290 case TYPE_ENUM:
291 return TRUE;
292 case TYPE_BASIC:
293 switch (type_basic_get_fc(type))
295 case RPC_FC_BYTE:
296 case RPC_FC_CHAR:
297 case RPC_FC_SMALL:
298 case RPC_FC_USMALL:
299 case RPC_FC_WCHAR:
300 case RPC_FC_SHORT:
301 case RPC_FC_USHORT:
302 case RPC_FC_LONG:
303 case RPC_FC_ULONG:
304 case RPC_FC_INT3264:
305 case RPC_FC_UINT3264:
306 case RPC_FC_HYPER:
307 return TRUE;
308 default:
309 return FALSE;
311 default:
312 return FALSE;
316 static int is_float_type(const type_t *type)
318 return (type_get_type(type) == TYPE_BASIC &&
319 (type_basic_get_fc(type) == RPC_FC_FLOAT ||
320 type_basic_get_fc(type) == RPC_FC_DOUBLE));
323 static void check_scalar_type(const struct expr_loc *expr_loc,
324 const type_t *cont_type, const type_t *type)
326 if (!cont_type || (!is_integer_type(type) && !is_ptr(type) &&
327 !is_float_type(type)))
328 error_loc_info(&expr_loc->v->loc_info, "scalar type required in expression%s%s\n",
329 expr_loc->attr ? " for attribute " : "",
330 expr_loc->attr ? expr_loc->attr : "");
333 static void check_arithmetic_type(const struct expr_loc *expr_loc,
334 const type_t *cont_type, const type_t *type)
336 if (!cont_type || (!is_integer_type(type) && !is_float_type(type)))
337 error_loc_info(&expr_loc->v->loc_info, "arithmetic type required in expression%s%s\n",
338 expr_loc->attr ? " for attribute " : "",
339 expr_loc->attr ? expr_loc->attr : "");
342 static void check_integer_type(const struct expr_loc *expr_loc,
343 const type_t *cont_type, const type_t *type)
345 if (!cont_type || !is_integer_type(type))
346 error_loc_info(&expr_loc->v->loc_info, "integer type required in expression%s%s\n",
347 expr_loc->attr ? " for attribute " : "",
348 expr_loc->attr ? expr_loc->attr : "");
351 static type_t *find_identifier(const char *identifier, const type_t *cont_type, int *found_in_cont_type)
353 type_t *type = NULL;
354 const var_t *field;
355 const var_list_t *fields = NULL;
357 *found_in_cont_type = 0;
359 if (cont_type)
361 switch (type_get_type(cont_type))
363 case TYPE_FUNCTION:
364 fields = type_function_get_args(cont_type);
365 break;
366 case TYPE_STRUCT:
367 fields = type_struct_get_fields(cont_type);
368 break;
369 case TYPE_UNION:
370 case TYPE_ENCAPSULATED_UNION:
371 fields = type_union_get_cases(cont_type);
372 break;
373 case TYPE_VOID:
374 case TYPE_BASIC:
375 case TYPE_ENUM:
376 case TYPE_MODULE:
377 case TYPE_COCLASS:
378 case TYPE_INTERFACE:
379 case TYPE_POINTER:
380 case TYPE_ARRAY:
381 /* nothing to do */
382 break;
383 case TYPE_ALIAS:
384 /* shouldn't get here because of using type_get_type above */
385 assert(0);
386 break;
390 if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
391 if (field->name && !strcmp(identifier, field->name))
393 type = field->type;
394 *found_in_cont_type = 1;
395 break;
398 if (!type)
400 var_t *const_var = find_const(identifier, 0);
401 if (const_var) type = const_var->type;
404 return type;
407 static int is_valid_member_operand(const type_t *type)
409 switch (type_get_type(type))
411 case TYPE_STRUCT:
412 case TYPE_UNION:
413 case TYPE_ENUM:
414 return TRUE;
415 default:
416 return FALSE;
420 static struct expression_type resolve_expression(const struct expr_loc *expr_loc,
421 const type_t *cont_type,
422 const expr_t *e)
424 struct expression_type result;
425 result.is_variable = FALSE;
426 result.is_temporary = FALSE;
427 result.type = NULL;
428 switch (e->type)
430 case EXPR_VOID:
431 break;
432 case EXPR_HEXNUM:
433 case EXPR_NUM:
434 case EXPR_TRUEFALSE:
435 result.is_variable = FALSE;
436 result.is_temporary = FALSE;
437 result.type = find_type("int", 0);
438 break;
439 case EXPR_STRLIT:
440 result.is_variable = FALSE;
441 result.is_temporary = TRUE;
442 result.type = make_type(RPC_FC_RP, find_type("char", 0));
443 break;
444 case EXPR_WSTRLIT:
445 result.is_variable = FALSE;
446 result.is_temporary = TRUE;
447 result.type = make_type(RPC_FC_RP, find_type("wchar_t", 0));
448 break;
449 case EXPR_DOUBLE:
450 result.is_variable = FALSE;
451 result.is_temporary = FALSE;
452 result.type = find_type("double", 0);
453 break;
454 case EXPR_IDENTIFIER:
456 int found_in_cont_type;
457 result.is_variable = TRUE;
458 result.is_temporary = FALSE;
459 result.type = find_identifier(e->u.sval, cont_type, &found_in_cont_type);
460 if (!result.type)
462 error_loc_info(&expr_loc->v->loc_info, "identifier %s cannot be resolved in expression%s%s\n",
463 e->u.sval, expr_loc->attr ? " for attribute " : "",
464 expr_loc->attr ? expr_loc->attr : "");
466 break;
468 case EXPR_LOGNOT:
469 result = resolve_expression(expr_loc, cont_type, e->ref);
470 check_scalar_type(expr_loc, cont_type, result.type);
471 result.is_variable = FALSE;
472 result.is_temporary = FALSE;
473 result.type = find_type("int", 0);
474 break;
475 case EXPR_NOT:
476 result = resolve_expression(expr_loc, cont_type, e->ref);
477 check_integer_type(expr_loc, cont_type, result.type);
478 result.is_variable = FALSE;
479 break;
480 case EXPR_POS:
481 case EXPR_NEG:
482 result = resolve_expression(expr_loc, cont_type, e->ref);
483 check_arithmetic_type(expr_loc, cont_type, result.type);
484 result.is_variable = FALSE;
485 break;
486 case EXPR_ADDRESSOF:
487 result = resolve_expression(expr_loc, cont_type, e->ref);
488 if (!result.is_variable)
489 error_loc_info(&expr_loc->v->loc_info, "address-of operator applied to non-variable type in expression%s%s\n",
490 expr_loc->attr ? " for attribute " : "",
491 expr_loc->attr ? expr_loc->attr : "");
492 result.is_variable = FALSE;
493 result.is_temporary = TRUE;
494 result.type = make_type(RPC_FC_RP, result.type);
495 break;
496 case EXPR_PPTR:
497 result = resolve_expression(expr_loc, cont_type, e->ref);
498 if (result.type && is_ptr(result.type))
499 result.type = type_pointer_get_ref(result.type);
500 else if(result.type && is_array(result.type)
501 && !result.type->declarray)
502 result.type = type_array_get_element(result.type);
503 else
504 error_loc_info(&expr_loc->v->loc_info, "dereference operator applied to non-pointer type in expression%s%s\n",
505 expr_loc->attr ? " for attribute " : "",
506 expr_loc->attr ? expr_loc->attr : "");
507 break;
508 case EXPR_CAST:
509 result = resolve_expression(expr_loc, cont_type, e->ref);
510 result.type = e->u.tref;
511 break;
512 case EXPR_SIZEOF:
513 result.is_variable = FALSE;
514 result.is_temporary = FALSE;
515 result.type = find_type("int", 0);
516 break;
517 case EXPR_SHL:
518 case EXPR_SHR:
519 case EXPR_MOD:
520 case EXPR_MUL:
521 case EXPR_DIV:
522 case EXPR_ADD:
523 case EXPR_SUB:
524 case EXPR_AND:
525 case EXPR_OR:
526 case EXPR_XOR:
528 struct expression_type result_right;
529 result = resolve_expression(expr_loc, cont_type, e->ref);
530 result.is_variable = FALSE;
531 result_right = resolve_expression(expr_loc, cont_type, e->u.ext);
532 /* FIXME: these checks aren't strict enough for some of the operators */
533 check_scalar_type(expr_loc, cont_type, result.type);
534 check_scalar_type(expr_loc, cont_type, result_right.type);
535 break;
537 case EXPR_LOGOR:
538 case EXPR_LOGAND:
539 case EXPR_EQUALITY:
540 case EXPR_INEQUALITY:
541 case EXPR_GTR:
542 case EXPR_LESS:
543 case EXPR_GTREQL:
544 case EXPR_LESSEQL:
546 struct expression_type result_left, result_right;
547 result_left = resolve_expression(expr_loc, cont_type, e->ref);
548 result_right = resolve_expression(expr_loc, cont_type, e->u.ext);
549 check_scalar_type(expr_loc, cont_type, result_left.type);
550 check_scalar_type(expr_loc, cont_type, result_right.type);
551 result.is_variable = FALSE;
552 result.is_temporary = FALSE;
553 result.type = find_type("int", 0);
554 break;
556 case EXPR_MEMBER:
557 result = resolve_expression(expr_loc, cont_type, e->ref);
558 if (result.type && is_valid_member_operand(result.type))
559 result = resolve_expression(expr_loc, result.type, e->u.ext);
560 else
561 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",
562 expr_loc->attr ? " for attribute " : "",
563 expr_loc->attr ? expr_loc->attr : "");
564 break;
565 case EXPR_COND:
567 struct expression_type result_first, result_second, result_third;
568 result_first = resolve_expression(expr_loc, cont_type, e->ref);
569 check_scalar_type(expr_loc, cont_type, result_first.type);
570 result_second = resolve_expression(expr_loc, cont_type, e->u.ext);
571 result_third = resolve_expression(expr_loc, cont_type, e->ext2);
572 /* FIXME: determine the correct return type */
573 result = result_second;
574 result.is_variable = FALSE;
575 break;
577 case EXPR_ARRAY:
578 result = resolve_expression(expr_loc, cont_type, e->ref);
579 if (result.type && is_array(result.type))
581 struct expression_type index_result;
582 result.type = type_array_get_element(result.type);
583 index_result = resolve_expression(expr_loc, cont_type /* FIXME */, e->u.ext);
584 if (!index_result.type || !is_integer_type(index_result.type))
585 error_loc_info(&expr_loc->v->loc_info, "array subscript not of integral type in expression%s%s\n",
586 expr_loc->attr ? " for attribute " : "",
587 expr_loc->attr ? expr_loc->attr : "");
589 else
590 error_loc_info(&expr_loc->v->loc_info, "array subscript operator applied to non-array type in expression%s%s\n",
591 expr_loc->attr ? " for attribute " : "",
592 expr_loc->attr ? expr_loc->attr : "");
593 break;
595 return result;
598 const type_t *expr_resolve_type(const struct expr_loc *expr_loc, const type_t *cont_type, const expr_t *expr)
600 struct expression_type expr_type;
601 expr_type = resolve_expression(expr_loc, cont_type, expr);
602 return expr_type.type;
605 void write_expr(FILE *h, const expr_t *e, int brackets,
606 int toplevel, const char *toplevel_prefix,
607 const type_t *cont_type, const char *local_var_prefix)
609 switch (e->type)
611 case EXPR_VOID:
612 break;
613 case EXPR_NUM:
614 fprintf(h, "%lu", e->u.lval);
615 break;
616 case EXPR_HEXNUM:
617 fprintf(h, "0x%lx", e->u.lval);
618 break;
619 case EXPR_DOUBLE:
620 fprintf(h, "%#.15g", e->u.dval);
621 break;
622 case EXPR_TRUEFALSE:
623 if (e->u.lval == 0)
624 fprintf(h, "FALSE");
625 else
626 fprintf(h, "TRUE");
627 break;
628 case EXPR_IDENTIFIER:
629 if (toplevel && toplevel_prefix && cont_type)
631 int found_in_cont_type;
632 find_identifier(e->u.sval, cont_type, &found_in_cont_type);
633 if (found_in_cont_type)
635 fprintf(h, "%s%s", toplevel_prefix, e->u.sval);
636 break;
639 fprintf(h, "%s%s", local_var_prefix, e->u.sval);
640 break;
641 case EXPR_STRLIT:
642 fprintf(h, "\"%s\"", e->u.sval);
643 break;
644 case EXPR_WSTRLIT:
645 fprintf(h, "L\"%s\"", e->u.sval);
646 break;
647 case EXPR_LOGNOT:
648 fprintf(h, "!");
649 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
650 break;
651 case EXPR_NOT:
652 fprintf(h, "~");
653 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
654 break;
655 case EXPR_POS:
656 fprintf(h, "+");
657 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
658 break;
659 case EXPR_NEG:
660 fprintf(h, "-");
661 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
662 break;
663 case EXPR_ADDRESSOF:
664 fprintf(h, "&");
665 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
666 break;
667 case EXPR_PPTR:
668 fprintf(h, "*");
669 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
670 break;
671 case EXPR_CAST:
672 fprintf(h, "(");
673 write_type_decl(h, e->u.tref, NULL);
674 fprintf(h, ")");
675 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
676 break;
677 case EXPR_SIZEOF:
678 fprintf(h, "sizeof(");
679 write_type_decl(h, e->u.tref, NULL);
680 fprintf(h, ")");
681 break;
682 case EXPR_SHL:
683 case EXPR_SHR:
684 case EXPR_MOD:
685 case EXPR_MUL:
686 case EXPR_DIV:
687 case EXPR_ADD:
688 case EXPR_SUB:
689 case EXPR_AND:
690 case EXPR_OR:
691 case EXPR_LOGOR:
692 case EXPR_LOGAND:
693 case EXPR_XOR:
694 case EXPR_EQUALITY:
695 case EXPR_INEQUALITY:
696 case EXPR_GTR:
697 case EXPR_LESS:
698 case EXPR_GTREQL:
699 case EXPR_LESSEQL:
700 if (brackets) fprintf(h, "(");
701 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
702 switch (e->type)
704 case EXPR_SHL: fprintf(h, " << "); break;
705 case EXPR_SHR: fprintf(h, " >> "); break;
706 case EXPR_MOD: fprintf(h, " %% "); break;
707 case EXPR_MUL: fprintf(h, " * "); break;
708 case EXPR_DIV: fprintf(h, " / "); break;
709 case EXPR_ADD: fprintf(h, " + "); break;
710 case EXPR_SUB: fprintf(h, " - "); break;
711 case EXPR_AND: fprintf(h, " & "); break;
712 case EXPR_OR: fprintf(h, " | "); break;
713 case EXPR_LOGOR: fprintf(h, " || "); break;
714 case EXPR_LOGAND: fprintf(h, " && "); break;
715 case EXPR_XOR: fprintf(h, " ^ "); break;
716 case EXPR_EQUALITY: fprintf(h, " == "); break;
717 case EXPR_INEQUALITY: fprintf(h, " != "); break;
718 case EXPR_GTR: fprintf(h, " > "); break;
719 case EXPR_LESS: fprintf(h, " < "); break;
720 case EXPR_GTREQL: fprintf(h, " >= "); break;
721 case EXPR_LESSEQL: fprintf(h, " <= "); break;
722 default: break;
724 write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
725 if (brackets) fprintf(h, ")");
726 break;
727 case EXPR_MEMBER:
728 if (brackets) fprintf(h, "(");
729 if (e->ref->type == EXPR_PPTR)
731 write_expr(h, e->ref->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
732 fprintf(h, "->");
734 else
736 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
737 fprintf(h, ".");
739 write_expr(h, e->u.ext, 1, 0, toplevel_prefix, cont_type, "");
740 if (brackets) fprintf(h, ")");
741 break;
742 case EXPR_COND:
743 if (brackets) fprintf(h, "(");
744 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
745 fprintf(h, " ? ");
746 write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
747 fprintf(h, " : ");
748 write_expr(h, e->ext2, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
749 if (brackets) fprintf(h, ")");
750 break;
751 case EXPR_ARRAY:
752 if (brackets) fprintf(h, "(");
753 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
754 fprintf(h, "[");
755 write_expr(h, e->u.ext, 1, 1, toplevel_prefix, cont_type, local_var_prefix);
756 fprintf(h, "]");
757 if (brackets) fprintf(h, ")");
758 break;
762 /* This is actually fairly involved to implement precisely, due to the
763 effects attributes may have and things like that. Right now this is
764 only used for optimization, so just check for a very small set of
765 criteria that guarantee the types are equivalent; assume every thing
766 else is different. */
767 static int compare_type(const type_t *a, const type_t *b)
769 if (a == b
770 || (a->name
771 && b->name
772 && strcmp(a->name, b->name) == 0))
773 return 0;
774 /* Ordering doesn't need to be implemented yet. */
775 return 1;
778 int compare_expr(const expr_t *a, const expr_t *b)
780 int ret;
782 if (a->type != b->type)
783 return a->type - b->type;
785 switch (a->type)
787 case EXPR_NUM:
788 case EXPR_HEXNUM:
789 case EXPR_TRUEFALSE:
790 return a->u.lval - b->u.lval;
791 case EXPR_DOUBLE:
792 return a->u.dval - b->u.dval;
793 case EXPR_IDENTIFIER:
794 case EXPR_STRLIT:
795 case EXPR_WSTRLIT:
796 return strcmp(a->u.sval, b->u.sval);
797 case EXPR_COND:
798 ret = compare_expr(a->ref, b->ref);
799 if (ret != 0)
800 return ret;
801 ret = compare_expr(a->u.ext, b->u.ext);
802 if (ret != 0)
803 return ret;
804 return compare_expr(a->ext2, b->ext2);
805 case EXPR_OR:
806 case EXPR_AND:
807 case EXPR_ADD:
808 case EXPR_SUB:
809 case EXPR_MOD:
810 case EXPR_MUL:
811 case EXPR_DIV:
812 case EXPR_SHL:
813 case EXPR_SHR:
814 case EXPR_MEMBER:
815 case EXPR_ARRAY:
816 case EXPR_LOGOR:
817 case EXPR_LOGAND:
818 case EXPR_XOR:
819 case EXPR_EQUALITY:
820 case EXPR_INEQUALITY:
821 case EXPR_GTR:
822 case EXPR_LESS:
823 case EXPR_GTREQL:
824 case EXPR_LESSEQL:
825 ret = compare_expr(a->ref, b->ref);
826 if (ret != 0)
827 return ret;
828 return compare_expr(a->u.ext, b->u.ext);
829 case EXPR_CAST:
830 ret = compare_type(a->u.tref, b->u.tref);
831 if (ret != 0)
832 return ret;
833 /* Fall through. */
834 case EXPR_NOT:
835 case EXPR_NEG:
836 case EXPR_PPTR:
837 case EXPR_ADDRESSOF:
838 case EXPR_LOGNOT:
839 case EXPR_POS:
840 return compare_expr(a->ref, b->ref);
841 case EXPR_SIZEOF:
842 return compare_type(a->u.tref, b->u.tref);
843 case EXPR_VOID:
844 return 0;
846 return -1;