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