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