shithub: mc

Download patch

ref: 8f2b7470799a4851a5f73e8566b18823c7fe72df
parent: 4a59ae120acc8cbb8ee2bccbd0bcbd171f8db7b5
author: Ori Bernstein <[email protected]>
date: Sat Sep 13 23:21:03 EDT 2014

Fix bigint parsing for hex.

    We weren't trimming the '0x' hex prefix,and that confused our
    code when it got the 'x' and tried to treat it as a digit.

--- a/libstd/bigint.myr
+++ b/libstd/bigint.myr
@@ -166,7 +166,7 @@
 }
 
 const bigparse = {str
-	var c, val : uint32, base
+	var c, val : int, base
 	var v, b
 	var a
 
@@ -179,9 +179,12 @@
 	else
 		base = 10
 	;;
+	if base != 10
+		str = str[2:]
+	;;
 
 	a = mkbigint(0)
-	b = mkbigint(base castto(int32))
+	b = mkbigint(base)
 	/*
 	 efficiency hack: to save allocations,
 	 just mutate v[0]. The value will always
@@ -194,11 +197,13 @@
 			continue
 		;;
 		val = charval(c, base)
-		if val < 0
+		if val < 0 || val > base
 			bigfree(a)
+			bigfree(b)
+			bigfree(v)
 			-> `None
 		;;
-		v.dig[0] = val
+		v.dig[0] = val castto(uint32)
 		if val == 0
 			v.sign = 0
 		else
--- a/test/bigint.myr
+++ /dev/null
@@ -1,96 +1,0 @@
-use std
-
-const main = {
-	var a, b, c, d, e
-	var buf : byte[4096], n
-
-	a = std.mkbigint(1234)
-	b = std.mkbigint(0x7fffffff)
-	c = std.mkbigint(7919)
-	d = std.mkbigint(113051)
-	e = std.mkbigint(11)
-
-	std.bigmul(a, b)
-	std.bigmul(a, b)
-	std.bigadd(a, c)
-	std.bigsub(a, d)
-	std.bigdiv(a, e)
-
-	std.bigfree(b)
-	std.bigfree(c)
-	std.bigfree(d)
-	std.bigfree(e)
-
-	n = std.bigbfmt(buf[:], a, 0)
-	std.put("%s\n", buf[:n])
-
-	/* smoke test */
-	match std.bigparse("1234_5678_1234_6789_6666_7777_8888")
-	| `std.Some val: a = val
-	| `std.None: std.die("Failed to parse a\n")
-	;;
-	match std.bigparse("1234_5678_1234_6789_6666_7777")
-	| `std.Some val: b = val
-	| `std.None: std.die("Failed to parse b\n")
-	;;
-
-	n = std.bigbfmt(buf[:], a, 0)
-	std.put("%s / ", buf[:n])
-	n = std.bigbfmt(buf[:], b, 0)
-	std.put("%s == ", buf[:n])
-
-	std.bigdiv(a, b)
-
-	n = std.bigbfmt(buf[:], a, 0)
-	std.put("%s\n", buf[:n])
-
-	/* test big shifts */
-	a = std.mkbigint(1)
-	var shift = 4095
-	n = std.bigbfmt(buf[:], a, 0)
-	std.put("%s << %i == 0x", buf[:n], shift)
-	std.bigshli(a, shift)
-	n = std.bigbfmt(buf[:], a, 10)
-	std.put("%s\n", buf[:n])
-	std.put("top bits: %xi\n", a.dig[a.dig.len - 1])
-
-	/* no shifting */
-	match std.bigparse("0xffff_1234_1234_1234_1234")
-	| `std.Some val: a = val
-	| `std.None: std.die("Failed to parse a\n")
-	;;
-	match std.bigparse("0xf010_1234_2314")
-	| `std.Some val: b = val
-	| `std.None: std.die("Failed to parse b\n")
-	;;
-
-	n = std.bigbfmt(buf[:], a, 0)
-	std.put("%s / ", buf[:n])
-	n = std.bigbfmt(buf[:], b, 0)
-	std.put("%s == ", buf[:n])
-
-	std.bigdiv(a, b)
-
-	n = std.bigbfmt(buf[:], a, 0)
-	std.put("%s\n", buf[:n])
-
-	/* no shifting */
-	match std.bigparse("0xffff_1234_1234_1234_1234")
-	| `std.Some val: a = val
-	| `std.None: std.die("Failed to parse a\n")
-	;;
-	match std.bigparse("0x0ff_1234_2314")
-	| `std.Some val: b = val
-	| `std.None: std.die("Failed to parse b\n")
-	;;
-
-	n = std.bigbfmt(buf[:], a, 0)
-	std.put("%s / ", buf[:n])
-	n = std.bigbfmt(buf[:], b, 0)
-	std.put("%s == ", buf[:n])
-
-	std.bigdiv(a, b)
-
-	n = std.bigbfmt(buf[:], a, 0)
-	std.put("%s\n", buf[:n])
-}
--- a/test/data/bigint-expected
+++ /dev/null
@@ -1,4 +1,0 @@
-517347321949036993306
-1234567812346789666677778888 / 123456781234678966667777 == 10000
-5192296858534810493479828944327220 / 1208925819597106013545236 == 4294967296
-5192296858534810493479828944327220 / 75557863709417659441940 == 68719476751
--- /dev/null
+++ b/test/data/stdbigint-expected
@@ -1,0 +1,4 @@
+517347321949036993306
+1234567812346789666677778888 / 123456781234678966667777 == 10000
+5192296858534810493479828944327220 / 1208925819597106013545236 == 4294967296
+5192296858534810493479828944327220 / 75557863709417659441940 == 68719476751
--- /dev/null
+++ b/test/stdbigint.myr
@@ -1,0 +1,88 @@
+use std
+
+const main = {
+	var a, b, c, d, e
+	var buf : byte[4096], n
+
+	a = std.mkbigint(1234)
+	b = std.mkbigint(0x7fffffff)
+	c = std.mkbigint(7919)
+	d = std.mkbigint(113051)
+	e = std.mkbigint(11)
+
+	std.bigmul(a, b)
+	std.bigmul(a, b)
+	std.bigadd(a, c)
+	std.bigsub(a, d)
+	std.bigdiv(a, e)
+
+	std.bigfree(b)
+	std.bigfree(c)
+	std.bigfree(d)
+	std.bigfree(e)
+
+	n = std.bigbfmt(buf[:], a, 0)
+	std.put("%s\n", buf[:n])
+
+	/* smoke test */
+	match std.bigparse("1234_5678_1234_6789_6666_7777_8888")
+	| `std.Some val: a = val
+	| `std.None: std.die("Failed to parse a\n")
+	;;
+	match std.bigparse("1234_5678_1234_6789_6666_7777")
+	| `std.Some val: b = val
+	| `std.None: std.die("Failed to parse b\n")
+	;;
+
+	n = std.bigbfmt(buf[:], a, 0)
+	std.put("%s / ", buf[:n])
+	n = std.bigbfmt(buf[:], b, 0)
+	std.put("%s == ", buf[:n])
+
+	std.bigdiv(a, b)
+
+	n = std.bigbfmt(buf[:], a, 0)
+	std.put("%s\n", buf[:n])
+
+	match std.bigparse("0xffff_1234_1234_1234_1234")
+	| `std.Some val: a = val
+	n = std.bigbfmt(buf[:], a, 0)
+	std.put("a = %s \n", buf[:n])
+	| `std.None: std.die("Failed to parse a\n")
+	;;
+	match std.bigparse("0xf010_1234_2314")
+	| `std.Some val: b = val
+	| `std.None: std.die("Failed to parse b\n")
+	;;
+
+	n = std.bigbfmt(buf[:], a, 0)
+	std.put("%s / ", buf[:n])
+	n = std.bigbfmt(buf[:], b, 0)
+	std.put("%s == ", buf[:n])
+
+	std.bigdiv(a, b)
+
+	n = std.bigbfmt(buf[:], a, 0)
+	std.put("%s\n", buf[:n])
+
+	match std.bigparse("5192296858534810493479828944327220")
+	| `std.Some val: a = val
+	n = std.bigbfmt(buf[:], a, 0)
+	std.put("a = %s \n", buf[:n])
+	| `std.None: std.die("Failed to parse a\n")
+	;;
+	match std.bigparse("75557863709417659441940")
+	| `std.Some val: b = val
+	| `std.None: std.die("Failed to parse b\n")
+	;;
+
+	n = std.bigbfmt(buf[:], a, 0)
+	std.put("%s / ", buf[:n])
+	n = std.bigbfmt(buf[:], b, 0)
+	std.put("%s == ", buf[:n])
+
+	std.bigdiv(a, b)
+
+	n = std.bigbfmt(buf[:], a, 0)
+	std.put("%s\n", buf[:n])
+}
--- a/test/tests
+++ b/test/tests
@@ -133,7 +133,7 @@
 B stdslcp	C
 B stdfmtpad	C
 B stdpathnorm	C
-B bigint	C
+B stdbigint	C
 B exporttrait
 # B local-labels	E	10 ## BUGGERED
 F declmismatch