• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/ucode/types.c

  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(&regexp->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