1 /* 2 * Copyright (C) 2021 Jo-Philipp Wich <jo@mein.io> 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include <stdlib.h> 18 #include <assert.h> 19 #include <errno.h> 20 #include <math.h> 21 #include <float.h> 22 23 24 #include "ucode/internal/types.h" 25 #include "ucode/internal/vm.h" /* ISA: I_* opcodes */ 26 #include "ucode/internal/program.h" 27 #include "ucode/internal/chunk.h" 28 #include "ucode/internal/json-c-compat.h" 29 30 static char *uc_default_search_path[] = { LIB_SEARCH_PATH }; 31 32 uc_parse_config_t uc_default_parse_config = { 33 .module_search_path = { 34 .count = ARRAY_SIZE(uc_default_search_path), 35 .entries = uc_default_search_path 36 } 37 }; 38 39 uc_type_t 40 ucv_type(uc_value_t *uv) 41 { 42 uc_type_t type = ((uintptr_t)uv & 3); 43 44 if (type == UC_NULL && uv != NULL) 45 type = uv->type; 46 47 return type; 48 } 49 50 const char * 51 ucv_typename(uc_value_t *uv) 52 { 53 switch (ucv_type(uv)) { 54 case UC_NULL: return "null"; 55 case UC_INTEGER: return "integer"; 56 case UC_BOOLEAN: return "boolean"; 57 case UC_STRING: return "string"; 58 case UC_DOUBLE: return "double"; 59 case UC_ARRAY: return "array"; 60 case UC_OBJECT: return "object"; 61 case UC_REGEXP: return "regexp"; 62 case UC_CFUNCTION: return "cfunction"; 63 case UC_CLOSURE: return "closure"; 64 case UC_UPVALUE: return "upvalue"; 65 case UC_RESOURCE: return "resource"; 66 case UC_PROGRAM: return "program"; 67 case UC_SOURCE: return "source"; 68 } 69 70 return "unknown"; 71 } 72 73 void 74 ucv_unref(uc_weakref_t *ref) 75 { 76 ref->prev->next = ref->next; 77 ref->next->prev = ref->prev; 78 } 79 80 static void 81 ucv_ref_tail(uc_weakref_t *head, uc_weakref_t *item) 82 { 83 item->next = head; 84 item->prev = head->prev; 85 head->prev->next = item; 86 head->prev = item; 87 } 88 89 void 90 ucv_ref(uc_weakref_t *head, uc_weakref_t *item) 91 { 92 item->next = head->next; 93 item->prev = head; 94 head->next->prev = item; 95 head->next = item; 96 } 97 98 static uc_value_t ** 99 ucv_resource_values(uc_resource_ext_t *res) 100 { 101 void *data; 102 103 if (!res->uvcount && !res->hasproto) 104 return NULL; 105 106 data = res + 1; 107 data += res->datasize * 8; 108 109 return data; 110 } 111 112 #if 0 113 static uc_weakref_t * 114 ucv_get_weakref(uc_value_t *uv) 115 { 116 switch (ucv_type(uv)) { 117 case UC_ARRAY: 118 return &ucv_as_array(uv)->ref; 119 120 case UC_OBJECT: 121 return &ucv_as_object(uv)->ref; 122 123 case UC_CLOSURE: 124 return &ucv_as_closure(uv)->ref; 125 126 default: 127 return NULL; 128 } 129 } 130 #endif 131 132 static void 133 ucv_put_value(uc_value_t *uv, bool retain) 134 { 135 if (uv == NULL || (uintptr_t)uv & 3) 136 return; 137 138 assert(uv->type == UC_NULL || uv->refcount > 0); 139 140 if (uv->refcount > 0) 141 uv->refcount--; 142 143 if (uv->refcount == 0) 144 ucv_free(uv, retain); 145 } 146 147 static void 148 ucv_gc_mark(uc_value_t *uv); 149 150 static void 151 ucv_gc_mark(uc_value_t *uv) 152 { 153 uc_function_t *function; 154 uc_closure_t *closure; 155 uc_upvalref_t *upval; 156 uc_object_t *object; 157 uc_array_t *array; 158 uc_resource_type_t *restype; 159 uc_program_t *program; 160 uc_value_t **values; 161 struct lh_entry *entry; 162 size_t i; 163 164 if (ucv_is_marked(uv)) 165 return; 166 167 switch (ucv_type(uv)) { 168 case UC_ARRAY: 169 array = ucv_as_array(uv); 170 171 if (array->ref.next) 172 ucv_set_mark(uv); 173 174 ucv_gc_mark(array->proto); 175 176 for (i = 0; i < array->count; i++) 177 ucv_gc_mark(array->entries[i]); 178 179 break; 180 181 case UC_OBJECT: 182 object = ucv_as_object(uv); 183 184 if (object->ref.next) 185 ucv_set_mark(uv); 186 187 ucv_gc_mark(object->proto); 188 189 lh_foreach(object->table, entry) 190 ucv_gc_mark((uc_value_t *)lh_entry_v(entry)); 191 192 break; 193 194 case UC_CLOSURE: 195 closure = ucv_as_closure(uv); 196 function = closure->function; 197 198 if (closure->ref.next) 199 ucv_set_mark(uv); 200 201 for (i = 0; i < function->nupvals; i++) 202 ucv_gc_mark(&closure->upvals[i]->header); 203 204 ucv_gc_mark(&function->program->header); 205 206 break; 207 208 case UC_UPVALUE: 209 upval = ucv_as_upvalue(uv); 210 ucv_gc_mark(upval->value); 211 break; 212 213 case UC_RESOURCE: 214 if (uv->ext_flag) { 215 uc_resource_ext_t *res = (uc_resource_ext_t *)uv; 216 217 if (res->ref.next) 218 ucv_set_mark(uv); 219 220 values = ucv_resource_values(res); 221 222 if (!values) 223 break; 224 225 for (i = 0; i < (size_t)res->uvcount + res->hasproto; i++) 226 ucv_gc_mark(values[i]); 227 } 228 229 restype = ucv_resource_type(uv); 230 if (restype) 231 ucv_gc_mark(restype->proto); 232 233 break; 234 235 case UC_PROGRAM: 236 program = ucv_as_program(uv); 237 238 for (i = 0; i < program->sources.count; i++) 239 ucv_gc_mark(&program->sources.entries[i]->header); 240 241 for (i = 0; i < program->exports.count; i++) 242 ucv_gc_mark(&program->exports.entries[i]->header); 243 244 break; 245 246 default: 247 break; 248 } 249 } 250 251 void 252 ucv_free(uc_value_t *uv, bool retain) 253 { 254 uc_function_t *function; 255 uc_closure_t *closure; 256 uc_program_t *program; 257 uc_upvalref_t *upval; 258 uc_source_t *source; 259 uc_regexp_t *regexp; 260 uc_object_t *object; 261 uc_array_t *array; 262 uc_weakref_t *ref; 263 size_t i; 264 265 if (uv == NULL || (uintptr_t)uv & 3) 266 return; 267 268 if (uv->mark) 269 return; 270 271 uv->mark = true; 272 273 ref = NULL; 274 275 switch (uv->type) { 276 case UC_ARRAY: 277 array = ucv_as_array(uv); 278 ref = &array->ref; 279 ucv_put_value(array->proto, retain); 280 281 for (i = 0; i < array->count; i++) 282 ucv_put_value(array->entries[i], retain); 283 284 uc_vector_clear(array); 285 break; 286 287 case UC_OBJECT: 288 object = ucv_as_object(uv); 289 ref = &object->ref; 290 ucv_put_value(object->proto, retain); 291 lh_table_free(object->table); 292 break; 293 294 case UC_REGEXP: 295 regexp = ucv_as_regexp(uv); 296 regfree(®exp->regexp); 297 break; 298 299 case UC_CLOSURE: 300 closure = ucv_as_closure(uv); 301 function = closure->function; 302 ref = &closure->ref; 303 304 for (i = 0; i < function->nupvals; i++) 305 if (closure->upvals[i]) 306 ucv_put_value(&closure->upvals[i]->header, retain); 307 308 ucv_put_value(&function->program->header, retain); 309 break; 310 311 case UC_RESOURCE: 312 if (uv->ext_flag) { 313 uc_resource_ext_t *res = (uc_resource_ext_t *)uv; 314 void *data = res + 1; 315 uc_value_t **values; 316 317 values = ucv_resource_values(res); 318 319 if (values) { 320 for (i = 0; i < (size_t)res->uvcount + res->hasproto; i++) 321 ucv_put_value(values[i], retain); 322 } 323 324 if (res->type && res->type->free) 325 res->type->free(data); 326 327 ref = &res->ref; 328 } 329 else { 330 uc_resource_t *res = ucv_as_resource(uv); 331 332 if (res->type && res->type->free) 333 res->type->free(res->data); 334 } 335 break; 336 337 case UC_UPVALUE: 338 upval = ucv_as_upvalue(uv); 339 ucv_put_value(upval->value, retain); 340 break; 341 342 case UC_PROGRAM: 343 program = ucv_as_program(uv); 344 345 uc_program_function_foreach_safe(program, func) 346 uc_program_function_free(func); 347 348 uc_vallist_free(&program->constants); 349 350 for (i = 0; i < program->sources.count; i++) 351 ucv_put_value(&program->sources.entries[i]->header, retain); 352 353 for (i = 0; i < program->exports.count; i++) 354 ucv_put_value(&program->exports.entries[i]->header, retain); 355 356 uc_vector_clear(&program->sources); 357 uc_vector_clear(&program->exports); 358 break; 359 360 case UC_SOURCE: 361 source = ucv_as_source(uv); 362 363 if (source->runpath != source->filename) 364 free(source->runpath); 365 366 for (i = 0; i < source->exports.count; i++) 367 ucv_put(source->exports.entries[i]); 368 369 uc_vector_clear(&source->lineinfo); 370 uc_vector_clear(&source->exports); 371 fclose(source->fp); 372 free(source->buffer); 373 break; 374 } 375 376 if (!ref || !retain || !ref->prev || !ref->next) { 377 if (ref && ref->prev && ref->next) 378 ucv_unref(ref); 379 380 free(uv); 381 } 382 else { 383 uv->type = UC_NULL; 384 } 385 } 386 387 void 388 ucv_put(uc_value_t *uv) 389 { 390 ucv_put_value(uv, false); 391 } 392 393 uc_value_t * 394 ucv_get(uc_value_t *uv) 395 { 396 if (uv == NULL || (uintptr_t)uv & 3) 397 return uv; 398 399 assert(uv->refcount < 0x03ffffff); 400 401 uv->refcount++; 402 403 return uv; 404 } 405 406 uc_value_t * 407 ucv_boolean_new(bool val) 408 { 409 uintptr_t pv = UC_BOOLEAN | (val << 2); 410 411 return (uc_value_t *)pv; 412 } 413 414 bool 415 ucv_boolean_get(uc_value_t *uv) 416 { 417 uintptr_t pv = (uintptr_t)uv; 418 419 if ((pv & 3) == UC_BOOLEAN) 420 return (pv >> 2) & 1; 421 422 return false; 423 } 424 425 426 uc_value_t * 427 ucv_string_new(const char *str) 428 { 429 return ucv_string_new_length(str, strlen(str)); 430 } 431 432 uc_value_t * 433 ucv_string_alloc(char **str, size_t length) 434 { 435 uc_string_t *ustr; 436 437 ustr = xalloc(sizeof(*ustr) + length + 1); 438 ustr->header.type = UC_STRING; 439 ustr->header.refcount = 1; 440 ustr->length = length; 441 *str = (char *)ustr->str; 442 443 return &ustr->header; 444 } 445 446 uc_value_t * 447 ucv_string_new_length(const char *str, size_t length) 448 { 449 uc_value_t *ustr; 450 char *buf; 451 452 if ((length + 1) < sizeof(void *)) { 453 uintptr_t pv = UC_STRING | (length << 2); 454 size_t i; 455 char *s; 456 457 #if __BYTE_ORDER == __LITTLE_ENDIAN 458 s = (char *)&pv + 1; 459 #else 460 s = (char *)&pv; 461 #endif 462 463 for (i = 0; i < length; i++) 464 s[i] = str[i]; 465 466 return (uc_value_t *)pv; 467 } 468 469 ustr = ucv_string_alloc(&buf, length); 470 memcpy(buf, str, length); 471 472 return ustr; 473 } 474 475 uc_stringbuf_t * 476 ucv_stringbuf_new(void) 477 { 478 uc_stringbuf_t *sb = xprintbuf_new(); 479 uc_string_t ustr = { 480 .header = { 481 .type = UC_STRING, 482 .refcount = 1 483 } 484 }; 485 486 printbuf_memappend_fast(sb, (char *)&ustr, (int)sizeof(ustr)); 487 488 return sb; 489 } 490 491 uc_value_t * 492 ucv_stringbuf_finish(uc_stringbuf_t *sb) 493 { 494 uc_string_t *ustr = (uc_string_t *)sb->buf; 495 496 ustr->length = printbuf_length(sb) - offsetof(uc_string_t, str); 497 498 free(sb); 499 500 return &ustr->header; 501 } 502 503 char * 504 _ucv_string_get(uc_value_t **uv) 505 { 506 uc_string_t *str; 507 508 switch ((uintptr_t)*uv & 3) { 509 case UC_STRING: 510 #if __BYTE_ORDER == __LITTLE_ENDIAN 511 return (char *)uv + 1; 512 #else 513 return (char *)uv; 514 #endif 515 516 case UC_NULL: 517 if (*uv != NULL && (*uv)->type == UC_STRING) { 518 str = (uc_string_t *)*uv; 519 520 return str->str; 521 } 522 } 523 524 return NULL; 525 } 526 527 size_t 528 ucv_string_length(uc_value_t *uv) 529 { 530 uc_string_t *str = ucv_as_string(uv); 531 uintptr_t pv = (uintptr_t)uv; 532 533 if ((pv & 3) == UC_STRING) 534 return (pv & 0xff) >> 2; 535 else if (uv != NULL && uv->type == UC_STRING) 536 return str->length; 537 538 return 0; 539 } 540 541 542 uc_value_t * 543 ucv_int64_new(int64_t n) 544 { 545 uint64_t uval = (n < 0) ? ((n > INT64_MIN) ? (~n + 1) : INT64_MAX) : n; 546 uint64_t max = (1ULL << ((sizeof(void *) * 8) - 3)) - 1; 547 uc_integer_t *integer; 548 uintptr_t pv; 549 550 if (uval <= max) { 551 pv = UC_INTEGER | ((n < 0) << 2) | (uval << 3); 552 553 return (uc_value_t *)pv; 554 } 555 556 integer = xalloc(sizeof(*integer)); 557 integer->header.type = UC_INTEGER; 558 integer->header.refcount = 1; 559 integer->header.ext_flag = 0; 560 integer->i.s64 = n; 561 562 return &integer->header; 563 } 564 565 uc_value_t * 566 ucv_uint64_new(uint64_t n) 567 { 568 uint64_t max = (1ULL << ((sizeof(void *) * 8) - 3)) - 1; 569 uc_integer_t *integer; 570 uintptr_t pv; 571 572 if (n <= max) { 573 pv = UC_INTEGER | (n << 3); 574 575 return (uc_value_t *)pv; 576 } 577 578 integer = xalloc(sizeof(*integer)); 579 integer->header.type = UC_INTEGER; 580 integer->header.refcount = 1; 581 integer->header.ext_flag = 1; 582 integer->i.u64 = n; 583 584 return &integer->header; 585 } 586 587 uint64_t 588 ucv_uint64_get(uc_value_t *uv) 589 { 590 uintptr_t pv = (uintptr_t)uv; 591 uc_integer_t *integer; 592 double d; 593 594 errno = 0; 595 596 if ((pv & 3) == UC_INTEGER) { 597 if (((pv >> 2) & 1) == 0) 598 return (uint64_t)(pv >> 3); 599 600 errno = ERANGE; 601 602 return 0; 603 } 604 605 switch (ucv_type(uv)) { 606 case UC_INTEGER: 607 integer = ucv_as_integer(uv); 608 609 if (integer->header.ext_flag) 610 return integer->i.u64; 611 612 if (integer->i.s64 >= 0) 613 return (uint64_t)integer->i.s64; 614 615 errno = ERANGE; 616 617 return 0; 618 619 case UC_DOUBLE: 620 d = ucv_double_get(uv); 621 622 if (d < 0.0) { 623 errno = ERANGE; 624 625 return 0; 626 } 627 628 if (d >= ldexp(1.0, 64)) { 629 errno = ERANGE; 630 631 return UINT64_MAX; 632 } 633 634 return (uint64_t)d; 635 636 default: 637 errno = EINVAL; 638 639 return 0; 640 } 641 } 642 643 int64_t 644 ucv_int64_get(uc_value_t *uv) 645 { 646 uintptr_t pv = (uintptr_t)uv; 647 uc_integer_t *integer; 648 double d; 649 650 errno = 0; 651 652 if ((pv & 3) == UC_INTEGER) { 653 if (((pv >> 2) & 1) == 0) 654 return (int64_t)(pv >> 3); 655 656 return -(int64_t)(pv >> 3); 657 } 658 659 switch (ucv_type(uv)) { 660 case UC_INTEGER: 661 integer = ucv_as_integer(uv); 662 663 if (integer->header.ext_flag && integer->i.u64 <= (uint64_t)INT64_MAX) 664 return (int64_t)integer->i.u64; 665 666 if (!integer->header.ext_flag) 667 return integer->i.s64; 668 669 errno = ERANGE; 670 671 return INT64_MAX; 672 673 case UC_DOUBLE: 674 d = ucv_double_get(uv); 675 676 if (d < ldexp(-1.0, 63)) { 677 errno = ERANGE; 678 679 return INT64_MIN; 680 } 681 682 if (d >= ldexp(1.0, 63)) { 683 errno = ERANGE; 684 685 return INT64_MAX; 686 } 687 688 return (int64_t)d; 689 690 default: 691 errno = EINVAL; 692 693 return 0; 694 } 695 } 696 697 698 uc_value_t * 699 ucv_double_new(double d) 700 { 701 uc_double_t *dbl; 702 703 dbl = xalloc(sizeof(*dbl)); 704 dbl->header.type = UC_DOUBLE; 705 dbl->header.refcount = 1; 706 dbl->dbl = d; 707 708 return &dbl->header; 709 } 710 711 double 712 ucv_double_get(uc_value_t *uv) 713 { 714 uint64_t max_int = (2ULL << (DBL_MANT_DIG - 1)); 715 uc_double_t *dbl; 716 uint64_t u; 717 int64_t n; 718 719 errno = 0; 720 721 switch (ucv_type(uv)) { 722 case UC_DOUBLE: 723 dbl = ucv_as_double(uv); 724 725 return dbl->dbl; 726 727 case UC_INTEGER: 728 n = ucv_int64_get(uv); 729 730 if (errno == ERANGE) { 731 u = ucv_uint64_get(uv); 732 733 /* signal precision loss for integral values >2^53 */ 734 if (u > max_int) 735 errno = ERANGE; 736 737 return (double)u; 738 } 739 740 /* signal precision loss for integral values <-2^53 or >2^53 */ 741 if (n < -(int64_t)max_int || n > (int64_t)max_int) 742 errno = ERANGE; 743 744 return (double)n; 745 746 default: 747 errno = EINVAL; 748 749 return NAN; 750 } 751 } 752 753 754 uc_value_t * 755 ucv_array_new(uc_vm_t *vm) 756 { 757 return ucv_array_new_length(vm, 0); 758 } 759 760 uc_value_t * 761 ucv_array_new_length(uc_vm_t *vm, size_t length) 762 { 763 uc_array_t *array; 764 765 array = xalloc(sizeof(*array)); 766 array->header.type = UC_ARRAY; 767 array->header.refcount = 1; 768 769 /* preallocate memory */ 770 if (length) 771 uc_vector_extend(array, length); 772 773 if (vm) { 774 ucv_ref(&vm->values, &array->ref); 775 vm->alloc_refs++; 776 } 777 778 return &array->header; 779 } 780 781 uc_value_t * 782 ucv_array_pop(uc_value_t *uv) 783 { 784 uc_array_t *array = ucv_as_array(uv); 785 uc_value_t *item; 786 787 if (ucv_type(uv) != UC_ARRAY || array->count == 0) 788 return NULL; 789 790 item = ucv_get(array->entries[array->count - 1]); 791 792 ucv_array_delete(uv, array->count - 1, 1); 793 794 return item; 795 } 796 797 uc_value_t * 798 ucv_array_push(uc_value_t *uv, uc_value_t *item) 799 { 800 uc_array_t *array = ucv_as_array(uv); 801 802 if (ucv_type(uv) != UC_ARRAY || uv->ext_flag) 803 return NULL; 804 805 ucv_array_set(uv, array->count, item); 806 807 return item; 808 } 809 810 uc_value_t * 811 ucv_array_shift(uc_value_t *uv) 812 { 813 uc_array_t *array = ucv_as_array(uv); 814 uc_value_t *item; 815 816 if (ucv_type(uv) != UC_ARRAY || array->count == 0) 817 return NULL; 818 819 item = ucv_get(array->entries[0]); 820 821 ucv_array_delete(uv, 0, 1); 822 823 return item; 824 } 825 826 uc_value_t * 827 ucv_array_unshift(uc_value_t *uv, uc_value_t *item) 828 { 829 uc_array_t *array = ucv_as_array(uv); 830 size_t i; 831 832 if (ucv_type(uv) != UC_ARRAY) 833 return NULL; 834 835 uc_vector_extend(array, 1); 836 837 for (i = ++array->count; i > 1; i--) 838 array->entries[i - 1] = array->entries[i - 2]; 839 840 array->entries[0] = item; 841 842 return item; 843 } 844 845 typedef struct { 846 int (*cmp)(uc_value_t *, uc_value_t *, void *); 847 void *ud; 848 } array_sort_ctx_t; 849 850 static uc_vector_sort_cb(ucv_array_sort_r_cb, uc_value_t *, array_sort_ctx_t *, { 851 return ctx->cmp(v1, v2, ctx->ud); 852 }); 853 854 void 855 ucv_array_sort_r(uc_value_t *uv, 856 int (*cmp)(uc_value_t *, uc_value_t *, void *), void *ud) 857 { 858 array_sort_ctx_t ctx = { .cmp = cmp, .ud = ud }; 859 uc_array_t *array = ucv_as_array(uv); 860 861 if (ucv_type(uv) != UC_ARRAY || array->count <= 1) 862 return; 863 864 uc_vector_sort(array, ucv_array_sort_r_cb, &ctx); 865 } 866 867 void 868 ucv_array_sort(uc_value_t *uv, int (*cmp)(const void *, const void *)) 869 { 870 uc_array_t *array = ucv_as_array(uv); 871 872 if (ucv_type(uv) != UC_ARRAY || array->count <= 1) 873 return; 874 875 qsort(array->entries, array->count, sizeof(array->entries[0]), cmp); 876 } 877 878 bool 879 ucv_array_delete(uc_value_t *uv, size_t offset, size_t count) 880 { 881 uc_array_t *array = ucv_as_array(uv); 882 size_t i; 883 884 if (ucv_type(uv) != UC_ARRAY || array->count == 0) 885 return false; 886 887 if (offset >= array->count) 888 return false; 889 890 if ((offset + count) < offset) 891 return false; 892 893 if ((offset + count) > array->count) 894 count = array->count - offset; 895 896 for (i = 0; i < count; i++) 897 ucv_put(array->entries[offset + i]); 898 899 memmove(&array->entries[offset], 900 &array->entries[offset + count], 901 (array->count - (offset + count)) * sizeof(array->entries[0])); 902 903 uc_vector_reduce(array, count); 904 array->count -= count; 905 906 return true; 907 } 908 909 bool 910 ucv_array_set(uc_value_t *uv, size_t index, uc_value_t *item) 911 { 912 uc_array_t *array = ucv_as_array(uv); 913 914 if (ucv_type(uv) != UC_ARRAY) 915 return false; 916 917 if (index >= array->count) { 918 uc_vector_extend(array, index + 1 - array->count); 919 array->count = index + 1; 920 } 921 else { 922 ucv_put(array->entries[index]); 923 } 924 925 array->entries[index] = item; 926 927 return true; 928 } 929 930 uc_value_t * 931 ucv_array_get(uc_value_t *uv, size_t index) 932 { 933 uc_array_t *array = ucv_as_array(uv); 934 935 if (ucv_type(uv) != UC_ARRAY) 936 return NULL; 937 938 if (index >= array->count) 939 return NULL; 940 941 return array->entries[index]; 942 } 943 size_t 944 ucv_array_length(uc_value_t *uv) 945 { 946 uc_array_t *array = ucv_as_array(uv); 947 948 if (ucv_type(uv) != UC_ARRAY) 949 return 0; 950 951 return array->count; 952 } 953 954 955 static void 956 ucv_free_object_entry(struct lh_entry *entry) 957 { 958 uc_list_foreach(item, &uc_thread_context_get()->object_iterators) { 959 uc_object_iterator_t *iter = (uc_object_iterator_t *)item; 960 961 if (iter->u.pos == entry) 962 iter->u.pos = entry->next; 963 } 964 965 free(lh_entry_k(entry)); 966 ucv_put(lh_entry_v(entry)); 967 } 968 969 uc_value_t * 970 ucv_object_new(uc_vm_t *vm) 971 { 972 struct lh_table *table; 973 uc_object_t *object; 974 975 table = lh_kchar_table_new(16, ucv_free_object_entry); 976 977 if (!table) { 978 fprintf(stderr, "Out of memory\n"); 979 abort(); 980 } 981 982 object = xalloc(sizeof(*object)); 983 object->header.type = UC_OBJECT; 984 object->header.refcount = 1; 985 object->table = table; 986 987 if (vm) { 988 ucv_ref(&vm->values, &object->ref); 989 vm->alloc_refs++; 990 } 991 992 return &object->header; 993 } 994 995 bool 996 ucv_object_add(uc_value_t *uv, const char *key, uc_value_t *val) 997 { 998 uc_object_t *object = ucv_as_object(uv); 999 struct lh_entry *existing_entry; 1000 uc_value_t *existing_value; 1001 unsigned long hash; 1002 void *k; 1003 1004 if (ucv_type(uv) != UC_OBJECT || uv->ext_flag) 1005 return false; 1006 1007 hash = lh_get_hash(object->table, (const void *)key); 1008 existing_entry = lh_table_lookup_entry_w_hash(object->table, (const void *)key, hash); 1009 1010 if (existing_entry == NULL) { 1011 bool rehash = (object->table->count >= object->table->size * LH_LOAD_FACTOR); 1012 1013 /* insert will rehash table, backup affected iterator states */ 1014 if (rehash) { 1015 uc_list_foreach(item, &uc_thread_context_get()->object_iterators) { 1016 uc_object_iterator_t *iter = (uc_object_iterator_t *)item; 1017 1018 if (iter->table != object->table) 1019 continue; 1020 1021 if (iter->u.pos == NULL) 1022 continue; 1023 1024 iter->u.kh.k = iter->u.pos->k; 1025 iter->u.kh.hash = lh_get_hash(iter->table, iter->u.kh.k); 1026 } 1027 } 1028 1029 k = xstrdup(key); 1030 1031 if (lh_table_insert_w_hash(object->table, k, val, hash, 0) != 0) { 1032 free(k); 1033 1034 return false; 1035 } 1036 1037 /* restore affected iterator state pointer after rehash */ 1038 if (rehash) { 1039 uc_list_foreach(item, &uc_thread_context_get()->object_iterators) { 1040 uc_object_iterator_t *iter = (uc_object_iterator_t *)item; 1041 1042 if (iter->table != object->table) 1043 continue; 1044 1045 if (iter->u.kh.k == NULL) 1046 continue; 1047 1048 iter->u.pos = lh_table_lookup_entry_w_hash(iter->table, 1049 iter->u.kh.k, 1050 iter->u.kh.hash); 1051 } 1052 } 1053 1054 return true; 1055 } 1056 1057 existing_value = (uc_value_t *)lh_entry_v(existing_entry); 1058 1059 if (existing_value) 1060 ucv_put(existing_value); 1061 1062 existing_entry->v = val; 1063 1064 return true; 1065 } 1066 1067 1068 typedef struct { 1069 int (*cmp)(const void *, const void *); 1070 int (*cmpr)(const char *, uc_value_t *, const char *, uc_value_t *, void *); 1071 void *ud; 1072 } object_sort_ctx_t; 1073 1074 static uc_vector_sort_cb(ucv_object_sort_cb, const void *, object_sort_ctx_t *, { 1075 (void)v1; 1076 (void)v2; 1077 1078 return ctx->cmp(k1, k2); 1079 }); 1080 1081 static uc_vector_sort_cb(ucv_object_sort_r_cb, const struct lh_entry *, object_sort_ctx_t *, { 1082 return ctx->cmpr( 1083 v1 ? lh_entry_k(v1) : NULL, v1 ? lh_entry_v(v1) : NULL, 1084 v2 ? lh_entry_k(v2) : NULL, v2 ? lh_entry_v(v2) : NULL, 1085 ctx->ud); 1086 }); 1087 1088 static void 1089 ucv_object_sort_common(uc_value_t *uv, object_sort_ctx_t *ctx) 1090 { 1091 uc_object_t *object = ucv_as_object(uv); 1092 struct lh_table *t; 1093 struct lh_entry *e; 1094 size_t i; 1095 1096 struct { 1097 struct lh_entry **entries; 1098 size_t count; 1099 } keys = { 0 }; 1100 1101 if (ucv_type(uv) != UC_OBJECT || lh_table_length(object->table) <= 1) 1102 return; 1103 1104 for (t = object->table, e = t->head; e; e = e->next) 1105 uc_vector_push(&keys, e); 1106 1107 if (!keys.entries) 1108 return; 1109 1110 uc_vector_sort(&keys, 1111 ctx->cmpr ? ucv_object_sort_r_cb : ucv_object_sort_cb, ctx); 1112 1113 for (i = 0; i < keys.count; i++) { 1114 e = keys.entries[i]; 1115 1116 if (i == 0) { 1117 t->head = t->tail = e; 1118 e->next = e->prev = NULL; 1119 } 1120 else { 1121 t->tail->next = e; 1122 e->prev = t->tail; 1123 e->next = NULL; 1124 t->tail = e; 1125 } 1126 } 1127 1128 uc_vector_clear(&keys); 1129 } 1130 1131 void 1132 ucv_object_sort_r(uc_value_t *uv, 1133 int (*cmp)(const char *, uc_value_t *, 1134 const char *, uc_value_t *, void *), 1135 void *ud) 1136 { 1137 object_sort_ctx_t ctx = { .cmp = NULL, .cmpr = cmp, .ud = ud }; 1138 1139 ucv_object_sort_common(uv, &ctx); 1140 } 1141 1142 void 1143 ucv_object_sort(uc_value_t *uv, int (*cmp)(const void *, const void *)) 1144 { 1145 object_sort_ctx_t ctx = { .cmp = cmp, .cmpr = NULL, .ud = NULL }; 1146 1147 ucv_object_sort_common(uv, &ctx); 1148 } 1149 1150 bool 1151 ucv_object_delete(uc_value_t *uv, const char *key) 1152 { 1153 uc_object_t *object = ucv_as_object(uv); 1154 1155 if (ucv_type(uv) != UC_OBJECT || uv->ext_flag) 1156 return false; 1157 1158 return (lh_table_delete(object->table, key) == 0); 1159 } 1160 1161 uc_value_t * 1162 ucv_object_get(uc_value_t *uv, const char *key, bool *found) 1163 { 1164 uc_object_t *object = ucv_as_object(uv); 1165 uc_value_t *val = NULL; 1166 bool rv; 1167 1168 if (found != NULL) 1169 *found = false; 1170 1171 if (ucv_type(uv) != UC_OBJECT) 1172 return NULL; 1173 1174 rv = lh_table_lookup_ex(object->table, (const void *)key, (void **)&val); 1175 1176 if (found != NULL) 1177 *found = rv; 1178 1179 return val; 1180 } 1181 1182 size_t 1183 ucv_object_length(uc_value_t *uv) 1184 { 1185 uc_object_t *object = ucv_as_object(uv); 1186 1187 if (ucv_type(uv) != UC_OBJECT) 1188 return 0; 1189 1190 return lh_table_length(object->table); 1191 } 1192 1193 1194 uc_value_t * 1195 ucv_cfunction_new(const char *name, uc_cfn_ptr_t fptr) 1196 { 1197 uc_cfunction_t *cfn; 1198 size_t namelen = 0; 1199 1200 if (name) 1201 namelen = strlen(name); 1202 1203 cfn = xalloc(sizeof(*cfn) + namelen + 1); 1204 cfn->header.type = UC_CFUNCTION; 1205 cfn->header.refcount = 1; 1206 1207 if (name) 1208 strcpy(cfn->name, name); 1209 1210 cfn->cfn = fptr; 1211 1212 return &cfn->header; 1213 } 1214 1215 1216 uc_value_t * 1217 ucv_closure_new(uc_vm_t *vm, uc_function_t *function, bool arrow_fn) 1218 { 1219 uc_closure_t *closure; 1220 1221 closure = xalloc(sizeof(*closure) + (sizeof(uc_upvalref_t *) * function->nupvals)); 1222 closure->header.type = UC_CLOSURE; 1223 closure->header.refcount = 1; 1224 closure->function = function; 1225 closure->is_arrow = arrow_fn; 1226 closure->upvals = function->nupvals ? (uc_upvalref_t **)((uintptr_t)closure + ALIGN(sizeof(*closure))) : NULL; 1227 1228 if (vm) { 1229 ucv_ref(&vm->values, &closure->ref); 1230 vm->alloc_refs++; 1231 } 1232 1233 uc_program_get(function->program); 1234 1235 return &closure->header; 1236 } 1237 1238 1239 uc_resource_type_t * 1240 ucv_resource_type_add(uc_vm_t *vm, const char *name, uc_value_t *proto, void (*freefn)(void *)) 1241 { 1242 uc_resource_type_t *type; 1243 1244 type = ucv_resource_type_lookup(vm, name); 1245 1246 if (type) { 1247 ucv_put(proto); 1248 1249 return type; 1250 } 1251 1252 type = xalloc(sizeof(*type)); 1253 type->name = name; 1254 type->proto = proto; 1255 type->free = freefn; 1256 1257 uc_vector_push(&vm->restypes, type); 1258 1259 return type; 1260 } 1261 1262 uc_resource_type_t * 1263 ucv_resource_type_lookup(uc_vm_t *vm, const char *name) 1264 { 1265 size_t i; 1266 1267 for (i = 0; i < vm->restypes.count; i++) 1268 if (!strcmp(vm->restypes.entries[i]->name, name)) 1269 return vm->restypes.entries[i]; 1270 1271 return NULL; 1272 } 1273 1274 1275 uc_value_t * 1276 ucv_resource_new(uc_resource_type_t *type, void *data) 1277 { 1278 uc_resource_t *res; 1279 1280 res = xalloc(sizeof(*res)); 1281 res->header.type = UC_RESOURCE; 1282 res->header.refcount = 1; 1283 res->type = type; 1284 res->data = data; 1285 1286 return &res->header; 1287 } 1288 1289 uc_value_t * 1290 ucv_resource_new_ex(uc_vm_t *vm, uc_resource_type_t *type, void **data, size_t uvcount, size_t datasize) 1291 { 1292 uc_resource_ext_t *res; 1293 size_t size; 1294 1295 assert(uvcount < (1 << 8)); 1296 assert(datasize < (8 << 20)); 1297 1298 size = sizeof(*res); 1299 size += datasize = (datasize + 7) & ~7; 1300 size += uvcount * sizeof(uc_value_t *); 1301 1302 res = xalloc(size); 1303 res->header.type = UC_RESOURCE; 1304 res->header.refcount = 1; 1305 res->header.ext_flag = 1; 1306 res->type = type; 1307 res->uvcount = uvcount; 1308 res->datasize = datasize / 8; 1309 res->hasproto = 0; 1310 if (data) 1311 *data = res + 1; 1312 1313 if (vm && uvcount) { 1314 ucv_ref_tail(&vm->values, &res->ref); 1315 vm->alloc_refs++; 1316 } 1317 1318 return &res->header; 1319 } 1320 1321 uc_value_t * 1322 ucv_resource_new_with_proto(uc_vm_t *vm, uc_resource_type_t *type, void **data, size_t uvcount, size_t datasize, uc_value_t *proto) 1323 { 1324 uc_resource_ext_t *res; 1325 size_t size; 1326 uc_value_t **values; 1327 1328 assert(uvcount < (1 << 8)); 1329 assert(datasize < (8 << 20)); 1330 1331 /* If no proto provided, fall back to type->proto (no instance proto slot) */ 1332 if (!proto) 1333 return ucv_resource_new_ex(vm, type, data, uvcount, datasize); 1334 1335 size = sizeof(*res); 1336 size += datasize = (datasize + 7) & ~7; 1337 size += (uvcount + 1) * sizeof(uc_value_t *); 1338 1339 res = xalloc(size); 1340 res->header.type = UC_RESOURCE; 1341 res->header.refcount = 1; 1342 res->header.ext_flag = 1; 1343 res->type = type; 1344 res->uvcount = uvcount; 1345 res->datasize = datasize / 8; 1346 res->hasproto = 1; 1347 1348 if (data) 1349 *data = res + 1; 1350 1351 if (vm && uvcount) { 1352 ucv_ref_tail(&vm->values, &res->ref); 1353 vm->alloc_refs++; 1354 } 1355 1356 /* Chain the given proto to type->proto so prototype lookup works correctly */ 1357 if (type) 1358 ucv_prototype_set(proto, ucv_get(type->proto)); 1359 1360 values = (uc_value_t **)((char *)(res + 1) + datasize); 1361 values[0] = proto; 1362 1363 return &res->header; 1364 } 1365 1366 static bool 1367 ucv_resource_check(uc_value_t *uv, const char *name) 1368 { 1369 uc_resource_type_t *restype; 1370 1371 if (ucv_type(uv) != UC_RESOURCE) 1372 return false; 1373 1374 if (!name) 1375 return true; 1376 1377 restype = ucv_resource_type(uv); 1378 1379 return restype && !strcmp(restype->name, name); 1380 } 1381 1382 void * 1383 ucv_resource_data(uc_value_t *uv, const char *name) 1384 { 1385 if (!ucv_resource_check(uv, name)) 1386 return NULL; 1387 1388 if (uv->ext_flag) { 1389 uc_resource_ext_t *res = (uc_resource_ext_t *)uv; 1390 void *data = res + 1; 1391 1392 return data; 1393 } 1394 else { 1395 uc_resource_t *res = ucv_as_resource(uv); 1396 1397 return res->data; 1398 } 1399 } 1400 1401 void ** 1402 ucv_resource_dataptr(uc_value_t *uv, const char *name) 1403 { 1404 uc_resource_t *res = ucv_as_resource(uv); 1405 1406 if (!ucv_resource_check(uv, name) || res->header.ext_flag) 1407 return NULL; 1408 1409 return &res->data; 1410 } 1411 1412 uc_value_t * 1413 ucv_resource_value_get(uc_value_t *uv, size_t idx) 1414 { 1415 uc_resource_ext_t *res = (uc_resource_ext_t *)uv; 1416 uc_value_t **uvdata = ucv_resource_values(res); 1417 1418 if (!uvdata) 1419 return NULL; 1420 1421 if (idx == UCV_RESOURCE_PROTO_IDX) { 1422 if (!res->hasproto) 1423 return NULL; 1424 1425 return uvdata[0]; 1426 } 1427 1428 if (idx >= res->uvcount) 1429 return NULL; 1430 1431 return uvdata[idx + res->hasproto]; 1432 } 1433 1434 bool 1435 ucv_resource_value_set(uc_value_t *uv, size_t idx, uc_value_t *val) 1436 { 1437 uc_resource_ext_t *res = (uc_resource_ext_t *)uv; 1438 uc_value_t **uvdata = ucv_resource_values(res); 1439 1440 if (!uvdata) 1441 return false; 1442 1443 if (idx == UCV_RESOURCE_PROTO_IDX) { 1444 if (!res->hasproto) 1445 return false; 1446 1447 ucv_put(uvdata[0]); 1448 uvdata[0] = val; 1449 1450 return true; 1451 } 1452 1453 if (idx >= res->uvcount) 1454 return false; 1455 1456 ucv_put(uvdata[idx + res->hasproto]); 1457 uvdata[idx + res->hasproto] = val; 1458 1459 return true; 1460 } 1461 1462 uc_value_t * 1463 ucv_regexp_new(const char *pattern, bool icase, bool newline, bool global, char **error) 1464 { 1465 int cflags = REG_EXTENDED, res; 1466 uc_regexp_t *re; 1467 size_t len; 1468 1469 re = xalloc(sizeof(*re) + strlen(pattern) + 1); 1470 re->header.type = UC_REGEXP; 1471 re->header.refcount = 1; 1472 re->icase = icase; 1473 re->global = global; 1474 re->newline = newline; 1475 strcpy(re->source, pattern); 1476 1477 if (icase) 1478 cflags |= REG_ICASE; 1479 1480 if (!newline) 1481 cflags |= REG_NEWLINE; 1482 1483 res = regcomp(&re->regexp, pattern, cflags); 1484 1485 if (res != 0) { 1486 if (error) { 1487 len = regerror(res, &re->regexp, NULL, 0); 1488 *error = xalloc(len); 1489 1490 regerror(res, &re->regexp, *error, len); 1491 } 1492 1493 free(re); 1494 1495 return NULL; 1496 } 1497 1498 return &re->header; 1499 } 1500 1501 1502 uc_value_t * 1503 ucv_upvalref_new(size_t slot) 1504 { 1505 uc_upvalref_t *up; 1506 1507 up = xalloc(sizeof(*up)); 1508 up->header.type = UC_UPVALUE; 1509 up->header.refcount = 1; 1510 up->slot = slot; 1511 1512 return &up->header; 1513 } 1514 1515 1516 uc_value_t * 1517 ucv_prototype_get(uc_value_t *uv) 1518 { 1519 uc_resource_type_t *restype; 1520 uc_object_t *object; 1521 uc_array_t *array; 1522 1523 switch (ucv_type(uv)) { 1524 case UC_ARRAY: 1525 array = ucv_as_array(uv); 1526 1527 return array->proto; 1528 1529 case UC_OBJECT: 1530 object = ucv_as_object(uv); 1531 1532 return object->proto; 1533 1534 case UC_RESOURCE: 1535 if (ucv_resource_hasproto(uv)) 1536 return ucv_resource_proto_get(uv); 1537 1538 restype = ucv_resource_type(uv); 1539 1540 return restype ? restype->proto : NULL; 1541 1542 default: 1543 return NULL; 1544 } 1545 } 1546 1547 bool 1548 ucv_prototype_set(uc_value_t *uv, uc_value_t *proto) 1549 { 1550 uc_object_t *object; 1551 uc_array_t *array; 1552 1553 if (ucv_type(proto) != UC_OBJECT) 1554 return false; 1555 1556 switch (ucv_type(uv)) { 1557 case UC_ARRAY: 1558 array = ucv_as_array(uv); 1559 ucv_put(array->proto); 1560 array->proto = proto; 1561 1562 return true; 1563 1564 case UC_OBJECT: 1565 object = ucv_as_object(uv); 1566 ucv_put(object->proto); 1567 object->proto = proto; 1568 1569 return true; 1570 1571 case UC_RESOURCE: 1572 if (uv->ext_flag) { 1573 uc_resource_ext_t *res = (uc_resource_ext_t *)uv; 1574 uc_value_t **values; 1575 1576 if (!res->hasproto) 1577 return false; 1578 1579 values = ucv_resource_values(res); 1580 1581 if (!values) 1582 return false; 1583 1584 values[0] = proto; 1585 1586 return true; 1587 } 1588 1589 return false; 1590 1591 default: 1592 return false; 1593 } 1594 } 1595 1596 uc_value_t * 1597 ucv_metamethod_lookup(uc_value_t *v, const char *name) 1598 { 1599 uc_value_t *m; 1600 1601 /* The walk starts at the prototype, not at the instance: an own property 1602 * with a dunder name is plain data, not a metamethod. Honoring own keys 1603 * would let ordinary property writes (mixin loops, external data, a 1604 * function stored under a dunder name) silently change how the value 1605 * behaves; metamethods are an explicit, prototype-level mechanism. */ 1606 for (v = ucv_prototype_get(v); v; v = ucv_prototype_get(v)) { 1607 m = ucv_object_get(v, name, NULL); 1608 1609 if (ucv_type(m) != UC_NULL) 1610 return m; 1611 } 1612 1613 return NULL; 1614 } 1615 1616 uc_value_t * 1617 ucv_property_get(uc_value_t *uv, const char *key) 1618 { 1619 uc_value_t *val; 1620 bool found; 1621 1622 for (; uv; uv = ucv_prototype_get(uv)) { 1623 val = ucv_object_get(uv, key, &found); 1624 1625 if (found) 1626 return val; 1627 } 1628 1629 return NULL; 1630 } 1631 1632 1633 uc_value_t * 1634 ucv_from_json(uc_vm_t *vm, json_object *jso) 1635 { 1636 //uc_array_t *arr; 1637 uc_value_t *uv, *item; 1638 int64_t n; 1639 size_t i; 1640 1641 switch (json_object_get_type(jso)) { 1642 case json_type_null: 1643 return NULL; 1644 1645 case json_type_boolean: 1646 return ucv_boolean_new(json_object_get_boolean(jso)); 1647 1648 case json_type_double: 1649 return ucv_double_new(json_object_get_double(jso)); 1650 1651 case json_type_int: 1652 n = json_object_get_int64(jso); 1653 1654 if (n == INT64_MAX) 1655 return ucv_uint64_new(json_object_get_uint64(jso)); 1656 1657 return ucv_int64_new(n); 1658 1659 case json_type_object: 1660 uv = ucv_object_new(vm); 1661 1662 json_object_object_foreach(jso, key, val) { 1663 item = ucv_from_json(vm, val); 1664 1665 if (!ucv_object_add(uv, key, item)) 1666 ucv_put(item); 1667 1668 #ifdef __clang_analyzer__ 1669 /* Clang static analyzer does not understand that the object retains 1670 * our item so pretend to free it here to suppress the false positive 1671 * memory leak warning. */ 1672 ucv_put(item); 1673 #endif 1674 } 1675 1676 return uv; 1677 1678 case json_type_array: 1679 /* XXX 1680 arr = (uc_array_t *)ucv_array_new_length(vm, json_object_array_length(jso)); 1681 1682 for (i = 0; i < arr->count; i++) 1683 arr->entries[i] = ucv_from_json(vm, json_object_array_get_idx(jso, i)); 1684 1685 return &arr->header; 1686 */ 1687 uv = ucv_array_new(vm); 1688 1689 for (i = 0; i < json_object_array_length(jso); i++) { 1690 item = ucv_from_json(vm, json_object_array_get_idx(jso, i)); 1691 1692 if (!ucv_array_push(uv, item)) 1693 ucv_put(item); 1694 1695 #ifdef __clang_analyzer__ 1696 /* Clang static analyzer does not understand that the array retains 1697 * our item so pretend to free it here to suppress the false positive 1698 * memory leak warning. */ 1699 ucv_put(item); 1700 #endif 1701 } 1702 1703 return uv; 1704 1705 case json_type_string: 1706 return ucv_string_new_length(json_object_get_string(jso), json_object_get_string_len(jso)); 1707 } 1708 1709 return NULL; 1710 } 1711 1712 json_object * 1713 ucv_to_json(uc_value_t *uv) 1714 { 1715 uc_regexp_t *regexp; 1716 uc_array_t *array; 1717 json_object *jso; 1718 size_t i; 1719 char *s; 1720 1721 switch (ucv_type(uv)) { 1722 case UC_BOOLEAN: 1723 return json_object_new_boolean(ucv_boolean_get(uv)); 1724 1725 case UC_INTEGER: 1726 if (ucv_is_u64(uv)) 1727 return json_object_new_uint64(ucv_uint64_get(uv)); 1728 1729 return json_object_new_int64(ucv_int64_get(uv)); 1730 1731 case UC_DOUBLE: 1732 return json_object_new_double(ucv_double_get(uv)); 1733 1734 case UC_STRING: 1735 return json_object_new_string_len(ucv_string_get(uv), ucv_string_length(uv)); 1736 1737 case UC_ARRAY: 1738 array = ucv_as_array(uv); 1739 jso = json_object_new_array_ext(array->count); 1740 1741 for (i = 0; i < array->count; i++) 1742 json_object_array_put_idx(jso, i, ucv_to_json(array->entries[i])); 1743 1744 return jso; 1745 1746 case UC_OBJECT: 1747 jso = json_object_new_object(); 1748 1749 ucv_object_foreach(uv, key, val) 1750 json_object_object_add(jso, key, ucv_to_json(val)); 1751 1752 return jso; 1753 1754 case UC_REGEXP: 1755 regexp = ucv_as_regexp(uv); 1756 i = asprintf(&s, "/%s/%s%s%s", 1757 regexp->source, 1758 regexp->global ? "g" : "", 1759 regexp->icase ? "i" : "", 1760 regexp->newline ? "s" : ""); 1761 1762 if (i <= 0) 1763 return NULL; 1764 1765 jso = json_object_new_string_len(s, i); 1766 1767 free(s); 1768 1769 return jso; 1770 1771 case UC_CLOSURE: 1772 case UC_CFUNCTION: 1773 case UC_RESOURCE: 1774 case UC_UPVALUE: 1775 case UC_PROGRAM: 1776 case UC_SOURCE: 1777 case UC_NULL: 1778 return NULL; 1779 } 1780 1781 return NULL; 1782 } 1783 1784 static void 1785 ucv_to_string_json_encoded(uc_stringbuf_t *pb, const char *s, size_t len, bool regexp) 1786 { 1787 size_t i; 1788 1789 if (!regexp) 1790 ucv_stringbuf_append(pb, "\""); 1791 1792 for (i = 0; s != NULL && i < len; i++, s++) { 1793 switch (*s) { 1794 case '"': 1795 ucv_stringbuf_append(pb, "\\\""); 1796 break; 1797 1798 case '\\': 1799 ucv_stringbuf_append(pb, "\\\\"); 1800 break; 1801 1802 case '\b': 1803 ucv_stringbuf_append(pb, "\\b"); 1804 break; 1805 1806 case '\f': 1807 ucv_stringbuf_append(pb, "\\f"); 1808 break; 1809 1810 case '\n': 1811 ucv_stringbuf_append(pb, "\\n"); 1812 break; 1813 1814 case '\r': 1815 ucv_stringbuf_append(pb, "\\r"); 1816 break; 1817 1818 case '\t': 1819 ucv_stringbuf_append(pb, "\\t"); 1820 break; 1821 1822 case '/': 1823 ucv_stringbuf_append(pb, "/"); 1824 break; 1825 1826 default: 1827 if ((unsigned char)*s < 0x20) 1828 ucv_stringbuf_printf(pb, "\\u%04x", (unsigned char)*s); 1829 else 1830 ucv_stringbuf_addstr(pb, s, 1); 1831 1832 break; 1833 } 1834 } 1835 1836 if (!regexp) 1837 ucv_stringbuf_append(pb, "\""); 1838 } 1839 1840 static bool 1841 ucv_call_tostring(uc_vm_t *vm, uc_stringbuf_t *pb, uc_value_t *uv, bool json) 1842 { 1843 uc_value_t *tostr; 1844 uc_value_t *str; 1845 size_t l; 1846 char *s; 1847 1848 /* Generalized from the old direct-prototype `tostring` lookup: the full 1849 * chain is walked, `__tostring__` wins over the legacy `tostring` alias, a 1850 * strict superset of the old behavior */ 1851 tostr = ucv_metamethod_lookup(uv, "__tostring__"); 1852 if (tostr == NULL) 1853 tostr = ucv_metamethod_lookup(uv, "tostring"); 1854 1855 if (!ucv_is_callable(tostr)) 1856 return false; 1857 1858 uc_vm_stack_push(vm, ucv_get(uv)); 1859 uc_vm_stack_push(vm, ucv_get(tostr)); 1860 1861 if (uc_vm_call(vm, true, 0) != EXCEPTION_NONE) 1862 return false; 1863 1864 str = uc_vm_stack_pop(vm); 1865 1866 if (ucv_type(str) == UC_STRING) { 1867 s = ucv_string_get(str); 1868 l = ucv_string_length(str); 1869 1870 if (json) 1871 ucv_to_string_json_encoded(pb, s, l, false); 1872 else if (s) 1873 ucv_stringbuf_addstr(pb, s, l); 1874 } 1875 else if (json) { 1876 ucv_stringbuf_append(pb, "\"\""); 1877 } 1878 1879 ucv_put(str); 1880 1881 return true; 1882 } 1883 1884 void 1885 _ucv_stringbuf_append(uc_stringbuf_t *pb, const char *str, size_t len) 1886 { 1887 printbuf_memappend_fast(pb, str, (int)len); 1888 } 1889 1890 static void 1891 ucv_to_stringbuf_add_padding(uc_stringbuf_t *pb, char pad_char, size_t pad_size) 1892 { 1893 if (pad_char != '\0' && pad_char != '\1') { 1894 ucv_stringbuf_append(pb, "\n"); 1895 printbuf_memset(pb, -1, pad_char, pad_size); 1896 } 1897 else { 1898 ucv_stringbuf_append(pb, " "); 1899 } 1900 } 1901 1902 static void 1903 ucv_to_stringbuf_add_double(uc_stringbuf_t *pb, double val, bool json) 1904 { 1905 int len = ucv_stringbuf_printf(pb, "%.14g", val); 1906 1907 if (!json) 1908 return; 1909 1910 for (char *p = pb->buf + pb->bpos - len; len > 0; len--, p++) 1911 if (*p == '.' || *p == 'e') 1912 return; 1913 1914 ucv_stringbuf_append(pb, ".0"); 1915 } 1916 1917 void 1918 ucv_to_stringbuf_formatted(uc_vm_t *vm, uc_stringbuf_t *pb, uc_value_t *uv, size_t depth, char pad_char, size_t pad_size) 1919 { 1920 bool json = (pad_char != '\0'); 1921 uc_resource_type_t *restype; 1922 uc_cfunction_t *cfunction; 1923 uc_function_t *function; 1924 uc_closure_t *closure; 1925 uc_regexp_t *regexp; 1926 uc_value_t *argname; 1927 uc_upvalref_t *ref; 1928 uc_array_t *array; 1929 size_t i, l; 1930 double d; 1931 char *s; 1932 1933 if (ucv_is_marked(uv)) { 1934 ucv_stringbuf_append(pb, "null"); 1935 1936 return; 1937 } 1938 1939 if (vm != NULL && ucv_call_tostring(vm, pb, uv, json)) 1940 return; 1941 1942 ucv_set_mark(uv); 1943 1944 switch (ucv_type(uv)) { 1945 case UC_NULL: 1946 ucv_stringbuf_append(pb, "null"); 1947 break; 1948 1949 case UC_BOOLEAN: 1950 if (ucv_boolean_get(uv)) 1951 ucv_stringbuf_append(pb, "true"); 1952 else 1953 ucv_stringbuf_append(pb, "false"); 1954 break; 1955 1956 case UC_INTEGER: 1957 if (ucv_is_u64(uv)) 1958 ucv_stringbuf_printf(pb, "%" PRIu64, ucv_uint64_get(uv)); 1959 else 1960 ucv_stringbuf_printf(pb, "%" PRId64, ucv_int64_get(uv)); 1961 break; 1962 1963 case UC_DOUBLE: 1964 d = ucv_double_get(uv); 1965 1966 if (json && isnan(d)) 1967 ucv_stringbuf_append(pb, "\"NaN\""); 1968 else if (json && d == INFINITY) 1969 ucv_stringbuf_append(pb, "1e309"); 1970 else if (json && d == -INFINITY) 1971 ucv_stringbuf_append(pb, "-1e309"); 1972 else if (isnan(d)) 1973 ucv_stringbuf_append(pb, "NaN"); 1974 else if (d == INFINITY) 1975 ucv_stringbuf_append(pb, "Infinity"); 1976 else if (d == -INFINITY) 1977 ucv_stringbuf_append(pb, "-Infinity"); 1978 else 1979 ucv_to_stringbuf_add_double(pb, d, json); 1980 1981 break; 1982 1983 case UC_STRING: 1984 s = ucv_string_get(uv); 1985 l = ucv_string_length(uv); 1986 1987 if (s) { 1988 if (json) 1989 ucv_to_string_json_encoded(pb, s, l, false); 1990 else 1991 ucv_stringbuf_addstr(pb, s, l); 1992 } 1993 1994 break; 1995 1996 case UC_ARRAY: 1997 array = ucv_as_array(uv); 1998 1999 ucv_stringbuf_append(pb, "["); 2000 2001 for (i = 0; i < array->count; i++) { 2002 if (i) 2003 ucv_stringbuf_append(pb, ","); 2004 2005 ucv_to_stringbuf_add_padding(pb, pad_char, (depth + 1) * pad_size); 2006 ucv_to_stringbuf_formatted(vm, pb, array->entries[i], depth + 1, pad_char ? pad_char : '\1', pad_size); 2007 } 2008 2009 ucv_to_stringbuf_add_padding(pb, pad_char, depth * pad_size); 2010 ucv_stringbuf_append(pb, "]"); 2011 break; 2012 2013 case UC_OBJECT: 2014 ucv_stringbuf_append(pb, "{"); 2015 2016 i = 0; 2017 ucv_object_foreach(uv, key, val) { 2018 if (i++) 2019 ucv_stringbuf_append(pb, ","); 2020 2021 ucv_to_stringbuf_add_padding(pb, pad_char, (depth + 1) * pad_size); 2022 ucv_to_string_json_encoded(pb, key, strlen(key), false); 2023 ucv_stringbuf_append(pb, ": "); 2024 ucv_to_stringbuf_formatted(vm, pb, val, depth + 1, pad_char ? pad_char : '\1', pad_size); 2025 } 2026 2027 ucv_to_stringbuf_add_padding(pb, pad_char, depth * pad_size); 2028 ucv_stringbuf_append(pb, "}"); 2029 break; 2030 2031 case UC_REGEXP: 2032 regexp = ucv_as_regexp(uv); 2033 2034 if (json) 2035 ucv_stringbuf_append(pb, "\""); 2036 2037 ucv_stringbuf_append(pb, "/"); 2038 ucv_to_string_json_encoded(pb, regexp->source, strlen(regexp->source), true); 2039 ucv_stringbuf_append(pb, "/"); 2040 2041 if (regexp->global) 2042 ucv_stringbuf_append(pb, "g"); 2043 2044 if (regexp->icase) 2045 ucv_stringbuf_append(pb, "i"); 2046 2047 if (regexp->newline) 2048 ucv_stringbuf_append(pb, "s"); 2049 2050 if (json) 2051 ucv_stringbuf_append(pb, "\""); 2052 2053 break; 2054 2055 case UC_CLOSURE: 2056 closure = ucv_as_closure(uv); 2057 function = closure->function; 2058 2059 if (json) 2060 ucv_stringbuf_append(pb, "\""); 2061 2062 if (!closure->is_arrow) { 2063 ucv_stringbuf_append(pb, "function"); 2064 2065 if (function->name[0]) { 2066 ucv_stringbuf_append(pb, " "); 2067 ucv_stringbuf_addstr(pb, function->name, strlen(function->name)); 2068 } 2069 } 2070 2071 ucv_stringbuf_append(pb, "("); 2072 2073 for (i = 1; i <= function->nargs; i++) { 2074 argname = uc_chunk_debug_get_variable(&function->chunk, i - 1, i, false); 2075 2076 if (i > 1) 2077 ucv_stringbuf_append(pb, ", "); 2078 2079 if (i == function->nargs && function->vararg) 2080 ucv_stringbuf_append(pb, "..."); 2081 2082 if (argname) { 2083 s = ucv_string_get(argname); 2084 l = ucv_string_length(argname); 2085 2086 if (s) 2087 ucv_stringbuf_addstr(pb, s, l); 2088 2089 ucv_put(argname); 2090 2091 continue; 2092 } 2093 2094 ucv_stringbuf_printf(pb, "[arg%zu]", i); 2095 } 2096 2097 ucv_stringbuf_printf(pb, ")%s { ... }%s", 2098 closure->is_arrow ? " =>" : "", 2099 json ? "\"" : ""); 2100 2101 break; 2102 2103 case UC_CFUNCTION: 2104 cfunction = ucv_as_cfunction(uv); 2105 2106 ucv_stringbuf_printf(pb, "%sfunction%s%s(...) { [native code] }%s", 2107 json ? "\"" : "", 2108 cfunction->name[0] ? " " : "", 2109 cfunction->name[0] ? cfunction->name : "", 2110 json ? "\"" : ""); 2111 2112 break; 2113 2114 case UC_RESOURCE: 2115 restype = ucv_resource_type(uv); 2116 2117 ucv_stringbuf_printf(pb, "%s<%s %p>%s", 2118 json ? "\"" : "", 2119 restype ? restype->name : "resource", 2120 ucv_resource_data(uv, NULL), 2121 json ? "\"" : ""); 2122 2123 break; 2124 2125 case UC_UPVALUE: 2126 ref = ucv_as_upvalue(uv); 2127 2128 if (ref->closed) 2129 ucv_to_stringbuf_formatted(vm, pb, ref->value, depth, pad_char, pad_size); 2130 else if (vm != NULL && ref->slot < vm->stack.count) 2131 ucv_to_stringbuf_formatted(vm, pb, vm->stack.entries[ref->slot], depth, pad_char, pad_size); 2132 else 2133 ucv_stringbuf_printf(pb, "%s<upvalref %p>%s", 2134 json ? "\"" : "", 2135 uv, 2136 json ? "\"" : ""); 2137 2138 break; 2139 2140 case UC_PROGRAM: 2141 ucv_stringbuf_printf(pb, "%s<program %p>%s", 2142 json ? "\"" : "", 2143 uv, 2144 json ? "\"" : ""); 2145 2146 break; 2147 2148 case UC_SOURCE: 2149 ucv_stringbuf_printf(pb, "%s<source %p>%s", 2150 json ? "\"" : "", 2151 uv, 2152 json ? "\"" : ""); 2153 } 2154 2155 ucv_clear_mark(uv); 2156 } 2157 2158 static char * 2159 ucv_to_string_any(uc_vm_t *vm, uc_value_t *uv, char pad_char, size_t pad_size) 2160 { 2161 uc_stringbuf_t *pb = xprintbuf_new(); 2162 char *rv; 2163 2164 ucv_to_stringbuf_formatted(vm, pb, uv, 0, pad_char, pad_size); 2165 2166 rv = pb->buf; 2167 2168 free(pb); 2169 2170 return rv; 2171 } 2172 2173 char * 2174 ucv_to_string(uc_vm_t *vm, uc_value_t *uv) 2175 { 2176 return ucv_to_string_any(vm, uv, '\0', 0); 2177 } 2178 2179 char * 2180 ucv_to_jsonstring_formatted(uc_vm_t *vm, uc_value_t *uv, char pad_char, size_t pad_size) 2181 { 2182 return ucv_to_string_any(vm, uv, pad_char ? pad_char : '\1', pad_size); 2183 } 2184 2185 2186 bool 2187 ucv_is_equal(uc_value_t *uv1, uc_value_t *uv2) 2188 { 2189 uc_type_t t1 = ucv_type(uv1); 2190 uc_type_t t2 = ucv_type(uv2); 2191 const char *s1, *s2; 2192 uint64_t u1, u2; 2193 int64_t n1, n2; 2194 bool b1, b2; 2195 2196 if (t1 != t2) 2197 return false; 2198 2199 if (t1 != UC_DOUBLE && uv1 == uv2) 2200 return true; 2201 2202 switch (t1) { 2203 case UC_NULL: 2204 return true; 2205 2206 case UC_BOOLEAN: 2207 return ucv_boolean_get(uv1) == ucv_boolean_get(uv2); 2208 2209 case UC_DOUBLE: 2210 return ucv_double_get(uv1) == ucv_double_get(uv2); 2211 2212 case UC_INTEGER: 2213 n1 = ucv_int64_get(uv1); 2214 b1 = (errno == 0); 2215 2216 n2 = ucv_int64_get(uv2); 2217 b2 = (errno == 0); 2218 2219 if (b1 && b2) 2220 return (n1 == n2); 2221 2222 u1 = ucv_uint64_get(uv1); 2223 b1 = (errno == 0); 2224 2225 u2 = ucv_uint64_get(uv2); 2226 b2 = (errno == 0); 2227 2228 if (b1 && b2) 2229 return (u1 == u2); 2230 2231 return false; 2232 2233 case UC_STRING: 2234 s1 = ucv_string_get(uv1); 2235 s2 = ucv_string_get(uv2); 2236 u1 = ucv_string_length(uv1); 2237 u2 = ucv_string_length(uv2); 2238 2239 if (s1 == NULL || s2 == NULL || u1 != u2) 2240 return false; 2241 2242 return (memcmp(s1, s2, u1) == 0); 2243 2244 case UC_ARRAY: 2245 u1 = ucv_array_length(uv1); 2246 u2 = ucv_array_length(uv2); 2247 2248 if (u1 != u2) 2249 return false; 2250 2251 for (u1 = 0; u1 < u2; u1++) 2252 if (!ucv_is_equal(ucv_array_get(uv1, u1), ucv_array_get(uv2, u1))) 2253 return false; 2254 2255 return true; 2256 2257 case UC_OBJECT: 2258 u1 = ucv_object_length(uv1); 2259 u2 = ucv_object_length(uv2); 2260 2261 if (u1 != u2) 2262 return false; 2263 2264 ucv_object_foreach(uv1, key, val) { 2265 if (!ucv_is_equal(val, ucv_object_get(uv2, key, NULL))) 2266 return false; 2267 } 2268 2269 ucv_object_foreach(uv2, key2, val2) { 2270 (void)val2; 2271 ucv_object_get(uv1, key2, &b1); 2272 2273 if (!b1) 2274 return false; 2275 } 2276 2277 return true; 2278 2279 default: 2280 return false; 2281 } 2282 } 2283 2284 bool 2285 ucv_is_truish(uc_value_t *val) 2286 { 2287 double d; 2288 2289 switch (ucv_type(val)) { 2290 case UC_INTEGER: 2291 if (ucv_is_u64(val)) 2292 return (ucv_uint64_get(val) != 0); 2293 2294 return (ucv_int64_get(val) != 0); 2295 2296 case UC_DOUBLE: 2297 d = ucv_double_get(val); 2298 2299 return (d != 0 && !isnan(d)); 2300 2301 case UC_BOOLEAN: 2302 return ucv_boolean_get(val); 2303 2304 case UC_STRING: 2305 return (ucv_string_length(val) > 0); 2306 2307 case UC_NULL: 2308 return false; 2309 2310 default: 2311 return true; 2312 } 2313 } 2314 2315 uc_value_t * 2316 ucv_to_number(uc_value_t *v) 2317 { 2318 switch (ucv_type(v)) { 2319 case UC_NULL: 2320 return ucv_uint64_new(0); 2321 2322 case UC_BOOLEAN: 2323 return ucv_uint64_new(ucv_boolean_get(v)); 2324 2325 case UC_INTEGER: 2326 return ucv_get(v); 2327 2328 case UC_DOUBLE: 2329 if (isnan(ucv_double_get(v))) 2330 return NULL; 2331 2332 return ucv_get(v); 2333 2334 case UC_STRING: 2335 return uc_number_parse(ucv_string_get(v), NULL); 2336 2337 default: 2338 return NULL; 2339 } 2340 } 2341 2342 bool 2343 ucv_compare(int how, uc_value_t *v1, uc_value_t *v2, int *deltap) 2344 { 2345 uc_type_t t1 = ucv_type(v1); 2346 uc_type_t t2 = ucv_type(v2); 2347 uc_value_t *nv1, *nv2; 2348 uint64_t u1, u2; 2349 int64_t n1, n2; 2350 double d1, d2; 2351 int delta; 2352 2353 /* at least one operand is null and we compare for equality or inequality ... */ 2354 if ((!v1 || !v2) && (how == I_EQ || how == I_NE)) { 2355 delta = (v1 != v2); 2356 } 2357 2358 /* ... otherwise if both operands are strings, compare bytewise ... */ 2359 else if (t1 == UC_STRING && t2 == UC_STRING) { 2360 u1 = ucv_string_length(v1); 2361 u2 = ucv_string_length(v2); 2362 2363 delta = memcmp(ucv_string_get(v1), ucv_string_get(v2), 2364 (u1 < u2) ? u1 : u2); 2365 2366 if (delta == 0 && u1 < u2) 2367 delta = -1; 2368 else if (delta == 0 && u1 > u2) 2369 delta = 1; 2370 } 2371 2372 /* handle non-string cases... */ 2373 else { 2374 /* ... both operands are of the same, non-scalar type... */ 2375 if (t1 == t2 && !ucv_is_scalar(v1)) { 2376 /* ... compare memory addrs */ 2377 if ((uintptr_t)v1 == (uintptr_t)v2) 2378 delta = 0; 2379 else if ((uintptr_t)v1 < (uintptr_t)v2) 2380 delta = -1; 2381 else 2382 delta = 1; 2383 } 2384 2385 /* ... operands are of different type or at least one is scalar... */ 2386 else { 2387 nv1 = ucv_to_number(v1); 2388 nv2 = ucv_to_number(v2); 2389 2390 /* ... at least one of them is NaN (not convertible)... */ 2391 if (!nv1 || !nv2) { 2392 ucv_put(nv1); 2393 ucv_put(nv2); 2394 2395 if (deltap) 2396 *deltap = 2; 2397 2398 /* ... all comparison results except `!=` involving NaN are false */ 2399 return (how == I_NE); 2400 } 2401 2402 /* ... either of them is a double, compare both as double */ 2403 if (ucv_type(nv1) == UC_DOUBLE || ucv_type(nv2) == UC_DOUBLE) { 2404 d1 = ucv_double_get(nv1); 2405 d2 = ucv_double_get(nv2); 2406 2407 if (d1 == d2) 2408 delta = 0; 2409 else if (d1 < d2) 2410 delta = -1; 2411 else 2412 delta = 1; 2413 } 2414 2415 /* ... both are integers... */ 2416 else { 2417 n1 = ucv_int64_get(nv1); 2418 2419 /* ... left operand is large positive... */ 2420 if (errno == ERANGE) { 2421 ucv_int64_get(nv2); 2422 2423 /* ... right operand is large positive too... */ 2424 if (errno == ERANGE) { 2425 /* ... compare both as unsigned */ 2426 u1 = ucv_uint64_get(nv1); 2427 u2 = ucv_uint64_get(nv2); 2428 2429 if (u1 == u2) 2430 delta = 0; 2431 else if (u1 < u2) 2432 delta = -1; 2433 else 2434 delta = 1; 2435 } 2436 2437 /* ... right operand is within int64_t range... */ 2438 else { 2439 /* ... left > right by definition */ 2440 delta = 1; 2441 } 2442 } 2443 2444 /* ... left operand is within int64_t range... */ 2445 else { 2446 n2 = ucv_int64_get(nv2); 2447 2448 /* ... right operand is large positive... */ 2449 if (errno == ERANGE) { 2450 /* ... left < right by definition */ 2451 delta = -1; 2452 } 2453 2454 /* ... right operand is within int64_t range... */ 2455 else { 2456 /* ... compare both as signed */ 2457 if (n1 == n2) 2458 delta = 0; 2459 else if (n1 < n2) 2460 delta = -1; 2461 else 2462 delta = 1; 2463 } 2464 } 2465 } 2466 2467 ucv_put(nv1); 2468 ucv_put(nv2); 2469 } 2470 } 2471 2472 if (deltap) 2473 *deltap = delta; 2474 2475 switch (how) { 2476 case I_LT: 2477 return (delta < 0); 2478 2479 case I_LE: 2480 return (delta <= 0); 2481 2482 case I_GT: 2483 return (delta > 0); 2484 2485 case I_GE: 2486 return (delta >= 0); 2487 2488 case I_EQ: 2489 return (delta == 0); 2490 2491 case I_NE: 2492 return (delta != 0); 2493 2494 default: 2495 return false; 2496 } 2497 } 2498 2499 2500 static char * 2501 ucv_key_to_string(uc_vm_t *vm, uc_value_t *val) 2502 { 2503 if (ucv_type(val) != UC_STRING) 2504 return ucv_to_string(vm, val); 2505 2506 return NULL; 2507 } 2508 2509 static int64_t 2510 ucv_key_to_index(uc_value_t *val) 2511 { 2512 const char *k; 2513 int64_t idx; 2514 double d; 2515 char *e; 2516 2517 /* only consider doubles with integer values as array keys */ 2518 if (ucv_type(val) == UC_DOUBLE) { 2519 d = ucv_double_get(val); 2520 2521 if (trunc(d) != d) 2522 return INT64_MIN; 2523 2524 return (int64_t)d; 2525 } 2526 else if (ucv_type(val) == UC_INTEGER) { 2527 return ucv_int64_get(val); 2528 } 2529 else if (ucv_type(val) == UC_STRING) { 2530 errno = 0; 2531 k = ucv_string_get(val); 2532 idx = strtoll(k, &e, 0); 2533 2534 if (errno != 0 || e == k || *e != 0) 2535 return INT64_MIN; 2536 2537 return idx; 2538 } 2539 2540 return INT64_MIN; 2541 } 2542 2543 /* 2544 * Raw key lookup: array index, resource type-proto, object prototype chain. 2545 * Sets *found and returns the located value (or NULL). Does NOT resolve 2546 * upvalue references and does NOT dispatch __get__ — those are layered on by 2547 * the aware ucv_key_get(). 2548 */ 2549 static uc_value_t * 2550 ucv_key_get_raw(uc_vm_t *vm, uc_value_t *scope, uc_value_t *key, bool *found) 2551 { 2552 uc_value_t *o, *v = NULL, *inst_proto; 2553 int64_t idx; 2554 char *k; 2555 2556 *found = false; 2557 2558 if (ucv_type(scope) == UC_ARRAY) { 2559 idx = ucv_key_to_index(key); 2560 2561 if (idx < 0 && idx > INT64_MIN && (uint64_t)llabs(idx) <= ucv_array_length(scope)) 2562 idx += ucv_array_length(scope); 2563 2564 if (idx >= 0 && (uint64_t)idx < ucv_array_length(scope)) { 2565 v = ucv_array_get(scope, idx); 2566 *found = true; 2567 } 2568 } 2569 2570 if (!*found) { 2571 k = ucv_key_to_string(vm, key); 2572 2573 /* Check resource type prototype first */ 2574 if (ucv_type(scope) == UC_RESOURCE) { 2575 uc_value_t *uv = scope; 2576 2577 if (uv->ext_flag) { 2578 uc_resource_ext_t *ext = (uc_resource_ext_t *)scope; 2579 2580 /* Check instance-specific proto first (set via 2581 * ucv_resource_new_prototyped); returns NULL for resources 2582 * without an instance proto. */ 2583 if ((inst_proto = ucv_resource_proto_get(scope)) != NULL) { 2584 v = ucv_object_get(inst_proto, k ? k : ucv_string_get(key), found); 2585 } 2586 2587 /* Then fall back to type prototype */ 2588 if (!*found && ext->type && ext->type->proto) { 2589 v = ucv_object_get(ext->type->proto, k ? k : ucv_string_get(key), found); 2590 } 2591 } else { 2592 uc_resource_t *res = ucv_as_resource(scope); 2593 if (res->type && res->type->proto) { 2594 v = ucv_object_get(res->type->proto, k ? k : ucv_string_get(key), found); 2595 } 2596 } 2597 } 2598 2599 /* Then check object prototype chain */ 2600 if (!*found) { 2601 for (o = scope; o; o = ucv_prototype_get(o)) { 2602 if (ucv_type(o) != UC_OBJECT) 2603 continue; 2604 2605 v = ucv_object_get(o, k ? k : ucv_string_get(key), found); 2606 2607 if (*found) 2608 break; 2609 } 2610 } 2611 2612 free(k); 2613 } 2614 2615 return v; 2616 } 2617 2618 /* Resolve an upvalue reference (if any) to its current value. */ 2619 static uc_value_t * 2620 ucv_key_resolve_upval(uc_vm_t *vm, uc_value_t *v) 2621 { 2622 uc_upvalref_t *ref; 2623 2624 #ifdef __clang_analyzer__ 2625 /* Clang static analyzer does not understand that ucv_type(NULL) can't 2626 * possibly yield UC_UPVALUE. Nudge it. */ 2627 if (v != NULL && ucv_type(v) == UC_UPVALUE) 2628 #else 2629 if (ucv_type(v) == UC_UPVALUE) 2630 #endif 2631 { 2632 ref = ucv_as_upvalue(v); 2633 2634 if (ref->closed) 2635 return ucv_get(ref->value); 2636 else if (vm) 2637 return ucv_get(vm->stack.entries[ref->slot]); 2638 else 2639 return NULL; 2640 } 2641 2642 return ucv_get(v); 2643 } 2644 2645 /* 2646 * Property accessors implementing `foo.bar`, `foo.bar = x` and 2647 * `delete foo.bar` for any kind of value. Own keys respectively numeric array 2648 * indices take precedence, metamethods - looked up in the prototype chain of 2649 * the accessed value, see ucv_metamethod_lookup() - serve as fallback: 2650 * 2651 * __get__(key) invoked when a raw lookup yields nothing; the result 2652 * of the read is its return value 2653 * __set__(key, val) invoked when writing a key an object does not have yet, 2654 * like Lua's __newindex; its return value is discarded 2655 * __delete__(key) invoked when deleting a key an object does not have 2656 * yet; a truthy result means "deleted" 2657 * 2658 * A metamethod which is an object (or array) rather than a function is not 2659 * invoked: the operation is re-dispatched on that value with the same key, 2660 * which gives the delegated value a chance to store or delete the key itself 2661 * or provide its own metamethod. Cycles are not a problem, each hop is a 2662 * fresh property access bound by the VM's recursion limit. 2663 * 2664 * Arrays keep their dense storage: keys which are valid indices never dispatch 2665 * a metamethod at all. Passing vm == NULL performs the raw operation only. 2666 */ 2667 2668 /* Invoke `meta` as method on `scope`, passing `key` and optionally `val` and 2669 * storing the result in `rvp`. Returns false if the metamethod raised, in 2670 * which case the exception is left pending for the interpreter loop to unwind. 2671 * 2672 * The operands are pushed on the VM stack to form the method call argument 2673 * list, but also to keep them reachable: a garbage collection may run at any 2674 * instruction of the invoked metamethod and its mark pass walks the VM stack, 2675 * not C locals. */ 2676 static bool 2677 ucv_meta_call(uc_vm_t *vm, uc_value_t *scope, uc_value_t *meta, 2678 uc_value_t *key, uc_value_t *val, uc_value_t **rvp) 2679 { 2680 size_t base = vm->stack.count, nargs = 1; 2681 2682 if (rvp) 2683 *rvp = NULL; 2684 2685 uc_vm_stack_push(vm, ucv_get(scope)); 2686 uc_vm_stack_push(vm, ucv_get(meta)); 2687 uc_vm_stack_push(vm, ucv_get(key)); 2688 2689 if (val != NULL) { 2690 uc_vm_stack_push(vm, ucv_get(val)); 2691 nargs = 2; 2692 } 2693 2694 if (uc_vm_call(vm, true, nargs) != EXCEPTION_NONE) { 2695 /* An exception raised within the metamethod unwinds its frame - and 2696 * with it the operands pushed above - while one raised before that 2697 * frame got established, out of recursion for instance, leaves them 2698 * behind; either way, drop back to the slots pushed here. */ 2699 while (vm->stack.count > base) 2700 ucv_put(uc_vm_stack_pop(vm)); 2701 2702 return false; 2703 } 2704 2705 *rvp = uc_vm_stack_pop(vm); 2706 2707 return true; 2708 } 2709 2710 /* Invoke the metamethod held in `meta` on `scope`, passing `key` and 2711 * optionally `val`, without storing its return value anywhere. Returns 2712 * false if the call raised, in which case the exception is left pending for 2713 * the interpreter loop to unwind. */ 2714 static bool 2715 ucv_meta_invoke(uc_vm_t *vm, uc_value_t *scope, uc_value_t *meta, 2716 uc_value_t *key, uc_value_t *val) 2717 { 2718 uc_value_t *rv; 2719 2720 if (!ucv_meta_call(vm, scope, meta, key, val, &rv)) 2721 return false; 2722 2723 ucv_put(rv); 2724 2725 return true; 2726 } 2727 2728 /* ucv_object_get(), ucv_object_add() and ucv_object_delete() taking a script 2729 * level key value instead of a C string. Like ucv_object_add(), the value to 2730 * store is consumed, also where the store fails - which it does for a frozen 2731 * object or a value which is not an object at all. */ 2732 static bool 2733 ucv_object_has_key(uc_vm_t *vm, uc_value_t *obj, uc_value_t *key) 2734 { 2735 char *s = ucv_key_to_string(vm, key); 2736 bool found = false; 2737 2738 ucv_object_get(obj, s ? s : ucv_string_get(key), &found); 2739 free(s); 2740 2741 return found; 2742 } 2743 2744 static bool 2745 ucv_object_put_key(uc_vm_t *vm, uc_value_t *obj, uc_value_t *key, uc_value_t *val) 2746 { 2747 char *s = ucv_key_to_string(vm, key); 2748 bool rv; 2749 2750 rv = ucv_object_add(obj, s ? s : ucv_string_get(key), val); 2751 free(s); 2752 2753 if (!rv) 2754 ucv_put(val); 2755 2756 return rv; 2757 } 2758 2759 static bool 2760 ucv_object_del_key(uc_vm_t *vm, uc_value_t *obj, uc_value_t *key) 2761 { 2762 char *s = ucv_key_to_string(vm, key); 2763 bool rv; 2764 2765 rv = ucv_object_delete(obj, s ? s : ucv_string_get(key)); 2766 free(s); 2767 2768 return rv; 2769 } 2770 2771 /* Store `val` at the array index denoted by `key`, extending the array as 2772 * needed. Returns false for keys which are no indices and for negative ones 2773 * which denote no element; like ucv_array_set(), the value to store is 2774 * consumed either way. */ 2775 static bool 2776 ucv_array_set_key(uc_value_t *arr, uc_value_t *key, uc_value_t *val) 2777 { 2778 int64_t idx = ucv_key_to_index(key); 2779 2780 if (idx != INT64_MIN) { 2781 if (idx < 0 && (uint64_t)llabs(idx) <= ucv_array_length(arr)) 2782 idx += ucv_array_length(arr); 2783 2784 if (idx >= 0 && ucv_array_set(arr, idx, val)) 2785 return true; 2786 } 2787 2788 ucv_put(val); 2789 2790 return false; 2791 } 2792 2793 uc_value_t * 2794 ucv_key_get(uc_vm_t *vm, uc_value_t *scope, uc_value_t *key) 2795 { 2796 uc_value_t *meta, *val; 2797 bool found; 2798 2799 if (!scope || !key) 2800 return NULL; 2801 2802 val = ucv_key_get_raw(vm, scope, key, &found); 2803 2804 if (found) 2805 return ucv_key_resolve_upval(vm, val); 2806 2807 /* a valid array index which is out of bounds reads as null, it does not 2808 * dispatch __get__ */ 2809 if (vm == NULL || (ucv_type(scope) == UC_ARRAY && ucv_key_to_index(key) != INT64_MIN)) 2810 return NULL; 2811 2812 meta = ucv_metamethod_lookup(scope, "__get__"); 2813 2814 /* a __get__ which is itself an object is a delegation target: look the key 2815 * up inside it instead, where it may exist, be virtual, or miss just as 2816 * on the original scope */ 2817 if (ucv_type(meta) == UC_OBJECT || ucv_type(meta) == UC_ARRAY) 2818 return ucv_key_get(vm, meta, key); 2819 2820 if (!ucv_is_callable(meta)) 2821 return NULL; 2822 2823 if (!ucv_meta_call(vm, scope, meta, key, NULL, &val)) 2824 return NULL; 2825 2826 return val; 2827 } 2828 2829 uc_value_t * 2830 ucv_key_set(uc_vm_t *vm, uc_value_t *scope, uc_value_t *key, uc_value_t *val) 2831 { 2832 uc_value_t *meta = NULL; 2833 int64_t idx; 2834 2835 /* only a null key is invalid, a null value stores null */ 2836 if (!scope || !key) 2837 return NULL; 2838 2839 switch (ucv_type(scope)) { 2840 case UC_ARRAY: 2841 idx = ucv_key_to_index(key); 2842 2843 if (idx != INT64_MIN) 2844 return ucv_array_set_key(scope, key, ucv_get(val)) ? ucv_get(val) : NULL; 2845 2846 /* a non-index key on an array has no own-key storage to fall back to: 2847 * without a __set__ metamethod the store is guaranteed to be dropped. 2848 * In strict mode that is a type error, consistent with setting a 2849 * property on any other non-object type; in non-strict mode it 2850 * remains a silent no-op. */ 2851 if (vm != NULL && uc_vm_is_strict(vm)) { 2852 meta = ucv_metamethod_lookup(scope, "__set__"); 2853 2854 if (!meta) { 2855 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 2856 "attempt to set property on %s value", 2857 ucv_typename(scope)); 2858 2859 return NULL; 2860 } 2861 } 2862 2863 break; 2864 2865 case UC_OBJECT: 2866 if (ucv_object_has_key(vm, scope, key)) 2867 return ucv_object_put_key(vm, scope, key, ucv_get(val)) ? ucv_get(val) : NULL; 2868 2869 break; 2870 2871 case UC_RESOURCE: 2872 break; 2873 2874 default: 2875 return NULL; 2876 } 2877 2878 /* meta may already be set from the strict array check above */ 2879 if (vm != NULL) { 2880 if (meta == NULL) 2881 meta = ucv_metamethod_lookup(scope, "__set__"); 2882 2883 /* a __set__ which is itself an object is a delegation target: store the 2884 * key inside it instead, mirroring an object __get__ */ 2885 if (ucv_type(meta) == UC_OBJECT || ucv_type(meta) == UC_ARRAY) 2886 return ucv_key_set(vm, meta, key, val); 2887 2888 if (ucv_is_callable(meta)) { 2889 if (!ucv_meta_invoke(vm, scope, meta, key, val)) 2890 return NULL; 2891 2892 /* an assignment evaluates to the assigned value, not to whatever 2893 * the metamethod returned */ 2894 return ucv_get(val); 2895 } 2896 } 2897 2898 /* without a __set__ in effect, the value ends up as own key */ 2899 return ucv_object_put_key(vm, scope, key, ucv_get(val)) ? ucv_get(val) : NULL; 2900 } 2901 2902 bool 2903 ucv_key_delete(uc_vm_t *vm, uc_value_t *scope, uc_value_t *key) 2904 { 2905 uc_value_t *meta, *rv; 2906 bool deleted; 2907 2908 if (!scope || !key) 2909 return false; 2910 2911 switch (ucv_type(scope)) { 2912 case UC_OBJECT: 2913 if (ucv_object_has_key(vm, scope, key)) 2914 return ucv_object_del_key(vm, scope, key); 2915 2916 break; 2917 2918 case UC_RESOURCE: 2919 break; 2920 2921 /* arrays consist of positional elements, they are not deletable */ 2922 default: 2923 return false; 2924 } 2925 2926 if (vm != NULL) { 2927 meta = ucv_metamethod_lookup(scope, "__delete__"); 2928 2929 /* a __delete__ which is itself an object is a delegation target: 2930 * delete the key inside it, mirroring an object __get__ */ 2931 if (ucv_type(meta) == UC_OBJECT || ucv_type(meta) == UC_ARRAY) 2932 return ucv_key_delete(vm, meta, key); 2933 2934 if (ucv_is_callable(meta)) { 2935 /* by convention, a truthy return value means "deleted" */ 2936 deleted = ucv_meta_call(vm, scope, meta, key, NULL, &rv) && ucv_is_truish(rv); 2937 ucv_put(rv); 2938 2939 return deleted; 2940 } 2941 } 2942 2943 return ucv_object_del_key(vm, scope, key); 2944 } 2945 2946 /* 2947 * Raw counterparts of the accessors above: what `foo.bar`, `foo.bar = x` and 2948 * `delete foo.bar` do in the absence of metamethods. These are the escape 2949 * hatch for a metamethod which needs to reach the storage below itself without 2950 * dispatching again, and are exposed to scripts as rawget(), rawset() and 2951 * rawdelete(). 2952 */ 2953 2954 uc_value_t * 2955 ucv_key_rawget(uc_vm_t *vm, uc_value_t *scope, uc_value_t *key) 2956 { 2957 uc_value_t *val; 2958 bool found; 2959 2960 if (!scope || !key) 2961 return NULL; 2962 2963 val = ucv_key_get_raw(vm, scope, key, &found); 2964 2965 return (found ? ucv_key_resolve_upval(vm, val) : NULL); 2966 } 2967 2968 uc_value_t * 2969 ucv_key_rawset(uc_vm_t *vm, uc_value_t *scope, uc_value_t *key, uc_value_t *val) 2970 { 2971 if (!scope || !key) 2972 return NULL; 2973 2974 switch (ucv_type(scope)) { 2975 case UC_ARRAY: 2976 return ucv_array_set_key(scope, key, ucv_get(val)) ? ucv_get(val) : NULL; 2977 2978 case UC_OBJECT: 2979 return ucv_object_put_key(vm, scope, key, ucv_get(val)) ? ucv_get(val) : NULL; 2980 2981 default: 2982 return NULL; 2983 } 2984 } 2985 2986 bool 2987 ucv_key_rawdelete(uc_vm_t *vm, uc_value_t *scope, uc_value_t *key) 2988 { 2989 if (!scope || !key) 2990 return false; 2991 2992 return ucv_object_del_key(vm, scope, key); 2993 } 2994 2995 static void 2996 ucv_gc_common(uc_vm_t *vm, bool final) 2997 { 2998 uc_weakref_t *ref, *tmp; 2999 uc_value_t *val; 3000 size_t i; 3001 3002 vm->alloc_refs = 0; 3003 3004 /* back out early if value list is uninitialized */ 3005 if (!vm->values.prev || !vm->values.next) 3006 return; 3007 3008 if (!final) { 3009 /* mark reachable objects */ 3010 ucv_gc_mark(vm->globals); 3011 ucv_gc_mark(vm->registry); 3012 ucv_gc_mark(vm->signal.handler); 3013 ucv_gc_mark(vm->exception.stacktrace); 3014 3015 for (i = 0; i < vm->callframes.count; i++) { 3016 ucv_gc_mark(vm->callframes.entries[i].ctx); 3017 3018 if (vm->callframes.entries[i].closure) 3019 ucv_gc_mark(&vm->callframes.entries[i].closure->header); 3020 3021 if (vm->callframes.entries[i].cfunction) 3022 ucv_gc_mark(&vm->callframes.entries[i].cfunction->header); 3023 } 3024 3025 for (i = 0; i < vm->stack.count; i++) 3026 ucv_gc_mark(vm->stack.entries[i]); 3027 3028 for (i = 0; i < vm->restypes.count; i++) 3029 ucv_gc_mark(vm->restypes.entries[i]->proto); 3030 3031 /* mark no-gc resources with embedded values */ 3032 for (ref = vm->values.prev; ref != &vm->values; ref = ref->prev) { 3033 val = (uc_value_t *)((uintptr_t)ref - offsetof(uc_array_t, ref)); 3034 if (ucv_type(val) != UC_RESOURCE) 3035 break; 3036 3037 if (ucv_resource_is_persistent(val)) 3038 ucv_gc_mark(val); 3039 } 3040 } 3041 3042 /* unref unreachable objects */ 3043 for (ref = vm->values.next; ref != &vm->values; ref = ref->next) { 3044 val = (uc_value_t *)((uintptr_t)ref - offsetof(uc_array_t, ref)); 3045 3046 if (ucv_is_marked(val)) 3047 ucv_clear_mark(val); 3048 else 3049 ucv_free(val, true); 3050 } 3051 3052 /* free destroyed objects */ 3053 for (ref = vm->values.next, tmp = ref->next; ref != &vm->values; ref = tmp, tmp = tmp->next) { 3054 val = (uc_value_t *)((uintptr_t)ref - offsetof(uc_array_t, ref)); 3055 3056 if (val->type == UC_NULL) { 3057 ucv_unref(ref); 3058 free(val); 3059 } 3060 } 3061 } 3062 3063 void 3064 ucv_gc(uc_vm_t *vm) 3065 { 3066 ucv_gc_common(vm, false); 3067 } 3068 3069 void 3070 ucv_freeall(uc_vm_t *vm) 3071 { 3072 ucv_gc_common(vm, true); 3073 } 3074 3075 void 3076 uc_search_path_init(uc_search_path_t *search_path) 3077 { 3078 size_t i; 3079 3080 for (i = 0; i < ARRAY_SIZE(uc_default_search_path); i++) 3081 uc_vector_push(search_path, xstrdup(uc_default_search_path[i])); 3082 } 3083 3084 3085 static __thread uc_thread_context_t *tls_ctx; 3086 3087 uc_thread_context_t * 3088 uc_thread_context_get(void) 3089 { 3090 if (tls_ctx == NULL) { 3091 tls_ctx = xalloc(sizeof(*tls_ctx)); 3092 tls_ctx->object_iterators.prev = &tls_ctx->object_iterators; 3093 tls_ctx->object_iterators.next = &tls_ctx->object_iterators; 3094 } 3095 3096 return tls_ctx; 3097 } 3098 3099 void 3100 uc_thread_context_free(void) 3101 { 3102 free(tls_ctx); 3103 tls_ctx = NULL; 3104 } 3105
This page was automatically generated by LXR 0.3.1. • OpenWrt