openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

cint_operators.c (44660B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        cint_operators.c
      8  * Purpose:     CINT operator functions
      9  */
     10 
     11 #include "cint_operators.h"
     12 #include "cint_porting.h"
     13 #include "cint_variables.h"
     14 #include "cint_eval_asts.h"
     15 #include "cint_internal.h"
     16 #include "cint_debug.h"
     17 #include "cint_error.h"
     18 #include "cint_datatypes.h"
     19 
     20 
     21 
     22 /*******************************************************************************
     23  * 
     24  * These macros are used to implement most of the arithmetic and logical 
     25  * operators
     26  */
     27 
     28 /* Perform a binary operation based on the given operand type */
     29 #define _CINT_BINARY_RESULT(_op,_type) ( (cint_##_type##_value(left)) _op (cint_##_type##_value(right)))
     30 /* Perform a binary operation based on the given operand type and create an autovar for the result */
     31 #define _CINT_BINARY_CREATE(_op,_type) ( (cint_auto_##_type(_CINT_BINARY_RESULT(_op,_type))) )
     32 
     33 /* Perform a unary operation based on the given operand type */
     34 #define _CINT_UNARY_RESULT(_op,_type) ( (_op cint_##_type##_value(right)) )
     35 /* Perform a unary operation based on the given operand type and create an autovar for the result */
     36 #define _CINT_UNARY_CREATE(_op,_type) ( cint_auto_##_type(_CINT_UNARY_RESULT(_op,_type)) )
     37 
     38 /* Perform a complete unary/binary arithmetical assign/create operation */
     39 #define _CINT_ARITH_OPERATION(_op,_ub,_ac) \
     40     switch(optype) { \
     41       case cintOperandInt:           return _CINT##_ub##_ac(_op, integer); \
     42       case cintOperandUInt:          return _CINT##_ub##_ac(_op, uinteger); \
     43       case cintOperandLong:          return _CINT##_ub##_ac(_op, long); \
     44       case cintOperandULong:         return _CINT##_ub##_ac(_op, ulong); \
     45       case cintOperandLongLong:      return _CINT##_ub##_ac(_op, longlong); \
     46       case cintOperandULongLong:     return _CINT##_ub##_ac(_op, ulonglong); \
     47       case cintOperandDouble:        return _CINT##_ub##_ac(_op, double); \
     48       case cintOperandPointer:       return _CINT##_ub##_ac(_op, logical); \
     49       default: cint_internal_error(__FILE__, __LINE__, "_CINT_ARITH_OPERATION: unexpected operand type 0x%x", optype); return NULL; } \
     50 
     51 /* Perform a complete unary/binary arithmetical assign/create operation */
     52 #define _CINT_INTEGRAL_OPERATION(_op,_ub,_ac) \
     53     switch(optype) { \
     54       case cintOperandInt:           return _CINT##_ub##_ac(_op, integer); \
     55       case cintOperandUInt:          return _CINT##_ub##_ac(_op, uinteger); \
     56       case cintOperandULong:         return _CINT##_ub##_ac(_op, ulong); \
     57       case cintOperandLongLong:      return _CINT##_ub##_ac(_op, longlong); \
     58       case cintOperandULongLong:      return _CINT##_ub##_ac(_op, ulonglong); \
     59       default: cint_internal_error(__FILE__, __LINE__, "_CINT_INTEGRAL_OPERATION: unexpected operand type 0x%x", optype); return NULL; } \
     60 
     61 
     62 
     63 /* Perform arithmetical and integral operations */
     64 #define CINT_BINARY_RESULT(_op) _CINT_ARITH_OPERATION(_op,_BINARY,_RESULT)
     65 #define CINT_BINARY_CREATE(_op) _CINT_ARITH_OPERATION(_op,_BINARY,_CREATE)
     66 #define CINT_UNARY_RESULT(_op)  _CINT_ARITH_OPERATION(_op,_UNARY,_RESULT)
     67 #define CINT_UNARY_CREATE(_op)  _CINT_ARITH_OPERATION(_op,_UNARY,_CREATE)
     68 
     69 /* Perform integral-only operations */
     70 #define CINT_IBINARY_RESULT(_op) _CINT_INTEGRAL_OPERATION(_op,_BINARY,_RESULT)
     71 #define CINT_IBINARY_CREATE(_op) _CINT_INTEGRAL_OPERATION(_op,_BINARY,_CREATE)
     72 #define CINT_IUNARY_RESULT(_op)  _CINT_INTEGRAL_OPERATION(_op,_UNARY,_RESULT)
     73 #define CINT_IUNARY_CREATE(_op)  _CINT_INTEGRAL_OPERATION(_op,_UNARY,_CREATE)
     74 
     75 /* Pointer Comparison Operations */
     76 #define CINT_PCBINARY_CREATE(_op) if(optype == cintOperandPointer) return cint_auto_integer(cint_pointer_value(left) _op cint_pointer_value(right))
     77 #define CINT_PCUNARY_CREATE(_op) if(optype == cintOperandPointer) return _op cint_pointer_value(right)
     78 #define CINT_PBINARY_CREATE(_op) CINT_PCBINARY_CREATE(_op); CINT_BINARY_CREATE(_op)
     79 #define CINT_PUNARY_CREATE(_op) CINT_PCUNARY_CREATE(_op); CINT_UNARY_CREATE(_op)
     80 
     81 /*
     82  * Check the actual operand value to be zero based on the given operand type
     83  */
     84 static int
     85 __cint_operator_operand_is_zero(cint_variable_t* operand, cint_operand_type_t optype)
     86 {
     87     if (operand != NULL) {
     88         switch(optype) {
     89             case cintOperandInt:           return (0 == cint_integer_value(operand));
     90             case cintOperandUInt:          return (0 == cint_uinteger_value(operand));
     91             case cintOperandLong:          return (0 == cint_long_value(operand));
     92             case cintOperandULong:         return (0 == cint_ulong_value(operand));
     93             case cintOperandLongLong:      return (0 == cint_longlong_value(operand)); 
     94             case cintOperandULongLong:     return (0 == cint_ulonglong_value(operand));
     95             case cintOperandDouble:        return ((CINT_DOUBLE)0.0 == cint_double_value(operand));
     96             case cintOperandPointer:       return (NULL == cint_pointer_value(operand));
     97             default: cint_internal_error(__FILE__, __LINE__, "__cint_operand_value_is_zero: unexpected operand type 0x%x", optype); return 1; 
     98         }
     99     }
    100     return(1);
    101 }
    102 
    103 /*
    104  * Calculate the size of the datatype to which a variable points
    105  */
    106 static int
    107 __cint_pointer_datatype_size(cint_variable_t* v)
    108 {
    109     cint_datatype_t dt; 
    110     dt = v->dt; 
    111     dt.desc.pcount--; 
    112     return cint_datatype_size(&dt); 
    113 }
    114 
    115 
    116 /*
    117  * Add a constant value to a pointer variable and return a 
    118  * new variable with the result. 
    119  */
    120 static cint_variable_t*
    121 __cint_pointer_add_constant(cint_variable_t* v, int count)
    122 {
    123     char* cp; 
    124     cint_variable_t* rv; 
    125     char* fptr = NULL;
    126 
    127     /* Clone the variable */
    128     rv = cint_variable_clone(v); 
    129 
    130     /* cp gets the pointer value */
    131     cp = (char*) *(void**)rv->data; 
    132     fptr = cp;
    133     cp += __cint_pointer_datatype_size(v) * count; 
    134     if(rv->flags & CINT_VARIABLE_F_CSTRING) {
    135         /*
    136          * if incremented ptr is 'char*'
    137          * 1. re-assing new pointer based on incremented address.
    138          * 2. free original ptr
    139          */
    140         *(void**)rv->data = (void*) CINT_STRDUP(cp);
    141         if(fptr) {
    142             CINT_FREE(fptr);
    143         }
    144     } else {
    145         *(void**)rv->data = (void*)cp;
    146     }
    147     return rv; 
    148 }
    149 
    150 static int
    151 __cint_pointer_conversion(cint_variable_t** v)
    152 {
    153     int dim_index;
    154     cint_error_t rc = CINT_E_NONE; 
    155     /*
    156      * Convert arrays to pointers to first element
    157      */
    158     if(v && *v && (*v)->dt.desc.num_dimensions != 0) {
    159         
    160         cint_variable_t* rv; 
    161         cint_parameter_desc_t desc = (*v)->dt.desc;
    162 
    163         /* Drop the array and increase the pointer count */
    164         desc.num_dimensions = 0; 
    165         desc.pcount++; 
    166         
    167         /* allocate pointer */
    168         rc = cint_variable_create(&rv, NULL, &desc, CINT_VARIABLE_F_AUTO, NULL); 
    169         if (rc == CINT_E_NONE) {
    170             /* Point to first element */
    171             *(void**)rv->data = (*v)->data; 
    172         
    173             /* Pass the original array size along for bounds checking
    174                and debug */
    175             rv->cached_num_dimensions = (*v)->dt.desc.num_dimensions;
    176             rv->dt.cap = (*v)->dt.cap;
    177             rv->dt.type_num_dimensions = (*v)->dt.type_num_dimensions;
    178             rv->dt.desc.num_dimensions = 0;
    179             for(dim_index = 0;
    180                 dim_index < (*v)->dt.desc.num_dimensions; 
    181                 dim_index++) {
    182                 rv->dt.desc.dimensions[dim_index] = 
    183                     desc.dimensions[dim_index];
    184             }
    185 
    186             /* Pass along AUTOCASTS */
    187             if((*v)->flags & CINT_VARIABLE_F_AUTOCAST) {
    188                 rv->flags |= CINT_VARIABLE_F_AUTOCAST; 
    189                 (*v)->flags &= ~CINT_VARIABLE_F_AUTOCAST; 
    190             }
    191             *v = rv;
    192         }
    193     }   
    194     return rc; 
    195 }
    196 
    197 static void __cint_bad_operands(cint_ast_t* ast, int op); 
    198 
    199 static int
    200 __cint_check_operand(cint_variable_t* v, unsigned opflags)
    201 {
    202     if(v) {
    203         unsigned vflags = cint_atomic_flags(v); 
    204 
    205         if(v->dt.desc.pcount > 0) {
    206             /* This is a pointer */
    207             return (opflags & CINT_OPERATOR_F_ACCEPT_POINTER); 
    208         }       
    209 
    210         if(vflags & CINT_ATOMIC_TYPE_FLAGS_INTEGRAL) {
    211             /* This is an integral type */
    212             return (opflags & CINT_OPERATOR_F_ACCEPT_INTEGRAL); 
    213         }
    214 
    215         if(vflags & CINT_ATOMIC_TYPE_F_DOUBLE) {
    216             /* This is a double type */
    217             return (opflags & CINT_OPERATOR_F_ACCEPT_DOUBLE); 
    218         }        
    219 
    220         /* All other types */
    221         return (opflags & CINT_OPERATOR_F_ACCEPT_ALL); 
    222     }
    223     return 1; 
    224 }       
    225 
    226 /*
    227  * All operator handlers. 
    228  */
    229 
    230 static cint_variable_t* 
    231 __cint_operator_RightShift(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    232 {
    233     CINT_IBINARY_CREATE(>>); 
    234 }
    235 
    236 
    237 static cint_variable_t* 
    238 __cint_operator_LeftShift(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    239 {
    240     CINT_IBINARY_CREATE(<<); 
    241 }
    242 
    243 
    244 static cint_variable_t* 
    245 __cint_operator_Increment(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    246 {
    247     cint_variable_t* rv = NULL; 
    248 
    249     if(left) {
    250         /* Post Increment */
    251         rv = cint_variable_clone(left);  
    252         cint_eval_operator_internal(ast, cintOpAssign, left, 
    253                                    cint_eval_operator_internal(ast, cintOpAdd, left, cint_auto_integer(1))); 
    254     }
    255     else if(right) {
    256         /* Pre Increment */
    257         rv = right; 
    258         cint_eval_operator_internal(ast, cintOpAssign, right, 
    259                                     cint_eval_operator_internal(ast, cintOpAdd, right, cint_auto_integer(1))); 
    260     }
    261     return rv; 
    262 }
    263 
    264 
    265 static cint_variable_t* 
    266 __cint_operator_Decrement(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    267 {
    268     cint_variable_t* rv = NULL; 
    269 
    270     if(left) {
    271         /* Post Decrement */
    272         rv = cint_variable_clone(left); 
    273         cint_eval_operator_internal(ast, cintOpAssign, left, 
    274                                     cint_eval_operator_internal(ast, cintOpSubtract, left, cint_auto_integer(1))); 
    275     }
    276     else if(right) {
    277         /* Pre Decrement */
    278         rv = right; 
    279         cint_eval_operator_internal(ast, cintOpAssign, right, 
    280                                     cint_eval_operator_internal(ast, cintOpSubtract, right, cint_auto_integer(1))); 
    281     }
    282     return rv;
    283 }
    284 
    285 
    286 static cint_variable_t* 
    287 __cint_operator_LogicalAnd(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    288 {
    289     /*
    290      * Left and Right are not yet evaluated. 
    291      */
    292 
    293     left = cint_eval_ast(ast->utype.operator.left); 
    294     if(left == NULL || (__cint_check_operand(left, CINT_OPERATOR_FLAGS_PBINARY) == 0)) {
    295         __cint_bad_operands(ast, cintOpLogicalAnd); 
    296         return NULL; 
    297     }
    298 
    299     if(cint_logical_value(left) == 0) {
    300         /* Shortcut evaluation */
    301         return cint_auto_integer(0); 
    302     }
    303 
    304     right = cint_eval_ast(ast->utype.operator.right); 
    305     if(right == NULL || (__cint_check_operand(right, CINT_OPERATOR_FLAGS_PBINARY) == 0)) {
    306         __cint_bad_operands(ast, cintOpLogicalAnd); 
    307         return NULL; 
    308     }
    309     
    310     return cint_auto_integer(cint_logical_value(right)); 
    311 }
    312 
    313 
    314 static cint_variable_t* 
    315 __cint_operator_LogicalOr(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    316 {
    317     /*
    318      * Left and Right are not yet evaluated. 
    319      */
    320 
    321     left = cint_eval_ast(ast->utype.operator.left); 
    322     if(left == NULL || (__cint_check_operand(left, CINT_OPERATOR_FLAGS_PBINARY) == 0)) {
    323         __cint_bad_operands(ast, cintOpLogicalOr); 
    324         return NULL; 
    325     }
    326 
    327     if(cint_logical_value(left) == 1) {
    328         /* Shortcut evaluation */
    329         return cint_auto_integer(1); 
    330     }
    331 
    332     right = cint_eval_ast(ast->utype.operator.right); 
    333     if(right == NULL || (__cint_check_operand(right, CINT_OPERATOR_FLAGS_PBINARY) == 0)) {
    334         __cint_bad_operands(ast, cintOpLogicalOr); 
    335         return NULL; 
    336     }
    337     
    338     return cint_auto_integer(cint_logical_value(right)); 
    339 }
    340 
    341 
    342 static cint_variable_t* 
    343 __cint_operator_LessThanOrEqual(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    344 {
    345     CINT_PBINARY_CREATE(<=); 
    346 }
    347 
    348 
    349 static cint_variable_t* 
    350 __cint_operator_GreaterThanOrEqual(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    351 {
    352     CINT_PBINARY_CREATE(>=); 
    353 }
    354 
    355 
    356 static cint_variable_t* 
    357 __cint_operator_Equal(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    358 {
    359     CINT_PBINARY_CREATE(==); 
    360 }
    361 
    362 
    363 static cint_variable_t* 
    364 __cint_operator_NotEqual(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    365 {
    366     CINT_PBINARY_CREATE(!=); 
    367 }
    368 
    369 
    370 static cint_variable_t* 
    371 __cint_operator_OpenBrace(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    372 {
    373     cint_variable_lscope_push("}"); 
    374     return NULL; 
    375 }
    376 
    377 
    378 static cint_variable_t* 
    379 __cint_operator_CloseBrace(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    380 {
    381     cint_variable_lscope_pop("{"); 
    382     return NULL; 
    383 }
    384 
    385 
    386 static cint_variable_t* 
    387 __cint_operator_Assign(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    388 {    
    389     unsigned lflags; 
    390     unsigned rflags; 
    391     cint_error_t rc; 
    392     char _rstr[256] = {0};
    393 
    394     /*
    395      * Left may not be a constant
    396      */
    397     if(left->flags & CINT_VARIABLE_F_CONST) {
    398         cint_ast_error(ast, CINT_E_BAD_OPERANDS, "constant lvalue in assignment"); 
    399         return NULL; 
    400     }
    401     /*
    402      * Is right a bracket initializer?
    403      */
    404     if(right == NULL) {
    405         /* Left must be a structure or array */
    406         if(left->dt.desc.num_dimensions) {
    407             cint_ast_t* init; 
    408             
    409             
    410 
    411             /* Foreach entry in the array */
    412             int i; 
    413             for(i = 0, init = ast->utype.operator.right->utype.initializer.initializers; 
    414                 init && i < left->dt.desc.dimensions[0]; 
    415                 i++, init = init->next) {
    416                 /* 
    417                  * Build an AST for this assignment 
    418                  */
    419                 cint_ast_t* l = cint_ast_identifier(left->name); 
    420                 cint_ast_t* r = cint_ast_integer(i); 
    421                 cint_ast_t* m  = cint_ast_operator(cintOpOpenBracket, l, r); 
    422                 cint_ast_t* nast = cint_ast_operator(cintOpAssign, m, init); 
    423                 cint_eval_ast(nast); 
    424 
    425                 /* Free up the ASTs as initializer evaluation is complete. */
    426                 cint_ast_free_single(nast);
    427                 cint_ast_free_single(m);
    428                 cint_ast_free_single(r);
    429                 cint_ast_free_single(l);
    430             }   
    431             if(init) {
    432                 cint_ast_error(ast, CINT_E_BAD_OPERANDS, "too many initializers"); 
    433                 return NULL; 
    434             }
    435             return left; 
    436         }
    437         else if(left->dt.flags & CINT_DATATYPE_F_STRUCT) {
    438             cint_ast_t* init; 
    439             
    440             /* Foreach parameter in the structure */
    441             const cint_parameter_desc_t* pd; 
    442             for(init = ast->utype.operator.right->utype.initializer.initializers, pd = left->dt.basetype.sp->struct_members; 
    443                 pd->name && init; 
    444                 pd++, init = init->next)
    445                 {
    446                     /* 
    447                      * Build an AST for this assignment 
    448                      */
    449                     cint_ast_t* l = cint_ast_identifier(left->name); 
    450                     cint_ast_t* r = cint_ast_identifier(pd->name); 
    451                     cint_ast_t* m = cint_ast_operator(cintOpDot, l, r); 
    452                     cint_ast_t* nast = cint_ast_operator(cintOpAssign, m, init); 
    453                     cint_eval_ast(nast);
    454 
    455                     /* Free up the ASTs as initializer evaluation is complete. */
    456                     cint_ast_free_single(nast);
    457                     cint_ast_free_single(m);
    458                     cint_ast_free_single(r);
    459                     cint_ast_free_single(l);
    460                 }
    461 
    462             if(init) {
    463                 cint_ast_error(ast, CINT_E_BAD_OPERANDS, "too many initializers"); 
    464                 return NULL; 
    465             }
    466         }       
    467         else {
    468             cint_ast_error(ast, CINT_E_BAD_OPERANDS, "bad initializer"); 
    469             return NULL; 
    470         }        
    471         return left; 
    472     }
    473 
    474 
    475     lflags = cint_atomic_flags(left); 
    476     rflags = cint_atomic_flags(right); 
    477 
    478     if(lflags && rflags) {
    479         
    480         /* Atomic types accept conversion/truncation */
    481         switch(lflags & CINT_ATOMIC_TYPE_FLAGS_MASK)
    482             {
    483             case CINT_ATOMIC_TYPE_F_CHAR:
    484                 if (lflags & CINT_ATOMIC_TYPE_F_SIGNED) {
    485                     cint_char_set(left, cint_char_value(right)); return left;
    486                 } else {
    487                     cint_char_set(left, cint_uchar_value(right)); return left;
    488                 }
    489             case CINT_ATOMIC_TYPE_F_SHORT:        cint_short_set(left, cint_short_value(right)); return left; 
    490             case CINT_ATOMIC_TYPE_F_INT:          cint_integer_set(left, cint_integer_value(right)); return left; 
    491             case CINT_ATOMIC_TYPE_F_LONG:         cint_long_set(left, cint_long_value(right)); return left; 
    492             case CINT_ATOMIC_TYPE_F_LONGLONG:     cint_longlong_set(left, cint_longlong_value(right)); return left; 
    493             case CINT_ATOMIC_TYPE_F_DOUBLE:        cint_double_set(left, cint_double_value(right)); return left; 
    494             default: cint_internal_error(__FILE__, __LINE__, "unexpected atomic type flags 0x%x", (unsigned int)lflags); return NULL; 
    495             }   
    496     }
    497     
    498     /* Pointer conversion for right hand side is allowed */
    499     if(cint_type_check(&left->dt, &right->dt) == 0) {
    500         __cint_pointer_conversion(&right); 
    501     }
    502 
    503     if(right == NULL) {
    504         cint_internal_error(__FILE__, __LINE__, "unexpected error");
    505         return NULL;
    506     }
    507 
    508     if( (left->dt.desc.pcount == 0) &&
    509         ( (left->dt.flags & CINT_DATATYPE_F_ATOMIC) || left->dt.cap) && 
    510         (((ast->utype.operator.right) && 
    511           (ast->utype.operator.right->ntype == cintAstString)) ||
    512          (right->flags & CINT_VARIABLE_F_CSTRING))) {
    513         /* 
    514          * This is a string assignment to a custom/atomic type. Pass the string to the type's 
    515          * assignment handler. 
    516          */
    517         
    518         if(left->dt.cap && left->dt.cap->assign) {
    519             if((rc = left->dt.cap->assign(left->data, *(char**)right->data)) != CINT_E_NONE) {
    520                 cint_ast_error(ast, rc, "datatype '%s' assignment error", left->dt.cap->name); 
    521                 return NULL; 
    522             }   
    523         } else if(left->dt.basetype.ap->assign) {
    524             cint_error_t rc = left->dt.basetype.ap->assign(left->data, *(char**)right->data); 
    525             if(rc != CINT_E_NONE) {
    526                 cint_ast_error(ast, rc, "datatype '%s' assignment error", cint_datatype_format(&left->dt,_rstr,0)); 
    527                 return NULL; 
    528             }
    529         }
    530         else {
    531             cint_ast_error(ast, CINT_E_UNSUPPORTED, "datatype '%s' from '%s' has no assignment function.", 
    532                            cint_datatype_format(&left->dt, _rstr, 0), left->dt.type); 
    533             return NULL; 
    534         }
    535 
    536         return left; 
    537     }
    538 
    539     /*
    540      * Function Pointer Assignments
    541      */
    542     if( (left->dt.flags & CINT_DATATYPE_F_FUNC_POINTER) ) {
    543 
    544         if(right->dt.flags & CINT_DATATYPE_F_FUNC) {
    545             /* function pointer = compiled function reference */
    546             CINT_MEMCPY(left->data, right->data, left->size); 
    547         }
    548         else if(right->dt.flags & CINT_DATATYPE_F_FUNC_DYNAMIC) {
    549             /* 
    550              * function pointer = dynamic function reference. 
    551              * 
    552              * This can only be supported if there is a matching function pointer
    553              * type for the dynamic function
    554              */
    555 
    556             /* Copy compiled callback handler type into address */
    557             CINT_MEMCPY(left->data, &left->dt.basetype.fpp->cb, sizeof(cint_fpointer_t)); 
    558             /* Set the data as the name of the dynamic function */
    559             left->dt.basetype.fpp->data = (void*)right->dt.basetype.fp->name;             
    560         }
    561         return left; 
    562     }   
    563 
    564     /*
    565      * Otherwise left and right must be of the same type with the following exceptions:
    566      *  void* = any pointer
    567      *  any pointer = void*
    568      *  variables with the AUTOCAST flag set. 
    569      */    
    570     if( (cint_type_check(&left->dt, &right->dt) == 0) && /* different types */
    571         ((cint_is_vpointer(left) && cint_is_pointer(right)) == 0) &&  /* not void* = pointer assignement */
    572         ((cint_is_pointer(left) && cint_is_vpointer(right)) == 0) &&  /* not a pointer = void* assignment */
    573         ((right->flags & CINT_VARIABLE_F_AUTOCAST) == 0) )            /* right side is not an autocast */
    574         {     
    575             char* f1 = cint_datatype_format(&left->dt, _rstr, 1); 
    576             cint_ast_error(ast, CINT_E_BAD_OPERANDS, "incompatible types in assignment (%s = %s)", 
    577                            f1, cint_datatype_format(&right->dt, _rstr, 0)); 
    578             CINT_FREE(f1); 
    579             return NULL; 
    580         }
    581 
    582     if(left->size != right->size &&
    583        right->dt.desc.pcount == 0) {
    584         /* Not allowed, even with autocasting */
    585         char* f1 = cint_datatype_format(&left->dt, _rstr, 1); 
    586         cint_ast_error(ast, CINT_E_BAD_OPERANDS, "incompatible sizes in assignment (%s = %s)", 
    587                        f1, cint_datatype_format(&right->dt, _rstr, 0)); 
    588         CINT_FREE(f1); 
    589         return NULL;         
    590     }
    591 
    592     cint_variable_data_copy(left, right);
    593 
    594     /* Clear any autocast flags set for this assignment */
    595     if(CINT_VARIABLE_F_AUTOCAST) {
    596         right->flags &= ~CINT_VARIABLE_F_AUTOCAST; 
    597     }
    598 
    599     return left; 
    600 }
    601 
    602 
    603 static cint_variable_t* 
    604 __cint_operator_OpenBracket(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    605 {
    606     int index = 0; 
    607 
    608     /*
    609      * Left must resolve to a pointer
    610      */
    611     if(left->dt.desc.pcount == 0) {
    612         cint_ast_error(ast, CINT_E_BAD_TYPE, "subscripted value is not a pointer"); 
    613         return NULL; 
    614     }
    615     
    616     /*
    617      * Left must not be void
    618      */
    619     if(cint_is_vpointer(left)) {
    620         cint_ast_error(ast, CINT_E_BAD_TYPE, "cannot dereference void pointer"); 
    621         return NULL; 
    622     }
    623 
    624     /*
    625      * Left must not be NULL
    626      */
    627     if( (*(char**)left->data) == NULL) {
    628         cint_ast_error(ast, CINT_E_BAD_VARIABLE, "subscripted value is NULL"); 
    629         return NULL; 
    630     }
    631 
    632     /*
    633      * Right must resolve to integral value
    634      */ 
    635     if((cint_atomic_flags(right) & CINT_ATOMIC_TYPE_FLAGS_INTEGRAL) == 0) {
    636         cint_ast_error(ast, CINT_E_BAD_TYPE, "array subscript is not an integral"); 
    637         return NULL; 
    638     }
    639     else {
    640         index = cint_integer_value(right); 
    641     }
    642 
    643     /* If the original variable was a pointer-converted array, check the bounds */
    644     if(left->cached_num_dimensions) {
    645         if(index < 0 || index >= left->dt.desc.dimensions[0]) {
    646             cint_ast_error(ast, CINT_E_BAD_TYPE, "array subscript out of range"); 
    647             return NULL;
    648         }       
    649     }   
    650     {   
    651         cint_error_t rc; 
    652         cint_parameter_desc_t desc; 
    653         cint_variable_t* rv; 
    654         char* p; 
    655         int dim_index;
    656         int dataTypeSize;
    657 
    658         desc = left->dt.desc; 
    659 
    660         if(left->cached_num_dimensions <= 1) {
    661             /* dereference to base element type */
    662             desc.pcount--; 
    663             rc = cint_variable_create(
    664                 &rv, 
    665                 NULL, 
    666                 &desc, 
    667                 CINT_VARIABLE_F_AUTO|CINT_VARIABLE_F_SDATA, 
    668                 (void*)0x1); 
    669             dataTypeSize = rv->size;
    670         }
    671         else {
    672             /* remove one dimension */
    673             desc.pcount = 1;
    674             desc.num_dimensions = 0;
    675             rc = cint_variable_create(
    676                 &rv, 
    677                 NULL, 
    678                 &desc,
    679                 CINT_VARIABLE_F_AUTO|CINT_VARIABLE_F_SDATA,
    680                 (void*)0x1); 
    681 
    682             rv->dt.desc.num_dimensions = left->cached_num_dimensions - 1;
    683             for(dim_index = 0; 
    684                 dim_index < rv->dt.desc.num_dimensions;
    685                 dim_index++) {
    686                 rv->dt.desc.dimensions[dim_index] = 
    687                     desc.dimensions[dim_index + 1];
    688             }
    689 
    690             rv->dt.desc.pcount = left->dt.desc.pcount - 1;
    691 
    692             dataTypeSize = cint_datatype_size(&rv->dt);
    693         }
    694 
    695         if(rv->dt.desc.num_dimensions > 0 && 
    696             rv->dt.desc.dimensions[0] == 
    697                 CINT_CONFIG_POINTER_INFINITE_DIMENSION) {
    698             rv->cached_num_dimensions = rv->dt.desc.num_dimensions;
    699             rv->dt.desc.num_dimensions = 0;
    700         }
    701 
    702         if(rv->cached_num_dimensions >= left->dt.type_num_dimensions ||
    703             rv->dt.desc.num_dimensions >= left->dt.type_num_dimensions) {
    704             rv->dt.cap = left->dt.cap;
    705             rv->dt.type_num_dimensions = left->dt.type_num_dimensions;
    706         }
    707         
    708         if (rc == CINT_E_NONE) {
    709             /* Replace the address */
    710             p = *(char**)left->data; 
    711             p += (dataTypeSize * cint_integer_value(right));
    712             rv->data = p;
    713         }
    714         return rv;
    715     }
    716     return NULL; 
    717 }
    718 
    719 static cint_variable_t* 
    720 __cint_operator_BitwiseAnd(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    721 {
    722     CINT_IBINARY_CREATE(&); 
    723 }
    724 
    725 
    726 static cint_variable_t* 
    727 __cint_operator_Not(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    728 {
    729     CINT_UNARY_CREATE(!); 
    730 }
    731 
    732 
    733 static cint_variable_t* 
    734 __cint_operator_Tilde(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    735 {
    736     CINT_IUNARY_CREATE(~); 
    737 }
    738 
    739 
    740 static cint_variable_t* 
    741 __cint_operator_Subtract(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    742 {
    743     if(left->dt.desc.pcount) {
    744         /*
    745          * We can subtract constant integral values and other pointers of the same type
    746          */
    747         if((cint_atomic_flags(right) & CINT_ATOMIC_TYPE_FLAGS_INTEGRAL) == 0) {
    748             
    749             if(cint_type_check(&left->dt, &right->dt)) {
    750                 /* Same pointer type */
    751                 char* leftp = (char*) *(void**)left->data; 
    752                 char* rightp = (char*) *(void**)right->data; 
    753 
    754                 /* Return the difference between the pointers */
    755                 return cint_auto_integer( (leftp-rightp) / __cint_pointer_datatype_size(left));                 
    756             }
    757             else {
    758                 cint_ast_error(ast, CINT_E_BAD_OPERANDS, "invalid pointer subtraction"); 
    759                 return NULL; 
    760             }
    761         }
    762         else {
    763             return __cint_pointer_add_constant(left, -1*cint_integer_value(right)); 
    764         }
    765     }
    766     CINT_BINARY_CREATE(-); 
    767 }
    768 
    769 
    770 static cint_variable_t* 
    771 __cint_operator_Add(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    772 {    
    773     if(left->dt.desc.pcount) {
    774         /* 
    775          * We can only add constant integral values to pointers
    776          */     
    777         if((cint_atomic_flags(right) & CINT_ATOMIC_TYPE_FLAGS_INTEGRAL) == 0) {
    778             cint_ast_error(ast, CINT_E_BAD_OPERANDS, "invalid pointer addition"); 
    779             return NULL; 
    780         }
    781         return __cint_pointer_add_constant(left, cint_integer_value(right)); 
    782     }
    783     CINT_BINARY_CREATE(+); 
    784 }
    785 
    786 
    787 static cint_variable_t* 
    788 __cint_operator_Multiply(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    789 {
    790     CINT_BINARY_CREATE(*); 
    791 }
    792 
    793 
    794 static cint_variable_t* 
    795 __cint_operator_Divide(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    796 {
    797     if ((0 == cint_logical_value(right)) || (0 != __cint_operator_operand_is_zero(right, optype))) {
    798         cint_ast_error(ast, CINT_E_BAD_OPERANDS, "attempt to divide by zero");
    799         return NULL;
    800     }
    801 
    802     CINT_BINARY_CREATE(/); 
    803 }
    804 
    805 
    806 static cint_variable_t* 
    807 __cint_operator_Mod(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    808 {
    809     if ((0 == cint_logical_value(right)) || (0 != __cint_operator_operand_is_zero(right, optype))) {
    810         cint_ast_error(ast, CINT_E_BAD_OPERANDS, "attempt to divide by zero");
    811         return NULL;
    812     }
    813 
    814     CINT_IBINARY_CREATE(%); 
    815 }
    816 
    817 
    818 static cint_variable_t* 
    819 __cint_operator_LessThan(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    820 {
    821     CINT_PBINARY_CREATE(<); 
    822 }
    823 
    824 
    825 static cint_variable_t* 
    826 __cint_operator_GreaterThan(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    827 {
    828     CINT_PBINARY_CREATE(>); 
    829 }
    830 
    831 
    832 static cint_variable_t* 
    833 __cint_operator_BitwiseXor(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    834 {
    835     CINT_IBINARY_CREATE(^); 
    836 }
    837 
    838 
    839 static cint_variable_t* 
    840 __cint_operator_BitwiseOr(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    841 {
    842     CINT_IBINARY_CREATE(|); 
    843 }
    844 
    845 
    846 static cint_variable_t* 
    847 __cint_operator_Question(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    848 {
    849     /*
    850      * Left contains the condition. 
    851      */
    852     if(cint_logical_value(left)) {
    853         /* Right contains the true expression */
    854         return cint_eval_ast(ast->utype.operator.right); 
    855     }
    856     else {
    857         return cint_eval_ast(ast->utype.operator.extra); 
    858     }
    859 }
    860 
    861 
    862 static cint_variable_t* 
    863 __cint_operator_AddressOf(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    864 {
    865     return cint_variable_address(right); 
    866 }
    867 
    868 
    869 static cint_variable_t* 
    870 __cint_operator_Dereference(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    871 {
    872     int dim_index;
    873     if(right->dt.desc.pcount == 0) {
    874         cint_ast_error(ast, CINT_E_BAD_OPERANDS, "cannot dereference non-pointer"); 
    875         return NULL; 
    876     }
    877     else if (!CINT_STRCMP(right->dt.desc.basetype, "void")) {
    878         cint_ast_error(ast, CINT_E_BAD_OPERANDS, "attempt to dereference void pointer"); 
    879         return NULL; 
    880     }
    881     else {
    882         cint_error_t rc; 
    883         cint_parameter_desc_t desc;             
    884         cint_variable_t* rv; 
    885 
    886         desc = right->dt.desc; 
    887         desc.pcount--; 
    888         desc.num_dimensions = right->cached_num_dimensions - 1;
    889         for(dim_index = 0; 
    890             dim_index < desc.num_dimensions; 
    891             dim_index++) {
    892             desc.dimensions[dim_index] = 
    893                 desc.dimensions[dim_index + 1];
    894         }
    895 
    896         if((*(void**)right->data) == NULL) {
    897             cint_ast_error(ast, CINT_E_BAD_OPERANDS, "attempt to dereference NULL pointer"); 
    898             return NULL; 
    899         }
    900 
    901         rc = cint_variable_create(
    902             &rv, 
    903             NULL, 
    904             &desc, 
    905             CINT_VARIABLE_F_AUTO|CINT_VARIABLE_F_SDATA, 
    906             *(void**)right->data);
    907         rv->dt.desc.pcount = right->dt.desc.pcount - 1;
    908         rv->dt.desc.num_dimensions = right->cached_num_dimensions - 1;
    909         for(dim_index = 0;
    910             dim_index < rv->dt.desc.num_dimensions;
    911             dim_index++) {
    912             rv->dt.desc.dimensions[dim_index] = 
    913                 right->dt.desc.dimensions[dim_index + 1];
    914         }
    915 
    916         if(rv->dt.desc.num_dimensions > 0 && 
    917             rv->dt.desc.dimensions[0] == 
    918                 CINT_CONFIG_POINTER_INFINITE_DIMENSION) {
    919             rv->cached_num_dimensions = rv->dt.desc.num_dimensions;
    920             rv->dt.desc.num_dimensions = 0;
    921         }
    922 
    923         rv->dt.cap = right->dt.cap;
    924         rv->dt.type_num_dimensions = right->dt.type_num_dimensions;
    925         return (rc == CINT_E_NONE) ? rv : NULL;
    926     }
    927 }
    928 
    929 
    930 static cint_variable_t* 
    931 __cint_operator_Positive(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    932 {
    933     CINT_UNARY_CREATE(+);
    934 }
    935 
    936 
    937 static cint_variable_t* 
    938 __cint_operator_Negative(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    939 {
    940     CINT_UNARY_CREATE(-); 
    941 }
    942 
    943 
    944 static cint_variable_t* 
    945 __cint_operator_Sizeof(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    946 {
    947     return cint_auto_integer(right->size); 
    948 }
    949 
    950 
    951 static int
    952 __find_struct_member_index(const char* member, const cint_parameter_desc_t* table)
    953 {
    954     const cint_parameter_desc_t* sm; 
    955     
    956     for(sm = table; sm->name; sm++) {
    957         if(!CINT_STRCMP(sm->name, member)) {
    958             return sm-table;
    959         }
    960     }
    961     return CINT_E_NOT_FOUND; 
    962 }
    963 
    964 static cint_variable_t*
    965 __cint_operator_Dot(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
    966 {
    967     int idx; 
    968     void* addr; 
    969     cint_variable_t* rv; 
    970 
    971     /*
    972      * Left must always be a structure
    973      * Right must always be an identifier
    974      */
    975     const char* member = ast->utype.operator.right->utype.identifier.s; 
    976     
    977     if( ((left->dt.flags & CINT_DATATYPE_F_STRUCT) == 0) ||
    978         left->dt.desc.pcount != 0 ) {
    979         cint_ast_error(ast, CINT_E_PARAM, "request for member '%s' in something not a structure", 
    980                        member); 
    981         return NULL; 
    982     }
    983     
    984     /*
    985      * Left points to a structure 
    986      */
    987     idx = __find_struct_member_index(member, left->dt.basetype.sp->struct_members); 
    988     if(idx < 0) {
    989         /* Member does no exist in this structure */
    990         cint_ast_error(ast, CINT_E_PARAM, "struct '%s' has no member '%s'", 
    991                        left->dt.basetype.sp->name, member); 
    992         return NULL; 
    993     }
    994 
    995     /*
    996      * Get the address of this member
    997      */
    998     addr = left->dt.basetype.sp->maddr(left->data, idx, left->dt.basetype.sp); 
    999 
   1000     /*
   1001      * Create a variable of this type with this address
   1002      */
   1003     cint_variable_create(&rv, 
   1004                          NULL, 
   1005                          left->dt.basetype.sp->struct_members+idx, 
   1006                          CINT_VARIABLE_F_SDATA, 
   1007                          addr); 
   1008     
   1009     return rv; 
   1010 }
   1011 
   1012 static cint_variable_t*
   1013 __cint_operator_Arrow(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
   1014 {
   1015     int idx; 
   1016     void* addr; 
   1017     cint_variable_t* rv; 
   1018 
   1019     /*
   1020      * Left must always be a structure pointer
   1021      * Right must always be an identifier
   1022      */
   1023     const char* member = ast->utype.operator.right->utype.identifier.s; 
   1024     
   1025     if( ((left->dt.flags & CINT_DATATYPE_F_STRUCT) == 0) ||
   1026         left->dt.desc.pcount != 1 ) {
   1027         cint_ast_error(ast, CINT_E_PARAM, "request for member '%s' in something not a structure", 
   1028                        member); 
   1029         return NULL; 
   1030     }
   1031     
   1032     /*
   1033      * Left points to a structure pointer 
   1034      */
   1035     idx = __find_struct_member_index(member, left->dt.basetype.sp->struct_members); 
   1036     if(idx < 0) {
   1037         /* Member does no exist in this structure */
   1038         cint_ast_error(ast, CINT_E_PARAM, "struct '%s' has no member '%s'", 
   1039                        left->dt.basetype.sp->name, member); 
   1040         return NULL; 
   1041     }
   1042 
   1043     /*
   1044      * Check for NULL pointer dereference 
   1045      */
   1046     if((*(void**)left->data) == NULL) {
   1047         cint_ast_error(ast, CINT_E_BAD_OPERANDS, "attempt to dereference a NULL structure member pointer"); 
   1048         return NULL; 
   1049     }
   1050 
   1051     /*
   1052      * Get the address of this member
   1053      */
   1054     addr = left->dt.basetype.sp->maddr(*((void**)left->data), idx, left->dt.basetype.sp); 
   1055     
   1056     
   1057     /*
   1058      * Create a variable of this type with this address
   1059      */
   1060     cint_variable_create(&rv, 
   1061                          NULL, 
   1062                          left->dt.basetype.sp->struct_members+idx, 
   1063                          CINT_VARIABLE_F_SDATA, 
   1064                          addr); 
   1065     
   1066     return rv; 
   1067 }
   1068 
   1069 
   1070 static cint_variable_t*
   1071 __cint_operator_Typecast(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right)
   1072 {
   1073     /*
   1074      * Right is the evaluated expression to typecast. 
   1075      * The left Ast contains the typename. 
   1076      *
   1077      * Full typename parsing is not yet implemented. 
   1078      * 
   1079      * Only the following are currently supported:
   1080      *
   1081      *  Casts to 'void*' -- left == 1 (See grammar)
   1082      *  Autocasts -- left == 2 (See grammer) allow variables to be any required type
   1083  */
   1084     cint_ast_t* type = ast->utype.operator.left; 
   1085     if(type == CINT_AST_PTR_VOID) {
   1086         /* Cast to 'void*' */
   1087         if(cint_is_pointer(right) || cint_is_integer(right)) {
   1088             return cint_auto_pointer("void", cint_pointer_value(right)); 
   1089         }   
   1090         else {
   1091             cint_ast_error(ast, CINT_E_BAD_TYPE, "bad type in cast"); 
   1092             return NULL; 
   1093         }
   1094     }
   1095     
   1096     if(type == CINT_AST_PTR_AUTO) {
   1097         /* Autocast */
   1098         right->flags |= CINT_VARIABLE_F_AUTOCAST; 
   1099         return right; 
   1100     }
   1101     return NULL; 
   1102 }
   1103     
   1104 
   1105 static int
   1106 __cint_arithmetic_conversions(cint_variable_t** left, cint_variable_t** right)
   1107 {
   1108     unsigned lflags = 0; 
   1109     unsigned rflags = 0; 
   1110 
   1111     /* Convert enums to ints */
   1112     if(left && cint_is_enum(*left)) {
   1113         *left = cint_auto_integer(cint_integer_value(*left)); 
   1114     }
   1115     if(right && cint_is_enum(*right)) {
   1116         *right = cint_auto_integer(cint_integer_value(*right)); 
   1117     }
   1118     
   1119     if(left == NULL || *left == NULL || right == NULL || *right == NULL) {
   1120         /* Nothing else to do */
   1121         return CINT_E_NONE; 
   1122     }
   1123 
   1124     if(cint_type_check(&(*left)->dt, &(*right)->dt)) {
   1125         /* They are already the same type. Nothing to do. */
   1126         return CINT_E_NONE; 
   1127     }
   1128 
   1129     lflags = cint_atomic_flags(*left); 
   1130     rflags = cint_atomic_flags(*right); 
   1131 
   1132     if( ((lflags & CINT_ATOMIC_TYPE_FLAGS_ARITH) == 0) ||
   1133         ((rflags & CINT_ATOMIC_TYPE_FLAGS_ARITH) == 0)) {
   1134         /* They are not both atomic arithmetic types. Nothing to do. */
   1135         return CINT_E_NONE;
   1136     }
   1137 
   1138 
   1139     /* If either is 'double', convert both to double */
   1140     if((lflags & CINT_ATOMIC_TYPE_F_DOUBLE) || (rflags & CINT_ATOMIC_TYPE_F_DOUBLE)) {
   1141         if(lflags & CINT_ATOMIC_TYPE_F_DOUBLE) {
   1142             *right = cint_auto_double(cint_double_value(*right)); 
   1143         }
   1144         else {
   1145             *left = cint_auto_double(cint_double_value(*left)); 
   1146         }
   1147         return CINT_E_NONE; 
   1148     }
   1149 
   1150     /* 
   1151      * Integral promotions. All char, short, and enum => integer. 
   1152      * It is assumed all values will fit in an integer. 
   1153      * We don't perform conversion to unsigned integer
   1154      */
   1155     if(lflags & (CINT_ATOMIC_TYPE_F_CHAR | CINT_ATOMIC_TYPE_F_SHORT) ) {
   1156         *left = cint_auto_integer(cint_integer_value(*left)); 
   1157         lflags = cint_atomic_flags(*left); 
   1158     }   
   1159     if(rflags & (CINT_ATOMIC_TYPE_F_CHAR | CINT_ATOMIC_TYPE_F_SHORT)) {
   1160         *right = cint_auto_integer(cint_integer_value(*right)); 
   1161         rflags = cint_atomic_flags(*right); 
   1162     }
   1163 
   1164     if(rflags == lflags) {
   1165         /* At this point if the flags are equal they are the same type. */
   1166         return CINT_E_NONE; 
   1167     }   
   1168 
   1169     /*
   1170      * Long Long and long promotion
   1171      */
   1172     if( (lflags & CINT_ATOMIC_TYPE_F_LONGLONG) ||
   1173         (lflags & CINT_ATOMIC_TYPE_F_LONGLONG) ) {
   1174 
   1175         if(lflags & CINT_ATOMIC_TYPE_F_LONGLONG) {
   1176             *right = cint_auto_longlong(cint_longlong_value(*right)); 
   1177         }
   1178         else {
   1179             *left = cint_auto_longlong(cint_longlong_value(*left)); 
   1180         }
   1181         return CINT_E_NONE;
   1182     }
   1183     if( (lflags & CINT_ATOMIC_TYPE_F_LONG) ||
   1184         (rflags & CINT_ATOMIC_TYPE_F_LONG) ) {
   1185 
   1186         if(lflags & CINT_ATOMIC_TYPE_F_LONG) {
   1187             *right = cint_auto_long(cint_long_value(*right)); 
   1188         }
   1189         else {
   1190             *left = cint_auto_long(cint_long_value(*left)); 
   1191         }
   1192         return CINT_E_NONE; 
   1193     }
   1194     
   1195     return CINT_E_NONE; 
   1196 }
   1197 
   1198 
   1199 static struct {
   1200 
   1201     const char* name; 
   1202     const char* iname; 
   1203     cint_variable_t* (*handler)(cint_ast_t* ast, cint_operand_type_t optype, cint_variable_t* left, cint_variable_t* right); 
   1204     unsigned flags; 
   1205 
   1206 } __operator_table[] = {
   1207 
   1208 #define CINT_OPERATOR_LIST_ENTRY(iname, _entry,f) { iname, #_entry, __cint_operator_##_entry, f }, 
   1209 #include "cint_op_entry.h"
   1210 
   1211     { NULL }
   1212 }; 
   1213 
   1214 
   1215 cint_variable_t*
   1216 cint_eval_operator_internal(cint_ast_t* ast, cint_operator_t op, cint_variable_t* left, cint_variable_t* right)
   1217 {
   1218     unsigned flags; 
   1219     int optype = 0; 
   1220     cint_variable_t* rv = NULL; 
   1221 
   1222     flags = __operator_table[op].flags; 
   1223     
   1224     if((flags & CINT_OPERATOR_F_ACCEPT_ALL) == 0) {
   1225 
   1226         /*
   1227          * Perform all arithmetic type conversions
   1228          */
   1229         __cint_arithmetic_conversions(&left, &right); 
   1230     
   1231         /*
   1232          * Perform pointer conversions 
   1233          */
   1234         __cint_pointer_conversion(&left); 
   1235         __cint_pointer_conversion(&right); 
   1236         /* 
   1237          * Not all types are accepted by the operator. 
   1238          * Check the operands for compatibility. 
   1239          */
   1240         if(__cint_check_operand(left, flags) == 0) {
   1241             __cint_bad_operands(ast, op); 
   1242             return NULL; 
   1243         }
   1244         if(__cint_check_operand(right, flags) == 0) {
   1245             __cint_bad_operands(ast, op); 
   1246             return NULL; 
   1247         }       
   1248     }
   1249             
   1250     if( (left && left->dt.desc.pcount) ||
   1251         (right && right->dt.desc.pcount) ) {
   1252 
   1253         /* Pointer operands */
   1254         optype = cintOperandPointer; 
   1255     }
   1256     else {
   1257 
   1258         unsigned flags = cint_atomic_flags(right) | cint_atomic_flags(left); 
   1259         
   1260         switch(flags & CINT_ATOMIC_TYPE_FLAGS_MASK) 
   1261             {
   1262             case CINT_ATOMIC_TYPE_F_INT:         optype = cintOperandInt; break; 
   1263             case CINT_ATOMIC_TYPE_F_LONG:        optype = cintOperandLong; break; 
   1264             case CINT_ATOMIC_TYPE_F_LONGLONG:    optype = cintOperandLongLong; break; 
   1265             case CINT_ATOMIC_TYPE_F_DOUBLE:      optype = cintOperandDouble; break; 
   1266             }   
   1267         /* If either operand is unsigned, treat all as unsigned */
   1268         optype += ( (flags & CINT_ATOMIC_TYPE_F_UNSIGNED) != 0); 
   1269     }
   1270 
   1271     rv = __operator_table[op].handler(ast, optype, left, right); 
   1272 
   1273 
   1274     if(flags & CINT_OPERATOR_F_LOGICAL) {
   1275         /*
   1276          * The result of this operator should be a logical integer. 
   1277          */
   1278         rv = cint_auto_integer(cint_logical_value(rv)); 
   1279     }
   1280 
   1281     return rv;   
   1282 }
   1283 
   1284 cint_variable_t*
   1285 cint_eval_operator(cint_ast_t* ast) 
   1286 {
   1287     cint_operator_t op = ast->utype.operator.op; 
   1288     cint_variable_t* left = NULL; 
   1289     cint_variable_t* right = NULL; 
   1290     unsigned flags = 0; 
   1291 
   1292     if(op >= cintOpLast) {
   1293         cint_errno = CINT_E_BAD_OPERATOR; 
   1294         return NULL; 
   1295     }   
   1296     
   1297     if(ast->ntype != cintAstOperator) {
   1298         cint_internal_error(__FILE__, __LINE__, "cint_eval_operator on non operator ast"); 
   1299         return NULL; 
   1300     }
   1301 
   1302     CINT_DTRACE(("OP '%s' %s", __operator_table[op].name, __operator_table[op].iname));     
   1303     
   1304     flags = __operator_table[op].flags; 
   1305 
   1306     /*
   1307      * Evaluate Left Value
   1308      */
   1309     if(flags & CINT_OPERATOR_F_LEFT) {
   1310         left = cint_eval_ast(ast->utype.operator.left); 
   1311         if(left == NULL &&
   1312            !(flags & CINT_OPERATOR_F_OPTIONAL)) {
   1313             __cint_bad_operands(ast, op); 
   1314             return NULL; 
   1315         }        
   1316     }
   1317 
   1318     /* 
   1319      * Evaluate Right Value
   1320      */
   1321     if(flags & CINT_OPERATOR_F_RIGHT) {
   1322         right = cint_eval_ast(ast->utype.operator.right); 
   1323 
   1324         if(right == NULL && 
   1325            !(flags & CINT_OPERATOR_F_OPTIONAL) &&
   1326            ((ast->utype.operator.right == NULL) ||
   1327            !(op == cintOpAssign &&
   1328              ast->utype.operator.right->ntype == cintAstInitializer)) ) {
   1329             __cint_bad_operands(ast, op); 
   1330             return NULL; 
   1331         }        
   1332     }
   1333     
   1334     return cint_eval_operator_internal(ast, op, left, right); 
   1335                          
   1336 }
   1337 
   1338 static void __cint_bad_operands(cint_ast_t* ast, int op)
   1339 {       
   1340     cint_ast_error(ast, CINT_E_BAD_OPERANDS, "invalid operand(s) to '%s'", __operator_table[op].name); 
   1341 }
   1342 
   1343 const char*
   1344 cint_operator_name(cint_operator_t op)
   1345 {
   1346     if(op >= cintOpLast) {
   1347         cint_errno = CINT_E_BAD_OPERATOR; 
   1348         return NULL; 
   1349     }
   1350     else {
   1351         return __operator_table[op].name; 
   1352     }
   1353 }
   1354 
   1355 cint_operator_t
   1356 cint_operator_type(cint_ast_t* ast)
   1357 {
   1358     cint_operator_t rc = cintOpLast; 
   1359     
   1360     if(ast->ntype == cintAstOperator) {
   1361         rc = ast->utype.operator.op; 
   1362     }
   1363 
   1364     return rc; 
   1365 }
   1366