diff --git a/lib/err.c b/lib/err.c index c58ad00..3b526f5 100644 --- a/lib/err.c +++ b/lib/err.c @@ -83,6 +83,8 @@ static char* synerrstr[] = "wrong character literal", "invalid numeric literal", "out of integer range", + "wrong error literal", + "wrong smptr literal", "sudden end of input", "( expected", diff --git a/lib/hcl.h b/lib/hcl.h index 5d6ca27..fe7be01 100644 --- a/lib/hcl.h +++ b/lib/hcl.h @@ -94,6 +94,8 @@ enum hcl_synerrnum_t HCL_SYNERR_CHARLIT, /* wrong character literal */ HCL_SYNERR_RADNUMLIT , /* invalid numeric literal with radix */ HCL_SYNERR_INTRANGE, /* integer range error */ + HCL_SYNERR_ERRORLIT, /* wrong error literal */ + HCL_SYNERR_SMPTRLIT, /* wrong smptr literal */ HCL_SYNERR_EOF, /* sudden end of input */ HCL_SYNERR_LPAREN, /* ( expected */ @@ -236,38 +238,6 @@ typedef struct hcl_obj_word_t* hcl_oop_word_t; #endif -#if 0 -/* - * OOP encoding - * An object pointer(OOP) is an ordinary pointer value to an object. - * but some simple numeric values are also encoded into OOP using a simple - * bit-shifting and masking. - * - * A real OOP is stored without any bit-shifting while a non-OOP value encoded - * in an OOP is bit-shifted to the left by 2 and the 2 least-significant bits - * are set to 1 or 2. - * - * This scheme works because the object allocators aligns the object size to - * a multiple of sizeof(hcl_oop_t). This way, the 2 least-significant bits - * of a real OOP are always 0s. - */ - -#define HCL_OOP_TAG_BITS 2 -#define HCL_OOP_TAG_SMOOI 1 -#define HCL_OOP_TAG_CHAR 2 - -#define HCL_OOP_IS_NUMERIC(oop) (((hcl_oow_t)oop) & (HCL_OOP_TAG_SMOOI | HCL_OOP_TAG_CHAR)) -#define HCL_OOP_IS_POINTER(oop) (!HCL_OOP_IS_NUMERIC(oop)) -#define HCL_OOP_GET_TAG(oop) (((hcl_oow_t)oop) & HCL_LBMASK(hcl_oow_t, HCL_OOP_TAG_BITS)) - -#define HCL_OOP_IS_SMOOI(oop) (((hcl_ooi_t)oop) & HCL_OOP_TAG_SMOOI) -#define HCL_OOP_IS_CHAR(oop) (((hcl_oow_t)oop) & HCL_OOP_TAG_CHAR) -#define HCL_SMOOI_TO_OOP(num) ((hcl_oop_t)((((hcl_ooi_t)(num)) << HCL_OOP_TAG_BITS) | HCL_OOP_TAG_SMOOI)) -#define HCL_OOP_TO_SMOOI(oop) (((hcl_ooi_t)oop) >> HCL_OOP_TAG_BITS) -#define HCL_CHAR_TO_OOP(num) ((hcl_oop_t)((((hcl_oow_t)(num)) << HCL_OOP_TAG_BITS) | HCL_OOP_TAG_CHAR)) -#define HCL_OOP_TO_CHAR(oop) (((hcl_oow_t)oop) >> HCL_OOP_TAG_BITS) - -#else /* * OOP encoding * An object pointer(OOP) is an ordinary pointer value to an object. @@ -327,8 +297,6 @@ typedef struct hcl_obj_word_t* hcl_oop_word_t; #define HCL_OOP_TO_ERROR(oop) (((hcl_oow_t)oop) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) #define HCL_ERROR_TO_OOP(num) ((hcl_oop_t)((((hcl_oow_t)(num)) << (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) | HCL_OOP_TAG_ERROR)) -#endif - /* SMOOI takes up 62 bit on a 64-bit architecture and 30 bits * on a 32-bit architecture. The absolute value takes up 61 bits and 29 bits * respectively for the 1 sign bit. */ @@ -341,6 +309,21 @@ typedef struct hcl_obj_word_t* hcl_oop_word_t; #define HCL_SMOOI_MIN (-HCL_SMOOI_MAX) #define HCL_IN_SMOOI_RANGE(ooi) ((ooi) >= HCL_SMOOI_MIN && (ooi) <= HCL_SMOOI_MAX) + +/* SMPTR is a special value which has been devised to encode an address value + * whose low HCL_OOP_TAG_BITS_LO bits are 0. its class is SmallPointer. A pointer + * returned by most of system functions would be aligned to the pointer size. + * you can use the followings macros when converting such a pointer without loss. */ +#define HCL_IN_SMPTR_RANGE(ptr) ((((hcl_oow_t)ptr) & HCL_LBMASK(hcl_oow_t, HCL_OOP_TAG_BITS_LO)) == 0) + +#define HCL_CHAR_BITS (HCL_OOI_BITS - HCL_OOP_TAG_BITS_LO - HCL_OOP_TAG_BITS_HI) +#define HCL_CHAR_MIN 0 +#define HCL_CHAR_MAX (~((hcl_oow_t)0) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_HI)) + +#define HCL_ERROR_BITS (HCL_OOI_BITS - HCL_OOP_TAG_BITS_LO - HCL_OOP_TAG_BITS_HI) +#define HCL_ERROR_MIN 0 +#define HCL_ERROR_MAX (~((hcl_oow_t)0) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_HI)) + /* TODO: There are untested code where smint is converted to hcl_oow_t. * for example, the spec making macro treats the number as hcl_oow_t instead of hcl_ooi_t. * as of this writing, i skip testing that part with the spec value exceeding HCL_SMOOI_MAX. diff --git a/lib/print.c b/lib/print.c index 35fca77..2a32a84 100644 --- a/lib/print.c +++ b/lib/print.c @@ -191,7 +191,7 @@ next: } else if (HCL_OOP_IS_SMPTR(obj)) { - if (outbfmt(hcl, mask, "#\\p%zu", (hcl_oow_t)HCL_OOP_TO_SMPTR(obj)) <= -1) return -1; + if (outbfmt(hcl, mask, "#\\p%zX", (hcl_oow_t)HCL_OOP_TO_SMPTR(obj)) <= -1) return -1; goto done; } else if (HCL_OOP_IS_ERROR(obj)) diff --git a/lib/read.c b/lib/read.c index 5ad71ef..d55c4d0 100644 --- a/lib/read.c +++ b/lib/read.c @@ -823,12 +823,13 @@ static int get_sharp_token (hcl_t* hcl) if (TOKEN_NAME_LEN(hcl) >= 4) { - if (hcl->c->tok.name.ptr[2] == 'p') + if (TOKEN_NAME_CHAR(hcl, 2) == 'P' || TOKEN_NAME_CHAR(hcl, 2) == 'p') { SET_TOKEN_TYPE (hcl, HCL_IOTOK_SMPTRLIT); goto hexcharlit; } - else if (hcl->c->tok.name.ptr[2] == 'x' || hcl->c->tok.name.ptr[2] == 'u') + else if (TOKEN_NAME_CHAR(hcl, 2) == 'X' || TOKEN_NAME_CHAR(hcl, 2) == 'x' || + TOKEN_NAME_CHAR(hcl, 2) == 'U' || TOKEN_NAME_CHAR(hcl, 2) == 'u') { hcl_oow_t i; @@ -845,7 +846,7 @@ static int get_sharp_token (hcl_t* hcl) c = c * 16 + CHAR_TO_NUM(hcl->c->tok.name.ptr[i], 16); /* don't care if it is for 'p' */ } } - else if (hcl->c->tok.name.ptr[2] == 'e') + else if (TOKEN_NAME_CHAR(hcl, 2) == 'E' || TOKEN_NAME_CHAR(hcl, 2) == 'e') { hcl_oow_t i; for (i = 3; i < TOKEN_NAME_LEN(hcl); i++) @@ -1756,7 +1757,6 @@ static int read_object (hcl_t* hcl) switch (TOKEN_TYPE(hcl)) { default: - HCL_ASSERT (hcl, !"should never happen - invalid token type"); hcl_seterrbfmt (hcl, HCL_EINTERN, "invalid token encountered - %d %.*js", TOKEN_TYPE(hcl), TOKEN_NAME_LEN(hcl), TOKEN_NAME_PTR(hcl)); return -1; @@ -1960,6 +1960,13 @@ static int read_object (hcl_t* hcl) v = v * 16 + CHAR_TO_NUM(TOKEN_NAME_CHAR(hcl, i), 16); } + if (!HCL_IN_SMPTR_RANGE(v)) + { + hcl_setsynerr (hcl, HCL_SYNERR_SMPTRLIT, TOKEN_LOC(hcl), TOKEN_NAME(hcl)); + return -1; + } + + obj = HCL_SMPTR_TO_OOP(v); break; } @@ -1974,6 +1981,12 @@ static int read_object (hcl_t* hcl) { HCL_ASSERT (hcl, is_digitchar(TOKEN_NAME_CHAR(hcl, i))); v = v * 10 + CHAR_TO_NUM(TOKEN_NAME_CHAR(hcl, i), 10); + + if (v > HCL_ERROR_MAX) + { + hcl_setsynerr (hcl, HCL_SYNERR_ERRORLIT, TOKEN_LOC(hcl), TOKEN_NAME(hcl)); + return -1; + } } obj = HCL_ERROR_TO_OOP(v);