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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt