shdocvw: Get rid of *_THIS macros in navigate.c.
[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     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 }