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 }