wined3d: Replace a few hardcoded Tx registers with proper name getters.
[wine.git] / tools / widl / expr.c
blob405b5def1b6c88516dd027b9a18c3e5ce53d240a
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_type(type))
295 case TYPE_BASIC_INT8:
296 case TYPE_BASIC_INT16:
297 case TYPE_BASIC_INT32:
298 case TYPE_BASIC_INT64:
299 case TYPE_BASIC_INT:
300 case TYPE_BASIC_CHAR:
301 case TYPE_BASIC_HYPER:
302 case TYPE_BASIC_BYTE:
303 case TYPE_BASIC_WCHAR:
304 case TYPE_BASIC_ERROR_STATUS_T:
305 return TRUE;
306 default:
307 return FALSE;
309 default:
310 return FALSE;
314 static int is_float_type(const type_t *type)
316 return (type_get_type(type) == TYPE_BASIC &&
317 (type_basic_get_type(type) == TYPE_BASIC_FLOAT ||
318 type_basic_get_type(type) == TYPE_BASIC_DOUBLE));
321 static void check_scalar_type(const struct expr_loc *expr_loc,
322 const type_t *cont_type, const type_t *type)
324 if (!cont_type || (!is_integer_type(type) && !is_ptr(type) &&
325 !is_float_type(type)))
326 error_loc_info(&expr_loc->v->loc_info, "scalar type required in expression%s%s\n",
327 expr_loc->attr ? " for attribute " : "",
328 expr_loc->attr ? expr_loc->attr : "");
331 static void check_arithmetic_type(const struct expr_loc *expr_loc,
332 const type_t *cont_type, const type_t *type)
334 if (!cont_type || (!is_integer_type(type) && !is_float_type(type)))
335 error_loc_info(&expr_loc->v->loc_info, "arithmetic type required in expression%s%s\n",
336 expr_loc->attr ? " for attribute " : "",
337 expr_loc->attr ? expr_loc->attr : "");
340 static void check_integer_type(const struct expr_loc *expr_loc,
341 const type_t *cont_type, const type_t *type)
343 if (!cont_type || !is_integer_type(type))
344 error_loc_info(&expr_loc->v->loc_info, "integer type required in expression%s%s\n",
345 expr_loc->attr ? " for attribute " : "",
346 expr_loc->attr ? expr_loc->attr : "");
349 static type_t *find_identifier(const char *identifier, const type_t *cont_type, int *found_in_cont_type)
351 type_t *type = NULL;
352 const var_t *field;
353 const var_list_t *fields = NULL;
355 *found_in_cont_type = 0;
357 if (cont_type)
359 switch (type_get_type(cont_type))
361 case TYPE_FUNCTION:
362 fields = type_function_get_args(cont_type);
363 break;
364 case TYPE_STRUCT:
365 fields = type_struct_get_fields(cont_type);
366 break;
367 case TYPE_UNION:
368 case TYPE_ENCAPSULATED_UNION:
369 fields = type_union_get_cases(cont_type);
370 break;
371 case TYPE_VOID:
372 case TYPE_BASIC:
373 case TYPE_ENUM:
374 case TYPE_MODULE:
375 case TYPE_COCLASS:
376 case TYPE_INTERFACE:
377 case TYPE_POINTER:
378 case TYPE_ARRAY:
379 /* nothing to do */
380 break;
381 case TYPE_ALIAS:
382 /* shouldn't get here because of using type_get_type above */
383 assert(0);
384 break;
388 if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
389 if (field->name && !strcmp(identifier, field->name))
391 type = field->type;
392 *found_in_cont_type = 1;
393 break;
396 if (!type)
398 var_t *const_var = find_const(identifier, 0);
399 if (const_var) type = const_var->type;
402 return type;
405 static int is_valid_member_operand(const type_t *type)
407 switch (type_get_type(type))
409 case TYPE_STRUCT:
410 case TYPE_UNION:
411 case TYPE_ENUM:
412 return TRUE;
413 default:
414 return FALSE;
418 static struct expression_type resolve_expression(const struct expr_loc *expr_loc,
419 const type_t *cont_type,
420 const expr_t *e)
422 struct expression_type result;
423 result.is_variable = FALSE;
424 result.is_temporary = FALSE;
425 result.type = NULL;
426 switch (e->type)
428 case EXPR_VOID:
429 break;
430 case EXPR_HEXNUM:
431 case EXPR_NUM:
432 case EXPR_TRUEFALSE:
433 result.is_variable = FALSE;
434 result.is_temporary = FALSE;
435 result.type = type_new_int(TYPE_BASIC_INT, 0);
436 break;
437 case EXPR_STRLIT:
438 result.is_variable = FALSE;
439 result.is_temporary = TRUE;
440 result.type = type_new_pointer(RPC_FC_UP, type_new_int(TYPE_BASIC_CHAR, 0), NULL);
441 break;
442 case EXPR_WSTRLIT:
443 result.is_variable = FALSE;
444 result.is_temporary = TRUE;
445 result.type = type_new_pointer(RPC_FC_UP, type_new_int(TYPE_BASIC_WCHAR, 0), NULL);
446 break;
447 case EXPR_DOUBLE:
448 result.is_variable = FALSE;
449 result.is_temporary = TRUE;
450 result.type = type_new_basic(TYPE_BASIC_DOUBLE);
451 break;
452 case EXPR_IDENTIFIER:
454 int found_in_cont_type;
455 result.is_variable = TRUE;
456 result.is_temporary = FALSE;
457 result.type = find_identifier(e->u.sval, cont_type, &found_in_cont_type);
458 if (!result.type)
460 error_loc_info(&expr_loc->v->loc_info, "identifier %s cannot be resolved in expression%s%s\n",
461 e->u.sval, expr_loc->attr ? " for attribute " : "",
462 expr_loc->attr ? expr_loc->attr : "");
464 break;
466 case EXPR_LOGNOT:
467 result = resolve_expression(expr_loc, cont_type, e->ref);
468 check_scalar_type(expr_loc, cont_type, result.type);
469 result.is_variable = FALSE;
470 result.is_temporary = FALSE;
471 result.type = type_new_int(TYPE_BASIC_INT, 0);
472 break;
473 case EXPR_NOT:
474 result = resolve_expression(expr_loc, cont_type, e->ref);
475 check_integer_type(expr_loc, cont_type, result.type);
476 result.is_variable = FALSE;
477 break;
478 case EXPR_POS:
479 case EXPR_NEG:
480 result = resolve_expression(expr_loc, cont_type, e->ref);
481 check_arithmetic_type(expr_loc, cont_type, result.type);
482 result.is_variable = FALSE;
483 break;
484 case EXPR_ADDRESSOF:
485 result = resolve_expression(expr_loc, cont_type, e->ref);
486 if (!result.is_variable)
487 error_loc_info(&expr_loc->v->loc_info, "address-of operator applied to non-variable type in expression%s%s\n",
488 expr_loc->attr ? " for attribute " : "",
489 expr_loc->attr ? expr_loc->attr : "");
490 result.is_variable = FALSE;
491 result.is_temporary = TRUE;
492 result.type = type_new_pointer(RPC_FC_UP, result.type, NULL);
493 break;
494 case EXPR_PPTR:
495 result = resolve_expression(expr_loc, cont_type, e->ref);
496 if (result.type && is_ptr(result.type))
497 result.type = type_pointer_get_ref(result.type);
498 else if(result.type && is_array(result.type)
499 && type_array_is_decl_as_ptr(result.type))
500 result.type = type_array_get_element(result.type);
501 else
502 error_loc_info(&expr_loc->v->loc_info, "dereference operator applied to non-pointer type in expression%s%s\n",
503 expr_loc->attr ? " for attribute " : "",
504 expr_loc->attr ? expr_loc->attr : "");
505 break;
506 case EXPR_CAST:
507 result = resolve_expression(expr_loc, cont_type, e->ref);
508 result.type = e->u.tref;
509 break;
510 case EXPR_SIZEOF:
511 result.is_variable = FALSE;
512 result.is_temporary = FALSE;
513 result.type = type_new_int(TYPE_BASIC_INT, 0);
514 break;
515 case EXPR_SHL:
516 case EXPR_SHR:
517 case EXPR_MOD:
518 case EXPR_MUL:
519 case EXPR_DIV:
520 case EXPR_ADD:
521 case EXPR_SUB:
522 case EXPR_AND:
523 case EXPR_OR:
524 case EXPR_XOR:
526 struct expression_type result_right;
527 result = resolve_expression(expr_loc, cont_type, e->ref);
528 result.is_variable = FALSE;
529 result_right = resolve_expression(expr_loc, cont_type, e->u.ext);
530 /* FIXME: these checks aren't strict enough for some of the operators */
531 check_scalar_type(expr_loc, cont_type, result.type);
532 check_scalar_type(expr_loc, cont_type, result_right.type);
533 break;
535 case EXPR_LOGOR:
536 case EXPR_LOGAND:
537 case EXPR_EQUALITY:
538 case EXPR_INEQUALITY:
539 case EXPR_GTR:
540 case EXPR_LESS:
541 case EXPR_GTREQL:
542 case EXPR_LESSEQL:
544 struct expression_type result_left, result_right;
545 result_left = resolve_expression(expr_loc, cont_type, e->ref);
546 result_right = resolve_expression(expr_loc, cont_type, e->u.ext);
547 check_scalar_type(expr_loc, cont_type, result_left.type);
548 check_scalar_type(expr_loc, cont_type, result_right.type);
549 result.is_variable = FALSE;
550 result.is_temporary = FALSE;
551 result.type = type_new_int(TYPE_BASIC_INT, 0);
552 break;
554 case EXPR_MEMBER:
555 result = resolve_expression(expr_loc, cont_type, e->ref);
556 if (result.type && is_valid_member_operand(result.type))
557 result = resolve_expression(expr_loc, result.type, e->u.ext);
558 else
559 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",
560 expr_loc->attr ? " for attribute " : "",
561 expr_loc->attr ? expr_loc->attr : "");
562 break;
563 case EXPR_COND:
565 struct expression_type result_first, result_second, result_third;
566 result_first = resolve_expression(expr_loc, cont_type, e->ref);
567 check_scalar_type(expr_loc, cont_type, result_first.type);
568 result_second = resolve_expression(expr_loc, cont_type, e->u.ext);
569 result_third = resolve_expression(expr_loc, cont_type, e->ext2);
570 /* FIXME: determine the correct return type */
571 result = result_second;
572 result.is_variable = FALSE;
573 break;
575 case EXPR_ARRAY:
576 result = resolve_expression(expr_loc, cont_type, e->ref);
577 if (result.type && is_array(result.type))
579 struct expression_type index_result;
580 result.type = type_array_get_element(result.type);
581 index_result = resolve_expression(expr_loc, cont_type /* FIXME */, e->u.ext);
582 if (!index_result.type || !is_integer_type(index_result.type))
583 error_loc_info(&expr_loc->v->loc_info, "array subscript not of integral type in expression%s%s\n",
584 expr_loc->attr ? " for attribute " : "",
585 expr_loc->attr ? expr_loc->attr : "");
587 else
588 error_loc_info(&expr_loc->v->loc_info, "array subscript operator applied to non-array type in expression%s%s\n",
589 expr_loc->attr ? " for attribute " : "",
590 expr_loc->attr ? expr_loc->attr : "");
591 break;
593 return result;
596 const type_t *expr_resolve_type(const struct expr_loc *expr_loc, const type_t *cont_type, const expr_t *expr)
598 struct expression_type expr_type;
599 expr_type = resolve_expression(expr_loc, cont_type, expr);
600 return expr_type.type;
603 void write_expr(FILE *h, const expr_t *e, int brackets,
604 int toplevel, const char *toplevel_prefix,
605 const type_t *cont_type, const char *local_var_prefix)
607 switch (e->type)
609 case EXPR_VOID:
610 break;
611 case EXPR_NUM:
612 fprintf(h, "%lu", e->u.lval);
613 break;
614 case EXPR_HEXNUM:
615 fprintf(h, "0x%lx", e->u.lval);
616 break;
617 case EXPR_DOUBLE:
618 fprintf(h, "%#.15g", e->u.dval);
619 break;
620 case EXPR_TRUEFALSE:
621 if (e->u.lval == 0)
622 fprintf(h, "FALSE");
623 else
624 fprintf(h, "TRUE");
625 break;
626 case EXPR_IDENTIFIER:
627 if (toplevel && toplevel_prefix && cont_type)
629 int found_in_cont_type;
630 find_identifier(e->u.sval, cont_type, &found_in_cont_type);
631 if (found_in_cont_type)
633 fprintf(h, "%s%s", toplevel_prefix, e->u.sval);
634 break;
637 fprintf(h, "%s%s", local_var_prefix, e->u.sval);
638 break;
639 case EXPR_STRLIT:
640 fprintf(h, "\"%s\"", e->u.sval);
641 break;
642 case EXPR_WSTRLIT:
643 fprintf(h, "L\"%s\"", e->u.sval);
644 break;
645 case EXPR_LOGNOT:
646 fprintf(h, "!");
647 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
648 break;
649 case EXPR_NOT:
650 fprintf(h, "~");
651 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
652 break;
653 case EXPR_POS:
654 fprintf(h, "+");
655 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
656 break;
657 case EXPR_NEG:
658 fprintf(h, "-");
659 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
660 break;
661 case EXPR_ADDRESSOF:
662 fprintf(h, "&");
663 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
664 break;
665 case EXPR_PPTR:
666 fprintf(h, "*");
667 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
668 break;
669 case EXPR_CAST:
670 fprintf(h, "(");
671 write_type_decl(h, e->u.tref, NULL);
672 fprintf(h, ")");
673 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
674 break;
675 case EXPR_SIZEOF:
676 fprintf(h, "sizeof(");
677 write_type_decl(h, e->u.tref, NULL);
678 fprintf(h, ")");
679 break;
680 case EXPR_SHL:
681 case EXPR_SHR:
682 case EXPR_MOD:
683 case EXPR_MUL:
684 case EXPR_DIV:
685 case EXPR_ADD:
686 case EXPR_SUB:
687 case EXPR_AND:
688 case EXPR_OR:
689 case EXPR_LOGOR:
690 case EXPR_LOGAND:
691 case EXPR_XOR:
692 case EXPR_EQUALITY:
693 case EXPR_INEQUALITY:
694 case EXPR_GTR:
695 case EXPR_LESS:
696 case EXPR_GTREQL:
697 case EXPR_LESSEQL:
698 if (brackets) fprintf(h, "(");
699 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
700 switch (e->type)
702 case EXPR_SHL: fprintf(h, " << "); break;
703 case EXPR_SHR: fprintf(h, " >> "); break;
704 case EXPR_MOD: fprintf(h, " %% "); break;
705 case EXPR_MUL: fprintf(h, " * "); break;
706 case EXPR_DIV: fprintf(h, " / "); break;
707 case EXPR_ADD: fprintf(h, " + "); break;
708 case EXPR_SUB: fprintf(h, " - "); break;
709 case EXPR_AND: fprintf(h, " & "); break;
710 case EXPR_OR: fprintf(h, " | "); break;
711 case EXPR_LOGOR: fprintf(h, " || "); break;
712 case EXPR_LOGAND: fprintf(h, " && "); break;
713 case EXPR_XOR: fprintf(h, " ^ "); break;
714 case EXPR_EQUALITY: fprintf(h, " == "); break;
715 case EXPR_INEQUALITY: fprintf(h, " != "); break;
716 case EXPR_GTR: fprintf(h, " > "); break;
717 case EXPR_LESS: fprintf(h, " < "); break;
718 case EXPR_GTREQL: fprintf(h, " >= "); break;
719 case EXPR_LESSEQL: fprintf(h, " <= "); break;
720 default: break;
722 write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
723 if (brackets) fprintf(h, ")");
724 break;
725 case EXPR_MEMBER:
726 if (brackets) fprintf(h, "(");
727 if (e->ref->type == EXPR_PPTR)
729 write_expr(h, e->ref->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
730 fprintf(h, "->");
732 else
734 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
735 fprintf(h, ".");
737 write_expr(h, e->u.ext, 1, 0, toplevel_prefix, cont_type, "");
738 if (brackets) fprintf(h, ")");
739 break;
740 case EXPR_COND:
741 if (brackets) fprintf(h, "(");
742 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
743 fprintf(h, " ? ");
744 write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
745 fprintf(h, " : ");
746 write_expr(h, e->ext2, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
747 if (brackets) fprintf(h, ")");
748 break;
749 case EXPR_ARRAY:
750 if (brackets) fprintf(h, "(");
751 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
752 fprintf(h, "[");
753 write_expr(h, e->u.ext, 1, 1, toplevel_prefix, cont_type, local_var_prefix);
754 fprintf(h, "]");
755 if (brackets) fprintf(h, ")");
756 break;
760 /* This is actually fairly involved to implement precisely, due to the
761 effects attributes may have and things like that. Right now this is
762 only used for optimization, so just check for a very small set of
763 criteria that guarantee the types are equivalent; assume every thing
764 else is different. */
765 static int compare_type(const type_t *a, const type_t *b)
767 if (a == b
768 || (a->name
769 && b->name
770 && strcmp(a->name, b->name) == 0))
771 return 0;
772 /* Ordering doesn't need to be implemented yet. */
773 return 1;
776 int compare_expr(const expr_t *a, const expr_t *b)
778 int ret;
780 if (a->type != b->type)
781 return a->type - b->type;
783 switch (a->type)
785 case EXPR_NUM:
786 case EXPR_HEXNUM:
787 case EXPR_TRUEFALSE:
788 return a->u.lval - b->u.lval;
789 case EXPR_DOUBLE:
790 return a->u.dval - b->u.dval;
791 case EXPR_IDENTIFIER:
792 case EXPR_STRLIT:
793 case EXPR_WSTRLIT:
794 return strcmp(a->u.sval, b->u.sval);
795 case EXPR_COND:
796 ret = compare_expr(a->ref, b->ref);
797 if (ret != 0)
798 return ret;
799 ret = compare_expr(a->u.ext, b->u.ext);
800 if (ret != 0)
801 return ret;
802 return compare_expr(a->ext2, b->ext2);
803 case EXPR_OR:
804 case EXPR_AND:
805 case EXPR_ADD:
806 case EXPR_SUB:
807 case EXPR_MOD:
808 case EXPR_MUL:
809 case EXPR_DIV:
810 case EXPR_SHL:
811 case EXPR_SHR:
812 case EXPR_MEMBER:
813 case EXPR_ARRAY:
814 case EXPR_LOGOR:
815 case EXPR_LOGAND:
816 case EXPR_XOR:
817 case EXPR_EQUALITY:
818 case EXPR_INEQUALITY:
819 case EXPR_GTR:
820 case EXPR_LESS:
821 case EXPR_GTREQL:
822 case EXPR_LESSEQL:
823 ret = compare_expr(a->ref, b->ref);
824 if (ret != 0)
825 return ret;
826 return compare_expr(a->u.ext, b->u.ext);
827 case EXPR_CAST:
828 ret = compare_type(a->u.tref, b->u.tref);
829 if (ret != 0)
830 return ret;
831 /* Fall through. */
832 case EXPR_NOT:
833 case EXPR_NEG:
834 case EXPR_PPTR:
835 case EXPR_ADDRESSOF:
836 case EXPR_LOGNOT:
837 case EXPR_POS:
838 return compare_expr(a->ref, b->ref);
839 case EXPR_SIZEOF:
840 return compare_type(a->u.tref, b->u.tref);
841 case EXPR_VOID:
842 return 0;
844 return -1;