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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt