From: Peter Johnson Date: Mon, 15 Oct 2001 04:32:16 +0000 (-0000) Subject: Allow both signed and unsigned interpretations for get_int and check_size. X-Git-Tag: v0.1.0~250 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c6d051a5f2f5c43171ab66bd88a666a1178955e9;p=yasm Allow both signed and unsigned interpretations for get_int and check_size. Change argument order on get_int and check_size to better match other functions (intnum * first arg). svn path=/trunk/yasm/; revision=280 --- diff --git a/libyasm/intnum.c b/libyasm/intnum.c index 05f5303e..0826a7ae 100644 --- a/libyasm/intnum.c +++ b/libyasm/intnum.c @@ -457,21 +457,49 @@ intnum_is_neg1(intnum *intn) (intn->type == INTNUM_BV && BitVector_is_full(intn->val.bv))); } -void -intnum_get_int(unsigned long *ret_val, const intnum *intn) +unsigned long +intnum_get_uint(const intnum *intn) { switch (intn->type) { case INTNUM_UL: - *ret_val = intn->val.ul; - break; + return intn->val.ul; case INTNUM_BV: - *ret_val = BitVector_Chunk_Read(intn->val.bv, 32, 0); - break; + return BitVector_Chunk_Read(intn->val.bv, 32, 0); + default: + InternalError(__LINE__, __FILE__, _("unknown intnum type")); + return 0; + } +} + +long +intnum_get_int(const intnum *intn) +{ + switch (intn->type) { + case INTNUM_UL: + return (long)intn->val.ul; + case INTNUM_BV: + if (BitVector_msb(intn->val.bv)) { + /* it's negative: negate the bitvector to get a positive + * number, then negate the positive number. + */ + intptr abs_bv = BitVector_Create(BITVECT_ALLOC_SIZE, FALSE); + long retval; + + BitVector_Negate(abs_bv, intn->val.bv); + retval = -((long)BitVector_Chunk_Read(abs_bv, 32, 0)); + + BitVector_Destroy(abs_bv); + return retval; + } else + return BitVector_Chunk_Read(intn->val.bv, 32, 0); + default: + InternalError(__LINE__, __FILE__, _("unknown intnum type")); + return 0; } } void -intnum_get_sized(unsigned char *ptr, const intnum *intn, size_t size) +intnum_get_sized(const intnum *intn, unsigned char *ptr, size_t size) { unsigned long ul; unsigned char *buf; @@ -499,27 +527,68 @@ intnum_get_sized(unsigned char *ptr, const intnum *intn, size_t size) /* Return 1 if okay size, 0 if not */ int -intnum_check_size(const intnum *intn, size_t size) +intnum_check_size(const intnum *intn, size_t size, int is_signed) { - switch (intn->type) { - case INTNUM_UL: - if (size >= 4) - return 1; - switch (size) { - case 3: - return ((intn->val.ul & 0x00FFFFFF) == intn->val.ul); - case 2: - return ((intn->val.ul & 0x0000FFFF) == intn->val.ul); - case 1: - return ((intn->val.ul & 0x000000FF) == intn->val.ul); - } - break; - case INTNUM_BV: - if (size >= 10) - return 1; - else - return (Set_Max(intn->val.bv) < size*8); - break; + if (is_signed) { + long absl; + + switch (intn->type) { + case INTNUM_UL: + if (size >= 4) + return 1; + /* absl = absolute value of (long)intn->val.ul */ + absl = (long)intn->val.ul; + if (absl < 0) + absl = -absl; + + switch (size) { + case 3: + return ((absl & 0x00FFFFFF) == absl); + case 2: + return ((absl & 0x0000FFFF) == absl); + case 1: + return ((absl & 0x000000FF) == absl); + } + break; + case INTNUM_BV: + if (size >= 10) + return 1; + if (BitVector_msb(intn->val.bv)) { + /* it's negative */ + intptr abs_bv = BitVector_Create(BITVECT_ALLOC_SIZE, + FALSE); + int retval; + + BitVector_Negate(abs_bv, intn->val.bv); + retval = Set_Max(abs_bv) < size*8; + + BitVector_Destroy(abs_bv); + return retval; + } else + return (Set_Max(intn->val.bv) < size*8); + break; + } + } else { + switch (intn->type) { + case INTNUM_UL: + if (size >= 4) + return 1; + switch (size) { + case 3: + return ((intn->val.ul & 0x00FFFFFF) == intn->val.ul); + case 2: + return ((intn->val.ul & 0x0000FFFF) == intn->val.ul); + case 1: + return ((intn->val.ul & 0x000000FF) == intn->val.ul); + } + break; + case INTNUM_BV: + if (size >= 10) + return 1; + else + return (Set_Max(intn->val.bv) < size*8); + break; + } } return 0; } diff --git a/libyasm/intnum.h b/libyasm/intnum.h index 62fe9e27..38f3248e 100644 --- a/libyasm/intnum.h +++ b/libyasm/intnum.h @@ -78,18 +78,23 @@ int intnum_is_neg1(intnum *acc); * for overflow. Use intnum_check_size() to check for overflow. */ -/* Return a 32-bit value in "standard" C format (eg, of unknown endian). */ -void intnum_get_int(unsigned long *ret_val, const intnum *intn); +/* Return a 32-bit value in "standard" C format (eg, of unknown endian). + * intnum_get_uint() treats intn as an unsigned integer (and returns as such). + * intnum_get_int() treats intn as a signed integer (and returns as such). + */ +unsigned long intnum_get_uint(const intnum *intn); +long intnum_get_int(const intnum *intn); /* ptr will point to the Intel-format little-endian byte string after * call (eg, [0] should be the first byte output to the file). */ -void intnum_get_sized(unsigned char *ptr, const intnum *intn, size_t size); +void intnum_get_sized(const intnum *intn, unsigned char *ptr, size_t size); /* Check to see if intn will fit without overflow in size bytes. + * If is_signed is 1, intn is treated as a signed number. * Returns 1 if it will, 0 if not. */ -int intnum_check_size(const intnum *intn, size_t size); +int intnum_check_size(const intnum *intn, size_t size, int is_signed); void intnum_print(const intnum *intn); diff --git a/src/intnum.c b/src/intnum.c index 05f5303e..0826a7ae 100644 --- a/src/intnum.c +++ b/src/intnum.c @@ -457,21 +457,49 @@ intnum_is_neg1(intnum *intn) (intn->type == INTNUM_BV && BitVector_is_full(intn->val.bv))); } -void -intnum_get_int(unsigned long *ret_val, const intnum *intn) +unsigned long +intnum_get_uint(const intnum *intn) { switch (intn->type) { case INTNUM_UL: - *ret_val = intn->val.ul; - break; + return intn->val.ul; case INTNUM_BV: - *ret_val = BitVector_Chunk_Read(intn->val.bv, 32, 0); - break; + return BitVector_Chunk_Read(intn->val.bv, 32, 0); + default: + InternalError(__LINE__, __FILE__, _("unknown intnum type")); + return 0; + } +} + +long +intnum_get_int(const intnum *intn) +{ + switch (intn->type) { + case INTNUM_UL: + return (long)intn->val.ul; + case INTNUM_BV: + if (BitVector_msb(intn->val.bv)) { + /* it's negative: negate the bitvector to get a positive + * number, then negate the positive number. + */ + intptr abs_bv = BitVector_Create(BITVECT_ALLOC_SIZE, FALSE); + long retval; + + BitVector_Negate(abs_bv, intn->val.bv); + retval = -((long)BitVector_Chunk_Read(abs_bv, 32, 0)); + + BitVector_Destroy(abs_bv); + return retval; + } else + return BitVector_Chunk_Read(intn->val.bv, 32, 0); + default: + InternalError(__LINE__, __FILE__, _("unknown intnum type")); + return 0; } } void -intnum_get_sized(unsigned char *ptr, const intnum *intn, size_t size) +intnum_get_sized(const intnum *intn, unsigned char *ptr, size_t size) { unsigned long ul; unsigned char *buf; @@ -499,27 +527,68 @@ intnum_get_sized(unsigned char *ptr, const intnum *intn, size_t size) /* Return 1 if okay size, 0 if not */ int -intnum_check_size(const intnum *intn, size_t size) +intnum_check_size(const intnum *intn, size_t size, int is_signed) { - switch (intn->type) { - case INTNUM_UL: - if (size >= 4) - return 1; - switch (size) { - case 3: - return ((intn->val.ul & 0x00FFFFFF) == intn->val.ul); - case 2: - return ((intn->val.ul & 0x0000FFFF) == intn->val.ul); - case 1: - return ((intn->val.ul & 0x000000FF) == intn->val.ul); - } - break; - case INTNUM_BV: - if (size >= 10) - return 1; - else - return (Set_Max(intn->val.bv) < size*8); - break; + if (is_signed) { + long absl; + + switch (intn->type) { + case INTNUM_UL: + if (size >= 4) + return 1; + /* absl = absolute value of (long)intn->val.ul */ + absl = (long)intn->val.ul; + if (absl < 0) + absl = -absl; + + switch (size) { + case 3: + return ((absl & 0x00FFFFFF) == absl); + case 2: + return ((absl & 0x0000FFFF) == absl); + case 1: + return ((absl & 0x000000FF) == absl); + } + break; + case INTNUM_BV: + if (size >= 10) + return 1; + if (BitVector_msb(intn->val.bv)) { + /* it's negative */ + intptr abs_bv = BitVector_Create(BITVECT_ALLOC_SIZE, + FALSE); + int retval; + + BitVector_Negate(abs_bv, intn->val.bv); + retval = Set_Max(abs_bv) < size*8; + + BitVector_Destroy(abs_bv); + return retval; + } else + return (Set_Max(intn->val.bv) < size*8); + break; + } + } else { + switch (intn->type) { + case INTNUM_UL: + if (size >= 4) + return 1; + switch (size) { + case 3: + return ((intn->val.ul & 0x00FFFFFF) == intn->val.ul); + case 2: + return ((intn->val.ul & 0x0000FFFF) == intn->val.ul); + case 1: + return ((intn->val.ul & 0x000000FF) == intn->val.ul); + } + break; + case INTNUM_BV: + if (size >= 10) + return 1; + else + return (Set_Max(intn->val.bv) < size*8); + break; + } } return 0; } diff --git a/src/intnum.h b/src/intnum.h index 62fe9e27..38f3248e 100644 --- a/src/intnum.h +++ b/src/intnum.h @@ -78,18 +78,23 @@ int intnum_is_neg1(intnum *acc); * for overflow. Use intnum_check_size() to check for overflow. */ -/* Return a 32-bit value in "standard" C format (eg, of unknown endian). */ -void intnum_get_int(unsigned long *ret_val, const intnum *intn); +/* Return a 32-bit value in "standard" C format (eg, of unknown endian). + * intnum_get_uint() treats intn as an unsigned integer (and returns as such). + * intnum_get_int() treats intn as a signed integer (and returns as such). + */ +unsigned long intnum_get_uint(const intnum *intn); +long intnum_get_int(const intnum *intn); /* ptr will point to the Intel-format little-endian byte string after * call (eg, [0] should be the first byte output to the file). */ -void intnum_get_sized(unsigned char *ptr, const intnum *intn, size_t size); +void intnum_get_sized(const intnum *intn, unsigned char *ptr, size_t size); /* Check to see if intn will fit without overflow in size bytes. + * If is_signed is 1, intn is treated as a signed number. * Returns 1 if it will, 0 if not. */ -int intnum_check_size(const intnum *intn, size_t size); +int intnum_check_size(const intnum *intn, size_t size, int is_signed); void intnum_print(const intnum *intn);