ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

expr.c
Go to the documentation of this file.
00001 /*
00002  * Expression Abstract Syntax Tree Functions
00003  *
00004  * Copyright 2002 Ove Kaaven
00005  * Copyright 2006-2008 Robert Shearman
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #include "config.h"
00023 
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <stdarg.h>
00027 #include <assert.h>
00028 #include <ctype.h>
00029 #include <string.h>
00030 
00031 #include "widl.h"
00032 #include "utils.h"
00033 #include "expr.h"
00034 #include "header.h"
00035 #include "typetree.h"
00036 #include "typegen.h"
00037 
00038 static int is_integer_type(const type_t *type)
00039 {
00040     switch (type_get_type(type))
00041     {
00042     case TYPE_ENUM:
00043         return TRUE;
00044     case TYPE_BASIC:
00045         switch (type_basic_get_type(type))
00046         {
00047         case TYPE_BASIC_INT8:
00048         case TYPE_BASIC_INT16:
00049         case TYPE_BASIC_INT32:
00050         case TYPE_BASIC_INT64:
00051         case TYPE_BASIC_INT:
00052         case TYPE_BASIC_INT3264:
00053         case TYPE_BASIC_CHAR:
00054         case TYPE_BASIC_HYPER:
00055         case TYPE_BASIC_BYTE:
00056         case TYPE_BASIC_WCHAR:
00057         case TYPE_BASIC_ERROR_STATUS_T:
00058             return TRUE;
00059         case TYPE_BASIC_FLOAT:
00060         case TYPE_BASIC_DOUBLE:
00061         case TYPE_BASIC_HANDLE:
00062             return FALSE;
00063         }
00064         return FALSE;
00065     default:
00066         return FALSE;
00067     }
00068 }
00069 
00070 static int is_signed_integer_type(const type_t *type)
00071 {
00072     switch (type_get_type(type))
00073     {
00074     case TYPE_ENUM:
00075         return FALSE;
00076     case TYPE_BASIC:
00077         switch (type_basic_get_type(type))
00078         {
00079         case TYPE_BASIC_INT8:
00080         case TYPE_BASIC_INT16:
00081         case TYPE_BASIC_INT32:
00082         case TYPE_BASIC_INT64:
00083         case TYPE_BASIC_INT:
00084         case TYPE_BASIC_INT3264:
00085             return type_basic_get_sign(type) < 0;
00086         case TYPE_BASIC_CHAR:
00087             return TRUE;
00088         case TYPE_BASIC_HYPER:
00089         case TYPE_BASIC_BYTE:
00090         case TYPE_BASIC_WCHAR:
00091         case TYPE_BASIC_ERROR_STATUS_T:
00092         case TYPE_BASIC_FLOAT:
00093         case TYPE_BASIC_DOUBLE:
00094         case TYPE_BASIC_HANDLE:
00095             return FALSE;
00096         }
00097         /* FALLTHROUGH */
00098     default:
00099         return FALSE;
00100     }
00101 }
00102 
00103 static int is_float_type(const type_t *type)
00104 {
00105     return (type_get_type(type) == TYPE_BASIC &&
00106         (type_basic_get_type(type) == TYPE_BASIC_FLOAT ||
00107          type_basic_get_type(type) == TYPE_BASIC_DOUBLE));
00108 }
00109 
00110 expr_t *make_expr(enum expr_type type)
00111 {
00112     expr_t *e = xmalloc(sizeof(expr_t));
00113     e->type = type;
00114     e->ref = NULL;
00115     e->u.lval = 0;
00116     e->is_const = FALSE;
00117     e->cval = 0;
00118     return e;
00119 }
00120 
00121 expr_t *make_exprl(enum expr_type type, int val)
00122 {
00123     expr_t *e = xmalloc(sizeof(expr_t));
00124     e->type = type;
00125     e->ref = NULL;
00126     e->u.lval = val;
00127     e->is_const = FALSE;
00128     /* check for numeric constant */
00129     if (type == EXPR_NUM || type == EXPR_HEXNUM || type == EXPR_TRUEFALSE)
00130     {
00131         /* make sure true/false value is valid */
00132         assert(type != EXPR_TRUEFALSE || val == 0 || val == 1);
00133         e->is_const = TRUE;
00134         e->cval = val;
00135     }
00136     return e;
00137 }
00138 
00139 expr_t *make_exprd(enum expr_type type, double val)
00140 {
00141     expr_t *e = xmalloc(sizeof(expr_t));
00142     e->type = type;
00143     e->ref = NULL;
00144     e->u.dval = val;
00145     e->is_const = TRUE;
00146     e->cval = val;
00147     return e;
00148 }
00149 
00150 expr_t *make_exprs(enum expr_type type, char *val)
00151 {
00152     expr_t *e;
00153     e = xmalloc(sizeof(expr_t));
00154     e->type = type;
00155     e->ref = NULL;
00156     e->u.sval = val;
00157     e->is_const = FALSE;
00158     /* check for predefined constants */
00159     switch (type)
00160     {
00161     case EXPR_IDENTIFIER:
00162     {
00163         var_t *c = find_const(val, 0);
00164         if (c)
00165         {
00166             e->u.sval = c->name;
00167             free(val);
00168             e->is_const = TRUE;
00169             e->cval = c->eval->cval;
00170         }
00171         break;
00172     }
00173     case EXPR_CHARCONST:
00174         if (!val[0])
00175             error_loc("empty character constant\n");
00176         else if (val[1])
00177             error_loc("multi-character constants are endian dependent\n");
00178         else
00179         {
00180             e->is_const = TRUE;
00181             e->cval = *val;
00182         }
00183         break;
00184     default:
00185         break;
00186     }
00187     return e;
00188 }
00189 
00190 expr_t *make_exprt(enum expr_type type, var_t *var, expr_t *expr)
00191 {
00192     expr_t *e;
00193     type_t *tref;
00194 
00195     if (var->stgclass != STG_NONE && var->stgclass != STG_REGISTER)
00196         error_loc("invalid storage class for type expression\n");
00197 
00198     tref = var->type;
00199 
00200     e = xmalloc(sizeof(expr_t));
00201     e->type = type;
00202     e->ref = expr;
00203     e->u.tref = tref;
00204     e->is_const = FALSE;
00205     if (type == EXPR_SIZEOF)
00206     {
00207         /* only do this for types that should be the same on all platforms */
00208         if (is_integer_type(tref) || is_float_type(tref))
00209         {
00210             e->is_const = TRUE;
00211             e->cval = type_memsize(tref);
00212         }
00213     }
00214     /* check for cast of constant expression */
00215     if (type == EXPR_CAST && expr->is_const)
00216     {
00217         if (is_integer_type(tref))
00218         {
00219             unsigned int cast_type_bits = type_memsize(tref) * 8;
00220             unsigned int cast_mask;
00221 
00222             e->is_const = TRUE;
00223             if (is_signed_integer_type(tref))
00224             {
00225                 cast_mask = (1 << (cast_type_bits - 1)) - 1;
00226                 if (expr->cval & (1 << (cast_type_bits - 1)))
00227                     e->cval = -((-expr->cval) & cast_mask);
00228                 else
00229                     e->cval = expr->cval & cast_mask;
00230             }
00231             else
00232             {
00233                 /* calculate ((1 << cast_type_bits) - 1) avoiding overflow */
00234                 cast_mask = ((1 << (cast_type_bits - 1)) - 1) |
00235                             1 << (cast_type_bits - 1);
00236                 e->cval = expr->cval & cast_mask;
00237             }
00238         }
00239         else
00240         {
00241             e->is_const = TRUE;
00242             e->cval = expr->cval;
00243         }
00244     }
00245     free(var);
00246     return e;
00247 }
00248 
00249 expr_t *make_expr1(enum expr_type type, expr_t *expr)
00250 {
00251     expr_t *e;
00252     e = xmalloc(sizeof(expr_t));
00253     e->type = type;
00254     e->ref = expr;
00255     e->u.lval = 0;
00256     e->is_const = FALSE;
00257     /* check for compile-time optimization */
00258     if (expr->is_const)
00259     {
00260         e->is_const = TRUE;
00261         switch (type)
00262         {
00263         case EXPR_LOGNOT:
00264             e->cval = !expr->cval;
00265             break;
00266         case EXPR_POS:
00267             e->cval = +expr->cval;
00268             break;
00269         case EXPR_NEG:
00270             e->cval = -expr->cval;
00271             break;
00272         case EXPR_NOT:
00273             e->cval = ~expr->cval;
00274             break;
00275         default:
00276             e->is_const = FALSE;
00277             break;
00278         }
00279     }
00280     return e;
00281 }
00282 
00283 expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2)
00284 {
00285     expr_t *e;
00286     e = xmalloc(sizeof(expr_t));
00287     e->type = type;
00288     e->ref = expr1;
00289     e->u.ext = expr2;
00290     e->is_const = FALSE;
00291     /* check for compile-time optimization */
00292     if (expr1->is_const && expr2->is_const)
00293     {
00294         e->is_const = TRUE;
00295         switch (type)
00296         {
00297         case EXPR_ADD:
00298             e->cval = expr1->cval + expr2->cval;
00299             break;
00300         case EXPR_SUB:
00301             e->cval = expr1->cval - expr2->cval;
00302             break;
00303         case EXPR_MOD:
00304             if (expr2->cval == 0)
00305             {
00306                 error_loc("divide by zero in expression\n");
00307                 e->cval = 0;
00308             }
00309             else
00310                 e->cval = expr1->cval % expr2->cval;
00311             break;
00312         case EXPR_MUL:
00313             e->cval = expr1->cval * expr2->cval;
00314             break;
00315         case EXPR_DIV:
00316             if (expr2->cval == 0)
00317             {
00318                 error_loc("divide by zero in expression\n");
00319                 e->cval = 0;
00320             }
00321             else
00322                 e->cval = expr1->cval / expr2->cval;
00323             break;
00324         case EXPR_OR:
00325             e->cval = expr1->cval | expr2->cval;
00326             break;
00327         case EXPR_AND:
00328             e->cval = expr1->cval & expr2->cval;
00329             break;
00330         case EXPR_SHL:
00331             e->cval = expr1->cval << expr2->cval;
00332             break;
00333         case EXPR_SHR:
00334             e->cval = expr1->cval >> expr2->cval;
00335             break;
00336         case EXPR_LOGOR:
00337             e->cval = expr1->cval || expr2->cval;
00338             break;
00339         case EXPR_LOGAND:
00340             e->cval = expr1->cval && expr2->cval;
00341             break;
00342         case EXPR_XOR:
00343             e->cval = expr1->cval ^ expr2->cval;
00344             break;
00345         case EXPR_EQUALITY:
00346             e->cval = expr1->cval == expr2->cval;
00347             break;
00348         case EXPR_INEQUALITY:
00349             e->cval = expr1->cval != expr2->cval;
00350             break;
00351         case EXPR_GTR:
00352             e->cval = expr1->cval > expr2->cval;
00353             break;
00354         case EXPR_LESS:
00355             e->cval = expr1->cval < expr2->cval;
00356             break;
00357         case EXPR_GTREQL:
00358             e->cval = expr1->cval >= expr2->cval;
00359             break;
00360         case EXPR_LESSEQL:
00361             e->cval = expr1->cval <= expr2->cval;
00362             break;
00363         default:
00364             e->is_const = FALSE;
00365             break;
00366         }
00367     }
00368     return e;
00369 }
00370 
00371 expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3)
00372 {
00373     expr_t *e;
00374     e = xmalloc(sizeof(expr_t));
00375     e->type = type;
00376     e->ref = expr1;
00377     e->u.ext = expr2;
00378     e->ext2 = expr3;
00379     e->is_const = FALSE;
00380     /* check for compile-time optimization */
00381     if (expr1->is_const && expr2->is_const && expr3->is_const)
00382     {
00383         e->is_const = TRUE;
00384         switch (type)
00385         {
00386         case EXPR_COND:
00387             e->cval = expr1->cval ? expr2->cval : expr3->cval;
00388             break;
00389         default:
00390             e->is_const = FALSE;
00391             break;
00392         }
00393     }
00394     return e;
00395 }
00396 
00397 struct expression_type
00398 {
00399     int is_variable; /* is the expression resolved to a variable? */
00400     int is_temporary; /* should the type be freed? */
00401     type_t *type;
00402 };
00403 
00404 static void check_scalar_type(const struct expr_loc *expr_loc,
00405                               const type_t *cont_type, const type_t *type)
00406 {
00407     if (!cont_type || (!is_integer_type(type) && !is_ptr(type) &&
00408                        !is_float_type(type)))
00409         error_loc_info(&expr_loc->v->loc_info, "scalar type required in expression%s%s\n",
00410                        expr_loc->attr ? " for attribute " : "",
00411                        expr_loc->attr ? expr_loc->attr : "");
00412 }
00413 
00414 static void check_arithmetic_type(const struct expr_loc *expr_loc,
00415                                   const type_t *cont_type, const type_t *type)
00416 {
00417     if (!cont_type || (!is_integer_type(type) && !is_float_type(type)))
00418         error_loc_info(&expr_loc->v->loc_info, "arithmetic type required in expression%s%s\n",
00419                        expr_loc->attr ? " for attribute " : "",
00420                        expr_loc->attr ? expr_loc->attr : "");
00421 }
00422 
00423 static void check_integer_type(const struct expr_loc *expr_loc,
00424                                const type_t *cont_type, const type_t *type)
00425 {
00426     if (!cont_type || !is_integer_type(type))
00427         error_loc_info(&expr_loc->v->loc_info, "integer type required in expression%s%s\n",
00428                        expr_loc->attr ? " for attribute " : "",
00429                        expr_loc->attr ? expr_loc->attr : "");
00430 }
00431 
00432 static type_t *find_identifier(const char *identifier, const type_t *cont_type, int *found_in_cont_type)
00433 {
00434     type_t *type = NULL;
00435     const var_t *field;
00436     const var_list_t *fields = NULL;
00437 
00438     *found_in_cont_type = 0;
00439 
00440     if (cont_type)
00441     {
00442         switch (type_get_type(cont_type))
00443         {
00444         case TYPE_FUNCTION:
00445             fields = type_function_get_args(cont_type);
00446             break;
00447         case TYPE_STRUCT:
00448             fields = type_struct_get_fields(cont_type);
00449             break;
00450         case TYPE_UNION:
00451         case TYPE_ENCAPSULATED_UNION:
00452             fields = type_union_get_cases(cont_type);
00453             break;
00454         case TYPE_VOID:
00455         case TYPE_BASIC:
00456         case TYPE_ENUM:
00457         case TYPE_MODULE:
00458         case TYPE_COCLASS:
00459         case TYPE_INTERFACE:
00460         case TYPE_POINTER:
00461         case TYPE_ARRAY:
00462         case TYPE_BITFIELD:
00463             /* nothing to do */
00464             break;
00465         case TYPE_ALIAS:
00466             /* shouldn't get here because of using type_get_type above */
00467             assert(0);
00468             break;
00469         }
00470     }
00471 
00472     if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
00473         if (field->name && !strcmp(identifier, field->name))
00474         {
00475             type = field->type;
00476             *found_in_cont_type = 1;
00477             break;
00478         }
00479 
00480     if (!type)
00481     {
00482         var_t *const_var = find_const(identifier, 0);
00483         if (const_var) type = const_var->type;
00484     }
00485 
00486     return type;
00487 }
00488 
00489 static int is_valid_member_operand(const type_t *type)
00490 {
00491     switch (type_get_type(type))
00492     {
00493     case TYPE_STRUCT:
00494     case TYPE_UNION:
00495     case TYPE_ENUM:
00496         return TRUE;
00497     default:
00498         return FALSE;
00499     }
00500 }
00501 
00502 static struct expression_type resolve_expression(const struct expr_loc *expr_loc,
00503                                                  const type_t *cont_type,
00504                                                  const expr_t *e)
00505 {
00506     struct expression_type result;
00507     result.is_variable = FALSE;
00508     result.is_temporary = FALSE;
00509     result.type = NULL;
00510     switch (e->type)
00511     {
00512     case EXPR_VOID:
00513         break;
00514     case EXPR_HEXNUM:
00515     case EXPR_NUM:
00516     case EXPR_TRUEFALSE:
00517         result.is_temporary = FALSE;
00518         result.type = type_new_int(TYPE_BASIC_INT, 0);
00519         break;
00520     case EXPR_STRLIT:
00521         result.is_temporary = TRUE;
00522         result.type = type_new_pointer(RPC_FC_UP, type_new_int(TYPE_BASIC_CHAR, 0), NULL);
00523         break;
00524     case EXPR_WSTRLIT:
00525         result.is_temporary = TRUE;
00526         result.type = type_new_pointer(RPC_FC_UP, type_new_int(TYPE_BASIC_WCHAR, 0), NULL);
00527         break;
00528     case EXPR_CHARCONST:
00529         result.is_temporary = TRUE;
00530         result.type = type_new_int(TYPE_BASIC_CHAR, 0);
00531         break;
00532     case EXPR_DOUBLE:
00533         result.is_temporary = TRUE;
00534         result.type = type_new_basic(TYPE_BASIC_DOUBLE);
00535         break;
00536     case EXPR_IDENTIFIER:
00537     {
00538         int found_in_cont_type;
00539         result.is_variable = TRUE;
00540         result.is_temporary = FALSE;
00541         result.type = find_identifier(e->u.sval, cont_type, &found_in_cont_type);
00542         if (!result.type)
00543         {
00544             error_loc_info(&expr_loc->v->loc_info, "identifier %s cannot be resolved in expression%s%s\n",
00545                            e->u.sval, expr_loc->attr ? " for attribute " : "",
00546                            expr_loc->attr ? expr_loc->attr : "");
00547         }
00548         break;
00549     }
00550     case EXPR_LOGNOT:
00551         result = resolve_expression(expr_loc, cont_type, e->ref);
00552         check_scalar_type(expr_loc, cont_type, result.type);
00553         result.is_variable = FALSE;
00554         result.is_temporary = FALSE;
00555         result.type = type_new_int(TYPE_BASIC_INT, 0);
00556         break;
00557     case EXPR_NOT:
00558         result = resolve_expression(expr_loc, cont_type, e->ref);
00559         check_integer_type(expr_loc, cont_type, result.type);
00560         result.is_variable = FALSE;
00561         break;
00562     case EXPR_POS:
00563     case EXPR_NEG:
00564         result = resolve_expression(expr_loc, cont_type, e->ref);
00565         check_arithmetic_type(expr_loc, cont_type, result.type);
00566         result.is_variable = FALSE;
00567         break;
00568     case EXPR_ADDRESSOF:
00569         result = resolve_expression(expr_loc, cont_type, e->ref);
00570         if (!result.is_variable)
00571             error_loc_info(&expr_loc->v->loc_info, "address-of operator applied to non-variable type in expression%s%s\n",
00572                            expr_loc->attr ? " for attribute " : "",
00573                            expr_loc->attr ? expr_loc->attr : "");
00574             result.is_variable = FALSE;
00575         result.is_temporary = TRUE;
00576         result.type = type_new_pointer(RPC_FC_UP, result.type, NULL);
00577         break;
00578     case EXPR_PPTR:
00579         result = resolve_expression(expr_loc, cont_type, e->ref);
00580         if (result.type && is_ptr(result.type))
00581             result.type = type_pointer_get_ref(result.type);
00582         else if(result.type && is_array(result.type)
00583                             && type_array_is_decl_as_ptr(result.type))
00584             result.type = type_array_get_element(result.type);
00585         else
00586             error_loc_info(&expr_loc->v->loc_info, "dereference operator applied to non-pointer type in expression%s%s\n",
00587                            expr_loc->attr ? " for attribute " : "",
00588                            expr_loc->attr ? expr_loc->attr : "");
00589         break;
00590     case EXPR_CAST:
00591         result = resolve_expression(expr_loc, cont_type, e->ref);
00592         result.type = e->u.tref;
00593         break;
00594     case EXPR_SIZEOF:
00595         result.is_temporary = FALSE;
00596         result.type = type_new_int(TYPE_BASIC_INT, 0);
00597         break;
00598     case EXPR_SHL:
00599     case EXPR_SHR:
00600     case EXPR_MOD:
00601     case EXPR_MUL:
00602     case EXPR_DIV:
00603     case EXPR_ADD:
00604     case EXPR_SUB:
00605     case EXPR_AND:
00606     case EXPR_OR:
00607     case EXPR_XOR:
00608     {
00609         struct expression_type result_right;
00610         result = resolve_expression(expr_loc, cont_type, e->ref);
00611         result.is_variable = FALSE;
00612         result_right = resolve_expression(expr_loc, cont_type, e->u.ext);
00613         /* FIXME: these checks aren't strict enough for some of the operators */
00614         check_scalar_type(expr_loc, cont_type, result.type);
00615         check_scalar_type(expr_loc, cont_type, result_right.type);
00616         break;
00617     }
00618     case EXPR_LOGOR:
00619     case EXPR_LOGAND:
00620     case EXPR_EQUALITY:
00621     case EXPR_INEQUALITY:
00622     case EXPR_GTR:
00623     case EXPR_LESS:
00624     case EXPR_GTREQL:
00625     case EXPR_LESSEQL:
00626     {
00627         struct expression_type result_left, result_right;
00628         result_left = resolve_expression(expr_loc, cont_type, e->ref);
00629         result_right = resolve_expression(expr_loc, cont_type, e->u.ext);
00630         check_scalar_type(expr_loc, cont_type, result_left.type);
00631         check_scalar_type(expr_loc, cont_type, result_right.type);
00632         result.is_temporary = FALSE;
00633         result.type = type_new_int(TYPE_BASIC_INT, 0);
00634         break;
00635     }
00636     case EXPR_MEMBER:
00637         result = resolve_expression(expr_loc, cont_type, e->ref);
00638         if (result.type && is_valid_member_operand(result.type))
00639             result = resolve_expression(expr_loc, result.type, e->u.ext);
00640         else
00641             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",
00642                            expr_loc->attr ? " for attribute " : "",
00643                            expr_loc->attr ? expr_loc->attr : "");
00644         break;
00645     case EXPR_COND:
00646     {
00647         struct expression_type result_first, result_second, result_third;
00648         result_first = resolve_expression(expr_loc, cont_type, e->ref);
00649         check_scalar_type(expr_loc, cont_type, result_first.type);
00650         result_second = resolve_expression(expr_loc, cont_type, e->u.ext);
00651         result_third = resolve_expression(expr_loc, cont_type, e->ext2);
00652         check_scalar_type(expr_loc, cont_type, result_second.type);
00653         check_scalar_type(expr_loc, cont_type, result_third.type);
00654         if (!is_ptr(result_second.type) ^ !is_ptr(result_third.type))
00655             error_loc_info(&expr_loc->v->loc_info, "type mismatch in ?: expression\n" );
00656         /* FIXME: determine the correct return type */
00657         result = result_second;
00658         result.is_variable = FALSE;
00659         break;
00660     }
00661     case EXPR_ARRAY:
00662         result = resolve_expression(expr_loc, cont_type, e->ref);
00663         if (result.type && is_array(result.type))
00664         {
00665             struct expression_type index_result;
00666             result.type = type_array_get_element(result.type);
00667             index_result = resolve_expression(expr_loc, cont_type /* FIXME */, e->u.ext);
00668             if (!index_result.type || !is_integer_type(index_result.type))
00669                 error_loc_info(&expr_loc->v->loc_info, "array subscript not of integral type in expression%s%s\n",
00670                                expr_loc->attr ? " for attribute " : "",
00671                                expr_loc->attr ? expr_loc->attr : "");
00672         }
00673         else
00674             error_loc_info(&expr_loc->v->loc_info, "array subscript operator applied to non-array type in expression%s%s\n",
00675                            expr_loc->attr ? " for attribute " : "",
00676                            expr_loc->attr ? expr_loc->attr : "");
00677         break;
00678     }
00679     return result;
00680 }
00681 
00682 const type_t *expr_resolve_type(const struct expr_loc *expr_loc, const type_t *cont_type, const expr_t *expr)
00683 {
00684     struct expression_type expr_type;
00685     expr_type = resolve_expression(expr_loc, cont_type, expr);
00686     return expr_type.type;
00687 }
00688 
00689 void write_expr(FILE *h, const expr_t *e, int brackets,
00690                 int toplevel, const char *toplevel_prefix,
00691                 const type_t *cont_type, const char *local_var_prefix)
00692 {
00693     switch (e->type)
00694     {
00695     case EXPR_VOID:
00696         break;
00697     case EXPR_NUM:
00698         fprintf(h, "%u", e->u.lval);
00699         break;
00700     case EXPR_HEXNUM:
00701         fprintf(h, "0x%x", e->u.lval);
00702         break;
00703     case EXPR_DOUBLE:
00704         fprintf(h, "%#.15g", e->u.dval);
00705         break;
00706     case EXPR_TRUEFALSE:
00707         if (e->u.lval == 0)
00708             fprintf(h, "FALSE");
00709         else
00710             fprintf(h, "TRUE");
00711         break;
00712     case EXPR_IDENTIFIER:
00713         if (toplevel && toplevel_prefix && cont_type)
00714         {
00715             int found_in_cont_type;
00716             find_identifier(e->u.sval, cont_type, &found_in_cont_type);
00717             if (found_in_cont_type)
00718             {
00719                 fprintf(h, "%s%s", toplevel_prefix, e->u.sval);
00720                 break;
00721             }
00722         }
00723         fprintf(h, "%s%s", local_var_prefix, e->u.sval);
00724         break;
00725     case EXPR_STRLIT:
00726         fprintf(h, "\"%s\"", e->u.sval);
00727         break;
00728     case EXPR_WSTRLIT:
00729         fprintf(h, "L\"%s\"", e->u.sval);
00730         break;
00731     case EXPR_CHARCONST:
00732         fprintf(h, "'%s'", e->u.sval);
00733         break;
00734     case EXPR_LOGNOT:
00735         fprintf(h, "!");
00736         write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
00737         break;
00738     case EXPR_NOT:
00739         fprintf(h, "~");
00740         write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
00741         break;
00742     case EXPR_POS:
00743         fprintf(h, "+");
00744         write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
00745         break;
00746     case EXPR_NEG:
00747         fprintf(h, "-");
00748         write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
00749         break;
00750     case EXPR_ADDRESSOF:
00751         fprintf(h, "&");
00752         write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
00753         break;
00754     case EXPR_PPTR:
00755         fprintf(h, "*");
00756         write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
00757         break;
00758     case EXPR_CAST:
00759         fprintf(h, "(");
00760         write_type_decl(h, e->u.tref, NULL);
00761         fprintf(h, ")");
00762         write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
00763         break;
00764     case EXPR_SIZEOF:
00765         fprintf(h, "sizeof(");
00766         write_type_decl(h, e->u.tref, NULL);
00767         fprintf(h, ")");
00768         break;
00769     case EXPR_SHL:
00770     case EXPR_SHR:
00771     case EXPR_MOD:
00772     case EXPR_MUL:
00773     case EXPR_DIV:
00774     case EXPR_ADD:
00775     case EXPR_SUB:
00776     case EXPR_AND:
00777     case EXPR_OR:
00778     case EXPR_LOGOR:
00779     case EXPR_LOGAND:
00780     case EXPR_XOR:
00781     case EXPR_EQUALITY:
00782     case EXPR_INEQUALITY:
00783     case EXPR_GTR:
00784     case EXPR_LESS:
00785     case EXPR_GTREQL:
00786     case EXPR_LESSEQL:
00787         if (brackets) fprintf(h, "(");
00788         write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
00789         switch (e->type)
00790         {
00791         case EXPR_SHL:          fprintf(h, " << "); break;
00792         case EXPR_SHR:          fprintf(h, " >> "); break;
00793         case EXPR_MOD:          fprintf(h, " %% "); break;
00794         case EXPR_MUL:          fprintf(h, " * "); break;
00795         case EXPR_DIV:          fprintf(h, " / "); break;
00796         case EXPR_ADD:          fprintf(h, " + "); break;
00797         case EXPR_SUB:          fprintf(h, " - "); break;
00798         case EXPR_AND:          fprintf(h, " & "); break;
00799         case EXPR_OR:           fprintf(h, " | "); break;
00800         case EXPR_LOGOR:        fprintf(h, " || "); break;
00801         case EXPR_LOGAND:       fprintf(h, " && "); break;
00802         case EXPR_XOR:          fprintf(h, " ^ "); break;
00803         case EXPR_EQUALITY:     fprintf(h, " == "); break;
00804         case EXPR_INEQUALITY:   fprintf(h, " != "); break;
00805         case EXPR_GTR:          fprintf(h, " > "); break;
00806         case EXPR_LESS:         fprintf(h, " < "); break;
00807         case EXPR_GTREQL:       fprintf(h, " >= "); break;
00808         case EXPR_LESSEQL:      fprintf(h, " <= "); break;
00809         default: break;
00810         }
00811         write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
00812         if (brackets) fprintf(h, ")");
00813         break;
00814     case EXPR_MEMBER:
00815         if (brackets) fprintf(h, "(");
00816         if (e->ref->type == EXPR_PPTR)
00817         {
00818             write_expr(h, e->ref->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
00819             fprintf(h, "->");
00820         }
00821         else
00822         {
00823             write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
00824             fprintf(h, ".");
00825         }
00826         write_expr(h, e->u.ext, 1, 0, toplevel_prefix, cont_type, "");
00827         if (brackets) fprintf(h, ")");
00828         break;
00829     case EXPR_COND:
00830         if (brackets) fprintf(h, "(");
00831         write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
00832         fprintf(h, " ? ");
00833         write_expr(h, e->u.ext, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
00834         fprintf(h, " : ");
00835         write_expr(h, e->ext2, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
00836         if (brackets) fprintf(h, ")");
00837         break;
00838     case EXPR_ARRAY:
00839         if (brackets) fprintf(h, "(");
00840         write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix);
00841         fprintf(h, "[");
00842         write_expr(h, e->u.ext, 1, 1, toplevel_prefix, cont_type, local_var_prefix);
00843         fprintf(h, "]");
00844         if (brackets) fprintf(h, ")");
00845         break;
00846     }
00847 }
00848 
00849 /* This is actually fairly involved to implement precisely, due to the
00850    effects attributes may have and things like that.  Right now this is
00851    only used for optimization, so just check for a very small set of
00852    criteria that guarantee the types are equivalent; assume every thing
00853    else is different.   */
00854 static int compare_type(const type_t *a, const type_t *b)
00855 {
00856     if (a == b
00857         || (a->name
00858             && b->name
00859             && strcmp(a->name, b->name) == 0))
00860         return 0;
00861     /* Ordering doesn't need to be implemented yet.  */
00862     return 1;
00863 }
00864 
00865 int compare_expr(const expr_t *a, const expr_t *b)
00866 {
00867     int ret;
00868 
00869     if (a->type != b->type)
00870         return a->type - b->type;
00871 
00872     switch (a->type)
00873     {
00874         case EXPR_NUM:
00875         case EXPR_HEXNUM:
00876         case EXPR_TRUEFALSE:
00877             return a->u.lval - b->u.lval;
00878         case EXPR_DOUBLE:
00879             return a->u.dval - b->u.dval;
00880         case EXPR_IDENTIFIER:
00881         case EXPR_STRLIT:
00882         case EXPR_WSTRLIT:
00883         case EXPR_CHARCONST:
00884             return strcmp(a->u.sval, b->u.sval);
00885         case EXPR_COND:
00886             ret = compare_expr(a->ref, b->ref);
00887             if (ret != 0)
00888                 return ret;
00889             ret = compare_expr(a->u.ext, b->u.ext);
00890             if (ret != 0)
00891                 return ret;
00892             return compare_expr(a->ext2, b->ext2);
00893         case EXPR_OR:
00894         case EXPR_AND:
00895         case EXPR_ADD:
00896         case EXPR_SUB:
00897         case EXPR_MOD:
00898         case EXPR_MUL:
00899         case EXPR_DIV:
00900         case EXPR_SHL:
00901         case EXPR_SHR:
00902         case EXPR_MEMBER:
00903         case EXPR_ARRAY:
00904         case EXPR_LOGOR:
00905         case EXPR_LOGAND:
00906         case EXPR_XOR:
00907         case EXPR_EQUALITY:
00908         case EXPR_INEQUALITY:
00909         case EXPR_GTR:
00910         case EXPR_LESS:
00911         case EXPR_GTREQL:
00912         case EXPR_LESSEQL:
00913             ret = compare_expr(a->ref, b->ref);
00914             if (ret != 0)
00915                 return ret;
00916             return compare_expr(a->u.ext, b->u.ext);
00917         case EXPR_CAST:
00918             ret = compare_type(a->u.tref, b->u.tref);
00919             if (ret != 0)
00920                 return ret;
00921             /* Fall through.  */
00922         case EXPR_NOT:
00923         case EXPR_NEG:
00924         case EXPR_PPTR:
00925         case EXPR_ADDRESSOF:
00926         case EXPR_LOGNOT:
00927         case EXPR_POS:
00928             return compare_expr(a->ref, b->ref);
00929         case EXPR_SIZEOF:
00930             return compare_type(a->u.tref, b->u.tref);
00931         case EXPR_VOID:
00932             return 0;
00933     }
00934     return -1;
00935 }

Generated on Fri May 25 2012 04:36:13 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.