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_internal.c (38619B)


      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_internal.c
      8  * Purpose:     CINT internal functions
      9  */
     10 
     11 #include "cint_internal.h"
     12 #include "cint_porting.h"
     13 #include "cint_variables.h"
     14 #include "cint_interpreter.h"
     15 
     16 
     17 
     18 /*
     19  * Create a variable of the given type.
     20  */
     21 static int _auto_counter = 0;
     22 
     23 int 
     24 cint_array_combine_dimensions(cint_parameter_desc_t * type,
     25                               const cint_parameter_desc_t * parameter) {
     26     int dim_index;
     27     int t_pcount = type->pcount;
     28     int p_pcount = parameter->pcount;
     29     int t_array_count = type->num_dimensions;
     30     int p_array_count = parameter->num_dimensions;
     31 
     32     /* 
     33      * The ordering of dimensions should be
     34      * parameter array dimensions
     35      * parameter pointer dimensions
     36      * base type pointer dimensions
     37      * base type array dimensions
     38      */
     39 
     40     if((t_pcount + p_pcount + t_array_count + p_array_count) > 
     41         CINT_CONFIG_ARRAY_DIMENSION_LIMIT) {
     42         cint_internal_error(__FILE__, __LINE__, "dimensions exceed limit"); 
     43         return CINT_E_INTERNAL; 
     44     }
     45 
     46     /* 
     47      * run backwards so that we do not overwrite the data we need to copy 
     48      * forwards
     49      */ 
     50     for(dim_index = t_array_count - 1; 
     51         dim_index >= 0; 
     52         dim_index--) {
     53         int index =
     54             dim_index + p_array_count + p_pcount + t_pcount;
     55         type->dimensions[index] = type->dimensions[dim_index];
     56     }
     57 
     58     for(dim_index = 0; 
     59         dim_index < t_pcount + p_pcount; dim_index++) {
     60         type->dimensions[dim_index + p_array_count] = 
     61             CINT_CONFIG_POINTER_INFINITE_DIMENSION;
     62     }
     63 
     64     for(dim_index = 0; dim_index < p_array_count; dim_index++) {
     65         type->dimensions[dim_index] = 
     66             parameter->dimensions[dim_index];
     67     }
     68 
     69     type->num_dimensions = 
     70         t_pcount + p_pcount + t_array_count + p_array_count;
     71     return CINT_E_NONE;
     72 }
     73 
     74 
     75 cint_error_t
     76 cint_variable_create_no_add(cint_variable_t** rvar,
     77                             const char* vname,
     78                             const cint_parameter_desc_t* desc,
     79                             unsigned vflags,
     80                             void* addr)
     81 {
     82     int rc;
     83     cint_variable_t* v;
     84     int size;
     85 
     86     char name[CINT_CONFIG_MAX_VARIABLE_NAME];
     87 
     88     if(vname == NULL) {
     89         /* Create an autovar */
     90         CINT_SPRINTF(name, "__auto$%d", _auto_counter); 
     91         _auto_counter++; 
     92         vflags |= CINT_VARIABLE_F_AUTO; 
     93     }
     94     else {
     95         cint_strlcpy(name, vname, sizeof(name)); 
     96     }   
     97 
     98     v = cint_variable_alloc(); 
     99     
    100     if(v == NULL) {
    101         return CINT_E_MEMORY; 
    102     }            
    103 
    104     if((rc = cint_datatype_find(desc->basetype, &v->dt)) != CINT_E_NONE) {
    105         /* Datatype not found */
    106         return rc; 
    107     }
    108 
    109     if( (v->dt.flags & CINT_DATATYPE_F_ATOMIC) &&
    110         (v->dt.basetype.ap->flags & CINT_ATOMIC_TYPE_F_ABSTRACT) && 
    111         (v->dt.desc.pcount == 0) && 
    112         (desc->pcount == 0) ) {
    113         
    114         /* Cannot declare abstract variables */
    115         cint_variable_free(v); 
    116         return CINT_E_BAD_TYPE; 
    117     }
    118 
    119     v->name = CINT_STRDUP(name);     
    120 
    121     if(v->name == NULL) {        
    122         cint_variable_free(v); 
    123         return CINT_E_MEMORY; 
    124     }   
    125 
    126     v->flags = vflags; 
    127 
    128     if((rc = cint_array_combine_dimensions(&(v->dt.desc), desc)) !=
    129         CINT_E_NONE) {
    130         return rc;
    131     }
    132 
    133     v->dt.desc.pcount += desc->pcount; 
    134 
    135     if(v->dt.desc.num_dimensions > 0 && 
    136         v->dt.desc.dimensions[0] == CINT_CONFIG_POINTER_INFINITE_DIMENSION) {
    137         v->cached_num_dimensions = v->dt.desc.num_dimensions;
    138         v->dt.desc.num_dimensions = 0;
    139     }
    140 
    141     if((size = cint_datatype_size(&v->dt)) <= 0) {
    142         return CINT_E_INTERNAL; 
    143     }
    144 
    145     if (addr || (vflags & CINT_VARIABLE_F_SDATA)) {
    146         v->data = addr; 
    147     }
    148     else {
    149         v->data = CINT_MALLOC(size); 
    150         if(v->data == NULL) {
    151             cint_variable_free(v); 
    152             return CINT_E_MEMORY; 
    153         }   
    154         CINT_MEMSET(v->data, 0, size); 
    155 
    156         /* Special value assignments */
    157         if(v->dt.flags & CINT_DATATYPE_F_FUNC) {
    158             *(cint_fpointer_t*)v->data = v->dt.basetype.fp->addr; 
    159         }
    160     }
    161 
    162     if(v->data == NULL) {
    163         cint_variable_free(v); 
    164         return CINT_E_MEMORY; 
    165     }   
    166     
    167     v->size = size; 
    168 
    169     if(rvar) {
    170         *rvar = v; 
    171     }
    172     else {
    173         cint_variable_free(v); 
    174     }           
    175         
    176     return CINT_E_NONE; 
    177 }       
    178 
    179 cint_error_t
    180 cint_variable_create(cint_variable_t** rvar,
    181                       const char* vname,
    182                       const cint_parameter_desc_t* desc,
    183                       unsigned vflags,
    184                       void* addr)
    185 {
    186     cint_error_t rc;
    187 
    188     rc = cint_variable_create_no_add(rvar, vname, desc, vflags,addr);
    189     if ((rc == CINT_E_NONE) && rvar && *rvar) {
    190 
    191         cint_variable_add(*rvar);
    192     }
    193 
    194     return rc;
    195 }
    196 
    197 
    198 cint_variable_t* 
    199 cint_auto_atomic(const char* type)
    200 {
    201     cint_error_t rc; 
    202     cint_parameter_desc_t dt; 
    203     cint_variable_t* rv = NULL; 
    204 
    205     dt.basetype = type; 
    206     dt.pcount = 0; 
    207     dt.num_dimensions = 0; 
    208 
    209     rc = cint_variable_create(&rv, 
    210                               NULL, 
    211                               &dt, 
    212                               CINT_VARIABLE_F_AUTO | CINT_VARIABLE_F_CONST,
    213                               NULL);     
    214     return (rc == CINT_E_NONE) ? rv : NULL; 
    215 }
    216 
    217 cint_variable_t*
    218 cint_auto_string(const char* str)
    219 {
    220     cint_error_t rc; 
    221     cint_variable_t* rv = NULL; 
    222     
    223     cint_parameter_desc_t dt; 
    224     dt.basetype = "char"; 
    225     dt.pcount = 1; 
    226     dt.num_dimensions = 0; 
    227     
    228     rc = cint_variable_create(&rv, 
    229                               NULL, 
    230                               &dt, 
    231                               CINT_VARIABLE_F_AUTO |
    232                               CINT_VARIABLE_F_CONST |
    233                               CINT_VARIABLE_F_CSTRING, 
    234                               NULL); 
    235 
    236     if(rv) {
    237         *((char**)rv->data) = cint_cstring_value(str);
    238     }
    239 
    240     return (rc == CINT_E_NONE) ? rv : NULL; 
    241 }
    242 
    243 int
    244 cint_is_integer(cint_variable_t* v)
    245 {
    246     return v && (cint_atomic_flags(v) & CINT_ATOMIC_TYPE_FLAGS_INTEGRAL); 
    247 }
    248 
    249 int
    250 cint_is_enum(cint_variable_t* v)
    251 {
    252     return (v && 
    253             (v->dt.flags & CINT_DATATYPE_F_ENUM) && 
    254             v->dt.desc.pcount == 0 && 
    255             v->dt.desc.num_dimensions == 0); 
    256 }
    257 
    258 
    259 cint_variable_t*
    260 cint_auto_pointer(const char* type, void* value)
    261 {
    262     cint_datatype_t dt; 
    263     cint_variable_t* v = NULL; 
    264     cint_error_t rc; 
    265 
    266     CINT_MEMSET(&dt, 0, sizeof(dt));
    267     rc = cint_datatype_find((type) ? type : "void", &dt); 
    268     dt.desc.pcount=1; 
    269     if((rc = cint_variable_create(&v, NULL, &dt.desc, CINT_VARIABLE_F_CONST, NULL)) == CINT_E_NONE) {
    270         *(void**)v->data = value; 
    271     }   
    272     
    273     return v; 
    274 }
    275 
    276 
    277 int
    278 cint_is_pointer(cint_variable_t* v)
    279 {
    280     return v && (v->dt.desc.pcount > 0 && v->dt.desc.num_dimensions == 0); 
    281 }
    282 
    283 int
    284 cint_is_vpointer(cint_variable_t* v)
    285 {
    286     return cint_is_pointer(v) && !CINT_STRCMP(v->dt.desc.basetype, "void"); 
    287 }
    288 
    289 unsigned
    290 cint_atomic_flags(cint_variable_t* v)
    291 {    
    292     if(v == NULL) {
    293         return 0; 
    294     }
    295     
    296     if(v->dt.desc.pcount || v->dt.desc.num_dimensions) {
    297         return 0; 
    298     }   
    299 
    300     if((v->dt.flags & CINT_DATATYPE_F_ATOMIC) == 0) {
    301         return 0; 
    302     }   
    303     
    304     return v->dt.basetype.ap->flags; 
    305 }
    306 
    307 
    308 /*
    309  * 'long' variable operations
    310  */
    311 long 
    312 cint_long_value(cint_variable_t* v)
    313 {    
    314     long rc = 0; 
    315 
    316     switch((cint_atomic_flags(v) & CINT_ATOMIC_TYPE_FLAGS_MASK))
    317         {
    318         case CINT_ATOMIC_TYPE_F_CHAR:   
    319             if ((cint_atomic_flags(v) & CINT_ATOMIC_TYPE_F_UNSIGNED) != 0)
    320             {
    321                 rc = *(unsigned char*)v->data; 
    322             } else {
    323                 rc = *(signed char*)v->data; 
    324             }
    325             break;
    326         case CINT_ATOMIC_TYPE_F_SHORT:
    327             if ((cint_atomic_flags(v) & CINT_ATOMIC_TYPE_F_UNSIGNED) != 0)
    328             {
    329                 rc = *(unsigned short*)v->data;         
    330             } else {
    331                 rc = *(short*)v->data;
    332             }
    333             break;
    334 
    335         case CINT_ATOMIC_TYPE_F_INT:    rc = *(int*)v->data; break; 
    336         case CINT_ATOMIC_TYPE_F_LONG:   rc = *(long*)v->data; break; 
    337         case CINT_ATOMIC_TYPE_F_LONGLONG: rc = *(CINT_LONGLONG*)v->data; break; 
    338         case CINT_ATOMIC_TYPE_F_DOUBLE:   rc = *(CINT_DOUBLE*)v->data; break; 
    339         default: 
    340             {
    341                 if(v->dt.flags & CINT_DATATYPE_F_ENUM) {
    342                     rc = *(int*)v->data; 
    343                 }
    344                 break; /* Should never get here */
    345             }   
    346         }
    347 
    348     return rc; 
    349 }
    350 
    351 cint_variable_t* 
    352 cint_long_set(cint_variable_t* v, long i)
    353 {
    354     switch((cint_atomic_flags(v) & CINT_ATOMIC_TYPE_FLAGS_MASK))
    355         {
    356         case CINT_ATOMIC_TYPE_F_CHAR:   *(signed char*)v->data = i; break;
    357         case CINT_ATOMIC_TYPE_F_SHORT:  *(short*)v->data = i;  break; 
    358         case CINT_ATOMIC_TYPE_F_INT:    *(int*)v->data = i; break; 
    359         case CINT_ATOMIC_TYPE_F_LONG:   *(long*)v->data = i; break; 
    360         case CINT_ATOMIC_TYPE_F_LONGLONG: *(CINT_LONGLONG*)v->data = i; break; 
    361         case CINT_ATOMIC_TYPE_F_DOUBLE:   *(CINT_DOUBLE*)v->data = i; break; 
    362         default: 
    363             {
    364                 if(v->dt.flags & CINT_DATATYPE_F_ENUM) {
    365                     *(int*)v->data = i; 
    366                 }
    367                 break; 
    368             }   
    369         }
    370     return v; 
    371 }
    372 
    373 cint_variable_t* 
    374 cint_auto_long(long i)
    375 {    
    376     cint_variable_t* rv = NULL; 
    377     
    378     rv = cint_auto_atomic("long"); 
    379 
    380     if(rv) {
    381         *((long*)rv->data) = i; 
    382     }   
    383     
    384     return rv; 
    385 }
    386 
    387 
    388 cint_variable_t* 
    389 cint_auto_ulong(unsigned long i)
    390 {    
    391     cint_variable_t* rv = NULL; 
    392     
    393     rv = cint_auto_atomic("unsigned long"); 
    394 
    395     if(rv) {
    396         *((unsigned long*)rv->data) = i; 
    397     }   
    398     
    399     return rv; 
    400 }
    401 
    402 /*
    403  * 'int' variable operations
    404  */
    405 int 
    406 cint_integer_value(cint_variable_t* v) 
    407 { 
    408     return cint_long_value(v);
    409 }
    410 
    411 cint_variable_t*
    412 cint_integer_set(cint_variable_t* v, int i)
    413 {
    414     return cint_long_set(v, (long)i); 
    415 }
    416 
    417 cint_variable_t*
    418 cint_auto_integer(int i)
    419 {
    420     cint_variable_t* rv = NULL; 
    421 
    422     rv = cint_auto_atomic("int"); 
    423 
    424     if(rv) {
    425         *((int*)rv->data) = i; 
    426     }
    427     
    428     return rv; 
    429 }
    430 
    431 cint_variable_t*
    432 cint_auto_uinteger(unsigned int i)
    433 {
    434     cint_variable_t* rv = NULL; 
    435 
    436     rv = cint_auto_atomic("unsigned int"); 
    437 
    438     if(rv) {
    439         *((unsigned int*)rv->data) = i; 
    440     }
    441     
    442     return rv; 
    443 }
    444 
    445 /*
    446  * 'char' variable operations
    447  */
    448 signed char
    449 cint_char_value(cint_variable_t* v)
    450 {
    451     return cint_long_value(v); 
    452 }
    453 
    454 cint_variable_t*
    455 cint_char_set(cint_variable_t* v, char c)
    456 {
    457     return cint_long_set(v, (long)c); 
    458 }
    459 
    460 cint_variable_t*
    461 cint_auto_char(signed char c)
    462 {
    463     cint_variable_t* rv = NULL; 
    464     rv = cint_auto_atomic("char"); 
    465     if(rv) {
    466         *((signed char*)rv->data) = c;
    467     }
    468     return rv; 
    469 }
    470 
    471 /*
    472  * 'short' variable operations
    473  */
    474 short
    475 cint_short_value(cint_variable_t* v)
    476 {
    477     return cint_long_value(v); 
    478 }
    479 
    480 cint_variable_t*
    481 cint_short_set(cint_variable_t* v, short s)
    482 {
    483     return cint_long_set(v, (long)s); 
    484 }
    485 
    486 cint_variable_t*
    487 cint_auto_short(short c)
    488 {
    489     cint_variable_t* rv = NULL; 
    490     rv = cint_auto_atomic("short"); 
    491     if(rv) {
    492         *((short*)rv->data) = c; 
    493     }
    494     return rv; 
    495 }
    496 
    497 /*
    498  * 'long long' variable operations
    499  */
    500 CINT_LONGLONG
    501 cint_longlong_value(cint_variable_t* v)
    502 {    
    503 #if CINT_CONFIG_INCLUDE_LONGLONGS == 0
    504 
    505     /* Should never even get here */
    506     cint_internal_error(__FILE__, __LINE__, "in 'longlong' function but long longs not supported"); 
    507     return 0;
    508 
    509 #else
    510     
    511     long long rc = 0; 
    512 
    513     switch((cint_atomic_flags(v) & CINT_ATOMIC_TYPE_FLAGS_MASK))
    514         {
    515         case CINT_ATOMIC_TYPE_F_CHAR:                                      
    516             if(cint_atomic_flags(v) & CINT_ATOMIC_TYPE_F_UNSIGNED)
    517             {
    518                 rc = *(unsigned char*)v->data;
    519             }
    520             else
    521             {
    522                 rc = *(signed char*)v->data;
    523             }
    524             break;
    525         case CINT_ATOMIC_TYPE_F_SHORT:  
    526             if(cint_atomic_flags(v) & CINT_ATOMIC_TYPE_F_UNSIGNED)
    527             {
    528                 rc = *(unsigned short*)v->data;
    529             }
    530             else
    531             {
    532                 rc = *(short*)v->data;
    533             }
    534             break;
    535         case CINT_ATOMIC_TYPE_F_INT:    
    536             if(cint_atomic_flags(v) & CINT_ATOMIC_TYPE_F_UNSIGNED)
    537             {
    538                 rc = *(unsigned int*)v->data;
    539             }
    540             else
    541             {
    542                 rc = *(int*)v->data;
    543             }
    544             break;
    545         case CINT_ATOMIC_TYPE_F_LONG:   
    546             if(cint_atomic_flags(v) & CINT_ATOMIC_TYPE_F_UNSIGNED)
    547             {
    548                 rc = *(unsigned long*)v->data;
    549             }
    550             else
    551             {
    552                 rc = *(long*)v->data;
    553             }
    554             break;
    555         case CINT_ATOMIC_TYPE_F_LONGLONG: 
    556             if(cint_atomic_flags(v) & CINT_ATOMIC_TYPE_F_UNSIGNED)
    557             {
    558                 rc = *(unsigned CINT_LONGLONG*)v->data;
    559             }
    560             else
    561             {
    562                 rc = *(CINT_LONGLONG*)v->data;
    563             }
    564             break;
    565         case CINT_ATOMIC_TYPE_F_DOUBLE:   rc = *(CINT_DOUBLE*)v->data; break; 
    566         default: 
    567             {
    568                 if(v->dt.flags & CINT_DATATYPE_F_ENUM) {
    569                     rc = *(int*)v->data; 
    570                 }
    571                 break;
    572             }
    573         }
    574 
    575     return rc; 
    576 
    577 #endif
    578 }
    579 
    580 cint_variable_t* 
    581 cint_longlong_set(cint_variable_t* v, CINT_LONGLONG i)
    582 {
    583 #if CINT_CONFIG_INCLUDE_LONGLONGS == 0
    584     
    585     /* Should never even get here */
    586     cint_internal_error(__FILE__, __LINE__, "in 'longlong' function but long longs not supported"); 
    587     return NULL; 
    588 
    589 #else
    590 
    591     switch((cint_atomic_flags(v) & CINT_ATOMIC_TYPE_FLAGS_MASK))
    592         {
    593         case CINT_ATOMIC_TYPE_F_CHAR:   *(signed char*)v->data = i; break;
    594         case CINT_ATOMIC_TYPE_F_SHORT:  *(short*)v->data = i;  break; 
    595         case CINT_ATOMIC_TYPE_F_INT:    *(int*)v->data = i; break; 
    596         case CINT_ATOMIC_TYPE_F_LONG:   *(long*)v->data = i; break; 
    597         case CINT_ATOMIC_TYPE_F_LONGLONG: *(CINT_LONGLONG*)v->data = i; break; 
    598         case CINT_ATOMIC_TYPE_F_DOUBLE:   *(CINT_DOUBLE*)v->data = i; break; 
    599         default: 
    600             {
    601                 if(v->dt.flags & CINT_DATATYPE_F_ENUM) {
    602                     *(int*)v->data = i; 
    603                 }
    604                 break;
    605             }
    606         }
    607     return v; 
    608 
    609 #endif
    610 }
    611 
    612 cint_variable_t* 
    613 cint_auto_longlong(CINT_LONGLONG i)
    614 {    
    615 
    616 #if CINT_CONFIG_INCLUDE_LONGLONGS == 0
    617 
    618     /* Should never even get here */
    619     cint_internal_error(__FILE__, __LINE__, "in 'longlong' function but long longs not supported"); 
    620     return NULL; 
    621 
    622 #else
    623 
    624     cint_variable_t* rv = NULL; 
    625     
    626     rv = cint_auto_atomic("long long"); 
    627 
    628     if(rv) {
    629         *((long long*)rv->data) = i; 
    630     }   
    631 
    632     return rv; 
    633 #endif
    634 }
    635 
    636 cint_variable_t* 
    637 cint_auto_ulonglong(unsigned CINT_LONGLONG i)
    638 {    
    639 
    640 #if CINT_CONFIG_INCLUDE_LONGLONGS == 0
    641 
    642     /* Should never even get here */
    643     cint_internal_error(__FILE__, __LINE__, "in 'longlong' function but long longs not supported"); 
    644     return NULL; 
    645 
    646 #else
    647 
    648     cint_variable_t* rv = NULL; 
    649     
    650     rv = cint_auto_atomic("unsigned long long"); 
    651 
    652     if(rv) {
    653         *((unsigned long long*)rv->data) = i; 
    654     }   
    655 
    656     return rv; 
    657 #endif
    658 }
    659 
    660 
    661 
    662 /*
    663  * 'double' variable operations
    664  */
    665 CINT_DOUBLE
    666 cint_double_value(cint_variable_t* v)
    667 {    
    668 #if CINT_CONFIG_INCLUDE_DOUBLES == 0
    669 
    670     /* Should never even get here */
    671     cint_internal_error(__FILE__, __LINE__, "in 'double' function but doubles not supported"); 
    672     return 0;
    673 
    674 #else
    675     
    676     double rc = 0; 
    677 
    678     switch((cint_atomic_flags(v) & CINT_ATOMIC_TYPE_FLAGS_MASK))
    679         {
    680         case CINT_ATOMIC_TYPE_F_CHAR:   rc = *(signed char*)v->data; break;
    681         case CINT_ATOMIC_TYPE_F_SHORT:  rc = *(short*)v->data; break; 
    682         case CINT_ATOMIC_TYPE_F_INT:    rc = *(int*)v->data; break; 
    683         case CINT_ATOMIC_TYPE_F_LONG:   rc = *(long*)v->data; break; 
    684         case CINT_ATOMIC_TYPE_F_LONGLONG: rc = *(CINT_LONGLONG*)v->data; break; 
    685         case CINT_ATOMIC_TYPE_F_DOUBLE:   rc = *(CINT_DOUBLE*)v->data; break; 
    686         default: 
    687             {
    688                 if(v->dt.flags & CINT_DATATYPE_F_ENUM) {
    689                     rc = *(int*)v->data; 
    690                 }
    691                 break; 
    692             }   
    693         }
    694 
    695     return rc; 
    696 
    697 #endif
    698 }
    699 
    700 cint_variable_t* 
    701 cint_double_set(cint_variable_t* v, CINT_DOUBLE i)
    702 {
    703 #if CINT_CONFIG_INCLUDE_DOUBLES == 0
    704     
    705     /* Should never even get here */
    706     cint_internal_error(__FILE__, __LINE__, "in 'double' function but doubles not supported"); 
    707     return NULL; 
    708 
    709 #else
    710 
    711     switch((cint_atomic_flags(v) & CINT_ATOMIC_TYPE_FLAGS_MASK))
    712         {
    713         case CINT_ATOMIC_TYPE_F_CHAR:   *(signed char*)v->data = i; break;
    714         case CINT_ATOMIC_TYPE_F_SHORT:  *(short*)v->data = i;  break; 
    715         case CINT_ATOMIC_TYPE_F_INT:    *(int*)v->data = i; break; 
    716         case CINT_ATOMIC_TYPE_F_LONG:   *(long*)v->data = i; break; 
    717         case CINT_ATOMIC_TYPE_F_LONGLONG: *(CINT_LONGLONG*)v->data = i; break; 
    718         case CINT_ATOMIC_TYPE_F_DOUBLE:   *(CINT_DOUBLE*)v->data = i; break; 
    719         default: 
    720             {
    721                 if(v->dt.flags & CINT_DATATYPE_F_ENUM) {
    722                     *(int*)v->data = i; 
    723                 }       
    724                 break;
    725             }
    726         }
    727     return v; 
    728 
    729 #endif
    730 }
    731 
    732 cint_variable_t* 
    733 cint_auto_double(CINT_DOUBLE i)
    734 {    
    735 
    736 #if CINT_CONFIG_INCLUDE_DOUBLES == 0
    737 
    738     /* Should never even get here */
    739     cint_internal_error(__FILE__, __LINE__, "in 'double' function but doubles not supported"); 
    740     return NULL; 
    741 
    742 #else
    743 
    744     cint_variable_t* rv = NULL; 
    745     
    746     rv = cint_auto_atomic("double"); 
    747 
    748     if(rv) {
    749         *((double*)rv->data) = i; 
    750     }   
    751 
    752     return rv; 
    753 #endif
    754 }
    755 
    756 /* copy cstring data from src to dst */
    757 static void
    758 cint_variable_cstring_copy(cint_variable_t* dst, cint_variable_t* src)
    759 {
    760     char **from = (char **)src->data;
    761     char **to   = (char **)dst->data;
    762 
    763     /* For C string data, allocate a new string buffer so this copied
    764        variable data will remain valid after the source variable is
    765        deallocated. If the destination pointer is not NULL, free it. */
    766     if (*to) {
    767         CINT_FREE(*to);
    768     }
    769     *to = CINT_STRDUP(*from);
    770     dst->flags |= CINT_VARIABLE_F_CSTRING;
    771 }
    772 
    773 /* copy data from src to dst */
    774 void
    775 cint_variable_data_copy(cint_variable_t* dst, cint_variable_t* src)
    776 {
    777     if (src->flags & CINT_VARIABLE_F_CSTRING) {
    778         cint_variable_cstring_copy(dst, src);
    779     } else {
    780         CINT_MEMCPY(dst->data, src->data, dst->size);
    781     }
    782 }
    783 
    784 cint_variable_t*
    785 cint_variable_clone(cint_variable_t* v)
    786 {
    787     cint_error_t rc; 
    788     cint_variable_t* rv; 
    789 
    790     rc = cint_variable_create(&rv, 
    791                               NULL, 
    792                               &v->dt.desc, 
    793                               CINT_VARIABLE_F_AUTO,     
    794                               NULL); 
    795 
    796     if(rv) {
    797         cint_variable_data_copy(rv, v);
    798     }
    799     return (rc == CINT_E_NONE) ? rv : NULL; 
    800 }
    801 
    802 cint_variable_t*
    803 cint_variable_address(cint_variable_t* v)
    804 {
    805     cint_error_t rc; 
    806     cint_variable_t* rv = NULL; 
    807     cint_parameter_desc_t desc; 
    808     int dim_index;
    809 
    810     desc = v->dt.desc; 
    811     desc.pcount++; 
    812 
    813     if(((v->cached_num_dimensions + 1) > CINT_CONFIG_ARRAY_DIMENSION_LIMIT) ||
    814         ((desc.num_dimensions + 1) > CINT_CONFIG_ARRAY_DIMENSION_LIMIT)) {
    815         return NULL; 
    816     }
    817 
    818     for(dim_index = CINT_CONFIG_ARRAY_DIMENSION_LIMIT - 1; 
    819         dim_index > 0; 
    820         dim_index--) {
    821         desc.dimensions[dim_index] = 
    822             desc.dimensions[dim_index - 1];
    823     }
    824     desc.dimensions[0] = CINT_CONFIG_POINTER_INFINITE_DIMENSION;
    825 
    826     if(v->cached_num_dimensions != 0) {
    827         desc.num_dimensions = v->cached_num_dimensions;
    828     }
    829     desc.num_dimensions++;
    830     
    831     rc = cint_variable_create(&rv, 
    832                               NULL, 
    833                               &desc, 
    834                               CINT_VARIABLE_F_AUTO | CINT_VARIABLE_F_CONST,     
    835                               NULL); 
    836 
    837     if(rv) {
    838         rv->dt.type_num_dimensions = v->dt.type_num_dimensions;
    839         rv->dt.cap = v->dt.cap;
    840         * ((void**) rv->data) = v->data; 
    841     }
    842     return (rc == CINT_E_NONE) ? rv : NULL; 
    843 }
    844 
    845 
    846 int
    847 cint_ctoi(const char *s, long* dst)
    848 {
    849     unsigned long	n;
    850     unsigned int	neg, base = 10;
    851 
    852     s += (neg = (*s == '-'));
    853 
    854     if (*s == '0') {
    855     s++;
    856 
    857     if (*s == 'x' || *s == 'X') {
    858         base = 16;
    859         s++;
    860     } else if (*s == 'b' || *s == 'B') {
    861         base = 2;
    862         s++;
    863     } else {
    864         base = 8;
    865     }
    866     }
    867 
    868     for (n = 0; ((*s >= 'a' && *s <= 'f' && base > 10) ||
    869          (*s >= 'A' && *s <= 'F' && base > 10) ||
    870          (*s >= '0' && *s <= '9')); s++) {
    871     n = n * base +
    872         (*s >= 'a' ? *s - 'a' + 10 :
    873          *s >= 'A' ? *s - 'A' + 10 :
    874          *s - '0');
    875     }
    876     
    877     *dst = (neg ? -n : n); 
    878     
    879     
    880     if(*s && !(*s == 'l' || *s == 'L' || *s == 'u' || *s == 'U')) {
    881         /* Parse error */       
    882         return -1; 
    883     }   
    884     else {
    885         /* Success */
    886         return 0; 
    887     }   
    888 }
    889 
    890 #if CINT_CONFIG_INCLUDE_LONGLONGS == 1
    891 
    892 /*
    893   Not all systems that support 'long long' properly support the '%ll'
    894   print format specification, so CINT does not use '%ll' directly, but
    895   uses this instead.
    896  */
    897 
    898 char *
    899 cint_lltoa(char *buf,           /* Result buffer        */
    900            int len,             /* length of buffer     */
    901            unsigned long long num,       /* Number to convert    */
    902            int sign,            /* True if signed conversion */
    903            int base,            /* Conversion base      */
    904            int prec)            /* Minimum digits       */
    905 {
    906     char *s;
    907     int digit, c;
    908 
    909     if (sign) {
    910         if ((signed long long)num < 0) {
    911             num = -num;
    912         } else {
    913             sign = 0;
    914         }
    915     }
    916 
    917     /* start at end of buffer */
    918     s = buf+len;
    919     if (s > buf) {
    920         *--s = 0;
    921     }
    922     
    923     /* convert digits */
    924     do {
    925         if (s <= buf) {
    926             break;
    927         }
    928         digit = num % base;
    929         c = (digit < 10 ? '0' : '7') + digit;
    930         *--s = c;
    931         num /= base;
    932         prec--;
    933     } while (num);
    934 
    935     /* zero fill if needed */
    936     while (prec-- > 0 && (s > buf)) {
    937         *--s = '0';
    938     }
    939 
    940     /* add sign if requested */
    941     if (sign && (s > buf)) {
    942         *--s = '-';
    943     }
    944 
    945     return s;
    946 }
    947 
    948 int
    949 cint_ctolli(const char *s, long long* dst)
    950 {
    951     unsigned long long	n;
    952     unsigned int	neg, base = 10;
    953 
    954     s += (neg = (*s == '-'));
    955 
    956     if (*s == '0') {
    957     s++;
    958 
    959     if (*s == 'x' || *s == 'X') {
    960         base = 16;
    961         s++;
    962     } else if (*s == 'b' || *s == 'B') {
    963         base = 2;
    964         s++;
    965     } else {
    966         base = 8;
    967     }
    968     }
    969 
    970     for (n = 0; ((*s >= 'a' && *s <= 'f' && base > 10) ||
    971          (*s >= 'A' && *s <= 'F' && base > 10) ||
    972          (*s >= '0' && *s <= '9')); s++) {
    973     n = n * base +
    974         (*s >= 'a' ? *s - 'a' + 10 :
    975          *s >= 'A' ? *s - 'A' + 10 :
    976          *s - '0');
    977     }
    978     
    979     *dst = (neg ? -n : n); 
    980     
    981     
    982     if(*s && !(*s == 'l' || *s == 'L' || *s == 'u' || *s == 'U')) {
    983         /* Parse error */       
    984         return -1; 
    985     }   
    986     else {
    987         /* Success */
    988         return 0; 
    989     }   
    990 }
    991 #endif
    992 
    993 int
    994 cint_chartoi(const char* str, int* dst)
    995 {
    996     int rc; 
    997     const char* s = str; 
    998 
    999     if(s == NULL) {
   1000         return -1; 
   1001     }
   1002 
   1003     if(*s++ != '\'') {
   1004         /* Not a character constant */
   1005         return -1; 
   1006     }   
   1007 
   1008     /* First character after quote */
   1009     switch(*s) 
   1010         {
   1011         case 0: 
   1012             {
   1013                 /* incorrectly formed constant */ 
   1014                 return -1; 
   1015             }
   1016 
   1017         case '\\':
   1018             {
   1019                 /* Escaped character */
   1020                 s++; 
   1021                 switch(*s) /* First character after backslash */
   1022                     {
   1023                     case '0': rc = 0; break; 
   1024                     case '\\': rc = '\\'; break; 
   1025                     case 'a': rc = '\a'; break; 
   1026                     case 'b': rc = '\b'; break; 
   1027                     case 'f': rc = '\f'; break; 
   1028                     case 'n': rc = '\n'; break; 
   1029                     case 'r': rc = '\r'; break; 
   1030                     case 't': rc = '\t'; break; 
   1031                     case 'v': rc = '\v'; break; 
   1032                     case '\'': rc = '\''; break; 
   1033                     case '\"': rc = '\"'; break; 
   1034                     case '\?': rc = '\?'; break; 
   1035                     default: 
   1036                         {
   1037                             /* Warn and assume character value */
   1038                             cint_warn(NULL, 0, "invalid escape sequence (%s)", str); 
   1039                             rc = *s; 
   1040                             break; 
   1041                         }
   1042                     }   
   1043                 s++; /* Advance to next character */ 
   1044                 break; 
   1045             }
   1046         default:
   1047             {
   1048                 rc = *s++; /* Assign character value and advance to next character */
   1049                 break; 
   1050             }   
   1051         }
   1052 
   1053     
   1054     /* Validate and warn on input */
   1055     switch(s[0]) 
   1056         {
   1057         case '\'': 
   1058             {
   1059                 switch(s[1]) 
   1060                     {
   1061                     case 0: /* Good */ break; 
   1062                     default: 
   1063                         {
   1064                             /* Bad */
   1065                             cint_warn(NULL, 0, "invalid character sequence (%s)", str); 
   1066                             break; 
   1067                         }
   1068                     }  
   1069                 break; 
   1070             }   
   1071         default:
   1072             {
   1073                 if(s[0] == 0) {
   1074                     cint_warn(NULL, 0, "invalid character sequence (%s)", str); 
   1075                 }
   1076                 else {
   1077                     cint_warn(NULL, 0, "multi-byte characters not supported (%s)", str); 
   1078                 }
   1079                 break; 
   1080             }
   1081         }
   1082         
   1083     /* In all cases we return the first valid character value */
   1084     *dst = rc; 
   1085     return 0; 
   1086 }
   1087 
   1088 #if CINT_CONFIG_INCLUDE_DOUBLES == 1
   1089 
   1090 int
   1091 cint_ctod(const char *s, double* dst)
   1092 {
   1093     double n = 0;
   1094     double f = 0;
   1095     int neg; 
   1096 
   1097     s += (neg = (*s == '-'));
   1098 
   1099     /* Whole digits */
   1100     for (n = 0; (*s >= '0' && *s <= '9'); s++) {
   1101         n = n * 10 + (*s - '0'); 
   1102     }   
   1103 
   1104     /* Fractional digits */
   1105     if(*s == '.') {
   1106         double b = .1; 
   1107         s++;
   1108         for(f = 0; (*s >= '0' && *s <= '9'); s++) {
   1109             f += (*s - '0') * b;
   1110             b *= .1; 
   1111         }
   1112     }
   1113     n+=f; 
   1114     
   1115     /* Exponent */
   1116     if(*s == 'E' || *s == 'e') {
   1117         long exp; 
   1118         if(cint_ctoi(s+1, &exp) == 0) {
   1119             if(exp >= 0) {
   1120                 while(exp--) {
   1121                     n = n*10;
   1122                 }
   1123             }   
   1124             else {
   1125                 exp = -exp;
   1126                 while(exp--) {
   1127                     n = n / 10; 
   1128                 }
   1129             }
   1130             /* String already validated by cint_ctoi() - skip to end */
   1131             while(*s) s++; 
   1132         }       
   1133         else {
   1134             /* Bad exponent */
   1135             return -1; 
   1136         }
   1137     }
   1138         
   1139     *dst = (neg ? -n : n); 
   1140     
   1141     
   1142     if(*s && !(*s == 'l' || *s == 'L' || *s == 'f' || *s == 'F')) {
   1143         /* Parse error */       
   1144         return -1; 
   1145     }   
   1146     else {
   1147         /* Success */
   1148         return 0; 
   1149     }   
   1150 }
   1151 #endif
   1152 
   1153 void*
   1154 cint_pointer_value(cint_variable_t* v)
   1155 {
   1156     unsigned flags; 
   1157     
   1158     flags = cint_atomic_flags(v); 
   1159 
   1160     if(v->dt.desc.pcount) {
   1161         return *(void**)v->data; 
   1162     }    
   1163     else if(flags & CINT_ATOMIC_TYPE_FLAGS_CSIL) {
   1164         return (void*) cint_long_value(v); 
   1165     }
   1166     else if(flags & CINT_ATOMIC_TYPE_F_LONGLONG) {
   1167         /* Should warn here */
   1168         return (void*) cint_long_value(v); 
   1169     }
   1170     return NULL; 
   1171 }
   1172 
   1173 int
   1174 cint_logical_value(cint_variable_t* v)
   1175 {
   1176     unsigned flags; 
   1177     
   1178     if(v == NULL) {
   1179         return 0; 
   1180     }
   1181 
   1182     flags = cint_atomic_flags(v); 
   1183 
   1184     if(v->dt.desc.pcount) {
   1185         return (*(void**)v->data) != NULL; 
   1186     }
   1187     else if(flags & CINT_ATOMIC_TYPE_FLAGS_CSIL) {
   1188         return (cint_long_value(v) != 0); 
   1189     }
   1190     else if(flags & CINT_ATOMIC_TYPE_F_LONGLONG) {
   1191         return (cint_longlong_value(v) != 0); 
   1192     }
   1193     else if(flags & CINT_ATOMIC_TYPE_F_DOUBLE) {
   1194         return (cint_double_value(v) != 0); 
   1195     }
   1196     else if(v->dt.flags & CINT_DATATYPE_F_ENUM) {
   1197         return (cint_integer_value(v) != 0); 
   1198     }
   1199     cint_internal_error(__FILE__, __LINE__, "unknown variable type in cint_logical_value()"); 
   1200     return 0; 
   1201 }
   1202 
   1203 
   1204 
   1205 char*
   1206 cint_cstring_value(const char* s)
   1207 {
   1208     char* rv; 
   1209     const char* src; 
   1210     char* dst; 
   1211     
   1212     if(s == NULL) {
   1213         return NULL; 
   1214     }
   1215     
   1216     rv = CINT_STRDUP(s); 
   1217     
   1218     for(src = s, dst = rv; *src; src++, dst++) {
   1219         
   1220         if(src == s && *src == '"') {
   1221             /* Skip leading quote */
   1222             dst--; 
   1223             continue; 
   1224         }
   1225         
   1226         if(*src == '\\') {
   1227             switch(*(src+1))
   1228                 {
   1229                 case '\\':
   1230                     *dst = '\\'; break; 
   1231                 case 'n':
   1232                     *dst = '\n'; break; 
   1233                 case 't':
   1234                     *dst = '\t'; break; 
   1235                 case 'r':
   1236                     *dst  = '\r'; break; 
   1237                 case '"':
   1238                     *dst = '"'; break;                         
   1239                 }
   1240             src++;
   1241         }
   1242         else {
   1243             *dst = *src; 
   1244         }
   1245     }   
   1246     
   1247     /* Remove trailing quote */
   1248     dst--; 
   1249     *dst = 0; 
   1250     return rv; 
   1251 }
   1252 
   1253 static int
   1254 cint_type_enum_int(cint_datatype_t* dte, cint_datatype_t* dti)
   1255 {
   1256     return ((dte->flags & CINT_DATATYPE_F_ENUM) &&
   1257             (dti->flags & CINT_DATATYPE_F_ATOMIC) &&
   1258             (dti->basetype.ap->flags & CINT_ATOMIC_TYPE_F_INT));
   1259 }
   1260 
   1261 int
   1262 cint_type_compatible(cint_datatype_t* dt1, cint_datatype_t* dt2)
   1263 {
   1264     return cint_type_enum_int(dt1, dt2) || cint_type_enum_int(dt2, dt1);
   1265 }
   1266 
   1267 int
   1268 cint_type_check(cint_datatype_t* dt1, cint_datatype_t* dt2)
   1269 {
   1270     int dim_index;
   1271     if(dt1->desc.pcount != dt2->desc.pcount) {
   1272         /* Different pointer counts */
   1273         return 0; 
   1274     }
   1275     if(dt1->desc.num_dimensions != dt2->desc.num_dimensions) {
   1276         /* Different array dimensions */
   1277         return 0; 
   1278     }
   1279     else {
   1280         for(dim_index = 0; 
   1281             dim_index < dt1->desc.num_dimensions;
   1282             dim_index++) {
   1283             if(dt1->desc.dimensions[dim_index] != 
   1284                 dt2->desc.dimensions[dim_index]) {
   1285                 /* Different array sizes */
   1286                 return 0;
   1287             }
   1288         }
   1289     }
   1290 
   1291     if(dt1->basetype.p != dt2->basetype.p) {
   1292         return cint_type_compatible(dt1, dt2);
   1293     }   
   1294 
   1295     return 1; 
   1296 }
   1297 
   1298 
   1299 int
   1300 cint_eval_type_list(cint_ast_t* ast, char* basetype_out, int len,
   1301                     unsigned* flags,
   1302                     int       is_variable_declaration)
   1303 {
   1304     unsigned f = 0; 
   1305     cint_ast_t* p; 
   1306     int rc = CINT_E_NONE; 
   1307     const char* modifier = NULL;     
   1308     char type[64]; 
   1309     const char *basetype = NULL;
   1310 
   1311     if (flags) {
   1312         *flags = 0;
   1313     }
   1314 
   1315     for(p = ast; p && rc == CINT_E_NONE; p = p->next) {
   1316         
   1317         if(p->ntype == cintAstInteger) {
   1318             switch (p->utype.integer.i)
   1319                 {
   1320                 case CINT_AST_TYPE_F_SIGNED:
   1321                     {
   1322                         if(f & CINT_AST_TYPE_F_SIGNED) {
   1323                             rc = cint_ast_error(ast, CINT_E_BAD_TYPE, "'signed' specified multiple times"); 
   1324                         }
   1325                         else if(f & CINT_AST_TYPE_F_UNSIGNED) {
   1326                             rc = cint_ast_error(ast, CINT_E_BAD_TYPE, "both 'signed' and 'unsigned' specified"); 
   1327                         } 
   1328                         else {
   1329                             modifier = "signed"; 
   1330                         }
   1331                         break; 
   1332                     }   
   1333                 case CINT_AST_TYPE_F_UNSIGNED:
   1334                     {
   1335                         if(f & CINT_AST_TYPE_F_UNSIGNED) {
   1336                             rc = cint_ast_error(ast, CINT_E_BAD_TYPE, "'unsigned' specified multiple times"); 
   1337                         }
   1338                         else if(f & CINT_AST_TYPE_F_SIGNED) {
   1339                             rc = cint_ast_error(ast, CINT_E_BAD_TYPE, "both 'signed' and 'unsigned' specified"); 
   1340                         }
   1341                         else {
   1342                             modifier = "unsigned"; 
   1343                         }
   1344                         break;
   1345                     }   
   1346                 case CINT_AST_TYPE_F_EXTERN:
   1347                     {
   1348                         if(is_variable_declaration){
   1349                             rc = cint_ast_error(ast, CINT_E_BAD_TYPE, "'extern' variables are not supported");
   1350                         }
   1351                         break; 
   1352                     }
   1353                 case CINT_AST_TYPE_F_CONST:
   1354                     {
   1355                         if(f & CINT_AST_TYPE_F_CONST) {
   1356                             rc = cint_ast_error(ast, CINT_E_BAD_TYPE, "'const' specified multiple times"); 
   1357                         }
   1358                         break; 
   1359                     }
   1360                 case CINT_AST_TYPE_F_TYPEDEF:
   1361                     {
   1362                         if(f & CINT_AST_TYPE_F_TYPEDEF) {
   1363                             rc = cint_ast_error(ast, CINT_E_BAD_TYPE, "'typedef' specified multiple times"); 
   1364                         }
   1365                         break; 
   1366                     }
   1367                 case CINT_AST_TYPE_F_VOLATILE:                    
   1368                     {
   1369                         if(f & CINT_AST_TYPE_F_VOLATILE) {
   1370                             rc = cint_ast_error(ast, CINT_E_BAD_TYPE, "'volatile' specified multiple times"); 
   1371                         }
   1372                         break; 
   1373                     }
   1374                 case CINT_AST_TYPE_F_STATIC:
   1375                     {
   1376                         if(f & CINT_AST_TYPE_F_STATIC) {
   1377                             rc = cint_ast_error(ast, CINT_E_BAD_TYPE, "'static' specified multiple times"); 
   1378                         }
   1379                         break; 
   1380                     }
   1381                 default:
   1382                     {
   1383                         rc = cint_ast_error(ast, CINT_E_BAD_AST, "unknown ast type flag 0x%lx", p->utype.integer.i); 
   1384                         break; 
   1385                     }   
   1386                 }       
   1387             
   1388             if(rc == CINT_E_NONE) {
   1389                 f |= p->utype.integer.i; 
   1390             }   
   1391         }       
   1392         else if(p->ntype == cintAstType) {
   1393             if(basetype) {
   1394                 
   1395                 /*
   1396                  * Already a a type defined. Check for optional 'int' type
   1397                  */
   1398                 if(CINT_STRCMP(basetype, "int") && !CINT_STRCMP(p->utype.type.s, "int")) {
   1399                     /*
   1400                      * This is an optional int after a sized type -- like 'short int x'; 
   1401                      * Just ignore it. 
   1402                      */
   1403                 }
   1404                 else if(!CINT_STRCMP(basetype, "long") && !CINT_STRCMP(p->utype.type.s, "long")) {
   1405                     /* This is a 'long long' type */
   1406                     basetype = "long long"; 
   1407                 }
   1408                 else {
   1409                     rc = cint_ast_error(ast, CINT_E_BAD_AST, "two or more data types in declaration"); 
   1410                 }
   1411             }
   1412             else {
   1413                 basetype = p->utype.type.s; 
   1414             }
   1415         }
   1416         else {
   1417             rc = cint_ast_error(ast, CINT_E_BAD_AST, "Bad ast node in typelist (%d)", p->ntype); 
   1418         }       
   1419     }   
   1420 
   1421     /* Special cases and modifiers */
   1422     if((basetype == NULL) && (f & (CINT_AST_TYPE_F_SIGNED|CINT_AST_TYPE_F_UNSIGNED))) {
   1423         /* Type was specified as just "signed" or "unsigned" */
   1424         basetype = "int"; 
   1425     }
   1426 
   1427     if(modifier) {
   1428         CINT_SPRINTF(type, "%s %s", modifier, basetype); 
   1429         basetype = type; 
   1430     }
   1431 
   1432     if (flags) {
   1433         *flags = f;
   1434     }
   1435 
   1436     if (rc == CINT_E_NONE) {
   1437         if (basetype) {
   1438             cint_strlcpy(basetype_out, basetype, len);
   1439         } else {
   1440             *basetype_out = 0;
   1441         }
   1442     }
   1443     
   1444     return rc; 
   1445 }
   1446 
   1447 
   1448 extern char*
   1449 cint_strlcpy(char* dst, const char* src, int size)
   1450 {
   1451     CINT_STRNCPY(dst, src, size-1); 
   1452     dst[size-1] = 0; 
   1453     return dst; 
   1454 }
   1455 
   1456 void*
   1457 cint_maddr_dynamic_struct_t(void* p, int mnum, cint_struct_type_t* parent)
   1458 {
   1459     int dim_index;
   1460     int i; 
   1461     int offset = 0; 
   1462     const cint_parameter_desc_t* pd; 
   1463     cint_datatype_t dt; 
   1464     CINT_MEMSET(&dt, 0, sizeof(dt));
   1465 
   1466     for(i = 0, pd = parent->struct_members;      
   1467         i < mnum; 
   1468         i++, pd++) {
   1469 
   1470         
   1471         if(cint_datatype_find(pd->basetype, &dt) != CINT_E_NONE) {
   1472             cint_internal_error(__FILE__, __LINE__, "structure type unknown"); 
   1473             return p;
   1474         }       
   1475 
   1476         for(dim_index = 0;
   1477             dim_index < pd->num_dimensions; 
   1478             dim_index++) {
   1479             dt.desc.dimensions[dim_index + dt.desc.num_dimensions] = 
   1480                 pd->dimensions[dim_index];
   1481         }
   1482         dt.desc.num_dimensions += pd->num_dimensions;
   1483         dt.desc.pcount += pd->pcount; 
   1484         offset += cint_datatype_size(&dt); 
   1485         
   1486         while(offset % 4) offset++;
   1487     }   
   1488     
   1489     return ( ((char*)p) + offset ); 
   1490 }
   1491 
   1492 int
   1493 cint_parameter_count(cint_parameter_desc_t* start)
   1494 {
   1495     cint_parameter_desc_t* pd; 
   1496     for(pd = start; pd && pd->basetype; pd++); 
   1497     return pd - start; 
   1498 }
   1499 
   1500 int
   1501 cint_parameter_void(cint_parameter_desc_t* pd)
   1502 {
   1503     if(pd && pd->basetype) {
   1504         return !CINT_STRCMP(pd->basetype, "void") && pd->pcount == 0; 
   1505     }
   1506     else {
   1507         return 1; 
   1508     }
   1509 }           
   1510 
   1511 void 
   1512 cint_fparams_print(cint_parameter_desc_t* pd)
   1513 {
   1514     char _rstr[256] = {0};
   1515     if(cint_parameter_void(pd)) {
   1516         CINT_PRINTF("(void)"); 
   1517     }
   1518     else {
   1519         CINT_PRINTF("("); 
   1520         while((pd+1)->basetype) {
   1521             CINT_PRINTF("%s %s, ", cint_datatype_format_pd(pd, _rstr, 0), pd->name); 
   1522             pd++; 
   1523         }
   1524         CINT_PRINTF("%s %s)", cint_datatype_format_pd(pd, _rstr, 0), pd->name); 
   1525     }   
   1526 }
   1527 
   1528 int
   1529 cint_snprintf_ex(char** dst, int* size, const char* fmt, ...)
   1530 {
   1531     va_list args; 
   1532     int c = 0; 
   1533 
   1534     va_start(args, fmt); 
   1535 
   1536     /* Space left? */
   1537     if(*size >= 0) {
   1538         c = CINT_VSNPRINTF(*dst, *size, fmt, args); 
   1539         *dst += c; 
   1540         *size -= c; 
   1541     }
   1542 
   1543     va_end(args);
   1544 
   1545     return c; 
   1546 }