msdaps: Add support for remoting IRowChange_SetColumns.
[wine/hramrach.git] / tools / widl / expr.c
blobbca7c5a3e917b268ce95b6516724aafd9b4f6d35
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 switch (type)
92 case EXPR_IDENTIFIER:
94 var_t *c = find_const(val, 0);
95 if (c)
97 e->u.sval = c->name;
98 free(val);
99 e->is_const = TRUE;
100 e->cval = c->eval->cval;
102 break;
104 case EXPR_CHARCONST:
105 if (!val[0])
106 error_loc("empty character constant\n");
107 else if (val[1])
108 error_loc("multi-character constants are endian dependent\n");
109 else
111 e->is_const = TRUE;
112 e->cval = *val;
114 break;
115 default:
116 break;
118 return e;
121 expr_t *make_exprt(enum expr_type type, var_t *var, expr_t *expr)
123 expr_t *e;
124 type_t *tref;
126 if (var->stgclass != STG_NONE && var->stgclass != STG_REGISTER)
127 error_loc("invalid storage class for type expression\n");
129 tref = var->type;
131 e = xmalloc(sizeof(expr_t));
132 e->type = type;
133 e->ref = expr;
134 e->u.tref = tref;
135 e->is_const = FALSE;
136 if (type == EXPR_SIZEOF)
138 /* only do this for types that should be the same on all platforms */
139 if (is_integer_type(tref) || is_float_type(tref))
141 unsigned int align = 0;
142 e->is_const = TRUE;
143 e->cval = type_memsize(tref, &align);
146 /* check for cast of constant expression */
147 if (type == EXPR_CAST && expr->is_const)
149 e->is_const = TRUE;
150 e->cval = expr->cval;
152 free(var);
153 return e;
156 expr_t *make_expr1(enum expr_type type, expr_t *expr)
158 expr_t *e;
159 e = xmalloc(sizeof(expr_t));
160 e->type = type;
161 e->ref = expr;
162 e->u.lval = 0;
163 e->is_const = FALSE;
164 /* check for compile-time optimization */
165 if (expr->is_const)
167 e->is_const = TRUE;
168 switch (type)
170 case EXPR_LOGNOT:
171 e->cval = !expr->cval;
172 break;
173 case EXPR_POS:
174 e->cval = +expr->cval;
175 break;
176 case EXPR_NEG:
177 e->cval = -expr->cval;
178 break;
179 case EXPR_NOT:
180 e->cval = ~expr->cval;
181 break;
182 default:
183 e->is_const = FALSE;
184 break;
187 return e;
190 expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2)
192 expr_t *e;
193 e = xmalloc(sizeof(expr_t));
194 e->type = type;
195 e->ref = expr1;
196 e->u.ext = expr2;
197 e->is_const = FALSE;
198 /* check for compile-time optimization */
199 if (expr1->is_const && expr2->is_const)
201 e->is_const = TRUE;
202 switch (type)
204 case EXPR_ADD:
205 e->cval = expr1->cval + expr2->cval;
206 break;
207 case EXPR_SUB:
208 e->cval = expr1->cval - expr2->cval;
209 break;
210 case EXPR_MOD:
211 if (expr2->cval == 0)
213 error_loc("divide by zero in expression\n");
214 e->cval = 0;
216 else
217 e->cval = expr1->cval % expr2->cval;
218 break;
219 case EXPR_MUL:
220 e->cval = expr1->cval * expr2->cval;
221 break;
222 case EXPR_DIV:
223 if (expr2->cval == 0)
225 error_loc("divide by zero in expression\n");
226 e->cval = 0;
228 else
229 e->cval = expr1->cval / expr2->cval;
230 break;
231 case EXPR_OR:
232 e->cval = expr1->cval | expr2->cval;
233 break;
234 case EXPR_AND:
235 e->cval = expr1->cval & expr2->cval;
236 break;
237 case EXPR_SHL:
238 e->cval = expr1->cval << expr2->cval;
239 break;
240 case EXPR_SHR:
241 e->cval = expr1->cval >> expr2->cval;
242 break;
243 case EXPR_LOGOR:
244 e->cval = expr1->cval || expr2->cval;
245 break;
246 case EXPR_LOGAND:
247 e->cval = expr1->cval && expr2->cval;
248 break;
249 case EXPR_XOR:
250 e->cval = expr1->cval ^ expr2->cval;
251 break;
252 case EXPR_EQUALITY:
253 e->cval = expr1->cval == expr2->cval;
254 break;
255 case EXPR_INEQUALITY:
256 e->cval = expr1->cval != expr2->cval;
257 break;
258 case EXPR_GTR:
259 e->cval = expr1->cval > expr2->cval;
260 break;
261 case EXPR_LESS:
262 e->cval = expr1->cval < expr2->cval;
263 break;
264 case EXPR_GTREQL:
265 e->cval = expr1->cval >= expr2->cval;
266 break;
267 case EXPR_LESSEQL:
268 e->cval = expr1->cval <= expr2->cval;
269 break;
270 default:
271 e->is_const = FALSE;
272 break;
275 return e;
278 expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3)
280 expr_t *e;
281 e = xmalloc(sizeof(expr_t));
282 e->type = type;
283 e->ref = expr1;
284 e->u.ext = expr2;
285 e->ext2 = expr3;
286 e->is_const = FALSE;
287 /* check for compile-time optimization */
288 if (expr1->is_const && expr2->is_const && expr3->is_const)
290 e->is_const = TRUE;
291 switch (type)
293 case EXPR_COND:
294 e->cval = expr1->cval ? expr2->cval : expr3->cval;
295 break;
296 default:
297 e->is_const = FALSE;
298 break;
301 return e;
304 struct expression_type
306 int is_variable; /* is the expression resolved to a variable? */
307 int is_temporary; /* should the type be freed? */
308 type_t *type;
311 static int is_integer_type(const type_t *type)
313 switch (type_get_type(type))
315 case TYPE_ENUM:
316 return TRUE;
317 case TYPE_BASIC:
318 switch (type_basic_get_type(type))
320 case TYPE_BASIC_INT8:
321 case TYPE_BASIC_INT16:
322 case TYPE_BASIC_INT32:
323 case TYPE_BASIC_INT64:
324 case TYPE_BASIC_INT:
325 case TYPE_BASIC_INT3264:
326 case TYPE_BASIC_CHAR:
327 case TYPE_BASIC_HYPER:
328 case TYPE_BASIC_BYTE:
329 case TYPE_BASIC_WCHAR:
330 case TYPE_BASIC_ERROR_STATUS_T:
331 return TRUE;
332 case TYPE_BASIC_FLOAT:
333 case TYPE_BASIC_DOUBLE:
334 case TYPE_BASIC_HANDLE:
335 return FALSE;
337 return FALSE;
338 default:
339 return FALSE;
343 static int is_float_type(const type_t *type)
345 return (type_get_type(type) == TYPE_BASIC &&
346 (type_basic_get_type(type) == TYPE_BASIC_FLOAT ||
347 type_basic_get_type(type) == TYPE_BASIC_DOUBLE));
350 static void check_scalar_type(const struct expr_loc *expr_loc,
351 const type_t *cont_type, const type_t *type)
353 if (!cont_type || (!is_integer_type(type) && !is_ptr(type) &&
354 !is_float_type(type)))
355 error_loc_info(&expr_loc->v->loc_info, "scalar type required in expression%s%s\n",
356 expr_loc->attr ? " for attribute " : "",
357 expr_loc->attr ? expr_loc->attr : "");
360 static void check_arithmetic_type(const struct expr_loc *expr_loc,
361 const type_t *cont_type, const type_t *type)
363 if (!cont_type || (!is_integer_type(type) && !is_float_type(type)))
364 error_loc_info(&expr_loc->v->loc_info, "arithmetic type required in expression%s%s\n",
365 expr_loc->attr ? " for attribute " : "",
366 expr_loc->attr ? expr_loc->attr : "");
369 static void check_integer_type(const struct expr_loc *expr_loc,
370 const type_t *cont_type, const type_t *type)
372 if (!cont_type || !is_integer_type(type))
373 error_loc_info(&expr_loc->v->loc_info, "integer type required in expression%s%s\n",
374 expr_loc->attr ? " for attribute " : "",
375 expr_loc->attr ? expr_loc->attr : "");
378 static type_t *find_identifier(const char *identifier, const type_t *cont_type, int *found_in_cont_type)
380 type_t *type = NULL;
381 const var_t *field;
382 const var_list_t *fields = NULL;
384 *found_in_cont_type = 0;
386 if (cont_type)
388 switch (type_get_type(cont_type))
390 case TYPE_FUNCTION:
391 fields = type_function_get_args(cont_type);
392 break;
393 case TYPE_STRUCT:
394 fields = type_struct_get_fields(cont_type);
395 break;
396 case TYPE_UNION:
397 case TYPE_ENCAPSULATED_UNION:
398 fields = type_union_get_cases(cont_type);
399 break;
400 case TYPE_VOID:
401 case TYPE_BASIC:
402 case TYPE_ENUM:
403 case TYPE_MODULE:
404 case TYPE_COCLASS:
405 case TYPE_INTERFACE:
406 case TYPE_POINTER:
407 case TYPE_ARRAY:
408 case TYPE_BITFIELD:
409 /* nothing to do */
410 break;
411 case TYPE_ALIAS:
412 /* shouldn't get here because of using type_get_type above */
413 assert(0);
414 break;
418 if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
419 if (field->name && !strcmp(identifier, field->name))
421 type = field->type;
422 *found_in_cont_type = 1;
423 break;
426 if (!type)
428 var_t *const_var = find_const(identifier, 0);
429 if (const_var) type = const_var->type;
432 return type;
435 static int is_valid_member_operand(const type_t *type)
437 switch (type_get_type(type))
439 case TYPE_STRUCT:
440 case TYPE_UNION:
441 case TYPE_ENUM:
442 return TRUE;
443 default:
444 return FALSE;
448 static struct expression_type resolve_expression(const struct expr_loc *expr_loc,
449 const type_t *cont_type,
450 const expr_t *e)
452 struct expression_type result;
453 result.is_variable = FALSE;
454 result.is_temporary = FALSE;
455 result.type = NULL;
456 switch (e->type)
458 case EXPR_VOID:
459 break;
460 case EXPR_HEXNUM:
461 case EXPR_NUM:
462 case EXPR_TRUEFALSE:
463 result.is_variable = FALSE;
464 result.is_temporary = FALSE;
465 result.type = type_new_int(TYPE_BASIC_INT, 0);
466 break;
467 case EXPR_STRLIT:
468 result.is_variable = FALSE;
469 result.is_temporary = TRUE;
470 result.type = type_new_pointer(RPC_FC_UP, type_new_int(TYPE_BASIC_CHAR, 0), NULL);
471 break;
472 case EXPR_WSTRLIT:
473 result.is_variable = FALSE;
474 result.is_temporary = TRUE;
475 result.type = type_new_pointer(RPC_FC_UP, type_new_int(TYPE_BASIC_WCHAR, 0), NULL);
476 break;
477 case EXPR_CHARCONST:
478 result.is_variable = FALSE;
479 result.is_temporary = TRUE;
480 result.type = type_new_int(TYPE_BASIC_CHAR, 0);
481 break;
482 case EXPR_DOUBLE:
483 result.is_variable = FALSE;
484 result.is_temporary = TRUE;
485 result.type = type_new_basic(TYPE_BASIC_DOUBLE);
486 break;
487 case EXPR_IDENTIFIER:
489 int found_in_cont_type;
490 result.is_variable = TRUE;
491 result.is_temporary = FALSE;
492 result.type = find_identifier(e->u.sval, cont_type, &found_in_cont_type);
493 if (!result.type)
495 error_loc_info(&expr_loc->v->loc_info, "identifier %s cannot be resolved in expression%s%s\n",
496 e->u.sval, expr_loc->attr ? " for attribute " : "",
497 expr_loc->attr ? expr_loc->attr : "");
499 break;
501 case EXPR_LOGNOT:
502 result = resolve_expression(expr_loc, cont_type, e->ref);
503 check_scalar_type(expr_loc, cont_type, result.type);
504 result.is_variable = FALSE;
505 result.is_temporary = FALSE;
506 result.type = type_new_int(TYPE_BASIC_INT, 0);
507 break;
508 case EXPR_NOT:
509 result = resolve_expression(expr_loc, cont_type, e->ref);
510 check_integer_type(expr_loc, cont_type, result.type);
511 result.is_variable = FALSE;
512 break;
513 case EXPR_POS:
514 case EXPR_NEG:
515 result = resolve_expression(expr_loc, cont_type, e->ref);
516 check_arithmetic_type(expr_loc, cont_type, result.type);
517 result.is_variable = FALSE;
518 break;
519 case EXPR_ADDRESSOF:
520 result = resolve_expression(expr_loc, cont_type, e->ref);
521 if (!result.is_variable)
522 error_loc_info(&expr_loc->v->loc_info, "address-of operator applied to non-variable type in expression%s%s\n",
523 expr_loc->attr ? " for attribute " : "",
524 expr_loc->attr ? expr_loc->attr : "");
525 result.is_variable = FALSE;
526 result.is_temporary = TRUE;
527 result.type = type_new_pointer(RPC_FC_UP, result.type, NULL);
528 break;
529 case EXPR_PPTR:
530 result = resolve_expression(expr_loc, cont_type, e->ref);
531 if (result.type && is_ptr(result.type))
532 result.type = type_pointer_get_ref(result.type);
533 else if(result.type && is_array(result.type)
534 && type_array_is_decl_as_ptr(result.type))
535 result.type = type_array_get_element(result.type);
536 else
537 error_loc_info(&expr_loc->v->loc_info, "dereference operator applied to non-pointer type in expression%s%s\n",
538 expr_loc->attr ? " for attribute " : "",
539 expr_loc->attr ? expr_loc->attr : "");
540 break;
541 case EXPR_CAST:
542 result = resolve_expression(expr_loc, cont_type, e->ref);
543 result.type = e->u.tref;
544 break;
545 case EXPR_SIZEOF:
546 result.is_variable = FALSE;
547 result.is_temporary = FALSE;
548 result.type = type_new_int(TYPE_BASIC_INT, 0);
549 break;
550 case EXPR_SHL:
551 case EXPR_SHR:
552 case EXPR_MOD:
553 case EXPR_MUL:
554 case EXPR_DIV:
555 case EXPR_ADD:
556 case EXPR_SUB:
557 case EXPR_AND:
558 case EXPR_OR:
559 case EXPR_XOR:
561 struct expression_type result_right;
562 result = resolve_expression(expr_loc, cont_type, e->ref);
563 result.is_variable = FALSE;
564 result_right = resolve_expression(expr_loc, cont_type, e->u.ext);
565 /* FIXME: these checks aren't strict enough for some of the operators */
566 check_scalar_type(expr_loc, cont_type, result.type);
567 check_scalar_type(expr_loc, cont_type, result_right.type);
568 break;
570 case EXPR_LOGOR:
571 case EXPR_LOGAND:
572 case EXPR_EQUALITY:
573 case EXPR_INEQUALITY:
574 case EXPR_GTR:
575 case EXPR_LESS:
576 case EXPR_GTREQL:
577 case EXPR_LESSEQL:
579 struct expression_type result_left, result_right;
580 result_left = resolve_expression(expr_loc, cont_type, e->ref);
581 result_right = resolve_expression(expr_loc, cont_type, e->u.ext);
582 check_scalar_type(expr_loc, cont_type, result_left.type);
583 check_scalar_type(expr_loc, cont_type, result_right.type);
584 result.is_variable = FALSE;
585 result.is_temporary = FALSE;
586 result.type = type_new_int(TYPE_BASIC_INT, 0);
587 break;
589 case EXPR_MEMBER:
590 result = resolve_expression(expr_loc, cont_type, e->ref);
591 if (result.type && is_valid_member_operand(result.type))
592 result = resolve_expression(expr_loc, result.type, e->u.ext);
593 else
594 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",
595 expr_loc->attr ? " for attribute " : "",
596 expr_loc->attr ? expr_loc->attr : "");
597 break;
598 case EXPR_COND:
600 struct expression_type result_first, result_second, result_third;
601 result_first = resolve_expression(expr_loc, cont_type, e->ref);
602 check_scalar_type(expr_loc, cont_type, result_first.type);
603 result_second = resolve_expression(expr_loc, cont_type, e->u.ext);
604 result_third = resolve_expression(expr_loc, cont_type, e->ext2);
605 /* FIXME: determine the correct return type */
606 result = result_second;
607 result.is_variable = FALSE;
608 break;
610 case EXPR_ARRAY:
611 result = resolve_expression(expr_loc, cont_type, e->ref);
612 if (result.type && is_array(result.type))
614 struct expression_type index_result;
615 result.type = type_array_get_element(result.type);
616 index_result = resolve_expression(expr_loc, cont_type /* FIXME */, e->u.ext);
617 if (!index_result.type || !is_integer_type(index_result.type))
618 error_loc_info(&expr_loc->v->loc_info, "array subscript not of integral type in expression%s%s\n",
619 expr_loc->attr ? " for attribute " : "",
620 expr_loc->attr ? expr_loc->attr : "");
622 else
623 error_loc_info(&expr_loc->v->loc_info, "array subscript operator applied to non-array type in expression%s%s\n",
624 expr_loc->attr ? " for attribute " : "",
625 expr_loc->attr ? expr_loc->attr : "");
626 break;
628 return result;
631 const type_t *expr_resolve_type(const struct expr_loc *expr_loc, const type_t *cont_type, const expr_t *expr)
633 struct expression_type expr_type;
634 expr_type = resolve_expression(expr_loc, cont_type, expr);
635 return expr_type.type;
638 void write_expr(FILE *h, const expr_t *e, int brackets,
639 int toplevel, const char *toplevel_prefix,
640 const type_t *cont_type, const char *local_var_prefix)
642 switch (e->type)
644 case EXPR_VOID:
645 break;
646 case EXPR_NUM:
647 fprintf(h, "%lu", e->u.lval);
648 break;
649 case EXPR_HEXNUM:
650 fprintf(h, "0x%lx", e->u.lval);
651 break;
652 case EXPR_DOUBLE:
653 fprintf(h, "%#.15g", e->u.dval);
654 break;
655 case EXPR_TRUEFALSE:
656 if (e->u.lval == 0)
657 fprintf(h, "FALSE");
658 else
659 fprintf(h, "TRUE");
660 break;
661 case EXPR_IDENTIFIER:
662 if (toplevel && toplevel_prefix && cont_type)
664 int found_in_cont_type;
665 find_identifier(e->u.sval, cont_type, &found_in_cont_type);
666 if (found_in_cont_type)
668 fprintf(h, "%s%s", toplevel_prefix, e->u.sval);
669 break;
672 fprintf(h, "%s%s", local_var_prefix, e->u.sval);
673 break;
674 case EXPR_STRLIT:
675 fprintf(h, "\"%s\"", e->u.sval);
676 break;
677 case EXPR_WSTRLIT:
678 fprintf(h, "L\"%s\"", e->u.sval);
679 break;
680 case EXPR_CHARCONST:
681 fprintf(h, "'%s'", e->u.sval);
682 break;
683 case EXPR_LOGNOT:
684 fprintf(h, "!");
685 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
686 break;
687 case EXPR_NOT:
688 fprintf(h, "~");
689 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
690 break;
691 case EXPR_POS:
692 fprintf(h, "+");
693 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
694 break;
695 case EXPR_NEG:
696 fprintf(h, "-");
697 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
698 break;
699 case EXPR_ADDRESSOF:
700 fprintf(h, "&");
701 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
702 break;
703 case EXPR_PPTR:
704 fprintf(h, "*");
705 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
706 break;
707 case EXPR_CAST:
708 fprintf(h, "(");
709 write_type_decl(h, e->u.tref, NULL);
710 fprintf(h, ")");
711 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
712 break;
713 case EXPR_SIZEOF:
714 fprintf(h, "sizeof(");
715 write_type_decl(h, e->u.tref, NULL);
716 fprintf(h, ")");
717 break;
718 case EXPR_SHL:
719 case EXPR_SHR:
720 case EXPR_MOD:
721 case EXPR_MUL:
722 case EXPR_DIV:
723 case EXPR_ADD:
724 case EXPR_SUB:
725 case EXPR_AND:
726 case EXPR_OR:
727 case EXPR_LOGOR:
728 case EXPR_LOGAND:
729 case EXPR_XOR:
730 case EXPR_EQUALITY:
731 case EXPR_INEQUALITY:
732 case EXPR_GTR:
733 case EXPR_LESS:
734 case EXPR_GTREQL:
735 case EXPR_LESSEQL:
736 if (brackets) fprintf(h, "(");
737 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
738 switch (e->type)
740 case EXPR_SHL: fprintf(h, " << "); break;
741 case EXPR_SHR: fprintf(h, " >> "); break;
742 case EXPR_MOD: fprintf(h, " %% "); break;
743 case EXPR_MUL: fprintf(h, " * "); break;
744 case EXPR_DIV: fprintf(h, " / "); break;
745 case EXPR_ADD: fprintf(h, " + "); break;
746 case EXPR_SUB: fprintf(h, " - "); break;
747 case EXPR_AND: fprintf(h, " & "); break;
748 case EXPR_OR: fprintf(h, " | "); break;
749 case EXPR_LOGOR: fprintf(h, " || "); break;
750 case EXPR_LOGAND: fprintf(h, " && "); break;
751 case EXPR_XOR: fprintf(h, " ^ "); break;
752 case EXPR_EQUALITY: fprintf(h, " == "); break;
753 case EXPR_INEQUALITY: fprintf(h, " != "); break;
754 case EXPR_GTR: fprintf(h, " > "); break;
755 case EXPR_LESS: fprintf(h, " < "); break;
756 case EXPR_GTREQL: fprintf(h, " >= "); break;
757 case EXPR_LESSEQL: fprintf(h, " <= "); break;
758 default: break;
760 write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
761 if (brackets) fprintf(h, ")");
762 break;
763 case EXPR_MEMBER:
764 if (brackets) fprintf(h, "(");
765 if (e->ref->type == EXPR_PPTR)
767 write_expr(h, e->ref->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
768 fprintf(h, "->");
770 else
772 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
773 fprintf(h, ".");
775 write_expr(h, e->u.ext, 1, 0, toplevel_prefix, cont_type, "");
776 if (brackets) fprintf(h, ")");
777 break;
778 case EXPR_COND:
779 if (brackets) fprintf(h, "(");
780 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
781 fprintf(h, " ? ");
782 write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
783 fprintf(h, " : ");
784 write_expr(h, e->ext2, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
785 if (brackets) fprintf(h, ")");
786 break;
787 case EXPR_ARRAY:
788 if (brackets) fprintf(h, "(");
789 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
790 fprintf(h, "[");
791 write_expr(h, e->u.ext, 1, 1, toplevel_prefix, cont_type, local_var_prefix);
792 fprintf(h, "]");
793 if (brackets) fprintf(h, ")");
794 break;
798 /* This is actually fairly involved to implement precisely, due to the
799 effects attributes may have and things like that. Right now this is
800 only used for optimization, so just check for a very small set of
801 criteria that guarantee the types are equivalent; assume every thing
802 else is different. */
803 static int compare_type(const type_t *a, const type_t *b)
805 if (a == b
806 || (a->name
807 && b->name
808 && strcmp(a->name, b->name) == 0))
809 return 0;
810 /* Ordering doesn't need to be implemented yet. */
811 return 1;
814 int compare_expr(const expr_t *a, const expr_t *b)
816 int ret;
818 if (a->type != b->type)
819 return a->type - b->type;
821 switch (a->type)
823 case EXPR_NUM:
824 case EXPR_HEXNUM:
825 case EXPR_TRUEFALSE:
826 return a->u.lval - b->u.lval;
827 case EXPR_DOUBLE:
828 return a->u.dval - b->u.dval;
829 case EXPR_IDENTIFIER:
830 case EXPR_STRLIT:
831 case EXPR_WSTRLIT:
832 case EXPR_CHARCONST:
833 return strcmp(a->u.sval, b->u.sval);
834 case EXPR_COND:
835 ret = compare_expr(a->ref, b->ref);
836 if (ret != 0)
837 return ret;
838 ret = compare_expr(a->u.ext, b->u.ext);
839 if (ret != 0)
840 return ret;
841 return compare_expr(a->ext2, b->ext2);
842 case EXPR_OR:
843 case EXPR_AND:
844 case EXPR_ADD:
845 case EXPR_SUB:
846 case EXPR_MOD:
847 case EXPR_MUL:
848 case EXPR_DIV:
849 case EXPR_SHL:
850 case EXPR_SHR:
851 case EXPR_MEMBER:
852 case EXPR_ARRAY:
853 case EXPR_LOGOR:
854 case EXPR_LOGAND:
855 case EXPR_XOR:
856 case EXPR_EQUALITY:
857 case EXPR_INEQUALITY:
858 case EXPR_GTR:
859 case EXPR_LESS:
860 case EXPR_GTREQL:
861 case EXPR_LESSEQL:
862 ret = compare_expr(a->ref, b->ref);
863 if (ret != 0)
864 return ret;
865 return compare_expr(a->u.ext, b->u.ext);
866 case EXPR_CAST:
867 ret = compare_type(a->u.tref, b->u.tref);
868 if (ret != 0)
869 return ret;
870 /* Fall through. */
871 case EXPR_NOT:
872 case EXPR_NEG:
873 case EXPR_PPTR:
874 case EXPR_ADDRESSOF:
875 case EXPR_LOGNOT:
876 case EXPR_POS:
877 return compare_expr(a->ref, b->ref);
878 case EXPR_SIZEOF:
879 return compare_type(a->u.tref, b->u.tref);
880 case EXPR_VOID:
881 return 0;
883 return -1;