From f618154aafc28b4a43f314f803d7d36639e78df4 Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Fri, 20 Nov 2015 09:05:55 +0000 Subject: [PATCH] changed STIX_SMOOI_MIN to -STIX_SMOOI_MAX instead of (-STIX_SMOOI_MAX - 1) fixed tally range check bugs in dic.c/sym.c/gc.c simplificed some code resulting from STIX_SMOOI_MIN change. --- stix/kernel/Stix.st | 9 +-- stix/kernel/test-005.st | 1 + stix/lib/bigint.c | 133 ++++++++++++++++++++++++++++++++++++---- stix/lib/comp.c | 100 +++++------------------------- stix/lib/dic.c | 28 +++++++-- stix/lib/exec.c | 4 +- stix/lib/gc.c | 16 +++-- stix/lib/stix.h | 9 ++- stix/lib/sym.c | 19 +++++- 9 files changed, 204 insertions(+), 115 deletions(-) diff --git a/stix/kernel/Stix.st b/stix/kernel/Stix.st index ce6272e..21c1120 100644 --- a/stix/kernel/Stix.st +++ b/stix/kernel/Stix.st @@ -115,18 +115,15 @@ { } -#class(#halfword) LargeInteger(Number) -## #class(#word) LargeInteger(Number) +#class(#liword) LargeInteger(Number) { } -#class(#halfword) LargePositiveInteger(LargeInteger) -## #class(#word) LargePositiveInteger(LargeInteger) +#class(#liword) LargePositiveInteger(LargeInteger) { } -#class(#halfword) LargeNegativeInteger(LargeInteger) -## #class(#word) LargeNegativeInteger(LargeInteger) +#class(#liword) LargeNegativeInteger(LargeInteger) { } diff --git a/stix/kernel/test-005.st b/stix/kernel/test-005.st index 04dd32a..344c296 100644 --- a/stix/kernel/test-005.st +++ b/stix/kernel/test-005.st @@ -266,6 +266,7 @@ PROCESS TESTING ##(-16rFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF * 1) dump. ##((-2305843009213693952 * -1) - 1 + 2) dump. ((-2305843009213693952 * -2305843009213693952 * 2305843009213693952 * 2305843009213693952 * 2305843009213693952) - 1 + 2) dump. + (2r111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 * 128971234897128931) dump. diff --git a/stix/lib/bigint.c b/stix/lib/bigint.c index 515fe1a..365036a 100644 --- a/stix/lib/bigint.c +++ b/stix/lib/bigint.c @@ -304,7 +304,7 @@ static stix_oop_t normalize_bigint (stix_t* stix, stix_oop_t oop) count = count_effective_digits (oop); #if defined(STIX_USE_FULL_WORD) - if (count == 1) + if (count == 1) /* 1 word */ { stix_oow_t w; @@ -315,13 +315,13 @@ static stix_oop_t normalize_bigint (stix_t* stix, stix_oop_t oop) } else { + STIX_ASSERT (-STIX_SMOOI_MAX == STIX_SMOOI_MIN); STIX_ASSERT (STIX_OBJ_GET_CLASS(oop) == stix->_large_negative_integer); - /*if (w <= -STIX_SMOOI_MIN) */ - if (w <= ((stix_oow_t)STIX_SMOOI_MAX + 1)) return STIX_SMOOI_TO_OOP(-(stix_ooi_t)w); + if (w <= STIX_SMOOI_MAX) return STIX_SMOOI_TO_OOP(-(stix_ooi_t)w); } } #else - if (count == 1) + if (count == 1) /* 1 half-word */ { if (STIX_OBJ_GET_CLASS(oop) == stix->_large_positive_integer) { @@ -330,10 +330,10 @@ static stix_oop_t normalize_bigint (stix_t* stix, stix_oop_t oop) else { STIX_ASSERT (STIX_OBJ_GET_CLASS(oop) == stix->_large_negative_integer); - return STIX_SMOOI_TO_OOP(-(stix_oow_t)((stix_oop_liword_t)oop)->slot[0]); + return STIX_SMOOI_TO_OOP(-(stix_ooi_t)((stix_oop_liword_t)oop)->slot[0]); } } - else if (count == 2) + else if (count == 2) /* 2 half-words */ { stix_oow_t w; @@ -344,9 +344,9 @@ static stix_oop_t normalize_bigint (stix_t* stix, stix_oop_t oop) } else { + STIX_ASSERT (-STIX_SMOOI_MAX == STIX_SMOOI_MIN); STIX_ASSERT (STIX_OBJ_GET_CLASS(oop) == stix->_large_negative_integer); - /*if (w <= -STIX_SMOOI_MIN) */ - if (w <= ((stix_oow_t)STIX_SMOOI_MAX + 1)) return STIX_SMOOI_TO_OOP(-(stix_ooi_t)w); + if (w <= STIX_SMOOI_MAX) return STIX_SMOOI_TO_OOP(-(stix_ooi_t)w); } } #endif @@ -632,6 +632,40 @@ static STIX_INLINE void rshift_unsigned_array (stix_liw_t* x, stix_oow_t xs, sti STIX_MEMSET (&x[xs - word_shifts], 0, word_shifts * STIX_SIZEOF(stix_liw_t)); } +static void divide_unsigned_array ( + const stix_liw_t* x, stix_oow_t xs, + const stix_liw_t* y, stix_oow_t ys, + stix_liw_t* q, stix_liw_t* r) +{ + /* TODO: this function needs to be rewritten for performance improvement. */ + + /* Perform binary long division. + * http://en.wikipedia.org/wiki/Division_algorithm + * --------------------------------------------------------------------- + * Q := 0 initialize quotient and remainder to zero + * R := 0 + * for i = n-1...0 do where n is number of bits in N + * R := R << 1 left-shift R by 1 bit + * R(0) := X(i) set the least-significant bit of R equal to bit i of the numerator + * if R >= Y then + * R = R - Y + * Q(i) := 1 + * end + * end + */ + + stix_liw_t* d; + stix_oow_t ds; + +/* TODO: */ + while (!is_less_unsigned_array (d, ds, y, ys)) /* while (y <= d) */ + { + + } + + STIX_MEMCPY (r, d, ds); +} + static stix_oop_t add_unsigned_integers (stix_t* stix, stix_oop_t x, stix_oop_t y) { stix_liw_t* a, * b; @@ -981,6 +1015,7 @@ printf ("%0*lX ", (int)(STIX_SIZEOF(stix_liw_t) * 2), (unsigned long)((stix_oop_ printf ("\n"); } +/* lshift_unsigned_array (((stix_oop_liword_t)z)->slot, STIX_OBJ_GET_SIZE(z), 16 * 5 + 4); { int i; printf ("LSHIFT10=>"); @@ -989,7 +1024,7 @@ for (i = STIX_OBJ_GET_SIZE(z); i > 0;) printf ("%0*lX ", (int)(STIX_SIZEOF(stix_liw_t) * 2), (unsigned long)((stix_oop_liword_t)z)->slot[--i]); } printf ("\n"); -} +}*/ return normalize_bigint (stix, z); @@ -1001,6 +1036,80 @@ oops_einval: stix_oop_t stix_divints (stix_t* stix, stix_oop_t x, stix_oop_t y, stix_oop_t* rem) { + stix_oop_t t; + + if (STIX_OOP_IS_SMOOI(x) && STIX_OOP_IS_SMOOI(y)) + { + stix_ooi_t xv, yv, q, r; + + xv = STIX_OOP_TO_SMOOI(x); + yv = STIX_OOP_TO_SMOOI(y); + + if (yv == 0) + { + stix->errnum = STIX_EDIVBY0; + return STIX_NULL; + } + + q = xv / yv; + STIX_ASSERT (STIX_IN_SMOOI_RANGE(q)); + +#if 1 +/* TODO : verify this... */ + r = xv - yv * q; + STIX_ASSERT (STIX_IN_SMOOI_RANGE(r)); + + /* handle sign difference */ + if (r && ((yv ^ r) < 0)) + { + /* if the sign bit is different betwen yv and r, + * the sign bit of (yv ^ r) must be set */ + r += yv; + --q; + + STIX_ASSERT (STIX_IN_SMOOI_RANGE(r)); + } +#else + r = xv % yv; + STIX_ASSERT (STIX_IN_SMOOI_RANGE(r)); +#endif + + *rem = STIX_SMOOI_TO_OOP(r); + return STIX_SMOOI_TO_OOP((stix_ooi_t)q); + } + else if (STIX_OOP_IS_SMOOI(x)) + { + if (STIX_OOP_TO_SMOOI(x) == 0) + { + t = clone_bigint (stix, y, STIX_OBJ_GET_SIZE(y)); + if (!t) return STIX_NULL; + + *rem = t; + return STIX_SMOOI_TO_OOP(0); + } + } + else if (STIX_OOP_IS_SMOOI(y)) + { + stix_ooi_t yv; + + if (yv == 0) + { + stix->errnum = STIX_EDIVBY0; + return STIX_NULL; + } + else if (yv == 1) + { + t = clone_bigint (stix, x, STIX_OBJ_GET_SIZE(x)); + if (!t) return STIX_NULL; + + *rem = STIX_SMOOI_TO_OOP(0); + return t; + } + } + else + { + } + return STIX_NULL; } @@ -1229,7 +1338,8 @@ printf ("\n"); w = hwp[0]; if (neg) { - if (w <= STIX_SMOOI_MAX + 1) return STIX_SMOOI_TO_OOP(-(stix_ooi_t)w); + STIX_ASSERT (-STIX_SMOOI_MAX == STIX_SMOOI_MIN); + if (w <= STIX_SMOOI_MAX) return STIX_SMOOI_TO_OOP(-(stix_ooi_t)w); } else { @@ -1243,7 +1353,8 @@ printf ("\n"); w = MAKE_WORD(hwp[0], hwp[1]); if (neg) { - if (w <= STIX_SMOOI_MAX + 1) return STIX_SMOOI_TO_OOP(-(stix_ooi_t)w); + STIX_ASSERT (-STIX_SMOOI_MAX == STIX_SMOOI_MIN); + if (w <= STIX_SMOOI_MAX) return STIX_SMOOI_TO_OOP(-(stix_ooi_t)w); } else { diff --git a/stix/lib/comp.c b/stix/lib/comp.c index 1c2d7d5..61d5b48 100644 --- a/stix/lib/comp.c +++ b/stix/lib/comp.c @@ -421,7 +421,6 @@ static int string_to_smint (stix_t* stix, stix_oocs_t* str, int radixed, stix_oo * it assumes a certain pre-sanity check on the string * done by the lexical analyzer */ -/* TODO: handle floating point numbers, etc, handle radix */ int v, negsign, base; const stix_ooch_t* ptr, * end; stix_oow_t value, old_value; @@ -477,27 +476,16 @@ static int string_to_smint (stix_t* stix, stix_oocs_t* str, int radixed, stix_oo return -1; } - if (negsign) + STIX_ASSERT (-STIX_SMOOI_MAX == STIX_SMOOI_MIN); + if (value > STIX_SMOOI_MAX) { - /*if (value > -STIX_SMOOI_MIN) */ - if (value > ((stix_oow_t)STIX_SMOOI_MAX + 1)) - { - stix->errnum = STIX_ERANGE; - return -1; - } - *num = value; - *num *= -1; - } - else - { - if (value > STIX_SMOOI_MAX) - { - stix->errnum = STIX_ERANGE; - return -1; - } - *num = value; + stix->errnum = STIX_ERANGE; + return -1; } + *num = value; + if (negsign) *num *= -1; + return 0; } @@ -1860,7 +1848,7 @@ static int add_literal (stix_t* stix, stix_oop_t lit, stix_size_t* index) static STIX_INLINE int add_character_literal (stix_t* stix, stix_ooch_t ch, stix_size_t* index) { - return add_literal (stix, STIX_OOP_FROM_CHAR(ch), index); + return add_literal (stix, STIX_CHAR_TO_OOP(ch), index); } static int add_string_literal (stix_t* stix, const stix_oocs_t* str, stix_size_t* index) @@ -3181,8 +3169,9 @@ static int __read_byte_array_literal (stix_t* stix, stix_oop_t* xlit) * than the range error must not occur */ STIX_ASSERT (stix->errnum == STIX_ERANGE); -printf ("NOT IMPLEMENTED LARGE_INTEGER or ERROR?\n"); - stix->errnum = STIX_ENOIMPL; + /* if the token is out of the SMOOI range, it's too big or + * to small to be a byte */ + set_syntax_error (stix, STIX_SYNERR_BYTERANGE, &stix->c->tok.loc, &stix->c->tok.name); return -1; } else if (tmp < 0 || tmp > 255) @@ -3233,28 +3222,13 @@ static int __read_array_literal (stix_t* stix, stix_oop_t* xlit) case STIX_IOTOK_NUMLIT: case STIX_IOTOK_RADNUMLIT: - { - stix_ooi_t tmp; - - if (string_to_smint(stix, &stix->c->tok.name, stix->c->tok.type == STIX_IOTOK_RADNUMLIT, &tmp) <= -1) - { - /* the token reader reads a valid token. no other errors - * than the range error must not occur */ - STIX_ASSERT (stix->errnum == STIX_ERANGE); - -/* TODO: IMPLMENET LARGE INTEGER */ -printf ("LARGE NOT IMPLEMENTED IN COMPILE_ARRAY_LITERAL\n"); - stix->errnum = STIX_ENOIMPL; - return -1; - } - - lit = STIX_SMOOI_TO_OOP(tmp); + lit = string_to_num (stix, &stix->c->tok.name, stix->c->tok.type == STIX_IOTOK_RADNUMLIT); + if (!lit) return -1; break; - } case STIX_IOTOK_CHARLIT: STIX_ASSERT (stix->c->tok.name.len == 1); - lit = STIX_OOP_FROM_CHAR(stix->c->tok.name.ptr[0]); + lit = STIX_CHAR_TO_OOP(stix->c->tok.name.ptr[0]); break; case STIX_IOTOK_STRLIT: @@ -3540,28 +3514,8 @@ printf ("\tpush symbol literal %d\n", (int)index); case STIX_IOTOK_NUMLIT: case STIX_IOTOK_RADNUMLIT: { - /* TODO: other types of numbers, negative numbers, etc */ -#if 0 -/* TODO: proper numbeic literal handling */ - stix_ooi_t tmp; - - if (string_to_smint(stix, &stix->c->tok.name, stix->c->tok.type == STIX_IOTOK_RADNUMLIT, &tmp) <= -1) - { - /* the token reader reads a valid token. no other errors - * than the range error must not occur */ - STIX_ASSERT (stix->errnum == STIX_ERANGE); - -printf ("NOT IMPLEMENTED LARGE_INTEGER or ERROR?\n"); - stix->errnum = STIX_ENOIMPL; - return -1; - } - else - { -printf ("\tpush int literal\n"); - if (emit_push_smint_literal(stix, tmp) <= -1) return -1; - } -#else - +/* TODO: floating pointer number */ + /* TODO: other types of numbers, etc */ stix_oop_t tmp; tmp = string_to_num (stix, &stix->c->tok.name, stix->c->tok.type == STIX_IOTOK_RADNUMLIT); if (!tmp) return -1; @@ -3576,7 +3530,6 @@ printf ("\tpush int literal\n"); if (add_literal(stix, tmp, &index) <= -1 || emit_single_param_instruction(stix, BCODE_PUSH_LITERAL_0, index) <= -1) return -1; } -#endif GET_TOKEN (stix); break; @@ -4947,7 +4900,7 @@ printf ("\n"); case STIX_IOTOK_CHARLIT: STIX_ASSERT (stix->c->tok.name.len == 1); - lit = STIX_OOP_FROM_CHAR(stix->c->tok.name.ptr[0]); + lit = STIX_CHAR_TO_OOP(stix->c->tok.name.ptr[0]); goto add_literal; case STIX_IOTOK_STRLIT: @@ -4963,27 +4916,8 @@ printf ("\n"); case STIX_IOTOK_NUMLIT: case STIX_IOTOK_RADNUMLIT: { -#if 0 - stix_ooi_t tmp; - - if (string_to_smint(stix, &stix->c->tok.name, stix->c->tok.type == STIX_IOTOK_RADNUMLIT, &tmp) <= -1) - { - /* the token reader reads a valid token. no other errors - * than the range error must not occur */ - STIX_ASSERT (stix->errnum == STIX_ERANGE); - -printf ("NOT IMPLEMENTED LARGE_INTEGER or ERROR?\n"); - stix->errnum = STIX_ENOIMPL; - return -1; - } - else - { - lit = STIX_SMOOI_TO_OOP(tmp); - } -#else lit = string_to_num (stix, &stix->c->tok.name, stix->c->tok.type == STIX_IOTOK_RADNUMLIT); if (!lit) return -1; -#endif goto add_literal; } diff --git a/stix/lib/dic.c b/stix/lib/dic.c index 745c502..bc5c73d 100644 --- a/stix/lib/dic.c +++ b/stix/lib/dic.c @@ -63,7 +63,8 @@ static stix_oop_oop_t expand_bucket (stix_t* stix, stix_oop_oop_t oldbuc) static stix_oop_association_t find_or_upsert (stix_t* stix, stix_oop_set_t dic, stix_oop_char_t key, stix_oop_t value) { - stix_oow_t index, tally; + stix_ooi_t tally; + stix_oow_t index; stix_oop_association_t ass; stix_oow_t tmp_count = 0; @@ -75,6 +76,7 @@ static stix_oop_association_t find_or_upsert (stix_t* stix, stix_oop_set_t dic, index = stix_hashchars(key->slot, STIX_OBJ_GET_SIZE(key)) % STIX_OBJ_GET_SIZE(dic->bucket); + /* find */ while (dic->bucket->slot[index] != stix->_nil) { ass = (stix_oop_association_t)dic->bucket->slot[index]; @@ -86,7 +88,7 @@ static stix_oop_association_t find_or_upsert (stix_t* stix, stix_oop_set_t dic, stix_equalchars (key->slot, ((stix_oop_char_t)ass->key)->slot, STIX_OBJ_GET_SIZE(key))) { /* the value of STIX_NULL indicates no insertion or update. */ - if (value) ass->value = value; + if (value) ass->value = value; /* update */ return ass; } @@ -101,20 +103,34 @@ static stix_oop_association_t find_or_upsert (stix_t* stix, stix_oop_set_t dic, return STIX_NULL; } + /* the key is not found. insert it. */ + STIX_ASSERT (STIX_OOP_IS_SMOOI(dic->tally)); + tally = STIX_OOP_TO_SMOOI(dic->tally); + if (tally >= STIX_SMOOI_MAX) + { + /* this built-in dictionary is not allowed to hold more than + * STIX_SMOOI_MAX items for efficiency sake */ + stix->errnum = STIX_EDFULL; + return STIX_NULL; + } + stix_pushtmp (stix, (stix_oop_t*)&dic); tmp_count++; stix_pushtmp (stix, (stix_oop_t*)&key); tmp_count++; stix_pushtmp (stix, &value); tmp_count++; - tally = STIX_OOP_TO_SMOOI(dic->tally); + /* no conversion to stix_oow_t is necessary for tally + 1. + * the maximum value of tally is checked to be STIX_SMOOI_MAX - 1. + * tally + 1 can produce at most STIX_SMOOI_MAX. above all, + * STIX_SMOOI_MAX is way smaller than STIX_TYPE_MAX(stix_ooi_t). */ if (tally + 1 >= STIX_OBJ_GET_SIZE(dic->bucket)) { stix_oop_oop_t bucket; /* TODO: make the growth policy configurable instead of growing - it just before it gets full. The polcy can be grow it + it just before it gets full. The polcy can be grow it if it's 70% full */ - /* Enlarge the symbol table before it gets full to + /* enlarge the bucket before it gets full to * make sure that it has at least one free slot left * after having added a new symbol. this is to help * traversal end at a _nil slot if no entry is found. */ @@ -138,6 +154,8 @@ static stix_oop_association_t find_or_upsert (stix_t* stix, stix_oop_set_t dic, ass->key = (stix_oop_t)key; ass->value = value; + /* the current tally must be less than the maximum value. otherwise, + * it overflows after increment below */ STIX_ASSERT (tally < STIX_SMOOI_MAX); dic->tally = STIX_SMOOI_TO_OOP(tally + 1); dic->bucket->slot[index] = (stix_oop_t)ass; diff --git a/stix/lib/exec.c b/stix/lib/exec.c index 19975a7..4f77250 100644 --- a/stix/lib/exec.c +++ b/stix/lib/exec.c @@ -688,7 +688,7 @@ static int prim_basic_at (stix_t* stix, stix_ooi_t nargs) break; case STIX_OBJ_TYPE_CHAR: - v = STIX_OOP_FROM_CHAR(((stix_oop_char_t)rcv)->slot[idx]); + v = STIX_CHAR_TO_OOP(((stix_oop_char_t)rcv)->slot[idx]); break; case STIX_OBJ_TYPE_HALFWORD: @@ -1491,7 +1491,7 @@ printf ("CALL MODE 222 ERROR %d %d\n", dcGetError (dc), DC_ERROR_UNSUPPORTED_MOD case 'c': { char r = dcCallChar (dc, f); - ACTIVE_STACK_SETTOP (stix, STIX_OOP_FROM_CHAR(r)); + ACTIVE_STACK_SETTOP (stix, STIX_CHAR_TO_OOP(r)); break; } diff --git a/stix/lib/gc.c b/stix/lib/gc.c index 240ec02..6b96045 100644 --- a/stix/lib/gc.c +++ b/stix/lib/gc.c @@ -29,18 +29,25 @@ static void compact_symbol_table (stix_t* stix, stix_oop_t _nil) { stix_oop_char_t symbol; - stix_oow_t tally, index, i, x, y, z; - stix_oow_t bucket_size; + stix_oow_t i, x, y, z; + stix_oow_t bucket_size, index; + stix_ooi_t tally; #if defined(STIX_SUPPORT_GC_DURING_IGNITION) if (!stix->symtab) return; /* symbol table has not been created */ #endif - bucket_size = STIX_OBJ_GET_SIZE(stix->symtab->bucket); - + /* the symbol table doesn't allow more data items than STIX_SMOOI_MAX. + * so stix->symtab->tally must always be a small integer */ + STIX_ASSERT (STIX_OOP_IS_SMOOI(stix->symtab->tally)); tally = STIX_OOP_TO_SMOOI(stix->symtab->tally); + STIX_ASSERT (tally >= 0); /* it must not be less than 0 */ if (tally <= 0) return; + /* NOTE: in theory, the bucket size can be greater than STIX_SMOOI_MAX + * as it is an internal header field and is of an unsigned type */ + bucket_size = STIX_OBJ_GET_SIZE(stix->symtab->bucket); + for (index = 0; index < bucket_size; ) { if (STIX_OBJ_GET_FLAGS_MOVED(stix->symtab->bucket->slot[index])) @@ -79,6 +86,7 @@ static void compact_symbol_table (stix_t* stix, stix_oop_t _nil) tally--; } + STIX_ASSERT (tally >= 0); STIX_ASSERT (tally <= STIX_SMOOI_MAX); stix->symtab->tally = STIX_SMOOI_TO_OOP(tally); } diff --git a/stix/lib/stix.h b/stix/lib/stix.h index 4850201..34bfe61 100644 --- a/stix/lib/stix.h +++ b/stix/lib/stix.h @@ -49,6 +49,8 @@ enum stix_errnum_t STIX_EINVAL, /**< invalid parameter or data */ STIX_ERANGE, /**< range error. overflow and underflow */ STIX_ENOENT, /**< no matching entry */ + STIX_EDFULL, /**< dictionary full */ + STIX_EDIVBY0, /**< divide by zero */ STIX_EIOERR, /**< I/O error */ STIX_EECERR, /**< encoding conversion error */ @@ -157,12 +159,15 @@ typedef struct stix_obj_word_t* stix_oop_word_t; #define STIX_OOP_IS_CHAR(oop) (((stix_oow_t)oop) & STIX_OOP_TAG_CHAR) #define STIX_SMOOI_TO_OOP(num) ((stix_oop_t)((((stix_ooi_t)(num)) << STIX_OOP_TAG_BITS) | STIX_OOP_TAG_SMINT)) #define STIX_OOP_TO_SMOOI(oop) (((stix_ooi_t)oop) >> STIX_OOP_TAG_BITS) -#define STIX_OOP_FROM_CHAR(num) ((stix_oop_t)((((stix_oow_t)(num)) << STIX_OOP_TAG_BITS) | STIX_OOP_TAG_CHAR)) +#define STIX_CHAR_TO_OOP(num) ((stix_oop_t)((((stix_oow_t)(num)) << STIX_OOP_TAG_BITS) | STIX_OOP_TAG_CHAR)) #define STIX_OOP_TO_CHAR(oop) (((stix_oow_t)oop) >> STIX_OOP_TAG_BITS) #define STIX_SMINT_BITS (STIX_SIZEOF(stix_ooi_t) * 8 - STIX_OOP_TAG_BITS) #define STIX_SMOOI_MAX ((stix_ooi_t)(~((stix_oow_t)0) >> (STIX_OOP_TAG_BITS + 1))) -#define STIX_SMOOI_MIN (-STIX_SMOOI_MAX - 1) +/* Sacrificing 1 bit pattern for a negative SMOOI makes implementation + * a lot eaisier in many parts */ +/*#define STIX_SMOOI_MIN (-STIX_SMOOI_MAX - 1)*/ +#define STIX_SMOOI_MIN (-STIX_SMOOI_MAX) #define STIX_IN_SMOOI_RANGE(ooi) ((ooi) >= STIX_SMOOI_MIN && (ooi) <= STIX_SMOOI_MAX) /* TODO: There are untested code where smint is converted to stix_oow_t. diff --git a/stix/lib/sym.c b/stix/lib/sym.c index 5a418b5..b24c9f8 100644 --- a/stix/lib/sym.c +++ b/stix/lib/sym.c @@ -60,7 +60,8 @@ static stix_oop_oop_t expand_bucket (stix_t* stix, stix_oop_oop_t oldbuc) static stix_oop_t find_or_make_symbol (stix_t* stix, const stix_ooch_t* ptr, stix_oow_t len, int create) { - stix_oow_t index, tally; + stix_ooi_t tally; + stix_oow_t index; stix_oop_char_t symbol; STIX_ASSERT (len > 0); @@ -95,7 +96,21 @@ static stix_oop_t find_or_make_symbol (stix_t* stix, const stix_ooch_t* ptr, sti return STIX_NULL; } + /* make a new symbol and insert it */ + STIX_ASSERT (STIX_OOP_IS_SMOOI(stix->symtab->tally)); tally = STIX_OOP_TO_SMOOI(stix->symtab->tally); + if (tally >= STIX_SMOOI_MAX) + { + /* this built-in table is not allowed to hold more than + * STIX_SMOOI_MAX items for efficiency sake */ + stix->errnum = STIX_EDFULL; + return STIX_NULL; + } + + /* no conversion to stix_oow_t is necessary for tally + 1. + * the maximum value of tally is checked to be STIX_SMOOI_MAX - 1. + * tally + 1 can produce at most STIX_SMOOI_MAX. above all, + * STIX_SMOOI_MAX is way smaller than STIX_TYPE_MAX(stix_ooi_t). */ if (tally + 1 >= STIX_OBJ_GET_SIZE(stix->symtab->bucket)) { stix_oop_oop_t bucket; @@ -104,7 +119,7 @@ static stix_oop_t find_or_make_symbol (stix_t* stix, const stix_ooch_t* ptr, sti it just before it gets full. The polcy can be grow it if it's 70% full */ - /* Enlarge the symbol table before it gets full to + /* enlarge the symbol table before it gets full to * make sure that it has at least one free slot left * after having added a new symbol. this is to help * traversal end at a _nil slot if no entry is found. */