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