1 /* 2 ** C type management. 3 ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice below. 4 ** 5 ** This file contains derived work from LuaJIT's FFI type system (lj_ctype.c). 6 ** 7 ** Modifications: 8 ** - Adapted VM interactions to use ucode's API (uc_vm_t, uc_value_t, etc.) 9 ** - Adapted type registration and lookup for ucode resource system 10 ** - Removed JIT-specific code and dependencies 11 ** 12 ** See NOTICE and ATTRIBUTION.md for complete attribution details. 13 */ 14 15 16 #include <stdio.h> 17 #include <assert.h> 18 19 #include "ucode/util.h" 20 21 #include "uc_ctype.h" 22 23 /* Hash constants from lj_tab.h - inlined since lj_tab.h removed */ 24 #define HASH_ROT1 14 25 #define HASH_ROT2 5 26 #define HASH_ROT3 13 27 28 static UC_AINLINE uint32_t hashrot(uint32_t lo, uint32_t hi) 29 { 30 #if UC_TARGET_X86ORX64 31 lo ^= hi; hi = uc_rol(hi, HASH_ROT1); 32 lo -= hi; hi = uc_rol(hi, HASH_ROT2); 33 hi ^= lo; hi -= uc_rol(lo, HASH_ROT3); 34 #else 35 lo ^= hi; 36 lo = lo - uc_rol(hi, HASH_ROT1); 37 hi = lo ^ uc_rol(hi, HASH_ROT1 + HASH_ROT2); 38 hi = hi - uc_rol(lo, HASH_ROT3); 39 #endif 40 return hi; 41 } 42 43 /* -- C type definitions -------------------------------------------------- */ 44 45 /* Predefined typedefs. */ 46 #define CTTDDEF(_) \ 47 /* Vararg handling. */ \ 48 _("va_list", P_VOID) \ 49 _("__builtin_va_list", P_VOID) \ 50 _("__gnuc_va_list", P_VOID) \ 51 /* From stddef.h. */ \ 52 _("ptrdiff_t", INT_PSZ) \ 53 _("size_t", UINT_PSZ) \ 54 _("wchar_t", WCHAR) \ 55 /* Subset of stdint.h. */ \ 56 _("int8_t", INT8) \ 57 _("int16_t", INT16) \ 58 _("int32_t", INT32) \ 59 _("int64_t", INT64) \ 60 _("uint8_t", UINT8) \ 61 _("uint16_t", UINT16) \ 62 _("uint32_t", UINT32) \ 63 _("uint64_t", UINT64) \ 64 _("intptr_t", INT_PSZ) \ 65 _("uintptr_t", UINT_PSZ) \ 66 /* From POSIX. */ \ 67 _("ssize_t", INT_PSZ) \ 68 /* End of typedef list. */ 69 70 /* Keywords (only the ones we actually care for). */ 71 #define CTKWDEF(_) \ 72 /* Type specifiers. */ \ 73 _("void", -1, CTOK_VOID) \ 74 _("_Bool", 0, CTOK_BOOL) \ 75 _("bool", 1, CTOK_BOOL) \ 76 _("char", 1, CTOK_CHAR) \ 77 _("int", 4, CTOK_INT) \ 78 _("__int8", 1, CTOK_INT) \ 79 _("__int16", 2, CTOK_INT) \ 80 _("__int32", 4, CTOK_INT) \ 81 _("__int64", 8, CTOK_INT) \ 82 _("float", 4, CTOK_FP) \ 83 _("double", 8, CTOK_FP) \ 84 _("long", 0, CTOK_LONG) \ 85 _("short", 0, CTOK_SHORT) \ 86 _("_Complex", 0, CTOK_COMPLEX) \ 87 _("complex", 0, CTOK_COMPLEX) \ 88 _("__complex", 0, CTOK_COMPLEX) \ 89 _("__complex__", 0, CTOK_COMPLEX) \ 90 _("signed", 0, CTOK_SIGNED) \ 91 _("__signed", 0, CTOK_SIGNED) \ 92 _("__signed__", 0, CTOK_SIGNED) \ 93 _("unsigned", 0, CTOK_UNSIGNED) \ 94 /* Type qualifiers. */ \ 95 _("const", 0, CTOK_CONST) \ 96 _("__const", 0, CTOK_CONST) \ 97 _("__const__", 0, CTOK_CONST) \ 98 _("volatile", 0, CTOK_VOLATILE) \ 99 _("__volatile", 0, CTOK_VOLATILE) \ 100 _("__volatile__", 0, CTOK_VOLATILE) \ 101 _("restrict", 0, CTOK_RESTRICT) \ 102 _("__restrict", 0, CTOK_RESTRICT) \ 103 _("__restrict__", 0, CTOK_RESTRICT) \ 104 _("inline", 0, CTOK_INLINE) \ 105 _("__inline", 0, CTOK_INLINE) \ 106 _("__inline__", 0, CTOK_INLINE) \ 107 /* Storage class specifiers. */ \ 108 _("typedef", 0, CTOK_TYPEDEF) \ 109 _("extern", 0, CTOK_EXTERN) \ 110 _("static", 0, CTOK_STATIC) \ 111 _("auto", 0, CTOK_AUTO) \ 112 _("register", 0, CTOK_REGISTER) \ 113 /* GCC Attributes. */ \ 114 _("__extension__", 0, CTOK_EXTENSION) \ 115 _("__attribute", 0, CTOK_ATTRIBUTE) \ 116 _("__attribute__", 0, CTOK_ATTRIBUTE) \ 117 _("asm", 0, CTOK_ASM) \ 118 _("__asm", 0, CTOK_ASM) \ 119 _("__asm__", 0, CTOK_ASM) \ 120 /* MSVC Attributes. */ \ 121 _("__declspec", 0, CTOK_DECLSPEC) \ 122 _("__cdecl", CTCC_CDECL, CTOK_CCDECL) \ 123 _("__thiscall", CTCC_THISCALL, CTOK_CCDECL) \ 124 _("__fastcall", CTCC_FASTCALL, CTOK_CCDECL) \ 125 _("__stdcall", CTCC_STDCALL, CTOK_CCDECL) \ 126 _("__ptr32", 4, CTOK_PTRSZ) \ 127 _("__ptr64", 8, CTOK_PTRSZ) \ 128 /* Other type specifiers. */ \ 129 _("struct", 0, CTOK_STRUCT) \ 130 _("union", 0, CTOK_UNION) \ 131 _("enum", 0, CTOK_ENUM) \ 132 /* Operators. */ \ 133 _("sizeof", 0, CTOK_SIZEOF) \ 134 _("__alignof", 0, CTOK_ALIGNOF) \ 135 _("__alignof__", 0, CTOK_ALIGNOF) \ 136 /* End of keyword list. */ 137 138 /* Type info for predefined types. Size merged in. */ 139 static CTInfo uc_ctype_typeinfo[] = { 140 #define CTTYINFODEF(id, sz, ct, info) CTINFO((ct), (((sz) & 0x3fu) << 10) + (info)), 141 #define CTTDINFODEF(name, id) CTINFO(CT_TYPEDEF, CTID_##id), 142 #define CTKWINFODEF(name, sz, kw) CTINFO(CT_KW, (((sz) & 0x3fu) << 10) + (kw)), 143 CTTYDEF(CTTYINFODEF) 144 CTTDDEF(CTTDINFODEF) 145 CTKWDEF(CTKWINFODEF) 146 #undef CTTYINFODEF 147 #undef CTTDINFODEF 148 #undef CTKWINFODEF 149 0}; 150 151 /* Predefined type names collected in a single string. */ 152 static const char *const uc_ctype_typenames = 153 #define CTTDNAMEDEF(name, id) name "\0" 154 #define CTKWNAMEDEF(name, sz, cds) name "\0" 155 CTTDDEF(CTTDNAMEDEF) 156 CTKWDEF(CTKWNAMEDEF) 157 #undef CTTDNAMEDEF 158 #undef CTKWNAMEDEF 159 ; 160 161 #define CTTYPEINFO_NUM (sizeof(uc_ctype_typeinfo) / sizeof(CTInfo) - 1) 162 #ifdef LUAJIT_CTYPE_CHECK_ANCHOR 163 #define CTTYPETAB_MIN CTTYPEINFO_NUM 164 #else 165 #define CTTYPETAB_MIN 128 166 #endif 167 168 /* -- C type interning ---------------------------------------------------- */ 169 170 #define ct_hashtype(info, size) (hashrot(info, size) & CTHASH_MASK) 171 172 static inline uint32_t 173 ct_hashname(uc_value_t *uv) 174 { 175 uint8_t *u8 = NULL; 176 size_t len = 0; 177 uint32_t h; 178 179 h = ucv_type(uv); 180 181 switch (h) 182 { 183 case UC_STRING: 184 u8 = (uint8_t *)ucv_string_get(uv); 185 len = ucv_string_length(uv); 186 break; 187 188 default: 189 assert(0); 190 } 191 192 while (len > 0) 193 { 194 h = h * 129 + (*u8++) + LH_PRIME; 195 len--; 196 } 197 198 return h & CTHASH_MASK; 199 } 200 201 /* Create new type element. */ 202 CTypeID uc_ctype_new(CTState *cts, CType **ctp) 203 { 204 CTypeID id = cts->vtab.count; 205 CType *ct; 206 if (UC_UNLIKELY(id >= CTID_MAX)) 207 { 208 uc_vm_raise_exception(cts->vm, EXCEPTION_RUNTIME, 209 "FFI type table overflow"); 210 return 0; 211 } 212 213 uc_vector_grow(&cts->vtab); 214 *ctp = ct = &cts->vtab.entries[cts->vtab.count++]; 215 ct->info = 0; 216 ct->size = 0; 217 ct->sib = 0; 218 ct->next = 0; 219 ct->uv_name = NULL; 220 return id; 221 } 222 223 /* Intern a type element. */ 224 CTypeID uc_ctype_intern(CTState *cts, CTInfo info, CTSize size) 225 { 226 uint32_t h = ct_hashtype(info, size); 227 CTypeID id = cts->hash[h]; 228 uc_assertCTS(cts->L, "uninitialized cts->L"); 229 while (id) 230 { 231 CType *ct = ctype_get(cts, id); 232 if (ct->info == info && ct->size == size) 233 return id; 234 id = ct->next; 235 } 236 uc_vector_grow(&cts->vtab); 237 id = cts->vtab.count++; 238 cts->vtab.entries[id].info = info; 239 cts->vtab.entries[id].size = size; 240 cts->vtab.entries[id].sib = 0; 241 cts->vtab.entries[id].next = cts->hash[h]; 242 cts->vtab.entries[id].uv_name = NULL; 243 cts->hash[h] = (CTypeID1)id; 244 return id; 245 } 246 247 /* Add type element to hash table. */ 248 static void ctype_addtype(CTState *cts, CType *ct, CTypeID id) 249 { 250 uint32_t h = ct_hashtype(ct->info, ct->size); 251 ct->next = cts->hash[h]; 252 cts->hash[h] = (CTypeID1)id; 253 } 254 255 /* Add named element to hash table. */ 256 void uc_ctype_addname(CTState *cts, CType *ct, CTypeID id) 257 { 258 uint32_t h = ct_hashname(ct->uv_name); 259 ct->next = cts->hash[h]; 260 cts->hash[h] = (CTypeID1)id; 261 } 262 263 /* Get a C type by name, matching the type mask. */ 264 CTypeID uc_ctype_getname(CTState *cts, CType **ctp, uc_value_t *name, uint32_t tmask) 265 { 266 CTypeID id = cts->hash[ct_hashname(name)]; 267 while (id) 268 { 269 CType *ct = ctype_get(cts, id); 270 271 if (ucv_is_equal(ct->uv_name, name) && ((tmask >> ctype_type(ct->info)) & 1)) 272 { 273 *ctp = ct; 274 return id; 275 } 276 id = ct->next; 277 } 278 *ctp = &cts->vtab.entries[0]; /* Simplify caller logic. ctype_get() would assert. */ 279 return 0; 280 } 281 282 /* Get a struct/union/enum/function field by name. */ 283 CType *uc_ctype_getfieldq(CTState *cts, CType *ct, uc_value_t *name, CTSize *ofs, 284 CTInfo *qual) 285 { 286 while (ct->sib) 287 { 288 ct = ctype_get(cts, ct->sib); 289 if (ucv_is_equal(ct->uv_name, name)) 290 { 291 *ofs = ct->size; 292 return ct; 293 } 294 if (ctype_isxattrib(ct->info, CTA_SUBTYPE)) 295 { 296 CType *fct, *cct = ctype_child(cts, ct); 297 CTInfo q = 0; 298 while (ctype_isattrib(cct->info)) 299 { 300 if (ctype_attrib(cct->info) == CTA_QUAL) 301 q |= cct->size; 302 cct = ctype_child(cts, cct); 303 } 304 fct = uc_ctype_getfieldq(cts, cct, name, ofs, qual); 305 if (fct) 306 { 307 if (qual) 308 *qual |= q; 309 *ofs += ct->size; 310 return fct; 311 } 312 } 313 } 314 return NULL; /* Not found. */ 315 } 316 317 /* -- C type information -------------------------------------------------- */ 318 319 /* Follow references and get raw type for a C type ID. */ 320 CType *uc_ctype_rawref(CTState *cts, CTypeID id) 321 { 322 CType *ct = ctype_get(cts, id); 323 while (ctype_isattrib(ct->info) || ctype_isref(ct->info)) 324 ct = ctype_child(cts, ct); 325 return ct; 326 } 327 328 /* Get size for a C type ID. Does NOT support VLA/VLS. */ 329 CTSize uc_ctype_size(CTState *cts, CTypeID id) 330 { 331 CType *ct = ctype_raw(cts, id); 332 return ctype_hassize(ct->info) ? ct->size : CTSIZE_INVALID; 333 } 334 335 /* Get size for a variable-length C type. Does NOT support other C types. */ 336 CTSize uc_ctype_vlsize(CTState *cts, CType *ct, CTSize nelem) 337 { 338 uint64_t xsz = 0; 339 if (ctype_isstruct(ct->info)) 340 { 341 CTypeID arrid = 0, fid = ct->sib; 342 xsz = ct->size; /* Add the struct size. */ 343 while (fid) 344 { 345 CType *ctf = ctype_get(cts, fid); 346 if (ctype_type(ctf->info) == CT_FIELD) 347 arrid = ctype_cid(ctf->info); /* Remember last field of VLS. */ 348 fid = ctf->sib; 349 } 350 ct = ctype_raw(cts, arrid); 351 } 352 uc_assertCTS(ctype_isvlarray(ct->info), "VLA expected"); 353 ct = ctype_rawchild(cts, ct); /* Get array element. */ 354 uc_assertCTS(ctype_hassize(ct->info), "bad VLA without size"); 355 /* Calculate actual size of VLA and check for overflow. */ 356 xsz += (uint64_t)ct->size * nelem; 357 return xsz < 0x80000000u ? (CTSize)xsz : CTSIZE_INVALID; 358 } 359 360 /* Get type, qualifiers, size and alignment for a C type ID. */ 361 CTInfo uc_ctype_info(CTState *cts, CTypeID id, CTSize *szp) 362 { 363 CTInfo qual = 0; 364 CType *ct = ctype_get(cts, id); 365 for (;;) 366 { 367 CTInfo info = ct->info; 368 if (ctype_isenum(info)) 369 { 370 /* Follow child. Need to look at its attributes, too. */ 371 } 372 else if (ctype_isattrib(info)) 373 { 374 if (ctype_isxattrib(info, CTA_QUAL)) 375 qual |= ct->size; 376 else if (ctype_isxattrib(info, CTA_ALIGN) && !(qual & CTFP_ALIGNED)) 377 qual |= CTFP_ALIGNED + CTALIGN(ct->size); 378 } 379 else 380 { 381 if (!(qual & CTFP_ALIGNED)) 382 qual |= (info & CTF_ALIGN); 383 qual |= (info & ~(CTF_ALIGN | CTMASK_CID)); 384 uc_assertCTS(ctype_hassize(info) || ctype_isfunc(info), 385 "ctype without size"); 386 *szp = ctype_isfunc(info) ? CTSIZE_INVALID : ct->size; 387 break; 388 } 389 ct = ctype_get(cts, ctype_cid(info)); 390 } 391 return qual; 392 } 393 394 /* Ditto, but follow a reference. */ 395 CTInfo uc_ctype_info_raw(CTState *cts, CTypeID id, CTSize *szp) 396 { 397 CType *ct = ctype_get(cts, id); 398 if (ctype_isref(ct->info)) 399 id = ctype_cid(ct->info); 400 return uc_ctype_info(cts, id, szp); 401 } 402 403 /* -- C type representation ----------------------------------------------- */ 404 405 /* Fixed max. length of a C type representation. */ 406 #define CTREPR_MAX 512 407 408 typedef struct CTRepr 409 { 410 char *pb, *pe; 411 CTState *cts; 412 int needsp; 413 int ok; 414 char buf[CTREPR_MAX]; 415 } CTRepr; 416 417 /* Prepend string. */ 418 static void ctype_prepstr(CTRepr *ctr, const char *str, size_t len) 419 { 420 char *p = ctr->pb; 421 if (ctr->buf + len + 1 > p) 422 { 423 ctr->ok = 0; 424 return; 425 } 426 if (ctr->needsp) 427 *--p = ' '; 428 ctr->needsp = 1; 429 p -= len; 430 while (len-- > 0) 431 p[len] = str[len]; 432 ctr->pb = p; 433 } 434 435 #define ctype_preplit(ctr, str) ctype_prepstr((ctr), "" str, sizeof(str) - 1) 436 437 /* Prepend char. */ 438 static void ctype_prepc(CTRepr *ctr, int c) 439 { 440 if (ctr->buf >= ctr->pb) 441 { 442 ctr->ok = 0; 443 return; 444 } 445 *--ctr->pb = c; 446 } 447 448 /* Prepend number. */ 449 static void ctype_prepnum(CTRepr *ctr, uint32_t n) 450 { 451 char *p = ctr->pb; 452 if (ctr->buf + 10 + 1 > p) 453 { 454 ctr->ok = 0; 455 return; 456 } 457 do 458 { 459 *--p = (char)('' + n % 10); 460 } while (n /= 10); 461 ctr->pb = p; 462 ctr->needsp = 0; 463 } 464 465 /* Append char. */ 466 static void ctype_appc(CTRepr *ctr, int c) 467 { 468 if (ctr->pe >= ctr->buf + CTREPR_MAX) 469 { 470 ctr->ok = 0; 471 return; 472 } 473 *ctr->pe++ = c; 474 } 475 476 /* Append number. */ 477 static void ctype_appnum(CTRepr *ctr, uint32_t n) 478 { 479 char buf[10]; 480 char *p = buf + sizeof(buf); 481 char *q = ctr->pe; 482 if (q > ctr->buf + CTREPR_MAX - 10) 483 { 484 ctr->ok = 0; 485 return; 486 } 487 do 488 { 489 *--p = (char)('' + n % 10); 490 } while (n /= 10); 491 do 492 { 493 *q++ = *p++; 494 } while (p < buf + sizeof(buf)); 495 ctr->pe = q; 496 } 497 498 /* Prepend qualifiers. */ 499 static void ctype_prepqual(CTRepr *ctr, CTInfo info) 500 { 501 if ((info & CTF_VOLATILE)) 502 ctype_preplit(ctr, "volatile"); 503 if ((info & CTF_CONST)) 504 ctype_preplit(ctr, "const"); 505 } 506 507 /* Prepend named type. */ 508 static void ctype_preptype(CTRepr *ctr, CType *ct, CTInfo qual, const char *t) 509 { 510 if (ct->uv_name) 511 { 512 ctype_prepstr(ctr, ucv_string_get(ct->uv_name), ucv_string_length(ct->uv_name)); 513 } 514 else 515 { 516 if (ctr->needsp) 517 ctype_prepc(ctr, ' '); 518 ctype_prepnum(ctr, ctype_typeid(ctr->cts, ct)); 519 ctr->needsp = 1; 520 } 521 ctype_prepstr(ctr, t, strlen(t)); 522 ctype_prepqual(ctr, qual); 523 } 524 525 static void ctype_repr(CTRepr *ctr, CTypeID id) 526 { 527 CType *ct = ctype_get(ctr->cts, id); 528 CTInfo qual = 0; 529 int ptrto = 0; 530 for (;;) 531 { 532 CTInfo info = ct->info; 533 CTSize size = ct->size; 534 switch (ctype_type(info)) 535 { 536 case CT_NUM: 537 if ((info & CTF_BOOL)) 538 { 539 ctype_preplit(ctr, "bool"); 540 } 541 else if ((info & CTF_FP)) 542 { 543 if (size == sizeof(double)) 544 ctype_preplit(ctr, "double"); 545 else if (size == sizeof(float)) 546 ctype_preplit(ctr, "float"); 547 else 548 ctype_preplit(ctr, "long double"); 549 } 550 else if (size == 1) 551 { 552 if (!((info ^ CTF_UCHAR) & CTF_UNSIGNED)) 553 ctype_preplit(ctr, "char"); 554 else if (CTF_UCHAR) 555 ctype_preplit(ctr, "signed char"); 556 else 557 ctype_preplit(ctr, "unsigned char"); 558 } 559 else if (size < 8) 560 { 561 if (size == 4) 562 ctype_preplit(ctr, "int"); 563 else 564 ctype_preplit(ctr, "short"); 565 if ((info & CTF_UNSIGNED)) 566 ctype_preplit(ctr, "unsigned"); 567 } 568 else 569 { 570 ctype_preplit(ctr, "_t"); 571 ctype_prepnum(ctr, size * 8); 572 ctype_preplit(ctr, "int"); 573 if ((info & CTF_UNSIGNED)) 574 ctype_prepc(ctr, 'u'); 575 } 576 ctype_prepqual(ctr, (qual | info)); 577 return; 578 case CT_VOID: 579 ctype_preplit(ctr, "void"); 580 ctype_prepqual(ctr, (qual | info)); 581 return; 582 case CT_STRUCT: 583 ctype_preptype(ctr, ct, qual, (info & CTF_UNION) ? "union" : "struct"); 584 return; 585 case CT_ENUM: 586 if (id == CTID_CTYPEID) 587 { 588 ctype_preplit(ctr, "ctype"); 589 return; 590 } 591 ctype_preptype(ctr, ct, qual, "enum"); 592 return; 593 case CT_ATTRIB: 594 if (ctype_attrib(info) == CTA_QUAL) 595 qual |= size; 596 break; 597 case CT_PTR: 598 if ((info & CTF_REF)) 599 { 600 CType *ct_child = ctype_get(ctr->cts, ctype_cid(info)); 601 if (ctype_type(ct_child->info) != CT_PTR) 602 ctype_prepc(ctr, '&'); 603 } 604 else 605 { 606 ctype_prepqual(ctr, (qual | info)); 607 if (UC_64 && size == 4) 608 ctype_preplit(ctr, "__ptr32"); 609 ctype_prepc(ctr, '*'); 610 } 611 qual = 0; 612 ptrto = 1; 613 ctr->needsp = 1; 614 break; 615 case CT_ARRAY: 616 if (ctype_isrefarray(info)) 617 { 618 ctr->needsp = 1; 619 if (ptrto) 620 { 621 ptrto = 0; 622 ctype_prepc(ctr, '('); 623 ctype_appc(ctr, ')'); 624 } 625 ctype_appc(ctr, '['); 626 if (size != CTSIZE_INVALID) 627 { 628 CTSize csize = ctype_child(ctr->cts, ct)->size; 629 ctype_appnum(ctr, csize ? size / csize : 0); 630 } 631 else if ((info & CTF_VLA)) 632 { 633 ctype_appc(ctr, '?'); 634 } 635 ctype_appc(ctr, ']'); 636 } 637 else if ((info & CTF_COMPLEX)) 638 { 639 if (size == 2 * sizeof(float)) 640 ctype_preplit(ctr, "float"); 641 ctype_preplit(ctr, "complex"); 642 return; 643 } 644 else 645 { 646 ctype_preplit(ctr, ")))"); 647 ctype_prepnum(ctr, size); 648 ctype_preplit(ctr, "__attribute__((vector_size("); 649 } 650 break; 651 case CT_FUNC: 652 ctr->needsp = 1; 653 if (ptrto) 654 { 655 ptrto = 0; 656 ctype_prepc(ctr, '('); 657 ctype_appc(ctr, ')'); 658 } 659 ctype_appc(ctr, '('); 660 ctype_appc(ctr, ')'); 661 break; 662 default: 663 uc_assertG_(ctr->cts->g, 0, "bad ctype %08x", info); 664 break; 665 } 666 ct = ctype_get(ctr->cts, ctype_cid(info)); 667 } 668 } 669 670 /* Return a printable representation of a C type. */ 671 uc_value_t *uc_ctype_repr(uc_vm_t *vm, CTypeID id, uc_value_t *name) 672 { 673 CTRepr ctr; 674 ctr.pb = ctr.pe = &ctr.buf[CTREPR_MAX / 2]; 675 ctr.cts = ctype_cts(vm); 676 ctr.ok = 1; 677 ctr.needsp = 0; 678 if (name) 679 ctype_prepstr(&ctr, ucv_string_get(name), ucv_string_length(name)); 680 ctype_repr(&ctr, id); 681 if (UC_UNLIKELY(!ctr.ok)) 682 return ucv_string_new("?"); 683 return ucv_string_new_length(ctr.pb, ctr.pe - ctr.pb); 684 } 685 686 /* Convert int64_t/uint64_t to string with 'LL' or 'ULL' suffix. */ 687 uc_value_t *uc_ctype_repr_int64(uint64_t n, int isunsigned) 688 { 689 char buf[1 + 20 + 3]; 690 char *p = buf + sizeof(buf); 691 int sign = 0; 692 *--p = 'L'; 693 *--p = 'L'; 694 if (isunsigned) 695 { 696 *--p = 'U'; 697 } 698 else if ((int64_t)n < 0) 699 { 700 n = ~n + 1u; 701 sign = 1; 702 } 703 do 704 { 705 *--p = (char)('' + n % 10); 706 } while (n /= 10); 707 if (sign) 708 *--p = '-'; 709 return ucv_string_new_length(p, (size_t)(buf + sizeof(buf) - p)); 710 } 711 712 /* Convert complex to string with 'i' or 'I' suffix. */ 713 uc_value_t *uc_ctype_repr_complex(void *sp, CTSize size) 714 { 715 uc_stringbuf_t *sb = ucv_stringbuf_new(); 716 TValue re, im; 717 if (size == 2 * sizeof(double)) 718 { 719 re.n = *(double *)sp; 720 im.n = ((double *)sp)[1]; 721 } 722 else 723 { 724 re.n = (double)*(float *)sp; 725 im.n = (double)((float *)sp)[1]; 726 } 727 ucv_stringbuf_printf(sb, "%.14g", re.n); 728 if (!(im.u32.hi & 0x80000000u) || im.n != im.n) 729 ucv_stringbuf_append(sb, "+"); 730 ucv_stringbuf_printf(sb, "%.14g", im.n); 731 if (sb->buf[sb->bpos - 1] >= 'a') 732 ucv_stringbuf_append(sb, "I"); 733 else 734 ucv_stringbuf_append(sb, "i"); 735 return ucv_stringbuf_finish(sb); 736 } 737 738 /* -- C type state -------------------------------------------------------- */ 739 740 static void free_ctypes(void *ud) 741 { 742 CTState *cts = ud; 743 744 while (cts->vtab.count) 745 ucv_put(cts->vtab.entries[--cts->vtab.count].uv_name); 746 747 free(cts->vtab.entries); 748 free(cts->vcbid.entries); 749 free(cts); 750 } 751 752 /* Initialize C type table and state. */ 753 CTState *uc_ctype_init(uc_vm_t *vm) 754 { 755 CTState *cts = xalloc(sizeof(CTState)); 756 CType *ct; // = lj_mem_newvec(L, CTTYPETAB_MIN, CType); 757 const char *name = uc_ctype_typenames; 758 CTypeID id; 759 memset(cts, 0, sizeof(CTState)); 760 // cts->tab = ct; 761 // cts->sizetab = CTTYPETAB_MIN; 762 // cts->top = CTTYPEINFO_NUM; 763 //cts->L = NULL; 764 //cts->g = G(L); 765 cts->vm = vm; 766 767 for (id = 0; id < CTTYPEINFO_NUM; id++, ct++) 768 { 769 CTInfo info = uc_ctype_typeinfo[id]; 770 uc_vector_grow(&cts->vtab); 771 ct = &cts->vtab.entries[cts->vtab.count++]; 772 ct->size = (CTSize)((int32_t)(info << 16) >> 26); 773 ct->info = info & 0xffff03ffu; 774 ct->sib = 0; 775 if (ctype_type(info) == CT_KW || ctype_istypedef(info)) 776 { 777 size_t len = strlen(name); 778 uc_value_t *str = ucv_string_new_length(name, len); 779 ctype_setname(ct, str); 780 ucv_put(str); 781 name += len + 1; 782 uc_ctype_addname(cts, ct, id); 783 } 784 else 785 { 786 ct->uv_name = NULL; 787 ct->next = 0; 788 if (!ctype_isenum(info)) 789 ctype_addtype(cts, ct, id); 790 } 791 } 792 793 //setmref(G(L)->ctype_state, cts); 794 795 uc_resource_type_t *cts_res; 796 797 cts_res = ucv_resource_type_add(vm, "ffi.types", NULL, free_ctypes); 798 799 uc_vm_registry_set(vm, "ffi.types", ucv_resource_new(cts_res, cts)); 800 801 return cts; 802 } 803
This page was automatically generated by LXR 0.3.1. • OpenWrt