summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2025-05-07 07:35:04 -0700
committerKaz Kylheku <kaz@kylheku.com>2025-05-07 07:35:04 -0700
commit4200a551e0ffe095ec9f4dc7458232d6748f3393 (patch)
tree3fa032c9ef8d136e73d826d47bf5f1baea87b245
parent50e958f5be982bff900a81ab55b34757921b3b31 (diff)
downloadtxr-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.c27
-rw-r--r--txr.124
2 files changed, 29 insertions, 22 deletions
diff --git a/arith.c b/arith.c
index eeb84c00..ad7e3e69 100644
--- a/arith.c
+++ b/arith.c
@@ -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);
}
diff --git a/txr.1 b/txr.1
index b6bdaa04..e6983904 100644
--- a/txr.1
+++ b/txr.1
@@ -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