diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2025-05-07 07:35:04 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2025-05-07 07:35:04 -0700 |
commit | 4200a551e0ffe095ec9f4dc7458232d6748f3393 (patch) | |
tree | 3fa032c9ef8d136e73d826d47bf5f1baea87b245 | |
parent | 50e958f5be982bff900a81ab55b34757921b3b31 (diff) | |
download | txr-4200a551e0ffe095ec9f4dc7458232d6748f3393.tar.gz txr-4200a551e0ffe095ec9f4dc7458232d6748f3393.tar.bz2 txr-4200a551e0ffe095ec9f4dc7458232d6748f3393.zip |
arith: logtrunc, lognot, bit, sign-extend: handle bits <= 0.
This fixes an exception in (int-buf #b'').
* arith.c (comp_trunc, lognot): Do not throw on negative bits,
just return zero.
(bit): Return nil if bit is negative rather than throwing.
(sign_extend): Fix instance of bad indentation. Renumber
goto labels.
Otherwise, nothing needs to be done here since bit
is where it was blowing up on a zero or negative bits value.
* txr.1: Document that logtrunc, lognot, sign-extend and bit
handle nonpositive bit widths, and negative bit positions.
-rw-r--r-- | arith.c | 27 | ||||
-rw-r--r-- | txr.1 | 24 |
2 files changed, 29 insertions, 22 deletions
@@ -3802,7 +3802,7 @@ static val comp_trunc(val a, val bits) bn = c_n(bits); if (bn < 0) - goto bad4; + return zero; switch (type(a)) { case NUM: @@ -3836,9 +3836,6 @@ bad2: bad3: uw_throwf(error_s, lit("~a: non-integral operand ~s"), self, a, nao); - -bad4: - uw_throwf(error_s, lit("~a: negative bits value ~s"), self, bits, nao); } val lognot(val a, val bits) @@ -3880,7 +3877,7 @@ val logtrunc(val a, val bits) bn = c_n(bits); if (bn < 0) - goto bad4; + return zero; switch (type(a)) { mp_err mpe; @@ -3912,9 +3909,6 @@ bad2: bad3: uw_throwf(error_s, lit("~a: non-integral operand ~s"), self, a, nao); - -bad4:; - uw_throwf(error_s, lit("~a: negative bits value ~s"), self, bits, nao); } val sign_extend(val n, val nbits) @@ -3922,7 +3916,7 @@ val sign_extend(val n, val nbits) val self = sign_extend_s; if (cobjp(n)) { - return do_binary_method(self, self, n, nbits); + return do_binary_method(self, self, n, nbits); } else { val msb = minus(nbits, one); val ntrunc = logtrunc(n, nbits); @@ -4065,7 +4059,7 @@ val bit(val a, val bit) bn = c_n(bit); if (bn < 0) - goto bad2; + return nil; switch (ta) { case NUM: @@ -4073,14 +4067,14 @@ val bit(val a, val bit) cnum an = c_n(a); if (bn < (SIZEOF_PTR * CHAR_BIT)) return (an & (convert(cnum, 1) << bn)) ? t : nil; - return an < 0 ? t : nil; + return tnil(an < 0); } case CHR: { cnum an = c_ch(a); if (bn < (SIZEOF_PTR * CHAR_BIT)) return (an & (convert(cnum, 1) << bn)) ? t : nil; - return an < 0 ? t : nil; + return tnil(an < 0); } case BGNUM: { @@ -4092,23 +4086,20 @@ val bit(val a, val bit) case MP_NO: return nil; default: - goto bad4; + goto bad3; } } default: - goto bad3; + goto bad2; } bad: uw_throwf(error_s, lit("~a: bit position ~s is not a fixnum"), self, bit, nao); bad2: - uw_throwf(error_s, lit("~a: bit position ~s is negative"), self, bit, nao); - -bad3: uw_throwf(error_s, lit("~a: non-integral operand ~s"), self, a, nao); -bad4: +bad3: do_mp_error(self, mpe); } @@ -53692,7 +53692,14 @@ to the specified number of bits. If .meta value is negative, then the two's complement representation -is truncated. The return value of +is truncated. + +If +.meta bits +is zero or negative, the value returned by both functions +is zero. + +The return value of .code logtrunc is always a nonnegative integer. @@ -53713,6 +53720,10 @@ function. Then, this truncated value is regarded as a two's complement integer. The value of this integer is calculated and returned. +If the bits +.meta bits +argument is zero or negative the value returned is zero. + .TP* Examples: .verb @@ -53778,13 +53789,18 @@ function tests whether the integer or character .meta value has a 1 in bit position .metn bit . -The -.meta bit -argument must be a nonnegative integer. A value of + +A value of .meta bit of zero indicates the least-significant-bit position of .metn value . +If +.meta bit +is negative, +.code nil +is returned. + The .code bit function has a Boolean result, returning the symbol |