QuickJS Javascript Engine
-
+
Copyright (c) 2017-2021 Fabrice Bellard
Copyright (c) 2017-2021 Charlie Gordon
#
# QuickJS Javascript Engine
-#
+#
# Copyright (c) 2017-2021 Fabrice Bellard
# Copyright (c) 2017-2021 Charlie Gordon
#
all: $(OBJDIR) $(OBJDIR)/quickjs.check.o $(OBJDIR)/qjs.check.o $(PROGS)
-QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o $(OBJDIR)/libbf.o
+QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o $(OBJDIR)/libbf.o
QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/repl.o $(QJS_LIB_OBJS)
ifdef CONFIG_BIGNUM
###############################################################################
# documentation
-DOCS=doc/quickjs.pdf doc/quickjs.html doc/jsbignum.pdf doc/jsbignum.html
+DOCS=doc/quickjs.pdf doc/quickjs.html doc/jsbignum.pdf doc/jsbignum.html
build_doc: $(DOCS)
-clean_doc:
+clean_doc:
rm -f $(DOCS)
doc/%.pdf: doc/%.texi
/*
* C utilities
- *
+ *
* Copyright (c) 2017 Fabrice Bellard
* Copyright (c) 2018 Charlie Gordon
*
va_list ap;
char buf[128];
int len;
-
+
va_start(ap, fmt);
len = vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
/*
* C utilities
- *
+ *
* Copyright (c) 2017 Fabrice Bellard
* Copyright (c) 2018 Charlie Gordon
*
static inline uint64_t bswap64(uint64_t v)
{
- return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) |
- ((v & ((uint64_t)0xff << (6 * 8))) >> (5 * 8)) |
- ((v & ((uint64_t)0xff << (5 * 8))) >> (3 * 8)) |
- ((v & ((uint64_t)0xff << (4 * 8))) >> (1 * 8)) |
- ((v & ((uint64_t)0xff << (3 * 8))) << (1 * 8)) |
- ((v & ((uint64_t)0xff << (2 * 8))) << (3 * 8)) |
- ((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) |
+ return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) |
+ ((v & ((uint64_t)0xff << (6 * 8))) >> (5 * 8)) |
+ ((v & ((uint64_t)0xff << (5 * 8))) >> (3 * 8)) |
+ ((v & ((uint64_t)0xff << (4 * 8))) >> (1 * 8)) |
+ ((v & ((uint64_t)0xff << (3 * 8))) << (1 * 8)) |
+ ((v & ((uint64_t)0xff << (2 * 8))) << (3 * 8)) |
+ ((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) |
((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8));
}
Otherwise, the number is rounded to nearest with ties to even using
the global precision. It is then converted to string using the minimum
number of digits so that its conversion back to a floating point using
-the global precision and round to nearest gives the same number.
+the global precision and round to nearest gives the same number.
@end itemize
@table @code
@item -c
Only output bytecode in a C file. The default is to output an executable file.
-@item -e
+@item -e
Output @code{main()} and bytecode in a C file. The default is to output an
executable file.
@item -o output
to be UTF-8 encoded.
@item full
-
+
Boolean (default = false). If true, return the an object contains
the properties @code{response} (response content),
@code{responseHeaders} (headers separated by CRLF), @code{status}
Open a file. Return a handle or < 0 if error.
@item O_RDONLY
-@item O_WRONLY
+@item O_WRONLY
@item O_RDWR
@item O_APPEND
@item O_CREAT
terminated. In this case, @code{exec} return the exit code if positive
or the negated signal number if the process was interrupted by a
signal. If false, do not block and return the process id of the child.
-
+
@item usePath
Boolean (default = true). If true, the file is searched in the
@code{PATH} environment variable.
@item uid
Integer. If present, the process uid with @code{setuid}.
- @item gid
+ @item gid
Integer. If present, the process gid with @code{setgid}.
@end table
@table @code
@item postMessage(msg)
-
+
Send a message to the corresponding worker. @code{msg} is cloned in
the destination worker using an algorithm similar to the @code{HTML}
structured clone algorithm. @code{SharedArrayBuffer} are shared
representation such as a parse tree, hence it is very fast. Several
optimizations passes are done over the generated bytecode.
-A stack-based bytecode was chosen because it is simple and generates
+A stack-based bytecode was chosen because it is simple and generates
compact code.
For each function, the maximum stack size is computed at compile time so that
/*
* QuickJS: Example of C module
- *
+ *
* Copyright (c) 2017-2018 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
const CHUD_C = 640320m;
const CHUD_C3 = 10939058860032000m; /* C^3/24 */
const CHUD_DIGITS_PER_TERM = 14.18164746272548; /* log10(C/12)*3 */
-
+
/* return [P, Q, G] */
function chud_bs(a, b, need_G) {
var c, P, Q, G, P1, Q1, G1, P2, Q2, G2, b1;
const CHUD_C = 640320n;
const CHUD_C3 = 10939058860032000n; /* C^3/24 */
const CHUD_BITS_PER_TERM = 47.11041313821584202247; /* log2(C/12)*3 */
-
+
/* return [P, Q, G] */
function chud_bs(a, b, need_G) {
var c, P, Q, G, P1, Q1, G1, P2, Q2, G2;
const CHUD_C = 640320n;
const CHUD_C3 = 10939058860032000n; /* C^3/24 */
const CHUD_BITS_PER_TERM = 47.11041313821584202247; /* log2(C/12)*3 */
-
+
/* return [P, Q, G] */
function chud_bs(a, b, need_G) {
var c, P, Q, G, P1, Q1, G1, P2, Q2, G2;
/*
* QuickJS: Example of C module with a class
- *
+ *
* Copyright (c) 2019 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
JSPointData *s;
JSValue obj = JS_UNDEFINED;
JSValue proto;
-
+
s = js_mallocz(ctx, sizeof(*s));
if (!s)
return JS_EXCEPTION;
static JSClassDef js_point_class = {
"Point",
.finalizer = js_point_finalizer,
-};
+};
static const JSCFunctionListEntry js_point_proto_funcs[] = {
JS_CGETSET_MAGIC_DEF("x", js_point_get_xy, js_point_set_xy, 0),
static int js_point_init(JSContext *ctx, JSModuleDef *m)
{
JSValue point_proto, point_class;
-
+
/* create the Point class */
JS_NewClassID(&js_point_class_id);
JS_NewClass(JS_GetRuntime(ctx), js_point_class_id, &js_point_class);
point_proto = JS_NewObject(ctx);
JS_SetPropertyFunctionList(ctx, point_proto, js_point_proto_funcs, countof(js_point_proto_funcs));
-
+
point_class = JS_NewCFunction2(ctx, js_point_ctor, "Point", 2, JS_CFUNC_constructor, 0);
/* set proto.constructor and ctor.prototype */
JS_SetConstructor(ctx, point_class, point_proto);
JS_SetClassProto(ctx, js_point_class_id, point_proto);
-
+
JS_SetModuleExport(ctx, m, "Point", point_class);
return 0;
}
/*
* Tiny arbitrary precision floating point library
- *
+ *
* Copyright (c) 2017-2021 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
#define UDIV1NORM_THRESHOLD 3
#if LIMB_BITS == 64
-#define FMT_LIMB1 "%" PRIx64
-#define FMT_LIMB "%016" PRIx64
+#define FMT_LIMB1 "%" PRIx64
+#define FMT_LIMB "%016" PRIx64
#define PRId_LIMB PRId64
#define PRIu_LIMB PRIu64
int bf_resize(bf_t *r, limb_t len)
{
limb_t *tab;
-
+
if (len != r->len) {
tab = bf_realloc(r->ctx, r->tab, len * sizeof(limb_t));
if (!tab && len != 0)
if (a == 0) {
r->expn = BF_EXP_ZERO;
bf_resize(r, 0); /* cannot fail */
- }
+ }
#if LIMB_BITS == 32
else if (a <= 0xffffffff)
#else
{
slimb_t pos;
limb_t v;
-
+
pos = bit_pos >> LIMB_LOG2_BITS;
if (pos < 0)
return 0;
{
int add_one, inexact;
limb_t bit1, bit0;
-
+
if (rnd_mode == BF_RNDF) {
bit0 = 1; /* faithful rounding does not honor the INEXACT flag */
} else {
/* get the bit at 'prec' */
bit1 = get_bit(r->tab, l, l * LIMB_BITS - 1 - prec);
inexact = (bit1 | bit0) != 0;
-
+
add_one = 0;
switch(rnd_mode) {
case BF_RNDZ:
default:
abort();
}
-
+
if (inexact)
*pret |= BF_ST_INEXACT;
return add_one;
{
slimb_t i, l, e_max;
int rnd_mode;
-
+
rnd_mode = flags & BF_RND_MASK;
if (prec == BF_PREC_INF ||
rnd_mode == BF_RNDN ||
e_range = (limb_t)1 << (bf_get_exp_bits(flags) - 1);
e_min = -e_range + 3;
e_max = e_range;
-
+
if (flags & BF_FLAG_RADPNT_PREC) {
/* 'prec' is the precision after the radix point */
if (prec1 != BF_PREC_INF)
/* round to prec bits */
rnd_mode = flags & BF_RND_MASK;
add_one = bf_get_rnd_add(&ret, r, l, prec, rnd_mode);
-
+
if (prec <= 0) {
if (add_one) {
bf_resize(r, 1); /* cannot fail */
}
} else if (add_one) {
limb_t carry;
-
+
/* add one starting at digit 'prec - 1' */
bit_pos = l * LIMB_BITS - 1 - (prec - 1);
pos = bit_pos >> LIMB_LOG2_BITS;
carry = (limb_t)1 << (bit_pos & (LIMB_BITS - 1));
-
+
for(i = pos; i < l; i++) {
v = r->tab[i] + carry;
carry = (v < carry);
r->expn++;
}
}
-
+
/* check underflow */
if (unlikely(r->expn < e_min)) {
if (flags & BF_FLAG_SUBNORMAL) {
return ret;
}
}
-
+
/* check overflow */
if (unlikely(r->expn > e_max))
return bf_set_overflow(r, r->sign, prec1, flags);
-
+
/* keep the bits starting at 'prec - 1' */
bit_pos = l * LIMB_BITS - 1 - (prec - 1);
i = bit_pos >> LIMB_LOG2_BITS;
limb_t l, v, a;
int shift, ret;
slimb_t i;
-
+
// bf_print_str("bf_renorm", r);
l = r->len;
while (l > 0 && r->tab[l - 1] == 0)
BOOL is_rndn;
slimb_t bit_pos, n;
limb_t bit;
-
+
if (a->expn == BF_EXP_INF || a->expn == BF_EXP_NAN)
return FALSE;
if (rnd_mode == BF_RNDF) {
bit_pos = a->len * LIMB_BITS - 1 - prec;
n = k - prec;
/* bit pattern for RNDN or RNDNA: 0111.. or 1000...
- for other rounding modes: 000... or 111...
+ for other rounding modes: 000... or 111...
*/
bit = get_bit(a->tab, a->len, bit_pos);
bit_pos--;
{
slimb_t i;
limb_t len, v1, v2;
-
+
if (a->expn != b->expn) {
if (a->expn < b->expn)
return -1;
int bf_cmp_full(const bf_t *a, const bf_t *b)
{
int res;
-
+
if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) {
if (a->expn == b->expn)
res = 0;
int bf_cmp(const bf_t *a, const bf_t *b)
{
int res;
-
+
if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) {
res = 2;
} else if (a->sign != b->sign) {
/* Compute the number of bits 'n' matching the pattern:
a= X1000..0
b= X0111..1
-
+
When computing a-b, the result will have at least n leading zero
bits.
} else {
cancelled_bits = 0;
}
-
+
/* add two extra bits for rounding */
precl = (cancelled_bits + prec + 2 + LIMB_BITS - 1) / LIMB_BITS;
tot_len = bf_max(a->len, b->len + (d + LIMB_BITS - 1) / LIMB_BITS);
while (i < 0) {
slimb_t ap, bp;
BOOL inflag;
-
+
ap = a_offset + i;
bp = b_bit_offset + i * LIMB_BITS;
inflag = FALSE;
if (ap < 0)
i = bf_min(i, -a_offset);
/* b_bit_offset + i * LIMB_BITS + LIMB_BITS >= 1
- equivalent to
+ equivalent to
i >= ceil(-b_bit_offset + 1 - LIMB_BITS) / LIMB_BITS)
*/
if (bp + LIMB_BITS <= 0)
return bf_add_internal(r, a, b, prec, flags, 1);
}
-limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2,
+limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2,
limb_t n, limb_t carry)
{
slimb_t i;
limb_t k, a, v, k1;
-
+
k = carry;
for(i=0;i<n;i++) {
v = op1[i];
return k;
}
-limb_t mp_sub(limb_t *res, const limb_t *op1, const limb_t *op2,
+limb_t mp_sub(limb_t *res, const limb_t *op1, const limb_t *op2,
mp_size_t n, limb_t carry)
{
int i;
limb_t k, a, v, k1;
-
+
k = carry;
for(i=0;i<n;i++) {
v = op1[i];
{
int i;
limb_t k, a, v, k1;
-
+
k = carry;
for(i=0;i<n;i++) {
v = 0;
{
mp_size_t i;
limb_t k, a, v;
-
+
k=b;
for(i=0;i<n;i++) {
v = tab[i];
return k;
}
-/* r = (a + high*B^n) >> shift. Return the remainder r (0 <= r < 2^shift).
+/* r = (a + high*B^n) >> shift. Return the remainder r (0 <= r < 2^shift).
1 <= shift <= LIMB_BITS - 1 */
-static limb_t mp_shr(limb_t *tab_r, const limb_t *tab, mp_size_t n,
+static limb_t mp_shr(limb_t *tab_r, const limb_t *tab, mp_size_t n,
int shift, limb_t high)
{
mp_size_t i;
}
/* tabr[] = taba[] * b + l. Return the high carry */
-static limb_t mp_mul1(limb_t *tabr, const limb_t *taba, limb_t n,
+static limb_t mp_mul1(limb_t *tabr, const limb_t *taba, limb_t n,
limb_t b, limb_t l)
{
limb_t i;
{
limb_t i, l;
dlimb_t t;
-
+
l = 0;
for(i = 0; i < n; i++) {
t = (dlimb_t)taba[i] * (dlimb_t)b + l + tabr[i];
}
/* size of the result : op1_size + op2_size. */
-static void mp_mul_basecase(limb_t *result,
- const limb_t *op1, limb_t op1_size,
- const limb_t *op2, limb_t op2_size)
+static void mp_mul_basecase(limb_t *result,
+ const limb_t *op1, limb_t op1_size,
+ const limb_t *op2, limb_t op2_size)
{
limb_t i, r;
-
+
result[op1_size] = mp_mul1(result, op1, op1_size, op2[0], 0);
for(i=1;i<op2_size;i++) {
r = mp_add_mul1(result + i, op1, op1_size, op2[i]);
/* return 0 if OK, -1 if memory error */
/* XXX: change API so that result can be allocated */
-int mp_mul(bf_context_t *s, limb_t *result,
- const limb_t *op1, limb_t op1_size,
- const limb_t *op2, limb_t op2_size)
+int mp_mul(bf_context_t *s, limb_t *result,
+ const limb_t *op1, limb_t op1_size,
+ const limb_t *op2, limb_t op2_size)
{
#ifdef USE_FFT_MUL
if (unlikely(bf_min(op1_size, op2_size) >= FFT_MUL_THRESHOLD)) {
{
limb_t i, l;
dlimb_t t;
-
+
l = 0;
for(i = 0; i < n; i++) {
t = tabr[i] - (dlimb_t)taba[i] * (dlimb_t)b - l;
return r;
}
-static int mp_divnorm_large(bf_context_t *s,
- limb_t *tabq, limb_t *taba, limb_t na,
+static int mp_divnorm_large(bf_context_t *s,
+ limb_t *tabq, limb_t *taba, limb_t na,
const limb_t *tabb, limb_t nb);
/* base case division: divides taba[0..na-1] by tabb[0..nb-1]. tabb[nb
- 1] must be >= 1 << (LIMB_BITS - 1). na - nb must be >= 0. 'taba'
is modified and contains the remainder (nb limbs). tabq[0..na-nb]
contains the quotient with tabq[na - nb] <= 1. */
-static int mp_divnorm(bf_context_t *s, limb_t *tabq, limb_t *taba, limb_t na,
+static int mp_divnorm(bf_context_t *s, limb_t *tabq, limb_t *taba, limb_t na,
const limb_t *tabb, limb_t nb)
{
limb_t r, a, c, q, v, b1, b1_inv, n, dummy_r;
if (bf_min(n, nb) >= DIVNORM_LARGE_THRESHOLD) {
return mp_divnorm_large(s, tabq, taba, na, tabb, nb);
}
-
+
if (n >= UDIV1NORM_THRESHOLD)
b1_inv = udiv1norm_init(b1);
else
if (q) {
mp_sub(taba + n, taba + n, tabb, nb, 0);
}
-
+
for(i = n - 1; i >= 0; i--) {
if (unlikely(taba[i + nb] >= b1)) {
q = -1;
/* compute r=B^(2*n)/a such as a*r < B^(2*n) < a*r + 2 with n >= 1. 'a'
has n limbs with a[n-1] >= B/2 and 'r' has n+1 limbs with r[n] = 1.
-
+
See Modern Computer Arithmetic by Richard P. Brent and Paul
Zimmermann, algorithm 3.5 */
int mp_recip(bf_context_t *s, limb_t *tabr, const limb_t *taba, limb_t n)
{
mp_size_t l, h, k, i;
limb_t *tabxh, *tabt, c, *tabu;
-
+
if (n <= 2) {
/* return ceil(B^(2*n)/a) - 1 */
/* XXX: could avoid allocation */
//#define DEBUG_DIVNORM_LARGE2
/* subquadratic divnorm */
-static int mp_divnorm_large(bf_context_t *s,
- limb_t *tabq, limb_t *taba, limb_t na,
+static int mp_divnorm_large(bf_context_t *s,
+ limb_t *tabq, limb_t *taba, limb_t na,
const limb_t *tabb, limb_t nb)
{
limb_t *tabb_inv, nq, *tabt, i, n;
assert(nq >= 1);
n = nq;
if (nq < nb)
- n++;
+ n++;
tabb_inv = bf_malloc(s, sizeof(limb_t) * (n + 1));
tabt = bf_malloc(s, sizeof(limb_t) * 2 * (n + 1));
if (!tabb_inv || !tabt)
/* Q=A*B^-1 */
if (mp_mul(s, tabt, tabb_inv, n + 1, taba + na - (n + 1), n + 1))
goto fail;
-
+
for(i = 0; i < nq + 1; i++)
tabq[i] = tabt[i + 2 * (n + 1) - (nq + 1)];
#ifdef DEBUG_DIVNORM_LARGE
bf_free(s, tabt);
bf_free(s, tabb_inv);
tabb_inv = NULL;
-
+
/* R=A-B*Q */
tabt = bf_malloc(s, sizeof(limb_t) * (na + 1));
if (!tabt)
bf_t tmp, *r1 = NULL;
limb_t a_len, b_len, precl;
limb_t *a_tab, *b_tab;
-
+
a_len = a->len;
b_len = b->len;
-
+
if ((flags & BF_RND_MASK) == BF_RNDF) {
/* faithful rounding does not require using the full inputs */
precl = (prec + 2 + LIMB_BITS - 1) / LIMB_BITS;
}
a_tab = a->tab + a->len - a_len;
b_tab = b->tab + b->len - b_len;
-
+
#ifdef USE_FFT_MUL
if (b_len >= FFT_MUL_THRESHOLD) {
int mul_flags = 0;
if (bf_resize(r, a_len + b_len)) {
#ifdef USE_FFT_MUL
fail:
-#endif
+#endif
bf_set_nan(r);
ret = BF_ST_MEM_ERROR;
goto done;
slimb_t i;
limb_t v;
int k;
-
+
for(i = 0; i < a->len; i++) {
v = a->tab[i];
if (v != 0) {
bf_context_t *s = r->ctx;
int ret, r_sign;
limb_t n, nb, precl;
-
+
r_sign = a->sign ^ b->sign;
if (a->expn >= BF_EXP_INF || b->expn >= BF_EXP_INF) {
if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) {
precl = (prec + 2 + LIMB_BITS - 1) / LIMB_BITS;
nb = b->len;
n = bf_max(a->len, precl);
-
+
{
limb_t *taba, na;
slimb_t d;
-
+
na = n + nb;
taba = bf_malloc(s, (na + 1) * sizeof(limb_t));
if (!taba)
return BF_ST_MEM_ERROR;
}
-/* division and remainder.
-
+/* division and remainder.
+
rnd_mode is the rounding mode for the quotient. The additional
rounding mode BF_RND_EUCLIDIAN is supported.
bf_t b1_s, *b1 = &b1_s;
int q_sign, ret;
BOOL is_ceil, is_rndn;
-
+
assert(q != a && q != b);
assert(r != a && r != b);
assert(q != r);
-
+
if (a->len == 0 || b->len == 0) {
bf_set_zero(q, 0);
if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) {
a1->tab = a->tab;
a1->len = a->len;
a1->sign = 0;
-
+
b1->expn = b->expn;
b1->tab = b->tab;
b1->len = b->len;
{
bf_t q_s, *q = &q_s;
int ret;
-
+
bf_init(r->ctx, q);
ret = bf_divrem(q, r, a, b, prec, flags, rnd_mode);
bf_delete(q);
{
bf_t q_s, *q = &q_s;
int ret;
-
+
bf_init(r->ctx, q);
ret = bf_divrem(q, r, a, b, prec, flags, rnd_mode);
bf_get_limb(pq, q, BF_GET_INT_MOD);
static limb_t mp_sqrtrem1(limb_t *pr, limb_t a)
{
limb_t s1, r1, s, r, q, u, num;
-
+
/* use a table for the 16 -> 8 bit sqrt */
s1 = sqrt_table[(a >> (LIMB_BITS - 8)) - 64];
r1 = (a >> (LIMB_BITS - 16)) - s1 * s1;
r1 -= 2 * s1 + 1;
s1++;
}
-
+
/* one iteration to get a 32 -> 16 bit sqrt */
num = (r1 << 8) | ((a >> (LIMB_BITS - 32 + 8)) & 0xff);
q = num / (2 * s1); /* q <= 2^8 */
limb_t *tmp_buf, limb_t *prh)
{
limb_t l, h, rh, ql, qh, c, i;
-
+
if (n == 1) {
*prh = mp_sqrtrem2(tabs, taba);
return 0;
mp_print_str_h("r1", taba + 2 * l, h, qh);
mp_print_str_h("r2", taba + l, n, qh);
#endif
-
+
/* the remainder is in taba + 2 * l. Its high bit is in qh */
if (qh) {
mp_sub(taba + 2 * l, taba + 2 * l, tabs + l, h, 0);
mp_print_str_h("q", tabs, l, qh);
mp_print_str_h("u", taba + l, h, rh);
#endif
-
+
mp_add_ui(tabs + l, qh, h);
#ifdef DEBUG_SQRTREM
mp_print_str_h("s2", tabs, n, sh);
#endif
-
+
/* q = qh, tabs[l - 1 ... 0], r = taba[n - 1 ... l] */
/* subtract q^2. if qh = 1 then q = B^l, so we can take shortcuts */
if (qh) {
int bf_sqrtrem(bf_t *r, bf_t *rem1, const bf_t *a)
{
int ret;
-
+
if (a->len == 0) {
if (a->expn == BF_EXP_NAN) {
bf_set_nan(r);
ret = BF_ST_INVALID_OP;
} else {
bf_t rem_s, *rem;
-
+
bf_sqrt(r, a, (a->expn + 1) / 2, BF_RNDZ);
bf_rint(r, BF_RNDZ);
/* see if the result is exact by computing the remainder */
limb_t *a1;
slimb_t n, n1;
limb_t res;
-
+
/* convert the mantissa to an integer with at least 2 *
prec + 4 bits */
n = (2 * (prec + 2) + 2 * LIMB_BITS - 1) / (2 * LIMB_BITS);
{
bf_t tmp;
int ret;
-
+
if (r == a || r == b) {
bf_init(r->ctx, &tmp);
ret = func(&tmp, a, b, prec, flags);
{
bf_t b;
int ret;
-
+
bf_init(r->ctx, &b);
ret = bf_set_si(&b, b1);
ret |= bf_add(r, a, &b, prec, flags);
bf_flags_t flags)
{
int ret, n_bits, i;
-
+
assert(r != a);
if (b == 0)
return bf_set_ui(r, 1);
{
bf_t a;
int ret;
-
+
#ifdef USE_BF_DEC
if (a1 == 10 && b <= LIMB_DIGITS) {
/* use precomputed powers. We do not round at this point
because we expect the caller to do it */
ret = bf_set_ui(r, mp_pow_dec[b]);
} else
-#endif
+#endif
{
bf_init(r->ctx, &a);
ret = bf_set_ui(&a, a1);
slimb_t l, i, a_bit_offset, b_bit_offset;
limb_t v1, v2, v1_mask, v2_mask, r_mask;
int ret;
-
+
assert(r != a1 && r != b1);
if (a1->expn <= 0)
b_sign = 0; /* minus zero is considered as positive */
else
b_sign = b1->sign;
-
+
if (a_sign) {
a = &a1_s;
bf_init(r->ctx, a);
} else {
b = (bf_t *)b1;
}
-
+
r_sign = bf_logic_op1(a_sign, b_sign, op);
if (op == BF_LOGIC_AND && r_sign == 0) {
/* no need to compute extra zeros for and */
Float64Union u;
int e, ret;
uint64_t m;
-
+
ret = 0;
if (a->expn == BF_EXP_NAN) {
u.u = 0x7ff8000000000000; /* quiet nan */
} else {
bf_t b_s, *b = &b_s;
-
+
bf_init(a->ctx, b);
bf_set(b, a);
if (bf_is_finite(b)) {
Float64Union u;
uint64_t m;
int shift, e, sgn;
-
+
u.d = d;
sgn = u.u >> 63;
e = (u.u >> 52) & ((1 << 11) - 1);
ret = BF_ST_INVALID_OP;
if (a->sign) {
v = (uint32_t)INT32_MAX + 1;
- if (a->expn == 32 &&
+ if (a->expn == 32 &&
(a->tab[a->len - 1] >> (LIMB_BITS - 32)) == v) {
ret = 0;
}
v = INT32_MAX;
}
} else {
- v = get_bits(a->tab, a->len, a->len * LIMB_BITS - a->expn);
+ v = get_bits(a->tab, a->len, a->len * LIMB_BITS - a->expn);
if (a->sign)
v = -v;
ret = 0;
}
} else {
slimb_t bit_pos = a->len * LIMB_BITS - a->expn;
- v = get_bits(a->tab, a->len, bit_pos);
+ v = get_bits(a->tab, a->len, bit_pos);
#if LIMB_BITS == 32
v |= (uint64_t)get_bits(a->tab, a->len, bit_pos + 32) << 32;
#endif
{
int i, k;
limb_t radixl;
-
+
k = digits_per_limb_table[radix - 2];
radixl = radix;
for(i = 1; i < k; i++)
} else {
bf_t T_s, *T = &T_s, *B;
limb_t n1, n2;
-
+
n2 = (((n0 * 2) >> (level + 1)) + 1) / 2;
n1 = n - n2;
// printf("level=%d n0=%ld n1=%ld n2=%ld\n", level, n0, n1, n2);
int pow_tab_len, i, ret;
limb_t radixl;
bf_t *pow_tab;
-
+
radixl = get_limb_radix(radix);
pow_tab_len = ceil_log2(n) + 2; /* XXX: check */
pow_tab = bf_malloc(s, sizeof(pow_tab[0]) * pow_tab_len);
slimb_t pos, expn, int_len, digit_count;
BOOL has_decpt, is_bin_exp;
bf_t a_s, *a;
-
+
*pexponent = 0;
p = str;
if (!(flags & BF_ATOF_NO_NAN_INF) && radix <= 16 &&
goto done;
}
is_neg = 0;
-
+
if (p[0] == '+') {
p++;
p_start = p;
goto done;
}
}
-
+
if (radix == 0)
radix = 10;
if (is_dec) {
goto done;
}
}
-
+
/* reset the next limbs to zero (we prefer to reallocate in the
renormalization) */
memset(a->tab, 0, (pos + 1) * sizeof(limb_t));
} else if (radix_bits) {
/* XXX: may overflow */
if (!is_bin_exp)
- expn *= radix_bits;
+ expn *= radix_bits;
a->expn = expn + (int_len * radix_bits);
a->sign = is_neg;
ret = bf_normalize_and_round(a, prec, flags);
return ret;
}
-/*
+/*
Return (status, n, exp). 'status' is the floating point status. 'n'
- is the parsed number.
+ is the parsed number.
If (flags & BF_ATOF_EXPONENT) and if the radix is not a power of
two, the parsed number is equal to r *
const uint32_t *tab;
limb_t b0, b1;
dlimb_t t;
-
+
if (is_inv) {
tab = inv_log2_radix[radix - 2];
#if LIMB_BITS == 32
{
limb_t n1, n2, q_prec;
int ret;
-
+
assert(n >= 1);
if (n == 1) {
out[0] = get_bits(a->tab, a->len, a->len * LIMB_BITS - a->expn);
q_prec = n1 * radixl_bits;
ret |= bf_mul(&Q, a, B_inv, q_prec, BF_RNDN);
ret |= bf_rint(&Q, BF_RNDZ);
-
+
ret |= bf_mul(&R, &Q, B, BF_PREC_INF, BF_RNDZ);
ret |= bf_sub(&R, a, &R, BF_PREC_INF, BF_RNDZ);
limb_t r_len;
bf_t *pow_tab;
int i, pow_tab_len, ret;
-
+
r_len = r->len;
pow_tab_len = (ceil_log2(r_len) + 2) * 2; /* XXX: check */
pow_tab = bf_malloc(s, sizeof(pow_tab[0]) * pow_tab_len);
slimb_t E, e, prec, extra_bits, ziv_extra_bits, prec0;
bf_t B_s, *B = &B_s;
int e_sign, ret, res;
-
+
if (a->len == 0) {
/* zero case */
*pE = 0;
}
// bf_print_str("a", a);
// printf("E=%ld P=%ld radix=%d\n", E, P, radix);
-
+
for(;;) {
e = P - E;
e_sign = 0;
bf_context_t *ctx = a2->ctx;
DynBuf s_s, *s = &s_s;
int radix_bits;
-
+
// bf_print_str("ftoa", a2);
// printf("radix=%d\n", radix);
dbuf_init2(s, ctx, bf_dbuf_realloc);
a->len = a2->len;
a->expn = a2->expn;
a->sign = 0;
-
+
/* one more digit for the rounding */
n = 1 + bf_mul_log2_radix(bf_max(a->expn, 0), radix, TRUE, TRUE);
n_digits = n + prec;
n = ceil_div(a1->expn, radix_bits);
} else {
bf_t a_s, *a = &a_s;
-
+
/* make a positive number */
a->tab = a2->tab;
a->len = a2->len;
a->expn = a2->expn;
a->sign = 0;
-
+
if (fmt == BF_FTOA_FORMAT_FIXED) {
n_digits = prec;
n_max = n_digits;
} else {
slimb_t n_digits_max, n_digits_min;
-
+
assert(prec != BF_PREC_INF);
n_digits = 1 + bf_mul_log2_radix(prec, radix, TRUE, TRUE);
/* max number of digits for non exponential
n_max = n_digits + 4;
if (fmt == BF_FTOA_FORMAT_FREE_MIN) {
bf_t b_s, *b = &b_s;
-
+
/* find the minimum number of digits by
dichotomy. */
/* XXX: inefficient */
bf_t T1_s, *T1 = &T1_s;
bf_t P1_s, *P1 = &P1_s;
bf_t Q1_s, *Q1 = &Q1_s;
-
+
m = n1 + ((n2 - n1) >> 1);
bf_const_log2_rec(T, P, Q, n1, m, TRUE);
bf_init(s, T1);
if (a == (b - 1)) {
bf_t T0, T1;
-
+
bf_init(s, &T0);
bf_init(s, &T1);
bf_set_ui(G, 2 * b - 1);
bf_delete(&T1);
} else {
bf_t P2, Q2, G2;
-
+
bf_init(s, &P2);
bf_init(s, &Q2);
bf_init(s, &G2);
c = (a + b) / 2;
chud_bs(P, Q, G, a, c, 1, prec);
chud_bs(&P2, &Q2, &G2, c, b, need_g, prec);
-
+
/* Q = Q1 * Q2 */
/* G = G1 * G2 */
/* P = P1 * Q2 + P2 * G1 */
bf_init(s, &G);
chud_bs(&P, Q, &G, 0, n, 0, BF_PREC_INF);
-
+
bf_mul_ui(&G, Q, CHUD_A, prec1, BF_RNDN);
bf_add(&P, &G, &P, prec1, BF_RNDN);
bf_div(Q, Q, &P, prec1, BF_RNDF);
-
+
bf_set_ui(&P, CHUD_C);
bf_sqrt(&G, &P, prec1, BF_RNDF);
bf_mul_ui(&G, &G, (uint64_t)CHUD_C / 12, prec1, BF_RNDF);
{
int rnd_mode, ret;
slimb_t prec1, ziv_extra_bits;
-
+
rnd_mode = flags & BF_RND_MASK;
if (rnd_mode == BF_RNDF) {
/* no need to iterate */
bf_context_t *s = r->ctx;
bf_t T_s, *T = &T_s;
slimb_t n, K, l, i, prec1;
-
+
assert(r != a);
/* argument reduction:
/* reduce the range of T */
bf_mul_2exp(T, -K, BF_PREC_INF, BF_RNDZ);
-
+
/* Taylor expansion around zero :
- 1 + x + x^2/2 + ... + x^n/n!
+ 1 + x + x^2/2 + ... + x^n/n!
= (1 + x * (1 + x/2 * (1 + ... (x/n))))
*/
{
bf_t U_s, *U = &U_s;
-
+
bf_init(s, U);
bf_set_ui(r, 1);
for(i = l ; i >= 1; i--) {
bf_delete(U);
}
bf_delete(T);
-
+
/* undo the range reduction */
for(i = 0; i < K; i++) {
bf_mul(r, r, r, prec1, BF_RNDN | BF_FLAG_EXT_EXP);
bf_t T_s, *T = &T_s;
bf_t log2_s, *log2 = &log2_s;
slimb_t e_min, e_max;
-
+
if (a_high->expn <= 0)
return 0;
e_min = -e_max + 3;
if (flags & BF_FLAG_SUBNORMAL)
e_min -= (prec - 1);
-
+
bf_init(s, T);
bf_init(s, log2);
bf_const_log2(log2, LIMB_BITS, BF_RNDU);
bf_mul_si(T, log2, e_min - 2, LIMB_BITS, BF_RNDD);
if (bf_cmp_lt(a_high, T)) {
int rnd_mode = flags & BF_RND_MASK;
-
+
/* underflow */
bf_delete(T);
bf_delete(log2);
ret = check_exp_underflow_overflow(s, r, a, a, prec, flags);
if (ret)
return ret;
- if (a->expn < 0 && (-a->expn) >= (prec + 2)) {
+ if (a->expn < 0 && (-a->expn) >= (prec + 2)) {
/* small argument case: result = 1 + epsilon * sign(x) */
bf_set_ui(r, 1);
return bf_add_epsilon(r, r, -(prec + 2), a->sign, prec, flags);
}
-
+
return bf_ziv_rounding(r, a, prec, flags, bf_exp_internal, NULL);
}
bf_t U_s, *U = &U_s;
bf_t V_s, *V = &V_s;
slimb_t n, prec1, l, i, K;
-
+
assert(r != a);
bf_init(s, T);
T->expn = 0;
/* U= ~ 2/3 */
bf_init(s, U);
- bf_set_ui(U, 0xaaaaaaaa);
+ bf_set_ui(U, 0xaaaaaaaa);
U->expn = 0;
if (bf_cmp_lt(T, U)) {
T->expn++;
/* XXX: precision analysis */
/* number of iterations for argument reduction 2 */
- K = bf_isqrt((prec + 1) / 2);
+ K = bf_isqrt((prec + 1) / 2);
/* order of Taylor expansion */
- l = prec / (2 * K) + 1;
+ l = prec / (2 * K) + 1;
/* precision of the intermediate computations */
prec1 = prec + K + 2 * l + 32;
bf_init(s, U);
bf_init(s, V);
-
+
/* Note: cancellation occurs here, so we use more precision (XXX:
reduce the precision by computing the exact cancellation) */
- bf_add_si(T, T, -1, BF_PREC_INF, BF_RNDN);
+ bf_add_si(T, T, -1, BF_PREC_INF, BF_RNDN);
/* argument reduction 2 */
for(i = 0; i < K; i++) {
bf_init(s, Y2);
/* compute ln(1+x) = ln((1+y)/(1-y)) with y=x/(2+x)
- = y + y^3/3 + ... + y^(2*l + 1) / (2*l+1)
+ = y + y^3/3 + ... + y^(2*l + 1) / (2*l+1)
with Y=Y^2
= y*(1+Y/3+Y^2/5+...) = y*(1+Y*(1/3+Y*(1/5 + ...)))
*/
/* multiplication by 2 for the Taylor expansion and undo the
argument reduction 2*/
bf_mul_2exp(r, K + 1, BF_PREC_INF, BF_RNDZ);
-
+
/* undo the argument reduction 1 */
bf_const_log2(T, prec1, BF_RNDF);
bf_mul_si(T, T, n, prec1, BF_RNDN);
bf_add(r, r, T, prec1, BF_RNDN);
-
+
bf_delete(T);
return BF_ST_INEXACT;
}
{
bf_context_t *s = r->ctx;
bf_t T_s, *T = &T_s;
-
+
assert(r != a);
if (a->len == 0) {
if (a->expn == BF_EXP_NAN) {
limb_t prec1;
int ret;
slimb_t y1;
-
+
bf_get_limb(&y1, y, 0);
if (y1 < 0)
y1 = -y1;
bf_t T_s, *T = &T_s;
slimb_t e, i, er;
limb_t v;
-
+
/* x = m*2^e with m odd integer */
e = bf_get_exp_min(x);
/* fast check on the exponent */
BOOL y_is_int, y_is_odd;
int r_sign, ret, rnd_mode;
slimb_t y_emin;
-
+
if (x->len == 0 || y->len == 0) {
if (y->expn == BF_EXP_ZERO) {
/* pow(x, 0) = 1 */
bf_t al_s, *al = &al_s;
bf_t ah_s, *ah = &ah_s;
limb_t precl = LIMB_BITS;
-
+
bf_init(s, al);
bf_init(s, ah);
/* compute bounds of log(abs(x)) * y with a low precision */
if (ret)
goto done;
}
-
+
if (y_is_int) {
slimb_t T_bits, e;
int_pow:
bf_t r_s, *r = &r_s;
slimb_t K, prec1, i, l, mod, prec2;
int is_neg;
-
+
assert(c != a && s != a);
bf_init(s1, T);
bf_init(s1, U);
bf_init(s1, r);
-
+
/* XXX: precision analysis */
K = bf_isqrt(prec / 2);
l = prec / (2 * K) + 1;
prec1 = prec + 2 * K + l + 8;
-
+
/* after the modulo reduction, -pi/4 <= T <= pi/4 */
if (a->expn <= -1) {
/* abs(a) <= 0.25: no modulo reduction needed */
}
mod &= 3;
}
-
+
is_neg = T->sign;
-
+
/* compute cosm1(x) = cos(x) - 1 */
bf_mul(T, T, T, prec1, BF_RNDN);
bf_mul_2exp(T, -2 * K, BF_PREC_INF, BF_RNDZ);
-
+
/* Taylor expansion:
-x^2/2 + x^4/4! - x^6/6! + ...
*/
return bf_add_epsilon(r, r, e, 1, prec, flags);
}
}
-
+
return bf_ziv_rounding(r, a, prec, flags, bf_cos_internal, NULL);
}
bf_context_t *s = r->ctx;
bf_t T_s, *T = &T_s;
limb_t prec1;
-
+
/* XXX: precision analysis */
prec1 = prec + 8;
bf_init(s, T);
return bf_add_epsilon(r, r, e, a->sign, prec, flags);
}
}
-
+
return bf_ziv_rounding(r, a, prec, flags, bf_tan_internal, NULL);
}
bf_t X2_s, *X2 = &X2_s;
int cmp_1;
slimb_t prec1, i, K, l;
-
+
/* XXX: precision analysis */
K = bf_isqrt((prec + 1) / 2);
l = prec / (2 * K) + 1;
prec1 = prec + K + 2 * l + 32;
// printf("prec=%d K=%d l=%d prec1=%d\n", (int)prec, (int)K, (int)l, (int)prec1);
-
+
bf_init(s, T);
cmp_1 = (a->expn >= 1); /* a >= 1 */
if (cmp_1) {
bf_div(T, T, V, prec1, BF_RNDN);
}
- /* Taylor series:
- x - x^3/3 + ... + (-1)^ l * y^(2*l + 1) / (2*l+1)
+ /* Taylor series:
+ x - x^3/3 + ... + (-1)^ l * y^(2*l + 1) / (2*l+1)
*/
bf_mul(X2, T, T, prec1, BF_RNDN);
bf_set_ui(r, 0);
/* undo the argument reduction */
bf_mul_2exp(r, K, BF_PREC_INF, BF_RNDZ);
-
+
bf_delete(U);
bf_delete(V);
bf_delete(X2);
T->sign = (i < 0);
bf_add(r, T, r, prec1, BF_RNDN);
}
-
+
bf_delete(T);
return BF_ST_INEXACT;
}
bf_context_t *s = r->ctx;
bf_t T_s, *T = &T_s;
int res;
-
+
if (a->len == 0) {
if (a->expn == BF_EXP_NAN) {
bf_set_nan(r);
return 0;
}
}
-
+
bf_init(s, T);
bf_set_ui(T, 1);
res = bf_cmpu(a, T);
return bf_add_epsilon(r, r, e, 1 - a->sign, prec, flags);
}
}
-
+
return bf_ziv_rounding(r, a, prec, flags, bf_atan_internal, (void *)FALSE);
}
bf_t T_s, *T = &T_s;
limb_t prec1;
int ret;
-
+
if (y->expn == BF_EXP_NAN || x->expn == BF_EXP_NAN) {
bf_set_nan(r);
return 0;
BOOL is_acos = (BOOL)(intptr_t)opaque;
bf_t T_s, *T = &T_s;
limb_t prec1, prec2;
-
- /* asin(x) = atan(x/sqrt(1-x^2))
+
+ /* asin(x) = atan(x/sqrt(1-x^2))
acos(x) = pi/2 - asin(x) */
prec1 = prec + 8;
/* increase the precision in x^2 to compensate the cancellation in
bf_set_nan(r);
return BF_ST_INVALID_OP;
}
-
+
/* small argument case: result = x+r(x) with r(x) = x^3/6 +
O(X^5). We assume r(x) < 2^(3*EXP(x) - 2). */
if (a->expn < 0) {
bf_set_zero(r, 0);
return 0;
}
-
+
return bf_ziv_rounding(r, a, prec, flags, bf_asin_internal, (void *)TRUE);
}
/* division and remainder by 10^shift */
#define fast_shr_rem_dec(q, r, a, shift) q = fast_shr_dec(a, shift), r = a - q * mp_pow_dec[shift]
-
-limb_t mp_add_dec(limb_t *res, const limb_t *op1, const limb_t *op2,
+
+limb_t mp_add_dec(limb_t *res, const limb_t *op1, const limb_t *op2,
mp_size_t n, limb_t carry)
{
limb_t base = BF_DEC_BASE;
v = op1[i];
a = v + op2[i] + k - base;
k = a <= v;
- if (!k)
+ if (!k)
a += base;
res[i]=a;
}
v = tab[i];
a = v + k - base;
k = a <= v;
- if (!k)
+ if (!k)
a += base;
tab[i] = a;
if (k == 0)
return k;
}
-limb_t mp_sub_dec(limb_t *res, const limb_t *op1, const limb_t *op2,
+limb_t mp_sub_dec(limb_t *res, const limb_t *op1, const limb_t *op2,
mp_size_t n, limb_t carry)
{
limb_t base = BF_DEC_BASE;
limb_t base = BF_DEC_BASE;
mp_size_t i;
limb_t k, v, a;
-
+
k=b;
for(i=0;i<n;i++) {
v = tab[i];
}
/* taba[] = taba[] * b + l. 0 <= b, l <= base - 1. Return the high carry */
-limb_t mp_mul1_dec(limb_t *tabr, const limb_t *taba, mp_size_t n,
+limb_t mp_mul1_dec(limb_t *tabr, const limb_t *taba, mp_size_t n,
limb_t b, limb_t l)
{
mp_size_t i;
}
/* size of the result : op1_size + op2_size. */
-void mp_mul_basecase_dec(limb_t *result,
- const limb_t *op1, mp_size_t op1_size,
- const limb_t *op2, mp_size_t op2_size)
+void mp_mul_basecase_dec(limb_t *result,
+ const limb_t *op1, mp_size_t op1_size,
+ const limb_t *op2, mp_size_t op2_size)
{
mp_size_t i;
limb_t r;
-
+
result[op1_size] = mp_mul1_dec(result, op1, op1_size, op2[0], 0);
for(i=1;i<op2_size;i++) {
/* taba[] = (taba[] + r*base^na) / b. 0 <= b < base. 0 <= r <
b. Return the remainder. */
-limb_t mp_div1_dec(limb_t *tabr, const limb_t *taba, mp_size_t na,
+limb_t mp_div1_dec(limb_t *tabr, const limb_t *taba, mp_size_t na,
limb_t b, limb_t r)
{
limb_t base = BF_DEC_BASE;
}
if (r)
r = 1;
- } else
+ } else
#endif
if (na >= UDIV1NORM_THRESHOLD) {
shift = clz(b);
#define DIV_STATIC_ALLOC_LEN 16
-/* return q = a / b and r = a % b.
+/* return q = a / b and r = a % b.
taba[na] must be allocated if tabb1[nb - 1] < B / 2. tabb1[nb - 1]
must be != zero. na must be >= nb. 's' can be NULL if tabb1[nb - 1]
*/
/* XXX: optimize */
static int mp_div_dec(bf_context_t *s, limb_t *tabq,
- limb_t *taba, mp_size_t na,
+ limb_t *taba, mp_size_t na,
const limb_t *tabb1, mp_size_t nb)
{
limb_t base = BF_DEC_BASE;
limb_t r, mult, t0, t1, a, c, q, v, *tabb;
mp_size_t i, j;
limb_t static_tabb[DIV_STATIC_ALLOC_LEN];
-
+
#ifdef DEBUG_DIV_SLOW
mp_print_str_dec("a", taba, na);
mp_print_str_dec("b", tabb1, nb);
}
/* divide by 10^shift */
-static limb_t mp_shr_dec(limb_t *tab_r, const limb_t *tab, mp_size_t n,
+static limb_t mp_shr_dec(limb_t *tab_r, const limb_t *tab, mp_size_t n,
limb_t shift, limb_t high)
{
mp_size_t i;
}
/* multiply by 10^shift */
-static limb_t mp_shl_dec(limb_t *tab_r, const limb_t *tab, mp_size_t n,
+static limb_t mp_shl_dec(limb_t *tab_r, const limb_t *tab, mp_size_t n,
limb_t shift, limb_t low)
{
mp_size_t i;
limb_t *tmp_buf)
{
limb_t l, h, rh, ql, qh, c, i;
-
+
if (n == 1)
return mp_sqrtrem2_dec(tabs, taba);
#ifdef DEBUG_SQRTREM_DEC
mp_print_str_h_dec("r1", taba + 2 * l, h, qh);
mp_print_str_h_dec("r2", taba + l, n, qh);
#endif
-
+
/* the remainder is in taba + 2 * l. Its high bit is in qh */
if (qh) {
mp_sub_dec(taba + 2 * l, taba + 2 * l, tabs + l, h, 0);
mp_print_str_h_dec("q", tabs, l, qh);
mp_print_str_h_dec("u", taba + l, h, rh);
#endif
-
+
mp_add_ui_dec(tabs + l, qh, h);
#ifdef DEBUG_SQRTREM_DEC
mp_print_str_dec("s2", tabs, n);
#endif
-
+
/* q = qh, tabs[l - 1 ... 0], r = taba[n - 1 ... l] */
/* subtract q^2. if qh = 1 then q = B^l, so we can take shortcuts */
if (qh) {
limb_t a0, a1;
int shift;
slimb_t i;
-
+
i = floor_div(pos, LIMB_DIGITS);
shift = pos - i * LIMB_DIGITS;
if (i >= 0 && i < len)
{
int add_one, inexact;
limb_t digit1, digit0;
-
+
// bfdec_print_str("get_rnd_add", r);
if (rnd_mode == BF_RNDF) {
digit0 = 1; /* faithful rounding does not honor the INEXACT flag */
/* get the digit at 'prec' */
digit1 = get_digit(r->tab, l, l * LIMB_DIGITS - 1 - prec);
inexact = (digit1 | digit0) != 0;
-
+
add_one = 0;
switch(rnd_mode) {
case BF_RNDZ:
default:
abort();
}
-
+
if (inexact)
*pret |= BF_ST_INEXACT;
return add_one;
e_range = (limb_t)1 << (bf_get_exp_bits(flags) - 1);
e_min = -e_range + 3;
e_max = e_range;
-
+
if (flags & BF_FLAG_RADPNT_PREC) {
/* 'prec' is the precision after the decimal point */
if (prec1 != BF_PREC_INF)
} else {
prec = prec1;
}
-
+
/* round to prec bits */
rnd_mode = flags & BF_RND_MASK;
ret = 0;
add_one = bfdec_get_rnd_add(&ret, r, l, prec, rnd_mode);
-
+
if (prec <= 0) {
if (add_one) {
bfdec_resize(r, 1); /* cannot fail because r is non zero */
}
} else if (add_one) {
limb_t carry;
-
+
/* add one starting at digit 'prec - 1' */
bit_pos = l * LIMB_DIGITS - 1 - (prec - 1);
pos = bit_pos / LIMB_DIGITS;
r->expn++;
}
}
-
+
/* check underflow */
if (unlikely(r->expn < e_min)) {
if (flags & BF_FLAG_SUBNORMAL) {
return ret;
}
}
-
+
/* check overflow */
if (unlikely(r->expn > e_max)) {
bfdec_set_inf(r, r->sign);
ret |= BF_ST_OVERFLOW | BF_ST_INEXACT;
return ret;
}
-
+
/* keep the bits starting at 'prec - 1' */
bit_pos = l * LIMB_DIGITS - 1 - (prec - 1);
i = floor_div(bit_pos, LIMB_DIGITS);
{
limb_t l, v;
int shift, ret;
-
+
// bfdec_print_str("bf_renorm", r);
l = r->len;
while (l > 0 && r->tab[l - 1] == 0)
limb_t *b1_tab;
int b_shift;
mp_size_t b1_len;
-
+
d = a->expn - b->expn;
/* XXX: not efficient in time and memory if the precision is
r->tab[i] = 0;
for(i = 0; i < a->len; i++)
r->tab[a_offset + i] = a->tab[i];
-
+
b_shift = d % LIMB_DIGITS;
if (b_shift == 0) {
b1_len = b->len;
mp_pow_dec[LIMB_DIGITS - b_shift];
}
b_offset = r_len - (b->len + (d + LIMB_DIGITS - 1) / LIMB_DIGITS);
-
+
if (is_sub) {
carry = mp_sub_dec(r->tab + b_offset, r->tab + b_offset,
b1_tab, b1_len, 0);
bfdec_t tmp, *r1 = NULL;
limb_t a_len, b_len;
limb_t *a_tab, *b_tab;
-
+
a_len = a->len;
b_len = b->len;
a_tab = a->tab;
b_tab = b->tab;
-
+
if (r == a || r == b) {
bfdec_init(r->ctx, &tmp);
r1 = r;
{
bfdec_t b;
int ret;
-
+
bfdec_init(r->ctx, &b);
ret = bfdec_set_si(&b, b1);
ret |= bfdec_add(r, a, &b, prec, flags);
{
int ret, r_sign;
limb_t n, nb, precl;
-
+
r_sign = a->sign ^ b->sign;
if (a->expn >= BF_EXP_INF || b->expn >= BF_EXP_INF) {
if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) {
precl = (prec + 2 + LIMB_DIGITS - 1) / LIMB_DIGITS;
}
n = bf_max(a->len, precl);
-
+
{
limb_t *taba, na, i;
slimb_t d;
-
+
na = n + nb;
taba = bf_malloc(r->ctx, (na + 1) * sizeof(limb_t));
if (!taba)
}
}
-/* division and remainder.
-
+/* division and remainder.
+
rnd_mode is the rounding mode for the quotient. The additional
rounding mode BF_RND_EUCLIDIAN is supported.
bfdec_t r1_s, *r1 = &r1_s;
int q_sign, res;
BOOL is_ceil, is_rndn;
-
+
assert(q != a && q != b);
assert(r != a && r != b);
assert(q != r);
-
+
if (a->len == 0 || b->len == 0) {
bfdec_set_zero(q, 0);
if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) {
a1->tab = a->tab;
a1->len = a->len;
a1->sign = 0;
-
+
b1->expn = b->expn;
b1->tab = b->tab;
b1->len = b->len;
goto fail;
// bfdec_print_str("q", q);
// bfdec_print_str("r", r);
-
+
if (r->len != 0) {
if (is_rndn) {
bfdec_init(s, r1);
{
bfdec_t q_s, *q = &q_s;
int ret;
-
+
bfdec_init(r->ctx, q);
ret = bfdec_divrem(q, r, a, b, prec, flags, rnd_mode);
bfdec_delete(q);
int bfdec_pow_ui(bfdec_t *r, const bfdec_t *a, limb_t b)
{
int ret, n_bits, i;
-
+
assert(r != a);
if (b == 0)
return bfdec_set_ui(r, 1);
typedef struct BFNTTState {
bf_context_t *ctx;
-
+
/* used for mul_mod_fast() */
limb_t ntt_mods_div[NB_MODS];
return r;
}
-/* return (r0+r1*B) mod m
- precondition: 0 <= r0+r1*B < 2^(64+NTT_MOD_LOG2_MIN)
+/* return (r0+r1*B) mod m
+ precondition: 0 <= r0+r1*B < 2^(64+NTT_MOD_LOG2_MIN)
*/
-static inline limb_t mod_fast(dlimb_t r,
+static inline limb_t mod_fast(dlimb_t r,
limb_t m, limb_t m_inv)
{
limb_t a1, q, t0, r1, r0;
-
+
a1 = r >> NTT_MOD_LOG2_MIN;
-
+
q = ((dlimb_t)a1 * m_inv) >> LIMB_BITS;
r = r - (dlimb_t)q * m - m * 2;
r1 = r >> LIMB_BITS;
return r0;
}
-/* faster version using precomputed modulo inverse.
+/* faster version using precomputed modulo inverse.
precondition: 0 <= a * b < 2^(64+NTT_MOD_LOG2_MIN) */
-static inline limb_t mul_mod_fast(limb_t a, limb_t b,
+static inline limb_t mul_mod_fast(limb_t a, limb_t b,
limb_t m, limb_t m_inv)
{
dlimb_t r;
/* Faster version used when the multiplier is constant. 0 <= a < 2^64,
0 <= b < m. */
-static inline limb_t mul_mod_fast2(limb_t a, limb_t b,
+static inline limb_t mul_mod_fast2(limb_t a, limb_t b,
limb_t m, limb_t b_inv)
{
limb_t r, q;
/* Faster version used when the multiplier is constant. 0 <= a < 2^64,
0 <= b < m. Let r = a * b mod m. The return value is 'r' or 'r +
m'. */
-static inline limb_t mul_mod_fast3(limb_t a, limb_t b,
+static inline limb_t mul_mod_fast3(limb_t a, limb_t b,
limb_t m, limb_t b_inv)
{
limb_t r, q;
__m256d m_inv, mf, m2f, c, a0, a1, b0, b1;
limb_t m;
int l;
-
+
m = ntt_mods[m_idx];
-
+
m_inv = _mm256_set1_pd(1.0 / (double)m);
mf = _mm256_set1_pd(m);
m2f = _mm256_set1_pd(m * 2);
tmp = tab_in;
tab_in = tab_out;
tab_out = tmp;
-
+
nb_blocks = n / 4;
fft_per_block = 4;
{
limb_t i, c_inv, n, m;
__m256d m_inv, mf, a, b, c;
-
+
m = ntt_mods[m_idx];
c_inv = s->ntt_len_inv[m_idx][k_tot][0];
m_inv = _mm256_set1_pd(1.0 / (double)m);
limb_t i, c2, c3, c4;
__m256d c, c_mul, a0, mf, m_inv;
assert(n >= 2);
-
+
mf = _mm256_set1_pd(m);
m_inv = _mm256_set1_pd(1.0 / (double)m);
limb_t nb_blocks, fft_per_block, p, k, n, stride_in, i, j, m, m2;
NTTLimb *tab_in, *tab_out, *tmp, a0, a1, b0, b1, c, *trig, c_inv;
int l;
-
+
m = ntt_mods[m_idx];
m2 = 2 * m;
n = (limb_t)1 << fft_len_log2;
tab_out = tmp;
}
/* no twiddle in last step */
- tab_out = out_buf;
+ tab_out = out_buf;
for(k = 0; k < stride_in; k++) {
a0 = tab_in[k];
a1 = tab_in[k + stride_in];
int k_tot, int m_idx)
{
limb_t i, norm, norm_inv, a, n, m, m_inv;
-
+
m = ntt_mods[m_idx];
m_inv = s->ntt_mods_div[m_idx];
norm = s->ntt_len_inv[m_idx][k_tot][0];
limb_t n, limb_t c_mul, limb_t m, limb_t m_inv)
{
limb_t i, c0, c_mul_inv;
-
+
c0 = 1;
c_mul_inv = init_mul_mod_fast2(c_mul, m);
for(i = 0; i < n; i++) {
{
NTTLimb *tab;
limb_t i, n2, c, c_mul, m, c_mul_inv;
-
+
if (k > NTT_TRIG_K_MAX)
return NULL;
{
limb_t i, j, c_mul, c0, m, m_inv, strip_len, l;
NTTLimb *buf2, *buf3;
-
+
buf2 = NULL;
buf3 = ntt_malloc(s, sizeof(NTTLimb) * n1);
if (!buf3)
mul_trig(buf2 + l * n1, n1, c_mul, m, m_inv);
c_mul = mul_mod_fast(c_mul, c0, m, m_inv);
}
-
+
for(i = 0; i < n1; i++) {
for(l = 0; l < strip_len; l++) {
buf1[i * n2 + (j + l)] = buf2[i + l *n1];
{
limb_t n1, n2, i;
int k1, k2;
-
+
if (k <= NTT_TRIG_K_MAX) {
k1 = k;
} else {
k2 = k - k1;
n1 = (limb_t)1 << k1;
n2 = (limb_t)1 << k2;
-
+
if (ntt_fft_partial(s, buf1, k1, k2, n1, n2, 0, m_idx))
return -1;
if (ntt_fft_partial(s, buf2, k1, k2, n1, n2, 0, m_idx))
dlimb_t a, b;
int j, shift;
limb_t base_mask1, a0, a1, a2, r, m, m_inv;
-
+
#if 0
for(i = 0; i < a_len; i++) {
printf("%" PRId64 ": " FMT_LIMB "\n",
(int64_t)i, taba[i]);
}
-#endif
+#endif
memset(tabr, 0, sizeof(NTTLimb) * fft_len * nb_mods);
shift = dpl & (LIMB_BITS - 1);
if (shift == 0)
slimb_t i, len, pos;
int j, k, l, shift, n_limb1, p;
dlimb_t t;
-
+
j = NB_MODS * (NB_MODS - 1) / 2 - nb_mods * (nb_mods - 1) / 2;
mods_cr_vec = s->ntt_mods_cr_vec + j;
mf = s->ntt_mods_vec + NB_MODS - nb_mods;
m_inv = s->ntt_mods_inv_vec + NB_MODS - nb_mods;
-
+
shift = dpl & (LIMB_BITS - 1);
if (shift == 0)
base_mask1 = -1;
else
base_mask1 = ((limb_t)1 << shift) - 1;
n_limb1 = ((unsigned)dpl - 1) / LIMB_BITS;
- for(j = 0; j < NB_MODS; j++)
+ for(j = 0; j < NB_MODS; j++)
carry[j] = 0;
- for(j = 0; j < NB_MODS; j++)
+ for(j = 0; j < NB_MODS; j++)
u[j] = 0; /* avoid warnings */
memset(tabr, 0, sizeof(limb_t) * r_len);
fft_len = (limb_t)1 << fft_len_log2;
}
}
y[j].v = ntt_mod1(y[j].v, mf[j]);
-
+
for(p = 0; p < VEC_LEN; p++) {
/* back to normal representation */
u[0] = (int64_t)y[nb_mods - 1].d[p];
l++;
}
/* XXX: for nb_mods = 5, l should be 4 */
-
+
/* last step adds the carry */
r = (int64_t)y[0].d[p];
for(k = 0; k < l; k++) {
}
printf("\n");
#endif
-
+
/* write the digits */
pos = i * dpl;
for(j = 0; j < n_limb1; j++) {
slimb_t i, len, pos;
int j, k, l, shift, n_limb1;
dlimb_t t;
-
+
j = NB_MODS * (NB_MODS - 1) / 2 - nb_mods * (nb_mods - 1) / 2;
mods_cr = ntt_mods_cr + j;
mods_cr_inv = s->ntt_mods_cr_inv + j;
else
base_mask1 = ((limb_t)1 << shift) - 1;
n_limb1 = ((unsigned)dpl - 1) / LIMB_BITS;
- for(j = 0; j < NB_MODS; j++)
+ for(j = 0; j < NB_MODS; j++)
carry[j] = 0;
- for(j = 0; j < NB_MODS; j++)
+ for(j = 0; j < NB_MODS; j++)
u[j] = 0; /* avoid warnings */
memset(tabr, 0, sizeof(limb_t) * r_len);
fft_len = (limb_t)1 << fft_len_log2;
m = mods[k];
/* Note: there is no overflow in the sub_mod() because
the modulos are sorted by increasing order */
- y[k] = mul_mod_fast2(y[k] - y[j] + m,
+ y[k] = mul_mod_fast2(y[k] - y[j] + m,
mods_cr[l], m, mods_cr_inv[l]);
l++;
}
}
-
+
/* back to normal representation */
u[0] = y[nb_mods - 1];
l = 1;
u[l] = r;
l++;
}
-
+
/* last step adds the carry */
r = y[0];
for(k = 0; k < l; k++) {
}
printf("\n");
#endif
-
+
/* write the digits */
pos = i * dpl;
for(j = 0; j < n_limb1; j++) {
memset(s, 0, sizeof(*s));
s1->ntt_state = s;
s->ctx = s1;
-
+
for(j = 0; j < NB_MODS; j++) {
m = ntt_mods[j];
m_inv = init_mul_mod_fast(m);
int dpl, fft_len_log2, n_bits, nb_mods, dpl_found, fft_len_log2_found;
int int_bits, nb_mods_found;
limb_t cost, min_cost;
-
+
min_cost = -1;
dpl_found = 0;
nb_mods_found = 4;
#if defined(USE_MUL_CHECK)
limb_t ha, hb, hr, h_ref;
#endif
-
+
if (ntt_static_init(s1))
return -1;
s = s1->ntt_state;
-
+
/* find the optimal number of digits per limb (dpl) */
len = a_len + b_len;
fft_len_log2 = bf_get_fft_size(&dpl, &nb_mods, len);
return -1;
limb_to_ntt(s, buf1, fft_len, a_tab, a_len, dpl,
NB_MODS - nb_mods, nb_mods);
- if ((mul_flags & (FFT_MUL_R_OVERLAP_A | FFT_MUL_R_OVERLAP_B)) ==
+ if ((mul_flags & (FFT_MUL_R_OVERLAP_A | FFT_MUL_R_OVERLAP_B)) ==
FFT_MUL_R_OVERLAP_A) {
if (!(mul_flags & FFT_MUL_R_NORESIZE))
bf_resize(res, 0);
// printf("ha=0x" FMT_LIMB" hb=0x" FMT_LIMB " hr=0x" FMT_LIMB " expected=0x" FMT_LIMB "\n", ha, hb, hr, h_ref);
exit(1);
}
-#endif
+#endif
return 0;
fail:
ntt_free(s, buf1);
/*
* Tiny arbitrary precision floating point library
- *
+ *
* Copyright (c) 2017-2021 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
#define BF_ST_UNDERFLOW (1 << 3)
#define BF_ST_INEXACT (1 << 4)
/* indicate that a memory allocation error occured. NaN is returned */
-#define BF_ST_MEM_ERROR (1 << 5)
+#define BF_ST_MEM_ERROR (1 << 5)
#define BF_RADIX_MAX 36 /* maximum radix for bf_atof() and bf_ftoa() */
int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, bf_flags_t flags);
int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
int bf_mul_ui(bf_t *r, const bf_t *a, uint64_t b1, limb_t prec, bf_flags_t flags);
-int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec,
+int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec,
bf_flags_t flags);
int bf_mul_2exp(bf_t *r, slimb_t e, limb_t prec, bf_flags_t flags);
int bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
/* fractional format: prec digits after the decimal point rounded with
(flags & BF_RND_MASK) */
#define BF_FTOA_FORMAT_FRAC (1 << 16)
-/* free format:
-
+/* free format:
+
For binary radices with bf_ftoa() and for bfdec_ftoa(): use the minimum
number of digits to represent 'a'. The precision and the rounding
mode are ignored.
-
+
For the non binary radices with bf_ftoa(): use as many digits as
necessary so that bf_atof() return the same number when using
precision 'prec', rounding to nearest and the subnormal
bf_flags_t flags);
/* modulo 2^n instead of saturation. NaN and infinity return 0 */
-#define BF_GET_INT_MOD (1 << 0)
+#define BF_GET_INT_MOD (1 << 0)
int bf_get_int32(int *pres, const bf_t *a, int flags);
int bf_get_int64(int64_t *pres, const bf_t *a, int flags);
int bf_get_uint64(uint64_t *pres, const bf_t *a);
int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k);
slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv,
int is_ceil1);
-int mp_mul(bf_context_t *s, limb_t *result,
- const limb_t *op1, limb_t op1_size,
+int mp_mul(bf_context_t *s, limb_t *result,
+ const limb_t *op1, limb_t op1_size,
const limb_t *op2, limb_t op2_size);
-limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2,
+limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2,
limb_t n, limb_t carry);
limb_t mp_add_ui(limb_t *tab, limb_t b, size_t n);
int mp_sqrtrem(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n);
/*
* Regular Expression Engine
- *
+ *
* Copyright (c) 2017-2018 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
/*
* Regular Expression Engine
- *
+ *
* Copyright (c) 2017-2018 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
BOOL invert;
const uint16_t *c_pt;
int len, i;
-
+
invert = c & 1;
c_pt = char_range_table[c >> 1];
len = *c_pt++;
{
int pos, len, opcode, bc_len, re_flags, i;
uint32_t val;
-
+
assert(buf_len >= RE_HEADER_LEN);
re_flags= buf[0];
const uint8_t *p;
uint64_t v;
int c;
-
+
p = *pp;
v = 0;
for(;;) {
{
int h, n, i;
uint32_t c1;
-
+
if (*p == '{' && allow_utf16) {
p++;
c = 0;
const uint8_t *p;
uint32_t c;
int ret;
-
+
p = *pp;
c = *p;
{
int len, i;
uint32_t high;
-
+
len = (unsigned)cr->len / 2;
if (len >= 65535)
return re_parse_error(s, "too many ranges");
CharRange cr_s, *cr = &cr_s;
CharRange cr1_s, *cr1 = &cr1_s;
BOOL invert;
-
+
cr_init(cr, s->opaque, lre_realloc);
p = *pp;
p++; /* skip '[' */
int pos, opcode, len;
uint32_t val;
BOOL ret;
-
+
ret = TRUE;
pos = 0;
while (pos < bc_buf_len) {
{
int pos, opcode, len, count;
uint32_t val;
-
+
count = 0;
pos = 0;
while (pos < bc_buf_len) {
const char *p, *buf_end;
size_t len, name_len;
int capture_index;
-
+
name_len = strlen(name);
p = (char *)s->group_names.buf;
buf_end = (char *)s->group_names.buf + s->group_names.size;
int c, last_atom_start, quant_min, quant_max, last_capture_count;
BOOL greedy, add_zero_advance_check, is_neg, is_backward_lookahead;
CharRange cr_s, *cr = &cr_s;
-
+
last_atom_start = -1;
last_capture_count = 0;
p = s->buf_ptr;
capture_index = s->capture_count++;
re_emit_op_u8(s, REOP_save_start + is_backward_dir,
capture_index);
-
+
s->buf_ptr = p;
if (re_parse_disjunction(s, is_backward_dir))
return -1;
p = s->buf_ptr;
-
+
re_emit_op_u8(s, REOP_save_start + 1 - is_backward_dir,
capture_index);
-
+
if (re_parse_expect(s, &p, ')'))
return -1;
}
{
const uint8_t *p1;
int dummy_res;
-
+
p1 = p;
if (p1[2] != '<') {
/* annex B: we tolerate invalid group names in non
goto normal_char;
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8':
- case '9':
+ case '9':
{
const uint8_t *q = ++p;
-
+
c = parse_digits(&p, FALSE);
if (c < 0 || (c >= s->capture_count && c >= re_count_captures(s))) {
if (!s->is_utf16) {
}
if (greedy) {
int len, pos;
-
+
if (quant_max > 0) {
/* specific optimization for simple quantifiers */
if (dbuf_error(&s->byte_code))
s->byte_code.size - last_atom_start);
if (len > 0) {
re_emit_op(s, REOP_match);
-
+
if (dbuf_insert(&s->byte_code, last_atom_start, 17))
goto out_of_memory;
pos = last_atom_start;
goto done;
}
}
-
+
if (dbuf_error(&s->byte_code))
goto out_of_memory;
/* the spec tells that if there is no advance when
} else {
add_zero_advance_check = FALSE;
}
-
+
{
int len, pos;
len = s->byte_code.size - last_atom_start;
len + 5 * has_goto + add_zero_advance_check * 2);
if (add_zero_advance_check) {
s->byte_code.buf[last_atom_start + 1 + 4] = REOP_push_char_pos;
- re_emit_op(s, REOP_check_advance);
+ re_emit_op(s, REOP_check_advance);
}
if (has_goto)
re_emit_goto(s, REOP_goto, last_atom_start);
pos += 4;
if (add_zero_advance_check) {
s->byte_code.buf[pos++] = REOP_push_char_pos;
- re_emit_op(s, REOP_check_advance);
+ re_emit_op(s, REOP_check_advance);
}
re_emit_goto(s, REOP_loop, last_atom_start + 5);
re_emit_op(s, REOP_drop);
}
return 0;
}
-
+
static int re_parse_disjunction(REParseState *s, BOOL is_backward_dir)
{
int start, len, pos;
if (lre_check_stack_overflow(s->opaque, 0))
return re_parse_error(s, "stack overflow");
-
+
start = s->byte_code.size;
if (re_parse_alternative(s, is_backward_dir))
return -1;
if (re_parse_alternative(s, is_backward_dir))
return -1;
-
+
/* patch the goto */
len = s->byte_code.size - (pos + 4);
put_u32(s->byte_code.buf + pos, len);
{
int stack_size, stack_size_max, pos, opcode, len;
uint32_t val;
-
+
stack_size = 0;
stack_size_max = 0;
bc_buf += RE_HEADER_LEN;
REParseState s_s, *s = &s_s;
int stack_size;
BOOL is_sticky;
-
+
memset(s, 0, sizeof(*s));
s->opaque = opaque;
s->buf_ptr = (const uint8_t *)buf;
s->capture_count = 1;
s->total_capture_count = -1;
s->has_named_captures = -1;
-
+
dbuf_init2(&s->byte_code, opaque, lre_realloc);
dbuf_init2(&s->group_names, opaque, lre_realloc);
dbuf_putc(&s->byte_code, 0); /* second element is the number of captures */
dbuf_putc(&s->byte_code, 0); /* stack size */
dbuf_put_u32(&s->byte_code, 0); /* bytecode length */
-
+
if (!is_sticky) {
/* iterate thru all positions (about the same as .*?( ... ) )
. We do it without an explicit loop so that lock step
}
re_emit_op_u8(s, REOP_save_end, 0);
-
+
re_emit_op(s, REOP_match);
if (*s->buf_ptr != '\0') {
re_parse_out_of_memory(s);
goto error;
}
-
+
stack_size = compute_stack_size(s->byte_code.buf, s->byte_code.size);
if (stack_size < 0) {
re_parse_error(s, "too many imbricated quantifiers");
goto error;
}
-
+
s->byte_code.buf[RE_HEADER_CAPTURE_COUNT] = s->capture_count;
s->byte_code.buf[RE_HEADER_STACK_SIZE] = stack_size;
put_u32(s->byte_code.buf + 3, s->byte_code.size - RE_HEADER_LEN);
s->byte_code.buf[RE_HEADER_FLAGS] |= LRE_FLAG_NAMED_GROUPS;
}
dbuf_free(&s->group_names);
-
+
#ifdef DUMP_REOP
lre_dump_bytecode(s->byte_code.buf, s->byte_code.size);
#endif
-
+
error_msg[0] = '\0';
*plen = s->byte_code.size;
return s->byte_code.buf;
const uint8_t *cbuf;
const uint8_t *cbuf_end;
/* 0 = 8 bit chars, 1 = 16 bit chars, 2 = 16 bit chars, UTF-16 */
- int cbuf_type;
+ int cbuf_type;
int capture_count;
int stack_size_max;
BOOL multi_line;
int cbuf_type;
uint32_t val, c;
const uint8_t *cbuf_end;
-
+
cbuf_type = s->cbuf_type;
cbuf_end = s->cbuf_end;
case REOP_split_next_first:
{
const uint8_t *pc1;
-
+
val = get_u32(pc);
pc += 4;
if (opcode == REOP_split_next_first) {
if (ret < 0)
return -1;
break;
-
+
case REOP_goto:
val = get_u32(pc);
pc += 4 + (int)val;
{
const uint8_t *cptr1, *cptr1_end, *cptr1_start;
uint32_t c1, c2;
-
+
val = *pc++;
if (val >= s->capture_count)
goto no_match;
{
int n;
uint32_t low, high, idx_min, idx_max, idx;
-
+
n = get_u16(pc); /* n must be >= 1 */
pc += 2;
if (cptr >= cbuf_end)
{
int n;
uint32_t low, high, idx_min, idx_max, idx;
-
+
n = get_u16(pc); /* n must be >= 1 */
pc += 2;
if (cptr >= cbuf_end)
size_t q;
intptr_t res;
const uint8_t *pc1;
-
+
next_pos = get_u32(pc);
quant_min = get_u32(pc + 4);
quant_max = get_u32(pc + 8);
pc += 16;
pc1 = pc;
pc += (int)next_pos;
-
+
q = 0;
for(;;) {
res = lre_exec_backtrack(s, capture, stack, stack_len,
REExecContext s_s, *s = &s_s;
int re_flags, i, alloca_size, ret;
StackInt *stack_buf;
-
+
re_flags = bc_buf[RE_HEADER_FLAGS];
s->multi_line = (re_flags & LRE_FLAG_MULTILINE) != 0;
s->ignore_case = (re_flags & LRE_FLAG_IGNORECASE) != 0;
s->state_stack = NULL;
s->state_stack_len = 0;
s->state_stack_size = 0;
-
+
for(i = 0; i < s->capture_count * 2; i++)
capture[i] = NULL;
alloca_size = s->stack_size_max * sizeof(stack_buf[0]);
uint8_t *capture[CAPTURE_COUNT_MAX * 2];
const char *input;
int input_len, capture_count;
-
+
if (argc < 3) {
printf("usage: %s regexp input\n", argv[0]);
exit(1);
input = argv[2];
input_len = strlen(input);
-
+
ret = lre_exec(capture, bc, (uint8_t *)input, 0, input_len, 0, NULL);
printf("ret=%d\n", ret);
if (ret == 1) {
/*
* Regular Expression Engine
- *
+ *
* Copyright (c) 2017-2018 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
LRE_BOOL lre_is_space(int c);
/* must be provided by the user */
-LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size);
+LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size);
void *lre_realloc(void *opaque, void *ptr, size_t size);
/* JS identifier test */
/*
* Unicode utilities
- *
+ *
* Copyright (c) 2017-2018 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
}
/* conv_type:
- 0 = to upper
+ 0 = to upper
1 = to lower
- 2 = case folding (= to lower with modifications)
+ 2 = case folding (= to lower with modifications)
*/
int lre_case_conv(uint32_t *res, uint32_t c, int conv_type)
{
} else {
uint32_t v, code, len;
int idx, idx_min, idx_max;
-
+
idx_min = 0;
idx_max = countof(case_conv_table1) - 1;
while (idx_min <= idx_max) {
} else {
uint32_t v, code, len;
int idx, idx_min, idx_max;
-
+
idx_min = 0;
idx_max = countof(case_conv_table1) - 1;
while (idx_min <= idx_max) {
uint32_t code, b, bit;
int pos;
const uint8_t *p;
-
+
pos = get_index_pos(&code, c, index_table, index_table_len);
if (pos < 0)
return FALSE; /* outside the table */
{
uint32_t v, code, len;
int idx, idx_min, idx_max;
-
+
idx_min = 0;
idx_max = countof(case_conv_table1) - 1;
while (idx_min <= idx_max) {
{
int new_size;
uint32_t *new_buf;
-
+
if (size > cr->size) {
new_size = max_int(size, cr->size * 3 / 2);
new_buf = cr->realloc_func(cr->mem_opaque, cr->points,
{
int i, j, k, len;
uint32_t *pt;
-
+
pt = cr->points;
len = cr->len;
i = 0;
{
int a_idx, b_idx, is_in;
uint32_t v;
-
+
a_idx = 0;
b_idx = 0;
for(;;) {
{
uint32_t v, type, is_compat, code, len;
int idx_min, idx_max, idx;
-
+
idx_min = 0;
idx_max = countof(unicode_decomp_table1) - 1;
while (idx_min <= idx_max) {
uint32_t code, len, type, v, idx1, d_idx, d_offset, ch;
int idx_min, idx_max, idx, d;
uint32_t pair[2];
-
+
idx_min = 0;
idx_max = countof(unicode_comp_table) - 1;
while (idx_min <= idx_max) {
uint32_t code, n, type, cc, c1, b;
int pos;
const uint8_t *p;
-
+
pos = get_index_pos(&code, c,
unicode_cc_index, sizeof(unicode_cc_index) / 3);
if (pos < 0)
static void sort_cc(int *buf, int len)
{
int i, j, k, cc, cc1, start, ch1;
-
+
for(i = 0; i < len; i++) {
cc = unicode_get_cc(buf[i]);
if (cc != 0) {
uint32_t c, v;
int i, l;
uint32_t res[UNICODE_DECOMP_LEN_MAX];
-
+
for(i = 0; i < src_len; i++) {
c = src[i];
if (c >= 0xac00 && c < 0xd7a4) {
int *buf, buf_len, i, p, starter_pos, cc, last_cc, out_len;
BOOL is_compat;
DynBuf dbuf_s, *dbuf = &dbuf_s;
-
+
is_compat = n_type >> 1;
dbuf_init2(dbuf, opaque, realloc_func);
}
buf = (int *)dbuf->buf;
buf_len = dbuf->size / sizeof(int);
-
+
sort_cc(buf, buf_len);
-
+
if (buf_len <= 1 || (n_type & 1) != 0) {
/* NFD / NFKD */
*pdst = (uint32_t *)buf;
return buf_len;
}
-
+
i = 1;
out_len = 1;
while (i < buf_len) {
const char *p, *r;
int pos;
size_t name_len, len;
-
+
p = name_table;
pos = 0;
name_len = strlen(name);
CharRange cr1_s, *cr1;
CharRange cr2_s, *cr2 = &cr2_s;
BOOL is_common;
-
+
script_idx = unicode_find_name(unicode_script_name_table, script_name);
if (script_idx < 0)
return -2;
/* Note: we remove the "Unknown" Script */
script_idx += UNICODE_SCRIPT_Unknown + 1;
-
+
is_common = (script_idx == UNICODE_SCRIPT_Common ||
script_idx == UNICODE_SCRIPT_Inherited);
if (is_ext) {
static void cr_sort_and_remove_overlap(CharRange *cr)
{
uint32_t start, end, start1, end1, i, j;
-
+
/* the resulting ranges are not necessarily sorted and may overlap */
rqsort(cr->points, cr->len / 2, sizeof(cr->points[0]) * 2, point_cmp, NULL);
j = 0;
{
CharRange cr_inter, cr_mask, cr_result, cr_sub;
uint32_t v, code, len, i, idx, start, end, c, d_start, d_end, d;
-
+
cr_init(&cr_mask, cr->mem_opaque, cr->realloc_func);
cr_init(&cr_inter, cr->mem_opaque, cr->realloc_func);
cr_init(&cr_result, cr->mem_opaque, cr->realloc_func);
goto fail;
if (cr_op(&cr_sub, cr_mask.points, cr_mask.len, cr->points, cr->len, CR_OP_INTER))
goto fail;
-
+
/* cr_inter = cr & cr_mask */
/* cr_sub = cr & ~cr_mask */
CharRange stack[POP_STACK_LEN_MAX];
int stack_len, op, ret, i;
uint32_t a;
-
+
va_start(ap, cr);
stack_len = 0;
for(;;) {
{
int gc_idx;
uint32_t gc_mask;
-
+
gc_idx = unicode_find_name(unicode_gc_name_table, gc_name);
if (gc_idx < 0)
return -2;
int unicode_prop(CharRange *cr, const char *prop_name)
{
int prop_idx, ret;
-
+
prop_idx = unicode_find_name(unicode_prop_name_table, prop_name);
if (prop_idx < 0)
return -2;
/*
* Unicode utilities
- *
+ *
* Copyright (c) 2017-2018 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
/*
* Linux klist like system
- *
+ *
* Copyright (c) 2016-2017 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
}
/* insert 'el' between 'prev' and 'next' */
-static inline void __list_add(struct list_head *el,
+static inline void __list_add(struct list_head *el,
struct list_head *prev, struct list_head *next)
{
prev->next = el;
/*
* QuickJS stand alone interpreter
- *
+ *
* Copyright (c) 2017-2021 Fabrice Bellard
* Copyright (c) 2017-2021 Charlie Gordon
*
uint8_t *buf;
int ret, eval_flags;
size_t buf_len;
-
+
buf = js_load_file(ctx, &buf_len, filename);
if (!buf) {
perror(filename);
int load_jscalc;
#endif
size_t stack_size = 0;
-
+
#ifdef CONFIG_BIGNUM
/* load jscalc runtime if invoked as 'qjscalc' */
{
load_jscalc = !strcmp(exename, "qjscalc");
}
#endif
-
+
/* cannot use getopt because we want to pass the command line to
the script */
optind = 1;
JS_SetHostPromiseRejectionTracker(rt, js_std_promise_rejection_tracker,
NULL);
}
-
+
if (!empty_run) {
#ifdef CONFIG_BIGNUM
if (load_jscalc) {
}
js_std_loop(ctx);
}
-
+
if (dump_memory) {
JSMemoryUsage stats;
JS_ComputeMemoryUsage(rt, &stats);
/*
* QuickJS command line compiler
- *
+ *
* Copyright (c) 2018-2021 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
size_t len, i;
int c;
char *q;
-
+
p = strrchr(file, '/');
if (!p)
p = file;
}
namelist_add(&cname_list, c_name, NULL, load_only);
-
- fprintf(fo, "const uint32_t %s_size = %u;\n\n",
+
+ fprintf(fo, "const uint32_t %s_size = %u;\n\n",
c_name, (unsigned int)out_buf_len);
fprintf(fo, "const uint8_t %s[%u] = {\n",
c_name, (unsigned int)out_buf_len);
uint8_t *buf;
JSValue func_val;
char cname[1024];
-
+
buf = js_load_file(ctx, &buf_len, module_name);
if (!buf) {
JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
module_name);
return NULL;
}
-
+
/* compile the module */
func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
find_unique_cname(cname, sizeof(cname));
}
output_object_code(ctx, outfile, func_val, cname, TRUE);
-
+
/* the module is already referenced, so we must free it */
m = JS_VALUE_GET_PTR(func_val);
JS_FreeValue(ctx, func_val);
int eval_flags;
JSValue obj;
size_t buf_len;
-
+
buf = js_load_file(ctx, &buf_len, filename);
if (!buf) {
fprintf(stderr, "Could not load '%s'\n", filename);
if (pid == 0) {
execvp(argv[0], argv);
exit(1);
- }
+ }
for(;;) {
ret = waitpid(pid, &status, 0);
char libjsname[1024];
char exe_dir[1024], inc_dir[1024], lib_dir[1024], buf[1024], *p;
int ret;
-
+
/* get the directory of the executable */
pstrcpy(exe_dir, sizeof(exe_dir), exename);
p = strrchr(exe_dir, '/');
snprintf(inc_dir, sizeof(inc_dir), "%s/include/quickjs", CONFIG_PREFIX);
snprintf(lib_dir, sizeof(lib_dir), "%s/lib/quickjs", CONFIG_PREFIX);
}
-
+
lto_suffix = "";
bn_suffix = "";
-
+
arg = argv;
*arg++ = CONFIG_CC;
*arg++ = "-O2";
*arg++ = "-ldl";
*arg++ = "-lpthread";
*arg = NULL;
-
+
if (verbose) {
for(arg = argv; *arg != NULL; arg++)
printf("%s ", *arg);
printf("\n");
}
-
+
ret = exec_cmd((char **)argv);
unlink(cfilename);
return ret;
BOOL bignum_ext = FALSE;
#endif
namelist_t dynamic_module_list;
-
+
out_filename = NULL;
output_type = OUTPUT_EXECUTABLE;
cname = NULL;
use_lto = FALSE;
stack_size = 0;
memset(&dynamic_module_list, 0, sizeof(dynamic_module_list));
-
+
/* add system modules */
namelist_add(&cmodule_list, "std", "std", 0);
namelist_add(&cmodule_list, "os", "os", 0);
} else {
pstrcpy(cfilename, sizeof(cfilename), out_filename);
}
-
+
fo = fopen(cfilename, "w");
if (!fo) {
perror(cfilename);
exit(1);
}
outfile = fo;
-
+
rt = JS_NewRuntime();
ctx = JS_NewContext(rt);
#ifdef CONFIG_BIGNUM
JS_EnableBignumExt(ctx, TRUE);
}
#endif
-
+
/* loader for ES6 modules */
JS_SetModuleLoaderFunc(rt, NULL, jsc_module_loader, NULL);
fprintf(fo, "/* File generated automatically by the QuickJS compiler. */\n"
"\n"
);
-
+
if (output_type != OUTPUT_C) {
fprintf(fo, "#include \"quickjs-libc.h\"\n"
"\n"
exit(1);
}
}
-
+
if (output_type != OUTPUT_C) {
fprintf(fo,
"static JSContext *JS_NewCustomContext(JSRuntime *rt)\n"
for(i = 0; i < init_module_list.count; i++) {
namelist_entry_t *e = &init_module_list.array[i];
/* initialize the static C modules */
-
+
fprintf(fo,
" {\n"
" extern JSModuleDef *js_init_module_%s(JSContext *ctx, const char *name);\n"
fprintf(fo,
" return ctx;\n"
"}\n\n");
-
+
fputs(main_c_template1, fo);
if (stack_size != 0) {
fprintf(fo, " JS_SetMaxStackSize(rt, %u);\n",
(unsigned int)stack_size);
}
-
+
/* add the module loader if necessary */
if (feature_bitmap & (1 << FE_MODULE_LOADER)) {
fprintf(fo, " JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n");
}
-
+
fprintf(fo,
" ctx = JS_NewCustomContext(rt);\n"
" js_std_add_helpers(ctx, argc, argv);\n");
}
fputs(main_c_template2, fo);
}
-
+
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
/*
* QuickJS Javascript Calculator
- *
+ *
* Copyright (c) 2017-2020 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
global.Integer = global.BigInt;
global.Float = global.BigFloat;
global.algebraicMode = true;
-
+
/* add non enumerable properties */
function add_props(obj, props) {
var i, val, prop, tab, desc;
}
}
proto[Symbol.operatorSet] =
- Operators.create.call(null, ...new_op_list);
+ Operators.create.call(null, ...new_op_list);
}
-
+
/* Integer */
function generic_pow(a, b) {
}
return r;
}
-
+
var small_primes = [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499 ];
function miller_rabin_test(n, t) {
}
}
});
-
+
add_props(Integer, {
isInteger(a) {
/* integers are represented either as bigint or as number */
r.push(-1);
n = -n;
}
-
+
while ((n % 2) == 0) {
n >>= 1;
r.push(2);
a = Integer.tdiv(a, d);
b = Integer.tdiv(b, d);
}
-
+
/* the fractions are normalized with den > 0 */
if (b < 0) {
a = -a;
else
return a < b;
}
-
+
operators_set(Fraction.prototype,
{
"+": fraction_add,
"==": float_eq,
"<": float_lt,
});
-
+
add_props(Fraction, {
/* (internal use) simplify 'a' to an integer when possible */
toFraction(a, b) {
}
},
});
-
+
/* Float */
var const_tab = [];
-
+
/* we cache the constants for small precisions */
function get_const(n) {
var t, c, p;
return c;
}
}
-
+
add_props(Float, {
isFloat(a) {
return typeof a === "number" || typeof a === "bigfloat";
}
},
});
-
+
/* Complex */
-
+
Complex = function Complex(re, im)
{
var obj;
return obj;
}
-
+
function complex_add(a, b) {
a = Complex(a);
b = Complex(b);
b = Complex(b);
return a.re == b.re && a.im == b.im;
}
-
+
operators_set(Complex.prototype,
{
"+": complex_add,
"**": generic_pow,
"==": complex_eq,
});
-
+
add_props(Complex, {
/* simplify to real number when possible */
toComplex(re, im) {
obj.mod = m;
return obj;
};
-
+
function mod_add(a, b) {
if (!(a instanceof Mod)) {
return Mod(a + b.res, b.mod);
return true;
return false;
}
-
+
Polynomial = function Polynomial(a)
{
if (new.target)
/* trivial zero */
if (p[0] == 0)
return 0.0;
-
+
p1 = p.deriv();
p2 = p1.deriv();
el = 0.0;
}
el = e;
zl = z;
-
+
z1 = p1.apply(z);
z2 = p2.apply(z);
t0 = (d - 1) * z1;
d2 = z1 - t0;
if (norm2(d2) > norm2(d1))
d1 = d2;
- if (d1 == 0)
+ if (d1 == 0)
return null;
z = z - d * z0 / d1;
}
"/": polynomial_div_scalar,
"**": generic_pow, /* XXX: only for integer */
});
-
+
add_props(Polynomial, {
divrem(a, b) {
var n1, n2, i, j, q, r, n, c;
});
/* Rational function */
-
+
RationalFunction = function RationalFunction(a, b)
{
var t, r, d, obj;
"/": ratfunc_div,
"**": generic_pow, /* should only be used with integers */
});
-
+
add_props(RationalFunction, {
/* This function always return a RationalFunction object even
if it could simplified to a polynomial, so it is not
}
},
});
-
+
/* Power series */
/* 'a' is an array */
return polynomial_is_scalar(a) ||
(a instanceof Polynomial);
}
-
+
/* n is the maximum number of terms if 'a' is not a serie */
Series = function Series(a, n) {
var emin, r, i;
-
+
if (a instanceof Series) {
return a;
} else if (series_is_scalar_or_polynomial(a)) {
return Series.zero(0, n);
},
});
-
+
/* Array (Matrix) */
Matrix = function Matrix(h, w) {
},
det(a) {
var n, i, j, k, s, src, v, c;
-
+
n = Matrix.check_square(a);
s = 1;
src = a.dup();
src[i][k] *= c;
dst[i][k] *= c;
}
-
+
for(j = 0; j < n; j++) {
if (j != i) {
c = src[j][i];
},
rank(a) {
var src, i, j, k, w, h, l, c;
-
+
if (!Array.isArray(a) ||
!Array.isArray(a[0]))
throw TypeError("matrix expected");
src[l][k] = v;
}
}
-
+
c = src[l][i].inverse();
for(k = 0; k < w; k++) {
src[l][k] *= c;
}
-
+
for(j = l + 1; j < h; j++) {
c = src[j][i];
for(k = i; k < w; k++) {
},
ker(a) {
var src, i, j, k, w, h, l, m, r, im_cols, ker_dim, c;
-
+
if (!Array.isArray(a) ||
!Array.isArray(a[0]))
throw TypeError("matrix expected");
src[l][k] = v;
}
}
-
+
c = src[l][i].inverse();
for(k = 0; k < w; k++) {
src[l][k] *= c;
}
-
+
for(j = 0; j < h; j++) {
if (j != l) {
c = src[j][i];
/*
* QuickJS atom definitions
- *
+ *
* Copyright (c) 2017-2018 Fabrice Bellard
* Copyright (c) 2017-2018 Charlie Gordon
*
DEF(ArrayBuffer, "ArrayBuffer")
DEF(SharedArrayBuffer, "SharedArrayBuffer")
/* must keep same order as class IDs for typed arrays */
-DEF(Uint8ClampedArray, "Uint8ClampedArray")
+DEF(Uint8ClampedArray, "Uint8ClampedArray")
DEF(Int8Array, "Int8Array")
DEF(Uint8Array, "Uint8Array")
DEF(Int16Array, "Int16Array")
#ifdef CONFIG_BIGNUM
DEF(Symbol_operatorSet, "Symbol.operatorSet")
#endif
-
+
#endif /* DEF */
/*
* QuickJS C library
- *
+ *
* Copyright (c) 2017-2021 Fabrice Bellard
* Copyright (c) 2017-2021 Charlie Gordon
*
break;
q = fmtbuf;
*q++ = *fmt++; /* copy '%' */
-
+
/* flags */
for(;;) {
c = *fmt;
if (*fmt == 'l') {
mod = *fmt++;
}
-
+
/* type */
c = *fmt++;
if (q >= fmtbuf + sizeof(fmtbuf) - 1)
goto invalid;
*q++ = c;
*q = '\0';
-
+
switch (c) {
case 'c':
if (i >= argc)
len = unicode_to_utf8(cbuf, int32_arg);
dbuf_put(&dbuf, cbuf, len);
break;
-
+
case 'd':
case 'i':
case 'o':
dbuf_printf_fun(&dbuf, fmtbuf, string_arg);
JS_FreeCString(ctx, string_arg);
break;
-
+
case 'e':
case 'f':
case 'g':
goto fail;
dbuf_printf_fun(&dbuf, fmtbuf, double_arg);
break;
-
+
case '%':
dbuf_putc(&dbuf, '%');
break;
-
+
default:
/* XXX: should support an extension mechanism */
invalid:
uint8_t *buf;
size_t buf_len;
long lret;
-
+
f = fopen(filename, "rb");
if (!f)
return NULL;
const char *filename;
JSValue ret;
size_t buf_len;
-
+
filename = JS_ToCString(ctx, argv[0]);
if (!filename)
return JS_EXCEPTION;
const char *filename;
JSValue ret;
size_t buf_len;
-
+
filename = JS_ToCString(ctx, argv[0]);
if (!filename)
return JS_EXCEPTION;
void *hd;
JSInitModuleFunc *init;
char *filename;
-
+
if (!strchr(module_name, '/')) {
/* must add a '/' so that the DLL is not searched in the
system library paths */
} else {
filename = (char *)module_name;
}
-
+
/* C module */
hd = dlopen(filename, RTLD_NOW | RTLD_LOCAL);
if (filename != module_name)
JSValue meta_obj;
JSAtom module_name_atom;
const char *module_name;
-
+
assert(JS_VALUE_GET_TAG(func_val) == JS_TAG_MODULE);
m = JS_VALUE_GET_PTR(func_val);
pstrcpy(buf, sizeof(buf), module_name);
}
JS_FreeCString(ctx, module_name);
-
+
meta_obj = JS_GetImportMeta(ctx, m);
if (JS_IsException(meta_obj))
return -1;
size_t buf_len;
uint8_t *buf;
JSValue func_val;
-
+
buf = js_load_file(ctx, &buf_len, module_name);
if (!buf) {
JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
module_name);
return NULL;
}
-
+
/* compile the module */
func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
BOOL backtrace_barrier = FALSE;
BOOL is_async = FALSE;
int flags;
-
+
if (argc >= 2) {
options_obj = argv[1];
if (get_bool_option(ctx, &backtrace_barrier, options_obj,
/* install the interrupt handler */
JS_SetInterruptHandler(JS_GetRuntime(ctx), interrupt_handler, NULL);
}
- flags = JS_EVAL_TYPE_GLOBAL;
+ flags = JS_EVAL_TYPE_GLOBAL;
if (backtrace_barrier)
flags |= JS_EVAL_FLAG_BACKTRACE_BARRIER;
if (is_async)
const char *filename, *mode = NULL;
FILE *f;
int err;
-
+
filename = JS_ToCString(ctx, argv[0]);
if (!filename)
goto fail;
const char *filename, *mode = NULL;
FILE *f;
int err;
-
+
filename = JS_ToCString(ctx, argv[0]);
if (!filename)
goto fail;
if (!f)
return JS_EXCEPTION;
}
-
+
for(i = 0; i < argc; i++) {
str = JS_ToCStringLen(ctx, &len, argv[i]);
if (!str)
uint64_t pos, len;
size_t size, ret;
uint8_t *buf;
-
+
if (!f)
return JS_EXCEPTION;
if (JS_ToIndex(ctx, &pos, argv[1]))
int c;
DynBuf dbuf;
JSValue obj;
-
+
if (!f)
return JS_EXCEPTION;
uint64_t max_size64;
size_t max_size;
JSValueConst max_size_val;
-
+
if (!f)
return JS_EXCEPTION;
{
int c;
char *p;
-
+
p = buf;
for(;;) {
c = fgetc(f);
DynBuf cmd_buf;
DynBuf data_buf_s, *data_buf = &data_buf_s;
DynBuf header_buf_s, *header_buf = &header_buf_s;
- char *buf;
+ char *buf;
size_t i, len;
int c, status;
JSValue response = JS_UNDEFINED, ret_obj;
JSValueConst options_obj;
FILE *f;
BOOL binary_flag, full_flag;
-
+
url = JS_ToCString(ctx, argv[0]);
if (!url)
return JS_EXCEPTION;
-
+
binary_flag = FALSE;
full_flag = FALSE;
-
+
if (argc >= 2) {
options_obj = argv[1];
return JS_EXCEPTION;
}
}
-
+
js_std_dbuf_init(ctx, &cmd_buf);
dbuf_printf(&cmd_buf, "%s ''", URL_GET_PROGRAM);
len = strlen(url);
js_std_dbuf_init(ctx, data_buf);
js_std_dbuf_init(ctx, header_buf);
-
+
buf = js_malloc(ctx, URL_GET_BUF_SIZE);
if (!buf)
goto fail;
if (!full_flag && !(status >= 200 && status <= 299)) {
goto bad_header;
}
-
+
/* wait until there is an empty line */
for(;;) {
if (http_get_header_line(f, buf, URL_GET_BUF_SIZE, header_buf) < 0) {
static JSClassDef js_std_file_class = {
"FILE",
.finalizer = js_std_file_finalizer,
-};
+};
static const JSCFunctionListEntry js_std_error_props[] = {
/* various errno values */
JS_CFUNC_DEF("loadFile", 1, js_std_loadFile ),
JS_CFUNC_DEF("strerror", 1, js_std_strerror ),
JS_CFUNC_DEF("parseExtJSON", 1, js_std_parseExtJSON ),
-
+
/* FILE I/O */
JS_CFUNC_DEF("open", 2, js_std_open ),
JS_CFUNC_DEF("popen", 2, js_std_popen ),
JS_PROP_INT32_DEF("SEEK_END", SEEK_END, JS_PROP_CONFIGURABLE ),
JS_OBJECT_DEF("Error", js_std_error_props, countof(js_std_error_props), JS_PROP_CONFIGURABLE),
};
-
+
static const JSCFunctionListEntry js_std_file_proto_funcs[] = {
JS_CFUNC_DEF("close", 0, js_std_file_close ),
JS_CFUNC_MAGIC_DEF("puts", 1, js_std_file_puts, 1 ),
static int js_std_init(JSContext *ctx, JSModuleDef *m)
{
JSValue proto;
-
+
/* FILE class */
/* the class ID is created once */
JS_NewClassID(&js_std_file_class_id);
int fd, whence;
int64_t pos, ret;
BOOL is_bigint;
-
+
if (JS_ToInt32(ctx, &fd, argv[0]))
return JS_EXCEPTION;
is_bigint = JS_IsBigInt(ctx, argv[1]);
size_t size;
ssize_t ret;
uint8_t *buf;
-
+
if (JS_ToInt32(ctx, &fd, argv[0]))
return JS_EXCEPTION;
if (JS_ToIndex(ctx, &pos, argv[2]))
if (JS_ToInt32(ctx, &fd, argv[0]))
return JS_EXCEPTION;
handle = (HANDLE)_get_osfhandle(fd);
-
+
if (!GetConsoleScreenBufferInfo(handle, &info))
return JS_NULL;
obj = JS_NewArray(ctx);
int fd;
struct winsize ws;
JSValue obj;
-
+
if (JS_ToInt32(ctx, &fd, argv[0]))
return JS_EXCEPTION;
if (ioctl(fd, TIOCGWINSZ, &ws) == 0 &&
{
struct termios tty;
int fd;
-
+
if (JS_ToInt32(ctx, &fd, argv[0]))
return JS_EXCEPTION;
-
+
memset(&tty, 0, sizeof(tty));
tcgetattr(fd, &tty);
oldtty = tty;
{
const char *filename;
int ret;
-
+
filename = JS_ToCString(ctx, argv[0]);
if (!filename)
return JS_EXCEPTION;
{
const char *oldpath, *newpath;
int ret;
-
+
oldpath = JS_ToCString(ctx, argv[0]);
if (!oldpath)
return JS_EXCEPTION;
JSOSRWHandler *rh;
int fd;
JSValueConst func;
-
+
if (JS_ToInt32(ctx, &fd, argv[0]))
return JS_EXCEPTION;
func = argv[1];
if (!is_main_thread(rt))
return JS_ThrowTypeError(ctx, "signal handler can only be set in the main thread");
-
+
if (JS_ToUint32(ctx, &sig_num, argv[0]))
return JS_EXCEPTION;
if (sig_num >= 64)
JSThreadState *ts = JS_GetRuntimeOpaque(rt);
JSOSTimer *th;
int timer_id;
-
+
if (JS_ToInt32(ctx, &timer_id, argv[0]))
return JS_EXCEPTION;
th = find_timer_by_id(ts, timer_id);
int64_t cur_time, delay;
JSOSRWHandler *rh;
struct list_head *el;
-
+
/* XXX: handle signals if useful */
if (list_empty(&ts->os_rw_handlers) && list_empty(&ts->os_timers))
return -1; /* no more events */
-
+
/* XXX: only timers and basic console input are supported */
if (!list_empty(&ts->os_timers)) {
cur_time = get_time_ms();
struct list_head *el;
JSWorkerMessage *msg;
JSValue obj, data_obj, func, retval;
-
+
pthread_mutex_lock(&ps->mutex);
if (!list_empty(&ps->msg_queue)) {
el = ps->msg_queue.next;
JS_READ_OBJ_SAB | JS_READ_OBJ_REFERENCE);
js_free_message(msg);
-
+
if (JS_IsException(data_obj))
goto fail;
obj = JS_NewObject(ctx);
unlikely(os_pending_signals != 0)) {
JSOSSignalHandler *sh;
uint64_t mask;
-
+
list_for_each(el, &ts->os_signal_handlers) {
sh = list_entry(el, JSOSSignalHandler, link);
mask = (uint64_t)1 << sh->sig_num;
if (list_empty(&ts->os_rw_handlers) && list_empty(&ts->os_timers) &&
list_empty(&ts->port_list))
return -1; /* no more events */
-
+
if (!list_empty(&ts->os_timers)) {
cur_time = get_time_ms();
min_delay = 10000;
} else {
tvp = NULL;
}
-
+
FD_ZERO(&rfds);
FD_ZERO(&wfds);
fd_max = -1;
{
char buf[PATH_MAX];
int err;
-
+
if (!getcwd(buf, sizeof(buf))) {
buf[0] = '\0';
err = errno;
{
int mode, ret;
const char *path;
-
+
if (argc >= 2) {
if (JS_ToInt32(ctx, &mode, argv[1]))
return JS_EXCEPTION;
JSValue obj;
int err;
uint32_t len;
-
+
path = JS_ToCString(ctx, argv[0]);
if (!path)
return JS_EXCEPTION;
const char *path;
int64_t atime, mtime;
int ret;
-
+
if (JS_ToInt64(ctx, &atime, argv[1]))
return JS_EXCEPTION;
if (JS_ToInt64(ctx, &mtime, argv[2]))
{
int64_t delay;
int ret;
-
+
if (JS_ToInt64(ctx, &delay, argv[0]))
return JS_EXCEPTION;
if (delay < 0)
{
const char *target, *linkpath;
int err;
-
+
target = JS_ToCString(ctx, argv[0]);
if (!target)
return JS_EXCEPTION;
char buf[PATH_MAX];
int err;
ssize_t res;
-
+
path = JS_ToCString(ctx, argv[0]);
if (!path)
return JS_EXCEPTION;
const char *key, *str;
JSValue val;
size_t key_len, str_len;
-
+
if (JS_GetOwnPropertyNames(ctx, &tab, &len, obj,
JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY) < 0)
return NULL;
char buf[PATH_MAX];
size_t filename_len, path_len;
BOOL eacces_error;
-
+
filename_len = strlen(filename);
if (filename_len == 0) {
errno = ENOENT;
}
if (strchr(filename, '/'))
return execve(filename, argv, envp);
-
+
path = getenv("PATH");
if (!path)
path = (char *)"/bin:/usr/bin";
buf[path_len] = '/';
memcpy(buf + path_len + 1, filename, filename_len);
buf[path_len + 1 + filename_len] = '\0';
-
+
execve(buf, argv, envp);
switch(errno) {
static const char *std_name[3] = { "stdin", "stdout", "stderr" };
int std_fds[3];
uint32_t uid = -1, gid = -1;
-
+
val = JS_GetPropertyStr(ctx, args, "length");
if (JS_IsException(val))
return JS_EXCEPTION;
for(i = 0; i < 3; i++)
std_fds[i] = i;
-
+
/* get the options, if any */
if (argc >= 2) {
options = argv[1];
goto exception;
if (get_bool_option(ctx, &use_path, options, "usePath"))
goto exception;
-
+
val = JS_GetPropertyStr(ctx, options, "file");
if (JS_IsException(val))
goto exception;
if (!envp)
goto exception;
}
-
+
val = JS_GetPropertyStr(ctx, options, "uid");
if (JS_IsException(val))
goto exception;
{
int pid, status, options, ret;
JSValue obj;
-
+
if (JS_ToInt32(ctx, &pid, argv[0]))
return JS_EXCEPTION;
if (JS_ToInt32(ctx, &options, argv[1]))
JS_DefinePropertyValueUint32(ctx, obj, 1, JS_NewInt32(ctx, status),
JS_PROP_C_W_E);
return obj;
-}
+}
/* pipe() -> [read_fd, write_fd] or null if error */
static JSValue js_os_pipe(JSContext *ctx, JSValueConst this_val,
{
int pipe_fds[2], ret;
JSValue obj;
-
+
ret = pipe(pipe_fds);
if (ret < 0)
return JS_NULL;
int argc, JSValueConst *argv)
{
int pid, sig, ret;
-
+
if (JS_ToInt32(ctx, &pid, argv[0]))
return JS_EXCEPTION;
if (JS_ToInt32(ctx, &sig, argv[1]))
int argc, JSValueConst *argv)
{
int fd, ret;
-
+
if (JS_ToInt32(ctx, &fd, argv[0]))
return JS_EXCEPTION;
ret = js_get_errno(dup(fd));
int argc, JSValueConst *argv)
{
int fd, fd2, ret;
-
+
if (JS_ToInt32(ctx, &fd, argv[0]))
return JS_EXCEPTION;
if (JS_ToInt32(ctx, &fd2, argv[1]))
{
JSWorkerMessagePipe *ps;
int pipe_fds[2];
-
+
if (pipe(pipe_fds) < 0)
return NULL;
struct list_head *el, *el1;
JSWorkerMessage *msg;
int ref_count;
-
+
if (!ps)
return;
-
+
ref_count = atomic_add_int(&ps->ref_count, -1);
assert(ref_count >= 0);
if (ref_count == 0) {
static JSClassDef js_worker_class = {
"Worker",
.finalizer = js_worker_finalizer,
-};
+};
static void *worker_func(void *opaque)
{
JSThreadState *ts;
JSContext *ctx;
JSValue val;
-
+
rt = JS_NewRuntime();
if (rt == NULL) {
fprintf(stderr, "JS_NewRuntime failure");
exit(1);
- }
+ }
js_std_init_handlers(rt);
JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
ts = JS_GetRuntimeOpaque(rt);
ts->recv_pipe = args->recv_pipe;
ts->send_pipe = args->send_pipe;
-
+
/* function pointer to avoid linking the whole JS_NewContext() if
not needed */
ctx = js_worker_new_context_func(rt);
{
JSValue obj = JS_UNDEFINED, proto;
JSWorkerData *s;
-
+
/* create the object */
if (JS_IsUndefined(new_target)) {
proto = JS_GetClassProto(ctx, js_worker_class_id);
int ret;
const char *filename = NULL, *basename;
JSAtom basename_atom;
-
+
/* XXX: in order to avoid problems with resource liberation, we
don't support creating workers inside workers */
if (!is_main_thread(rt))
JS_FreeAtom(ctx, basename_atom);
if (!basename)
goto fail;
-
+
/* module name */
filename = JS_ToCString(ctx, argv[0]);
if (!filename)
args->send_pipe, args->recv_pipe);
if (JS_IsException(obj))
goto fail;
-
+
pthread_attr_init(&attr);
/* no join at the end */
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
uint8_t *data;
JSWorkerMessage *msg;
uint8_t **sab_tab;
-
+
if (!worker)
return JS_EXCEPTION;
-
+
data = JS_WriteObject2(ctx, &data_len, argv[0],
JS_WRITE_OBJ_SAB | JS_WRITE_OBJ_REFERENCE,
&sab_tab, &sab_tab_len);
js_free(ctx, data);
js_free(ctx, sab_tab);
-
+
/* increment the SAB reference counts */
for(i = 0; i < msg->sab_tab_len; i++) {
js_sab_dup(NULL, msg->sab_tab[i]);
js_free(ctx, data);
js_free(ctx, sab_tab);
return JS_EXCEPTION;
-
+
}
static JSValue js_worker_set_onmessage(JSContext *ctx, JSValueConst this_val,
JSThreadState *ts = JS_GetRuntimeOpaque(rt);
JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, js_worker_class_id);
JSWorkerMessageHandler *port;
-
+
if (!worker)
return JS_EXCEPTION;
static int js_os_init(JSContext *ctx, JSModuleDef *m)
{
os_poll_func = js_os_poll;
-
+
#ifdef USE_WORKER
{
JSRuntime *rt = JS_GetRuntime(ctx);
JS_NewClass(JS_GetRuntime(ctx), js_worker_class_id, &js_worker_class);
proto = JS_NewObject(ctx);
JS_SetPropertyFunctionList(ctx, proto, js_worker_proto_funcs, countof(js_worker_proto_funcs));
-
+
obj = JS_NewCFunction2(ctx, js_worker_ctor, "Worker", 1,
JS_CFUNC_constructor, 0);
JS_SetConstructor(ctx, obj, proto);
-
+
JS_SetClassProto(ctx, js_worker_class_id, proto);
-
+
/* set 'Worker.parent' if necessary */
if (ts->recv_pipe && ts->send_pipe) {
JS_DefinePropertyValueStr(ctx, obj, "parent",
js_worker_ctor_internal(ctx, JS_UNDEFINED, ts->recv_pipe, ts->send_pipe),
JS_PROP_C_W_E);
}
-
+
JS_SetModuleExport(ctx, m, "Worker", obj);
}
#endif /* USE_WORKER */
}
JS_SetPropertyStr(ctx, global_obj, "scriptArgs", args);
}
-
+
JS_SetPropertyStr(ctx, global_obj, "print",
JS_NewCFunction(ctx, js_print, "print", 1));
JS_SetPropertyStr(ctx, global_obj, "__loadScript",
JS_NewCFunction(ctx, js_loadScript, "__loadScript", 1));
-
+
JS_FreeValue(ctx, global_obj);
}
init_list_head(&ts->os_timers);
init_list_head(&ts->port_list);
ts->next_timer_id = 1;
-
+
JS_SetRuntimeOpaque(rt, ts);
#ifdef USE_WORKER
JSOSSignalHandler *sh = list_entry(el, JSOSSignalHandler, link);
free_sh(rt, sh);
}
-
+
list_for_each_safe(el, el1, &ts->os_timers) {
JSOSTimer *th = list_entry(el, JSOSTimer, link);
free_timer(rt, th);
static void js_dump_obj(JSContext *ctx, FILE *f, JSValueConst val)
{
const char *str;
-
+
str = JS_ToCString(ctx, val);
if (str) {
fprintf(f, "%s\n", str);
{
JSValue val;
BOOL is_error;
-
+
is_error = JS_IsError(ctx, exception_val);
js_dump_obj(ctx, stderr, exception_val);
if (is_error) {
void js_std_dump_error(JSContext *ctx)
{
JSValue exception_val;
-
+
exception_val = JS_GetException(ctx);
js_std_dump_error1(ctx, exception_val);
JS_FreeValue(ctx, exception_val);
/*
* QuickJS C library
- *
+ *
* Copyright (c) 2017-2018 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
JSValueConst reason,
JS_BOOL is_handled, void *opaque);
void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt));
-
+
#ifdef __cplusplus
} /* extern "C" { */
#endif
/*
* QuickJS opcode definitions
- *
+ *
* Copyright (c) 2017-2018 Fabrice Bellard
* Copyright (c) 2017-2018 Charlie Gordon
*
DEF( get_arg, 3, 0, 1, arg)
DEF( put_arg, 3, 1, 0, arg) /* must come after get_arg */
DEF( set_arg, 3, 1, 1, arg) /* must come after put_arg */
-DEF( get_var_ref, 3, 0, 1, var_ref)
+DEF( get_var_ref, 3, 0, 1, var_ref)
DEF( put_var_ref, 3, 1, 0, var_ref) /* must come after get_var_ref */
DEF( set_var_ref, 3, 1, 1, var_ref) /* must come after put_var_ref */
DEF(set_loc_uninitialized, 3, 0, 0, loc)
DEF( put_loc_check, 3, 1, 0, loc) /* must come after get_loc_check */
DEF( put_loc_check_init, 3, 1, 0, loc)
DEF(get_loc_checkthis, 3, 0, 1, loc)
-DEF(get_var_ref_check, 3, 0, 1, var_ref)
+DEF(get_var_ref_check, 3, 0, 1, var_ref)
DEF(put_var_ref_check, 3, 1, 0, var_ref) /* must come after get_var_ref_check */
DEF(put_var_ref_check_init, 3, 1, 0, var_ref)
DEF( close_loc, 3, 0, 0, loc)
DEF( math_mod, 1, 2, 1, none)
#endif
/* must be the last non short and non temporary opcode */
-DEF( nop, 1, 0, 0, none)
+DEF( nop, 1, 0, 0, none)
/* temporary opcodes: never emitted in the final bytecode */
def(get_field_opt_chain, 5, 1, 1, atom) /* emitted in phase 1, removed in phase 2 */
def(get_array_el_opt_chain, 1, 2, 1, none) /* emitted in phase 1, removed in phase 2 */
def( set_class_name, 5, 1, 1, u32) /* emitted in phase 1, removed in phase 2 */
-
+
def( line_num, 5, 0, 0, u32) /* emitted in phase 1, removed in phase 3 */
#if SHORT_OPCODES
/*
* QuickJS Javascript Engine
- *
+ *
* Copyright (c) 2017-2021 Fabrice Bellard
* Copyright (c) 2017-2021 Charlie Gordon
*
JS_URI_ERROR,
JS_INTERNAL_ERROR,
JS_AGGREGATE_ERROR,
-
+
JS_NATIVE_ERROR_COUNT, /* number of different NativeError objects */
} JSErrorEnum;
by the garbage collector) */
struct list_head gc_obj_list;
/* list of JSGCObjectHeader.link. Used during JS_FreeValueRT() */
- struct list_head gc_zero_ref_count_list;
+ struct list_head gc_zero_ref_count_list;
struct list_head tmp_obj_list; /* used during GC */
JSGCPhaseEnum gc_phase : 8;
size_t malloc_gc_threshold;
uintptr_t stack_size; /* in bytes, 0 if no limit */
uintptr_t stack_top;
uintptr_t stack_limit; /* lower stack limit */
-
+
JSValue current_exception;
/* true if inside an out of memory error, to avoid recursing */
BOOL in_out_of_memory : 8;
JSHostPromiseRejectionTracker *host_promise_rejection_tracker;
void *host_promise_rejection_tracker_opaque;
-
+
struct list_head job_list; /* list of JSJobEntry.link */
JSModuleNormalizeFunc *module_normalize_func;
void *module_loader_opaque;
/* timestamp for internal use in module evaluation */
int64_t module_async_evaluation_next_timestamp;
-
+
BOOL can_block : 8; /* TRUE if Atomics.wait can block */
/* used to allocate, free and clone SharedArrayBuffers */
JSSharedArrayBufferFunctions sab_funcs;
-
+
/* Shape hash table */
int shape_hash_bits;
int shape_hash_size;
int arg_count;
int js_mode; /* for C functions, only JS_MODE_MATH may be set */
/* only used in generators. Current stack pointer value. NULL if
- the function is running. */
+ the function is running. */
JSValue *cur_sp;
} JSStackFrame;
struct {
int __gc_ref_count; /* corresponds to header.ref_count */
uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */
- uint8_t is_detached : 1;
+ uint8_t is_detached : 1;
uint8_t is_arg : 1;
uint16_t var_idx; /* index of the corresponding function variable on
the stack */
JSAtom var_name;
/* index into fd->scopes of this variable lexical scope */
int scope_level;
- /* during compilation:
+ /* during compilation:
- if scope_level = 0: scope in which the variable is defined
- if scope_level != 0: index into fd->vars of the next
variable in the same or enclosing lexical scope
index into fd->vars of the next
variable in the same or enclosing lexical scope
*/
- int scope_next;
+ int scope_next;
uint8_t is_const : 1;
uint8_t is_lexical : 1;
uint8_t is_captured : 1;
uint8_t has_debug : 1;
uint8_t backtrace_barrier : 1; /* stop backtrace on this function */
uint8_t read_only_bytecode : 1;
- uint8_t is_direct_or_indirect_eval : 1; /* used by JS_GetScriptOrModuleName() */
+ uint8_t is_direct_or_indirect_eval : 1; /* used by JS_GetScriptOrModuleName() */
/* XXX: 4 bits available */
uint8_t *byte_code_buf; /* (self pointer) */
int byte_code_len;
JSModuleDef *cycle_root;
JSValue promise; /* corresponds to spec field: capability */
JSValue resolving_funcs[2]; /* corresponds to spec field: capability */
-
+
/* true if evaluation yielded an exception. It is saved in
eval_exception */
- BOOL eval_has_exception : 8;
+ BOOL eval_has_exception : 8;
JSValue eval_exception;
JSValue meta_obj; /* for import.meta */
};
struct {
int __gc_ref_count; /* corresponds to header.ref_count */
uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */
-
+
uint8_t extensible : 1;
uint8_t free_mark : 1; /* only used when freeing objects with cycles */
uint8_t is_exotic : 1; /* TRUE if object has exotic property handlers */
struct JSTypedArray *typed_array; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */
} u1;
union {
- JSValue *values; /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */
+ JSValue *values; /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */
void *ptr; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */
int8_t *int8_ptr; /* JS_CLASS_INT8_ARRAY */
uint8_t *uint8_ptr; /* JS_CLASS_UINT8_ARRAY, JS_CLASS_UINT8C_ARRAY */
init_list_head(&rt->gc_obj_list);
init_list_head(&rt->gc_zero_ref_count_list);
rt->gc_phase = JS_GC_PHASE_NONE;
-
+
#ifdef DUMP_LEAKS
init_list_head(&rt->string_list);
#endif
if (--ctx->header.ref_count > 0)
return;
assert(ctx->header.ref_count == 0);
-
+
#ifdef DUMP_ATOMS
JS_DumpAtoms(ctx->rt);
#endif
const char *cstr;
char *cstr2;
size_t len, len1;
-
+
str = JS_AtomToString(ctx, name);
if (JS_IsException(str))
return JS_ATOM_NULL;
uint32_t c;
StringBuffer b_s, *b = &b_s;
size_t len1;
-
+
p_start = (const uint8_t *)buf;
p_end = p_start + buf_len;
p = p_start;
sh->prop_size = prop_size;
sh->prop_count = 0;
sh->deleted_prop_count = 0;
-
+
/* insert in the hash table */
sh->hash = shape_initial_hash(proto);
sh->is_hashed = TRUE;
memcpy(sh, old_sh,
sizeof(JSShape) + sizeof(sh->prop[0]) * old_sh->prop_count);
list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
-
+
if (new_hash_size != (sh->prop_hash_mask + 1)) {
/* resize the hash table and the properties */
new_hash_mask = new_hash_size - 1;
uint32_t new_hash_size, i, j, new_hash_mask, new_size;
JSShapeProperty *old_pr, *pr;
JSProperty *prop, *new_prop;
-
+
sh = p->shape;
assert(!sh->is_hashed);
list_del(&old_sh->header.link);
memcpy(sh, old_sh, sizeof(JSShape));
list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
-
+
memset(prop_hash_end(sh) - new_hash_size, 0,
sizeof(prop_hash_end(sh)[0]) * new_hash_size);
p->shape = sh;
js_free(ctx, get_alloc_from_shape(old_sh));
-
+
/* reduce the size of the object properties */
new_prop = js_realloc(ctx, p->prop, sizeof(new_prop[0]) * new_size);
if (new_prop)
struct list_head *el;
JSObject *p;
JSGCObjectHeader *gp;
-
+
printf("JSShapes: {\n");
printf("%5s %4s %14s %5s %5s %s\n", "SLOT", "REFS", "PROTO", "SIZE", "COUNT", "PROPS");
for(i = 0; i < rt->shape_hash_size; i++) {
JSValue func_obj;
JSObject *p;
JSAtom name_atom;
-
+
func_obj = JS_NewObjectProtoClass(ctx, proto_val, JS_CLASS_C_FUNCTION);
if (JS_IsException(func_obj))
return func_obj;
JSObject *p = JS_VALUE_GET_OBJ(val);
JSForInIterator *it = p->u.for_in_iterator;
int i;
-
+
JS_FreeValueRT(rt, it->obj);
if (!it->is_array) {
for(i = 0; i < it->atom_count; i++) {
{
struct list_head *el;
JSGCObjectHeader *p;
-
+
rt->gc_phase = JS_GC_PHASE_DECREF;
for(;;) {
el = rt->gc_zero_ref_count_list.next;
case JS_TAG_BIG_INT:
#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
-#endif
+#endif
{
JSBigFloat *bf = JS_VALUE_GET_PTR(v);
bf_delete(&bf->num);
{
struct list_head *el, *el1;
JSGCObjectHeader *p;
-
+
init_list_head(&rt->tmp_obj_list);
/* decrement the refcount of all the children of all the GC
p->mark = 0; /* reset the mark for the next GC call */
mark_children(rt, p, gc_scan_incref_child);
}
-
+
/* restore the refcount of the objects to be deleted. */
list_for_each(el, &rt->tmp_obj_list) {
p = list_entry(el, JSGCObjectHeader, link);
}
}
rt->gc_phase = JS_GC_PHASE_NONE;
-
+
list_for_each_safe(el, el1, &rt->gc_zero_ref_count_list) {
p = list_entry(el, JSGCObjectHeader, link);
assert(p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT ||
JSProperty *pr;
JSShapeProperty *prs;
JSValueConst val;
-
+
if (JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT)
return NULL;
prs = find_own_property(&pr, JS_VALUE_GET_OBJ(func), JS_ATOM_name);
const char *str1;
JSObject *p;
BOOL backtrace_barrier;
-
+
js_dbuf_init(ctx, &dbuf);
if (filename) {
dbuf_printf(&dbuf, " at %s", filename);
JSProperty *pr;
JSValue brand;
JSAtom brand_atom;
-
+
if (unlikely(JS_VALUE_GET_TAG(home_obj) != JS_TAG_OBJECT)) {
JS_ThrowTypeErrorNotAnObject(ctx);
return -1;
brand = JS_DupValue(ctx, pr->u.value);
}
brand_atom = js_symbol_to_atom(ctx, brand);
-
+
if (JS_IsObject(obj)) {
p1 = JS_VALUE_GET_OBJ(obj);
prs = find_own_property(&pr, p1, brand_atom);
JSShapeProperty *prs;
JSProperty *pr;
JSValueConst brand;
-
+
/* get the home object of 'func' */
if (unlikely(JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT))
goto not_obj;
/* safety check */
if (unlikely(JS_VALUE_GET_TAG(brand) != JS_TAG_SYMBOL))
goto not_obj;
-
+
/* get the brand array of 'obj' */
if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) {
not_obj:
BOOL is_enumerable, num_sorted;
uint32_t num_key;
JSAtomKindEnum kind;
-
+
/* clear pointer for consistency in case of failure */
*ptab = NULL;
*plen = 0;
{
JSValue arr;
JSObject *p;
-
+
if (len > INT32_MAX)
return JS_ThrowRangeError(ctx, "invalid array length");
arr = JS_NewArray(ctx);
goto read_only_prop;
}
}
-
+
for(;;) {
if (p1->is_exotic) {
if (p1->fast_array) {
JSShapeProperty *prs;
JSValueConst val;
JSString *p;
-
+
prs = find_own_property(&pr, JS_VALUE_GET_OBJ(obj), JS_ATOM_name);
if (!prs)
return FALSE;
return 0;
}
flags = JS_PROP_THROW_STRICT;
- if (is_strict_mode(ctx))
+ if (is_strict_mode(ctx))
flags |= JS_PROP_NO_ADD;
return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, ctx->global_obj, flags);
}
JSValue obj1;
JSObject *p;
int res;
-
+
obj1 = JS_ToObject(ctx, obj);
if (JS_IsException(obj1))
return -1;
p = JS_VALUE_GET_OBJ(obj);
return p->is_HTMLDDA;
}
-
+
static int JS_ToBoolFree(JSContext *ctx, JSValue val)
{
uint32_t tag = JS_VALUE_GET_TAG(val);
case JS_TAG_BIG_INT:
#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
-#endif
+#endif
{
JSBigFloat *p = JS_VALUE_GET_PTR(val);
BOOL ret;
{
double d;
int c;
-
+
if (!is_float || radix != 10) {
const char *p = str;
uint64_t n_max, n;
int int_exp, is_neg;
-
+
is_neg = 0;
if (*p == '-') {
is_neg = 1;
/* accept _ between digits as a digit separator */
#define ATOD_ACCEPT_UNDERSCORES (1 << 5)
/* allow a suffix to override the type */
-#define ATOD_ACCEPT_SUFFIX (1 << 6)
+#define ATOD_ACCEPT_SUFFIX (1 << 6)
/* default type */
#define ATOD_TYPE_MASK (3 << 7)
#define ATOD_TYPE_FLOAT64 (0 << 7)
#define ATOD_TYPE_BIG_DECIMAL (3 << 7)
/* assume bigint mode: floats are parsed as integers if no decimal
point nor exponent */
-#define ATOD_MODE_BIGINT (1 << 9)
+#define ATOD_MODE_BIGINT (1 << 9)
#endif
/* accept -0x1 */
#define ATOD_ACCEPT_PREFIX_AFTER_SIGN (1 << 10)
bf_t *a;
int ret;
JSValue val;
-
+
val = JS_NewBigFloat(ctx);
if (JS_IsException(val))
return val;
bfdec_t *a;
int ret;
JSValue val;
-
+
val = JS_NewBigDecimal(ctx);
if (JS_IsException(val))
return val;
int i, j, len;
BOOL buf_allocated = FALSE;
JSValue val;
-
+
/* optional separator between digits */
sep = (flags & ATOD_ACCEPT_UNDERSCORES) ? '_' : 256;
has_legacy_octal = FALSE;
-
+
p = str;
p_start = p;
is_neg = 0;
(atod_type == ATOD_TYPE_FLOAT64
#ifdef CONFIG_BIGNUM
|| atod_type == ATOD_TYPE_BIG_FLOAT
-#endif
+#endif
) &&
strstart(p, "Infinity", &p)) {
#ifdef CONFIG_BIGNUM
if (has_legacy_octal)
goto fail;
} else
-#endif
+#endif
{
if (is_float && radix != 10)
goto fail;
goto fail;
val = ctx->rt->bigdecimal_ops.from_string(ctx, buf, radix, flags, NULL);
break;
-#endif
+#endif
default:
abort();
}
-
+
done:
if (buf_allocated)
js_free_rt(ctx->rt, buf);
const char *str;
const char *p;
size_t len;
-
+
str = JS_ToCStringLen(ctx, &len, val);
JS_FreeValue(ctx, val);
if (!str)
case JS_TAG_BIG_INT:
#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
-#endif
+#endif
{
JSBigFloat *p = JS_VALUE_GET_PTR(val);
bf_t a;
}
printf(" }");
}
-
+
if (js_class_has_bytecode(p->class_id)) {
JSFunctionBytecode *b = p->u.func.function_bytecode;
JSVarRef **var_refs;
const char *str, *p;
size_t len;
int flags;
-
+
str = JS_ToCStringLen(ctx, &len, val);
JS_FreeValue(ctx, val);
if (!str)
#ifdef CONFIG_BIGNUM
if (is_math_mode(ctx))
flags |= ATOD_MODE_BIGINT;
-#endif
+#endif
val = js_atof(ctx, p, &p, 0, flags);
p += skip_spaces(p);
if (!JS_IsException(val)) {
bf_rint(r, BF_RNDZ);
JS_FreeValue(ctx, val);
break;
-#endif
+#endif
case JS_TAG_STRING:
val = JS_StringToBigIntErr(ctx, val);
if (JS_IsException(val))
} else {
bf_t a_s, *a, *r;
int ret;
- JSValue res;
+ JSValue res;
res = JS_NewBigInt(ctx);
if (JS_IsException(res))
{
int64_t v;
bf_t *a;
-
+
if (JS_VALUE_GET_TAG(val) != JS_TAG_BIG_INT)
return val; /* fail safe */
a = JS_GetBigInt(val);
uint32_t tag;
JSBigDecimal *p;
bfdec_t *r;
-
+
tag = JS_VALUE_GET_NORM_TAG(val);
switch(tag) {
case JS_TAG_BIG_DECIMAL:
JSOverloadableOperatorEnum ovop;
JSObject *p;
JSValueConst args[2];
-
+
if (!ctx->allow_operator_overloading)
return 0;
-
+
opset2_obj = JS_UNDEFINED;
opset1_obj = JS_GetProperty(ctx, op1, JS_ATOM_Symbol_operatorSet);
if (JS_IsException(opset1_obj))
}
ovop = get_ovop_from_opcode(op);
-
+
if (opset1->operator_counter == opset2->operator_counter) {
p = opset1->self_ops[ovop];
} else if (opset1->operator_counter > opset2->operator_counter) {
} else {
new_op1 = JS_DupValue(ctx, op1);
}
-
+
if (opset2->is_primitive) {
if (is_numeric) {
new_op2 = JS_ToNumeric(ctx, op2);
/* XXX: could apply JS_ToPrimitive() if primitive type so that the
operator function does not get a value object */
-
+
method = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
if (ovop == JS_OVOP_LESS && (op == OP_lte || op == OP_gt)) {
args[0] = new_op2;
if (!ctx->allow_operator_overloading)
return 0;
-
+
opset1_obj = JS_GetProperty(ctx, op1, JS_ATOM_Symbol_operatorSet);
if (JS_IsException(opset1_obj))
goto exception;
bf_t a_s, *r, *a;
int ret, v;
JSValue res;
-
+
if (op == OP_plus && !is_math_mode(ctx)) {
JS_ThrowTypeError(ctx, "bigfloat argument with unary +");
JS_FreeValue(ctx, op1);
bfdec_t *r, *a;
int ret, v;
JSValue res;
-
+
if (op == OP_plus && !is_math_mode(ctx)) {
JS_ThrowTypeError(ctx, "bigdecimal argument with unary +");
JS_FreeValue(ctx, op1);
bf_t a_s, *r, *a;
int ret, v;
JSValue res;
-
+
if (op == OP_plus && !is_math_mode(ctx)) {
JS_ThrowTypeError(ctx, "bigint argument with unary +");
JS_FreeValue(ctx, op1);
if (ctx->rt->bigdecimal_ops.unary_arith(ctx, sp - 1, op, op1))
goto exception;
break;
-#endif
+#endif
default:
handle_float64:
{
static no_inline int js_not_slow(JSContext *ctx, JSValue *sp)
{
JSValue op1;
-
+
op1 = sp[-1];
#ifdef CONFIG_BIGNUM
if (JS_IsObject(op1)) {
bf_t a_s, b_s, *r, *a, *b;
int ret;
JSValue res;
-
+
res = JS_NewBigInt(ctx);
if (JS_IsException(res))
goto fail;
ret = bf_rem(r, a, b, BF_PREC_INF, BF_RNDZ,
BF_DIVREM_EUCLIDIAN) & BF_ST_INVALID_OP;
break;
-#endif
+#endif
case OP_mod:
ret = bf_rem(r, a, b, BF_PREC_INF, BF_RNDZ,
BF_RNDZ) & BF_ST_INVALID_OP;
bf_t a_s, b_s, *r, *a, *b;
int ret;
JSValue res;
-
+
res = JS_NewBigFloat(ctx);
if (JS_IsException(res))
goto fail;
if (JS_IsException(res))
goto fail;
r = JS_GetBigDecimal(res);
-
+
a = JS_ToBigDecimal(ctx, op1);
if (!a)
goto fail;
v += v2;
}
break;
-#endif
+#endif
case OP_mod:
if (v1 < 0 || v2 <= 0) {
sp[-2] = JS_NewFloat64(ctx, fmod(v1, v2));
if (ctx->rt->bigfloat_ops.binary_arith(ctx, op, sp - 2, op1, op2))
goto exception;
} else
-#endif
+#endif
if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
handle_bigint:
if (ctx->rt->bigint_ops.binary_arith(ctx, op, sp - 2, op1, op2))
if (dr < 0)
dr += d2;
break;
-#endif
+#endif
case OP_pow:
dr = js_pow(d1, d2);
break;
if (ctx->rt->bigfloat_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))
goto exception;
} else
-#endif
+#endif
if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
handle_bigint:
if (ctx->rt->bigint_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))
{
bf_t a_s, b_s, *a, *b;
int res;
-
+
a = JS_ToBigFloat(ctx, &a_s, op1);
if (!a) {
JS_FreeValue(ctx, op2);
}
a = JS_ToBigDecimal(ctx, op1); /* cannot fail */
b = JS_ToBigDecimal(ctx, op2); /* cannot fail */
-
+
switch(op) {
case OP_lt:
res = bfdec_cmp_lt(a, b); /* if NaN return false */
}
}
}
-#endif
+#endif
op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NUMBER);
if (JS_IsException(op1)) {
JS_FreeValue(ctx, op2);
if (res < 0)
goto exception;
} else
-#endif
+#endif
if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
res = ctx->rt->bigint_ops.compare(ctx, op, op1, op2);
if (res < 0)
if (res < 0)
goto exception;
} else
-#endif
+#endif
{
res = ctx->rt->bigint_ops.compare(ctx, OP_eq, op1, op2);
if (res < 0)
}
}
}
-#endif
+#endif
res = js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT);
} else if ((tag1 == JS_TAG_NULL && tag2 == JS_TAG_UNDEFINED) ||
(tag2 == JS_TAG_NULL && tag1 == JS_TAG_UNDEFINED)) {
bf_t r_s, *r = &r_s;
double d;
int ret;
-
+
/* always convert to Float64 */
bf_init(ctx->bf_ctx, r);
ret = bf_mul_pow_radix(r, a, 10, exponent,
{
JSObject *p;
p = JS_VALUE_GET_OBJ(op1);
- if (unlikely(p->is_HTMLDDA))
+ if (unlikely(p->is_HTMLDDA))
atom = JS_ATOM_undefined;
else if (JS_IsFunction(ctx, op1))
atom = JS_ATOM_function;
JSPropertyEnum *tab_atom;
uint32_t tab_atom_count, i;
JSValue obj1;
-
+
p = JS_VALUE_GET_OBJ(enum_obj);
it = p->u.for_in_iterator;
it->tab_atom = tab_atom;
it->atom_count = tab_atom_count;
}
-
+
for(i = 0; i < it->atom_count; i++) {
if (JS_DefinePropertyValue(ctx, enum_obj, it->tab_atom[i].atom, JS_NULL, JS_PROP_ENUMERABLE) < 0)
goto fail;
int is_array_iterator;
JSValue *arrp;
uint32_t i, count32, pos;
-
+
if (JS_VALUE_GET_TAG(sp[-2]) != JS_TAG_INT) {
JS_ThrowInternalError(ctx, "invalid index for append");
return -1;
int ret, gpn_flags;
JSPropertyDescriptor desc;
BOOL is_enumerable;
-
+
if (JS_VALUE_GET_TAG(source) != JS_TAG_OBJECT)
return 0;
if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p,
gpn_flags))
return -1;
-
+
for (i = 0; i < tab_atom_count; i++) {
if (pexcl) {
ret = JS_GetOwnPropertyInternal(ctx, NULL, pexcl, tab_atom[i].atom);
sf->prev_frame = prev_sf;
rt->current_stack_frame = sf;
ctx = p->u.cfunc.realm; /* change the current realm */
-
+
#ifdef CONFIG_BIGNUM
/* we only propagate the bignum mode as some runtime functions
test it */
#define DEF(id, size, n_pop, n_push, f) && case_OP_ ## id,
#if SHORT_OPCODES
#define def(id, size, n_pop, n_push, f)
-#else
+#else
#define def(id, size, n_pop, n_push, f) && case_default,
#endif
#include "quickjs-opcode.h"
sf->prev_frame = rt->current_stack_frame;
rt->current_stack_frame = sf;
ctx = b->realm; /* set the current realm */
-
+
restart:
for(;;) {
int call_argc;
JS_FreeValue(ctx, sp[-1]);
sp -= 2;
BREAK;
-
+
CASE(OP_throw):
JS_Throw(ctx, *--sp);
goto exception;
{
JSAtom atom;
JSValue val;
-
+
atom = get_u32(pc);
pc += 4;
val = JS_NewSymbolFromAtom(ctx, atom, JS_ATOM_TYPE_PRIVATE);
*sp++ = val;
}
BREAK;
-
+
CASE(OP_get_private_field):
{
JSValue val;
{
int class_flags;
JSAtom atom;
-
+
atom = get_u32(pc);
class_flags = pc[4];
pc += 5;
{
JSObject *p;
JSContext *realm;
-
+
if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT)
return ctx;
p = JS_VALUE_GET_OBJ(func_obj);
{
JSValue proto, obj;
JSContext *realm;
-
+
if (JS_IsUndefined(ctor)) {
proto = JS_DupValue(ctx, ctx->class_proto[class_id]);
} else {
if (!s->is_completed) {
async_func_free_frame(rt, s);
}
-
+
JS_FreeValueRT(rt, s->resolving_funcs[0]);
JS_FreeValueRT(rt, s->resolving_funcs[1]);
JS_FreeValue(ctx, promise);
goto fail;
}
-
+
/* Note: no need to create 'thrownawayCapability' as in
the spec */
for(i = 0; i < 2; i++)
}
js_async_function_resume(ctx, s);
-
+
async_func_free(ctx->rt, s);
return promise;
JSObject *generator; /* back pointer to the object (const) */
JSAsyncGeneratorStateEnum state;
/* func_state is NULL is state AWAITING_RETURN and COMPLETED */
- JSAsyncFunctionState *func_state;
+ JSAsyncFunctionState *func_state;
struct list_head queue; /* list of JSAsyncGeneratorRequest.link */
} JSAsyncGeneratorData;
int var_object_idx; /* -1 if none */
int arg_var_object_idx; /* -1 if none (var object for the argument scope) */
int arguments_var_idx; /* -1 if none */
- int arguments_arg_idx; /* argument variable definition in argument scope,
+ int arguments_arg_idx; /* argument variable definition in argument scope,
-1 if none */
int func_var_idx; /* variable containing the current function (-1
if none, only used if is_func_expr is true) */
int this_active_func_var_idx; /* variable containg the 'this.active_func' value, -1 if none */
int home_object_var_idx;
BOOL need_home_object;
-
+
int scope_level; /* index into fd->scopes if the current lexical scope */
int scope_first; /* index into vd->vars of first lexically scoped variable */
int scope_size; /* allocated size of fd->scopes array */
int last_opcode_pos; /* -1 if no last opcode */
int last_opcode_line_num;
BOOL use_short_opcodes; /* true if short opcodes are used in byte_code */
-
+
LabelSlot *label_slots;
int label_size; /* allocated size for label_slots[] */
int label_count;
JSContext *ctx = s->ctx;
va_list ap;
int backtrace_flags;
-
+
va_start(ap, fmt);
JS_ThrowError2(ctx, JS_SYNTAX_ERROR, fmt, ap, FALSE);
va_end(ap);
{
char *buf, *new_buf;
size_t size, new_size;
-
+
buf = *pbuf;
size = *psize;
if (size >= (SIZE_MAX / 3) * 2)
char ident_buf[128], *buf;
size_t ident_size, ident_pos;
JSAtom atom;
-
+
p = *pp;
buf = ident_buf;
ident_size = sizeof(ident_buf);
buf[ident_pos++] = '#';
for(;;) {
p1 = p;
-
+
if (c < 128) {
buf[ident_pos++] = c;
} else {
int c;
BOOL ident_has_escape;
JSAtom atom;
-
+
if (js_check_stack_overflow(s->ctx->rt, 0)) {
return js_parse_error(s, "stack overflow");
}
-
+
free_token(s, &s->token);
p = s->last_ptr = s->buf_ptr;
case 'm': case 'n': case 'o': case 'p':
case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x':
- case 'y': case 'z':
+ case 'y': case 'z':
case 'A': case 'B': case 'C': case 'D':
case 'E': case 'F': case 'G': case 'H':
case 'I': case 'J': case 'K': case 'L':
case 'M': case 'N': case 'O': case 'P':
case 'Q': case 'R': case 'S': case 'T':
case 'U': case 'V': case 'W': case 'X':
- case 'Y': case 'Z':
+ case 'Y': case 'Z':
case '_':
case '$':
/* identifier */
goto parse_number;
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8':
- case '9':
+ case '9':
/* number */
parse_number:
{
case CP_LS:
/* XXX: should avoid incrementing line_number, but
needed to handle HTML comments */
- goto line_terminator;
+ goto line_terminator;
default:
if (lre_is_space(c)) {
goto redo;
char ident_buf[128], *buf;
size_t ident_size, ident_pos;
JSAtom atom;
-
+
p = *pp;
buf = ident_buf;
ident_size = sizeof(ident_buf);
const uint8_t *p;
int c;
JSAtom atom;
-
+
if (js_check_stack_overflow(s->ctx->rt, 0)) {
return js_parse_error(s, "stack overflow");
}
-
+
free_token(s, &s->token);
p = s->last_ptr = s->buf_ptr;
case 'm': case 'n': case 'o': case 'p':
case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x':
- case 'y': case 'z':
+ case 'y': case 'z':
case 'A': case 'B': case 'C': case 'D':
case 'E': case 'F': case 'G': case 'H':
case 'I': case 'J': case 'K': case 'L':
case 'M': case 'N': case 'O': case 'P':
case 'Q': case 'R': case 'S': case 'T':
case 'U': case 'V': case 'W': case 'X':
- case 'Y': case 'Z':
+ case 'Y': case 'Z':
case '_':
case '$':
/* identifier : only pure ascii characters are accepted */
goto parse_number;
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8':
- case '9':
+ case '9':
/* number */
parse_number:
{
{
const uint8_t *p;
uint32_t c;
-
+
/* skip spaces and comments */
p = *pp;
for (;;) {
static int cpool_add(JSParseState *s, JSValue val)
{
JSFunctionDef *fd = s->cur_func;
-
+
if (js_resize_array(s->ctx, (void *)&fd->cpool, sizeof(fd->cpool[0]),
&fd->cpool_size, fd->cpool_count + 1))
return -1;
if (find_var_in_child_scope(ctx, fd, name, fd->scope_level) >= 0) {
return js_parse_error(s, "invalid redefinition of a variable");
}
-
+
if (fd->is_global_var) {
JSGlobalVar *hf;
hf = find_global_var(fd, name);
return js_parse_error(s, "invalid redefinition of global identifier");
}
}
-
+
if (fd->is_eval &&
(fd->eval_type == JS_EVAL_TYPE_GLOBAL ||
fd->eval_type == JS_EVAL_TYPE_MODULE) &&
BOOL is_non_reserved_ident;
JSAtom name;
int prop_type;
-
+
prop_type = PROP_TYPE_IDENT;
if (allow_method) {
if (token_is_pseudo_keyword(s, JS_ATOM_get)
if (level >= sizeof(state))
goto done;
state[level++] = '`';
- }
+ }
break;
case TOK_EOF:
goto done;
case '=':
bits |= SKIP_HAS_ASSIGNMENT;
break;
-
+
case TOK_DIV_ASSIGN:
tok_len = 2;
goto parse_regexp;
}
/* allow the 'in' binary operator */
-#define PF_IN_ACCEPTED (1 << 0)
+#define PF_IN_ACCEPTED (1 << 0)
/* allow function calls parsing in js_parse_postfix_expr() */
-#define PF_POSTFIX_CALL (1 << 1)
+#define PF_POSTFIX_CALL (1 << 1)
/* allow the exponentiation operator in js_parse_unary() */
-#define PF_POW_ALLOWED (1 << 2)
+#define PF_POW_ALLOWED (1 << 2)
/* forbid the exponentiation operator in js_parse_unary() */
-#define PF_POW_FORBIDDEN (1 << 3)
+#define PF_POW_FORBIDDEN (1 << 3)
static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags);
int ret, line_num;
JSParseFunctionEnum func_type;
const uint8_t *saved_buf_end;
-
+
js_parse_get_pos(s, &pos);
if (has_super) {
/* spec change: no argument evaluation */
static void emit_class_field_init(JSParseState *s)
{
int label_next;
-
+
emit_op(s, OP_scope_get_var);
emit_atom(s, JS_ATOM_class_fields_init);
emit_u16(s, s->cur_func->scope_level);
/* no need to call the class field initializer if not defined */
emit_op(s, OP_dup);
label_next = emit_goto(s, OP_if_false, -1);
-
+
emit_op(s, OP_scope_get_var);
emit_atom(s, JS_ATOM_this);
emit_u16(s, 0);
-
+
emit_op(s, OP_swap);
-
+
emit_op(s, OP_call_method);
emit_u16(s, 0);
ClassFieldsDef *cf)
{
int label_add_brand;
-
+
cf->fields_init_fd = js_parse_function_class_fields_init(s);
if (!cf->fields_init_fd)
return -1;
s->cur_func = cf->fields_init_fd;
-
+
if (!cf->is_static) {
/* add the brand to the newly created instance */
/* XXX: would be better to add the code only if needed, maybe in a
emit_op(s, OP_push_false); /* will be patched later */
cf->brand_push_pos = cf->fields_init_fd->last_opcode_pos;
label_add_brand = emit_goto(s, OP_if_false, -1);
-
+
emit_op(s, OP_scope_get_var);
emit_atom(s, JS_ATOM_this);
emit_u16(s, 0);
-
+
emit_op(s, OP_scope_get_var);
emit_atom(s, JS_ATOM_home_object);
emit_u16(s, 0);
-
+
emit_op(s, OP_add_brand);
-
+
emit_label(s, label_add_brand);
}
s->cur_func = s->cur_func->parent;
s->cur_func = cf->fields_init_fd;
emit_op(s, OP_return_undef);
s->cur_func = s->cur_func->parent;
-
+
cpool_idx = cpool_add(s, JS_NULL);
cf->fields_init_fd->parent_cpool_idx = cpool_idx;
emit_op(s, OP_fclosure);
} else {
class_name1 = class_name;
}
-
+
emit_op(s, OP_define_class);
emit_atom(s, class_name1);
emit_u8(s, class_flags);
cf->need_brand = FALSE;
cf->is_static = i;
}
-
+
ctor_fd = NULL;
while (s->token.val != '}') {
if (s->token.val == ';') {
}
is_private = prop_type & PROP_TYPE_PRIVATE;
prop_type &= ~PROP_TYPE_PRIVATE;
-
+
if ((name == JS_ATOM_constructor && !is_static &&
prop_type != PROP_TYPE_IDENT) ||
(name == JS_ATOM_prototype && is_static) ||
if (is_set) {
JSAtom setter_name;
int ret;
-
+
setter_name = get_private_setter_name(ctx, name);
if (setter_name == JS_ATOM_NULL)
goto fail;
} else if (prop_type == PROP_TYPE_IDENT && s->token.val != '(') {
ClassFieldsDef *cf = &class_fields[is_static];
JSAtom field_var_name = JS_ATOM_NULL;
-
+
/* class field */
/* XXX: spec: not consistent with method name checks */
js_parse_error(s, "invalid field name");
goto fail;
}
-
+
if (is_private) {
if (find_private_class_field(ctx, fd, name,
fd->scope_level) >= 0) {
emit_atom(s, name);
emit_u16(s, s->cur_func->scope_level);
}
-
+
if (s->token.val == '=') {
if (next_token(s))
goto fail;
} else {
JSParseFunctionEnum func_type;
JSFunctionKindEnum func_kind;
-
+
func_type = JS_PARSE_FUNC_METHOD;
func_kind = JS_FUNC_NORMAL;
if (prop_type == PROP_TYPE_STAR) {
emit_op(s, OP_null);
emit_op(s, OP_swap);
emit_op(s, OP_add_brand);
-
+
/* define the brand field in 'this' of the initializer */
if (!cf->fields_init_fd) {
if (emit_class_init_start(s, cf))
OP_add_brand_instance code */
cf->fields_init_fd->byte_code.buf[cf->brand_push_pos] = OP_push_true;
}
-
+
/* store the function to initialize the fields to that it can be
referenced by the constructor */
var_idx = define_var(s, fd, JS_ATOM_class_fields_init,
emit_u16(s, 0);
emit_op(s, OP_drop);
}
-
+
pop_scope(s);
pop_scope(s);
default:
break;
}
-
+
switch(opcode) {
case OP_scope_get_var: /* val -- */
assert(special == PUT_LVALUE_NOKEEP ||
{
JSFunctionDef *fd = s->cur_func;
JSVarDefEnum var_def_type;
-
+
if (name == JS_ATOM_yield && fd->func_kind == JS_FUNC_GENERATOR) {
return js_parse_error(s, "yield is a reserved identifier");
}
JSAtom prop_name, var_name;
int opcode, scope, tok1, skip_bits;
BOOL has_initializer;
-
+
if (has_ellipsis < 0) {
/* pre-parse destructuration target for spread detection */
js_parse_skip_parens_token(s, &skip_bits, FALSE);
FuncCallType call_type;
int optional_chaining_label;
BOOL accept_lparen = (parse_flags & PF_POSTFIX_CALL) != 0;
-
+
call_type = FUNC_CALL_NORMAL;
switch(s->token.val) {
case TOK_NUMBER:
if (next_token(s))
return -1;
break;
-
+
case TOK_DIV_ASSIGN:
s->buf_ptr -= 2;
goto parse_regexp;
for(;;) {
JSFunctionDef *fd = s->cur_func;
BOOL has_optional_chain = FALSE;
-
+
if (s->token.val == TOK_QUESTION_MARK_DOT) {
/* optional chaining */
if (next_token(s))
put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_SECOND,
FALSE);
if (next_token(s))
- return -1;
+ return -1;
}
break;
}
static __exception int js_parse_coalesce_expr(JSParseState *s, int parse_flags)
{
int label1;
-
+
if (js_parse_logical_and_or(s, TOK_LOR, parse_flags))
return -1;
if (s->token.val == TOK_DOUBLE_QUESTION_MARK) {
for(;;) {
if (next_token(s))
return -1;
-
+
emit_op(s, OP_dup);
emit_op(s, OP_is_undefined_or_null);
emit_goto(s, OP_if_false, label1);
emit_op(s, OP_drop);
-
+
if (js_parse_expr_binary(s, 8, parse_flags))
return -1;
if (s->token.val != TOK_DOUBLE_QUESTION_MARK)
if (s->token.val == TOK_YIELD) {
BOOL is_star = FALSE, is_async;
-
+
if (!(s->cur_func->func_kind & JS_FUNC_GENERATOR))
return js_parse_error(s, "unexpected 'yield' keyword");
if (!s->cur_func->in_function_body)
undefined) */
emit_op(s, OP_drop);
emit_op(s, OP_undefined);
-
+
emit_op(s, OP_undefined); /* initial value */
-
+
emit_label(s, label_loop);
emit_op(s, OP_iterator_next);
if (is_async)
label_return = emit_goto(s, OP_if_true, -1);
emit_op(s, OP_drop);
emit_goto(s, OP_goto, label_loop);
-
+
emit_label(s, label_return);
emit_op(s, OP_push_i32);
emit_u32(s, 2);
emit_op(s, OP_strict_eq);
label_throw = emit_goto(s, OP_if_true, -1);
-
+
/* return handling */
if (is_async)
emit_op(s, OP_await);
emit_op(s, OP_get_field);
emit_atom(s, JS_ATOM_value);
-
+
emit_label(s, label_return1);
emit_op(s, OP_nip);
emit_op(s, OP_nip);
emit_op(s, OP_nip);
emit_return(s, TRUE);
-
+
/* throw handling */
emit_label(s, label_throw);
emit_op(s, OP_iterator_call);
emit_op(s, OP_throw_error);
emit_atom(s, JS_ATOM_NULL);
emit_u8(s, JS_THROW_ERROR_ITERATOR_THROW);
-
+
emit_label(s, label_next);
emit_op(s, OP_get_field);
emit_atom(s, JS_ATOM_value);
emit_op(s, OP_nip);
} else {
int label_next;
-
+
if (is_async)
emit_op(s, OP_await);
emit_op(s, OP_yield);
emit_label(s, label_next);
}
return 0;
- } else if (s->token.val == '(' &&
+ } else if (s->token.val == '(' &&
js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) {
return js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
JS_FUNC_NORMAL, JS_ATOM_NULL,
put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_TOP, FALSE);
} else if (op >= TOK_LAND_ASSIGN && op <= TOK_DOUBLE_QUESTION_MARK_ASSIGN) {
int label, label1, depth_lvalue, label2;
-
+
if (next_token(s))
return -1;
if (get_lvalue(s, &opcode, &scope, &name, &label,
label1 = emit_goto(s, op == TOK_LOR_ASSIGN ? OP_if_true : OP_if_false,
-1);
emit_op(s, OP_drop);
-
+
if (js_parse_assign_expr2(s, parse_flags)) {
JS_FreeAtom(s->ctx, name);
return -1;
if (opcode == OP_get_ref_value && name == name0) {
set_object_name(s, name);
}
-
+
switch(depth_lvalue) {
case 1:
emit_op(s, OP_insert2);
put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_NOKEEP_DEPTH,
FALSE);
label2 = emit_goto(s, OP_goto, -1);
-
+
emit_label(s, label1);
/* remove the lvalue stack entries */
emit_op(s, OP_await);
}
}
-
+
top = s->cur_func->top_break;
while (top != NULL) {
if (top->has_iterator || top->label_finally != -1) {
emit_label(s, label_finally);
if (s->token.val == TOK_FINALLY) {
int saved_eval_ret_idx = 0; /* avoid warning */
-
+
if (next_token(s))
goto fail;
/* on the stack: ret_value gosub_ret_value */
emit_u16(s, saved_eval_ret_idx);
set_eval_ret_undefined(s);
}
-
+
if (js_parse_block(s))
goto fail;
if (js_parse_expect_semi(s))
goto fail;
break;
-
+
case TOK_ENUM:
case TOK_EXPORT:
case TOK_EXTENDS:
{
struct list_head *el;
JSModuleDef *m;
-
+
/* first look at the loaded modules */
list_for_each(el, &ctx->loaded_modules) {
m = list_entry(el, JSModuleDef, link);
{
const char *base_cname, *cname;
JSModuleDef *m;
-
+
base_cname = JS_AtomToCString(ctx, base_module_name);
if (!base_cname)
return NULL;
BOOL is_c_module;
int i;
JSVarRef *var_ref;
-
+
if (m->func_created)
return 0;
m->func_created = TRUE;
/* do it on the dependencies */
-
+
for(i = 0; i < m->req_module_entries_count; i++) {
JSReqModuleEntry *rme = &m->req_module_entries[i];
if (js_create_module_function(ctx, rme->module) < 0)
}
return 0;
-}
+}
+
-
/* Prepare a module to be executed by resolving all the imported
variables. */
static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m,
JSObject *p;
BOOL is_c_module;
JSValue ret_val;
-
+
if (js_check_stack_overflow(ctx->rt, 0)) {
JS_ThrowStackOverflow(ctx);
return -1;
}
-
+
#ifdef DUMP_MODULE_RESOLVE
{
char buf1[ATOM_GET_STR_BUF_SIZE];
{
JSAtom filename;
JSModuleDef *m;
-
+
filename = JS_GetScriptOrModuleName(ctx, 0);
if (filename == JS_ATOM_NULL)
goto fail;
JSValueConst *resolving_funcs = (JSValueConst *)func_data;
JSValueConst error;
JSValue ret;
-
+
/* XXX: check if the test is necessary */
if (argc >= 1)
error = argv[0];
JSValueConst *resolving_funcs = (JSValueConst *)func_data;
JSModuleDef *m = JS_VALUE_GET_PTR(func_data[2]);
JSValue ret, ns;
-
+
/* return the module namespace */
ns = JS_GetModuleNamespace(ctx, m);
if (JS_IsException(ns)) {
JSModuleDef *m;
JSValue ret, err, func_obj, evaluate_resolving_funcs[2];
JSValueConst func_data[3];
-
+
m = js_host_resolve_imported_module(ctx, basename, filename);
if (!m)
goto fail;
-
+
if (js_resolve_module(ctx, m) < 0) {
js_free_modules(ctx, JS_FREE_MODULE_NOT_RESOLVED);
goto fail;
const char *filename)
{
JSValue promise, resolving_funcs[2];
-
+
promise = JS_NewPromiseCapability(ctx, resolving_funcs);
if (JS_IsException(promise))
return JS_EXCEPTION;
filename = JS_ToCString(ctx, specifier);
if (!filename)
goto exception;
-
+
JS_LoadModuleInternal(ctx, basename, filename,
resolving_funcs);
JS_FreeCString(ctx, filename);
JS_FreeAtom(ctx, basename);
if (JS_IsException(basename_val))
return basename_val;
-
+
promise = JS_NewPromiseCapability(ctx, resolving_funcs);
if (JS_IsException(promise)) {
JS_FreeValue(ctx, basename_val);
args[1] = resolving_funcs[1];
args[2] = basename_val;
args[3] = specifier;
-
+
/* cannot run JS_LoadModuleInternal synchronously because it would
cause an unexpected recursion in js_evaluate_module() */
JS_EnqueueJob(ctx, js_dynamic_import_job, 4, args);
JSModuleDef *module = JS_VALUE_GET_PTR(func_data[0]);
JSValueConst error = argv[0];
int i;
-
+
if (js_check_stack_overflow(ctx->rt, 0))
return JS_ThrowStackOverflow(ctx);
JSModuleDef *module = JS_VALUE_GET_PTR(func_data[0]);
ExecModuleList exec_list_s, *exec_list = &exec_list_s;
int i;
-
+
if (module->status == JS_MODULE_STATUS_EVALUATED) {
assert(module->eval_has_exception);
return JS_UNDEFINED;
/* sort by increasing async_evaluation timestamp */
rqsort(exec_list->tab, exec_list->count, sizeof(exec_list->tab[0]),
exec_module_list_cmp, NULL);
-
+
for(i = 0; i < exec_list->count; i++) {
JSModuleDef *m = exec_list->tab[i];
if (m->status == JS_MODULE_STATUS_EVALUATED) {
*pvalue = JS_GetException(ctx);
return -1;
}
-
+
#ifdef DUMP_MODULE_RESOLVE
{
char buf1[ATOM_GET_STR_BUF_SIZE];
/* push 'm' on stack */
m->stack_prev = *pstack_top;
*pstack_top = m;
-
+
for(i = 0; i < m->req_module_entries_count; i++) {
JSReqModuleEntry *rme = &m->req_module_entries[i];
m1 = rme->module;
index = js_inner_module_evaluation(ctx, m1, index, pstack_top, pvalue);
- if (index < 0)
+ if (index < 0)
return -1;
assert(m1->status == JS_MODULE_STATUS_EVALUATING ||
m1->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
{
JSFunctionDef *fd = s->cur_func;
int tok;
-
+
if (s->token.val == TOK_FUNCTION ||
(token_is_pseudo_keyword(s, JS_ATOM_async) &&
peek_token(s, TRUE) == TOK_FUNCTION)) {
int pos, len, op;
JSAtom atom;
const JSOpCode *oi;
-
+
pos = 0;
while (pos < bc_len) {
op = bc_buf[pos];
oi = &short_opcode_info(op);
else
oi = &opcode_info[op];
-
+
len = oi->size;
switch(oi->fmt) {
case OP_FMT_atom:
update_label(s, *plabel_done, 1);
s->jump_size++;
}
-
+
/* return the position of the next opcode */
static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
JSAtom var_name, int scope_level, int op,
is_arg_scope = (idx == ARG_SCOPE_END);
if (var_idx >= 0)
break;
-
+
if (!is_arg_scope) {
var_idx = find_var(ctx, fd, var_name);
if (var_idx >= 0)
dbuf_put_u16(bc, idx);
var_object_test(ctx, s, var_name, op, bc, &label_done, 0);
}
-
+
if (fd->is_eval)
break; /* it it necessarily the top level function */
}
{
/* if the field is not initialized, the error is catched when
accessing it */
- if (is_ref)
+ if (is_ref)
dbuf_putc(bc, OP_get_var_ref);
else
dbuf_putc(bc, OP_get_loc);
int idx, var_kind;
JSFunctionDef *fd;
BOOL is_ref;
-
+
fd = s;
is_ref = FALSE;
for(;;) {
int i, count;
JSVarDef *vd;
BOOL is_arg_scope;
-
+
count = b->arg_count + b->var_count + b->closure_var_count;
s->closure_var = NULL;
s->closure_var_count = 0;
visible if there are cyclic module references */
if (s->module) {
label_next = new_label_fd(s, -1);
-
+
/* if 'this' is true, initialize the global variables and return */
dbuf_putc(bc, OP_push_this);
dbuf_putc(bc, OP_if_false);
update_label(s, label_next, 1);
s->jump_size++;
}
-
+
/* add the global variables (only happens if s->is_global_var is
true) */
for(i = 0; i < s->global_var_count; i++) {
}
if (!has_closure) {
int flags;
-
+
flags = 0;
if (s->eval_type != JS_EVAL_TYPE_GLOBAL)
flags |= JS_PROP_CONFIGURABLE;
/* global function definitions need a specific handling */
dbuf_putc(bc, OP_fclosure);
dbuf_put_u32(bc, hf->cpool_idx);
-
+
dbuf_putc(bc, OP_define_func);
dbuf_put_u32(bc, JS_DupAtom(ctx, hf->var_name));
dbuf_putc(bc, flags);
-
+
goto done_global_var;
} else {
if (hf->is_lexical) {
if (s->module) {
dbuf_putc(bc, OP_return_undef);
-
+
dbuf_putc(bc, OP_label);
dbuf_put_u32(bc, label_next);
s->label_slots[label_next].pos2 = bc->size;
for(i = 0; i < s->global_var_count; i++) {
JSGlobalVar *hf = &s->global_vars[i];
int flags;
-
+
/* check if global variable (XXX: simplify) */
for(idx = 0; idx < s->closure_var_count; idx++) {
JSClosureVar *cv = &s->closure_var[idx];
cv->var_name == JS_ATOM__arg_var_)
goto next;
}
-
+
dbuf_putc(&bc_out, OP_check_define_var);
dbuf_put_u32(&bc_out, JS_DupAtom(ctx, hf->var_name));
flags = 0;
case OP_get_array_el_opt_chain: /* equivalent to OP_get_array_el */
dbuf_putc(&bc_out, OP_get_array_el);
break;
-
+
default:
no_change:
dbuf_put(&bc_out, bc_buf + pos, len);
/* mark as explored and store the stack size */
s->stack_level_tab[pos] = stack_len;
s->catch_pos_tab[pos] = catch_pos;
-
+
/* queue the new PC to explore */
if (js_resize_array(ctx, (void **)&s->pc_stack, sizeof(s->pc_stack[0]),
&s->pc_stack_size, s->pc_stack_len + 1))
b->realm = JS_DupContext(ctx);
add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE);
-
+
#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 1)
if (!(fd->js_mode & JS_MODE_STRIP)) {
js_dump_function_bytecode(ctx, b);
static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s)
{
JSFunctionDef *fd;
-
+
fd = js_new_function_def(s->ctx, s->cur_func, FALSE, FALSE,
s->filename, 0);
if (!fd)
fd->func_name = JS_ATOM_NULL;
fd->has_prototype = FALSE;
fd->has_home_object = TRUE;
-
+
fd->has_arguments_binding = FALSE;
fd->has_this_binding = TRUE;
fd->is_derived_class_constructor = FALSE;
fd->super_call_allowed = FALSE;
fd->super_allowed = fd->has_home_object;
fd->arguments_allowed = FALSE;
-
+
fd->func_kind = JS_FUNC_NORMAL;
fd->func_type = JS_PARSE_FUNC_METHOD;
return fd;
if (func_type == JS_PARSE_FUNC_CLASS_CONSTRUCTOR) {
emit_class_field_init(s);
}
-
+
/* parse arguments */
fd->has_simple_parameter_list = TRUE;
fd->has_parameter_expressions = FALSE;
if (push_scope(s) < 0)
return -1;
}
-
+
while (s->token.val != ')') {
JSAtom name;
BOOL rest = FALSE;
has_opt_arg = TRUE;
} else if (s->token.val == '=') {
int label;
-
+
fd->has_simple_parameter_list = FALSE;
has_opt_arg = TRUE;
}
idx = vd->scope_next;
}
-
+
/* the argument scope has no parent, hence we don't use pop_scope(s) */
emit_op(s, OP_leave_scope);
emit_u16(s, fd->scope_level);
fd->scope_level = 0;
fd->scope_first = fd->scopes[fd->scope_level].first;
}
-
+
if (next_token(s))
goto fail;
by just using next_token() here for normal functions, but it is
necessary for arrow functions with an expression body. */
reparse_ident_token(s);
-
+
/* create the function object */
{
int idx;
/* it is considered as defined at the top level
(needed for annex B.3.3.4 and B.3.3.5
checks) */
- hf->scope_level = 0;
+ hf->scope_level = 0;
hf->force_init = ((s->cur_func->js_mode & JS_MODE_STRICT) != 0);
/* store directly into global var, bypass lexical scope */
emit_op(s, OP_dup);
push_scope(s); /* body scope */
fd->body_scope = fd->scope_level;
-
+
err = js_parse_program(s);
if (err) {
fail:
js_free(ctx, s->hash_table);
s->hash_table = new_hash_table;
s->hash_size = new_hash_size;
-
+
for(i = 0; i < s->hash_size; i++) {
s->hash_table[i] = -1;
}
for(i = 0; i < s->object_count; i++) {
e = &s->object_tab[i];
- h = js_object_list_get_hash(e->obj, s->hash_size);
+ h = js_object_list_get_hash(e->obj, s->hash_size);
e->hash_next = s->hash_table[h];
s->hash_table[h] = i;
}
{
JSObjectListEntry *e;
uint32_t h, new_hash_size;
-
+
if (js_resize_array(ctx, (void *)&s->object_tab,
sizeof(s->object_tab[0]),
&s->object_size, s->object_count + 1))
return -1;
}
e = &s->object_tab[s->object_count++];
- h = js_object_list_get_hash(obj, s->hash_size);
+ h = js_object_list_get_hash(obj, s->hash_size);
e->obj = obj;
e->hash_next = s->hash_table[h];
s->hash_table[h] = s->object_count - 1;
/* must test empty size because there is no hash table */
if (s->object_count == 0)
return -1;
- h = js_object_list_get_hash(obj, s->hash_size);
+ h = js_object_list_get_hash(obj, s->hash_size);
p = s->hash_table[h];
while (p != -1) {
e = &s->object_tab[p];
case JS_TAG_BIG_DECIMAL:
tag1 = BC_TAG_BIG_DECIMAL;
break;
-#endif
+#endif
default:
abort();
}
int bpos, d;
uint8_t v8;
size_t i0;
-
+
/* little endian BCD */
i = 0;
while (i < a->len && a->tab[i] == 0)
return -1;
}
bc_put_leb128(s, len);
-
+
bpos = 0;
v8 = 0;
i0 = i;
JSFunctionBytecode *b = JS_VALUE_GET_PTR(obj);
uint32_t flags;
int idx, i;
-
+
bc_put_u8(s, BC_TAG_FUNCTION_BYTECODE);
flags = idx = 0;
bc_set_flags(&flags, &idx, b->has_prototype, 1);
bc_put_u16(s, flags);
bc_put_u8(s, b->js_mode);
bc_put_atom(s, b->func_name);
-
+
bc_put_leb128(s, b->arg_count);
bc_put_leb128(s, b->var_count);
bc_put_leb128(s, b->defined_arg_count);
} else {
bc_put_leb128(s, 0);
}
-
+
for(i = 0; i < b->closure_var_count; i++) {
JSClosureVar *cv = &b->closure_var[i];
bc_put_atom(s, cv->var_name);
assert(idx <= 8);
bc_put_u8(s, flags);
}
-
+
if (JS_WriteFunctionBytecode(s, b->byte_code_buf, b->byte_code_len))
goto fail;
-
+
if (b->has_debug) {
bc_put_atom(s, b->debug.filename);
bc_put_leb128(s, b->debug.line_num);
bc_put_leb128(s, b->debug.pc2line_len);
dbuf_put(&s->dbuf, b->debug.pc2line_buf, b->debug.pc2line_len);
}
-
+
for(i = 0; i < b->cpool_count; i++) {
if (JS_WriteObjectRec(s, b->cpool[i]))
goto fail;
{
JSModuleDef *m = JS_VALUE_GET_PTR(obj);
int i;
-
+
bc_put_u8(s, BC_TAG_MODULE);
bc_put_atom(s, m->module_name);
-
+
bc_put_leb128(s, m->req_module_entries_count);
for(i = 0; i < m->req_module_entries_count; i++) {
JSReqModuleEntry *rme = &m->req_module_entries[i];
bc_put_atom(s, rme->module_name);
}
-
+
bc_put_leb128(s, m->export_entries_count);
for(i = 0; i < m->export_entries_count; i++) {
JSExportEntry *me = &m->export_entries[i];
}
bc_put_atom(s, me->export_name);
}
-
+
bc_put_leb128(s, m->star_export_entries_count);
for(i = 0; i < m->star_export_entries_count; i++) {
JSStarExportEntry *se = &m->star_export_entries[i];
bc_put_leb128(s, se->req_module_idx);
}
-
+
bc_put_leb128(s, m->import_entries_count);
for(i = 0; i < m->import_entries_count; i++) {
JSImportEntry *mi = &m->import_entries[i];
}
bc_put_u8(s, m->has_tla);
-
+
if (JS_WriteObjectRec(s, m->func_obj))
goto fail;
return 0;
JSValue val;
int ret;
BOOL is_template;
-
+
if (s->allow_bytecode && !p->extensible) {
/* not extensible array: we consider it is a
template when we are saving bytecode */
{
JSObject *p = JS_VALUE_GET_OBJ(obj);
int ret, idx;
-
+
if (s->allow_reference) {
idx = js_object_list_find(s->ctx, &s->object_list, p);
if (idx >= 0) {
s->first_atom = 1;
js_dbuf_init(ctx, &s->dbuf);
js_object_list_init(&s->object_list);
-
+
if (JS_WriteObjectRec(s, obj))
goto fail;
if (JS_WriteObjectAtoms(s))
JSObject **objects;
int objects_count;
int objects_size;
-
+
#ifdef DUMP_READ_OBJECT
const uint8_t *ptr_last;
int level;
limb_t v;
bf_t *a;
int bpos, d;
-
+
p = js_new_bf(s->ctx);
if (!p)
goto fail;
case BC_TAG_BIG_DECIMAL:
obj = JS_MKPTR(JS_TAG_BIG_DECIMAL, p);
break;
-#endif
+#endif
default:
abort();
}
b = js_mallocz(ctx, function_size);
if (!b)
return JS_EXCEPTION;
-
+
memcpy(b, &bc, offsetof(JSFunctionBytecode, debug));
b->header.ref_count = 1;
if (local_count != 0) {
if (b->cpool_count != 0) {
b->cpool = (void *)((uint8_t*)b + cpool_offset);
}
-
+
add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE);
-
+
obj = JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b);
#ifdef DUMP_READ_OBJECT
JSAtom module_name;
int i;
uint8_t v8;
-
+
if (bc_get_atom(s, &module_name))
goto fail;
#ifdef DUMP_READ_OBJECT
JSAtom atom;
JSValue val;
int ret;
-
+
obj = JS_NewObject(ctx);
if (BC_add_object_ref(s, obj))
goto fail;
uint8_t array_tag;
JSValueConst args[3];
uint32_t offset, len, idx;
-
+
if (bc_get_u8(s, &array_tag))
return JS_EXCEPTION;
if (array_tag >= JS_TYPED_ARRAY_COUNT)
JSContext *ctx = s->ctx;
uint32_t byte_length;
JSValue obj;
-
+
if (bc_get_leb128(s, &byte_length))
return JS_EXCEPTION;
if (unlikely(s->buf_end - s->ptr < byte_length)) {
uint8_t *data_ptr;
JSValue obj;
uint64_t u64;
-
+
if (bc_get_leb128(s, &byte_length))
return JS_EXCEPTION;
if (bc_get_u64(s, &u64))
set_cycle_flag(ctx, proto);
}
-void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj,
+void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj,
JSValueConst proto)
{
JS_SetConstructor2(ctx, func_obj, proto,
if (!res) {
return JS_ThrowTypeError(ctx, "proxy preventExtensions handler returned false");
}
-
+
p = JS_VALUE_GET_OBJ(obj);
flags = JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK;
if (JS_GetOwnPropertyNamesInternal(ctx, &props, &len, p, flags))
JSPropertyEnum *props;
uint32_t len, i;
int flags, res;
-
+
if (!JS_IsObject(obj))
return JS_TRUE;
if (res < 0)
return JS_EXCEPTION;
res ^= 1;
-done:
+done:
js_free_prop_enum(ctx, props, len);
return JS_NewBool(ctx, res);
obj = JS_NewObject(ctx);
if (JS_IsException(obj))
return obj;
-
+
iter = JS_GetIterator(ctx, iterable, FALSE);
if (JS_IsException(iter))
goto fail;
next_method = JS_GetProperty(ctx, iter, JS_ATOM_next);
if (JS_IsException(next_method))
goto fail;
-
+
for(;;) {
JSValue key, value, item;
item = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done);
JS_FreeValue(ctx, item);
break;
}
-
+
key = JS_UNDEFINED;
value = JS_UNDEFINED;
if (!JS_IsObject(item)) {
string_buffer_init(ctx, b, 0);
string_buffer_putc8(b, '(');
-
+
if (func_kind == JS_FUNC_ASYNC || func_kind == JS_FUNC_ASYNC_GENERATOR) {
string_buffer_puts8(b, "async ");
}
JSValue v, r = JS_UNDEFINED;
int64_t k;
BOOL done;
-
+
iter = JS_GetIterator(ctx, items, FALSE);
if (JS_IsException(iter))
goto exception;
if (!JS_IsObject(proto)) {
JSContext *realm;
JSValueConst proto1;
-
+
JS_FreeValue(ctx, proto);
realm = JS_GetFunctionRealm(ctx, new_target);
if (!realm)
JSValueConst errors)
{
JSValue obj;
-
+
obj = JS_NewObjectProtoClass(ctx,
ctx->native_error_proto[JS_AGGREGATE_ERROR],
JS_CLASS_ERROR);
fromPresent = JS_TryGetPropertyInt64(ctx, obj, from, &val);
if (fromPresent < 0)
goto exception;
-
+
if (fromPresent) {
if (JS_SetPropertyInt64(ctx, obj, to, val) < 0)
goto exception;
JSValue ctor, ret, species;
int res;
JSContext *realm;
-
+
res = JS_IsArray(ctx, obj);
if (res < 0)
return JS_EXCEPTION;
int64_t len, idx;
JSValue *arrp;
uint32_t count;
-
+
obj = JS_ToObject(ctx, this_val);
if (js_get_length64(ctx, &len, obj))
goto exception;
this_arg = JS_UNDEFINED;
if (argc > 1)
this_arg = argv[1];
-
+
if (check_function(ctx, func))
goto exception;
case JS_TAG_BIG_INT:
#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
-#endif
+#endif
{
JSBigFloat *p = JS_VALUE_GET_PTR(val);
double d;
uint32_t idx;
JSObject *p;
JSString *p1, *p2;
-
+
if (__JS_AtomIsTaggedInt(prop)) {
idx = __JS_AtomToUInt32(prop);
p = JS_VALUE_GET_OBJ(this_obj);
goto exception;
if (js_get_length64(ctx, &n, raw) < 0)
goto exception;
-
+
for (i = 0; i < n; i++) {
val = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, raw, i));
if (JS_IsException(val))
JSValue str;
JSString *p;
BOOL ret;
-
+
str = JS_ToStringCheckObject(ctx, this_val);
if (JS_IsException(str))
return JS_EXCEPTION;
JS_FreeValue(ctx, str);
if (JS_IsException(ret))
return JS_EXCEPTION;
-
+
p = JS_VALUE_GET_STRING(ret);
for (; i < p->len; i++) {
c = p->u.str16[i];
{
int ret;
JSValue flags;
-
+
ret = js_is_regexp(ctx, regexp);
if (ret < 0)
return -1;
}
if (JS_IsException(repl_str))
goto exception;
-
+
string_buffer_concat(b, sp, endOfLastMatch, pos);
string_buffer_concat_value_free(b, repl_str);
endOfLastMatch = pos + searchp->len;
return JS_EXCEPTION;
}
-static int js_string_normalize1(JSContext *ctx, uint32_t **pout_buf,
+static int js_string_normalize1(JSContext *ctx, uint32_t **pout_buf,
JSValueConst val,
UnicodeNormalizationEnum n_type)
{
int buf_len, out_len;
uint32_t *buf, *out_buf;
-
+
buf_len = JS_ToUTF32String(ctx, &buf, val);
if (buf_len < 0)
return -1;
JSValue a, b;
int cmp, a_len, b_len;
uint32_t *a_buf, *b_buf;
-
+
a = JS_ToStringCheckObject(ctx, this_val);
if (JS_IsException(a))
return JS_EXCEPTION;
static struct { const char *tag, *attr; } const defs[] = {
{ "a", "name" }, { "big", NULL }, { "blink", NULL }, { "b", NULL },
{ "tt", NULL }, { "font", "color" }, { "font", "size" }, { "i", NULL },
- { "a", "href" }, { "small", NULL }, { "strike", NULL },
+ { "a", "href" }, { "small", NULL }, { "strike", NULL },
{ "sub", NULL }, { "sup", NULL },
};
{
time_t ti;
int res;
-
+
time /= 1000; /* convert to seconds */
if (sizeof(time_t) == 4) {
/* on 32-bit systems, we need to clamp the time value to the
{
struct tm *tm;
time_t gm_ti, loc_ti;
-
+
tm = gmtime(&ti);
gm_ti = mktime(tm);
-
+
tm = localtime(&ti);
loc_ti = mktime(tm);
if (p->len == 0) {
empty_regex:
return JS_NewString(ctx, "(?:)");
- }
+ }
string_buffer_init2(ctx, b, p->len, p->is_wide_char);
/* Escape '/' and newline sequences as needed */
else
return JS_ThrowTypeErrorInvalidClass(ctx, JS_CLASS_REGEXP);
}
-
+
flags = lre_get_flags(re->bytecode->u.str8);
return JS_NewBool(ctx, (flags & mask) != 0);
}
int start = -1;
int end = -1;
JSValue val;
-
+
if (group_name_ptr && i > 0) {
if (*group_name_ptr) name = group_name_ptr;
group_name_ptr += strlen(group_name_ptr) + 1;
JSString *strp;
int64_t lastIndex;
JSRegExpStringIteratorData *it;
-
+
if (!JS_IsObject(R))
return JS_ThrowTypeErrorNotAnObject(ctx);
flags = JS_UNDEFINED;
matcher = JS_UNDEFINED;
iter = JS_UNDEFINED;
-
+
S = JS_ToString(ctx, argv[0]);
if (JS_IsException(S))
goto exception;
if (JS_SetProperty(ctx, matcher, JS_ATOM_lastIndex,
JS_NewInt64(ctx, lastIndex)) < 0)
goto exception;
-
+
iter = JS_NewObjectClass(ctx, JS_CLASS_REGEXP_STRING_ITERATOR);
if (JS_IsException(iter))
goto exception;
str = JS_ToString(ctx, argv[0]);
if (JS_IsException(str))
goto exception;
-
+
sp = JS_VALUE_GET_STRING(str);
rp = NULL;
functionalReplace = JS_IsFunction(ctx, rep);
while (q < size) {
if (JS_SetProperty(ctx, splitter, JS_ATOM_lastIndex, JS_NewInt32(ctx, q)) < 0)
goto exception;
- JS_FreeValue(ctx, z);
+ JS_FreeValue(ctx, z);
z = JS_RegExpExec(ctx, splitter, str);
if (JS_IsException(z))
goto exception;
JS_FreeValue(ctx, ctor);
JS_FreeValue(ctx, splitter);
JS_FreeValue(ctx, flags);
- JS_FreeValue(ctx, z);
+ JS_FreeValue(ctx, z);
return A;
}
{
JSValue prop_val;
JSAtom prop_name;
-
+
if (json_next_token(s))
goto fail;
val = JS_NewObject(ctx);
JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len,
const char *filename)
{
- return JS_ParseJSON2(ctx, buf, buf_len, filename, 0);
+ return JS_ParseJSON2(ctx, buf, buf_len, filename, 0);
}
static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder,
int64_t i, len;
int cl, ret;
BOOL has_content;
-
+
indent1 = JS_UNDEFINED;
sep = JS_UNDEFINED;
sep1 = JS_UNDEFINED;
JS_FreeValue(ctx, val);
return 0;
}
-
+
exception:
JS_FreeValue(ctx, val);
JS_FreeValue(ctx, tab);
JS_DupValue(ctx, obj), JS_PROP_C_W_E) < 0)
goto exception;
val = JS_DupValue(ctx, obj);
-
+
val = js_json_check(ctx, jsc, wrapper, val, jsc->empty);
if (JS_IsException(val))
goto exception;
JS_ThrowStackOverflow(ctx);
return NULL;
}
-
+
/* 's' should never be NULL */
if (s->is_revoked) {
JS_ThrowTypeErrorRevokedProxy(ctx);
JS_FreeValue(ctx, trap_result_obj);
if (res < 0)
return -1;
-
+
if (target_desc_ret) {
/* convert result_desc.flags to defineProperty flags */
flags1 = result_desc.flags | JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_ENUMERABLE;
if (flags & JS_CALL_FLAG_CONSTRUCTOR)
return js_proxy_call_constructor(ctx, func_obj, this_obj, argc, argv);
-
+
s = get_proxy_method(ctx, &method, func_obj, JS_ATOM_apply);
if (!s)
return JS_EXCEPTION;
{
JSMapRecord *mr, *mr_next;
JSMapState *s;
-
+
/* first pass to remove the records from the WeakMap/WeakSet
lists */
for(mr = p->first_weak_ref; mr != NULL; mr = mr->next_weak_ref) {
list_del(&mr->hash_link);
list_del(&mr->link);
}
-
+
/* second pass to free the values to avoid modifying the weak
reference list while traversing it. */
for(mr = p->first_weak_ref; mr != NULL; mr = mr_next) {
v = JS_UNDEFINED;
prop = JS_UNDEFINED;
groups = JS_UNDEFINED;
-
+
next = JS_GetProperty(ctx, iter, JS_ATOM_next);
if (JS_IsException(next))
goto exception;
JSValueConst resolve_element_env = func_data[4];
JSValue ret, obj;
int is_zero, index;
-
+
if (JS_ToInt32(ctx, &index, func_data[1]))
return JS_EXCEPTION;
if (alreadyCalled)
if (resolve_type == PROMISE_MAGIC_allSettled) {
JSValue str;
-
+
obj = JS_NewObject(ctx);
if (JS_IsException(obj))
return JS_EXCEPTION;
if (JS_DefinePropertyValueUint32(ctx, values, index,
obj, JS_PROP_C_W_E) < 0)
return JS_EXCEPTION;
-
+
is_zero = remainingElementsCount_add(ctx, resolve_element_env, -1);
if (is_zero < 0)
return JS_EXCEPTION;
JSValueConst then_args[2], resolve_element_data[5];
BOOL done;
int index, is_zero, is_promise_any = (magic == PROMISE_MAGIC_any);
-
+
if (!JS_IsObject(this_val))
return JS_ThrowTypeErrorNotAnObject(ctx);
result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val);
JS_NewInt32(ctx, 1),
JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0)
goto fail_reject;
-
+
index = 0;
for(;;) {
/* XXX: conformance: should close the iterator if error on 'done'
goto fail_reject;
if (done)
break;
- next_promise = JS_Call(ctx, promise_resolve,
+ next_promise = JS_Call(ctx, promise_resolve,
this_val, 1, (JSValueConst *)&item);
JS_FreeValue(ctx, item);
if (JS_IsException(next_promise)) {
JS_FreeValue(ctx, next_promise);
goto fail_reject1;
}
-
+
if (magic == PROMISE_MAGIC_allSettled) {
reject_element =
JS_NewCFunctionData(ctx, js_promise_all_resolve_element, 1,
int64_t y;
double days, d, h, m1;
int i, m, md;
-
+
m1 = fields[1];
m = fmod(m1, 12);
if (m < 0)
days += md;
}
days += fields[2] - 1;
- h = fields[3] * 3600000 + fields[4] * 60000 +
+ h = fields[3] * 3600000 + fields[4] * 60000 +
fields[5] * 1000 + fields[6];
d = days * 86400000 + h;
if (is_local)
static int string_get_digits(JSString *sp, int *pp, int64_t *pval) {
int64_t v = 0;
int c, p = *pp, p_start;
-
+
if (p >= sp->len)
return -1;
p_start = p;
static int string_get_signed_digits(JSString *sp, int *pp, int64_t *pval) {
int res, sgn, p = *pp;
-
+
if (p >= sp->len)
return -1;
sgn = string_get(sp, p);
if (sgn == '-' || sgn == '+')
p++;
-
+
res = string_get_digits(sp, &p, pval);
if (res == 0 && sgn == '-') {
if (*pval == 0)
int p, i, c, sgn, l;
JSString *sp;
BOOL is_local;
-
+
rv = JS_NAN;
s = JS_ToString(ctx, argv[0]);
if (JS_IsException(s))
return JS_EXCEPTION;
-
+
sp = JS_VALUE_GET_STRING(s);
p = 0;
if (p < sp->len && (((c = string_get(sp, p)) >= '0' && c <= '9') || c == '+' || c == '-')) {
JSOperatorSetData *opset = JS_GetOpaque(val, JS_CLASS_OPERATOR_SET);
int i, j;
JSBinaryOperatorDefEntry *ent;
-
+
if (opset) {
for(i = 0; i < JS_OVOP_COUNT; i++) {
if (opset->self_ops[i])
JSOperatorSetData *opset = JS_GetOpaque(val, JS_CLASS_OPERATOR_SET);
int i, j;
JSBinaryOperatorDefEntry *ent;
-
+
if (opset) {
for(i = 0; i < JS_OVOP_COUNT; i++) {
if (opset->self_ops[i])
}
op_count = opset1->operator_counter;
JS_FreeValue(ctx, prop);
-
+
/* we assume there are few entries */
new_tab = js_realloc(ctx, def->tab,
(def->count + 1) * sizeof(def->tab[0]));
ent = def->tab + def->count - 1;
memset(ent, 0, sizeof(def->tab[0]));
ent->operator_index = op_count;
-
+
for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) {
prop = JS_GetPropertyStr(ctx, arg,
js_overloadable_operator_names[i]);
const JSOverloadableOperatorEnum ops[2] = { JS_OVOP_DIV, JS_OVOP_POW };
JSOverloadableOperatorEnum op;
int i;
-
+
opset_obj = JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_BIG_INT],
JS_ATOM_Symbol_operatorSet);
if (JS_IsException(opset_obj))
case JS_TAG_FLOAT64:
#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
-#endif
+#endif
{
bf_t *a, a_s;
-
+
a = JS_ToBigFloat(ctx, &a_s, val);
if (!a) {
JS_FreeValue(ctx, val);
if (JS_IsException(val))
break;
goto redo;
-#endif
+#endif
case JS_TAG_STRING:
val = JS_StringToBigIntErr(ctx, val);
break;
bf_t a_s, b_s, *a, *b, *r, *q;
int status;
JSValue q_val, r_val;
-
+
q_val = JS_NewBigInt(ctx);
if (JS_IsException(q_val))
return JS_EXCEPTION;
bf_t a_s, *a, *r, *rem;
int status;
JSValue r_val, rem_val;
-
+
r_val = JS_NewBigInt(ctx);
if (JS_IsException(r_val))
return JS_EXCEPTION;
uint64_t bits;
bf_t a_s, *a = &a_s, *r, mask_s, *mask = &mask_s;
JSValue res;
-
+
if (JS_ToIndex(ctx, &bits, argv[0]))
return JS_EXCEPTION;
res = JS_NewBigInt(ctx);
JS_CFUNC_MAGIC_DEF("sqrtrem", 1, js_bigint_sqrt, 1 ),
JS_CFUNC_MAGIC_DEF("floorLog2", 1, js_bigint_op1, 0 ),
JS_CFUNC_MAGIC_DEF("ctz", 1, js_bigint_op1, 1 ),
-#endif
+#endif
};
static const JSCFunctionListEntry js_bigint_proto_funcs[] = {
{
JSValueConst val = argv[0];
JSBigFloat *p;
-
+
if (JS_VALUE_GET_NORM_TAG(val) != JS_TAG_BIG_FLOAT)
return JS_FALSE;
p = JS_VALUE_GET_PTR(val);
{
JSValueConst val = argv[0];
JSBigFloat *p;
-
+
if (JS_VALUE_GET_NORM_TAG(val) != JS_TAG_BIG_FLOAT)
return JS_FALSE;
p = JS_VALUE_GET_PTR(val);
{
JSRuntime *rt = ctx->rt;
JSValueConst obj1;
-
+
rt->bigfloat_ops.to_string = js_bigfloat_to_string;
rt->bigfloat_ops.from_string = js_string_to_bigfloat;
rt->bigfloat_ops.unary_arith = js_unary_arith_bigfloat;
rt->bigfloat_ops.compare = js_compare_bigfloat;
rt->bigfloat_ops.mul_pow10_to_float64 = js_mul_pow10_to_float64;
rt->bigfloat_ops.mul_pow10 = js_mul_pow10;
-
+
ctx->class_proto[JS_CLASS_BIG_FLOAT] = JS_NewObject(ctx);
JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_FLOAT],
js_bigfloat_proto_funcs,
const char *str;
size_t size;
int rnd_mode;
-
+
str = JS_ToCStringLen(ctx, &size, obj);
if (!str)
return -1;
int64_t val;
BOOL has_prec;
int rnd_mode;
-
+
if (!JS_IsObject(obj)) {
JS_ThrowTypeErrorNotAnObject(ctx);
return -1;
if (rnd_mode < 0)
return -1;
fe->flags = rnd_mode;
-
+
prop = JS_GetProperty(ctx, obj, JS_ATOM_maximumSignificantDigits);
if (JS_IsException(prop))
return -1;
op_count = 1;
else
op_count = 2;
-
+
op1 = JS_ToNumeric(ctx, argv[0]);
if (JS_IsException(op1))
return op1;
JSObject *p = JS_VALUE_GET_OBJ(val);
JSArrayBuffer *abuf = p->u.array_buffer;
struct list_head *el, *el1;
-
+
if (abuf) {
/* The ArrayBuffer finalizer may be called before the typed
array finalizers using it, so abuf->array_list is not
list_for_each_safe(el, el1, &abuf->array_list) {
JSTypedArray *ta;
JSObject *p1;
-
+
ta = list_entry(el, JSTypedArray, link);
ta->link.prev = NULL;
ta->link.next = NULL;
}
return JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, ta->buffer));
}
-
+
static JSValue js_typed_array_get_toStringTag(JSContext *ctx,
JSValueConst this_val)
{
if (typed_array_is_detached(ctx, p))
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
-
+
shift = typed_array_size_log2(p->class_id);
switch(shift) {
case 0:
res = 0;
goto done;
}
-
+
is_bigint = 0;
is_int = 0; /* avoid warning */
v64 = 0; /* avoid warning */
is_int = (v64 == d);
} else if (tag == JS_TAG_BIG_INT) {
JSBigFloat *p1 = JS_VALUE_GET_PTR(argv[0]);
-
+
if (p->class_id == JS_CLASS_BIG_INT64_ARRAY) {
if (bf_get_int64(&v64, &p1->num, 0) != 0)
goto done;
uint32_t *array_idx;
void *array_tmp;
size_t i, j;
-
+
/* XXX: a stable sort would use less memory */
array_idx = js_malloc(ctx, len * sizeof(array_idx[0]));
if (!array_idx)
}
switch(op | (size_log2 << 3)) {
-
+
#define OP(op_name, func_name) \
case ATOMICS_OP_ ## op_name | (0 << 3): \
a = func_name((_Atomic(uint8_t) *)ptr, v); \
case ATOMICS_OP_ ## op_name | (3 << 3): \
a = func_name((_Atomic(uint64_t) *)ptr, v); \
break;
-
+
OP(ADD, atomic_fetch_add)
OP(AND, atomic_fetch_and)
OP(OR, atomic_fetch_or)
case ATOMICS_OP_LOAD | (3 << 3):
a = atomic_load((_Atomic(uint64_t) *)ptr);
break;
-
+
case ATOMICS_OP_COMPARE_EXCHANGE | (0 << 3):
{
uint8_t v1 = v;
if (size_log2 == 3) {
if (JS_ToBigInt64(ctx, &v, argv[2]))
return JS_EXCEPTION;
- } else {
+ } else {
if (JS_ToInt32(ctx, &v32, argv[2]))
return JS_EXCEPTION;
v = v32;
{
return 0;
}
-
+
#elif defined(JS_NAN_BOXING)
typedef uint64_t JSValue;
tag = JS_VALUE_GET_TAG(v);
return tag == (JS_NAN >> 32);
}
-
+
#else /* !JS_NAN_BOXING */
typedef union JSValueUnion {
#define JS_EVAL_FLAG_BACKTRACE_BARRIER (1 << 6)
/* allow top-level await in normal script. JS_Eval() returns a
promise. Only allowed with JS_EVAL_TYPE_GLOBAL */
-#define JS_EVAL_FLAG_ASYNC (1 << 7)
+#define JS_EVAL_FLAG_ASYNC (1 << 7)
typedef JSValue JSCFunction(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv);
typedef JSValue JSCFunctionMagic(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic);
{
return JS_NewCFunction2(ctx, (JSCFunction *)func, name, length, cproto, magic);
}
-void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj,
+void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj,
JSValueConst proto);
/* C property definition */
echo "release.sh [release_list]"
echo ""
echo "release_list: extras binary win_binary quickjs"
-
+
exit 1
fi
outdir="/tmp/${d}"
rm -rf $outdir
-mkdir -p $outdir $outdir/unicode $outdir/tests
+mkdir -p $outdir $outdir/unicode $outdir/tests
cp unicode/* $outdir/unicode
cp -a tests/bench-v8 $outdir/tests
( cd /tmp/$d && rm -f ../${d}.zip && zip -r ../${d}.zip . )
fi
-
+
#################################################"
# Linux binary release
cp doc/quickjs.texi doc/quickjs.pdf doc/quickjs.html \
doc/jsbignum.texi doc/jsbignum.html doc/jsbignum.pdf \
- $outdir/doc
+ $outdir/doc
( cd /tmp && tar Jcvf /tmp/${d}.tar.xz ${d} )
/*
* QuickJS Read Eval Print Loop
- *
+ *
* Copyright (c) 2017-2020 Fabrice Bellard
* Copyright (c) 2017-2020 Charlie Gordon
*
/* add 'os' and 'std' bindings */
g.os = os;
g.std = std;
-
+
/* close global objects */
var Object = g.Object;
var String = g.String;
var config_numcalc = (typeof os.open === "undefined");
var has_jscalc = (typeof Fraction === "function");
var has_bignum = (typeof BigFloat === "function");
-
+
var colors = {
none: "\x1b[0m",
black: "\x1b[30m",
var prec;
var expBits;
var log2_10;
-
+
var pstate = "";
var prompt = "";
var plen = 0;
var show_colors = true;
var eval_start_time;
var eval_time = 0;
-
+
var mexpr = "";
var level = 0;
var cmd = "";
var term_read_buf;
var term_width;
/* current X position of the cursor in the terminal */
- var term_cursor_x = 0;
-
+ var term_cursor_x = 0;
+
function termInit() {
var tab;
term_fd = std.in.fileno();
-
+
/* get the terminal size */
term_width = 80;
if (os.isatty(term_fd)) {
/* send Ctrl-C to readline */
handle_byte(3);
}
-
+
function term_read_handler() {
var l, i;
l = os.read(term_fd, term_read_buf.buffer, 0, term_read_buf.length);
for(i = 0; i < l; i++)
handle_byte(term_read_buf[i]);
}
-
+
function handle_byte(c) {
if (!utf8) {
handle_char(c);
handle_char(c);
}
}
-
+
function is_alpha(c) {
return typeof c === "string" &&
((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
}
-
+
function is_digit(c) {
return typeof c === "string" && (c >= '0' && c <= '9');
}
d = c.codePointAt(0); /* can be NaN if empty string */
return d >= 0xdc00 && d < 0xe000;
}
-
+
function is_balanced(a, b) {
switch (a + b) {
case "()":
} else {
l = Math.min(term_width - 1 - term_cursor_x, delta);
print_csi(l, "C"); /* right */
- delta -= l;
+ delta -= l;
term_cursor_x += l;
}
}
function backward_word() {
cursor_pos = skip_word_backward(cursor_pos);
- }
+ }
function accept_line() {
std.puts("\n");
readline_print_prompt();
}
}
-
+
function reset() {
cmd = "";
cursor_pos = 0;
readline_print_prompt();
}
}
-
+
var commands = { /* command table */
"\x01": beginning_of_line, /* ^A - bol */
"\x02": backward_char, /* ^B - backward-char */
cursor_pos = cmd.length;
history_index = history.length;
readline_cb = cb;
-
+
prompt = pstate;
-
+
if (mexpr) {
prompt += dupstr(" ", plen - prompt.length);
prompt += ps2;
} else {
alert(); /* beep! */
}
-
+
cursor_pos = (cursor_pos < 0) ? 0 :
(cursor_pos > cmd.length) ? cmd.length : cursor_pos;
update();
s += "n";
return s;
}
-
+
function print(a) {
var stack = [];
function print_rec(a) {
var n, i, keys, key, type, s;
-
+
type = typeof(a);
if (type === "object") {
if (a === null) {
}
print_rec(a);
}
-
+
function extract_directive(a) {
var pos;
if (a[0] !== '\\')
/* return true if the string after cmd can be evaluted as JS */
function handle_directive(cmd, expr) {
var param, prec1, expBits1;
-
+
if (cmd === "h" || cmd === "?" || cmd == "help") {
help();
} else if (cmd === "load") {
}
}
}
-
+
function help() {
function sel(n) {
return n ? "*": " ";
function cmd_readline_start() {
readline_start(dupstr(" ", level), readline_handle_cmd);
}
-
+
function readline_handle_cmd(expr) {
if (!handle_cmd(expr)) {
cmd_readline_start();
/* return true if async termination */
function handle_cmd(expr) {
var colorstate, cmd;
-
+
if (expr === null) {
expr = "";
return false;
}
if (expr === "")
return false;
-
+
if (mexpr)
expr = mexpr + '\n' + expr;
colorstate = colorize_js(expr);
return false;
}
mexpr = "";
-
+
if (has_bignum) {
/* XXX: async is not supported in this case */
BigFloatEnv.setPrec(eval_and_print_start.bind(null, expr, false),
function eval_and_print_start(expr, is_async) {
var result;
-
+
try {
if (eval_mode === "math")
expr = '"use math"; void 0;' + expr;
console.log(error);
}
std.puts(colors.none);
-
+
handle_cmd_end();
}
}
termInit();
-
+
cmd_start();
})(globalThis);
/*
* ECMA Test 262 Runner for QuickJS
- *
+ *
* Copyright (c) 2017-2021 Fabrice Bellard
* Copyright (c) 2017-2021 Charlie Gordon
*
char *p = str_strip(buf);
if (*p == '#' || *p == ';' || *p == '\0')
continue; /* line comment */
-
+
namelist_add(lp, base_name, p);
}
free(base_name);
JSContext *ctx;
JSValue ret_val;
int ret;
-
+
rt = JS_NewRuntime();
if (rt == NULL) {
fatal(1, "JS_NewRuntime failure");
- }
+ }
ctx = JS_NewContext(rt);
if (ctx == NULL) {
JS_FreeRuntime(rt);
JS_SetContextOpaque(ctx, agent);
JS_SetRuntimeInfo(rt, "agent");
JS_SetCanBlock(rt, TRUE);
-
+
add_helpers(ctx);
ret_val = JS_Eval(ctx, agent->script, strlen(agent->script),
"<evalScript>", JS_EVAL_TYPE_GLOBAL);
if (JS_IsException(ret_val))
js_std_dump_error(ctx);
JS_FreeValue(ctx, ret_val);
-
+
for(;;) {
JSContext *ctx1;
ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1);
break;
} else {
JSValue args[2];
-
+
pthread_mutex_lock(&agent_mutex);
while (!agent->broadcast_pending) {
pthread_cond_wait(&agent_cond, &agent_mutex);
}
-
+
agent->broadcast_pending = FALSE;
pthread_cond_signal(&agent_cond);
if (JS_GetContextOpaque(ctx) != NULL)
return JS_ThrowTypeError(ctx, "cannot be called inside an agent");
-
+
script = JS_ToCString(ctx, argv[0]);
if (!script)
return JS_EXCEPTION;
{
struct list_head *el, *el1;
Test262Agent *agent;
-
+
list_for_each_safe(el, el1, &agent_list) {
agent = list_entry(el, Test262Agent, link);
pthread_join(agent->tid, NULL);
free(agent);
}
}
-
+
static JSValue js_agent_leaving(JSContext *ctx, JSValue this_val,
int argc, JSValue *argv)
{
uint8_t *buf;
size_t buf_size;
int32_t val;
-
+
if (JS_GetContextOpaque(ctx) != NULL)
return JS_ThrowTypeError(ctx, "cannot be called inside an agent");
-
+
buf = JS_GetArrayBuffer(ctx, &buf_size, sab);
if (!buf)
return JS_EXCEPTION;
if (JS_ToInt32(ctx, &val, argv[1]))
return JS_EXCEPTION;
-
+
/* broadcast the values and wait until all agents have started
calling their callbacks */
pthread_mutex_lock(&agent_mutex);
rep = malloc(sizeof(*rep));
rep->str = strdup(str);
JS_FreeCString(ctx, str);
-
+
pthread_mutex_lock(&report_mutex);
list_add_tail(&rep->link, &report_list);
pthread_mutex_unlock(&report_mutex);
JS_CFUNC_DEF("sleep", 1, js_agent_sleep ),
JS_CFUNC_DEF("monotonicNow", 0, js_agent_monotonicNow ),
};
-
+
static JSValue js_new_agent(JSContext *ctx)
{
JSValue agent;
{
JSContext *ctx1;
JSValue ret;
-
+
ctx1 = JS_NewContext(JS_GetRuntime(ctx));
if (!ctx1)
return JS_ThrowOutOfMemory(ctx);
{
JSValue global_obj;
JSValue obj262, obj;
-
+
global_obj = JS_GetGlobalObject(ctx);
JS_SetPropertyStr(ctx, global_obj, "print",
JS_SetPropertyStr(ctx, obj262, "IsHTMLDDA", obj);
JS_SetPropertyStr(ctx, global_obj, "$262", JS_DupValue(ctx, obj262));
-
+
JS_FreeValue(ctx, global_obj);
return obj262;
}
uint8_t *buf;
JSModuleDef *m;
JSValue func_val;
-
+
buf = js_load_file(ctx, &buf_len, module_name);
if (!buf) {
JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
module_name);
return NULL;
}
-
+
/* compile the module */
func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
perror_exit(1, filename);
}
base_name = get_basename(filename);
-
+
while (fgets(buf, sizeof(buf), f) != NULL) {
char *p, *q;
lineno++;
p = str_strip(buf);
if (*p == '#' || *p == ';' || *p == '\0')
continue; /* line comment */
-
+
if (*p == "[]"[0]) {
/* new section */
p++;
test_mode = TEST_STRICT;
else if (str_equal(q, "all") || str_equal(q, "both"))
test_mode = TEST_ALL;
- else
+ else
fatal(2, "unknown test mode: %s", q);
continue;
}
int len, maxlen;
maxlen = 0;
-
+
if (*find) {
const char *p;
for (p = str + pos; *p; p++) {
int ret, error_line, pos, pos_line;
BOOL is_error, has_error_line, ret_promise;
const char *error_name;
-
+
pos = skip_comments(buf, 1, &pos_line);
error_line = pos_line;
has_error_line = FALSE;
/* a module evaluation returns a promise */
ret_promise = ((eval_flags & JS_EVAL_TYPE_MODULE) != 0);
async_done = 0; /* counter of "Test262:AsyncTestComplete" messages */
-
+
res_val = JS_Eval(ctx, buf, buf_len, filename, eval_flags);
if ((is_async || ret_promise) && !JS_IsException(res_val)) {
if (is_error) {
JSValue name, stack;
const char *stack_str;
-
+
name = JS_GetPropertyStr(ctx, exception_val, "name");
error_name = JS_ToCString(ctx, name);
stack = JS_GetPropertyStr(ctx, exception_val, "stack");
if (stack_str) {
const char *p;
int len;
-
+
if (outfile)
fprintf(outfile, "%s", stack_str);
-
+
len = strlen(filename);
p = strstr(stack_str, filename);
if (p != NULL && p[len] == ':') {
if (error_type) {
char *error_class;
const char *msg;
-
+
msg = JS_ToCString(ctx, exception_val);
error_class = strdup_len(msg, strcspn(msg, ":"));
if (!str_equal(error_class, error_type))
const char *p, *desc_start;
char *desc;
int len;
-
+
p = buf;
while (*p != '\0') {
if (p[0] == '/' && p[1] == '*' && p[2] == style && p[3] != '/') {
JSRuntime *rt;
JSContext *ctx;
int i, ret;
-
+
rt = JS_NewRuntime();
if (rt == NULL) {
fatal(1, "JS_NewRuntime failure");
- }
+ }
ctx = JS_NewContext(rt);
if (ctx == NULL) {
JS_FreeRuntime(rt);
JS_SetRuntimeInfo(rt, filename);
JS_SetCanBlock(rt, can_block);
-
+
/* loader for ES6 modules */
JS_SetModuleLoaderFunc(rt, NULL, js_module_loader_test, NULL);
-
+
add_helpers(ctx);
for (i = 0; i < ip->count; i++) {
ret = eval_buf(ctx, buf, buf_len, filename, TRUE, is_negative,
error_type, outfile, eval_flags, is_async);
ret = (ret != 0);
-
+
if (dump_memory) {
update_stats(rt, filename);
}
BOOL is_negative, is_nostrict, is_onlystrict, is_async, is_module, skip;
BOOL can_block;
namelist_t include_list = { 0 }, *ip = &include_list;
-
+
is_nostrict = is_onlystrict = is_negative = is_async = is_module = skip = FALSE;
can_block = TRUE;
error_type = NULL;
int eval_flags, ret_code, ret;
JSValue res_val;
BOOL can_block;
-
+
outfile = stdout; /* for js_print */
rt = JS_NewRuntime();
if (rt == NULL) {
fatal(1, "JS_NewRuntime failure");
- }
+ }
ctx = JS_NewContext(rt);
if (ctx == NULL) {
JS_FreeRuntime(rt);
can_block = TRUE;
JS_SetCanBlock(rt, can_block);
-
+
/* loader for ES6 modules */
JS_SetModuleLoaderFunc(rt, NULL, js_module_loader_test, NULL);
-
+
add_helpers(ctx);
buf = load_file(filename, &buf_len);
break;
}
}
-
+
if (optind >= argc && !test_list.count)
help();
if (is_test262_harness) {
return run_test262_harness_test(argv[optind], is_module);
}
-
+
error_out = stdout;
if (error_filename) {
error_file = load_file(error_filename, NULL);
# handle tests flagged as [async]: yes, no, skip
# for these, load 'harness/doneprintHandle.js' prior to test
-# and expect `print('Test262:AsyncTestComplete')` to be called for
+# and expect `print('Test262:AsyncTestComplete')` to be called for
# successful termination
async=yes
/*
* QuickJS: binary JSON module (test only)
- *
+ *
* Copyright (c) 2017-2019 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
JSValue obj;
size_t size;
int flags;
-
+
if (JS_ToIndex(ctx, &pos, argv[1]))
return JS_EXCEPTION;
if (JS_ToIndex(ctx, &len, argv[2]))
uint8_t *buf;
JSValue array;
int flags;
-
+
flags = 0;
if (JS_ToBool(ctx, argv[1]))
flags |= JS_WRITE_OBJ_REFERENCE;
s = s.substring(0, i) + "." + s.substring(i);
return s;
}
-
+
var ref_data;
var log_data;
];
var tests = [];
var i, j, n, f, name;
-
+
if (typeof BigInt == "function") {
/* BigInt test */
test_list.push(bigint64_arith);
/* BigFloat test */
test_list.push(float256_arith);
}
-
+
for (i = 1; i < argc;) {
name = argv[i++];
if (name == "-a") {
log_line("total", "", total[2], total[3], total_score * 100 / total_scale);
else
log_line("total", "", total[2]);
-
+
if (tests == test_list)
save_result("microbench-new.txt", log_data);
}
@@ -6,24 +6,27 @@ description: |
defines: [buildString, testPropertyEscapes, matchValidator]
---*/
-
+
+if ($262 && typeof $262.codePointRange === "function") {
+ /* use C function to build the codePointRange (much faster with
+ slow JS engines) */
- return result;
+ return result;
}
-
+
function testPropertyEscapes(regex, string, expression) {
r = 1n << 31n;
assert(r, 2147483648n, "1 << 31n === 2147483648n");
-
+
r = 1n << 32n;
assert(r, 4294967296n, "1 << 32n === 4294967296n");
}
function test_bigfloat()
{
var e, a, b, sqrt2;
-
+
assert(typeof 1n === "bigint");
assert(typeof 1l === "bigfloat");
assert(1 == 1.0l);
test_less(2.1, 3l);
test_eq(Math.sqrt(9), 3l);
-
+
test_less(2n, 3l);
test_eq(3n, 3l);
assert(a === BigFloat.parseFloat("0x1.6a09e667f3bcc908b2fb1366ea957d3e", 0, e));
assert(e.inexact === true);
assert(BigFloat.fpRound(a) == 0x1.6a09e667f3bcc908b2fb1366ea95l);
-
+
b = BigFloatEnv.setPrec(BigFloat.sqrt.bind(null, 2), 128);
assert(a === b);
assert(BigFloat.exp(0.2l) === 1.2214027581601698339210719946396742l);
assert(BigFloat.log(3l) === 1.0986122886681096913952452369225256l);
assert(BigFloat.pow(2.1l, 1.6l) === 3.277561666451861947162828744873745l);
-
+
assert(BigFloat.sin(-1l) === -0.841470984807896506652502321630299l);
assert(BigFloat.cos(1l) === 0.5403023058681397174009366074429766l);
assert(BigFloat.tan(0.1l) === 0.10033467208545054505808004578111154l);
assert(1m !== 2m);
test_less(1m, 2m);
test_eq(2m, 2m);
-
+
test_less(1, 2m);
test_eq(2, 2m);
test_less(1.1, 2m);
test_eq(Math.sqrt(4), 2m);
-
+
test_less(2n, 3m);
test_eq(3n, 3m);
-
+
assert(BigDecimal("1234.1") === 1234.1m);
assert(BigDecimal(" 1234.1") === 1234.1m);
assert(BigDecimal(" 1234.1 ") === 1234.1m);
assert(1234.5m ** 3m === 1881365963.625m);
assertThrows(RangeError, () => { 2m ** 3.1m } );
assertThrows(RangeError, () => { 2m ** -3m } );
-
+
assert(BigDecimal.sqrt(2m,
{ roundingMode: "half-even",
maximumSignificantDigits: 4 }) === 1.414m);
assert(BigDecimal.sqrt(0.002m,
{ roundingMode: "half-even",
maximumFractionDigits: 3 }) === 0.045m);
-
+
assert(BigDecimal.round(3.14159m,
{ roundingMode: "half-even",
maximumFractionDigits: 3 }) === 3.142m);
function isArrayLike(a)
{
- return Array.isArray(a) ||
+ return Array.isArray(a) ||
(a instanceof Uint8ClampedArray) ||
(a instanceof Uint8Array) ||
(a instanceof Uint16Array) ||
function bjson_test_all()
{
var obj;
-
+
bjson_test({x:1, y:2, if:3});
bjson_test([1, 2, 3]);
bjson_test([1.0, "aa", true, false, undefined, null, NaN, -Infinity, -0.0]);
bjson_test(new Int32Array([123123, 222111, -32222]));
bjson_test(new Float64Array([123123, 222111.5]));
-
+
/* tested with a circular reference */
obj = {};
obj.x = obj;
}
var r, g;
-
+
r = my_func.call(null, 1, 2);
assert(r, 3, "call");
assert_throws(TypeError, (function() {
Reflect.apply((function () { return 1; }), null, undefined);
}));
-
+
r = new Function("a", "b", "return a + b;");
assert(r(2,3), 5, "function");
-
+
g = f.bind(1, 2);
assert(g.length, 1);
assert(g.name, "bound f");
assert(a.z, 4, "get");
a.z = 5;
assert(a.z_val, 5, "set");
-
+
a = { get z() { return 4; }, set z(val) { this.z_val = val; } };
assert(a.z, 4, "get");
a.z = 5;
assert(a.charAt(1), "b");
assert(a.charAt(-1), "");
assert(a.charAt(3), "");
-
+
a = "abcd";
assert(a.substring(1, 3), "bc", "substring");
a = String.fromCharCode(0x20ac);
assert(a, "\u20ac", "unicode");
assert(a, "\u{20ac}", "unicode");
assert("a", "\x61", "unicode");
-
+
a = "\u{10ffff}";
assert(a.length, 2, "unicode");
assert(a, "\u{dbff}\u{dfff}", "unicode");
assert(eval("if (0) 2; else 3;"), 3);
assert(f.call(1, "this"), 1);
-
+
a = 2;
assert(eval("a"), 2);
a[2] = 0.5;
a[3] = 1233.5;
assert(a.toString(), "0,2,0,255");
-
+
buffer = new ArrayBuffer(16);
assert(buffer.byteLength, 16);
a = new Uint32Array(buffer, 12, 1);
a = new Float32Array(buffer, 8, 1);
a[0] = 1;
-
+
a = new Uint8Array(buffer);
str = a.toString();
a = /(\.(?!com|org)|\/)/.exec("ah.com");
assert(a, null);
-
+
a = /(?=(a+))/.exec("baaabac");
assert(a.index === 1 && a[0] === "" && a[1] === "aaa");
}
i = 0;
- a.forEach(function (v, o) {
+ a.forEach(function (v, o) {
assert(o, tab[i++][0]);
assert(a.has(o));
assert(a.delete(o));
a.set(o, v);
}
o = null;
-
+
n2 = n >> 1;
for(i = 0; i < n2; i++) {
a.delete(tab[i][0]);
function f2()
{
var val = 1;
-
+
function set(a) {
val = a;
}
}
return { "set": set, "get": get };
}
-
+
var obj = f2();
obj.set(10);
var r;
r = 1 << 31;
assert(r, -2147483648, "1 << 31 === -2147483648");
-
+
r = 1 << 32;
assert(r, 1, "1 << 32 === 1");
-
+
r = (1 << 31) < 0;
assert(r, true, "(1 << 31) < 0 === true");
assert(("12345" | 0) === 12345);
assert(("0x12345" | 0) === 0x12345);
assert(((4294967296 * 3 - 4) | 0) === -4);
-
+
assert(("12345" >>> 0) === 12345);
assert(("0x12345" >>> 0) === 0x12345);
assert((NaN >>> 0) === 0);
function test_inc_dec()
{
var a, r;
-
+
a = 1;
r = a++;
assert(r === 1 && a === 2, true, "++");
a = [true];
a[0]++;
assert(a[0], 2, "++");
-
+
a = {x:true};
r = a.x++;
assert(r === 1 && a.x === 2, true, "++");
-
+
a = {x:true};
r = a.x--;
assert(r === 1 && a.x === 0, true, "--");
-
+
a = [true];
r = a[0]++;
assert(r === 1 && a[0] === 2, true, "++");
-
+
a = [true];
r = a[0]--;
assert(r === 1 && a[0] === 0, true, "--");
assert((typeof Object), "function", "typeof");
assert((typeof null), "object", "typeof");
assert((typeof unknown_var), "undefined", "typeof");
-
+
a = {x: 1, if: 2, async: 3};
assert(a.if === 2);
assert(a.async === 3);
a = {x: 1, y: 1};
assert((delete a.x), true, "delete");
assert(("x" in a), false, "delete");
-
+
/* the following are not tested by test262 */
assert(delete "abc"[100], true);
o = new C();
assert(o.f() === 1);
assert(o.x === 10);
-
+
assert(D.F() === -1);
assert(D.G() === -2);
assert(D.H() === -1);
var a, b;
[a, b = /abc\(/] = [1];
assert(a === 1);
-
+
[a, b =/abc\(/] = [2];
assert(a === 2);
}
{
var f;
var c = "global";
-
+
f = function(a = eval("var arguments")) {};
assert_throws(SyntaxError, f);
/* non strict mode test : assignment to the function name silently
fails */
-
+
f = function myfunc() {
myfunc = 1;
return myfunc;
return myfunc;
};
assert(f(), f);
-
+
/* strict mode test : assignment to the function name raises a
TypeError exception */
assert(delete z?.b["c"], true);
assert(delete a?.b["c"], true);
assert(JSON.stringify(a), '{"b":{}}');
-
+
a = {
b() { return this._b; },
_b: { c: 42 }
function test_try_catch8()
{
var i, s;
-
+
s = "";
for(var i in {x:1, y:2}) {
try {
return "Vec2(" + this.x + "," + this.y + ")";
}
}
-
+
Vec2.prototype[Symbol.operatorSet] = Operators.create(
{
"+"(p1, p2) {
return "Vec2(" + this.x + "," + this.y + ")";
}
}
-
+
var a = new Vec2(1, 2);
var b = new Vec2(3, 4);
var r;
r = 1 << 31;
assert(r, 2147483648, "1 << 31 === 2147483648");
-
+
r = 1 << 32;
assert(r, 4294967296, "1 << 32 === 4294967296");
-
+
r = (1 << 31) < 0;
assert(r, false, "(1 << 31) < 0 === false");
function test_mod()
{
var a, b, p;
-
+
a = Mod(3, 101);
b = Mod(-1, 101);
assert((a + b) == Mod(2, 101));
var a, b, q, r, t, i;
a = (1 + X) ^ 4;
assert(a == X^4+4*X^3+6*X^2+4*X+1);
-
+
r = (1 + X);
q = (1+X+X^2);
b = (1 - X^2);
f.seek(0, std.SEEK_SET);
str1 = f.readAsString();
assert(str1 === str);
-
+
f.seek(0, std.SEEK_END);
size = f.tell();
assert(size === str.length);
function test_getline()
{
var f, line, line_count, lines, i;
-
+
lines = ["hello world", "line 1", "line 2" ];
f = std.tmpfile();
for(i = 0; i < lines.length; i++) {
f.close();
}
-
+
function test_popen()
{
var str, f, fname = "tmp_file.txt";
/* test loadFile */
assert(std.loadFile(fname), content);
-
+
/* execute the 'cat' shell command */
f = std.popen("cat " + fname, "r");
str = f.readAsString();
fname = "tmp_file.txt";
fpath = fdir + "/" + fname;
link_path = fdir + "/test_link";
-
+
os.remove(link_path);
os.remove(fpath);
os.remove(fdir);
err = os.mkdir(fdir, 0o755);
assert(err === 0);
-
+
fd = os.open(fpath, os.O_RDWR | os.O_CREAT | os.O_TRUNC);
assert(fd >= 0);
-
+
buf = new Uint8Array(10);
for(i = 0; i < buf.length; i++)
buf[i] = i;
assert(os.seek(fd, 0, std.SEEK_SET) === 0);
buf2 = new Uint8Array(buf.length);
assert(os.read(fd, buf2.buffer, 0, buf2.length) === buf2.length);
-
+
for(i = 0; i < buf.length; i++)
assert(buf[i] == buf2[i]);
-
+
if (typeof BigInt !== "undefined") {
assert(os.seek(fd, BigInt(6), std.SEEK_SET), BigInt(6));
assert(os.read(fd, buf2.buffer, 0, 1) === 1);
assert(buf[6] == buf2[0]);
}
-
+
assert(os.close(fd) === 0);
[files, err] = os.readdir(fdir);
err = os.utimes(fpath, fdate, fdate);
assert(err, 0);
-
+
[st, err] = os.stat(fpath);
assert(err, 0);
assert(st.mode & os.S_IFMT, os.S_IFREG);
err = os.symlink(fname, link_path);
assert(err === 0);
-
+
[st, err] = os.lstat(link_path);
assert(err, 0);
assert(st.mode & os.S_IFMT, os.S_IFLNK);
[buf, err] = os.readlink(link_path);
assert(err, 0);
assert(buf, fname);
-
+
assert(os.remove(link_path) === 0);
[buf, err] = os.getcwd();
assert(err, 0);
assert(buf, buf2);
-
+
assert(os.remove(fpath) === 0);
fd = os.open(fpath, os.O_RDONLY);
ret = os.exec(["/bin/sh", "-c", "exit 1"], { usePath: false });
assert(ret, 1);
-
+
fds = os.pipe();
pid = os.exec(["sh", "-c", "echo $FOO"], {
stdout: fds[1],
{
(async function run () {
let obj = {}
-
+
let done = () => {
obj
std.gc();
}
-
+
Promise.resolve().then(done)
-
+
const p = new Promise(() => {})
-
+
await p
})();
}
function worker_main() {
var i;
-
+
parent.onmessage = handle_msg;
for(i = 0; i < 10; i++) {
- parent.postMessage({ type: "num", num: i });
+ parent.postMessage({ type: "num", num: i });
}
}
g="${url}/${f}"
wget $g -O unicode/$f
done
-
+
wget $emoji_url -O unicode/emoji-data.txt
/*
* Generation of Unicode tables
- *
+ *
* Copyright (c) 2017-2018 Fabrice Bellard
* Copyright (c) 2017-2018 Charlie Gordon
*
const char *p;
int code, lc, uc, last_code;
CCInfo *ci, *tab = unicode_db;
-
+
f = fopen(filename, "rb");
if (!f) {
perror(filename);
code = strtoul(p, NULL, 16);
lc = 0;
uc = 0;
-
+
p = get_field(line, 12);
if (p && *p != ';') {
uc = strtoul(p, NULL, 16);
}
ci->general_category = i;
}
-
+
p = get_field(line, 3);
if (p && *p != ';' && *p != '\0') {
int cc;
if (p && *p == 'Y') {
set_prop(code, PROP_Bidi_Mirrored, 1);
}
-
+
/* handle ranges */
get_field_buf(buf1, sizeof(buf1), line, 1);
if (strstr(buf1, " Last>")) {
}
last_code = code;
}
-
+
fclose(f);
}
const char *p;
int code;
CCInfo *ci;
-
+
f = fopen(filename, "rb");
if (!f) {
perror(filename);
if (*p != '#' && *p != '\0')
continue;
}
-
-
+
+
p = get_field(line, 1);
if (p && *p != ';') {
ci->l_len = 0;
ci->u_len = 0;
}
}
-
+
fclose(f);
}
const char *p;
int code, status;
CCInfo *ci;
-
+
f = fopen(filename, "rb");
if (!f) {
perror(filename);
status = *p;
if (status != 'C' && status != 'S' && status != 'F')
continue;
-
+
p = get_field(line, 2);
assert(p != NULL);
if (status == 'S') {
ci->f_data[ci->f_len++] = strtoul(p, (char **)&p, 16);
}
}
-
+
fclose(f);
}
FILE *f;
char line[4096], *p;
uint32_t c0;
-
+
f = fopen(filename, "rb");
if (!f) {
perror(filename);
char line[4096], *p, buf[256], *q;
uint32_t c0, c1, c;
int i;
-
+
f = fopen(filename, "rb");
if (!f) {
perror(filename);
FILE *f;
char line[4096], *p, buf[256], *q;
uint32_t c0, c1, c;
-
+
f = fopen(filename, "rb");
if (!f) {
perror(filename);
char line[4096], *p, buf[256], *q;
uint32_t c0, c1, c;
int i;
-
+
f = fopen(filename, "rb");
if (!f) {
perror(filename);
char line[4096], *p, buf[256], *q;
uint32_t c0, c1, c;
int i;
-
+
f = fopen(filename, "rb");
if (!f) {
perror(filename);
int i;
uint8_t script_ext[255];
int script_ext_len;
-
+
f = fopen(filename, "rb");
if (!f) {
perror(filename);
ci1 = &tab[code + 1];
ci2 = &tab[code + 2];
te->code = code;
-
+
if (ci->l_len == 1 && ci->l_data[0] == code + 2 &&
ci->f_len == 1 && ci->f_data[0] == ci->l_data[0] &&
ci->u_len == 0 &&
te->data = 0;
return;
}
-
+
ci = &tab[code];
is_lower = ci->l_len > 0;
len = 1;
int code, i, j;
CCInfo *ci;
TableEntry *te;
-
+
te = conv_table;
for(code = 0; code <= CHARCODE_MAX; code++) {
ci = &tab[code];
for(i = 0; i < conv_table_len; i++) {
int data_index;
te = &conv_table[i];
-
+
switch(te->type) {
case RUN_TYPE_U:
case RUN_TYPE_L:
return memcmp(c1->f_data, c2->f_data, sizeof(c1->f_data[0]) * c1->f_len);
}
}
-
+
/* dump the case special cases (multi character results which are
identical and need specific handling in lre_canonicalize() */
void dump_case_folding_special_cases(CCInfo *tab)
len = 1;
while ((i + len) <= CHARCODE_MAX && !sp_cc_cmp(&perm[i], &perm[i + len]))
len++;
-
+
if (len > 1) {
for(j = i; j < i + len; j++)
dump_cc_info(&tab[perm[j]], perm[j]);
free(perm);
global_tab = NULL;
}
-
+
int tabcmp(const int *tab1, const int *tab2, int n)
{
const uint32_t *buf;
int buf_len, block_end_pos, bit;
char cname[128];
-
+
dbuf_init(dbuf1);
for(i = 0; i <= CHARCODE_MAX;) {
dbuf_put_u32(dbuf1, n - 1);
i += n;
}
-
+
dbuf_init(dbuf);
dbuf_init(dbuf2);
buf = (uint32_t *)dbuf1->buf;
buf_len = dbuf1->size / sizeof(buf[0]);
-
+
/* the first value is assumed to be 0 */
assert(get_prop(0, prop_index) == 0);
-
+
block_end_pos = PROP_BLOCK_LEN;
i = 0;
code = 0;
snprintf(cname, sizeof(cname), "unicode_prop_%s_index", unicode_prop_name[prop_index]);
dump_byte_table(f, cname, dbuf2->buf, dbuf2->size);
}
-
+
dbuf_free(dbuf);
dbuf_free(dbuf1);
dbuf_free(dbuf2);
printf(" %d", cw_len_count[i]);
printf(" ], length=%d bytes\n", (int)dbuf->size);
#endif
-
+
dump_byte_table(f, "unicode_gc_table", dbuf->buf, dbuf->size);
dbuf_free(dbuf);
printf(" %d", cw_len_count[i]);
printf(" ], length=%d bytes\n", (int)dbuf->size);
#endif
-
+
dump_byte_table(f, "unicode_script_table", dbuf->buf, dbuf->size);
dbuf_free(dbuf);
cw_count);
printf(", length=%d bytes\n", (int)dbuf->size);
#endif
-
+
dump_byte_table(f, "unicode_script_ext_table", dbuf->buf, dbuf->size);
dbuf_free(dbuf);
void build_prop_list_table(FILE *f)
{
int i;
-
+
for(i = 0; i < PROP_TABLE_COUNT; i++) {
if (i == PROP_ID_Start ||
i == PROP_Case_Ignorable ||
build_prop_table(f, i, FALSE);
}
}
-
+
fprintf(f, "typedef enum {\n");
for(i = 0; i < PROP_COUNT; i++)
fprintf(f, " UNICODE_PROP_%s,\n", unicode_prop_name[i]);
int l, error;
CCInfo ci_s, *ci1, *ci = &ci_s;
int code;
-
+
for(code = 0; code <= CHARCODE_MAX; code++) {
ci1 = &tab[code];
*ci = *ci1;
DynBuf dbuf1_s, *dbuf1 = &dbuf1_s;
int cw_len_tab[3], cw_start, block_end_pos;
uint32_t v;
-
+
dbuf_init(dbuf);
dbuf_init(dbuf1);
cc_table_len = 0;
dbuf_putc(dbuf1, v);
dbuf_putc(dbuf1, v >> 8);
dbuf_putc(dbuf1, v >> 16);
-
+
dump_byte_table(f, "unicode_cc_table", dbuf->buf, dbuf->size);
dump_byte_table(f, "unicode_cc_index", dbuf1->buf, dbuf1->size);
/*
entry size:
type bits
- code 18
+ code 18
len 7
compat 1
type 5
DecompEntry de_s, *de = &de_s;
CCInfo *ci, *ci1, *ci2;
int l, j, n, len_max;
-
+
ci = &unicode_db[i];
l = ci->decomp_len;
if (l == 0) {
/* the offset for the compose table has only 6 bits, so we must
limit if it can be used by the compose table */
if (!ci->is_compat && !ci->is_excluded && l == 2)
- len_max = 64;
+ len_max = 64;
else
len_max = 127;
-
+
tab_de[i].cost = 0x7fffffff;
-
+
if (!is_16bit(ci->decomp_data, l)) {
assert(l <= 2);
if (de->cost < tab_de[i].cost) {
tab_de[i] = *de;
}
-
+
if (!((i + n) <= CHARCODE_MAX && n < len_max))
break;
ci1 = &unicode_db[i + n];
n++;
}
}
-
+
if (l <= 8 || l == 18) {
int c_min, c_max, c;
c_min = c_max = -1;
/* check if a single char is increasing */
if (l <= 4) {
int idx1, idx;
-
+
for(idx1 = 1; (idx = decomp_incr_tab[l - 1][idx1]) >= 0; idx1++) {
n = 1;
for(;;) {
if (l == 2) {
BOOL is_16bit;
-
+
n = 0;
is_16bit = FALSE;
for(;;) {
{
int i, j, idx, c;
CCInfo *ci;
-
+
idx = *pidx;
de->data_index = idx;
if (de->type <= DECOMP_TYPE_C1) {
int i, array_len, code_max, data_len, count;
DecompEntry *tab_de, de_s, *de = &de_s;
uint8_t *data_buf;
-
+
code_max = CHARCODE_MAX;
-
+
tab_de = mallocz((code_max + 2) * sizeof(*tab_de));
for(i = code_max; i >= 0; i--) {
/* dump */
{
int size, size1;
-
+
printf("START LEN TYPE L C SIZE\n");
size = 0;
for(i = 0; i <= code_max; i++) {
size += size1;
}
}
-
+
printf("array_len=%d estimated size=%d bytes actual=%d bytes\n",
array_len, size, array_len * 6 + data_len);
}
}
}
fprintf(f, "\n};\n\n");
-
+
fprintf(f, "static const uint8_t unicode_decomp_data[%u] = {",
data_len);
for(i = 0; i < data_len; i++) {
build_compose_table(f, tab_de);
free(data_buf);
-
+
free(tab_de);
}
{
int i, v, k;
const DecompEntry *de;
-
+
k = 0;
for(i = 0; i <= CHARCODE_MAX; i++) {
de = &tab_de[i];
{
int i, v, tab_ce_len;
ComposeEntry *ce, *tab_ce;
-
+
tab_ce = malloc(sizeof(*tab_ce) * COMPOSE_LEN_MAX);
tab_ce_len = 0;
for(i = 0; i <= CHARCODE_MAX; i++) {
CCInfo *ci = &unicode_db[i];
if (ci->decomp_len == 2 && !ci->is_compat &&
!ci->is_excluded) {
- assert(tab_ce_len < COMPOSE_LEN_MAX);
+ assert(tab_ce_len < COMPOSE_LEN_MAX);
ce = &tab_ce[tab_ce_len++];
ce->c[0] = ci->decomp_data[0];
ce->c[1] = ci->decomp_data[1];
}
}
#endif
-
+
fprintf(f, "static const uint16_t unicode_comp_table[%u] = {",
tab_ce_len);
for(i = 0; i < tab_ce_len; i++) {
fprintf(f, " 0x%04x,", v);
}
fprintf(f, "\n};\n\n");
-
+
free(tab_ce);
}
}
}
}
-
+
}
#ifdef PROFILE
{
int64_t ti, count;
-
+
ti = get_time_ns();
count = 0;
/* only do it on meaningful chars */
int *in_str, *nfc_str, *nfd_str, *nfkc_str, *nfkd_str;
int in_len, nfc_len, nfd_len, nfkc_len, nfkd_len;
int *buf, buf_len, pos;
-
+
f = fopen(filename, "rb");
if (!f) {
perror(filename);
buf_len = unicode_normalize((uint32_t **)&buf, (uint32_t *)in_str, in_len, UNICODE_NFKD, NULL, NULL);
check_str("nfkd", pos, in_str, in_len, buf, buf_len, nfkd_str, nfkd_len);
free(buf);
-
+
buf_len = unicode_normalize((uint32_t **)&buf, (uint32_t *)in_str, in_len, UNICODE_NFC, NULL, NULL);
check_str("nfc", pos, in_str, in_len, buf, buf_len, nfc_str, nfc_len);
free(buf);
{
const char *unicode_db_path, *outfilename;
char filename[1024];
-
+
if (argc < 2) {
printf("usage: %s unicode_db_path [output_file]\n"
"\n"
snprintf(filename, sizeof(filename), "%s/SpecialCasing.txt", unicode_db_path);
parse_special_casing(unicode_db, filename);
-
+
snprintf(filename, sizeof(filename), "%s/CaseFolding.txt", unicode_db_path);
parse_case_folding(unicode_db, filename);
snprintf(filename, sizeof(filename), "%s/CompositionExclusions.txt", unicode_db_path);
parse_composition_exclusions(filename);
-
+
snprintf(filename, sizeof(filename), "%s/DerivedCoreProperties.txt", unicode_db_path);
parse_derived_core_properties(filename);
snprintf(filename, sizeof(filename), "%s/ScriptExtensions.txt",
unicode_db_path);
parse_script_extensions(filename);
-
+
snprintf(filename, sizeof(filename), "%s/emoji-data.txt",
unicode_db_path);
parse_prop_list(filename);
build_conv_table(unicode_db);
#ifdef DUMP_CASE_FOLDING_SPECIAL_CASES
- dump_case_folding_special_cases(unicode_db);
+ dump_case_folding_special_cases(unicode_db);
#endif
if (!outfilename) {
} else
{
FILE *fo = fopen(outfilename, "wb");
-
+
if (!fo) {
perror(outfilename);
exit(1);