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