#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <inttypes.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include <math.h>
#include "cutils.h"
#include "list.h"
#include "mquickjs_build.h"
static unsigned JSW = 4;
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,
DEF(null, "null")
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")
DEF(class, "class")
DEF(const, "const")
DEF(enum, "enum")
DEF(export, "export")
DEF(extends, "extends")
DEF(import, "import")
DEF(super, "super")
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
"",
"toString",
"valueOf",
"number",
"object",
"undefined",
"string",
"boolean",
"<ret>",
"<eval>",
"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));
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);
}
#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) {
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;
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)
{
uint32_t prop = dump_atom(s, name, TRUE);
return (prop / JSW) ^ (prop % JSW);
}
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);
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__
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);
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;
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;
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) {
printf("(uint32_t)(-%s - 1) << 1,", class_id_str);
} else {
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;
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 {
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,
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,
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;
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);
for(i = 0; i < countof(atoms); i++) {
add_atom(&s->atom_list, atoms[i]);
}
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);
}
}
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;
}