enhanced moo_inttostr() with 2 new flags - MOO_INTTOSTR_LOWERCASE and MOO_INTTOSTR_NONEWOBJ
redefined bigint and fpdec check macros added the strfmt primitive to String
This commit is contained in:
parent
d3227d1452
commit
71a617b95b
@ -265,6 +265,8 @@ class(#character) String(Array)
|
||||
* if no terminating null character exists, it returns the same value as the size method *)
|
||||
method(#primitive,#lenient) _strlen.
|
||||
method(#primitive) strlen.
|
||||
|
||||
method(#primitive,#variadic) strfmt().
|
||||
}
|
||||
|
||||
## -------------------------------------------------------------------------------
|
||||
|
208
moo/lib/bigint.c
208
moo/lib/bigint.c
@ -69,13 +69,12 @@
|
||||
|
||||
#define IS_SIGN_DIFF(x,y) (((x) ^ (y)) < 0)
|
||||
|
||||
#define IS_PBIGINT(moo,x) (MOO_OBJ_GET_CLASS(x) == (moo)->_large_positive_integer)
|
||||
#define IS_NBIGINT(moo,x) (MOO_OBJ_GET_CLASS(x) == (moo)->_large_negative_integer)
|
||||
#define IS_BIGINT(moo,x) (IS_PBIGINT(moo,x) || IS_NBIGINT(moo,x))
|
||||
|
||||
/* digit character array */
|
||||
static char _digitc_upper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
static char _digitc_lower[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
static char* _digitc_array[] =
|
||||
{
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
"0123456789abcdefghijklmnopqrstuvwxyz"
|
||||
};
|
||||
|
||||
/* exponent table */
|
||||
static moo_uint8_t _exp_tab[] =
|
||||
@ -208,7 +207,7 @@ static int is_normalized_integer (moo_t* moo, moo_oop_t oop)
|
||||
{
|
||||
/* TODO: is it better to introduce a special integer mark into the class itself */
|
||||
/* TODO: or should it check if it's a subclass, subsubclass, subsubsubclass, etc of a large_integer as well? */
|
||||
if (IS_BIGINT(moo, oop))
|
||||
if (MOO_POINTER_IS_BIGINT(moo, oop))
|
||||
{
|
||||
moo_oow_t sz;
|
||||
|
||||
@ -228,7 +227,7 @@ MOO_INLINE static int is_bigint (moo_t* moo, moo_oop_t x)
|
||||
|
||||
/* TODO: is it better to introduce a special integer mark into the class itself */
|
||||
/* TODO: or should it check if it's a subclass, subsubclass, subsubsubclass, etc of a large_integer as well? */
|
||||
return IS_BIGINT(moo, x);
|
||||
return MOO_POINTER_IS_BIGINT(moo, x);
|
||||
}
|
||||
|
||||
MOO_INLINE int moo_isint (moo_t* moo, moo_oop_t x)
|
||||
@ -241,14 +240,14 @@ MOO_INLINE int moo_isint (moo_t* moo, moo_oop_t x)
|
||||
static MOO_INLINE int bigint_to_oow (moo_t* moo, moo_oop_t num, moo_oow_t* w)
|
||||
{
|
||||
MOO_ASSERT (moo, MOO_OOP_IS_POINTER(num));
|
||||
MOO_ASSERT (moo, IS_PBIGINT(moo, num) || IS_NBIGINT(moo, num));
|
||||
MOO_ASSERT (moo, MOO_POINTER_IS_PBIGINT(moo, num) || MOO_POINTER_IS_NBIGINT(moo, num));
|
||||
|
||||
#if (MOO_LIW_BITS == MOO_OOW_BITS)
|
||||
MOO_ASSERT (moo, MOO_OBJ_GET_SIZE(num) >= 1);
|
||||
if (MOO_OBJ_GET_SIZE(num) == 1)
|
||||
{
|
||||
*w = MOO_OBJ_GET_WORD_SLOT(num)[0];
|
||||
return (IS_NBIGINT(moo, num))? -1: 1;
|
||||
return (MOO_POINTER_IS_NBIGINT(moo, num))? -1: 1;
|
||||
}
|
||||
|
||||
#elif (MOO_LIW_BITS == MOO_OOHW_BITS)
|
||||
@ -261,7 +260,7 @@ static MOO_INLINE int bigint_to_oow (moo_t* moo, moo_oop_t num, moo_oow_t* w)
|
||||
if (MOO_OBJ_GET_SIZE(num) == 2)
|
||||
{
|
||||
*w = MAKE_WORD (MOO_OBJ_GET_HALFWORD_SLOT(num)[0], MOO_OBJ_GET_HALFWORD_SLOT(num)[1]);
|
||||
return (IS_NBIGINT(moo, num))? -1: 1;
|
||||
return (MOO_POINTER_IS_NBIGINT(moo, num))? -1: 1;
|
||||
}
|
||||
#else
|
||||
# error UNSUPPORTED LIW BIT SIZE
|
||||
@ -574,13 +573,13 @@ static MOO_INLINE moo_oop_t clone_bigint_negated (moo_t* moo, moo_oop_t oop, moo
|
||||
moo_oop_class_t _class;
|
||||
|
||||
MOO_ASSERT (moo, MOO_OOP_IS_POINTER(oop));
|
||||
if (IS_PBIGINT(moo, oop))
|
||||
if (MOO_POINTER_IS_PBIGINT(moo, oop))
|
||||
{
|
||||
_class = moo->_large_negative_integer;
|
||||
}
|
||||
else
|
||||
{
|
||||
MOO_ASSERT (moo, IS_NBIGINT(moo, oop));
|
||||
MOO_ASSERT (moo, MOO_POINTER_IS_NBIGINT(moo, oop));
|
||||
_class = moo->_large_positive_integer;
|
||||
}
|
||||
|
||||
@ -629,14 +628,14 @@ static moo_oop_t normalize_bigint (moo_t* moo, moo_oop_t oop)
|
||||
moo_oow_t w;
|
||||
|
||||
w = MOO_OBJ_GET_LIWORD_SLOT(oop)[0];
|
||||
if (IS_PBIGINT(moo, oop))
|
||||
if (MOO_POINTER_IS_PBIGINT(moo, oop))
|
||||
{
|
||||
if (w <= MOO_SMOOI_MAX) return MOO_SMOOI_TO_OOP(w);
|
||||
}
|
||||
else
|
||||
{
|
||||
MOO_ASSERT (moo, -MOO_SMOOI_MAX == MOO_SMOOI_MIN);
|
||||
MOO_ASSERT (moo, IS_NBIGINT(moo, oop));
|
||||
MOO_ASSERT (moo, MOO_POINTER_IS_NBIGINT(moo, oop));
|
||||
if (w <= MOO_SMOOI_MAX) return MOO_SMOOI_TO_OOP(-(moo_ooi_t)w);
|
||||
}
|
||||
}
|
||||
@ -644,13 +643,13 @@ static moo_oop_t normalize_bigint (moo_t* moo, moo_oop_t oop)
|
||||
|
||||
if (count == 1) /* 1 half-word */
|
||||
{
|
||||
if (IS_PBIGINT(moo, oop))
|
||||
if (MOO_POINTER_IS_PBIGINT(moo, oop))
|
||||
{
|
||||
return MOO_SMOOI_TO_OOP(MOO_OBJ_GET_LIWORD_SLOT(oop)[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
MOO_ASSERT (moo, IS_NBIGINT(moo, oop));
|
||||
MOO_ASSERT (moo, MOO_POINTER_IS_NBIGINT(moo, oop));
|
||||
return MOO_SMOOI_TO_OOP(-(moo_ooi_t)MOO_OBJ_GET_LIWORD_SLOT(oop)[0]);
|
||||
}
|
||||
}
|
||||
@ -659,14 +658,14 @@ static moo_oop_t normalize_bigint (moo_t* moo, moo_oop_t oop)
|
||||
moo_oow_t w;
|
||||
|
||||
w = MAKE_WORD (MOO_OBJ_GET_LIWORD_SLOT(oop)[0], MOO_OBJ_GET_LIWORD_SLOT(oop)[1]);
|
||||
if (IS_PBIGINT(moo, oop))
|
||||
if (MOO_POINTER_IS_PBIGINT(moo, oop))
|
||||
{
|
||||
if (w <= MOO_SMOOI_MAX) return MOO_SMOOI_TO_OOP(w);
|
||||
}
|
||||
else
|
||||
{
|
||||
MOO_ASSERT (moo, -MOO_SMOOI_MAX == MOO_SMOOI_MIN);
|
||||
MOO_ASSERT (moo, IS_NBIGINT(moo, oop));
|
||||
MOO_ASSERT (moo, MOO_POINTER_IS_NBIGINT(moo, oop));
|
||||
if (w <= MOO_SMOOI_MAX) return MOO_SMOOI_TO_OOP(-(moo_ooi_t)w);
|
||||
}
|
||||
}
|
||||
@ -707,10 +706,10 @@ static MOO_INLINE int is_less (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
{
|
||||
if (MOO_OBJ_GET_CLASS(x) != MOO_OBJ_GET_CLASS(y))
|
||||
{
|
||||
return IS_NBIGINT(moo, x);
|
||||
return MOO_POINTER_IS_NBIGINT(moo, x);
|
||||
}
|
||||
|
||||
if (IS_PBIGINT(moo, x))
|
||||
if (MOO_POINTER_IS_PBIGINT(moo, x))
|
||||
{
|
||||
return is_less_unsigned(x, y);
|
||||
}
|
||||
@ -745,10 +744,10 @@ static MOO_INLINE int is_greater (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
{
|
||||
if (MOO_OBJ_GET_CLASS(x) != MOO_OBJ_GET_CLASS(y))
|
||||
{
|
||||
return IS_NBIGINT(moo, y);
|
||||
return MOO_POINTER_IS_NBIGINT(moo, y);
|
||||
}
|
||||
|
||||
if (IS_PBIGINT(moo, x))
|
||||
if (MOO_POINTER_IS_PBIGINT(moo, x))
|
||||
{
|
||||
return is_greater_unsigned(x, y);
|
||||
}
|
||||
@ -1624,7 +1623,7 @@ moo_oop_t moo_addints (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
i = MOO_OOP_TO_SMOOI(x) + MOO_OOP_TO_SMOOI(y);
|
||||
if (MOO_IN_SMOOI_RANGE(i)) return MOO_SMOOI_TO_OOP(i);
|
||||
|
||||
return make_bigint_with_ooi (moo, i);
|
||||
return make_bigint_with_ooi(moo, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1638,7 +1637,7 @@ moo_oop_t moo_addints (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
if (v == 0) return clone_bigint (moo, y, MOO_OBJ_GET_SIZE(y));
|
||||
|
||||
moo_pushtmp (moo, &y);
|
||||
x = make_bigint_with_ooi (moo, v);
|
||||
x = make_bigint_with_ooi(moo, v);
|
||||
moo_poptmp (moo);
|
||||
if (!x) return MOO_NULL;
|
||||
}
|
||||
@ -1650,7 +1649,7 @@ moo_oop_t moo_addints (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
if (v == 0) return clone_bigint (moo, x, MOO_OBJ_GET_SIZE(x));
|
||||
|
||||
moo_pushtmp (moo, &x);
|
||||
y = make_bigint_with_ooi (moo, v);
|
||||
y = make_bigint_with_ooi(moo, v);
|
||||
moo_poptmp (moo);
|
||||
if (!y) return MOO_NULL;
|
||||
}
|
||||
@ -1662,17 +1661,17 @@ moo_oop_t moo_addints (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
|
||||
if (MOO_OBJ_GET_CLASS(x) != MOO_OBJ_GET_CLASS(y))
|
||||
{
|
||||
if (IS_NBIGINT(moo, x))
|
||||
if (MOO_POINTER_IS_NBIGINT(moo, x))
|
||||
{
|
||||
/* x is negative, y is positive */
|
||||
if (is_less_unsigned (x, y))
|
||||
if (is_less_unsigned(x, y))
|
||||
{
|
||||
z = subtract_unsigned_integers (moo, y, x);
|
||||
z = subtract_unsigned_integers(moo, y, x);
|
||||
if (!z) return MOO_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
z = subtract_unsigned_integers (moo, x, y);
|
||||
z = subtract_unsigned_integers(moo, x, y);
|
||||
if (!z) return MOO_NULL;
|
||||
MOO_OBJ_SET_CLASS(z, moo->_large_negative_integer);
|
||||
}
|
||||
@ -1680,15 +1679,15 @@ moo_oop_t moo_addints (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
else
|
||||
{
|
||||
/* x is positive, y is negative */
|
||||
if (is_less_unsigned (x, y))
|
||||
if (is_less_unsigned(x, y))
|
||||
{
|
||||
z = subtract_unsigned_integers (moo, y, x);
|
||||
z = subtract_unsigned_integers(moo, y, x);
|
||||
if (!z) return MOO_NULL;
|
||||
MOO_OBJ_SET_CLASS(z, moo->_large_negative_integer);
|
||||
}
|
||||
else
|
||||
{
|
||||
z = subtract_unsigned_integers (moo, x, y);
|
||||
z = subtract_unsigned_integers(moo, x, y);
|
||||
if (!z) return MOO_NULL;
|
||||
}
|
||||
}
|
||||
@ -1697,14 +1696,14 @@ moo_oop_t moo_addints (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
{
|
||||
int neg;
|
||||
/* both are positive or negative */
|
||||
neg = (IS_NBIGINT(moo, x));
|
||||
z = add_unsigned_integers (moo, x, y);
|
||||
neg = (MOO_POINTER_IS_NBIGINT(moo, x));
|
||||
z = add_unsigned_integers(moo, x, y);
|
||||
if (!z) return MOO_NULL;
|
||||
if (neg) MOO_OBJ_SET_CLASS(z, moo->_large_negative_integer);
|
||||
}
|
||||
}
|
||||
|
||||
return normalize_bigint (moo, z);
|
||||
return normalize_bigint(moo, z);
|
||||
|
||||
oops_einval:
|
||||
moo_seterrbfmt (moo, MOO_EINVAL, "invalid parameters - %O, %O", x, y);
|
||||
@ -1770,7 +1769,7 @@ moo_oop_t moo_subints (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
|
||||
if (MOO_OBJ_GET_CLASS(x) != MOO_OBJ_GET_CLASS(y))
|
||||
{
|
||||
neg = (IS_NBIGINT(moo, x));
|
||||
neg = (MOO_POINTER_IS_NBIGINT(moo, x));
|
||||
z = add_unsigned_integers (moo, x, y);
|
||||
if (!z) return MOO_NULL;
|
||||
if (neg) MOO_OBJ_SET_CLASS(z, moo->_large_negative_integer);
|
||||
@ -1780,14 +1779,14 @@ moo_oop_t moo_subints (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
/* both are positive or negative */
|
||||
if (is_less_unsigned (x, y))
|
||||
{
|
||||
neg = (IS_NBIGINT(moo, x));
|
||||
neg = (MOO_POINTER_IS_NBIGINT(moo, x));
|
||||
z = subtract_unsigned_integers (moo, y, x);
|
||||
if (!z) return MOO_NULL;
|
||||
if (!neg) MOO_OBJ_SET_CLASS(z, moo->_large_negative_integer);
|
||||
}
|
||||
else
|
||||
{
|
||||
neg = (IS_NBIGINT(moo, x));
|
||||
neg = (MOO_POINTER_IS_NBIGINT(moo, x));
|
||||
z = subtract_unsigned_integers (moo, x, y); /* take x's sign */
|
||||
if (!z) return MOO_NULL;
|
||||
if (neg) MOO_OBJ_SET_CLASS(z, moo->_large_negative_integer);
|
||||
@ -2083,8 +2082,8 @@ moo_oop_t moo_divints (moo_t* moo, moo_oop_t x, moo_oop_t y, int modulo, moo_oop
|
||||
}
|
||||
}
|
||||
|
||||
x_neg = (IS_NBIGINT(moo, x));
|
||||
y_neg = (IS_NBIGINT(moo, y));
|
||||
x_neg = (MOO_POINTER_IS_NBIGINT(moo, x));
|
||||
y_neg = (MOO_POINTER_IS_NBIGINT(moo, y));
|
||||
|
||||
moo_pushtmp (moo, &x);
|
||||
moo_pushtmp (moo, &y);
|
||||
@ -2208,7 +2207,7 @@ moo_oop_t moo_bitatint (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
{
|
||||
if (!is_bigint(moo, y)) goto oops_einval;
|
||||
|
||||
if (IS_NBIGINT(moo, y)) return MOO_SMOOI_TO_OOP(0);
|
||||
if (MOO_POINTER_IS_NBIGINT(moo, y)) return MOO_SMOOI_TO_OOP(0);
|
||||
|
||||
/* y is definitely >= MOO_SMOOI_BITS */
|
||||
if (MOO_OOP_TO_SMOOI(x) >= 0)
|
||||
@ -2229,7 +2228,7 @@ moo_oop_t moo_bitatint (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
bp = v - (wp * MOO_LIW_BITS);
|
||||
|
||||
xs = MOO_OBJ_GET_SIZE(x);
|
||||
if (IS_PBIGINT(moo, x))
|
||||
if (MOO_POINTER_IS_PBIGINT(moo, x))
|
||||
{
|
||||
if (wp >= xs) return MOO_SMOOI_TO_OOP(0);
|
||||
v = (MOO_OBJ_GET_LIWORD_SLOT(x)[wp] >> bp) & 1;
|
||||
@ -2265,10 +2264,10 @@ moo_oop_t moo_bitatint (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
if (!is_bigint(moo, x) || !is_bigint(moo, y)) goto oops_einval;
|
||||
|
||||
#if defined(MOO_LIMIT_OBJ_SIZE)
|
||||
if (IS_NBIGINT(moo, y)) return MOO_SMOOI_TO_OOP(0);
|
||||
if (MOO_POINTER_IS_NBIGINT(moo, y)) return MOO_SMOOI_TO_OOP(0);
|
||||
|
||||
MOO_ASSERT (moo, MOO_OBJ_SIZE_BITS_MAX <= MOO_TYPE_MAX(moo_oow_t));
|
||||
if (IS_PBIGINT(moo, x))
|
||||
if (MOO_POINTER_IS_PBIGINT(moo, x))
|
||||
{
|
||||
return MOO_SMOOI_TO_OOP (0);
|
||||
}
|
||||
@ -2279,7 +2278,7 @@ moo_oop_t moo_bitatint (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
#else
|
||||
xs = MOO_OBJ_GET_SIZE(x);
|
||||
|
||||
if (IS_NBIGINT(moo, y)) return MOO_SMOOI_TO_OOP(0);
|
||||
if (MOO_POINTER_IS_NBIGINT(moo, y)) return MOO_SMOOI_TO_OOP(0);
|
||||
|
||||
sign = bigint_to_oow (moo, y, &w);
|
||||
MOO_ASSERT (moo, sign >= 0);
|
||||
@ -2313,7 +2312,7 @@ moo_oop_t moo_bitatint (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
MOO_ASSERT (moo, bp >= 0 && bp < MOO_LIW_BITS);
|
||||
}
|
||||
|
||||
if (IS_PBIGINT(moo, x))
|
||||
if (MOO_POINTER_IS_PBIGINT(moo, x))
|
||||
{
|
||||
if (wp >= xs) return MOO_SMOOI_TO_OOP(0);
|
||||
v = (MOO_OBJ_GET_LIWORD_SLOT(x)[wp] >> bp) & 1;
|
||||
@ -2411,8 +2410,8 @@ moo_oop_t moo_bitandints (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
xs = zs;
|
||||
}
|
||||
|
||||
negx = (IS_NBIGINT(moo, x))? 1: 0;
|
||||
negy = (IS_NBIGINT(moo, y))? 1: 0;
|
||||
negx = (MOO_POINTER_IS_NBIGINT(moo, x))? 1: 0;
|
||||
negy = (MOO_POINTER_IS_NBIGINT(moo, y))? 1: 0;
|
||||
|
||||
if (negx && negy)
|
||||
{
|
||||
@ -2624,8 +2623,8 @@ moo_oop_t moo_bitorints (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
xs = zs;
|
||||
}
|
||||
|
||||
negx = (IS_NBIGINT(moo, x))? 1: 0;
|
||||
negy = (IS_NBIGINT(moo, y))? 1: 0;
|
||||
negx = (MOO_POINTER_IS_NBIGINT(moo, x))? 1: 0;
|
||||
negy = (MOO_POINTER_IS_NBIGINT(moo, y))? 1: 0;
|
||||
|
||||
if (negx && negy)
|
||||
{
|
||||
@ -2842,8 +2841,8 @@ moo_oop_t moo_bitxorints (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
xs = zs;
|
||||
}
|
||||
|
||||
negx = (IS_NBIGINT(moo, x))? 1: 0;
|
||||
negy = (IS_NBIGINT(moo, y))? 1: 0;
|
||||
negx = (MOO_POINTER_IS_NBIGINT(moo, x))? 1: 0;
|
||||
negy = (MOO_POINTER_IS_NBIGINT(moo, y))? 1: 0;
|
||||
|
||||
if (negx && negy)
|
||||
{
|
||||
@ -3012,7 +3011,7 @@ moo_oop_t moo_bitinvint (moo_t* moo, moo_oop_t x)
|
||||
if (!is_bigint(moo,x)) goto oops_einval;
|
||||
|
||||
xs = MOO_OBJ_GET_SIZE(x);
|
||||
negx = (IS_NBIGINT(moo, x))? 1: 0;
|
||||
negx = (MOO_POINTER_IS_NBIGINT(moo, x))? 1: 0;
|
||||
|
||||
if (negx)
|
||||
{
|
||||
@ -3100,7 +3099,7 @@ static MOO_INLINE moo_oop_t rshift_negative_bigint (moo_t* moo, moo_oop_t x, moo
|
||||
moo_lidw_t carry;
|
||||
moo_oow_t i, xs;
|
||||
|
||||
MOO_ASSERT (moo, IS_NBIGINT(moo, x));
|
||||
MOO_ASSERT (moo, MOO_POINTER_IS_NBIGINT(moo, x));
|
||||
xs = MOO_OBJ_GET_SIZE(x);
|
||||
|
||||
moo_pushtmp (moo, &x);
|
||||
@ -3163,8 +3162,8 @@ static MOO_INLINE moo_oop_t rshift_negative_bigint_and_normalize (moo_t* moo, mo
|
||||
moo_oow_t shift;
|
||||
int sign;
|
||||
|
||||
MOO_ASSERT (moo, IS_NBIGINT(moo, x));
|
||||
MOO_ASSERT (moo, IS_NBIGINT(moo, y));
|
||||
MOO_ASSERT (moo, MOO_POINTER_IS_NBIGINT(moo, x));
|
||||
MOO_ASSERT (moo, MOO_POINTER_IS_NBIGINT(moo, y));
|
||||
|
||||
/* for convenience in subtraction below.
|
||||
* it could be MOO_TYPE_MAX(moo_oow_t)
|
||||
@ -3241,8 +3240,8 @@ static MOO_INLINE moo_oop_t rshift_positive_bigint_and_normalize (moo_t* moo, mo
|
||||
moo_oow_t zs, shift;
|
||||
int sign;
|
||||
|
||||
MOO_ASSERT (moo, IS_PBIGINT(moo, x));
|
||||
MOO_ASSERT (moo, IS_NBIGINT(moo, y));
|
||||
MOO_ASSERT (moo, MOO_POINTER_IS_PBIGINT(moo, x));
|
||||
MOO_ASSERT (moo, MOO_POINTER_IS_NBIGINT(moo, y));
|
||||
|
||||
zs = MOO_OBJ_GET_SIZE(x);
|
||||
|
||||
@ -3291,7 +3290,7 @@ static MOO_INLINE moo_oop_t lshift_bigint_and_normalize (moo_t* moo, moo_oop_t x
|
||||
moo_oow_t wshift, shift;
|
||||
int sign;
|
||||
|
||||
MOO_ASSERT (moo, IS_PBIGINT(moo, y));
|
||||
MOO_ASSERT (moo, MOO_POINTER_IS_PBIGINT(moo, y));
|
||||
|
||||
/* this loop is very inefficient as shifting is repeated
|
||||
* with lshift_unsigned_array(). however, this part of the
|
||||
@ -3435,7 +3434,7 @@ moo_oop_t moo_bitshiftint (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
v = MOO_OOP_TO_SMOOI(x);
|
||||
if (v == 0) return MOO_SMOOI_TO_OOP(0);
|
||||
|
||||
if (IS_NBIGINT(moo, y))
|
||||
if (MOO_POINTER_IS_NBIGINT(moo, y))
|
||||
{
|
||||
/* right shift - special case.
|
||||
* x is a small integer. it is just a few bytes long.
|
||||
@ -3460,7 +3459,7 @@ moo_oop_t moo_bitshiftint (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
v = MOO_OOP_TO_SMOOI(y);
|
||||
if (v == 0) return clone_bigint (moo, x, MOO_OBJ_GET_SIZE(x));
|
||||
|
||||
negx = (IS_NBIGINT(moo, x))? 1: 0;
|
||||
negx = (MOO_POINTER_IS_NBIGINT(moo, x))? 1: 0;
|
||||
if (v > 0)
|
||||
{
|
||||
sign = 1;
|
||||
@ -3483,8 +3482,8 @@ moo_oop_t moo_bitshiftint (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
if (!is_bigint(moo,x) || !is_bigint(moo, y)) goto oops_einval;
|
||||
|
||||
bigint_and_bigint:
|
||||
negx = (IS_NBIGINT(moo, x))? 1: 0;
|
||||
negy = (IS_NBIGINT(moo, y))? 1: 0;
|
||||
negx = (MOO_POINTER_IS_NBIGINT(moo, x))? 1: 0;
|
||||
negy = (MOO_POINTER_IS_NBIGINT(moo, y))? 1: 0;
|
||||
|
||||
sign = bigint_to_oow (moo, y, &shift);
|
||||
if (sign == 0)
|
||||
@ -3807,21 +3806,14 @@ oops_einval:
|
||||
return MOO_NULL;
|
||||
}
|
||||
|
||||
static moo_oow_t oow_to_text (moo_t* moo, moo_oow_t w, int radix, moo_ooch_t* buf)
|
||||
static moo_oow_t oow_to_text (moo_t* moo, moo_oow_t w, int flagged_radix, moo_ooch_t* buf)
|
||||
{
|
||||
moo_ooch_t* ptr;
|
||||
const char* _digitc;
|
||||
int radix;
|
||||
|
||||
if (radix < 0)
|
||||
{
|
||||
_digitc = _digitc_lower;
|
||||
radix = -radix;
|
||||
}
|
||||
else
|
||||
{
|
||||
_digitc = _digitc_upper;
|
||||
}
|
||||
|
||||
radix = flagged_radix & 0xFF;
|
||||
_digitc = _digitc_array[!!(flagged_radix & MOO_INTTOSTR_LOWERCASE)];
|
||||
MOO_ASSERT (moo, radix >= 2 && radix <= 36);
|
||||
|
||||
ptr = buf;
|
||||
@ -3900,12 +3892,12 @@ moo_oop_t moo_gtints (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
else if (MOO_OOP_IS_SMOOI(x))
|
||||
{
|
||||
if (!is_bigint(moo, y)) goto oops_einval;
|
||||
return (IS_NBIGINT(moo, y))? moo->_true: moo->_false;
|
||||
return (MOO_POINTER_IS_NBIGINT(moo, y))? moo->_true: moo->_false;
|
||||
}
|
||||
else if (MOO_OOP_IS_SMOOI(y))
|
||||
{
|
||||
if (!is_bigint(moo, x)) goto oops_einval;
|
||||
return (IS_PBIGINT(moo, x))? moo->_true: moo->_false;
|
||||
return (MOO_POINTER_IS_PBIGINT(moo, x))? moo->_true: moo->_false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3927,12 +3919,12 @@ moo_oop_t moo_geints (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
else if (MOO_OOP_IS_SMOOI(x))
|
||||
{
|
||||
if (!is_bigint(moo, y)) goto oops_einval;
|
||||
return (IS_NBIGINT(moo, y))? moo->_true: moo->_false;
|
||||
return (MOO_POINTER_IS_NBIGINT(moo, y))? moo->_true: moo->_false;
|
||||
}
|
||||
else if (MOO_OOP_IS_SMOOI(y))
|
||||
{
|
||||
if (!is_bigint(moo, x)) goto oops_einval;
|
||||
return (IS_PBIGINT(moo, x))? moo->_true: moo->_false;
|
||||
return (MOO_POINTER_IS_PBIGINT(moo, x))? moo->_true: moo->_false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3954,12 +3946,12 @@ moo_oop_t moo_ltints (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
else if (MOO_OOP_IS_SMOOI(x))
|
||||
{
|
||||
if (!is_bigint(moo, y)) goto oops_einval;
|
||||
return (IS_PBIGINT(moo, y))? moo->_true: moo->_false;
|
||||
return (MOO_POINTER_IS_PBIGINT(moo, y))? moo->_true: moo->_false;
|
||||
}
|
||||
else if (MOO_OOP_IS_SMOOI(y))
|
||||
{
|
||||
if (!is_bigint(moo, x)) goto oops_einval;
|
||||
return (IS_NBIGINT(moo, x))? moo->_true: moo->_false;
|
||||
return (MOO_POINTER_IS_NBIGINT(moo, x))? moo->_true: moo->_false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3981,12 +3973,12 @@ moo_oop_t moo_leints (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
||||
else if (MOO_OOP_IS_SMOOI(x))
|
||||
{
|
||||
if (!is_bigint(moo, y)) goto oops_einval;
|
||||
return (IS_PBIGINT(moo, y))? moo->_true: moo->_false;
|
||||
return (MOO_POINTER_IS_PBIGINT(moo, y))? moo->_true: moo->_false;
|
||||
}
|
||||
else if (MOO_OOP_IS_SMOOI(y))
|
||||
{
|
||||
if (!is_bigint(moo, x)) goto oops_einval;
|
||||
return (IS_NBIGINT(moo, x))? moo->_true: moo->_false;
|
||||
return (MOO_POINTER_IS_NBIGINT(moo, x))? moo->_true: moo->_false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4091,11 +4083,11 @@ moo_oop_t moo_absint (moo_t* moo, moo_oop_t x)
|
||||
x = MOO_SMOOI_TO_OOP(v);
|
||||
}
|
||||
}
|
||||
else if (IS_NBIGINT(moo, x))
|
||||
else if (MOO_POINTER_IS_NBIGINT(moo, x))
|
||||
{
|
||||
x = _clone_bigint(moo, x, MOO_OBJ_GET_SIZE(x), moo->_large_positive_integer);
|
||||
}
|
||||
else if (IS_PBIGINT(moo, x))
|
||||
else if (MOO_POINTER_IS_PBIGINT(moo, x))
|
||||
{
|
||||
/* do nothing. return x without change.
|
||||
* [THINK] but do i need to clone a positive bigint? */
|
||||
@ -4109,7 +4101,7 @@ moo_oop_t moo_absint (moo_t* moo, moo_oop_t x)
|
||||
return x;
|
||||
}
|
||||
|
||||
moo_oop_t moo_inttostr (moo_t* moo, moo_oop_t num, int radix)
|
||||
moo_oop_t moo_inttostr (moo_t* moo, moo_oop_t num, int flagged_radix)
|
||||
{
|
||||
moo_ooi_t v = 0;
|
||||
moo_oow_t w;
|
||||
@ -4126,18 +4118,11 @@ moo_oop_t moo_inttostr (moo_t* moo, moo_oop_t num, int radix)
|
||||
moo_ooch_t* xbuf = MOO_NULL;
|
||||
moo_oow_t xlen = 0, seglen, reqcapa;
|
||||
|
||||
int radix;
|
||||
const char* _digitc;
|
||||
int orgradix = radix;
|
||||
|
||||
if (radix < 0)
|
||||
{
|
||||
_digitc = _digitc_lower;
|
||||
radix = -radix;
|
||||
}
|
||||
else
|
||||
{
|
||||
_digitc = _digitc_upper;
|
||||
}
|
||||
radix = flagged_radix & 0xFF;
|
||||
_digitc = _digitc_array[!!(flagged_radix & MOO_INTTOSTR_LOWERCASE)];
|
||||
MOO_ASSERT (moo, radix >= 2 && radix <= 36);
|
||||
|
||||
if (!moo_isint(moo,num)) goto oops_einval;
|
||||
@ -4163,10 +4148,17 @@ moo_oop_t moo_inttostr (moo_t* moo, moo_oop_t num, int radix)
|
||||
xbuf = moo->inttostr.xbuf.ptr;
|
||||
}
|
||||
|
||||
xlen = oow_to_text(moo, w, orgradix, xbuf);
|
||||
xlen = oow_to_text(moo, w, flagged_radix, xbuf);
|
||||
if (v < 0) xbuf[xlen++] = '-';
|
||||
|
||||
reverse_string (xbuf, xlen);
|
||||
if (flagged_radix & MOO_INTTOSTR_NONEWOBJ)
|
||||
{
|
||||
/* special case. don't create a new object.
|
||||
* the caller can use the data left in moo->inttostr.xbuf */
|
||||
moo->inttostr.xbuf.len = xlen;
|
||||
return moo->_nil;
|
||||
}
|
||||
return moo_makestring(moo, xbuf, xlen);
|
||||
}
|
||||
|
||||
@ -4223,7 +4215,16 @@ moo_oop_t moo_inttostr (moo_t* moo, moo_oop_t num, int radix)
|
||||
}
|
||||
|
||||
MOO_ASSERT (moo, xpos >= 1);
|
||||
if (IS_NBIGINT(moo, num)) xbuf[--xpos] = '-';
|
||||
if (MOO_POINTER_IS_NBIGINT(moo, num)) xbuf[--xpos] = '-';
|
||||
|
||||
if (flagged_radix & MOO_INTTOSTR_NONEWOBJ)
|
||||
{
|
||||
/* special case. don't create a new object.
|
||||
* the caller can use the data left in moo->inttostr.xbuf */
|
||||
MOO_MEMMOVE (&xbuf[0], &xbuf[xpos], MOO_SIZEOF(*xbuf) * (xlen - xpos));
|
||||
moo->inttostr.xbuf.len = xlen - xpos;
|
||||
return moo->_nil;
|
||||
}
|
||||
|
||||
return moo_makestring(moo, &xbuf[xpos], xlen - xpos);
|
||||
}
|
||||
@ -4313,7 +4314,7 @@ moo_oop_t moo_inttostr (moo_t* moo, moo_oop_t num, int radix)
|
||||
#else
|
||||
# error UNSUPPORTED LIW BIT SIZE
|
||||
#endif
|
||||
seglen = oow_to_text (moo, w, orgradix, &xbuf[xlen]);
|
||||
seglen = oow_to_text (moo, w, flagged_radix, &xbuf[xlen]);
|
||||
xlen += seglen;
|
||||
if (r == a) break; /* reached the last block */
|
||||
|
||||
@ -4327,8 +4328,15 @@ moo_oop_t moo_inttostr (moo_t* moo, moo_oop_t num, int radix)
|
||||
}
|
||||
while (1);
|
||||
|
||||
if (IS_NBIGINT(moo, num)) xbuf[xlen++] = '-';
|
||||
if (MOO_POINTER_IS_NBIGINT(moo, num)) xbuf[xlen++] = '-';
|
||||
reverse_string (xbuf, xlen);
|
||||
if (flagged_radix & MOO_INTTOSTR_NONEWOBJ)
|
||||
{
|
||||
/* special case. don't create a new object.
|
||||
* the caller can use the data left in moo->inttostr.xbuf */
|
||||
moo->inttostr.xbuf.len = xlen;
|
||||
return moo->_nil;
|
||||
}
|
||||
|
||||
return moo_makestring(moo, xbuf, xlen);
|
||||
|
||||
|
@ -2831,7 +2831,7 @@ static moo_pfrc_t pf_integer_add (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
|
||||
res = moo_addints (moo, rcv, arg);
|
||||
res = moo_addints(moo, rcv, arg);
|
||||
if (!res) return (moo->errnum == MOO_EINVAL? MOO_PF_FAILURE: MOO_PF_HARD_FAILURE);
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, res);
|
||||
@ -2847,7 +2847,7 @@ static moo_pfrc_t pf_integer_sub (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
|
||||
res = moo_subints (moo, rcv, arg);
|
||||
res = moo_subints(moo, rcv, arg);
|
||||
if (!res) return (moo->errnum == MOO_EINVAL? MOO_PF_FAILURE: MOO_PF_HARD_FAILURE);
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, res);
|
||||
@ -2863,7 +2863,7 @@ static moo_pfrc_t pf_integer_mul (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
|
||||
res = moo_mulints (moo, rcv, arg);
|
||||
res = moo_mulints(moo, rcv, arg);
|
||||
if (!res) return (moo->errnum == MOO_EINVAL? MOO_PF_FAILURE: MOO_PF_HARD_FAILURE);
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, res);
|
||||
@ -2975,7 +2975,7 @@ static moo_pfrc_t pf_integer_bitand (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
|
||||
res = moo_bitandints (moo, rcv, arg);
|
||||
res = moo_bitandints(moo, rcv, arg);
|
||||
if (!res) return (moo->errnum == MOO_EINVAL? MOO_PF_FAILURE: MOO_PF_HARD_FAILURE);
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, res);
|
||||
@ -2991,7 +2991,7 @@ static moo_pfrc_t pf_integer_bitor (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
|
||||
res = moo_bitorints (moo, rcv, arg);
|
||||
res = moo_bitorints(moo, rcv, arg);
|
||||
if (!res) return (moo->errnum == MOO_EINVAL? MOO_PF_FAILURE: MOO_PF_HARD_FAILURE);
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, res);
|
||||
@ -3007,7 +3007,7 @@ static moo_pfrc_t pf_integer_bitxor (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
|
||||
res = moo_bitxorints (moo, rcv, arg);
|
||||
res = moo_bitxorints(moo, rcv, arg);
|
||||
if (!res) return (moo->errnum == MOO_EINVAL? MOO_PF_FAILURE: MOO_PF_HARD_FAILURE);
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, res);
|
||||
@ -3022,7 +3022,7 @@ static moo_pfrc_t pf_integer_bitinv (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs
|
||||
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
|
||||
res = moo_bitinvint (moo, rcv);
|
||||
res = moo_bitinvint(moo, rcv);
|
||||
if (!res) return (moo->errnum == MOO_EINVAL? MOO_PF_FAILURE: MOO_PF_HARD_FAILURE);
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, res);
|
||||
@ -3038,7 +3038,7 @@ static moo_pfrc_t pf_integer_bitshift (moo_t* moo, moo_mod_t* mod, moo_ooi_t nar
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
|
||||
res = moo_bitshiftint (moo, rcv, arg);
|
||||
res = moo_bitshiftint(moo, rcv, arg);
|
||||
if (!res) return (moo->errnum == MOO_EINVAL? MOO_PF_FAILURE: MOO_PF_HARD_FAILURE);
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, res);
|
||||
@ -3054,7 +3054,7 @@ static moo_pfrc_t pf_integer_eq (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
|
||||
res = moo_eqints (moo, rcv, arg);
|
||||
res = moo_eqints(moo, rcv, arg);
|
||||
if (!res) return (moo->errnum == MOO_EINVAL? MOO_PF_FAILURE: MOO_PF_HARD_FAILURE);
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, res);
|
||||
@ -3070,7 +3070,7 @@ static moo_pfrc_t pf_integer_ne (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
|
||||
res = moo_neints (moo, rcv, arg);
|
||||
res = moo_neints(moo, rcv, arg);
|
||||
if (!res) return (moo->errnum == MOO_EINVAL? MOO_PF_FAILURE: MOO_PF_HARD_FAILURE);
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, res);
|
||||
@ -3086,7 +3086,7 @@ static moo_pfrc_t pf_integer_lt (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
|
||||
res = moo_ltints (moo, rcv, arg);
|
||||
res = moo_ltints(moo, rcv, arg);
|
||||
if (!res) return (moo->errnum == MOO_EINVAL? MOO_PF_FAILURE: MOO_PF_HARD_FAILURE);
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, res);
|
||||
@ -3102,7 +3102,7 @@ static moo_pfrc_t pf_integer_gt (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
|
||||
res = moo_gtints (moo, rcv, arg);
|
||||
res = moo_gtints(moo, rcv, arg);
|
||||
if (!res) return (moo->errnum == MOO_EINVAL? MOO_PF_FAILURE: MOO_PF_HARD_FAILURE);
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, res);
|
||||
@ -3118,7 +3118,7 @@ static moo_pfrc_t pf_integer_le (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
|
||||
res = moo_leints (moo, rcv, arg);
|
||||
res = moo_leints(moo, rcv, arg);
|
||||
if (!res) return (moo->errnum == MOO_EINVAL? MOO_PF_FAILURE: MOO_PF_HARD_FAILURE);
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, res);
|
||||
@ -3134,7 +3134,7 @@ static moo_pfrc_t pf_integer_ge (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
|
||||
res = moo_geints (moo, rcv, arg);
|
||||
res = moo_geints(moo, rcv, arg);
|
||||
if (!res) return (moo->errnum == MOO_EINVAL? MOO_PF_FAILURE: MOO_PF_HARD_FAILURE);
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, res);
|
||||
@ -3155,7 +3155,7 @@ static moo_pfrc_t pf_integer_inttostr (moo_t* moo, moo_mod_t* mod, moo_ooi_t nar
|
||||
radix = MOO_OOP_TO_SMOOI(arg);
|
||||
|
||||
if (radix < 2 || radix > 36) return MOO_PF_FAILURE;
|
||||
str = moo_inttostr (moo, rcv, radix);
|
||||
str = moo_inttostr(moo, rcv, radix);
|
||||
if (!str) return (moo->errnum == MOO_EINVAL? MOO_PF_FAILURE: MOO_PF_HARD_FAILURE);
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, str);
|
||||
@ -3389,6 +3389,29 @@ static moo_pfrc_t pf_error_as_string (moo_t* moo, moo_mod_t* mod, moo_ooi_t narg
|
||||
return MOO_PF_SUCCESS;
|
||||
}
|
||||
|
||||
static moo_pfrc_t pf_strfmt (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||
{
|
||||
moo_oop_t rcv;
|
||||
|
||||
rcv = MOO_STACK_GETRCV(moo, nargs);
|
||||
MOO_PF_CHECK_RCV (moo, MOO_OBJ_IS_CHAR_POINTER(rcv));
|
||||
|
||||
if (moo_sprintfmtst(moo, nargs) <= -1)
|
||||
{
|
||||
MOO_STACK_SETRETTOERRNUM (moo, nargs);
|
||||
}
|
||||
else
|
||||
{
|
||||
moo_oop_t str;
|
||||
str = moo_makestring(moo, moo->sprintf.xbuf.ptr, moo->sprintf.xbuf.len);
|
||||
if (!str) return MOO_PF_FAILURE;
|
||||
|
||||
MOO_STACK_SETRET (moo, nargs, str);
|
||||
}
|
||||
|
||||
return MOO_PF_SUCCESS;
|
||||
}
|
||||
|
||||
static moo_pfrc_t pf_strlen (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||
{
|
||||
moo_oop_t rcv, ret;
|
||||
@ -3574,6 +3597,7 @@ static pf_t pftab[] =
|
||||
{ "SmallPointer_putUint64", { moo_pf_smptr_put_uint64, 2, 2 } },
|
||||
{ "SmallPointer_putUint8", { moo_pf_smptr_put_uint8, 2, 2 } },
|
||||
|
||||
{ "String_strfmt", { pf_strfmt, 0, MA } },
|
||||
{ "String_strlen", { pf_strlen, 0, 0 } },
|
||||
|
||||
{ "System_calloc", { moo_pf_system_calloc, 1, 1 } },
|
||||
|
745
moo/lib/logfmt.c
745
moo/lib/logfmt.c
@ -130,14 +130,14 @@ static moo_bch_t bch_nullstr[] = { '(','n','u','l','l', ')','\0' };
|
||||
|
||||
typedef int (*moo_fmtout_putch_t) (
|
||||
moo_t* moo,
|
||||
moo_bitmask_t mask,
|
||||
moo_bitmask_t mask,
|
||||
moo_ooch_t c,
|
||||
moo_oow_t len
|
||||
);
|
||||
|
||||
typedef int (*moo_fmtout_putcs_t) (
|
||||
moo_t* moo,
|
||||
moo_bitmask_t mask,
|
||||
moo_bitmask_t mask,
|
||||
const moo_ooch_t* ptr,
|
||||
moo_oow_t len
|
||||
);
|
||||
@ -146,7 +146,7 @@ typedef struct moo_fmtout_t moo_fmtout_t;
|
||||
struct moo_fmtout_t
|
||||
{
|
||||
moo_oow_t count; /* out */
|
||||
moo_bitmask_t mask; /* in */
|
||||
moo_bitmask_t mask; /* in */
|
||||
moo_fmtout_putch_t putch; /* in */
|
||||
moo_fmtout_putcs_t putcs; /* in */
|
||||
};
|
||||
@ -417,7 +417,7 @@ static int print_object (moo_t* moo, moo_bitmask_t mask, moo_oop_t oop, outbfmt_
|
||||
if (c == moo->_large_negative_integer)
|
||||
{
|
||||
moo_oow_t i;
|
||||
if (outbfmt (moo, mask, "-16r") <= -1) return -1;
|
||||
if (outbfmt(moo, mask, "-16r") <= -1) return -1;
|
||||
for (i = MOO_OBJ_GET_SIZE(oop); i > 0;)
|
||||
{
|
||||
if (outbfmt(moo, mask, "%0*lX", (int)(MOO_SIZEOF(moo_liw_t) * 2), (unsigned long int)(MOO_OBJ_GET_LIWORD_SLOT(oop)[--i])) <= -1) return -1;
|
||||
@ -823,3 +823,740 @@ void moo_seterrufmtv (moo_t* moo, moo_errnum_t errnum, const moo_uch_t* fmt, va_
|
||||
_errufmtv (moo, fmt, &fo, ap);
|
||||
moo->errnum = errnum;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* SUPPORT FOR FORMATTED OUTPUT TO BE USED BY BUILTIN PRIMITIVE FUNCTIONS
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
#define PRINT_OOCH(c,n) do { \
|
||||
if (n > 0) { \
|
||||
int xx; \
|
||||
if ((xx = data->putch(moo, data->mask, c, n)) <= -1) goto oops; \
|
||||
if (xx == 0) goto done; \
|
||||
data->count += n; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define PRINT_OOCS(ptr,len) do { \
|
||||
if (len > 0) { \
|
||||
int xx; \
|
||||
if ((xx = data->putcs(moo, data->mask, ptr, len)) <= -1) goto oops; \
|
||||
if (xx == 0) goto done; \
|
||||
data->count += len; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define GET_NEXT_ARG_TO(moo,nargs,arg_state,arg) do { \
|
||||
if ((arg_state)->idx >= nargs) { (arg_state)->stop = 1; goto invalid_format; } \
|
||||
arg = MOO_STACK_GETARG(moo, nargs, (arg_state)->idx); \
|
||||
(arg_state)->idx++; \
|
||||
} while(0)
|
||||
|
||||
#define GET_NEXT_CHAR_TO(moo,fmt,fmtend,ch) do { \
|
||||
if (fmt >= fmtend) ch = MOO_OOCI_EOF; \
|
||||
else { ch = *(fmt); (fmt)++; }\
|
||||
} while(0)
|
||||
|
||||
static MOO_INLINE int print_formatted (moo_t* moo, moo_ooi_t nargs, moo_fmtout_t* data, moo_outbfmt_t outbfmt, int ignore_rcv)
|
||||
{
|
||||
const moo_ooch_t* fmt, * fmtend;
|
||||
const moo_ooch_t* checkpoint, * percent;
|
||||
|
||||
int n, radix, neg, sign, radix_flags;
|
||||
moo_ooi_t extra, width, precision;
|
||||
moo_ooch_t padc, ooch;
|
||||
moo_ooci_t ch;
|
||||
int flagc;
|
||||
|
||||
struct
|
||||
{
|
||||
moo_ooi_t idx;
|
||||
int stop;
|
||||
} arg_state;
|
||||
moo_oop_t arg;
|
||||
|
||||
if (ignore_rcv)
|
||||
{
|
||||
arg = MOO_STACK_GETARG(moo, nargs, 0);
|
||||
arg_state.idx = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
arg = MOO_STACK_GETRCV(moo, nargs);
|
||||
arg_state.idx = 0;
|
||||
}
|
||||
|
||||
if (!MOO_OOP_IS_POINTER(arg) || MOO_OBJ_GET_FLAGS_TYPE(arg) != MOO_OBJ_TYPE_CHAR)
|
||||
{
|
||||
moo_ooi_t i;
|
||||
/* if the first argument is not a valid formatting string,
|
||||
* print all arguments as objects */
|
||||
if (print_object(moo, data->mask, arg, outbfmt) <= -1) goto oops;
|
||||
for (i = arg_state.idx; i < nargs; i++)
|
||||
{
|
||||
arg = MOO_STACK_GETARG(moo, nargs, i);
|
||||
if (print_object(moo, data->mask, arg, outbfmt) <= -1) goto oops;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
arg_state.stop = 0;
|
||||
|
||||
fmt = MOO_OBJ_GET_CHAR_SLOT(arg);
|
||||
fmtend = fmt + MOO_OBJ_GET_SIZE(arg);
|
||||
|
||||
data->count = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
checkpoint = fmt;
|
||||
|
||||
while (1)
|
||||
{
|
||||
GET_NEXT_CHAR_TO (moo, fmt, fmtend, ch);
|
||||
if (ch == '%' && !arg_state.stop) break;
|
||||
|
||||
if (ch == MOO_OOCI_EOF)
|
||||
{
|
||||
/* fmt is not advanced when it is length-bounded.
|
||||
* so not fmt - checkpoint - 1 */
|
||||
PRINT_OOCS (checkpoint, fmt - checkpoint);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
PRINT_OOCS (checkpoint, fmt - checkpoint - 1);
|
||||
|
||||
percent = fmt - 1;
|
||||
|
||||
padc = ' ';
|
||||
width = 0; precision = 0;
|
||||
neg = 0; sign = 0;
|
||||
|
||||
flagc = 0;
|
||||
radix_flags = MOO_INTTOSTR_NONEWOBJ;
|
||||
|
||||
reswitch:
|
||||
GET_NEXT_CHAR_TO (moo, fmt, fmtend, ch);
|
||||
switch (ch)
|
||||
{
|
||||
case '%': /* %% */
|
||||
ooch = ch;
|
||||
goto print_char;
|
||||
|
||||
/* flag characters */
|
||||
case '.':
|
||||
if (flagc & FLAGC_DOT) goto invalid_format;
|
||||
flagc |= FLAGC_DOT;
|
||||
goto reswitch;
|
||||
|
||||
case '#':
|
||||
if (flagc & (FLAGC_WIDTH | FLAGC_DOT | FLAGC_LENMOD)) goto invalid_format;
|
||||
flagc |= FLAGC_SHARP;
|
||||
goto reswitch;
|
||||
|
||||
case ' ':
|
||||
if (flagc & (FLAGC_WIDTH | FLAGC_DOT | FLAGC_LENMOD)) goto invalid_format;
|
||||
flagc |= FLAGC_SPACE;
|
||||
goto reswitch;
|
||||
|
||||
case '+': /* place sign for signed conversion */
|
||||
if (flagc & (FLAGC_WIDTH | FLAGC_DOT | FLAGC_LENMOD)) goto invalid_format;
|
||||
flagc |= FLAGC_SIGN;
|
||||
goto reswitch;
|
||||
|
||||
case '-': /* left adjusted */
|
||||
if (flagc & (FLAGC_WIDTH | FLAGC_DOT | FLAGC_LENMOD)) goto invalid_format;
|
||||
if (flagc & FLAGC_DOT)
|
||||
{
|
||||
goto invalid_format;
|
||||
}
|
||||
else
|
||||
{
|
||||
flagc |= FLAGC_LEFTADJ;
|
||||
if (flagc & FLAGC_ZEROPAD)
|
||||
{
|
||||
padc = ' ';
|
||||
flagc &= ~FLAGC_ZEROPAD;
|
||||
}
|
||||
}
|
||||
|
||||
goto reswitch;
|
||||
|
||||
case '*': /* take the length from the parameter */
|
||||
if (flagc & FLAGC_DOT)
|
||||
{
|
||||
if (flagc & (FLAGC_STAR2 | FLAGC_PRECISION)) goto invalid_format;
|
||||
flagc |= FLAGC_STAR2;
|
||||
|
||||
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
|
||||
if (moo_inttoooi(moo, arg, &precision) <= -1) goto invalid_format;
|
||||
if (precision < 0)
|
||||
{
|
||||
/* if precision is less than 0,
|
||||
* treat it as if no .precision is specified */
|
||||
flagc &= ~FLAGC_DOT;
|
||||
precision = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flagc & (FLAGC_STAR1 | FLAGC_WIDTH)) goto invalid_format;
|
||||
flagc |= FLAGC_STAR1;
|
||||
|
||||
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
|
||||
if (moo_inttoooi(moo, arg, &width) <= -1) goto invalid_format;
|
||||
if (width < 0)
|
||||
{
|
||||
flagc |= FLAGC_LEFTADJ;
|
||||
width = -width;
|
||||
}
|
||||
}
|
||||
goto reswitch;
|
||||
|
||||
case '0': /* zero pad */
|
||||
if (flagc & FLAGC_LENMOD) goto invalid_format;
|
||||
if (!(flagc & (FLAGC_DOT | FLAGC_LEFTADJ)))
|
||||
{
|
||||
padc = '0';
|
||||
flagc |= FLAGC_ZEROPAD;
|
||||
goto reswitch;
|
||||
}
|
||||
/* end of flags characters */
|
||||
|
||||
case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
if (flagc & FLAGC_LENMOD) goto invalid_format;
|
||||
for (n = 0;; ++fmt)
|
||||
{
|
||||
n = n * 10 + ch - '0';
|
||||
ch = *fmt;
|
||||
if (ch < '0' || ch > '9') break;
|
||||
}
|
||||
if (flagc & FLAGC_DOT)
|
||||
{
|
||||
if (flagc & FLAGC_STAR2) goto invalid_format;
|
||||
precision = n;
|
||||
flagc |= FLAGC_PRECISION;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flagc & FLAGC_STAR1) goto invalid_format;
|
||||
width = n;
|
||||
flagc |= FLAGC_WIDTH;
|
||||
}
|
||||
goto reswitch;
|
||||
|
||||
/* integer conversions */
|
||||
case 'd':
|
||||
case 'i': /* signed conversion */
|
||||
radix = 10;
|
||||
sign = 1;
|
||||
goto print_integer;
|
||||
case 'o':
|
||||
radix = 8;
|
||||
goto print_integer;
|
||||
case 'u':
|
||||
radix = 10;
|
||||
goto print_integer;
|
||||
case 'x':
|
||||
radix_flags |= MOO_INTTOSTR_LOWERCASE;
|
||||
case 'X':
|
||||
radix = 16;
|
||||
goto print_integer;
|
||||
case 'b':
|
||||
radix = 2;
|
||||
goto print_integer;
|
||||
/* end of integer conversions */
|
||||
|
||||
case 'f':
|
||||
{
|
||||
const moo_ooch_t* nsptr;
|
||||
moo_oow_t nslen;
|
||||
moo_oow_t scale = 0;
|
||||
|
||||
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
|
||||
if (MOO_OOP_IS_CHAR(arg))
|
||||
{
|
||||
arg = MOO_SMOOI_TO_OOP(MOO_OOP_TO_CHAR(arg));
|
||||
}
|
||||
else if (MOO_OOP_IS_FPDEC(moo, arg))
|
||||
{
|
||||
moo_oop_fpdec_t fa = (moo_oop_fpdec_t)arg;
|
||||
scale = MOO_OOP_TO_SMOOI(fa->scale);
|
||||
arg = fa->value;
|
||||
}
|
||||
|
||||
if (!moo_inttostr(moo, arg, 10 | MOO_INTTOSTR_NONEWOBJ))
|
||||
{
|
||||
MOO_LOG1 (moo, MOO_LOG_WARN | MOO_LOG_UNTYPED, "unable to convert %O to string \n", arg);
|
||||
goto invalid_format;
|
||||
}
|
||||
|
||||
nsptr = moo->inttostr.xbuf.ptr;
|
||||
nslen = moo->inttostr.xbuf.len;
|
||||
MOO_ASSERT (moo, nslen > 0);
|
||||
|
||||
if (nsptr[0] == '-')
|
||||
{
|
||||
MOO_ASSERT (moo, (MOO_OOP_IS_SMOOI(arg) && MOO_OOP_TO_SMOOI(arg) < 0) || MOO_OOP_IS_NBIGINT(moo,arg));
|
||||
nsptr++;
|
||||
nslen--;
|
||||
neg = 1;
|
||||
}
|
||||
|
||||
if (!(flagc & FLAGC_DOT))
|
||||
{
|
||||
precision = scale;
|
||||
if (precision <= 0) precision = 1;
|
||||
}
|
||||
|
||||
if ((flagc & FLAGC_DOT) && precision < scale)
|
||||
{
|
||||
moo_oow_t diff = scale - precision;
|
||||
scale = precision;
|
||||
nslen = (nslen < diff)? 0: (nslen - diff);
|
||||
}
|
||||
|
||||
if (nslen < scale + 1)
|
||||
{
|
||||
extra = 1;
|
||||
if (precision > 0) extra += 1 + scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
extra = 0;
|
||||
if (nslen > 0) extra += nslen - scale;
|
||||
if (precision > 0)
|
||||
{
|
||||
extra += 1;
|
||||
if (nslen > 0) extra += scale;
|
||||
}
|
||||
}
|
||||
|
||||
if (neg) extra++;
|
||||
else if (flagc & FLAGC_SIGN) extra++;
|
||||
else if (flagc & FLAGC_SPACE) extra++;
|
||||
|
||||
if ((flagc & FLAGC_DOT) && precision > scale)
|
||||
{
|
||||
/* trailing zeros in the fractional part */
|
||||
extra += precision - scale;
|
||||
}
|
||||
|
||||
if (!(flagc & FLAGC_LEFTADJ) && !(flagc & FLAGC_ZEROPAD) && width > extra)
|
||||
{
|
||||
width -= extra;
|
||||
PRINT_OOCH (padc, width);
|
||||
width = 0;
|
||||
}
|
||||
if (neg) PRINT_OOCH ('-', 1);
|
||||
else if (flagc & FLAGC_SIGN) PRINT_OOCH ('+', 1);
|
||||
else if (flagc & FLAGC_SPACE) PRINT_OOCH (' ', 1);
|
||||
|
||||
if (!(flagc & FLAGC_LEFTADJ) && width > extra)
|
||||
{
|
||||
width -= extra;
|
||||
PRINT_OOCH (padc, width);
|
||||
}
|
||||
|
||||
if (nslen < scale + 1)
|
||||
{
|
||||
PRINT_OOCH ('0', 1);
|
||||
if (precision > 0)
|
||||
{
|
||||
PRINT_OOCH ('.', 1);
|
||||
PRINT_OOCH ('0', scale - nslen);
|
||||
PRINT_OOCS (nsptr, nslen);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nslen > 0) PRINT_OOCS (nsptr, nslen - scale);
|
||||
if (precision > 0)
|
||||
{
|
||||
PRINT_OOCH ('.', 1);
|
||||
if (nslen > 0) PRINT_OOCS (&nsptr[nslen - scale], scale);
|
||||
}
|
||||
}
|
||||
if (precision > scale)
|
||||
{
|
||||
/* trailing zeros in the fractional part */
|
||||
PRINT_OOCH ('0', precision - scale);
|
||||
}
|
||||
|
||||
if ((flagc & FLAGC_LEFTADJ) && width > extra)
|
||||
{
|
||||
width -= extra;
|
||||
PRINT_OOCH (padc, width);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'c':
|
||||
case 'C':
|
||||
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
|
||||
if (MOO_OOP_IS_SMOOI(arg)) arg = MOO_CHAR_TO_OOP(MOO_OOP_TO_SMOOI(arg));
|
||||
if (!MOO_OOP_IS_CHAR(arg)) goto invalid_format;
|
||||
ooch = MOO_OOP_TO_CHAR(arg);
|
||||
|
||||
print_char:
|
||||
/* zeropad must not take effect for 'c' */
|
||||
if (flagc & FLAGC_ZEROPAD) padc = ' ';
|
||||
|
||||
/* precision 0 doesn't kill the letter */
|
||||
width--;
|
||||
if (!(flagc & FLAGC_LEFTADJ) && width > 0) PRINT_OOCH (padc, width);
|
||||
PRINT_OOCH (ooch, 1);
|
||||
if ((flagc & FLAGC_LEFTADJ) && width > 0) PRINT_OOCH (padc, width);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
case 'S':
|
||||
{
|
||||
const moo_ooch_t* oosp;
|
||||
moo_oow_t oosl;
|
||||
|
||||
/* zeropad must not take effect for 'S' */
|
||||
if (flagc & FLAGC_ZEROPAD) padc = ' ';
|
||||
|
||||
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
|
||||
if (!MOO_OOP_IS_POINTER(arg) || MOO_OBJ_GET_FLAGS_TYPE(arg) != MOO_OBJ_TYPE_CHAR) goto invalid_format;
|
||||
|
||||
oosp = MOO_OBJ_GET_CHAR_SLOT(arg);
|
||||
oosl = MOO_OBJ_GET_SIZE(arg);
|
||||
|
||||
if (flagc & FLAGC_DOT)
|
||||
{
|
||||
if (oosl > precision) oosl = precision;
|
||||
}
|
||||
width -= oosl;
|
||||
|
||||
if (!(flagc & FLAGC_LEFTADJ) && width > 0) PRINT_OOCH (padc, width);
|
||||
PRINT_OOCS (oosp, oosl);
|
||||
if ((flagc & FLAGC_LEFTADJ) && width > 0) PRINT_OOCH (padc, width);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'O': /* object - ignore precision, width, adjustment */
|
||||
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
|
||||
/*if (print_object(moo, (data->mask & ~MOO_LOG_PREFER_JSON), arg, outbfmt) <= -1) goto oops;*/
|
||||
if (print_object(moo, data->mask, arg, outbfmt) <= -1) goto oops;
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case 'J':
|
||||
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
|
||||
if (print_object(moo, (data->mask | MOO_LOG_PREFER_JSON), arg, outbfmt) <= -1) goto oops;
|
||||
break;
|
||||
#endif
|
||||
|
||||
print_integer:
|
||||
{
|
||||
const moo_ooch_t* nsptr;
|
||||
moo_oow_t nslen;
|
||||
|
||||
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
|
||||
if (MOO_OOP_IS_CHAR(arg))
|
||||
{
|
||||
arg = MOO_SMOOI_TO_OOP(MOO_OOP_TO_CHAR(arg));
|
||||
}
|
||||
else if (MOO_OOP_IS_FPDEC(moo, arg))
|
||||
{
|
||||
moo_oop_t nv;
|
||||
moo_oop_fpdec_t fa = (moo_oop_fpdec_t)arg;
|
||||
|
||||
/* the given number for integer output is a fixed-point decimal.
|
||||
* i will drop all digits after the fixed point */
|
||||
moo_pushtmp (moo, &arg);
|
||||
nv = moo_truncfpdecval(moo, fa->value, MOO_OOP_TO_SMOOI(fa->scale), 0);
|
||||
moo_poptmp (moo);
|
||||
if (!nv)
|
||||
{
|
||||
MOO_LOG1 (moo, MOO_LOG_WARN | MOO_LOG_UNTYPED, "unable to truncate a fixed-point number %O to an integer for output\n", arg);
|
||||
goto invalid_format;
|
||||
}
|
||||
|
||||
arg = nv;
|
||||
}
|
||||
|
||||
if (!moo_inttostr(moo, arg, radix | radix_flags))
|
||||
{
|
||||
/*moo_seterrbfmt (moo, MOO_EINVAL, "not a valid number - %O", arg);
|
||||
goto oops;*/
|
||||
MOO_LOG1 (moo, MOO_LOG_WARN | MOO_LOG_UNTYPED, "unable to convert integer %O to string \n", arg);
|
||||
goto invalid_format;
|
||||
}
|
||||
|
||||
nsptr = moo->inttostr.xbuf.ptr;
|
||||
nslen = moo->inttostr.xbuf.len;
|
||||
|
||||
MOO_ASSERT (moo, nslen > 0);
|
||||
if (nsptr[0] == '-')
|
||||
{
|
||||
/* a negative number was given. i must skip the minus sign
|
||||
* added by moo_inttostr() for a negative number. */
|
||||
MOO_ASSERT (moo, (MOO_OOP_IS_SMOOI(arg) && MOO_OOP_TO_SMOOI(arg) < 0) || MOO_OOP_IS_NBIGINT(moo,arg));
|
||||
nsptr++;
|
||||
nslen--;
|
||||
}
|
||||
|
||||
extra = nslen;
|
||||
if (sign && ((MOO_OOP_IS_SMOOI(arg) && MOO_OOP_TO_SMOOI(arg) < 0) || MOO_OOP_IS_NBIGINT(moo,arg))) neg = 1;
|
||||
|
||||
if ((flagc & FLAGC_SHARP) && arg != MOO_SMOOI_TO_OOP(0))
|
||||
{
|
||||
if (radix == 2 || radix == 8 || radix == 16) extra += 2;
|
||||
}
|
||||
if (neg) extra++;
|
||||
else if (flagc & FLAGC_SIGN) extra++;
|
||||
else if (flagc & FLAGC_SPACE) extra++;
|
||||
|
||||
if ((flagc & FLAGC_DOT) && precision > nslen)
|
||||
{
|
||||
/* extra zeros for precision specified */
|
||||
extra += (precision - nslen);
|
||||
}
|
||||
|
||||
if (!(flagc & FLAGC_LEFTADJ) && !(flagc & FLAGC_ZEROPAD) && width > 0 && (width -= extra) > 0)
|
||||
{
|
||||
PRINT_OOCH (padc, width);
|
||||
width = 0;
|
||||
}
|
||||
|
||||
if (neg) PRINT_OOCH ('-', 1);
|
||||
else if (flagc & FLAGC_SIGN) PRINT_OOCH ('+', 1);
|
||||
else if (flagc & FLAGC_SPACE) PRINT_OOCH (' ', 1);
|
||||
|
||||
if ((flagc & FLAGC_SHARP) && arg != MOO_SMOOI_TO_OOP(0))
|
||||
{
|
||||
if (radix == 2)
|
||||
{
|
||||
PRINT_OOCH ('2', 1);
|
||||
PRINT_OOCH ('r', 1);
|
||||
}
|
||||
if (radix == 8)
|
||||
{
|
||||
PRINT_OOCH ('8', 1);
|
||||
PRINT_OOCH ('r', 1);
|
||||
}
|
||||
else if (radix == 16)
|
||||
{
|
||||
PRINT_OOCH ('1', 1);
|
||||
PRINT_OOCH ('6', 1);
|
||||
PRINT_OOCH ('r', 1);
|
||||
}
|
||||
}
|
||||
|
||||
if ((flagc & FLAGC_DOT) && precision > nslen)
|
||||
{
|
||||
/* extra zeros for precision specified */
|
||||
PRINT_OOCH ('0', precision - nslen);
|
||||
}
|
||||
|
||||
if (!(flagc & FLAGC_LEFTADJ) && width > 0 && (width -= extra) > 0)
|
||||
{
|
||||
PRINT_OOCH (padc, width);
|
||||
}
|
||||
|
||||
PRINT_OOCS (nsptr, nslen);
|
||||
|
||||
if ((flagc & FLAGC_LEFTADJ) && width > 0 && (width -= extra) > 0)
|
||||
{
|
||||
PRINT_OOCH (padc, width);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
invalid_format:
|
||||
PRINT_OOCS (percent, fmt - percent);
|
||||
break;
|
||||
|
||||
default:
|
||||
PRINT_OOCS (percent, fmt - percent);
|
||||
/*
|
||||
* Since we ignore an formatting argument it is no
|
||||
* longer safe to obey the remaining formatting
|
||||
* arguments as the arguments will no longer match
|
||||
* the format specs.
|
||||
*/
|
||||
arg_state.stop = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* --------------------------------------------------------------------------
|
||||
* SUPPORT FOR THE BUILTIN PRINTF PRIMITIVE FUNCTION
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
int moo_printfmtst (moo_t* moo, moo_ooi_t nargs)
|
||||
{
|
||||
moo_fmtout_t fo;
|
||||
MOO_MEMSET (&fo, 0, MOO_SIZEOF(fo));
|
||||
fo.putch = put_prch;
|
||||
fo.putcs = put_prcs;
|
||||
return print_formatted(moo, nargs, &fo, moo_proutbfmt, 0);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* SUPPORT FOR THE BUILTIN LOGF PRIMITIVE FUNCTION
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
int moo_logfmtst (moo_t* moo, moo_ooi_t nargs)
|
||||
{
|
||||
moo_fmtout_t fo;
|
||||
|
||||
MOO_MEMSET (&fo, 0, MOO_SIZEOF(fo));
|
||||
fo.mask = MOO_LOG_FATAL | MOO_LOG_APP;
|
||||
|
||||
if (moo->log.default_type_mask & MOO_LOG_ALL_TYPES)
|
||||
{
|
||||
/* if a type is given, it's not untyped any more.
|
||||
* mask off the UNTYPED bit */
|
||||
fo.mask &= ~MOO_LOG_UNTYPED;
|
||||
|
||||
/* if the default_type_mask has the UNTYPED bit on,
|
||||
* it'll get turned back on */
|
||||
fo.mask |= (moo->log.default_type_mask & MOO_LOG_ALL_TYPES);
|
||||
}
|
||||
|
||||
fo.putch = put_logch;
|
||||
fo.putcs = put_logcs;
|
||||
return print_formatted(moo, nargs, &fo, moo_logbfmt, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* SUPPORT FOR THE BUILTIN SPRINTF PRIMITIVE FUNCTION
|
||||
* -------------------------------------------------------------------------- */
|
||||
static int put_sprcs (moo_t* moo, moo_bitmask_t mask, const moo_ooch_t* ptr, moo_oow_t len)
|
||||
{
|
||||
if (len > moo->sprintf.xbuf.capa - moo->sprintf.xbuf.len)
|
||||
{
|
||||
moo_ooch_t* tmp;
|
||||
moo_oow_t newcapa;
|
||||
|
||||
newcapa = moo->sprintf.xbuf.len + len + 1;
|
||||
newcapa = MOO_ALIGN_POW2(newcapa, 256);
|
||||
|
||||
tmp = (moo_ooch_t*)moo_reallocmem(moo, moo->sprintf.xbuf.ptr, newcapa * MOO_SIZEOF(*tmp));
|
||||
if (!tmp) return -1;
|
||||
|
||||
moo->sprintf.xbuf.ptr = tmp;
|
||||
moo->sprintf.xbuf.capa = newcapa;
|
||||
}
|
||||
|
||||
MOO_MEMCPY (&moo->sprintf.xbuf.ptr[moo->sprintf.xbuf.len], ptr, len * MOO_SIZEOF(*ptr));
|
||||
moo->sprintf.xbuf.len += len;
|
||||
return 1; /* success */
|
||||
}
|
||||
|
||||
static int put_sprch (moo_t* moo, moo_bitmask_t mask, moo_ooch_t ch, moo_oow_t len)
|
||||
{
|
||||
if (len > moo->sprintf.xbuf.capa - moo->sprintf.xbuf.len)
|
||||
{
|
||||
moo_ooch_t* tmp;
|
||||
moo_oow_t newcapa;
|
||||
|
||||
newcapa = moo->sprintf.xbuf.len + len + 1;
|
||||
newcapa = MOO_ALIGN_POW2(newcapa, 256);
|
||||
|
||||
tmp = (moo_ooch_t*)moo_reallocmem(moo, moo->sprintf.xbuf.ptr, newcapa * MOO_SIZEOF(*tmp));
|
||||
if (!tmp) return -1;
|
||||
|
||||
moo->sprintf.xbuf.ptr = tmp;
|
||||
moo->sprintf.xbuf.capa = newcapa;
|
||||
}
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
--len;
|
||||
moo->sprintf.xbuf.ptr[moo->sprintf.xbuf.len++] = ch;
|
||||
}
|
||||
|
||||
return 1; /* success */
|
||||
}
|
||||
|
||||
static moo_ooi_t __sprbfmtv (moo_t* moo, moo_bitmask_t mask, const moo_bch_t* fmt, ...);
|
||||
|
||||
static int _sprbfmtv (moo_t* moo, const moo_bch_t* fmt, moo_fmtout_t* data, va_list ap)
|
||||
{
|
||||
return __logbfmtv (moo, fmt, data, ap, __sprbfmtv);
|
||||
}
|
||||
|
||||
/*
|
||||
static int _sprufmtv (moo_t* moo, const moo_uch_t* fmt, moo_fmtout_t* data, va_list ap)
|
||||
{
|
||||
return __logufmtv (moo, fmt, data, ap, __sprbfmtv);
|
||||
}*/
|
||||
|
||||
static moo_ooi_t __sprbfmtv (moo_t* moo, moo_bitmask_t mask, const moo_bch_t* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
moo_fmtout_t fo;
|
||||
|
||||
fo.mask = mask; /* not used */
|
||||
fo.putch = put_sprch;
|
||||
fo.putcs = put_sprcs;
|
||||
|
||||
va_start (ap, fmt);
|
||||
_sprbfmtv (moo, fmt, &fo, ap);
|
||||
va_end (ap);
|
||||
|
||||
return fo.count;
|
||||
}
|
||||
|
||||
moo_ooi_t moo_sproutbfmt (moo_t* moo, moo_bitmask_t mask, const moo_bch_t* fmt, ...)
|
||||
{
|
||||
int x;
|
||||
va_list ap;
|
||||
moo_fmtout_t fo;
|
||||
|
||||
fo.mask = mask;
|
||||
fo.putch = put_sprch;
|
||||
fo.putcs = put_sprcs;
|
||||
|
||||
va_start (ap, fmt);
|
||||
x = _sprbfmtv(moo, fmt, &fo, ap);
|
||||
va_end (ap);
|
||||
|
||||
return (x <= -1)? -1: fo.count;
|
||||
}
|
||||
|
||||
/*
|
||||
moo_ooi_t moo_sproutufmt (moo_t* moo, moo_bitmask_t mask, const moo_uch_t* fmt, ...)
|
||||
{
|
||||
int x;
|
||||
va_list ap;
|
||||
moo_fmtout_t fo;
|
||||
|
||||
fo.mask = mask;
|
||||
fo.putch = put_sprch;
|
||||
fo.putcs = put_sprcs;
|
||||
|
||||
va_start (ap, fmt);
|
||||
x = _sprufmtv (moo, fmt, &fo, ap);
|
||||
va_end (ap);
|
||||
|
||||
return (x <= -1)? -1: fo.count;
|
||||
}*/
|
||||
|
||||
|
||||
int moo_sprintfmtst (moo_t* moo, moo_ooi_t nargs)
|
||||
{
|
||||
/* format a string using the receiver and arguments on the stack */
|
||||
moo_fmtout_t fo;
|
||||
MOO_MEMSET (&fo, 0, MOO_SIZEOF(fo));
|
||||
fo.putch = put_sprch;
|
||||
fo.putcs = put_sprcs;
|
||||
moo->sprintf.xbuf.len = 0;
|
||||
return print_formatted(moo, nargs, &fo, moo_sproutbfmt, 0);
|
||||
}
|
||||
|
@ -257,6 +257,24 @@
|
||||
#endif
|
||||
|
||||
|
||||
#define MOO_OOP_IS_PBIGINT(moo,x) (MOO_CLASSOF(moo,x) == (moo)->_large_positive_integer)
|
||||
#define MOO_OOP_IS_NBIGINT(moo,x) (MOO_CLASSOF(moo,x) == (moo)->_large_negative_integer)
|
||||
#define MOO_OOP_IS_BIGINT(moo,x) (MOO_OOP_IS_PBIGINT(moo,x) || MOO_OOP_IS_NBIGINT(moo,x))
|
||||
|
||||
#define MOO_POINTER_IS_PBIGINT(moo,x) (MOO_OBJ_GET_CLASS(x) == (moo)->_large_positive_integer)
|
||||
#define MOO_POINTER_IS_NBIGINT(moo,x) (MOO_OBJ_GET_CLASS(x) == (moo)->_large_negative_integer)
|
||||
#define MOO_POINTER_IS_BIGINT(moo,x) (MOO_OOP_IS_PBIGINT(moo,x) || MOO_OOP_IS_NBIGINT(moo,x))
|
||||
|
||||
#define MOO_OOP_IS_FPDEC(moo,x) (MOO_CLASSOF(moo,x) == (moo)->_fixed_point_decimal)
|
||||
#define MOO_POINTER_IS_FPDEC(moo,x) (MOO_OBJ_GET_CLASS(x) == (moo)->_fixed_point_Decimal)
|
||||
|
||||
typedef moo_ooi_t (*moo_outbfmt_t) (
|
||||
moo_t* moo,
|
||||
moo_bitmask_t mask,
|
||||
const moo_bch_t* fmt,
|
||||
...
|
||||
);
|
||||
|
||||
#if defined(MOO_INCLUDE_COMPILER)
|
||||
|
||||
/* ========================================================================= */
|
||||
@ -981,7 +999,6 @@ enum moo_bcode_t
|
||||
BCODE_NOOP = 0xFF
|
||||
};
|
||||
|
||||
|
||||
/* i don't want an error raised inside the callback to override
|
||||
* the existing error number and message. */
|
||||
#define vmprim_log_write(moo,mask,ptr,len) do { \
|
||||
@ -1216,13 +1233,6 @@ int moo_regfinalizable (moo_t* moo, moo_oop_t oop);
|
||||
int moo_deregfinalizable (moo_t* moo, moo_oop_t oop);
|
||||
void moo_deregallfinalizables (moo_t* moo);
|
||||
|
||||
/* ========================================================================= */
|
||||
/* proc.c */
|
||||
/* ========================================================================= */
|
||||
moo_oop_process_t moo_makeproc (
|
||||
moo_t* moo
|
||||
);
|
||||
|
||||
/* ========================================================================= */
|
||||
/* bigint.c */
|
||||
/* ========================================================================= */
|
||||
@ -1350,10 +1360,29 @@ moo_oop_t moo_strtoint (
|
||||
int radix
|
||||
);
|
||||
|
||||
#define MOO_INTTOSTR_LOWERCASE (1 << 14)
|
||||
#define MOO_INTTOSTR_NONEWOBJ (1 << 15)
|
||||
|
||||
moo_oop_t moo_inttostr (
|
||||
moo_t* moo,
|
||||
moo_oop_t num,
|
||||
int radix
|
||||
int flagged_radix /* radix between 2 and 36 inclusive, optionally bitwise ORed of MOO_INTTOSTR_XXX bits */
|
||||
);
|
||||
|
||||
/* ========================================================================= */
|
||||
/* number.c */
|
||||
/* ========================================================================= */
|
||||
moo_oop_t moo_makefpdec (
|
||||
moo_t* moo,
|
||||
moo_oop_t value,
|
||||
moo_ooi_t scale
|
||||
);
|
||||
|
||||
moo_oop_t moo_truncfpdecval (
|
||||
moo_t* moo,
|
||||
moo_oop_t iv,
|
||||
moo_ooi_t cs,
|
||||
moo_ooi_t ns
|
||||
);
|
||||
|
||||
/* ========================================================================= */
|
||||
|
@ -282,6 +282,14 @@ void moo_fini (moo_t* moo)
|
||||
moo->inttostr.t.capa = 0;
|
||||
}
|
||||
|
||||
if (moo->sprintf.xbuf.ptr)
|
||||
{
|
||||
moo_freemem (moo, moo->sprintf.xbuf.ptr);
|
||||
moo->sprintf.xbuf.ptr = MOO_NULL;
|
||||
moo->sprintf.xbuf.capa = 0;
|
||||
moo->sprintf.xbuf.len = 0;
|
||||
}
|
||||
|
||||
if (moo->vmprim.dl_cleanup) moo->vmprim.dl_cleanup (moo);
|
||||
}
|
||||
|
||||
|
@ -435,6 +435,7 @@ typedef enum moo_gcfin_t moo_gcfin_t;
|
||||
#define MOO_OBJ_IS_HALFWORD_POINTER(oop) (MOO_OOP_IS_POINTER(oop) && (MOO_OBJ_GET_FLAGS_TYPE(oop) == MOO_OBJ_TYPE_HALFWORD))
|
||||
#define MOO_OBJ_IS_WORD_POINTER(oop) (MOO_OOP_IS_POINTER(oop) && (MOO_OBJ_GET_FLAGS_TYPE(oop) == MOO_OBJ_TYPE_WORD))
|
||||
|
||||
|
||||
/* [NOTE] this macro doesn't check the range of the actual value.
|
||||
* make sure that the value of each bit fields given falls within the
|
||||
* possible range of the defined bits */
|
||||
@ -1632,6 +1633,16 @@ struct moo_t
|
||||
} inttostr;
|
||||
/* == END BIGINT CONVERSION == */
|
||||
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
moo_ooch_t* ptr;
|
||||
moo_oow_t capa;
|
||||
moo_oow_t len;
|
||||
} xbuf; /* buffer to support sprintf */
|
||||
} sprintf;
|
||||
|
||||
moo_sbuf_t sbuf[64];
|
||||
|
||||
struct
|
||||
|
@ -32,6 +32,15 @@ moo_oop_t moo_makefpdec (moo_t* moo, moo_oop_t value, moo_ooi_t scale)
|
||||
{
|
||||
moo_oop_fpdec_t fpdec;
|
||||
|
||||
MOO_ASSERT (moo, moo_isint(moo, value));
|
||||
if (scale <= 0) return value; /* if scale is 0 or less, return the value as it it */
|
||||
|
||||
if (scale > MOO_SMOOI_MAX)
|
||||
{
|
||||
moo_seterrbfmt (moo, MOO_EINVAL, "fpdec scale too large - %zd", scale);
|
||||
return MOO_NULL;
|
||||
}
|
||||
|
||||
moo_pushtmp (moo, &value);
|
||||
fpdec = (moo_oop_fpdec_t)moo_instantiate(moo, moo->_fixed_point_decimal, MOO_NULL, 0);
|
||||
moo_poptmp (moo);
|
||||
|
@ -94,7 +94,7 @@ static moo_oop_t find_or_make_symbol (moo_t* moo, const moo_ooch_t* ptr, moo_oow
|
||||
index = moo_hashoochars(ptr, len) % MOO_OBJ_GET_SIZE(moo->symtab->bucket);
|
||||
|
||||
/* find a matching symbol in the open-addressed symbol table */
|
||||
while ((moo_oop_t)(symbol = MOO_OBJ_GET_OOP_VAL(moo->symtab->bucket, index)) != moo->_nil)
|
||||
while ((moo_oop_t)(symbol = (moo_oop_char_t)MOO_OBJ_GET_OOP_VAL(moo->symtab->bucket, index)) != moo->_nil)
|
||||
{
|
||||
MOO_ASSERT (moo, MOO_CLASSOF(moo,symbol) == moo->_symbol);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user