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