b5283767288966171ccda39471be6edf37b05dcf
[reactos.git] / reactos / tools / widl / expr.c
1 /*
2 * Expression Abstract Syntax Tree Functions
3 *
4 * Copyright 2002 Ove Kaaven
5 * Copyright 2006-2008 Robert Shearman
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #include "config.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <assert.h>
28 #include <ctype.h>
29 #include <string.h>
30
31 #include "widl.h"
32 #include "utils.h"
33 #include "expr.h"
34 #include "header.h"
35 #include "typetree.h"
36 #include "typegen.h"
37
38 static int is_integer_type(const type_t *type);
39 static int is_float_type(const type_t *type);
40
41 expr_t *make_expr(enum expr_type type)
42 {
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;
50 }
51
52 expr_t *make_exprl(enum expr_type type, long val)
53 {
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)
61 {
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;
66 }
67 return e;
68 }
69
70 expr_t *make_exprd(enum expr_type type, double val)
71 {
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;
79 }
80
81 expr_t *make_exprs(enum expr_type type, char *val)
82 {
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)
91 {
92 var_t *c = find_const(val, 0);
93 if (c)
94 {
95 e->u.sval = c->name;
96 free(val);
97 e->is_const = TRUE;
98 e->cval = c->eval->cval;
99 }
100 }
101 return e;
102 }
103
104 expr_t *make_exprt(enum expr_type type, var_t *var, expr_t *expr)
105 {
106 expr_t *e;
107 type_t *tref;
108
109 if (var->stgclass != STG_NONE && var->stgclass != STG_REGISTER)
110 error_loc("invalid storage class for type expression\n");
111
112 tref = var->type;
113
114 e = xmalloc(sizeof(expr_t));
115 e->type = type;
116 e->ref = expr;
117 e->u.tref = tref;
118 e->is_const = FALSE;
119 if (type == EXPR_SIZEOF)
120 {
121 /* only do this for types that should be the same on all platforms */
122 if (is_integer_type(tref) || is_float_type(tref))
123 {
124 unsigned int align = 0;
125 e->is_const = TRUE;
126 e->cval = type_memsize(tref, &align);
127 }
128 }
129 /* check for cast of constant expression */
130 if (type == EXPR_CAST && expr->is_const)
131 {
132 e->is_const = TRUE;
133 e->cval = expr->cval;
134 }
135 free(var);
136 return e;
137 }
138
139 expr_t *make_expr1(enum expr_type type, expr_t *expr)
140 {
141 expr_t *e;
142 e = xmalloc(sizeof(expr_t));
143 e->type = type;
144 e->ref = expr;
145 e->u.lval = 0;
146 e->is_const = FALSE;
147 /* check for compile-time optimization */
148 if (expr->is_const)
149 {
150 e->is_const = TRUE;
151 switch (type)
152 {
153 case EXPR_LOGNOT:
154 e->cval = !expr->cval;
155 break;
156 case EXPR_POS:
157 e->cval = +expr->cval;
158 break;
159 case EXPR_NEG:
160 e->cval = -expr->cval;
161 break;
162 case EXPR_NOT:
163 e->cval = ~expr->cval;
164 break;
165 default:
166 e->is_const = FALSE;
167 break;
168 }
169 }
170 return e;
171 }
172
173 expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2)
174 {
175 expr_t *e;
176 e = xmalloc(sizeof(expr_t));
177 e->type = type;
178 e->ref = expr1;
179 e->u.ext = expr2;
180 e->is_const = FALSE;
181 /* check for compile-time optimization */
182 if (expr1->is_const && expr2->is_const)
183 {
184 e->is_const = TRUE;
185 switch (type)
186 {
187 case EXPR_ADD:
188 e->cval = expr1->cval + expr2->cval;
189 break;
190 case EXPR_SUB:
191 e->cval = expr1->cval - expr2->cval;
192 break;
193 case EXPR_MOD:
194 if (expr2->cval == 0)
195 {
196 error_loc("divide by zero in expression\n");
197 e->cval = 0;
198 }
199 else
200 e->cval = expr1->cval % expr2->cval;
201 break;
202 case EXPR_MUL:
203 e->cval = expr1->cval * expr2->cval;
204 break;
205 case EXPR_DIV:
206 if (expr2->cval == 0)
207 {
208 error_loc("divide by zero in expression\n");
209 e->cval = 0;
210 }
211 else
212 e->cval = expr1->cval / expr2->cval;
213 break;
214 case EXPR_OR:
215 e->cval = expr1->cval | expr2->cval;
216 break;
217 case EXPR_AND:
218 e->cval = expr1->cval & expr2->cval;
219 break;
220 case EXPR_SHL:
221 e->cval = expr1->cval << expr2->cval;
222 break;
223 case EXPR_SHR:
224 e->cval = expr1->cval >> expr2->cval;
225 break;
226 case EXPR_LOGOR:
227 e->cval = expr1->cval || expr2->cval;
228 break;
229 case EXPR_LOGAND:
230 e->cval = expr1->cval && expr2->cval;
231 break;
232 case EXPR_XOR:
233 e->cval = expr1->cval ^ expr2->cval;
234 break;
235 case EXPR_EQUALITY:
236 e->cval = expr1->cval == expr2->cval;
237 break;
238 case EXPR_INEQUALITY:
239 e->cval = expr1->cval != expr2->cval;
240 break;
241 case EXPR_GTR:
242 e->cval = expr1->cval > expr2->cval;
243 break;
244 case EXPR_LESS:
245 e->cval = expr1->cval < expr2->cval;
246 break;
247 case EXPR_GTREQL:
248 e->cval = expr1->cval >= expr2->cval;
249 break;
250 case EXPR_LESSEQL:
251 e->cval = expr1->cval <= expr2->cval;
252 break;
253 default:
254 e->is_const = FALSE;
255 break;
256 }
257 }
258 return e;
259 }
260
261 expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3)
262 {
263 expr_t *e;
264 e = xmalloc(sizeof(expr_t));
265 e->type = type;
266 e->ref = expr1;
267 e->u.ext = expr2;
268 e->ext2 = expr3;
269 e->is_const = FALSE;
270 /* check for compile-time optimization */
271 if (expr1->is_const && expr2->is_const && expr3->is_const)
272 {
273 e->is_const = TRUE;
274 switch (type)
275 {
276 case EXPR_COND:
277 e->cval = expr1->cval ? expr2->cval : expr3->cval;
278 break;
279 default:
280 e->is_const = FALSE;
281 break;
282 }
283 }
284 return e;
285 }
286
287 struct expression_type
288 {
289 int is_variable; /* is the expression resolved to a variable? */
290 int is_temporary; /* should the type be freed? */
291 type_t *type;
292 };
293
294 static int is_integer_type(const type_t *type)
295 {
296 switch (type_get_type(type))
297 {
298 case TYPE_ENUM:
299 return TRUE;
300 case TYPE_BASIC:
301 switch (type_basic_get_type(type))
302 {
303 case TYPE_BASIC_INT8:
304 case TYPE_BASIC_INT16:
305 case TYPE_BASIC_INT32:
306 case TYPE_BASIC_INT64:
307 case TYPE_BASIC_INT:
308 case TYPE_BASIC_INT3264:
309 case TYPE_BASIC_CHAR:
310 case TYPE_BASIC_HYPER:
311 case TYPE_BASIC_BYTE:
312 case TYPE_BASIC_WCHAR:
313 case TYPE_BASIC_ERROR_STATUS_T:
314 return TRUE;
315 case TYPE_BASIC_FLOAT:
316 case TYPE_BASIC_DOUBLE:
317 case TYPE_BASIC_HANDLE:
318 return FALSE;
319 }
320 return FALSE;
321 default:
322 return FALSE;
323 }
324 }
325
326 static int is_float_type(const type_t *type)
327 {
328 return (type_get_type(type) == TYPE_BASIC &&
329 (type_basic_get_type(type) == TYPE_BASIC_FLOAT ||
330 type_basic_get_type(type) == TYPE_BASIC_DOUBLE));
331 }
332
333 static void check_scalar_type(const struct expr_loc *expr_loc,
334 const type_t *cont_type, const type_t *type)
335 {
336 if (!cont_type || (!is_integer_type(type) && !is_ptr(type) &&
337 !is_float_type(type)))
338 error_loc_info(&expr_loc->v->loc_info, "scalar type required in expression%s%s\n",
339 expr_loc->attr ? " for attribute " : "",
340 expr_loc->attr ? expr_loc->attr : "");
341 }
342
343 static void check_arithmetic_type(const struct expr_loc *expr_loc,
344 const type_t *cont_type, const type_t *type)
345 {
346 if (!cont_type || (!is_integer_type(type) && !is_float_type(type)))
347 error_loc_info(&expr_loc->v->loc_info, "arithmetic type required in expression%s%s\n",
348 expr_loc->attr ? " for attribute " : "",
349 expr_loc->attr ? expr_loc->attr : "");
350 }
351
352 static void check_integer_type(const struct expr_loc *expr_loc,
353 const type_t *cont_type, const type_t *type)
354 {
355 if (!cont_type || !is_integer_type(type))
356 error_loc_info(&expr_loc->v->loc_info, "integer type required in expression%s%s\n",
357 expr_loc->attr ? " for attribute " : "",
358 expr_loc->attr ? expr_loc->attr : "");
359 }
360
361 static type_t *find_identifier(const char *identifier, const type_t *cont_type, int *found_in_cont_type)
362 {
363 type_t *type = NULL;
364 const var_t *field;
365 const var_list_t *fields = NULL;
366
367 *found_in_cont_type = 0;
368
369 if (cont_type)
370 {
371 switch (type_get_type(cont_type))
372 {
373 case TYPE_FUNCTION:
374 fields = type_function_get_args(cont_type);
375 break;
376 case TYPE_STRUCT:
377 fields = type_struct_get_fields(cont_type);
378 break;
379 case TYPE_UNION:
380 case TYPE_ENCAPSULATED_UNION:
381 fields = type_union_get_cases(cont_type);
382 break;
383 case TYPE_VOID:
384 case TYPE_BASIC:
385 case TYPE_ENUM:
386 case TYPE_MODULE:
387 case TYPE_COCLASS:
388 case TYPE_INTERFACE:
389 case TYPE_POINTER:
390 case TYPE_ARRAY:
391 case TYPE_BITFIELD:
392 /* nothing to do */
393 break;
394 case TYPE_ALIAS:
395 /* shouldn't get here because of using type_get_type above */
396 assert(0);
397 break;
398 }
399 }
400
401 if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
402 if (field->name && !strcmp(identifier, field->name))
403 {
404 type = field->type;
405 *found_in_cont_type = 1;
406 break;
407 }
408
409 if (!type)
410 {
411 var_t *const_var = find_const(identifier, 0);
412 if (const_var) type = const_var->type;
413 }
414
415 return type;
416 }
417
418 static int is_valid_member_operand(const type_t *type)
419 {
420 switch (type_get_type(type))
421 {
422 case TYPE_STRUCT:
423 case TYPE_UNION:
424 case TYPE_ENUM:
425 return TRUE;
426 default:
427 return FALSE;
428 }
429 }
430
431 static struct expression_type resolve_expression(const struct expr_loc *expr_loc,
432 const type_t *cont_type,
433 const expr_t *e)
434 {
435 struct expression_type result;
436 result.is_variable = FALSE;
437 result.is_temporary = FALSE;
438 result.type = NULL;
439 switch (e->type)
440 {
441 case EXPR_VOID:
442 break;
443 case EXPR_HEXNUM:
444 case EXPR_NUM:
445 case EXPR_TRUEFALSE:
446 result.is_variable = FALSE;
447 result.is_temporary = FALSE;
448 result.type = type_new_int(TYPE_BASIC_INT, 0);
449 break;
450 case EXPR_STRLIT:
451 result.is_variable = FALSE;
452 result.is_temporary = TRUE;
453 result.type = type_new_pointer(RPC_FC_UP, type_new_int(TYPE_BASIC_CHAR, 0), NULL);
454 break;
455 case EXPR_WSTRLIT:
456 result.is_variable = FALSE;
457 result.is_temporary = TRUE;
458 result.type = type_new_pointer(RPC_FC_UP, type_new_int(TYPE_BASIC_WCHAR, 0), NULL);
459 break;
460 case EXPR_DOUBLE:
461 result.is_variable = FALSE;
462 result.is_temporary = TRUE;
463 result.type = type_new_basic(TYPE_BASIC_DOUBLE);
464 break;
465 case EXPR_IDENTIFIER:
466 {
467 int found_in_cont_type;
468 result.is_variable = TRUE;
469 result.is_temporary = FALSE;
470 result.type = find_identifier(e->u.sval, cont_type, &found_in_cont_type);
471 if (!result.type)
472 {
473 error_loc_info(&expr_loc->v->loc_info, "identifier %s cannot be resolved in expression%s%s\n",
474 e->u.sval, expr_loc->attr ? " for attribute " : "",
475 expr_loc->attr ? expr_loc->attr : "");
476 }
477 break;
478 }
479 case EXPR_LOGNOT:
480 result = resolve_expression(expr_loc, cont_type, e->ref);
481 check_scalar_type(expr_loc, cont_type, result.type);
482 result.is_variable = FALSE;
483 result.is_temporary = FALSE;
484 result.type = type_new_int(TYPE_BASIC_INT, 0);
485 break;
486 case EXPR_NOT:
487 result = resolve_expression(expr_loc, cont_type, e->ref);
488 check_integer_type(expr_loc, cont_type, result.type);
489 result.is_variable = FALSE;
490 break;
491 case EXPR_POS:
492 case EXPR_NEG:
493 result = resolve_expression(expr_loc, cont_type, e->ref);
494 check_arithmetic_type(expr_loc, cont_type, result.type);
495 result.is_variable = FALSE;
496 break;
497 case EXPR_ADDRESSOF:
498 result = resolve_expression(expr_loc, cont_type, e->ref);
499 if (!result.is_variable)
500 error_loc_info(&expr_loc->v->loc_info, "address-of operator applied to non-variable type in expression%s%s\n",
501 expr_loc->attr ? " for attribute " : "",
502 expr_loc->attr ? expr_loc->attr : "");
503 result.is_variable = FALSE;
504 result.is_temporary = TRUE;
505 result.type = type_new_pointer(RPC_FC_UP, result.type, NULL);
506 break;
507 case EXPR_PPTR:
508 result = resolve_expression(expr_loc, cont_type, e->ref);
509 if (result.type && is_ptr(result.type))
510 result.type = type_pointer_get_ref(result.type);
511 else if(result.type && is_array(result.type)
512 && type_array_is_decl_as_ptr(result.type))
513 result.type = type_array_get_element(result.type);
514 else
515 error_loc_info(&expr_loc->v->loc_info, "dereference operator applied to non-pointer type in expression%s%s\n",
516 expr_loc->attr ? " for attribute " : "",
517 expr_loc->attr ? expr_loc->attr : "");
518 break;
519 case EXPR_CAST:
520 result = resolve_expression(expr_loc, cont_type, e->ref);
521 result.type = e->u.tref;
522 break;
523 case EXPR_SIZEOF:
524 result.is_variable = FALSE;
525 result.is_temporary = FALSE;
526 result.type = type_new_int(TYPE_BASIC_INT, 0);
527 break;
528 case EXPR_SHL:
529 case EXPR_SHR:
530 case EXPR_MOD:
531 case EXPR_MUL:
532 case EXPR_DIV:
533 case EXPR_ADD:
534 case EXPR_SUB:
535 case EXPR_AND:
536 case EXPR_OR:
537 case EXPR_XOR:
538 {
539 struct expression_type result_right;
540 result = resolve_expression(expr_loc, cont_type, e->ref);
541 result.is_variable = FALSE;
542 result_right = resolve_expression(expr_loc, cont_type, e->u.ext);
543 /* FIXME: these checks aren't strict enough for some of the operators */
544 check_scalar_type(expr_loc, cont_type, result.type);
545 check_scalar_type(expr_loc, cont_type, result_right.type);
546 break;
547 }
548 case EXPR_LOGOR:
549 case EXPR_LOGAND:
550 case EXPR_EQUALITY:
551 case EXPR_INEQUALITY:
552 case EXPR_GTR:
553 case EXPR_LESS:
554 case EXPR_GTREQL:
555 case EXPR_LESSEQL:
556 {
557 struct expression_type result_left, result_right;
558 result_left = resolve_expression(expr_loc, cont_type, e->ref);
559 result_right = resolve_expression(expr_loc, cont_type, e->u.ext);
560 check_scalar_type(expr_loc, cont_type, result_left.type);
561 check_scalar_type(expr_loc, cont_type, result_right.type);
562 result.is_variable = FALSE;
563 result.is_temporary = FALSE;
564 result.type = type_new_int(TYPE_BASIC_INT, 0);
565 break;
566 }
567 case EXPR_MEMBER:
568 result = resolve_expression(expr_loc, cont_type, e->ref);
569 if (result.type && is_valid_member_operand(result.type))
570 result = resolve_expression(expr_loc, result.type, e->u.ext);
571 else
572 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",
573 expr_loc->attr ? " for attribute " : "",
574 expr_loc->attr ? expr_loc->attr : "");
575 break;
576 case EXPR_COND:
577 {
578 struct expression_type result_first, result_second, result_third;
579 result_first = resolve_expression(expr_loc, cont_type, e->ref);
580 check_scalar_type(expr_loc, cont_type, result_first.type);
581 result_second = resolve_expression(expr_loc, cont_type, e->u.ext);
582 result_third = resolve_expression(expr_loc, cont_type, e->ext2);
583 /* FIXME: determine the correct return type */
584 result = result_second;
585 result.is_variable = FALSE;
586 break;
587 }
588 case EXPR_ARRAY:
589 result = resolve_expression(expr_loc, cont_type, e->ref);
590 if (result.type && is_array(result.type))
591 {
592 struct expression_type index_result;
593 result.type = type_array_get_element(result.type);
594 index_result = resolve_expression(expr_loc, cont_type /* FIXME */, e->u.ext);
595 if (!index_result.type || !is_integer_type(index_result.type))
596 error_loc_info(&expr_loc->v->loc_info, "array subscript not of integral type in expression%s%s\n",
597 expr_loc->attr ? " for attribute " : "",
598 expr_loc->attr ? expr_loc->attr : "");
599 }
600 else
601 error_loc_info(&expr_loc->v->loc_info, "array subscript operator applied to non-array type in expression%s%s\n",
602 expr_loc->attr ? " for attribute " : "",
603 expr_loc->attr ? expr_loc->attr : "");
604 break;
605 }
606 return result;
607 }
608
609 const type_t *expr_resolve_type(const struct expr_loc *expr_loc, const type_t *cont_type, const expr_t *expr)
610 {
611 struct expression_type expr_type;
612 expr_type = resolve_expression(expr_loc, cont_type, expr);
613 return expr_type.type;
614 }
615
616 void write_expr(FILE *h, const expr_t *e, int brackets,
617 int toplevel, const char *toplevel_prefix,
618 const type_t *cont_type, const char *local_var_prefix)
619 {
620 switch (e->type)
621 {
622 case EXPR_VOID:
623 break;
624 case EXPR_NUM:
625 fprintf(h, "%lu", e->u.lval);
626 break;
627 case EXPR_HEXNUM:
628 fprintf(h, "0x%lx", e->u.lval);
629 break;
630 case EXPR_DOUBLE:
631 fprintf(h, "%#.15g", e->u.dval);
632 break;
633 case EXPR_TRUEFALSE:
634 if (e->u.lval == 0)
635 fprintf(h, "FALSE");
636 else
637 fprintf(h, "TRUE");
638 break;
639 case EXPR_IDENTIFIER:
640 if (toplevel && toplevel_prefix && cont_type)
641 {
642 int found_in_cont_type;
643 find_identifier(e->u.sval, cont_type, &found_in_cont_type);
644 if (found_in_cont_type)
645 {
646 fprintf(h, "%s%s", toplevel_prefix, e->u.sval);
647 break;
648 }
649 }
650 fprintf(h, "%s%s", local_var_prefix, e->u.sval);
651 break;
652 case EXPR_STRLIT:
653 fprintf(h, "\"%s\"", e->u.sval);
654 break;
655 case EXPR_WSTRLIT:
656 fprintf(h, "L\"%s\"", e->u.sval);
657 break;
658 case EXPR_LOGNOT:
659 fprintf(h, "!");
660 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
661 break;
662 case EXPR_NOT:
663 fprintf(h, "~");
664 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
665 break;
666 case EXPR_POS:
667 fprintf(h, "+");
668 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
669 break;
670 case EXPR_NEG:
671 fprintf(h, "-");
672 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
673 break;
674 case EXPR_ADDRESSOF:
675 fprintf(h, "&");
676 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
677 break;
678 case EXPR_PPTR:
679 fprintf(h, "*");
680 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
681 break;
682 case EXPR_CAST:
683 fprintf(h, "(");
684 write_type_decl(h, e->u.tref, NULL);
685 fprintf(h, ")");
686 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
687 break;
688 case EXPR_SIZEOF:
689 fprintf(h, "sizeof(");
690 write_type_decl(h, e->u.tref, NULL);
691 fprintf(h, ")");
692 break;
693 case EXPR_SHL:
694 case EXPR_SHR:
695 case EXPR_MOD:
696 case EXPR_MUL:
697 case EXPR_DIV:
698 case EXPR_ADD:
699 case EXPR_SUB:
700 case EXPR_AND:
701 case EXPR_OR:
702 case EXPR_LOGOR:
703 case EXPR_LOGAND:
704 case EXPR_XOR:
705 case EXPR_EQUALITY:
706 case EXPR_INEQUALITY:
707 case EXPR_GTR:
708 case EXPR_LESS:
709 case EXPR_GTREQL:
710 case EXPR_LESSEQL:
711 if (brackets) fprintf(h, "(");
712 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
713 switch (e->type)
714 {
715 case EXPR_SHL: fprintf(h, " << "); break;
716 case EXPR_SHR: fprintf(h, " >> "); break;
717 case EXPR_MOD: fprintf(h, " %% "); break;
718 case EXPR_MUL: fprintf(h, " * "); break;
719 case EXPR_DIV: fprintf(h, " / "); break;
720 case EXPR_ADD: fprintf(h, " + "); break;
721 case EXPR_SUB: fprintf(h, " - "); break;
722 case EXPR_AND: fprintf(h, " & "); break;
723 case EXPR_OR: fprintf(h, " | "); break;
724 case EXPR_LOGOR: fprintf(h, " || "); break;
725 case EXPR_LOGAND: fprintf(h, " && "); break;
726 case EXPR_XOR: fprintf(h, " ^ "); break;
727 case EXPR_EQUALITY: fprintf(h, " == "); break;
728 case EXPR_INEQUALITY: fprintf(h, " != "); break;
729 case EXPR_GTR: fprintf(h, " > "); break;
730 case EXPR_LESS: fprintf(h, " < "); break;
731 case EXPR_GTREQL: fprintf(h, " >= "); break;
732 case EXPR_LESSEQL: fprintf(h, " <= "); break;
733 default: break;
734 }
735 write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
736 if (brackets) fprintf(h, ")");
737 break;
738 case EXPR_MEMBER:
739 if (brackets) fprintf(h, "(");
740 if (e->ref->type == EXPR_PPTR)
741 {
742 write_expr(h, e->ref->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
743 fprintf(h, "->");
744 }
745 else
746 {
747 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
748 fprintf(h, ".");
749 }
750 write_expr(h, e->u.ext, 1, 0, toplevel_prefix, cont_type, "");
751 if (brackets) fprintf(h, ")");
752 break;
753 case EXPR_COND:
754 if (brackets) fprintf(h, "(");
755 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
756 fprintf(h, " ? ");
757 write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
758 fprintf(h, " : ");
759 write_expr(h, e->ext2, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
760 if (brackets) fprintf(h, ")");
761 break;
762 case EXPR_ARRAY:
763 if (brackets) fprintf(h, "(");
764 write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
765 fprintf(h, "[");
766 write_expr(h, e->u.ext, 1, 1, toplevel_prefix, cont_type, local_var_prefix);
767 fprintf(h, "]");
768 if (brackets) fprintf(h, ")");
769 break;
770 }
771 }
772
773 /* This is actually fairly involved to implement precisely, due to the
774 effects attributes may have and things like that. Right now this is
775 only used for optimization, so just check for a very small set of
776 criteria that guarantee the types are equivalent; assume every thing
777 else is different. */
778 static int compare_type(const type_t *a, const type_t *b)
779 {
780 if (a == b
781 || (a->name
782 && b->name
783 && strcmp(a->name, b->name) == 0))
784 return 0;
785 /* Ordering doesn't need to be implemented yet. */
786 return 1;
787 }
788
789 int compare_expr(const expr_t *a, const expr_t *b)
790 {
791 int ret;
792
793 if (a->type != b->type)
794 return a->type - b->type;
795
796 switch (a->type)
797 {
798 case EXPR_NUM:
799 case EXPR_HEXNUM:
800 case EXPR_TRUEFALSE:
801 return a->u.lval - b->u.lval;
802 case EXPR_DOUBLE:
803 return a->u.dval - b->u.dval;
804 case EXPR_IDENTIFIER:
805 case EXPR_STRLIT:
806 case EXPR_WSTRLIT:
807 return strcmp(a->u.sval, b->u.sval);
808 case EXPR_COND:
809 ret = compare_expr(a->ref, b->ref);
810 if (ret != 0)
811 return ret;
812 ret = compare_expr(a->u.ext, b->u.ext);
813 if (ret != 0)
814 return ret;
815 return compare_expr(a->ext2, b->ext2);
816 case EXPR_OR:
817 case EXPR_AND:
818 case EXPR_ADD:
819 case EXPR_SUB:
820 case EXPR_MOD:
821 case EXPR_MUL:
822 case EXPR_DIV:
823 case EXPR_SHL:
824 case EXPR_SHR:
825 case EXPR_MEMBER:
826 case EXPR_ARRAY:
827 case EXPR_LOGOR:
828 case EXPR_LOGAND:
829 case EXPR_XOR:
830 case EXPR_EQUALITY:
831 case EXPR_INEQUALITY:
832 case EXPR_GTR:
833 case EXPR_LESS:
834 case EXPR_GTREQL:
835 case EXPR_LESSEQL:
836 ret = compare_expr(a->ref, b->ref);
837 if (ret != 0)
838 return ret;
839 return compare_expr(a->u.ext, b->u.ext);
840 case EXPR_CAST:
841 ret = compare_type(a->u.tref, b->u.tref);
842 if (ret != 0)
843 return ret;
844 /* Fall through. */
845 case EXPR_NOT:
846 case EXPR_NEG:
847 case EXPR_PPTR:
848 case EXPR_ADDRESSOF:
849 case EXPR_LOGNOT:
850 case EXPR_POS:
851 return compare_expr(a->ref, b->ref);
852 case EXPR_SIZEOF:
853 return compare_type(a->u.tref, b->u.tref);
854 case EXPR_VOID:
855 return 0;
856 }
857 return -1;
858 }