about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--Doc/Zsh/arith.yo5
-rw-r--r--Src/math.c37
-rw-r--r--Src/params.c9
4 files changed, 42 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index a1e14f46e..f2dbdbf57 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2000-09-02  Andrew Main  <zefram@zsh.org>
+
+	* 12722: Doc/Zsh/arith.yo, Src/math.c, Src/params.c: Allow
+	[##base] as well as [#base]; the doubled # suppresses output
+	of a base prefix.  Also clean up parsing of [] base-selection
+	constructs.
+
 2000-09-01  Bart Schaefer  <schaefer@zsh.org>
 
 	* 12721: Functions/Misc/allopt: Remove "emulate" which changes the
diff --git a/Doc/Zsh/arith.yo b/Doc/Zsh/arith.yo
index 095756667..fcd45a1f5 100644
--- a/Doc/Zsh/arith.yo
+++ b/Doc/Zsh/arith.yo
@@ -65,6 +65,11 @@ have output base 16, while tt(x) (assuming it does not already exist) is
 implicitly typed by the arithmetic evaluation, where it acquires the output
 base 8.
 
+When an output base is specified using the `tt([#)var(base)tt(])' syntax,
+an appropriate base prefix will be output if necessary, so that the value
+output is valid syntax for input.  If the tt(#) is doubled, for example
+`tt([##16])', then no base prefix is output.
+
 Floating point constants are recognized by the presence of a decimal point
 or an exponent.  The decimal point may be the first character of the
 constant, but the exponent character tt(e) or tt(E) may not, as it will be
diff --git a/Src/math.c b/Src/math.c
index 38466ed8e..77c7df2a5 100644
--- a/Src/math.c
+++ b/Src/math.c
@@ -342,21 +342,34 @@ zzlex(void)
 	    return EOI;
 	case '[':
 	    {
-		int base, setradix = 0;
-		if (*ptr == '#') {
-		    ptr++;
-		    setradix = 1;
-		}
-		base = zstrtol(ptr, &ptr, 10);
+		int n;
 
-		if (*ptr == ']')
-		    ptr++;
-		if (setradix)
-		    outputradix = base;
-		else {
-		    yyval.u.l = zstrtol(ptr, &ptr, lastbase = base);
+		if (idigit(*ptr)) {
+		    n = zstrtol(ptr, &ptr, 10);
+		    if (*ptr != ']' || !idigit(*++ptr)) {
+			zerr("bad base syntax", NULL, 0);
+			return EOI;
+		    }
+		    yyval.u.l = zstrtol(ptr, &ptr, lastbase = n);
 		    return NUM;
 		}
+		if (*ptr == '#') {
+		    n = 1;
+		    if (*++ptr == '#') {
+			n = -1;
+			ptr++;
+		    }
+		    if (!idigit(*ptr))
+			goto bofs;
+		    outputradix = n * zstrtol(ptr, &ptr, 10);
+		} else {
+		    bofs:
+		    zerr("bad output format specification", NULL, 0);
+		    return EOI;
+		}
+		if(*ptr != ']')
+			goto bofs;
+		ptr++;
 		break;
 	    }
 	case ' ':
diff --git a/Src/params.c b/Src/params.c
index 1439e9af8..2d38272a6 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -3041,10 +3041,10 @@ convbase(char *s, zlong v, int base)
 
     if (v < 0)
 	*s++ = '-', v = -v;
-    if (base <= 1)
-	base = 10;
+    if (base >= -1 && base <= 1)
+	base = -10;
 
-    if (base != 10) {
+    if (base > 0) {
 	if (isset(CBASES) && base == 16)
 	    sprintf(s, "0x");
 	else if (isset(CBASES) && base == 8 && isset(OCTALZEROES))
@@ -3052,7 +3052,8 @@ convbase(char *s, zlong v, int base)
 	else
 	    sprintf(s, "%d#", base);
 	s += strlen(s);
-    }
+    } else
+	base = -base;
     for (x = v; x; digs++)
 	x /= base;
     if (!digs)