widl: Infrastructure for adding a prefix to local variable references.
[wine/multimedia.git] / tools / widl / expr.c
blob3b668ef07e70d3e4db4ba5c32d411b11f9e967ad
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"
36 expr_t *make_expr(enum expr_type type)
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;
47 expr_t *make_exprl(enum expr_type type, long val)
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)
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;
62 return e;
65 expr_t *make_exprd(enum expr_type type, double val)
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;
76 expr_t *make_exprs(enum expr_type type, char *val)
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)
87 var_t *c = find_const(val, 0);
88 if (c)
90 e->u.sval = c->name;
91 free(val);
92 e->is_const = TRUE;
93 e->cval = c->eval->cval;
96 return e;
99 expr_t *make_exprt(enum expr_type type, type_t *tref, expr_t *expr)
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)
110 switch (tref->type)
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;
139 if (type == EXPR_CAST && expr->is_const)
141 e->is_const = TRUE;
142 e->cval = expr->cval;
144 return e;
147 expr_t *make_expr1(enum expr_type type, expr_t *expr)
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)
158 e->is_const = TRUE;
159 switch (type)
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;
178 return e;
181 expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2)
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)
192 e->is_const = TRUE;
193 switch (type)
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)
204 error_loc("divide by zero in expression\n");
205 e->cval = 0;
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)
216 error_loc("divide by zero in expression\n");
217 e->cval = 0;
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;
266 return e;
269 expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3)
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)
281 e->is_const = TRUE;
282 switch (type)
284 case EXPR_COND:
285 e->cval = expr1->cval ? expr2->cval : expr3->cval;
286 break;
287 default:
288 e->is_const = FALSE;
289 break;
292 return e;
295 struct expression_type
297 int is_variable; /* is the expression resolved to a variable? */
298 int is_temporary; /* should the type be freed? */
299 type_t *type;
302 static int is_integer_type(const type_t *type)
304 switch (type->type)
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;
326 static void check_scalar_type(const struct expr_loc *expr_loc,
327 const type_t *cont_type, const type_t *type)
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 : "");
337 static void check_arithmetic_type(const struct expr_loc *expr_loc,
338 const type_t *cont_type, const type_t *type)
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 : "");
348 static void check_integer_type(const struct expr_loc *expr_loc,
349 const type_t *cont_type, const type_t *type)
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 : "");
357 static type_t *find_identifier(const char *identifier, const type_t *cont_type, int *found_in_cont_type)
359 type_t *type = NULL;
360 const var_t *field;
361 const var_list_t *fields = NULL;
363 *found_in_cont_type = 0;
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))
369 if (cont_type->type == RPC_FC_ENCAPSULATED_UNION)
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;
374 else
375 fields = cont_type->fields_or_args;
378 if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
379 if (field->name && !strcmp(identifier, field->name))
381 type = field->type;
382 *found_in_cont_type = 1;
383 break;
386 if (!type)
388 var_t *const_var = find_const(identifier, 0);
389 if (const_var) type = const_var->type;
392 return type;
395 static struct expression_type resolve_expression(const struct expr_loc *expr_loc,
396 const type_t *cont_type,
397 const expr_t *e)
399 struct expression_type result;
400 result.is_variable = FALSE;
401 result.is_temporary = FALSE;
402 result.type = NULL;
403 switch (e->type)
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:
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)
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 : "");
441 break;
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:
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;
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:
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;
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:
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;
549 case EXPR_ARRAY:
550 result = resolve_expression(expr_loc, cont_type, e->ref);
551 if (result.type && is_array(result.type))
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 : "");
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;
567 return result;
570 const type_t *expr_resolve_type(const struct expr_loc *expr_loc, const type_t *cont_type, const expr_t *expr)
572 struct expression_type expr_type;
573 expr_type = resolve_expression(expr_loc, cont_type, expr);
574 return expr_type.type;
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, const char *local_var_prefix)
581 switch (e->type)
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)
603 int found_in_cont_type;
604 find_identifier(e->u.sval, cont_type, &found_in_cont_type);
605 if (found_in_cont_type)
607 fprintf(h, "%s%s", toplevel_prefix, e->u.sval);
608 break;
611 fprintf(h, "%s%s", local_var_prefix, e->u.sval);
612 break;
613 case EXPR_STRLIT:
614 fprintf(h, "\"%s\"", e->u.sval);
615 break;
616 case EXPR_WSTRLIT:
617 fprintf(h, "L\"%s\"", e->u.sval);
618 break;
619 case EXPR_LOGNOT:
620 fprintf(h, "!");
621 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
622 break;
623 case EXPR_NOT:
624 fprintf(h, "~");
625 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
626 break;
627 case EXPR_POS:
628 fprintf(h, "+");
629 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
630 break;
631 case EXPR_NEG:
632 fprintf(h, "-");
633 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
634 break;
635 case EXPR_ADDRESSOF:
636 fprintf(h, "&");
637 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
638 break;
639 case EXPR_PPTR:
640 fprintf(h, "*");
641 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
642 break;
643 case EXPR_CAST:
644 fprintf(h, "(");
645 write_type_decl(h, e->u.tref, NULL);
646 fprintf(h, ")");
647 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
648 break;
649 case EXPR_SIZEOF:
650 fprintf(h, "sizeof(");
651 write_type_decl(h, e->u.tref, NULL);
652 fprintf(h, ")");
653 break;
654 case EXPR_SHL:
655 case EXPR_SHR:
656 case EXPR_MOD:
657 case EXPR_MUL:
658 case EXPR_DIV:
659 case EXPR_ADD:
660 case EXPR_SUB:
661 case EXPR_AND:
662 case EXPR_OR:
663 case EXPR_LOGOR:
664 case EXPR_LOGAND:
665 case EXPR_XOR:
666 case EXPR_EQUALITY:
667 case EXPR_INEQUALITY:
668 case EXPR_GTR:
669 case EXPR_LESS:
670 case EXPR_GTREQL:
671 case EXPR_LESSEQL:
672 if (brackets) fprintf(h, "(");
673 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
674 switch (e->type)
676 case EXPR_SHL: fprintf(h, " << "); break;
677 case EXPR_SHR: fprintf(h, " >> "); break;
678 case EXPR_MOD: fprintf(h, " %% "); break;
679 case EXPR_MUL: fprintf(h, " * "); break;
680 case EXPR_DIV: fprintf(h, " / "); break;
681 case EXPR_ADD: fprintf(h, " + "); break;
682 case EXPR_SUB: fprintf(h, " - "); break;
683 case EXPR_AND: fprintf(h, " & "); break;
684 case EXPR_OR: fprintf(h, " | "); break;
685 case EXPR_LOGOR: fprintf(h, " || "); break;
686 case EXPR_LOGAND: fprintf(h, " && "); break;
687 case EXPR_XOR: fprintf(h, " ^ "); break;
688 case EXPR_EQUALITY: fprintf(h, " == "); break;
689 case EXPR_INEQUALITY: fprintf(h, " != "); break;
690 case EXPR_GTR: fprintf(h, " > "); break;
691 case EXPR_LESS: fprintf(h, " < "); break;
692 case EXPR_GTREQL: fprintf(h, " >= "); break;
693 case EXPR_LESSEQL: fprintf(h, " <= "); break;
694 default: break;
696 write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
697 if (brackets) fprintf(h, ")");
698 break;
699 case EXPR_MEMBER:
700 if (brackets) fprintf(h, "(");
701 if (e->ref->type == EXPR_PPTR)
703 write_expr(h, e->ref->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
704 fprintf(h, "->");
706 else
708 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
709 fprintf(h, ".");
711 write_expr(h, e->u.ext, 1, 0, toplevel_prefix, cont_type, "");
712 if (brackets) fprintf(h, ")");
713 break;
714 case EXPR_COND:
715 if (brackets) fprintf(h, "(");
716 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
717 fprintf(h, " ? ");
718 write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
719 fprintf(h, " : ");
720 write_expr(h, e->ext2, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
721 if (brackets) fprintf(h, ")");
722 break;
723 case EXPR_ARRAY:
724 if (brackets) fprintf(h, "(");
725 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
726 fprintf(h, "[");
727 write_expr(h, e->u.ext, 1, 1, toplevel_prefix, cont_type, local_var_prefix);
728 fprintf(h, "]");
729 if (brackets) fprintf(h, ")");
730 break;
734 /* This is actually fairly involved to implement precisely, due to the
735 effects attributes may have and things like that. Right now this is
736 only used for optimization, so just check for a very small set of
737 criteria that guarantee the types are equivalent; assume every thing
738 else is different. */
739 static int compare_type(const type_t *a, const type_t *b)
741 if (a == b
742 || (a->name
743 && b->name
744 && strcmp(a->name, b->name) == 0))
745 return 0;
746 /* Ordering doesn't need to be implemented yet. */
747 return 1;
750 int compare_expr(const expr_t *a, const expr_t *b)
752 int ret;
754 if (a->type != b->type)
755 return a->type - b->type;
757 switch (a->type)
759 case EXPR_NUM:
760 case EXPR_HEXNUM:
761 case EXPR_TRUEFALSE:
762 return a->u.lval - b->u.lval;
763 case EXPR_DOUBLE:
764 return a->u.dval - b->u.dval;
765 case EXPR_IDENTIFIER:
766 case EXPR_STRLIT:
767 case EXPR_WSTRLIT:
768 return strcmp(a->u.sval, b->u.sval);
769 case EXPR_COND:
770 ret = compare_expr(a->ref, b->ref);
771 if (ret != 0)
772 return ret;
773 ret = compare_expr(a->u.ext, b->u.ext);
774 if (ret != 0)
775 return ret;
776 return compare_expr(a->ext2, b->ext2);
777 case EXPR_OR:
778 case EXPR_AND:
779 case EXPR_ADD:
780 case EXPR_SUB:
781 case EXPR_MOD:
782 case EXPR_MUL:
783 case EXPR_DIV:
784 case EXPR_SHL:
785 case EXPR_SHR:
786 case EXPR_MEMBER:
787 case EXPR_ARRAY:
788 case EXPR_LOGOR:
789 case EXPR_LOGAND:
790 case EXPR_XOR:
791 case EXPR_EQUALITY:
792 case EXPR_INEQUALITY:
793 case EXPR_GTR:
794 case EXPR_LESS:
795 case EXPR_GTREQL:
796 case EXPR_LESSEQL:
797 ret = compare_expr(a->ref, b->ref);
798 if (ret != 0)
799 return ret;
800 return compare_expr(a->u.ext, b->u.ext);
801 case EXPR_CAST:
802 ret = compare_type(a->u.tref, b->u.tref);
803 if (ret != 0)
804 return ret;
805 /* Fall through. */
806 case EXPR_NOT:
807 case EXPR_NEG:
808 case EXPR_PPTR:
809 case EXPR_ADDRESSOF:
810 case EXPR_LOGNOT:
811 case EXPR_POS:
812 return compare_expr(a->ref, b->ref);
813 case EXPR_SIZEOF:
814 return compare_type(a->u.tref, b->u.tref);
815 case EXPR_VOID:
816 return 0;
818 return -1;