bc/dc: fix length(0) and length(0.000nnn) result

function                                             old     new   delta
zxc_vm_process                                      6464    6498     +34

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/miscutils/bc.c b/miscutils/bc.c
index 84bbe7b..9156409 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -6259,13 +6259,20 @@
 {
 	size_t len = n->len;
 
-	if (n->rdx != len) return len;
+	if (n->rdx != len)
+		// length(100): rdx 0 len 3, return 3
+		// length(0.01-0.01): rdx 2 len 0, return 2
+		// dc: 0.01 0.01 - Zp: rdx 2 len 0, return 1
+		return len != 0 ? len : (IS_BC ? n->rdx : 1);
+
+	// length(0): return 1
+	// length(0.000nnn): count nnn
 	for (;;) {
 		if (len == 0) break;
 		len--;
 		if (n->num[len] != 0) break;
 	}
-	return len;
+	return len + 1;
 }
 
 static BC_STATUS zxc_program_builtin(char inst)
@@ -6293,12 +6300,12 @@
 	if (inst == XC_INST_SQRT)
 		s = zbc_num_sqrt(num, &res.d.n, G.prog.scale);
 #if ENABLE_BC
-	else if (len != 0 && opnd->t == XC_RESULT_ARRAY) {
+	else if (len && opnd->t == XC_RESULT_ARRAY) {
 		bc_num_ulong2num(&res.d.n, (unsigned long) ((BcVec *) num)->len);
 	}
 #endif
 #if ENABLE_DC
-	else if (len != 0 && !BC_PROG_NUM(opnd, num)) {
+	else if (len && !BC_PROG_NUM(opnd, num)) {
 		char **str;
 		size_t idx = opnd->t == XC_RESULT_STR ? opnd->d.id.idx : num->rdx;
 
@@ -6307,6 +6314,8 @@
 	}
 #endif
 	else {
+//TODO: length(.00) and scale(.00) should return 2, they return 1 and 0 now
+//(don't forget to check that dc Z and X commands do not break)
 		bc_num_ulong2num(&res.d.n, len ? xc_program_len(num) : xc_program_scale(num));
 	}
 
diff --git a/testsuite/bc.tests b/testsuite/bc.tests
index 179d5d2..1c74872 100755
--- a/testsuite/bc.tests
+++ b/testsuite/bc.tests
@@ -182,6 +182,11 @@
 	"123" \
 	"" "print 1,2,3"
 
+testing "bc length" \
+	"bc" \
+	"1\n3\n1\n3\n3\n" \
+	"" "length(0); length(100); length(0.01); length(0.00120); length(0.012-0.012);"
+
 testing "bc { print 1 }" \
 	"bc" \
 	"1" \
diff --git a/testsuite/dc.tests b/testsuite/dc.tests
index 361bc84..ad00993 100755
--- a/testsuite/dc.tests
+++ b/testsuite/dc.tests
@@ -114,6 +114,11 @@
 	"2\n9\n" \
 	"" "[2p]s\n[3p]l\nx\n9p"
 
+testing "dc Z (length) for numbers" \
+	"dc" \
+	"1\n1\n3\n1\n3\n1\n" \
+	"" "0Zp\n0.000Zp\n100Zp\n0.01Zp\n0.00120Zp\n0.0012 0.0012 - Zp\n"
+
 for f in dc_*.dc; do
 	r="`basename "$f" .dc`_results.txt"
 	test -f "$r" || continue