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