mshtml: Implement IHTMLStyle get/put borderRightStyle.
[wine/wine-gecko.git] / tools / widl / expr.c
blob7717da3f7bfb39d2eb6ebb64f4a0ef69a3eee810
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"
37 expr_t *make_expr(enum expr_type type)
39 expr_t *e = xmalloc(sizeof(expr_t));
40 e->type = type;
41 e->ref = NULL;
42 e->u.lval = 0;
43 e->is_const = FALSE;
44 e->cval = 0;
45 return e;
48 expr_t *make_exprl(enum expr_type type, long val)
50 expr_t *e = xmalloc(sizeof(expr_t));
51 e->type = type;
52 e->ref = NULL;
53 e->u.lval = val;
54 e->is_const = FALSE;
55 /* check for numeric constant */
56 if (type == EXPR_NUM || type == EXPR_HEXNUM || type == EXPR_TRUEFALSE)
58 /* make sure true/false value is valid */
59 assert(type != EXPR_TRUEFALSE || val == 0 || val == 1);
60 e->is_const = TRUE;
61 e->cval = val;
63 return e;
66 expr_t *make_exprd(enum expr_type type, double val)
68 expr_t *e = xmalloc(sizeof(expr_t));
69 e->type = type;
70 e->ref = NULL;
71 e->u.dval = val;
72 e->is_const = TRUE;
73 e->cval = val;
74 return e;
77 expr_t *make_exprs(enum expr_type type, char *val)
79 expr_t *e;
80 e = xmalloc(sizeof(expr_t));
81 e->type = type;
82 e->ref = NULL;
83 e->u.sval = val;
84 e->is_const = FALSE;
85 /* check for predefined constants */
86 if (type == EXPR_IDENTIFIER)
88 var_t *c = find_const(val, 0);
89 if (c)
91 e->u.sval = c->name;
92 free(val);
93 e->is_const = TRUE;
94 e->cval = c->eval->cval;
97 return e;
100 expr_t *make_exprt(enum expr_type type, type_t *tref, expr_t *expr)
102 expr_t *e;
103 e = xmalloc(sizeof(expr_t));
104 e->type = type;
105 e->ref = expr;
106 e->u.tref = tref;
107 e->is_const = FALSE;
108 /* check for cast of constant expression */
109 if (type == EXPR_SIZEOF)
111 switch (tref->type)
113 case RPC_FC_BYTE:
114 case RPC_FC_CHAR:
115 case RPC_FC_SMALL:
116 case RPC_FC_USMALL:
117 e->is_const = TRUE;
118 e->cval = 1;
119 break;
120 case RPC_FC_WCHAR:
121 case RPC_FC_USHORT:
122 case RPC_FC_SHORT:
123 e->is_const = TRUE;
124 e->cval = 2;
125 break;
126 case RPC_FC_LONG:
127 case RPC_FC_ULONG:
128 case RPC_FC_FLOAT:
129 case RPC_FC_ERROR_STATUS_T:
130 e->is_const = TRUE;
131 e->cval = 4;
132 break;
133 case RPC_FC_HYPER:
134 case RPC_FC_DOUBLE:
135 e->is_const = TRUE;
136 e->cval = 8;
137 break;
140 if (type == EXPR_CAST && expr->is_const)
142 e->is_const = TRUE;
143 e->cval = expr->cval;
145 return e;
148 expr_t *make_expr1(enum expr_type type, expr_t *expr)
150 expr_t *e;
151 e = xmalloc(sizeof(expr_t));
152 e->type = type;
153 e->ref = expr;
154 e->u.lval = 0;
155 e->is_const = FALSE;
156 /* check for compile-time optimization */
157 if (expr->is_const)
159 e->is_const = TRUE;
160 switch (type)
162 case EXPR_LOGNOT:
163 e->cval = !expr->cval;
164 break;
165 case EXPR_POS:
166 e->cval = +expr->cval;
167 break;
168 case EXPR_NEG:
169 e->cval = -expr->cval;
170 break;
171 case EXPR_NOT:
172 e->cval = ~expr->cval;
173 break;
174 default:
175 e->is_const = FALSE;
176 break;
179 return e;
182 expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2)
184 expr_t *e;
185 e = xmalloc(sizeof(expr_t));
186 e->type = type;
187 e->ref = expr1;
188 e->u.ext = expr2;
189 e->is_const = FALSE;
190 /* check for compile-time optimization */
191 if (expr1->is_const && expr2->is_const)
193 e->is_const = TRUE;
194 switch (type)
196 case EXPR_ADD:
197 e->cval = expr1->cval + expr2->cval;
198 break;
199 case EXPR_SUB:
200 e->cval = expr1->cval - expr2->cval;
201 break;
202 case EXPR_MOD:
203 if (expr2->cval == 0)
205 error_loc("divide by zero in expression\n");
206 e->cval = 0;
208 else
209 e->cval = expr1->cval % expr2->cval;
210 break;
211 case EXPR_MUL:
212 e->cval = expr1->cval * expr2->cval;
213 break;
214 case EXPR_DIV:
215 if (expr2->cval == 0)
217 error_loc("divide by zero in expression\n");
218 e->cval = 0;
220 else
221 e->cval = expr1->cval / expr2->cval;
222 break;
223 case EXPR_OR:
224 e->cval = expr1->cval | expr2->cval;
225 break;
226 case EXPR_AND:
227 e->cval = expr1->cval & expr2->cval;
228 break;
229 case EXPR_SHL:
230 e->cval = expr1->cval << expr2->cval;
231 break;
232 case EXPR_SHR:
233 e->cval = expr1->cval >> expr2->cval;
234 break;
235 case EXPR_LOGOR:
236 e->cval = expr1->cval || expr2->cval;
237 break;
238 case EXPR_LOGAND:
239 e->cval = expr1->cval && expr2->cval;
240 break;
241 case EXPR_XOR:
242 e->cval = expr1->cval ^ expr2->cval;
243 break;
244 case EXPR_EQUALITY:
245 e->cval = expr1->cval == expr2->cval;
246 break;
247 case EXPR_INEQUALITY:
248 e->cval = expr1->cval != expr2->cval;
249 break;
250 case EXPR_GTR:
251 e->cval = expr1->cval > expr2->cval;
252 break;
253 case EXPR_LESS:
254 e->cval = expr1->cval < expr2->cval;
255 break;
256 case EXPR_GTREQL:
257 e->cval = expr1->cval >= expr2->cval;
258 break;
259 case EXPR_LESSEQL:
260 e->cval = expr1->cval <= expr2->cval;
261 break;
262 default:
263 e->is_const = FALSE;
264 break;
267 return e;
270 expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3)
272 expr_t *e;
273 e = xmalloc(sizeof(expr_t));
274 e->type = type;
275 e->ref = expr1;
276 e->u.ext = expr2;
277 e->ext2 = expr3;
278 e->is_const = FALSE;
279 /* check for compile-time optimization */
280 if (expr1->is_const && expr2->is_const && expr3->is_const)
282 e->is_const = TRUE;
283 switch (type)
285 case EXPR_COND:
286 e->cval = expr1->cval ? expr2->cval : expr3->cval;
287 break;
288 default:
289 e->is_const = FALSE;
290 break;
293 return e;
296 struct expression_type
298 int is_variable; /* is the expression resolved to a variable? */
299 int is_temporary; /* should the type be freed? */
300 type_t *type;
303 static int is_integer_type(const type_t *type)
305 switch (type->type)
307 case RPC_FC_BYTE:
308 case RPC_FC_CHAR:
309 case RPC_FC_SMALL:
310 case RPC_FC_USMALL:
311 case RPC_FC_WCHAR:
312 case RPC_FC_SHORT:
313 case RPC_FC_USHORT:
314 case RPC_FC_LONG:
315 case RPC_FC_ULONG:
316 case RPC_FC_INT3264:
317 case RPC_FC_UINT3264:
318 case RPC_FC_HYPER:
319 case RPC_FC_ENUM16:
320 case RPC_FC_ENUM32:
321 return TRUE;
322 default:
323 return FALSE;
327 static void check_scalar_type(const struct expr_loc *expr_loc,
328 const type_t *cont_type, const type_t *type)
330 if (!cont_type || (!is_integer_type(type) && !is_ptr(type) &&
331 type->type != RPC_FC_FLOAT &&
332 type->type != RPC_FC_DOUBLE))
333 error_loc_info(&expr_loc->v->loc_info, "scalar type required in expression%s%s\n",
334 expr_loc->attr ? " for attribute " : "",
335 expr_loc->attr ? expr_loc->attr : "");
338 static void check_arithmetic_type(const struct expr_loc *expr_loc,
339 const type_t *cont_type, const type_t *type)
341 if (!cont_type || (!is_integer_type(type) &&
342 type->type != RPC_FC_FLOAT &&
343 type->type != RPC_FC_DOUBLE))
344 error_loc_info(&expr_loc->v->loc_info, "arithmetic type required in expression%s%s\n",
345 expr_loc->attr ? " for attribute " : "",
346 expr_loc->attr ? expr_loc->attr : "");
349 static void check_integer_type(const struct expr_loc *expr_loc,
350 const type_t *cont_type, const type_t *type)
352 if (!cont_type || !is_integer_type(type))
353 error_loc_info(&expr_loc->v->loc_info, "integer type required in expression%s%s\n",
354 expr_loc->attr ? " for attribute " : "",
355 expr_loc->attr ? expr_loc->attr : "");
358 static type_t *find_identifier(const char *identifier, const type_t *cont_type, int *found_in_cont_type)
360 type_t *type = NULL;
361 const var_t *field;
362 const var_list_t *fields = NULL;
364 *found_in_cont_type = 0;
366 if (cont_type)
368 if (cont_type->type == RPC_FC_FUNCTION)
369 fields = type_function_get_args(cont_type);
370 else if (is_struct(cont_type->type))
371 fields = type_struct_get_fields(cont_type);
372 else if (is_union(cont_type->type))
373 fields = type_union_get_cases(cont_type);
376 if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
377 if (field->name && !strcmp(identifier, field->name))
379 type = field->type;
380 *found_in_cont_type = 1;
381 break;
384 if (!type)
386 var_t *const_var = find_const(identifier, 0);
387 if (const_var) type = const_var->type;
390 return type;
393 static struct expression_type resolve_expression(const struct expr_loc *expr_loc,
394 const type_t *cont_type,
395 const expr_t *e)
397 struct expression_type result;
398 result.is_variable = FALSE;
399 result.is_temporary = FALSE;
400 result.type = NULL;
401 switch (e->type)
403 case EXPR_VOID:
404 break;
405 case EXPR_HEXNUM:
406 case EXPR_NUM:
407 case EXPR_TRUEFALSE:
408 result.is_variable = FALSE;
409 result.is_temporary = FALSE;
410 result.type = find_type("int", 0);
411 break;
412 case EXPR_STRLIT:
413 result.is_variable = FALSE;
414 result.is_temporary = TRUE;
415 result.type = make_type(RPC_FC_RP, find_type("char", 0));
416 break;
417 case EXPR_WSTRLIT:
418 result.is_variable = FALSE;
419 result.is_temporary = TRUE;
420 result.type = make_type(RPC_FC_RP, find_type("wchar_t", 0));
421 break;
422 case EXPR_DOUBLE:
423 result.is_variable = FALSE;
424 result.is_temporary = FALSE;
425 result.type = find_type("double", 0);
426 break;
427 case EXPR_IDENTIFIER:
429 int found_in_cont_type;
430 result.is_variable = TRUE;
431 result.is_temporary = FALSE;
432 result.type = find_identifier(e->u.sval, cont_type, &found_in_cont_type);
433 if (!result.type)
435 error_loc_info(&expr_loc->v->loc_info, "identifier %s cannot be resolved in expression%s%s\n",
436 e->u.sval, expr_loc->attr ? " for attribute " : "",
437 expr_loc->attr ? expr_loc->attr : "");
439 break;
441 case EXPR_LOGNOT:
442 result = resolve_expression(expr_loc, cont_type, e->ref);
443 check_scalar_type(expr_loc, cont_type, result.type);
444 result.is_variable = FALSE;
445 result.is_temporary = FALSE;
446 result.type = find_type("int", 0);
447 break;
448 case EXPR_NOT:
449 result = resolve_expression(expr_loc, cont_type, e->ref);
450 check_integer_type(expr_loc, cont_type, result.type);
451 result.is_variable = FALSE;
452 break;
453 case EXPR_POS:
454 case EXPR_NEG:
455 result = resolve_expression(expr_loc, cont_type, e->ref);
456 check_arithmetic_type(expr_loc, cont_type, result.type);
457 result.is_variable = FALSE;
458 break;
459 case EXPR_ADDRESSOF:
460 result = resolve_expression(expr_loc, cont_type, e->ref);
461 if (!result.is_variable)
462 error_loc_info(&expr_loc->v->loc_info, "address-of operator applied to non-variable type in expression%s%s\n",
463 expr_loc->attr ? " for attribute " : "",
464 expr_loc->attr ? expr_loc->attr : "");
465 result.is_variable = FALSE;
466 result.is_temporary = TRUE;
467 result.type = make_type(RPC_FC_RP, result.type);
468 break;
469 case EXPR_PPTR:
470 result = resolve_expression(expr_loc, cont_type, e->ref);
471 if (result.type && is_ptr(result.type))
472 result.type = type_pointer_get_ref(result.type);
473 else if(result.type && is_array(result.type)
474 && !result.type->declarray)
475 result.type = type_array_get_element(result.type);
476 else
477 error_loc_info(&expr_loc->v->loc_info, "dereference operator applied to non-pointer type in expression%s%s\n",
478 expr_loc->attr ? " for attribute " : "",
479 expr_loc->attr ? expr_loc->attr : "");
480 break;
481 case EXPR_CAST:
482 result = resolve_expression(expr_loc, cont_type, e->ref);
483 result.type = e->u.tref;
484 break;
485 case EXPR_SIZEOF:
486 result.is_variable = FALSE;
487 result.is_temporary = FALSE;
488 result.type = find_type("int", 0);
489 break;
490 case EXPR_SHL:
491 case EXPR_SHR:
492 case EXPR_MOD:
493 case EXPR_MUL:
494 case EXPR_DIV:
495 case EXPR_ADD:
496 case EXPR_SUB:
497 case EXPR_AND:
498 case EXPR_OR:
499 case EXPR_XOR:
501 struct expression_type result_right;
502 result = resolve_expression(expr_loc, cont_type, e->ref);
503 result.is_variable = FALSE;
504 result_right = resolve_expression(expr_loc, cont_type, e->u.ext);
505 /* FIXME: these checks aren't strict enough for some of the operators */
506 check_scalar_type(expr_loc, cont_type, result.type);
507 check_scalar_type(expr_loc, cont_type, result_right.type);
508 break;
510 case EXPR_LOGOR:
511 case EXPR_LOGAND:
512 case EXPR_EQUALITY:
513 case EXPR_INEQUALITY:
514 case EXPR_GTR:
515 case EXPR_LESS:
516 case EXPR_GTREQL:
517 case EXPR_LESSEQL:
519 struct expression_type result_left, result_right;
520 result_left = resolve_expression(expr_loc, cont_type, e->ref);
521 result_right = resolve_expression(expr_loc, cont_type, e->u.ext);
522 check_scalar_type(expr_loc, cont_type, result_left.type);
523 check_scalar_type(expr_loc, cont_type, result_right.type);
524 result.is_variable = FALSE;
525 result.is_temporary = FALSE;
526 result.type = find_type("int", 0);
527 break;
529 case EXPR_MEMBER:
530 result = resolve_expression(expr_loc, cont_type, e->ref);
531 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))
532 result = resolve_expression(expr_loc, result.type, e->u.ext);
533 else
534 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",
535 expr_loc->attr ? " for attribute " : "",
536 expr_loc->attr ? expr_loc->attr : "");
537 break;
538 case EXPR_COND:
540 struct expression_type result_first, result_second, result_third;
541 result_first = resolve_expression(expr_loc, cont_type, e->ref);
542 check_scalar_type(expr_loc, cont_type, result_first.type);
543 result_second = resolve_expression(expr_loc, cont_type, e->u.ext);
544 result_third = resolve_expression(expr_loc, cont_type, e->ext2);
545 /* FIXME: determine the correct return type */
546 result = result_second;
547 result.is_variable = FALSE;
548 break;
550 case EXPR_ARRAY:
551 result = resolve_expression(expr_loc, cont_type, e->ref);
552 if (result.type && is_array(result.type))
554 struct expression_type index_result;
555 result.type = type_array_get_element(result.type);
556 index_result = resolve_expression(expr_loc, cont_type /* FIXME */, e->u.ext);
557 if (!index_result.type || !is_integer_type(index_result.type))
558 error_loc_info(&expr_loc->v->loc_info, "array subscript not of integral type in expression%s%s\n",
559 expr_loc->attr ? " for attribute " : "",
560 expr_loc->attr ? expr_loc->attr : "");
562 else
563 error_loc_info(&expr_loc->v->loc_info, "array subscript operator applied to non-array type in expression%s%s\n",
564 expr_loc->attr ? " for attribute " : "",
565 expr_loc->attr ? expr_loc->attr : "");
566 break;
568 return result;
571 const type_t *expr_resolve_type(const struct expr_loc *expr_loc, const type_t *cont_type, const expr_t *expr)
573 struct expression_type expr_type;
574 expr_type = resolve_expression(expr_loc, cont_type, expr);
575 return expr_type.type;
578 void write_expr(FILE *h, const expr_t *e, int brackets,
579 int toplevel, const char *toplevel_prefix,
580 const type_t *cont_type, const char *local_var_prefix)
582 switch (e->type)
584 case EXPR_VOID:
585 break;
586 case EXPR_NUM:
587 fprintf(h, "%lu", e->u.lval);
588 break;
589 case EXPR_HEXNUM:
590 fprintf(h, "0x%lx", e->u.lval);
591 break;
592 case EXPR_DOUBLE:
593 fprintf(h, "%#.15g", e->u.dval);
594 break;
595 case EXPR_TRUEFALSE:
596 if (e->u.lval == 0)
597 fprintf(h, "FALSE");
598 else
599 fprintf(h, "TRUE");
600 break;
601 case EXPR_IDENTIFIER:
602 if (toplevel && toplevel_prefix && cont_type)
604 int found_in_cont_type;
605 find_identifier(e->u.sval, cont_type, &found_in_cont_type);
606 if (found_in_cont_type)
608 fprintf(h, "%s%s", toplevel_prefix, e->u.sval);
609 break;
612 fprintf(h, "%s%s", local_var_prefix, e->u.sval);
613 break;
614 case EXPR_STRLIT:
615 fprintf(h, "\"%s\"", e->u.sval);
616 break;
617 case EXPR_WSTRLIT:
618 fprintf(h, "L\"%s\"", e->u.sval);
619 break;
620 case EXPR_LOGNOT:
621 fprintf(h, "!");
622 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
623 break;
624 case EXPR_NOT:
625 fprintf(h, "~");
626 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
627 break;
628 case EXPR_POS:
629 fprintf(h, "+");
630 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
631 break;
632 case EXPR_NEG:
633 fprintf(h, "-");
634 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
635 break;
636 case EXPR_ADDRESSOF:
637 fprintf(h, "&");
638 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
639 break;
640 case EXPR_PPTR:
641 fprintf(h, "*");
642 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
643 break;
644 case EXPR_CAST:
645 fprintf(h, "(");
646 write_type_decl(h, e->u.tref, NULL);
647 fprintf(h, ")");
648 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
649 break;
650 case EXPR_SIZEOF:
651 fprintf(h, "sizeof(");
652 write_type_decl(h, e->u.tref, NULL);
653 fprintf(h, ")");
654 break;
655 case EXPR_SHL:
656 case EXPR_SHR:
657 case EXPR_MOD:
658 case EXPR_MUL:
659 case EXPR_DIV:
660 case EXPR_ADD:
661 case EXPR_SUB:
662 case EXPR_AND:
663 case EXPR_OR:
664 case EXPR_LOGOR:
665 case EXPR_LOGAND:
666 case EXPR_XOR:
667 case EXPR_EQUALITY:
668 case EXPR_INEQUALITY:
669 case EXPR_GTR:
670 case EXPR_LESS:
671 case EXPR_GTREQL:
672 case EXPR_LESSEQL:
673 if (brackets) fprintf(h, "(");
674 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
675 switch (e->type)
677 case EXPR_SHL: fprintf(h, " << "); break;
678 case EXPR_SHR: fprintf(h, " >> "); break;
679 case EXPR_MOD: fprintf(h, " %% "); break;
680 case EXPR_MUL: fprintf(h, " * "); break;
681 case EXPR_DIV: fprintf(h, " / "); break;
682 case EXPR_ADD: fprintf(h, " + "); break;
683 case EXPR_SUB: fprintf(h, " - "); break;
684 case EXPR_AND: fprintf(h, " & "); break;
685 case EXPR_OR: fprintf(h, " | "); break;
686 case EXPR_LOGOR: fprintf(h, " || "); break;
687 case EXPR_LOGAND: fprintf(h, " && "); break;
688 case EXPR_XOR: fprintf(h, " ^ "); break;
689 case EXPR_EQUALITY: fprintf(h, " == "); break;
690 case EXPR_INEQUALITY: fprintf(h, " != "); break;
691 case EXPR_GTR: fprintf(h, " > "); break;
692 case EXPR_LESS: fprintf(h, " < "); break;
693 case EXPR_GTREQL: fprintf(h, " >= "); break;
694 case EXPR_LESSEQL: fprintf(h, " <= "); break;
695 default: break;
697 write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
698 if (brackets) fprintf(h, ")");
699 break;
700 case EXPR_MEMBER:
701 if (brackets) fprintf(h, "(");
702 if (e->ref->type == EXPR_PPTR)
704 write_expr(h, e->ref->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
705 fprintf(h, "->");
707 else
709 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
710 fprintf(h, ".");
712 write_expr(h, e->u.ext, 1, 0, toplevel_prefix, cont_type, "");
713 if (brackets) fprintf(h, ")");
714 break;
715 case EXPR_COND:
716 if (brackets) fprintf(h, "(");
717 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
718 fprintf(h, " ? ");
719 write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
720 fprintf(h, " : ");
721 write_expr(h, e->ext2, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
722 if (brackets) fprintf(h, ")");
723 break;
724 case EXPR_ARRAY:
725 if (brackets) fprintf(h, "(");
726 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
727 fprintf(h, "[");
728 write_expr(h, e->u.ext, 1, 1, toplevel_prefix, cont_type, local_var_prefix);
729 fprintf(h, "]");
730 if (brackets) fprintf(h, ")");
731 break;
735 /* This is actually fairly involved to implement precisely, due to the
736 effects attributes may have and things like that. Right now this is
737 only used for optimization, so just check for a very small set of
738 criteria that guarantee the types are equivalent; assume every thing
739 else is different. */
740 static int compare_type(const type_t *a, const type_t *b)
742 if (a == b
743 || (a->name
744 && b->name
745 && strcmp(a->name, b->name) == 0))
746 return 0;
747 /* Ordering doesn't need to be implemented yet. */
748 return 1;
751 int compare_expr(const expr_t *a, const expr_t *b)
753 int ret;
755 if (a->type != b->type)
756 return a->type - b->type;
758 switch (a->type)
760 case EXPR_NUM:
761 case EXPR_HEXNUM:
762 case EXPR_TRUEFALSE:
763 return a->u.lval - b->u.lval;
764 case EXPR_DOUBLE:
765 return a->u.dval - b->u.dval;
766 case EXPR_IDENTIFIER:
767 case EXPR_STRLIT:
768 case EXPR_WSTRLIT:
769 return strcmp(a->u.sval, b->u.sval);
770 case EXPR_COND:
771 ret = compare_expr(a->ref, b->ref);
772 if (ret != 0)
773 return ret;
774 ret = compare_expr(a->u.ext, b->u.ext);
775 if (ret != 0)
776 return ret;
777 return compare_expr(a->ext2, b->ext2);
778 case EXPR_OR:
779 case EXPR_AND:
780 case EXPR_ADD:
781 case EXPR_SUB:
782 case EXPR_MOD:
783 case EXPR_MUL:
784 case EXPR_DIV:
785 case EXPR_SHL:
786 case EXPR_SHR:
787 case EXPR_MEMBER:
788 case EXPR_ARRAY:
789 case EXPR_LOGOR:
790 case EXPR_LOGAND:
791 case EXPR_XOR:
792 case EXPR_EQUALITY:
793 case EXPR_INEQUALITY:
794 case EXPR_GTR:
795 case EXPR_LESS:
796 case EXPR_GTREQL:
797 case EXPR_LESSEQL:
798 ret = compare_expr(a->ref, b->ref);
799 if (ret != 0)
800 return ret;
801 return compare_expr(a->u.ext, b->u.ext);
802 case EXPR_CAST:
803 ret = compare_type(a->u.tref, b->u.tref);
804 if (ret != 0)
805 return ret;
806 /* Fall through. */
807 case EXPR_NOT:
808 case EXPR_NEG:
809 case EXPR_PPTR:
810 case EXPR_ADDRESSOF:
811 case EXPR_LOGNOT:
812 case EXPR_POS:
813 return compare_expr(a->ref, b->ref);
814 case EXPR_SIZEOF:
815 return compare_type(a->u.tref, b->u.tref);
816 case EXPR_VOID:
817 return 0;
819 return -1;