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 <stdarg.h> 18 #include <stdlib.h> 19 #include <assert.h> 20 #include <endian.h> 21 #include <errno.h> 22 #include <math.h> 23 #include <ctype.h> 24 #include <float.h> 25 26 #include "json-c-compat.h" 27 28 #include "ucode/types.h" 29 #include "ucode/util.h" 30 #include "ucode/vm.h" 31 #include "ucode/program.h" 32 33 static char *uc_default_search_path[] = { LIB_SEARCH_PATH }; 34 35 uc_parse_config_t uc_default_parse_config = { 36 .module_search_path = { 37 .count = ARRAY_SIZE(uc_default_search_path), 38 .entries = uc_default_search_path 39 } 40 }; 41 42 uc_type_t 43 ucv_type(uc_value_t *uv) 44 { 45 uc_type_t type = ((uintptr_t)uv & 3); 46 47 if (type == UC_NULL && uv != NULL) 48 type = uv->type; 49 50 return type; 51 } 52 53 const char * 54 ucv_typename(uc_value_t *uv) 55 { 56 switch (ucv_type(uv)) { 57 case UC_NULL: return "null"; 58 case UC_INTEGER: return "integer"; 59 case UC_BOOLEAN: return "boolean"; 60 case UC_STRING: return "string"; 61 case UC_DOUBLE: return "double"; 62 case UC_ARRAY: return "array"; 63 case UC_OBJECT: return "object"; 64 case UC_REGEXP: return "regexp"; 65 case UC_CFUNCTION: return "cfunction"; 66 case UC_CLOSURE: return "closure"; 67 case UC_UPVALUE: return "upvalue"; 68 case UC_RESOURCE: return "resource"; 69 case UC_PROGRAM: return "program"; 70 case UC_SOURCE: return "source"; 71 } 72 73 return "unknown"; 74 } 75 76 void 77 ucv_unref(uc_weakref_t *ref) 78 { 79 ref->prev->next = ref->next; 80 ref->next->prev = ref->prev; 81 } 82 83 void 84 ucv_ref(uc_weakref_t *head, uc_weakref_t *item) 85 { 86 item->next = head->next; 87 item->prev = head; 88 head->next->prev = item; 89 head->next = item; 90 } 91 92 #if 0 93 static uc_weakref_t * 94 ucv_get_weakref(uc_value_t *uv) 95 { 96 switch (ucv_type(uv)) { 97 case UC_ARRAY: 98 return &((uc_array_t *)uv)->ref; 99 100 case UC_OBJECT: 101 return &((uc_object_t *)uv)->ref; 102 103 case UC_CLOSURE: 104 return &((uc_closure_t *)uv)->ref; 105 106 default: 107 return NULL; 108 } 109 } 110 #endif 111 112 static void 113 ucv_put_value(uc_value_t *uv, bool retain) 114 { 115 if (uv == NULL || (uintptr_t)uv & 3) 116 return; 117 118 assert(uv->type == UC_NULL || uv->refcount > 0); 119 120 if (uv->refcount > 0) 121 uv->refcount--; 122 123 if (uv->refcount == 0) 124 ucv_free(uv, retain); 125 } 126 127 static void 128 ucv_gc_mark(uc_value_t *uv); 129 130 static void 131 ucv_gc_mark(uc_value_t *uv) 132 { 133 uc_function_t *function; 134 uc_closure_t *closure; 135 uc_upvalref_t *upval; 136 uc_object_t *object; 137 uc_array_t *array; 138 uc_resource_t *resource; 139 uc_program_t *program; 140 struct lh_entry *entry; 141 size_t i; 142 143 if (ucv_is_marked(uv)) 144 return; 145 146 switch (ucv_type(uv)) { 147 case UC_ARRAY: 148 array = (uc_array_t *)uv; 149 150 if (array->ref.next) 151 ucv_set_mark(uv); 152 153 ucv_gc_mark(array->proto); 154 155 for (i = 0; i < array->count; i++) 156 ucv_gc_mark(array->entries[i]); 157 158 break; 159 160 case UC_OBJECT: 161 object = (uc_object_t *)uv; 162 163 if (object->ref.next) 164 ucv_set_mark(uv); 165 166 ucv_gc_mark(object->proto); 167 168 lh_foreach(object->table, entry) 169 ucv_gc_mark((uc_value_t *)lh_entry_v(entry)); 170 171 break; 172 173 case UC_CLOSURE: 174 closure = (uc_closure_t *)uv; 175 function = closure->function; 176 177 if (closure->ref.next) 178 ucv_set_mark(uv); 179 180 for (i = 0; i < function->nupvals; i++) 181 ucv_gc_mark(&closure->upvals[i]->header); 182 183 ucv_gc_mark(&function->program->header); 184 185 break; 186 187 case UC_UPVALUE: 188 upval = (uc_upvalref_t *)uv; 189 ucv_gc_mark(upval->value); 190 break; 191 192 case UC_RESOURCE: 193 resource = (uc_resource_t *)uv; 194 195 if (resource->type) 196 ucv_gc_mark(resource->type->proto); 197 198 break; 199 200 case UC_PROGRAM: 201 program = (uc_program_t *)uv; 202 203 for (i = 0; i < program->sources.count; i++) 204 ucv_gc_mark(&program->sources.entries[i]->header); 205 206 for (i = 0; i < program->exports.count; i++) 207 ucv_gc_mark(&program->exports.entries[i]->header); 208 209 break; 210 211 default: 212 break; 213 } 214 } 215 216 void 217 ucv_free(uc_value_t *uv, bool retain) 218 { 219 uc_resource_type_t *restype; 220 uc_resource_t *resource; 221 uc_function_t *function; 222 uc_closure_t *closure; 223 uc_program_t *program; 224 uc_upvalref_t *upval; 225 uc_source_t *source; 226 uc_regexp_t *regexp; 227 uc_object_t *object; 228 uc_array_t *array; 229 uc_weakref_t *ref; 230 size_t i; 231 232 if (uv == NULL || (uintptr_t)uv & 3) 233 return; 234 235 if (uv->mark) 236 return; 237 238 uv->mark = true; 239 240 ref = NULL; 241 242 switch (uv->type) { 243 case UC_ARRAY: 244 array = (uc_array_t *)uv; 245 ref = &array->ref; 246 ucv_put_value(array->proto, retain); 247 248 for (i = 0; i < array->count; i++) 249 ucv_put_value(array->entries[i], retain); 250 251 uc_vector_clear(array); 252 break; 253 254 case UC_OBJECT: 255 object = (uc_object_t *)uv; 256 ref = &object->ref; 257 ucv_put_value(object->proto, retain); 258 lh_table_free(object->table); 259 break; 260 261 case UC_REGEXP: 262 regexp = (uc_regexp_t *)uv; 263 regfree(®exp->regexp); 264 break; 265 266 case UC_CLOSURE: 267 closure = (uc_closure_t *)uv; 268 function = closure->function; 269 ref = &closure->ref; 270 271 for (i = 0; i < function->nupvals; i++) 272 if (closure->upvals[i]) 273 ucv_put_value(&closure->upvals[i]->header, retain); 274 275 ucv_put_value(&function->program->header, retain); 276 break; 277 278 case UC_RESOURCE: 279 resource = (uc_resource_t *)uv; 280 restype = resource->type; 281 282 if (restype && restype->free) 283 restype->free(resource->data); 284 285 break; 286 287 case UC_UPVALUE: 288 upval = (uc_upvalref_t *)uv; 289 ucv_put_value(upval->value, retain); 290 break; 291 292 case UC_PROGRAM: 293 program = (uc_program_t *)uv; 294 295 uc_program_function_foreach_safe(program, func) 296 uc_program_function_free(func); 297 298 uc_vallist_free(&program->constants); 299 300 for (i = 0; i < program->sources.count; i++) 301 ucv_put_value(&program->sources.entries[i]->header, retain); 302 303 for (i = 0; i < program->exports.count; i++) 304 ucv_put_value(&program->exports.entries[i]->header, retain); 305 306 uc_vector_clear(&program->sources); 307 uc_vector_clear(&program->exports); 308 break; 309 310 case UC_SOURCE: 311 source = (uc_source_t *)uv; 312 313 if (source->runpath != source->filename) 314 free(source->runpath); 315 316 for (i = 0; i < source->exports.count; i++) 317 ucv_put(source->exports.entries[i]); 318 319 uc_vector_clear(&source->lineinfo); 320 uc_vector_clear(&source->exports); 321 fclose(source->fp); 322 free(source->buffer); 323 break; 324 } 325 326 if (!ref || !retain) { 327 if (ref && ref->prev && ref->next) 328 ucv_unref(ref); 329 330 free(uv); 331 } 332 else { 333 uv->type = UC_NULL; 334 } 335 } 336 337 void 338 ucv_put(uc_value_t *uv) 339 { 340 ucv_put_value(uv, false); 341 } 342 343 uc_value_t * 344 ucv_get(uc_value_t *uv) 345 { 346 if (uv == NULL || (uintptr_t)uv & 3) 347 return uv; 348 349 assert(uv->refcount < 0x03ffffff); 350 351 uv->refcount++; 352 353 return uv; 354 } 355 356 uc_value_t * 357 ucv_boolean_new(bool val) 358 { 359 uintptr_t pv = UC_BOOLEAN | (val << 2); 360 361 return (uc_value_t *)pv; 362 } 363 364 bool 365 ucv_boolean_get(uc_value_t *uv) 366 { 367 uintptr_t pv = (uintptr_t)uv; 368 369 if ((pv & 3) == UC_BOOLEAN) 370 return (pv >> 2) & 1; 371 372 return false; 373 } 374 375 376 uc_value_t * 377 ucv_string_new(const char *str) 378 { 379 return ucv_string_new_length(str, strlen(str)); 380 } 381 382 uc_value_t * 383 ucv_string_new_length(const char *str, size_t length) 384 { 385 uc_string_t *ustr; 386 uintptr_t pv; 387 size_t i; 388 char *s; 389 390 if ((length + 1) < sizeof(void *)) { 391 pv = UC_STRING | (length << 2); 392 393 #if __BYTE_ORDER == __LITTLE_ENDIAN 394 s = (char *)&pv + 1; 395 #else 396 s = (char *)&pv; 397 #endif 398 399 for (i = 0; i < length; i++) 400 s[i] = str[i]; 401 402 return (uc_value_t *)pv; 403 } 404 405 ustr = xalloc(sizeof(*ustr) + length + 1); 406 ustr->header.type = UC_STRING; 407 ustr->header.refcount = 1; 408 ustr->length = length; 409 memcpy(ustr->str, str, length); 410 411 return &ustr->header; 412 } 413 414 uc_stringbuf_t * 415 ucv_stringbuf_new(void) 416 { 417 uc_stringbuf_t *sb = xprintbuf_new(); 418 uc_string_t ustr = { 419 .header = { 420 .type = UC_STRING, 421 .refcount = 1 422 } 423 }; 424 425 printbuf_memappend_fast(sb, (char *)&ustr, (int)sizeof(ustr)); 426 427 return sb; 428 } 429 430 uc_value_t * 431 ucv_stringbuf_finish(uc_stringbuf_t *sb) 432 { 433 uc_string_t *ustr = (uc_string_t *)sb->buf; 434 435 ustr->length = printbuf_length(sb) - offsetof(uc_string_t, str); 436 437 free(sb); 438 439 return &ustr->header; 440 } 441 442 char * 443 _ucv_string_get(uc_value_t **uv) 444 { 445 uc_string_t *str; 446 447 switch ((uintptr_t)*uv & 3) { 448 case UC_STRING: 449 #if __BYTE_ORDER == __LITTLE_ENDIAN 450 return (char *)uv + 1; 451 #else 452 return (char *)uv; 453 #endif 454 455 case UC_NULL: 456 if (*uv != NULL && (*uv)->type == UC_STRING) { 457 str = (uc_string_t *)*uv; 458 459 return str->str; 460 } 461 } 462 463 return NULL; 464 } 465 466 size_t 467 ucv_string_length(uc_value_t *uv) 468 { 469 uc_string_t *str = (uc_string_t *)uv; 470 uintptr_t pv = (uintptr_t)uv; 471 472 if ((pv & 3) == UC_STRING) 473 return (pv & 0xff) >> 2; 474 else if (uv != NULL && uv->type == UC_STRING) 475 return str->length; 476 477 return 0; 478 } 479 480 481 uc_value_t * 482 ucv_int64_new(int64_t n) 483 { 484 uint64_t uval = (n < 0) ? ((n > INT64_MIN) ? (~n + 1) : INT64_MAX) : n; 485 uint64_t max = (1ULL << ((sizeof(void *) * 8) - 3)) - 1; 486 uc_integer_t *integer; 487 uintptr_t pv; 488 489 if (uval <= max) { 490 pv = UC_INTEGER | ((n < 0) << 2) | (uval << 3); 491 492 return (uc_value_t *)pv; 493 } 494 495 integer = xalloc(sizeof(*integer)); 496 integer->header.type = UC_INTEGER; 497 integer->header.refcount = 1; 498 integer->header.u64_or_constant = 0; 499 integer->i.s64 = n; 500 501 return &integer->header; 502 } 503 504 uc_value_t * 505 ucv_uint64_new(uint64_t n) 506 { 507 uint64_t max = (1ULL << ((sizeof(void *) * 8) - 3)) - 1; 508 uc_integer_t *integer; 509 uintptr_t pv; 510 511 if (n <= max) { 512 pv = UC_INTEGER | (n << 3); 513 514 return (uc_value_t *)pv; 515 } 516 517 integer = xalloc(sizeof(*integer)); 518 integer->header.type = UC_INTEGER; 519 integer->header.refcount = 1; 520 integer->header.u64_or_constant = 1; 521 integer->i.u64 = n; 522 523 return &integer->header; 524 } 525 526 uint64_t 527 ucv_uint64_get(uc_value_t *uv) 528 { 529 uintptr_t pv = (uintptr_t)uv; 530 uc_integer_t *integer; 531 double d; 532 533 errno = 0; 534 535 if ((pv & 3) == UC_INTEGER) { 536 if (((pv >> 2) & 1) == 0) 537 return (uint64_t)(pv >> 3); 538 539 errno = ERANGE; 540 541 return 0; 542 } 543 544 switch (ucv_type(uv)) { 545 case UC_INTEGER: 546 integer = (uc_integer_t *)uv; 547 548 if (integer->header.u64_or_constant) 549 return integer->i.u64; 550 551 if (integer->i.s64 >= 0) 552 return (uint64_t)integer->i.s64; 553 554 errno = ERANGE; 555 556 return 0; 557 558 case UC_DOUBLE: 559 d = ucv_double_get(uv); 560 561 if (d < 0.0) { 562 errno = ERANGE; 563 564 return 0; 565 } 566 567 if (d >= ldexp(1.0, 64)) { 568 errno = ERANGE; 569 570 return UINT64_MAX; 571 } 572 573 return (uint64_t)d; 574 575 default: 576 errno = EINVAL; 577 578 return 0; 579 } 580 } 581 582 int64_t 583 ucv_int64_get(uc_value_t *uv) 584 { 585 uintptr_t pv = (uintptr_t)uv; 586 uc_integer_t *integer; 587 double d; 588 589 errno = 0; 590 591 if ((pv & 3) == UC_INTEGER) { 592 if (((pv >> 2) & 1) == 0) 593 return (int64_t)(pv >> 3); 594 595 return -(int64_t)(pv >> 3); 596 } 597 598 switch (ucv_type(uv)) { 599 case UC_INTEGER: 600 integer = (uc_integer_t *)uv; 601 602 if (integer->header.u64_or_constant && integer->i.u64 <= (uint64_t)INT64_MAX) 603 return (int64_t)integer->i.u64; 604 605 if (!integer->header.u64_or_constant) 606 return integer->i.s64; 607 608 errno = ERANGE; 609 610 return INT64_MAX; 611 612 case UC_DOUBLE: 613 d = ucv_double_get(uv); 614 615 if (d < ldexp(-1.0, 63)) { 616 errno = ERANGE; 617 618 return INT64_MIN; 619 } 620 621 if (d >= ldexp(1.0, 63)) { 622 errno = ERANGE; 623 624 return INT64_MAX; 625 } 626 627 return (int64_t)d; 628 629 default: 630 errno = EINVAL; 631 632 return 0; 633 } 634 } 635 636 637 uc_value_t * 638 ucv_double_new(double d) 639 { 640 uc_double_t *dbl; 641 642 dbl = xalloc(sizeof(*dbl)); 643 dbl->header.type = UC_DOUBLE; 644 dbl->header.refcount = 1; 645 dbl->dbl = d; 646 647 return &dbl->header; 648 } 649 650 double 651 ucv_double_get(uc_value_t *uv) 652 { 653 uint64_t max_int = (2ULL << (DBL_MANT_DIG - 1)); 654 uc_double_t *dbl; 655 uint64_t u; 656 int64_t n; 657 658 errno = 0; 659 660 switch (ucv_type(uv)) { 661 case UC_DOUBLE: 662 dbl = (uc_double_t *)uv; 663 664 return dbl->dbl; 665 666 case UC_INTEGER: 667 n = ucv_int64_get(uv); 668 669 if (errno == ERANGE) { 670 u = ucv_uint64_get(uv); 671 672 /* signal precision loss for integral values >2^53 */ 673 if (u > max_int) 674 errno = ERANGE; 675 676 return (double)u; 677 } 678 679 /* signal precision loss for integral values <-2^53 or >2^53 */ 680 if (n < -(int64_t)max_int || n > (int64_t)max_int) 681 errno = ERANGE; 682 683 return (double)n; 684 685 default: 686 errno = EINVAL; 687 688 return NAN; 689 } 690 } 691 692 693 uc_value_t * 694 ucv_array_new(uc_vm_t *vm) 695 { 696 return ucv_array_new_length(vm, 0); 697 } 698 699 uc_value_t * 700 ucv_array_new_length(uc_vm_t *vm, size_t length) 701 { 702 uc_array_t *array; 703 704 /* XXX */ 705 length = 0; 706 707 array = xalloc(sizeof(*array) + length * sizeof(array->entries[0])); 708 array->header.type = UC_ARRAY; 709 array->header.refcount = 1; 710 711 if (length > 0) 712 array->count = length; 713 714 uc_vector_grow(array); 715 716 if (vm) { 717 ucv_ref(&vm->values, &array->ref); 718 vm->alloc_refs++; 719 } 720 721 return &array->header; 722 } 723 724 uc_value_t * 725 ucv_array_pop(uc_value_t *uv) 726 { 727 uc_array_t *array = (uc_array_t *)uv; 728 uc_value_t *item; 729 730 if (ucv_type(uv) != UC_ARRAY || array->count == 0) 731 return NULL; 732 733 item = ucv_get(array->entries[array->count - 1]); 734 735 ucv_array_delete(uv, array->count - 1, 1); 736 737 return item; 738 } 739 740 uc_value_t * 741 ucv_array_push(uc_value_t *uv, uc_value_t *item) 742 { 743 uc_array_t *array = (uc_array_t *)uv; 744 745 if (ucv_type(uv) != UC_ARRAY || uv->u64_or_constant) 746 return NULL; 747 748 ucv_array_set(uv, array->count, item); 749 750 return item; 751 } 752 753 uc_value_t * 754 ucv_array_shift(uc_value_t *uv) 755 { 756 uc_array_t *array = (uc_array_t *)uv; 757 uc_value_t *item; 758 759 if (ucv_type(uv) != UC_ARRAY || array->count == 0) 760 return NULL; 761 762 item = ucv_get(array->entries[0]); 763 764 ucv_array_delete(uv, 0, 1); 765 766 return item; 767 } 768 769 uc_value_t * 770 ucv_array_unshift(uc_value_t *uv, uc_value_t *item) 771 { 772 uc_array_t *array = (uc_array_t *)uv; 773 size_t i; 774 775 if (ucv_type(uv) != UC_ARRAY) 776 return NULL; 777 778 array->count++; 779 uc_vector_grow(array); 780 781 for (i = array->count; i > 1; i--) 782 array->entries[i - 1] = array->entries[i - 2]; 783 784 array->entries[0] = item; 785 786 return item; 787 } 788 789 void 790 ucv_array_sort(uc_value_t *uv, int (*cmp)(const void *, const void *)) 791 { 792 uc_array_t *array = (uc_array_t *)uv; 793 794 if (ucv_type(uv) != UC_ARRAY || array->count <= 1) 795 return; 796 797 qsort(array->entries, array->count, sizeof(array->entries[0]), cmp); 798 } 799 800 bool 801 ucv_array_delete(uc_value_t *uv, size_t offset, size_t count) 802 { 803 uc_array_t *array = (uc_array_t *)uv; 804 size_t i; 805 806 if (ucv_type(uv) != UC_ARRAY || array->count == 0) 807 return false; 808 809 if (offset >= array->count) 810 return false; 811 812 if ((offset + count) < offset) 813 return false; 814 815 if ((offset + count) > array->count) 816 count = array->count - offset; 817 818 for (i = 0; i < count; i++) 819 ucv_put(array->entries[offset + i]); 820 821 memmove(&array->entries[offset], 822 &array->entries[offset + count], 823 (array->count - (offset + count)) * sizeof(array->entries[0])); 824 825 array->count -= count; 826 827 uc_vector_grow(array); 828 829 return true; 830 } 831 832 bool 833 ucv_array_set(uc_value_t *uv, size_t index, uc_value_t *item) 834 { 835 uc_array_t *array = (uc_array_t *)uv; 836 size_t old_count, new_count; 837 838 if (ucv_type(uv) != UC_ARRAY) 839 return false; 840 841 if (index >= array->count) { 842 old_count = array->count; 843 new_count = (index + 1) & ~(UC_VECTOR_CHUNK_SIZE - 1); 844 845 if (new_count > old_count) { 846 array->count = new_count; 847 uc_vector_grow(array); 848 } 849 850 array->count = index + 1; 851 852 while (old_count < array->count) 853 array->entries[old_count++] = NULL; 854 } 855 else { 856 ucv_put(array->entries[index]); 857 } 858 859 array->entries[index] = item; 860 861 return true; 862 } 863 864 uc_value_t * 865 ucv_array_get(uc_value_t *uv, size_t index) 866 { 867 uc_array_t *array = (uc_array_t *)uv; 868 869 if (ucv_type(uv) != UC_ARRAY) 870 return NULL; 871 872 if (index >= array->count) 873 return NULL; 874 875 return array->entries[index]; 876 } 877 size_t 878 ucv_array_length(uc_value_t *uv) 879 { 880 uc_array_t *array = (uc_array_t *)uv; 881 882 if (ucv_type(uv) != UC_ARRAY) 883 return 0; 884 885 return array->count; 886 } 887 888 889 static void 890 ucv_free_object_entry(struct lh_entry *entry) 891 { 892 free(lh_entry_k(entry)); 893 ucv_put(lh_entry_v(entry)); 894 } 895 896 uc_value_t * 897 ucv_object_new(uc_vm_t *vm) 898 { 899 struct lh_table *table; 900 uc_object_t *object; 901 902 table = lh_kchar_table_new(16, ucv_free_object_entry); 903 904 if (!table) { 905 fprintf(stderr, "Out of memory\n"); 906 abort(); 907 } 908 909 object = xalloc(sizeof(*object)); 910 object->header.type = UC_OBJECT; 911 object->header.refcount = 1; 912 object->table = table; 913 914 if (vm) { 915 ucv_ref(&vm->values, &object->ref); 916 vm->alloc_refs++; 917 } 918 919 return &object->header; 920 } 921 922 bool 923 ucv_object_add(uc_value_t *uv, const char *key, uc_value_t *val) 924 { 925 uc_object_t *object = (uc_object_t *)uv; 926 struct lh_entry *existing_entry; 927 uc_value_t *existing_value; 928 unsigned long hash; 929 void *k; 930 931 if (ucv_type(uv) != UC_OBJECT || uv->u64_or_constant) 932 return false; 933 934 hash = lh_get_hash(object->table, (const void *)key); 935 existing_entry = lh_table_lookup_entry_w_hash(object->table, (const void *)key, hash); 936 937 if (existing_entry == NULL) { 938 k = xstrdup(key); 939 940 if (lh_table_insert_w_hash(object->table, k, val, hash, 0) != 0) { 941 free(k); 942 943 return false; 944 } 945 946 return true; 947 } 948 949 existing_value = (uc_value_t *)lh_entry_v(existing_entry); 950 951 if (existing_value) 952 ucv_put(existing_value); 953 954 existing_entry->v = val; 955 956 return true; 957 } 958 959 bool 960 ucv_object_delete(uc_value_t *uv, const char *key) 961 { 962 uc_object_t *object = (uc_object_t *)uv; 963 964 if (ucv_type(uv) != UC_OBJECT || uv->u64_or_constant) 965 return false; 966 967 return (lh_table_delete(object->table, key) == 0); 968 } 969 970 uc_value_t * 971 ucv_object_get(uc_value_t *uv, const char *key, bool *found) 972 { 973 uc_object_t *object = (uc_object_t *)uv; 974 uc_value_t *val = NULL; 975 bool rv; 976 977 if (found != NULL) 978 *found = false; 979 980 if (ucv_type(uv) != UC_OBJECT) 981 return NULL; 982 983 rv = lh_table_lookup_ex(object->table, (const void *)key, (void **)&val); 984 985 if (found != NULL) 986 *found = rv; 987 988 return val; 989 } 990 991 size_t 992 ucv_object_length(uc_value_t *uv) 993 { 994 uc_object_t *object = (uc_object_t *)uv; 995 996 if (ucv_type(uv) != UC_OBJECT) 997 return 0; 998 999 return lh_table_length(object->table); 1000 } 1001 1002 1003 uc_value_t * 1004 ucv_cfunction_new(const char *name, uc_cfn_ptr_t fptr) 1005 { 1006 uc_cfunction_t *cfn; 1007 size_t namelen = 0; 1008 1009 if (name) 1010 namelen = strlen(name); 1011 1012 cfn = xalloc(sizeof(*cfn) + namelen + 1); 1013 cfn->header.type = UC_CFUNCTION; 1014 cfn->header.refcount = 1; 1015 1016 if (name) 1017 strcpy(cfn->name, name); 1018 1019 cfn->cfn = fptr; 1020 1021 return &cfn->header; 1022 } 1023 1024 1025 uc_value_t * 1026 ucv_closure_new(uc_vm_t *vm, uc_function_t *function, bool arrow_fn) 1027 { 1028 uc_closure_t *closure; 1029 1030 closure = xalloc(sizeof(*closure) + (sizeof(uc_upvalref_t *) * function->nupvals)); 1031 closure->header.type = UC_CLOSURE; 1032 closure->header.refcount = 1; 1033 closure->function = function; 1034 closure->is_arrow = arrow_fn; 1035 closure->upvals = function->nupvals ? (uc_upvalref_t **)((uintptr_t)closure + ALIGN(sizeof(*closure))) : NULL; 1036 1037 if (vm) { 1038 ucv_ref(&vm->values, &closure->ref); 1039 vm->alloc_refs++; 1040 } 1041 1042 uc_program_get(function->program); 1043 1044 return &closure->header; 1045 } 1046 1047 1048 uc_resource_type_t * 1049 ucv_resource_type_add(uc_vm_t *vm, const char *name, uc_value_t *proto, void (*freefn)(void *)) 1050 { 1051 uc_resource_type_t *type; 1052 1053 type = ucv_resource_type_lookup(vm, name); 1054 1055 if (type) { 1056 ucv_put(proto); 1057 1058 return type; 1059 } 1060 1061 type = xalloc(sizeof(*type)); 1062 type->name = name; 1063 type->proto = proto; 1064 type->free = freefn; 1065 1066 uc_vector_grow(&vm->restypes); 1067 vm->restypes.entries[vm->restypes.count++] = type; 1068 1069 return type; 1070 } 1071 1072 uc_resource_type_t * 1073 ucv_resource_type_lookup(uc_vm_t *vm, const char *name) 1074 { 1075 size_t i; 1076 1077 for (i = 0; i < vm->restypes.count; i++) 1078 if (!strcmp(vm->restypes.entries[i]->name, name)) 1079 return vm->restypes.entries[i]; 1080 1081 return NULL; 1082 } 1083 1084 1085 uc_value_t * 1086 ucv_resource_new(uc_resource_type_t *type, void *data) 1087 { 1088 uc_resource_t *res; 1089 1090 res = xalloc(sizeof(*res)); 1091 res->header.type = UC_RESOURCE; 1092 res->header.refcount = 1; 1093 res->type = type; 1094 res->data = data; 1095 1096 return &res->header; 1097 } 1098 1099 static uc_resource_t * 1100 ucv_resource_check(uc_value_t *uv, const char *name) 1101 { 1102 uc_resource_t *res = (uc_resource_t *)uv; 1103 1104 if (ucv_type(uv) != UC_RESOURCE) 1105 return NULL; 1106 1107 if (name) { 1108 if (!res->type || strcmp(res->type->name, name)) 1109 return NULL; 1110 } 1111 1112 return res; 1113 } 1114 1115 void * 1116 ucv_resource_data(uc_value_t *uv, const char *name) 1117 { 1118 uc_resource_t *res = ucv_resource_check(uv, name); 1119 1120 return res ? res->data : NULL; 1121 } 1122 1123 void ** 1124 ucv_resource_dataptr(uc_value_t *uv, const char *name) 1125 { 1126 uc_resource_t *res = ucv_resource_check(uv, name); 1127 1128 return res ? &res->data : NULL; 1129 } 1130 1131 1132 uc_value_t * 1133 ucv_regexp_new(const char *pattern, bool icase, bool newline, bool global, char **error) 1134 { 1135 int cflags = REG_EXTENDED, res; 1136 uc_regexp_t *re; 1137 size_t len; 1138 1139 re = xalloc(sizeof(*re) + strlen(pattern) + 1); 1140 re->header.type = UC_REGEXP; 1141 re->header.refcount = 1; 1142 re->icase = icase; 1143 re->global = global; 1144 re->newline = newline; 1145 strcpy(re->source, pattern); 1146 1147 if (icase) 1148 cflags |= REG_ICASE; 1149 1150 if (newline) 1151 cflags |= REG_NEWLINE; 1152 1153 res = regcomp(&re->regexp, pattern, cflags); 1154 1155 if (res != 0) { 1156 if (error) { 1157 len = regerror(res, &re->regexp, NULL, 0); 1158 *error = xalloc(len); 1159 1160 regerror(res, &re->regexp, *error, len); 1161 } 1162 1163 free(re); 1164 1165 return NULL; 1166 } 1167 1168 return &re->header; 1169 } 1170 1171 1172 uc_value_t * 1173 ucv_upvalref_new(size_t slot) 1174 { 1175 uc_upvalref_t *up; 1176 1177 up = xalloc(sizeof(*up)); 1178 up->header.type = UC_UPVALUE; 1179 up->header.refcount = 1; 1180 up->slot = slot; 1181 1182 return &up->header; 1183 } 1184 1185 1186 uc_value_t * 1187 ucv_prototype_get(uc_value_t *uv) 1188 { 1189 uc_resource_type_t *restype; 1190 uc_resource_t *resource; 1191 uc_object_t *object; 1192 uc_array_t *array; 1193 1194 switch (ucv_type(uv)) { 1195 case UC_ARRAY: 1196 array = (uc_array_t *)uv; 1197 1198 return array->proto; 1199 1200 case UC_OBJECT: 1201 object = (uc_object_t *)uv; 1202 1203 return object->proto; 1204 1205 case UC_RESOURCE: 1206 resource = (uc_resource_t *)uv; 1207 restype = resource->type; 1208 1209 return restype ? restype->proto : NULL; 1210 1211 default: 1212 return NULL; 1213 } 1214 } 1215 1216 bool 1217 ucv_prototype_set(uc_value_t *uv, uc_value_t *proto) 1218 { 1219 uc_object_t *object; 1220 uc_array_t *array; 1221 1222 if (ucv_type(proto) != UC_OBJECT) 1223 return false; 1224 1225 switch (ucv_type(uv)) { 1226 case UC_ARRAY: 1227 array = (uc_array_t *)uv; 1228 array->proto = proto; 1229 1230 return true; 1231 1232 case UC_OBJECT: 1233 object = (uc_object_t *)uv; 1234 object->proto = proto; 1235 1236 return true; 1237 1238 default: 1239 return false; 1240 } 1241 } 1242 1243 uc_value_t * 1244 ucv_property_get(uc_value_t *uv, const char *key) 1245 { 1246 uc_value_t *val; 1247 bool found; 1248 1249 for (; uv; uv = ucv_prototype_get(uv)) { 1250 val = ucv_object_get(uv, key, &found); 1251 1252 if (found) 1253 return val; 1254 } 1255 1256 return NULL; 1257 } 1258 1259 1260 uc_value_t * 1261 ucv_from_json(uc_vm_t *vm, json_object *jso) 1262 { 1263 //uc_array_t *arr; 1264 uc_value_t *uv, *item; 1265 int64_t n; 1266 size_t i; 1267 1268 switch (json_object_get_type(jso)) { 1269 case json_type_null: 1270 return NULL; 1271 1272 case json_type_boolean: 1273 return ucv_boolean_new(json_object_get_boolean(jso)); 1274 1275 case json_type_double: 1276 return ucv_double_new(json_object_get_double(jso)); 1277 1278 case json_type_int: 1279 n = json_object_get_int64(jso); 1280 1281 if (n == INT64_MAX) 1282 return ucv_uint64_new(json_object_get_uint64(jso)); 1283 1284 return ucv_int64_new(n); 1285 1286 case json_type_object: 1287 uv = ucv_object_new(vm); 1288 1289 json_object_object_foreach(jso, key, val) { 1290 item = ucv_from_json(vm, val); 1291 1292 if (!ucv_object_add(uv, key, item)) 1293 ucv_put(item); 1294 1295 #ifdef __clang_analyzer__ 1296 /* Clang static analyzer does not understand that the object retains 1297 * our item so pretend to free it here to suppress the false positive 1298 * memory leak warning. */ 1299 ucv_put(item); 1300 #endif 1301 } 1302 1303 return uv; 1304 1305 case json_type_array: 1306 /* XXX 1307 arr = (uc_array_t *)ucv_array_new_length(vm, json_object_array_length(jso)); 1308 1309 for (i = 0; i < arr->count; i++) 1310 arr->entries[i] = ucv_from_json(vm, json_object_array_get_idx(jso, i)); 1311 1312 return &arr->header; 1313 */ 1314 uv = ucv_array_new(vm); 1315 1316 for (i = 0; i < json_object_array_length(jso); i++) { 1317 item = ucv_from_json(vm, json_object_array_get_idx(jso, i)); 1318 1319 if (!ucv_array_push(uv, item)) 1320 ucv_put(item); 1321 1322 #ifdef __clang_analyzer__ 1323 /* Clang static analyzer does not understand that the array retains 1324 * our item so pretend to free it here to suppress the false positive 1325 * memory leak warning. */ 1326 ucv_put(item); 1327 #endif 1328 } 1329 1330 return uv; 1331 1332 case json_type_string: 1333 return ucv_string_new_length(json_object_get_string(jso), json_object_get_string_len(jso)); 1334 } 1335 1336 return NULL; 1337 } 1338 1339 json_object * 1340 ucv_to_json(uc_value_t *uv) 1341 { 1342 uc_regexp_t *regexp; 1343 uc_array_t *array; 1344 json_object *jso; 1345 size_t i; 1346 char *s; 1347 1348 switch (ucv_type(uv)) { 1349 case UC_BOOLEAN: 1350 return json_object_new_boolean(ucv_boolean_get(uv)); 1351 1352 case UC_INTEGER: 1353 if (ucv_is_u64(uv)) 1354 return json_object_new_uint64(ucv_uint64_get(uv)); 1355 1356 return json_object_new_int64(ucv_int64_get(uv)); 1357 1358 case UC_DOUBLE: 1359 return json_object_new_double(ucv_double_get(uv)); 1360 1361 case UC_STRING: 1362 return json_object_new_string_len(ucv_string_get(uv), ucv_string_length(uv)); 1363 1364 case UC_ARRAY: 1365 array = (uc_array_t *)uv; 1366 jso = json_object_new_array_ext(array->count); 1367 1368 for (i = 0; i < array->count; i++) 1369 json_object_array_put_idx(jso, i, ucv_to_json(array->entries[i])); 1370 1371 return jso; 1372 1373 case UC_OBJECT: 1374 jso = json_object_new_object(); 1375 1376 ucv_object_foreach(uv, key, val) 1377 json_object_object_add(jso, key, ucv_to_json(val)); 1378 1379 return jso; 1380 1381 case UC_REGEXP: 1382 regexp = (uc_regexp_t *)uv; 1383 i = asprintf(&s, "/%s/%s%s%s", 1384 regexp->source, 1385 regexp->global ? "g" : "", 1386 regexp->icase ? "i" : "", 1387 regexp->newline ? "s" : ""); 1388 1389 if (i <= 0) 1390 return NULL; 1391 1392 jso = json_object_new_string_len(s, i); 1393 1394 free(s); 1395 1396 return jso; 1397 1398 case UC_CLOSURE: 1399 case UC_CFUNCTION: 1400 case UC_RESOURCE: 1401 case UC_UPVALUE: 1402 case UC_PROGRAM: 1403 case UC_SOURCE: 1404 case UC_NULL: 1405 return NULL; 1406 } 1407 1408 return NULL; 1409 } 1410 1411 static void 1412 ucv_to_string_json_encoded(uc_stringbuf_t *pb, const char *s, size_t len, bool regexp) 1413 { 1414 size_t i; 1415 1416 if (!regexp) 1417 ucv_stringbuf_append(pb, "\""); 1418 1419 for (i = 0; s != NULL && i < len; i++, s++) { 1420 switch (*s) { 1421 case '"': 1422 ucv_stringbuf_append(pb, "\\\""); 1423 break; 1424 1425 case '\\': 1426 ucv_stringbuf_append(pb, "\\\\"); 1427 break; 1428 1429 case '\b': 1430 ucv_stringbuf_append(pb, "\\b"); 1431 break; 1432 1433 case '\f': 1434 ucv_stringbuf_append(pb, "\\f"); 1435 break; 1436 1437 case '\n': 1438 ucv_stringbuf_append(pb, "\\n"); 1439 break; 1440 1441 case '\r': 1442 ucv_stringbuf_append(pb, "\\r"); 1443 break; 1444 1445 case '\t': 1446 ucv_stringbuf_append(pb, "\\t"); 1447 break; 1448 1449 case '/': 1450 ucv_stringbuf_append(pb, "/"); 1451 break; 1452 1453 default: 1454 if ((unsigned char)*s < 0x20) 1455 ucv_stringbuf_printf(pb, "\\u%04x", (unsigned char)*s); 1456 else 1457 ucv_stringbuf_addstr(pb, s, 1); 1458 1459 break; 1460 } 1461 } 1462 1463 if (!regexp) 1464 ucv_stringbuf_append(pb, "\""); 1465 } 1466 1467 static bool 1468 ucv_call_tostring(uc_vm_t *vm, uc_stringbuf_t *pb, uc_value_t *uv, bool json) 1469 { 1470 uc_value_t *proto = ucv_prototype_get(uv); 1471 uc_value_t *tostr = ucv_object_get(proto, "tostring", NULL); 1472 uc_value_t *str; 1473 size_t l; 1474 char *s; 1475 1476 if (!ucv_is_callable(tostr)) 1477 return false; 1478 1479 uc_vm_stack_push(vm, ucv_get(uv)); 1480 uc_vm_stack_push(vm, ucv_get(tostr)); 1481 1482 if (uc_vm_call(vm, true, 0) != EXCEPTION_NONE) 1483 return false; 1484 1485 str = uc_vm_stack_pop(vm); 1486 1487 if (ucv_type(str) == UC_STRING) { 1488 s = ucv_string_get(str); 1489 l = ucv_string_length(str); 1490 1491 if (json) 1492 ucv_to_string_json_encoded(pb, s, l, false); 1493 else if (s) 1494 ucv_stringbuf_addstr(pb, s, l); 1495 } 1496 else if (json) { 1497 ucv_stringbuf_append(pb, "\"\""); 1498 } 1499 1500 ucv_put(str); 1501 1502 return true; 1503 } 1504 1505 void 1506 _ucv_stringbuf_append(uc_stringbuf_t *pb, const char *str, size_t len) 1507 { 1508 printbuf_memappend_fast(pb, str, (int)len); 1509 } 1510 1511 static void 1512 ucv_to_stringbuf_add_padding(uc_stringbuf_t *pb, char pad_char, size_t pad_size) 1513 { 1514 if (pad_char != '\0' && pad_char != '\1') { 1515 ucv_stringbuf_append(pb, "\n"); 1516 printbuf_memset(pb, -1, pad_char, pad_size); 1517 } 1518 else { 1519 ucv_stringbuf_append(pb, " "); 1520 } 1521 } 1522 1523 void 1524 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) 1525 { 1526 bool json = (pad_char != '\0'); 1527 uc_resource_type_t *restype; 1528 uc_resource_t *resource; 1529 uc_cfunction_t *cfunction; 1530 uc_function_t *function; 1531 uc_closure_t *closure; 1532 uc_regexp_t *regexp; 1533 uc_value_t *argname; 1534 uc_upvalref_t *ref; 1535 uc_array_t *array; 1536 size_t i, l; 1537 double d; 1538 char *s; 1539 1540 if (ucv_is_marked(uv)) { 1541 ucv_stringbuf_append(pb, "null"); 1542 1543 return; 1544 } 1545 1546 if (vm != NULL && ucv_call_tostring(vm, pb, uv, json)) 1547 return; 1548 1549 ucv_set_mark(uv); 1550 1551 switch (ucv_type(uv)) { 1552 case UC_NULL: 1553 ucv_stringbuf_append(pb, "null"); 1554 break; 1555 1556 case UC_BOOLEAN: 1557 if (ucv_boolean_get(uv)) 1558 ucv_stringbuf_append(pb, "true"); 1559 else 1560 ucv_stringbuf_append(pb, "false"); 1561 break; 1562 1563 case UC_INTEGER: 1564 if (ucv_is_u64(uv)) 1565 ucv_stringbuf_printf(pb, "%" PRIu64, ucv_uint64_get(uv)); 1566 else 1567 ucv_stringbuf_printf(pb, "%" PRId64, ucv_int64_get(uv)); 1568 break; 1569 1570 case UC_DOUBLE: 1571 d = ucv_double_get(uv); 1572 1573 if (json && isnan(d)) 1574 ucv_stringbuf_append(pb, "\"NaN\""); 1575 else if (json && d == INFINITY) 1576 ucv_stringbuf_append(pb, "1e309"); 1577 else if (json && d == -INFINITY) 1578 ucv_stringbuf_append(pb, "-1e309"); 1579 else if (isnan(d)) 1580 ucv_stringbuf_append(pb, "NaN"); 1581 else if (d == INFINITY) 1582 ucv_stringbuf_append(pb, "Infinity"); 1583 else if (d == -INFINITY) 1584 ucv_stringbuf_append(pb, "-Infinity"); 1585 else 1586 ucv_stringbuf_printf(pb, "%.14g", d); 1587 1588 break; 1589 1590 case UC_STRING: 1591 s = ucv_string_get(uv); 1592 l = ucv_string_length(uv); 1593 1594 if (s) { 1595 if (json) 1596 ucv_to_string_json_encoded(pb, s, l, false); 1597 else 1598 ucv_stringbuf_addstr(pb, s, l); 1599 } 1600 1601 break; 1602 1603 case UC_ARRAY: 1604 array = (uc_array_t *)uv; 1605 1606 ucv_stringbuf_append(pb, "["); 1607 1608 for (i = 0; i < array->count; i++) { 1609 if (i) 1610 ucv_stringbuf_append(pb, ","); 1611 1612 ucv_to_stringbuf_add_padding(pb, pad_char, (depth + 1) * pad_size); 1613 ucv_to_stringbuf_formatted(vm, pb, array->entries[i], depth + 1, pad_char ? pad_char : '\1', pad_size); 1614 } 1615 1616 ucv_to_stringbuf_add_padding(pb, pad_char, depth * pad_size); 1617 ucv_stringbuf_append(pb, "]"); 1618 break; 1619 1620 case UC_OBJECT: 1621 ucv_stringbuf_append(pb, "{"); 1622 1623 i = 0; 1624 ucv_object_foreach(uv, key, val) { 1625 if (i++) 1626 ucv_stringbuf_append(pb, ","); 1627 1628 ucv_to_stringbuf_add_padding(pb, pad_char, (depth + 1) * pad_size); 1629 ucv_to_string_json_encoded(pb, key, strlen(key), false); 1630 ucv_stringbuf_append(pb, ": "); 1631 ucv_to_stringbuf_formatted(vm, pb, val, depth + 1, pad_char ? pad_char : '\1', pad_size); 1632 } 1633 1634 ucv_to_stringbuf_add_padding(pb, pad_char, depth * pad_size); 1635 ucv_stringbuf_append(pb, "}"); 1636 break; 1637 1638 case UC_REGEXP: 1639 regexp = (uc_regexp_t *)uv; 1640 1641 if (json) 1642 ucv_stringbuf_append(pb, "\""); 1643 1644 ucv_stringbuf_append(pb, "/"); 1645 ucv_to_string_json_encoded(pb, regexp->source, strlen(regexp->source), true); 1646 ucv_stringbuf_append(pb, "/"); 1647 1648 if (regexp->global) 1649 ucv_stringbuf_append(pb, "g"); 1650 1651 if (regexp->icase) 1652 ucv_stringbuf_append(pb, "i"); 1653 1654 if (regexp->newline) 1655 ucv_stringbuf_append(pb, "s"); 1656 1657 if (json) 1658 ucv_stringbuf_append(pb, "\""); 1659 1660 break; 1661 1662 case UC_CLOSURE: 1663 closure = (uc_closure_t *)uv; 1664 function = closure->function; 1665 1666 if (json) 1667 ucv_stringbuf_append(pb, "\""); 1668 1669 if (!closure->is_arrow) { 1670 ucv_stringbuf_append(pb, "function"); 1671 1672 if (function->name[0]) { 1673 ucv_stringbuf_append(pb, " "); 1674 ucv_stringbuf_addstr(pb, function->name, strlen(function->name)); 1675 } 1676 } 1677 1678 ucv_stringbuf_append(pb, "("); 1679 1680 for (i = 1; i <= function->nargs; i++) { 1681 argname = uc_chunk_debug_get_variable(&function->chunk, i - 1, i, false); 1682 1683 if (i > 1) 1684 ucv_stringbuf_append(pb, ", "); 1685 1686 if (i == function->nargs && function->vararg) 1687 ucv_stringbuf_append(pb, "..."); 1688 1689 if (argname) { 1690 s = ucv_string_get(argname); 1691 l = ucv_string_length(argname); 1692 1693 if (s) 1694 ucv_stringbuf_addstr(pb, s, l); 1695 1696 ucv_put(argname); 1697 1698 continue; 1699 } 1700 1701 ucv_stringbuf_printf(pb, "[arg%zu]", i); 1702 } 1703 1704 ucv_stringbuf_printf(pb, ")%s { ... }%s", 1705 closure->is_arrow ? " =>" : "", 1706 json ? "\"" : ""); 1707 1708 break; 1709 1710 case UC_CFUNCTION: 1711 cfunction = (uc_cfunction_t *)uv; 1712 1713 ucv_stringbuf_printf(pb, "%sfunction%s%s(...) { [native code] }%s", 1714 json ? "\"" : "", 1715 cfunction->name[0] ? " " : "", 1716 cfunction->name[0] ? cfunction->name : "", 1717 json ? "\"" : ""); 1718 1719 break; 1720 1721 case UC_RESOURCE: 1722 resource = (uc_resource_t *)uv; 1723 restype = resource->type; 1724 1725 ucv_stringbuf_printf(pb, "%s<%s %p>%s", 1726 json ? "\"" : "", 1727 restype ? restype->name : "resource", 1728 resource->data, 1729 json ? "\"" : ""); 1730 1731 break; 1732 1733 case UC_UPVALUE: 1734 ref = (uc_upvalref_t *)uv; 1735 1736 if (ref->closed) 1737 ucv_to_stringbuf_formatted(vm, pb, ref->value, depth, pad_char, pad_size); 1738 else if (vm != NULL && ref->slot < vm->stack.count) 1739 ucv_to_stringbuf_formatted(vm, pb, vm->stack.entries[ref->slot], depth, pad_char, pad_size); 1740 else 1741 ucv_stringbuf_printf(pb, "%s<upvalref %p>%s", 1742 json ? "\"" : "", 1743 uv, 1744 json ? "\"" : ""); 1745 1746 break; 1747 1748 case UC_PROGRAM: 1749 ucv_stringbuf_printf(pb, "%s<program %p>%s", 1750 json ? "\"" : "", 1751 uv, 1752 json ? "\"" : ""); 1753 1754 break; 1755 1756 case UC_SOURCE: 1757 ucv_stringbuf_printf(pb, "%s<source %p>%s", 1758 json ? "\"" : "", 1759 uv, 1760 json ? "\"" : ""); 1761 } 1762 1763 ucv_clear_mark(uv); 1764 } 1765 1766 static char * 1767 ucv_to_string_any(uc_vm_t *vm, uc_value_t *uv, char pad_char, size_t pad_size) 1768 { 1769 uc_stringbuf_t *pb = xprintbuf_new(); 1770 char *rv; 1771 1772 ucv_to_stringbuf_formatted(vm, pb, uv, 0, pad_char, pad_size); 1773 1774 rv = pb->buf; 1775 1776 free(pb); 1777 1778 return rv; 1779 } 1780 1781 char * 1782 ucv_to_string(uc_vm_t *vm, uc_value_t *uv) 1783 { 1784 return ucv_to_string_any(vm, uv, '\0', 0); 1785 } 1786 1787 char * 1788 ucv_to_jsonstring_formatted(uc_vm_t *vm, uc_value_t *uv, char pad_char, size_t pad_size) 1789 { 1790 return ucv_to_string_any(vm, uv, pad_char ? pad_char : '\1', pad_size); 1791 } 1792 1793 1794 bool 1795 ucv_is_equal(uc_value_t *uv1, uc_value_t *uv2) 1796 { 1797 uc_type_t t1 = ucv_type(uv1); 1798 uc_type_t t2 = ucv_type(uv2); 1799 const char *s1, *s2; 1800 uint64_t u1, u2; 1801 int64_t n1, n2; 1802 bool b1, b2; 1803 1804 if (t1 != t2) 1805 return false; 1806 1807 if (t1 != UC_DOUBLE && uv1 == uv2) 1808 return true; 1809 1810 switch (t1) { 1811 case UC_NULL: 1812 return true; 1813 1814 case UC_BOOLEAN: 1815 return ucv_boolean_get(uv1) == ucv_boolean_get(uv2); 1816 1817 case UC_DOUBLE: 1818 return ucv_double_get(uv1) == ucv_double_get(uv2); 1819 1820 case UC_INTEGER: 1821 n1 = ucv_int64_get(uv1); 1822 b1 = (errno == 0); 1823 1824 n2 = ucv_int64_get(uv2); 1825 b2 = (errno == 0); 1826 1827 if (b1 && b2) 1828 return (n1 == n2); 1829 1830 u1 = ucv_uint64_get(uv1); 1831 b1 = (errno == 0); 1832 1833 u2 = ucv_uint64_get(uv2); 1834 b2 = (errno == 0); 1835 1836 if (b1 && b2) 1837 return (u1 == u2); 1838 1839 return false; 1840 1841 case UC_STRING: 1842 s1 = ucv_string_get(uv1); 1843 s2 = ucv_string_get(uv2); 1844 u1 = ucv_string_length(uv1); 1845 u2 = ucv_string_length(uv2); 1846 1847 if (s1 == NULL || s2 == NULL || u1 != u2) 1848 return false; 1849 1850 return (memcmp(s1, s2, u1) == 0); 1851 1852 case UC_ARRAY: 1853 u1 = ucv_array_length(uv1); 1854 u2 = ucv_array_length(uv2); 1855 1856 if (u1 != u2) 1857 return false; 1858 1859 for (u1 = 0; u1 < u2; u1++) 1860 if (!ucv_is_equal(ucv_array_get(uv1, u1), ucv_array_get(uv2, u1))) 1861 return false; 1862 1863 return true; 1864 1865 case UC_OBJECT: 1866 u1 = ucv_object_length(uv1); 1867 u2 = ucv_object_length(uv2); 1868 1869 if (u1 != u2) 1870 return false; 1871 1872 ucv_object_foreach(uv1, key, val) { 1873 if (!ucv_is_equal(val, ucv_object_get(uv2, key, NULL))) 1874 return false; 1875 } 1876 1877 ucv_object_foreach(uv2, key2, val2) { 1878 (void)val2; 1879 ucv_object_get(uv1, key2, &b1); 1880 1881 if (!b1) 1882 return false; 1883 } 1884 1885 return true; 1886 1887 default: 1888 return false; 1889 } 1890 } 1891 1892 bool 1893 ucv_is_truish(uc_value_t *val) 1894 { 1895 double d; 1896 1897 switch (ucv_type(val)) { 1898 case UC_INTEGER: 1899 if (ucv_is_u64(val)) 1900 return (ucv_uint64_get(val) != 0); 1901 1902 return (ucv_int64_get(val) != 0); 1903 1904 case UC_DOUBLE: 1905 d = ucv_double_get(val); 1906 1907 return (d != 0 && !isnan(d)); 1908 1909 case UC_BOOLEAN: 1910 return ucv_boolean_get(val); 1911 1912 case UC_STRING: 1913 return (ucv_string_length(val) > 0); 1914 1915 case UC_NULL: 1916 return false; 1917 1918 default: 1919 return true; 1920 } 1921 } 1922 1923 uc_value_t * 1924 ucv_to_number(uc_value_t *v) 1925 { 1926 switch (ucv_type(v)) { 1927 case UC_NULL: 1928 return ucv_uint64_new(0); 1929 1930 case UC_BOOLEAN: 1931 return ucv_uint64_new(ucv_boolean_get(v)); 1932 1933 case UC_INTEGER: 1934 return ucv_get(v); 1935 1936 case UC_DOUBLE: 1937 if (isnan(ucv_double_get(v))) 1938 return NULL; 1939 1940 return ucv_get(v); 1941 1942 case UC_STRING: 1943 return uc_number_parse(ucv_string_get(v), NULL); 1944 1945 default: 1946 return NULL; 1947 } 1948 } 1949 1950 bool 1951 ucv_compare(int how, uc_value_t *v1, uc_value_t *v2, int *deltap) 1952 { 1953 uc_type_t t1 = ucv_type(v1); 1954 uc_type_t t2 = ucv_type(v2); 1955 uc_value_t *nv1, *nv2; 1956 uint64_t u1, u2; 1957 int64_t n1, n2; 1958 double d1, d2; 1959 int8_t delta; 1960 1961 /* at least one operand is null and we compare for equality or inequality ... */ 1962 if ((!v1 || !v2) && (how == I_EQ || how == I_NE)) { 1963 delta = (v1 != v2); 1964 } 1965 1966 /* ... otherwise if both operands are strings, compare bytewise ... */ 1967 else if (t1 == UC_STRING && t2 == UC_STRING) { 1968 delta = strcmp(ucv_string_get(v1), ucv_string_get(v2)); 1969 } 1970 1971 /* handle non-string cases... */ 1972 else { 1973 /* ... both operands are of the same, non-scalar type... */ 1974 if (t1 == t2 && !ucv_is_scalar(v1)) { 1975 /* ... compare memory addrs */ 1976 delta = (intptr_t)v1 - (intptr_t)v2; 1977 } 1978 1979 /* ... operands are of different type or at least one is scalar... */ 1980 else { 1981 nv1 = ucv_to_number(v1); 1982 nv2 = ucv_to_number(v2); 1983 1984 /* ... at least one of them is NaN (not convertible)... */ 1985 if (!nv1 || !nv2) { 1986 ucv_put(nv1); 1987 ucv_put(nv2); 1988 1989 if (deltap) 1990 *deltap = 2; 1991 1992 /* ... all comparison results except `!=` involving NaN are false */ 1993 return (how == I_NE); 1994 } 1995 1996 /* ... either of them is a double, compare both as double */ 1997 if (ucv_type(nv1) == UC_DOUBLE || ucv_type(nv2) == UC_DOUBLE) { 1998 d1 = ucv_double_get(nv1); 1999 d2 = ucv_double_get(nv2); 2000 2001 if (d1 == d2) 2002 delta = 0; 2003 else if (d1 < d2) 2004 delta = -1; 2005 else 2006 delta = 1; 2007 } 2008 2009 /* ... both are integers... */ 2010 else { 2011 n1 = ucv_int64_get(nv1); 2012 2013 /* ... left operand is large positive... */ 2014 if (errno == ERANGE) { 2015 ucv_int64_get(nv2); 2016 2017 /* ... right operand is large positive too... */ 2018 if (errno == ERANGE) { 2019 /* ... compare both as unsigned */ 2020 u1 = ucv_uint64_get(nv1); 2021 u2 = ucv_uint64_get(nv2); 2022 2023 if (u1 == u2) 2024 delta = 0; 2025 else if (u1 < u2) 2026 delta = -1; 2027 else 2028 delta = 1; 2029 } 2030 2031 /* ... right operand is within int64_t range... */ 2032 else { 2033 /* ... left > right by definition */ 2034 delta = 1; 2035 } 2036 } 2037 2038 /* ... left operand is within int64_t range... */ 2039 else { 2040 n2 = ucv_int64_get(nv2); 2041 2042 /* ... right operand is large positive... */ 2043 if (errno == ERANGE) { 2044 /* ... left < right by definition */ 2045 delta = -1; 2046 } 2047 2048 /* ... right operand is within int64_t range... */ 2049 else { 2050 /* ... compare both as signed */ 2051 if (n1 == n2) 2052 delta = 0; 2053 else if (n1 < n2) 2054 delta = -1; 2055 else 2056 delta = 1; 2057 } 2058 } 2059 } 2060 2061 ucv_put(nv1); 2062 ucv_put(nv2); 2063 } 2064 } 2065 2066 if (deltap) 2067 *deltap = delta; 2068 2069 switch (how) { 2070 case I_LT: 2071 return (delta < 0); 2072 2073 case I_LE: 2074 return (delta <= 0); 2075 2076 case I_GT: 2077 return (delta > 0); 2078 2079 case I_GE: 2080 return (delta >= 0); 2081 2082 case I_EQ: 2083 return (delta == 0); 2084 2085 case I_NE: 2086 return (delta != 0); 2087 2088 default: 2089 return false; 2090 } 2091 } 2092 2093 2094 static char * 2095 ucv_key_to_string(uc_vm_t *vm, uc_value_t *val) 2096 { 2097 if (ucv_type(val) != UC_STRING) 2098 return ucv_to_string(vm, val); 2099 2100 return NULL; 2101 } 2102 2103 static int64_t 2104 ucv_key_to_index(uc_value_t *val) 2105 { 2106 const char *k; 2107 int64_t idx; 2108 double d; 2109 char *e; 2110 2111 /* only consider doubles with integer values as array keys */ 2112 if (ucv_type(val) == UC_DOUBLE) { 2113 d = ucv_double_get(val); 2114 2115 if (trunc(d) != d) 2116 return INT64_MIN; 2117 2118 return (int64_t)d; 2119 } 2120 else if (ucv_type(val) == UC_INTEGER) { 2121 return ucv_int64_get(val); 2122 } 2123 else if (ucv_type(val) == UC_STRING) { 2124 errno = 0; 2125 k = ucv_string_get(val); 2126 idx = strtoll(k, &e, 0); 2127 2128 if (errno != 0 || e == k || *e != 0) 2129 return INT64_MIN; 2130 2131 return idx; 2132 } 2133 2134 return INT64_MIN; 2135 } 2136 2137 uc_value_t * 2138 ucv_key_get(uc_vm_t *vm, uc_value_t *scope, uc_value_t *key) 2139 { 2140 uc_value_t *o, *v = NULL; 2141 int64_t idx; 2142 bool found; 2143 char *k; 2144 2145 if (ucv_type(scope) == UC_ARRAY) { 2146 idx = ucv_key_to_index(key); 2147 2148 if (idx < 0 && idx > INT64_MIN && (uint64_t)llabs(idx) <= ucv_array_length(scope)) 2149 idx += ucv_array_length(scope); 2150 2151 if (idx >= 0 && (uint64_t)idx < ucv_array_length(scope)) 2152 return ucv_get(ucv_array_get(scope, idx)); 2153 } 2154 2155 k = ucv_key_to_string(vm, key); 2156 2157 for (o = scope; o; o = ucv_prototype_get(o)) { 2158 if (ucv_type(o) != UC_OBJECT) 2159 continue; 2160 2161 v = ucv_object_get(o, k ? k : ucv_string_get(key), &found); 2162 2163 if (found) 2164 break; 2165 } 2166 2167 free(k); 2168 2169 return ucv_get(v); 2170 } 2171 2172 uc_value_t * 2173 ucv_key_set(uc_vm_t *vm, uc_value_t *scope, uc_value_t *key, uc_value_t *val) 2174 { 2175 int64_t idx; 2176 char *s; 2177 bool rv; 2178 2179 if (!key) 2180 return NULL; 2181 2182 if (ucv_type(scope) == UC_ARRAY) { 2183 idx = ucv_key_to_index(key); 2184 2185 if (idx < 0 && idx > INT64_MIN && (uint64_t)llabs(idx) <= ucv_array_length(scope)) 2186 idx += ucv_array_length(scope); 2187 2188 if (idx < 0 || !ucv_array_set(scope, idx, val)) 2189 return NULL; 2190 2191 return ucv_get(val); 2192 } 2193 2194 s = ucv_key_to_string(vm, key); 2195 rv = ucv_object_add(scope, s ? s : ucv_string_get(key), val); 2196 free(s); 2197 2198 return rv ? ucv_get(val) : NULL; 2199 } 2200 2201 bool 2202 ucv_key_delete(uc_vm_t *vm, uc_value_t *scope, uc_value_t *key) 2203 { 2204 char *s; 2205 bool rv; 2206 2207 if (!key) 2208 return NULL; 2209 2210 s = ucv_key_to_string(vm, key); 2211 rv = ucv_object_delete(scope, s ? s : ucv_string_get(key)); 2212 free(s); 2213 2214 return rv; 2215 } 2216 2217 2218 static void 2219 ucv_gc_common(uc_vm_t *vm, bool final) 2220 { 2221 uc_weakref_t *ref, *tmp; 2222 uc_value_t *val; 2223 size_t i; 2224 2225 vm->alloc_refs = 0; 2226 2227 /* back out early if value list is uninitialized */ 2228 if (!vm->values.prev || !vm->values.next) 2229 return; 2230 2231 if (!final) { 2232 /* mark reachable objects */ 2233 ucv_gc_mark(vm->globals); 2234 ucv_gc_mark(vm->registry); 2235 ucv_gc_mark(vm->exception.stacktrace); 2236 2237 for (i = 0; i < vm->callframes.count; i++) { 2238 ucv_gc_mark(vm->callframes.entries[i].ctx); 2239 2240 if (vm->callframes.entries[i].closure) 2241 ucv_gc_mark(&vm->callframes.entries[i].closure->header); 2242 2243 if (vm->callframes.entries[i].cfunction) 2244 ucv_gc_mark(&vm->callframes.entries[i].cfunction->header); 2245 } 2246 2247 for (i = 0; i < vm->stack.count; i++) 2248 ucv_gc_mark(vm->stack.entries[i]); 2249 2250 for (i = 0; i < vm->restypes.count; i++) 2251 ucv_gc_mark(vm->restypes.entries[i]->proto); 2252 } 2253 2254 /* unref unreachable objects */ 2255 for (ref = vm->values.next; ref != &vm->values; ref = ref->next) { 2256 val = (uc_value_t *)((uintptr_t)ref - offsetof(uc_array_t, ref)); 2257 2258 if (ucv_is_marked(val)) 2259 ucv_clear_mark(val); 2260 else 2261 ucv_free(val, true); 2262 } 2263 2264 /* free destroyed objects */ 2265 for (ref = vm->values.next, tmp = ref->next; ref != &vm->values; ref = tmp, tmp = tmp->next) { 2266 val = (uc_value_t *)((uintptr_t)ref - offsetof(uc_array_t, ref)); 2267 2268 if (val->type == UC_NULL) { 2269 ucv_unref(ref); 2270 free(val); 2271 } 2272 } 2273 } 2274 2275 void 2276 ucv_gc(uc_vm_t *vm) 2277 { 2278 ucv_gc_common(vm, false); 2279 } 2280 2281 void 2282 ucv_freeall(uc_vm_t *vm) 2283 { 2284 ucv_gc_common(vm, true); 2285 } 2286 2287 void 2288 uc_search_path_init(uc_search_path_t *search_path) 2289 { 2290 size_t i; 2291 2292 for (i = 0; i < ARRAY_SIZE(uc_default_search_path); i++) 2293 uc_vector_push(search_path, xstrdup(uc_default_search_path[i])); 2294 } 2295
This page was automatically generated by LXR 0.3.1. • OpenWrt