Xteink-X4-crosspoint-reader/lib/mquickjs/scripts/mquickjs_build.c
Xuan Son Nguyen 49d2c5eba8 init version
2026-01-31 22:01:10 +01:00

933 lines
27 KiB
C

/*
* 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 <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; // 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",
"<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));
/* 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;
}