ole32: Fix memory leaks in the storage test.
[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 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 }