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