/* * Micro QuickJS build utility * * Copyright (c) 2017-2025 Fabrice Bellard * Copyright (c) 2017-2025 Charlie Gordon * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include "cutils.h" #include "list.h" #include "mquickjs_build.h" static unsigned JSW = 4; // override this with -m64 typedef struct { char *str; int offset; } AtomDef; typedef struct { AtomDef *tab; int count; int size; int offset; } AtomList; typedef struct { char *name; int length; char *magic; char *cproto_name; char *cfunc_name; } CFuncDef; typedef struct { CFuncDef *tab; int count; int size; } CFuncList; typedef struct { struct list_head link; const JSClassDef *class1; int class_idx; char *finalizer_name; char *class_id; } ClassDefEntry; typedef struct { AtomList atom_list; CFuncList cfunc_list; int cur_offset; int sorted_atom_table_offset; int global_object_offset; struct list_head class_list; } BuildContext; static const char *atoms[] = { #define DEF(a, b) b, /* keywords */ DEF(null, "null") /* must be first */ DEF(false, "false") DEF(true, "true") DEF(if, "if") DEF(else, "else") DEF(return, "return") DEF(var, "var") DEF(this, "this") DEF(delete, "delete") DEF(void, "void") DEF(typeof, "typeof") DEF(new, "new") DEF(in, "in") DEF(instanceof, "instanceof") DEF(do, "do") DEF(while, "while") DEF(for, "for") DEF(break, "break") DEF(continue, "continue") DEF(switch, "switch") DEF(case, "case") DEF(default, "default") DEF(throw, "throw") DEF(try, "try") DEF(catch, "catch") DEF(finally, "finally") DEF(function, "function") DEF(debugger, "debugger") DEF(with, "with") /* FutureReservedWord */ DEF(class, "class") DEF(const, "const") DEF(enum, "enum") DEF(export, "export") DEF(extends, "extends") DEF(import, "import") DEF(super, "super") /* FutureReservedWords when parsing strict mode code */ DEF(implements, "implements") DEF(interface, "interface") DEF(let, "let") DEF(package, "package") DEF(private, "private") DEF(protected, "protected") DEF(public, "public") DEF(static, "static") DEF(yield, "yield") #undef DEF /* other atoms */ "", "toString", "valueOf", "number", "object", "undefined", "string", "boolean", "", "", "eval", "arguments", "value", "get", "set", "prototype", "constructor", "length", "target", "of", "NaN", "Infinity", "-Infinity", "name", "Error", "__proto__", "index", "input", }; static char *cvt_name(char *buf, size_t buf_size, const char *str) { size_t i, len = strlen(str); assert(len < buf_size); if (len == 0) { strcpy(buf, "empty"); } else { strcpy(buf, str); for(i = 0; i < len; i++) { if (buf[i] == '<' || buf[i] == '>' || buf[i] == '-') buf[i] = '_'; } } return buf; } static BOOL is_ascii_string(const char *buf, size_t len) { size_t i; for(i = 0; i < len; i++) { if ((uint8_t)buf[i] > 0x7f) return FALSE; } return TRUE; } static BOOL is_numeric_string(const char *buf, size_t len) { return (!strcmp(buf, "NaN") || !strcmp(buf, "Infinity") || !strcmp(buf, "-Infinity")); } static int find_atom(AtomList *s, const char *str) { int i; for(i = 0; i < s->count; i++) { if (!strcmp(str, s->tab[i].str)) return i; } return -1; } static int add_atom(AtomList *s, const char *str) { int i; AtomDef *e; i = find_atom(s, str); if (i >= 0) return s->tab[i].offset; if ((s->count + 1) > s->size) { s->size = max_int(s->count + 1, s->size * 3 / 2); s->tab = realloc(s->tab, sizeof(s->tab[0]) * s->size); } e = &s->tab[s->count++]; e->str = strdup(str); e->offset = s->offset; s->offset += 1 + ((strlen(str) + JSW) / JSW); return s->count - 1; } static int add_cfunc(CFuncList *s, const char *name, int length, const char *magic, const char *cproto_name, const char *cfunc_name) { int i; CFuncDef *e; for(i = 0; i < s->count; i++) { e = &s->tab[i]; if (!strcmp(name, e->name) && length == e->length && !strcmp(magic, e->magic) && !strcmp(cproto_name, e->cproto_name) && !strcmp(cfunc_name, e->cfunc_name)) { return i; } } if ((s->count + 1) > s->size) { s->size = max_int(s->count + 1, s->size * 3 / 2); s->tab = realloc(s->tab, sizeof(s->tab[0]) * s->size); } e = &s->tab[s->count++]; e->name = strdup(name); e->magic = strdup(magic); e->length = length; e->cproto_name = strdup(cproto_name); e->cfunc_name = strdup(cfunc_name); return s->count - 1; } static void dump_atom_defines(void) { AtomList atom_list_s, *s = &atom_list_s; AtomDef *e; int i; char buf[256]; memset(s, 0, sizeof(*s)); /* add the predefined atoms (they have a corresponding define) */ for(i = 0; i < countof(atoms); i++) { add_atom(s, atoms[i]); } for(i = 0; i < s->count; i++) { e = &s->tab[i]; printf("#define JS_ATOM_%s %d\n", cvt_name(buf, sizeof(buf), e->str), e->offset); } printf("\n"); printf("#define JS_ATOM_END %d\n", s->offset); printf("\n"); } static int atom_cmp(const void *p1, const void *p2) { const AtomDef *a1 = (const AtomDef *)p1; const AtomDef *a2 = (const AtomDef *)p2; return strcmp(a1->str, a2->str); } /* js_atom_table must be properly aligned because the property hash table uses the low bits of the atom pointer value */ #define ATOM_ALIGN 64 static void dump_atoms(BuildContext *ctx) { AtomList *s = &ctx->atom_list; int i, j, k, l, len, len1, is_ascii, is_numeric; uint64_t v; const char *str; AtomDef *sorted_atoms; char buf[256]; sorted_atoms = malloc(sizeof(sorted_atoms[0]) * s->count); memcpy(sorted_atoms, s->tab, sizeof(sorted_atoms[0]) * s->count); qsort(sorted_atoms, s->count, sizeof(sorted_atoms[0]), atom_cmp); printf(" /* atom_table */\n"); for(i = 0; i < s->count; i++) { str = s->tab[i].str; len = strlen(str); is_ascii = is_ascii_string(str, len); is_numeric = is_numeric_string(str, len); printf(" (JS_MTAG_STRING << 1) | (1 << JS_MTAG_BITS) | (%d << (JS_MTAG_BITS + 1)) | (%d << (JS_MTAG_BITS + 2)) | (%d << (JS_MTAG_BITS + 3)), /* \"%s\" (offset=%d) */\n", is_ascii, is_numeric, len, str, ctx->cur_offset); len1 = (len + JSW) / JSW; for(j = 0; j < len1; j++) { l = min_uint32(JSW, len - j * JSW); v = 0; for(k = 0; k < l; k++) v |= (uint64_t)(uint8_t)str[j * JSW + k] << (k * 8); printf(" 0x%0*" PRIx64 ",\n", JSW * 2, v); } assert(ctx->cur_offset == s->tab[i].offset); ctx->cur_offset += len1 + 1; } printf("\n"); ctx->sorted_atom_table_offset = ctx->cur_offset; printf(" /* sorted atom table (offset=%d) */\n", ctx->cur_offset); printf(" JS_VALUE_ARRAY_HEADER(%d),\n", s->count); for(i = 0; i < s->count; i++) { AtomDef *e = &sorted_atoms[i]; printf(" JS_ROM_VALUE(%d), /* %s */\n", e->offset, cvt_name(buf, sizeof(buf), e->str)); } ctx->cur_offset += s->count + 1; printf("\n"); free(sorted_atoms); } static int define_value(BuildContext *s, const JSPropDef *d); static uint32_t dump_atom(BuildContext *s, const char *str, BOOL value_only) { int len, idx, i, offset; len = strlen(str); for(i = 0; i < len; i++) { if ((uint8_t)str[i] >= 128) { fprintf(stderr, "unicode property names are not supported yet (%s)\n", str); exit(1); } } if (len >= 1 && (str[0] >= '0' && str[0] <= '9')) { fprintf(stderr, "numeric property names are not supported yet (%s)\n", str); exit(1); } if (len == 1) { if (value_only) { /* XXX: hardcoded */ return ((uint8_t)str[0] << 5) | 0x1b; } printf("JS_VALUE_MAKE_SPECIAL(JS_TAG_STRING_CHAR, %d)", (uint8_t)str[0]); } else { idx = find_atom(&s->atom_list, str); if (idx < 0) { fprintf(stderr, "atom '%s' is undefined\n", str); exit(1); } offset = s->atom_list.tab[idx].offset; if (value_only) return (offset * JSW) + 1; /* correct modulo ATOM_ALIGN */ printf("JS_ROM_VALUE(%d)", offset); } printf(" /* %s */", str); return 0; } static void dump_cfuncs(BuildContext *s) { int i; CFuncDef *e; printf("static const JSCFunctionDef js_c_function_table[] = {\n"); for(i = 0; i < s->cfunc_list.count; i++) { e = &s->cfunc_list.tab[i]; printf(" { { .%s = %s },\n", e->cproto_name, e->cfunc_name); printf(" "); dump_atom(s, e->name, FALSE); printf(",\n"); printf(" JS_CFUNC_%s, %d, %s },\n", e->cproto_name, e->length, e->magic); } printf("};\n\n"); } static void dump_cfinalizers(BuildContext *s) { struct list_head *el; ClassDefEntry *e; printf("static const JSCFinalizer js_c_finalizer_table[JS_CLASS_COUNT - JS_CLASS_USER] = {\n"); list_for_each(el, &s->class_list) { e = list_entry(el, ClassDefEntry, link); if (e->finalizer_name && strcmp(e->finalizer_name, "NULL") != 0) { printf(" [%s - JS_CLASS_USER] = %s,\n", e->class_id, e->finalizer_name); } } printf("};\n\n"); } typedef enum { PROPS_KIND_GLOBAL, PROPS_KIND_PROTO, PROPS_KIND_CLASS, PROPS_KIND_OBJECT, } JSPropsKindEnum; static inline uint32_t hash_prop(BuildContext *s, const char *name) { /* Compute the hash for a symbol, must be consistent with mquickjs.c implementation. */ uint32_t prop = dump_atom(s, name, TRUE); return (prop / JSW) ^ (prop % JSW); /* XXX: improve */ } static int define_props(BuildContext *s, const JSPropDef *props_def, JSPropsKindEnum props_kind, const char *class_id_str) { int i, *ident_tab, idx, props_ident, n_props; int prop_idx; const JSPropDef *d; uint32_t *prop_hash; BOOL is_global_object = (props_kind == PROPS_KIND_GLOBAL); static const JSPropDef dummy_props[] = { { JS_DEF_END }, }; if (!props_def) props_def = dummy_props; n_props = 0; for(d = props_def; d->def_type != JS_DEF_END; d++) { n_props++; } if (props_kind == PROPS_KIND_PROTO || props_kind == PROPS_KIND_CLASS) n_props++; ident_tab = malloc(sizeof(ident_tab[0]) * n_props); /* define the various objects */ for(d = props_def, i = 0; d->def_type != JS_DEF_END; d++, i++) { ident_tab[i] = define_value(s, d); } props_ident = -1; prop_hash = NULL; if (is_global_object) { props_ident = s->cur_offset; printf(" /* global object properties (offset=%d) */\n", props_ident); printf(" JS_VALUE_ARRAY_HEADER(%d),\n", 2 * n_props); s->cur_offset += 2 * n_props + 1; } else { int hash_size_log2; uint32_t hash_size, hash_mask; uint32_t *hash_table, h; if (n_props <= 1) hash_size_log2 = 0; else hash_size_log2 = (32 - clz32(n_props - 1)) - 1; hash_size = 1 << hash_size_log2; if (hash_size > ATOM_ALIGN / JSW) { #if !defined __APPLE__ // XXX: Cannot request data alignment larger than 64 bytes on Darwin fprintf(stderr, "Too many properties, consider increasing ATOM_ALIGN\n"); #endif hash_size = ATOM_ALIGN / JSW; } hash_mask = hash_size - 1; hash_table = malloc(sizeof(hash_table[0]) * hash_size); prop_hash = malloc(sizeof(prop_hash[0]) * n_props); /* build the hash table */ for(i = 0; i < hash_size; i++) hash_table[i] = 0; prop_idx = 0; for(i = 0, d = props_def; i < n_props; i++, d++) { const char *name; if (d->def_type != JS_DEF_END) { name = d->name; } else { if (props_kind == PROPS_KIND_PROTO) name = "constructor"; else name = "prototype"; } h = hash_prop(s, name) & hash_mask; prop_hash[prop_idx] = hash_table[h]; hash_table[h] = 2 + hash_size + 3 * prop_idx; prop_idx++; } props_ident = s->cur_offset; printf(" /* properties (offset=%d) */\n", props_ident); printf(" JS_VALUE_ARRAY_HEADER(%d),\n", 2 + hash_size + n_props * 3); printf(" %d << 1, /* n_props */\n", n_props); printf(" %d << 1, /* hash_mask */\n", hash_mask); for(i = 0; i < hash_size; i++) { printf(" %d << 1,\n", hash_table[i]); } s->cur_offset += hash_size + 3 + 3 * n_props; free(hash_table); } prop_idx = 0; for(d = props_def, i = 0; i < n_props; d++, i++) { const char *name, *prop_type; /* name */ printf(" "); if (d->def_type != JS_DEF_END) { name = d->name; } else { if (props_kind == PROPS_KIND_PROTO) name = "constructor"; else name = "prototype"; } dump_atom(s, name, FALSE); printf(",\n"); printf(" "); prop_type = "NORMAL"; switch(d->def_type) { case JS_DEF_PROP_DOUBLE: if (ident_tab[i] >= 0) goto value_ptr; /* short int */ printf("%d << 1,", (int32_t)d->u.f64); break; case JS_DEF_CGETSET: if (is_global_object) { fprintf(stderr, "getter/setter forbidden in global object\n"); exit(1); } prop_type = "GETSET"; goto value_ptr; case JS_DEF_CLASS: value_ptr: assert(ident_tab[i] >= 0); printf("JS_ROM_VALUE(%d),", ident_tab[i]); break; case JS_DEF_PROP_UNDEFINED: printf("JS_UNDEFINED,"); break; case JS_DEF_PROP_NULL: printf("JS_NULL,"); break; case JS_DEF_PROP_STRING: dump_atom(s, d->u.str, FALSE); printf(","); break; case JS_DEF_CFUNC: idx = add_cfunc(&s->cfunc_list, d->name, d->u.func.length, d->u.func.magic, d->u.func.cproto_name, d->u.func.func_name); printf("JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, %d),", idx); break; case JS_DEF_END: if (props_kind == PROPS_KIND_PROTO) { /* constructor property */ printf("(uint32_t)(-%s - 1) << 1,", class_id_str); } else { /* prototype property */ printf("%s << 1,", class_id_str); } prop_type = "SPECIAL"; break; default: abort(); } printf("\n"); if (!is_global_object) { printf(" (%d << 1) | (JS_PROP_%s << 30),\n", prop_hash[prop_idx], prop_type); } prop_idx++; } free(prop_hash); free(ident_tab); return props_ident; } static ClassDefEntry *find_class(BuildContext *s, const JSClassDef *d) { struct list_head *el; ClassDefEntry *e; list_for_each(el, &s->class_list) { e = list_entry(el, ClassDefEntry, link); if (e->class1 == d) return e; } return NULL; } static void free_class_entries(BuildContext *s) { struct list_head *el, *el1; ClassDefEntry *e; list_for_each_safe(el, el1, &s->class_list) { e = list_entry(el, ClassDefEntry, link); free(e->class_id); free(e->finalizer_name); free(e); } init_list_head(&s->class_list); } static int define_class(BuildContext *s, const JSClassDef *d) { int ctor_func_idx = -1, class_props_idx = -1, proto_props_idx = -1; int ident, parent_class_idx = -1; ClassDefEntry *e; /* check if the class is already defined */ e = find_class(s, d); if (e) return e->class_idx; if (d->parent_class) parent_class_idx = define_class(s, d->parent_class); if (d->func_name) { ctor_func_idx = add_cfunc(&s->cfunc_list, d->name, d->length, d->class_id, d->cproto_name, d->func_name); } if (ctor_func_idx >= 0) { class_props_idx = define_props(s, d->class_props, PROPS_KIND_CLASS, d->class_id); proto_props_idx = define_props(s, d->proto_props, PROPS_KIND_PROTO, d->class_id); } else { if (d->class_props) class_props_idx = define_props(s, d->class_props, PROPS_KIND_OBJECT, d->class_id); } ident = s->cur_offset; printf(" /* class (offset=%d) */\n", ident); printf(" JS_MB_HEADER_DEF(JS_MTAG_OBJECT),\n"); if (class_props_idx >= 0) printf(" JS_ROM_VALUE(%d),\n", class_props_idx); else printf(" JS_NULL,\n"); printf(" %d,\n", ctor_func_idx); if (proto_props_idx >= 0) printf(" JS_ROM_VALUE(%d),\n", proto_props_idx); else printf(" JS_NULL,\n"); if (parent_class_idx >= 0) { printf(" JS_ROM_VALUE(%d),\n", parent_class_idx); } else { printf(" JS_NULL,\n"); } printf("\n"); s->cur_offset += 5; e = malloc(sizeof(*e)); memset(e, 0, sizeof(*e)); e->class_idx = ident; e->class1 = d; if (ctor_func_idx >= 0) { e->class_id = strdup(d->class_id); e->finalizer_name = strdup(d->finalizer_name); } list_add_tail(&e->link, &s->class_list); return ident; } #define JS_SHORTINT_MIN (-(1 << 30)) #define JS_SHORTINT_MAX ((1 << 30) - 1) static BOOL is_short_int(double d) { return (d >= JS_SHORTINT_MIN && d <= JS_SHORTINT_MAX && (int32_t)d == d); } static int define_value(BuildContext *s, const JSPropDef *d) { int ident; ident = -1; switch(d->def_type) { case JS_DEF_PROP_DOUBLE: { uint64_t v; if (!is_short_int(d->u.f64)) { ident = s->cur_offset; printf(" /* float64 (offset=%d) */\n", ident); printf(" JS_MB_HEADER_DEF(JS_MTAG_FLOAT64),\n"); v = float64_as_uint64(d->u.f64); if (JSW == 8) { printf(" 0x%016zx,\n", (size_t)v); printf("\n"); s->cur_offset += 2; } else { /* XXX: little endian assumed */ printf(" 0x%08x,\n", (uint32_t)v); printf(" 0x%08x,\n", (uint32_t)(v >> 32)); printf("\n"); s->cur_offset += 3; } } } break; case JS_DEF_CLASS: ident = define_class(s, d->u.class1); break; case JS_DEF_CGETSET: { int get_idx = -1, set_idx = -1; char buf[256]; if (strcmp(d->u.getset.get_func_name, "NULL") != 0) { snprintf(buf, sizeof(buf), "get %s", d->name); get_idx = add_cfunc(&s->cfunc_list, buf, 0, /* length */ d->u.getset.magic, d->u.getset.cproto_name, d->u.getset.get_func_name); } if (strcmp(d->u.getset.set_func_name, "NULL") != 0) { snprintf(buf, sizeof(buf), "set %s", d->name); set_idx = add_cfunc(&s->cfunc_list, buf, 1, /* length */ d->u.getset.magic, d->u.getset.cproto_name, d->u.getset.set_func_name); } ident = s->cur_offset; printf(" /* getset (offset=%d) */\n", ident); printf(" JS_VALUE_ARRAY_HEADER(2),\n"); if (get_idx >= 0) printf(" JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, %d),\n", get_idx); else printf(" JS_UNDEFINED,\n"); if (set_idx >= 0) printf(" JS_VALUE_MAKE_SPECIAL(JS_TAG_SHORT_FUNC, %d),\n", set_idx); else printf(" JS_UNDEFINED,\n"); printf("\n"); s->cur_offset += 3; } break; default: break; } return ident; } static void define_atoms_props(BuildContext *s, const JSPropDef *props_def, JSPropsKindEnum props_kind); static void define_atoms_class(BuildContext *s, const JSClassDef *d) { ClassDefEntry *e; /* check if the class is already defined */ e = find_class(s, d); if (e) return; if (d->parent_class) define_atoms_class(s, d->parent_class); if (d->func_name) add_atom(&s->atom_list, d->name); if (d->class_props) define_atoms_props(s, d->class_props, d->func_name ? PROPS_KIND_CLASS : PROPS_KIND_OBJECT); if (d->proto_props) define_atoms_props(s, d->proto_props, PROPS_KIND_PROTO); } static void define_atoms_props(BuildContext *s, const JSPropDef *props_def, JSPropsKindEnum props_kind) { const JSPropDef *d; for(d = props_def; d->def_type != JS_DEF_END; d++) { add_atom(&s->atom_list, d->name); switch(d->def_type) { case JS_DEF_PROP_STRING: add_atom(&s->atom_list, d->u.str); break; case JS_DEF_CLASS: define_atoms_class(s, d->u.class1); break; case JS_DEF_CGETSET: { char buf[256]; if (strcmp(d->u.getset.get_func_name, "NULL") != 0) { snprintf(buf, sizeof(buf), "get %s", d->name); add_atom(&s->atom_list, buf); } if (strcmp(d->u.getset.set_func_name, "NULL") != 0) { snprintf(buf, sizeof(buf), "set %s", d->name); add_atom(&s->atom_list, buf); } } break; default: break; } } } static int usage(const char *name) { fprintf(stderr, "usage: %s {-m32 | -m64} [-a]\n", name); fprintf(stderr, " create a ROM file for the mquickjs standard library\n" "--help list options\n" "-m32 force generation for a 32 bit target\n" "-m64 force generation for a 64 bit target\n" "-a generate the mquickjs_atom.h header\n" ); return 1; } int build_atoms(const char *stdlib_name, const JSPropDef *global_obj, const JSPropDef *c_function_decl, int argc, char **argv) { int i; unsigned jsw; BuildContext ss, *s = &ss; BOOL build_atom_defines = FALSE; #if INTPTR_MAX >= INT64_MAX jsw = 8; #else jsw = 4; #endif for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-m64")) { jsw = 8; } else if (!strcmp(argv[i], "-m32")) { jsw = 4; } else if (!strcmp(argv[i], "-a")) { build_atom_defines = TRUE; } else if (!strcmp(argv[i], "--help")) { return usage(argv[0]); } else { fprintf(stderr, "invalid argument '%s'\n", argv[i]); return usage(argv[0]); } } JSW = jsw; if (build_atom_defines) { dump_atom_defines(); return 0; } memset(s, 0, sizeof(*s)); init_list_head(&s->class_list); /* add the predefined atoms (they have a corresponding define) */ for(i = 0; i < countof(atoms); i++) { add_atom(&s->atom_list, atoms[i]); } /* add the predefined functions */ if (c_function_decl) { const JSPropDef *d; for(d = c_function_decl; d->def_type != JS_DEF_END; d++) { if (d->def_type != JS_DEF_CFUNC) { fprintf(stderr, "only C functions are allowed in c_function_decl[]\n"); exit(1); } add_atom(&s->atom_list, d->name); add_cfunc(&s->cfunc_list, d->name, d->u.func.length, d->u.func.magic, d->u.func.cproto_name, d->u.func.func_name); } } /* first pass to define the atoms */ define_atoms_props(s, global_obj, PROPS_KIND_GLOBAL); free_class_entries(s); printf("/* this file is automatically generated - do not edit */\n\n"); printf("#include \"mquickjs_priv.h\"\n\n"); printf("static const uint%u_t __attribute((aligned(%d))) js_stdlib_table[] = {\n", JSW * 8, ATOM_ALIGN); dump_atoms(s); s->global_object_offset = define_props(s, global_obj, PROPS_KIND_GLOBAL, NULL); printf("};\n\n"); dump_cfuncs(s); printf("#ifndef JS_CLASS_COUNT\n" "#define JS_CLASS_COUNT JS_CLASS_USER /* total number of classes */\n" "#endif\n\n"); dump_cfinalizers(s); free_class_entries(s); printf("const JSSTDLibraryDef %s = {\n", stdlib_name); printf(" js_stdlib_table,\n"); printf(" js_c_function_table,\n"); printf(" js_c_finalizer_table,\n"); printf(" %d,\n", s->cur_offset); printf(" %d,\n", ATOM_ALIGN); printf(" %d,\n", s->sorted_atom_table_offset); printf(" %d,\n", s->global_object_offset); printf(" JS_CLASS_COUNT,\n"); printf("};\n\n"); return 0; }