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