jscript: Implement the String.fixed() method.
[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, const char *local_var_prefix)
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)
606             {
607                 fprintf(h, "%s%s", toplevel_prefix, e->u.sval);
608                 break;
609             }
610         }
611         fprintf(h, "%s%s", local_var_prefix, e->u.sval);
612         break;
613     case EXPR_STRLIT:
614         fprintf(h, "\"%s\"", e->u.sval);
615         break;
616     case EXPR_WSTRLIT:
617         fprintf(h, "L\"%s\"", e->u.sval);
618         break;
619     case EXPR_LOGNOT:
620         fprintf(h, "!");
621         write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
622         break;
623     case EXPR_NOT:
624         fprintf(h, "~");
625         write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
626         break;
627     case EXPR_POS:
628         fprintf(h, "+");
629         write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
630         break;
631     case EXPR_NEG:
632         fprintf(h, "-");
633         write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
634         break;
635     case EXPR_ADDRESSOF:
636         fprintf(h, "&");
637         write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
638         break;
639     case EXPR_PPTR:
640         fprintf(h, "*");
641         write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
642         break;
643     case EXPR_CAST:
644         fprintf(h, "(");
645         write_type_decl(h, e->u.tref, NULL);
646         fprintf(h, ")");
647         write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
648         break;
649     case EXPR_SIZEOF:
650         fprintf(h, "sizeof(");
651         write_type_decl(h, e->u.tref, NULL);
652         fprintf(h, ")");
653         break;
654     case EXPR_SHL:
655     case EXPR_SHR:
656     case EXPR_MOD:
657     case EXPR_MUL:
658     case EXPR_DIV:
659     case EXPR_ADD:
660     case EXPR_SUB:
661     case EXPR_AND:
662     case EXPR_OR:
663     case EXPR_LOGOR:
664     case EXPR_LOGAND:
665     case EXPR_XOR:
666     case EXPR_EQUALITY:
667     case EXPR_INEQUALITY:
668     case EXPR_GTR:
669     case EXPR_LESS:
670     case EXPR_GTREQL:
671     case EXPR_LESSEQL:
672         if (brackets) fprintf(h, "(");
673         write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
674         switch (e->type)
675         {
676         case EXPR_SHL:          fprintf(h, " << "); break;
677         case EXPR_SHR:          fprintf(h, " >> "); break;
678         case EXPR_MOD:          fprintf(h, " %% "); break;
679         case EXPR_MUL:          fprintf(h, " * "); break;
680         case EXPR_DIV:          fprintf(h, " / "); break;
681         case EXPR_ADD:          fprintf(h, " + "); break;
682         case EXPR_SUB:          fprintf(h, " - "); break;
683         case EXPR_AND:          fprintf(h, " & "); break;
684         case EXPR_OR:           fprintf(h, " | "); break;
685         case EXPR_LOGOR:        fprintf(h, " || "); break;
686         case EXPR_LOGAND:       fprintf(h, " && "); break;
687         case EXPR_XOR:          fprintf(h, " ^ "); break;
688         case EXPR_EQUALITY:     fprintf(h, " == "); break;
689         case EXPR_INEQUALITY:   fprintf(h, " != "); break;
690         case EXPR_GTR:          fprintf(h, " > "); break;
691         case EXPR_LESS:         fprintf(h, " < "); break;
692         case EXPR_GTREQL:       fprintf(h, " >= "); break;
693         case EXPR_LESSEQL:      fprintf(h, " <= "); break;
694         default: break;
695         }
696         write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
697         if (brackets) fprintf(h, ")");
698         break;
699     case EXPR_MEMBER:
700         if (brackets) fprintf(h, "(");
701         if (e->ref->type == EXPR_PPTR)
702         {
703             write_expr(h, e->ref->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
704             fprintf(h, "->");
705         }
706         else
707         {
708             write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
709             fprintf(h, ".");
710         }
711         write_expr(h, e->u.ext, 1, 0, toplevel_prefix, cont_type, "");
712         if (brackets) fprintf(h, ")");
713         break;
714     case EXPR_COND:
715         if (brackets) fprintf(h, "(");
716         write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
717         fprintf(h, " ? ");
718         write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
719         fprintf(h, " : ");
720         write_expr(h, e->ext2, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
721         if (brackets) fprintf(h, ")");
722         break;
723     case EXPR_ARRAY:
724         if (brackets) fprintf(h, "(");
725         write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
726         fprintf(h, "[");
727         write_expr(h, e->u.ext, 1, 1, toplevel_prefix, cont_type, local_var_prefix);
728         fprintf(h, "]");
729         if (brackets) fprintf(h, ")");
730         break;
731     }
732 }
733
734 /* This is actually fairly involved to implement precisely, due to the
735    effects attributes may have and things like that.  Right now this is
736    only used for optimization, so just check for a very small set of
737    criteria that guarantee the types are equivalent; assume every thing
738    else is different.   */
739 static int compare_type(const type_t *a, const type_t *b)
740 {
741     if (a == b
742         || (a->name
743             && b->name
744             && strcmp(a->name, b->name) == 0))
745         return 0;
746     /* Ordering doesn't need to be implemented yet.  */
747     return 1;
748 }
749
750 int compare_expr(const expr_t *a, const expr_t *b)
751 {
752     int ret;
753
754     if (a->type != b->type)
755         return a->type - b->type;
756
757     switch (a->type)
758     {
759         case EXPR_NUM:
760         case EXPR_HEXNUM:
761         case EXPR_TRUEFALSE:
762             return a->u.lval - b->u.lval;
763         case EXPR_DOUBLE:
764             return a->u.dval - b->u.dval;
765         case EXPR_IDENTIFIER:
766         case EXPR_STRLIT:
767         case EXPR_WSTRLIT:
768             return strcmp(a->u.sval, b->u.sval);
769         case EXPR_COND:
770             ret = compare_expr(a->ref, b->ref);
771             if (ret != 0)
772                 return ret;
773             ret = compare_expr(a->u.ext, b->u.ext);
774             if (ret != 0)
775                 return ret;
776             return compare_expr(a->ext2, b->ext2);
777         case EXPR_OR:
778         case EXPR_AND:
779         case EXPR_ADD:
780         case EXPR_SUB:
781         case EXPR_MOD:
782         case EXPR_MUL:
783         case EXPR_DIV:
784         case EXPR_SHL:
785         case EXPR_SHR:
786         case EXPR_MEMBER:
787         case EXPR_ARRAY:
788         case EXPR_LOGOR:
789         case EXPR_LOGAND:
790         case EXPR_XOR:
791         case EXPR_EQUALITY:
792         case EXPR_INEQUALITY:
793         case EXPR_GTR:
794         case EXPR_LESS:
795         case EXPR_GTREQL:
796         case EXPR_LESSEQL:
797             ret = compare_expr(a->ref, b->ref);
798             if (ret != 0)
799                 return ret;
800             return compare_expr(a->u.ext, b->u.ext);
801         case EXPR_CAST:
802             ret = compare_type(a->u.tref, b->u.tref);
803             if (ret != 0)
804                 return ret;
805             /* Fall through.  */
806         case EXPR_NOT:
807         case EXPR_NEG:
808         case EXPR_PPTR:
809         case EXPR_ADDRESSOF:
810         case EXPR_LOGNOT:
811         case EXPR_POS:
812             return compare_expr(a->ref, b->ref);
813         case EXPR_SIZEOF:
814             return compare_type(a->u.tref, b->u.tref);
815         case EXPR_VOID:
816             return 0;
817     }
818     return -1;
819 }