Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 12 Jun 2005 21:29:12 +0200 (CEST)
From:      Derik van Zuetphen <dz@426.ch>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   bin/82170: m4's eval does not work as documented
Message-ID:  <20050612192912.13F80678E6@trevize.a.426.ch>
Resent-Message-ID: <200506121930.j5CJUL1l094487@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         82170
>Category:       bin
>Synopsis:       m4's eval does not work as documented
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Jun 12 19:30:21 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Derik van Zuetphen
>Release:        FreeBSD 5.4-RELEASE-p1 i386
>Organization:
>Environment:
System: FreeBSD trevize.a.426.ch 5.4-RELEASE-p1 FreeBSD 5.4-RELEASE-p1 #15: Mon May 30 14:32:58 CEST 2005 root@trevize.a.426.ch:/usr/obj/usr/src/sys/TREVIZE i386


>Description:

>From the manpage:

---
eval [...] The second argument (if
any) specifies the radix for the result, and the third argu-
ment (if any) specifies the minimum number of digits in the
result.
---

This is not implemented. The attached patch fixes this.

See also my PR bin/82161. This patch includes the patch from bin/82161!


>How-To-Repeat:

% echo "eval(16,16,4)"|/usr/bin/m4
16

Correct output should be:

% echo "eval(16,16,4)"|./m4
0010


>Fix:

diff -ruN --exclude=CVS current/TEST/radix.m4 my/TEST/radix.m4
--- current/TEST/radix.m4	Thu Jan  1 01:00:00 1970
+++ my/TEST/radix.m4	Sun Jun 12 20:57:34 2005
@@ -0,0 +1,65 @@
+define(row,`$1		eval($1,16,2)		eval($1,8)		eval($1,2,4)		eval($1,36)')dnl
+Base 10		Base 16		Base 8		Base 2		Base 36
+		(>=2 digits)			(>=4 digits)
+-------------------------------------------------------------------------
+row(0)
+row(1)
+row(2)
+row(3)
+row(4)
+row(5)
+row(6)
+row(7)
+row(8)
+row(010)
+row(9)
+row(10)
+row(11)
+row(12)
+row(13)
+row(14)
+row(15)
+row(0xf)
+row(16)
+row(17)
+row(18)
+row(19)
+row(20)
+row(21)
+row(22)
+row(23)
+row(24)
+row(25)
+row(26)
+row(27)
+row(28)
+row(29)
+row(30)
+row(31)
+row(32)
+row(33)
+row(34)
+row(35)
+row(36)
+row(37)
+row(100)
+row(101)
+row(102)
+row(1001)
+row(-1)
+row(-2)
+row(-15)
+row(-16)
+row(-35)
+row(-36)
+row(-37)
+row(-72)
+row(-73)
+
+Margin values on i386, gcc 3.4.2
+--------------------------------
+-INT_MAX
+row(-0x7fffffff)
+
+INT_MAX
+row(0x7fffffff)
diff -ruN --exclude=CVS current/eval.c my/eval.c
--- current/eval.c	Mon Aug 16 16:18:21 2004
+++ my/eval.c	Thu Feb 24 17:11:48 2005
@@ -76,6 +76,7 @@
 static void	dopushdef(const char *, const char *);
 static void	dodump(const char *[], int);
 static void	dotrace(const char *[], int, int);
+static void	doexpr(const char *[], int);
 static void	doifelse(const char *[], int);
 static int	doincl(const char *);
 static int	dopaste(const char *);
@@ -189,7 +190,7 @@
 	 * expression
 	 */
 		if (argc > 2)
-			pbnum(expr(argv[2]));
+			doexpr(argv, argc);
 		break;
 
 	case IFELTYPE:
@@ -709,6 +710,25 @@
 			mark_traced(argv[n], on);
 	} else
 		mark_traced(NULL, on);
+}
+
+/*
+ * doexpr - evaluate arithmetic expression
+ */
+static void
+doexpr(const char *argv[], int argc)
+{
+	switch (argc) {
+	case 3:
+		pbnum(expr(argv[2]));
+		break;
+	case 4:
+		pbnum_radix(expr(argv[2]),atoi(argv[3]),0);
+		break;
+	default: /* >= 5 */
+		pbnum_radix(expr(argv[2]),atoi(argv[3]),atoi(argv[4]));
+		break;
+	}
 }
 
 /*
diff -ruN --exclude=CVS current/expr.c my/expr.c
--- current/expr.c	Sat May  1 05:59:43 2004
+++ my/expr.c	Sun May 22 23:11:37 2005
@@ -50,6 +50,7 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD: src/usr.bin/m4/expr.c,v 1.14 2004/05/01 03:59:43 smkelly Exp $");
 
+#include <sys/limits.h>
 #include <sys/types.h>
 #include <ctype.h>
 #include <err.h>
@@ -568,7 +569,8 @@
 static int
 num(int mayeval)
 {
-	int rval, c, base;
+	unsigned int rval;
+	int c, base;
 	int ndig;
 
 	rval = 0;
@@ -614,10 +616,10 @@
 bad_digit:
 	ungetch();
 
-	if (ndig == 0)
+	if (ndig == 0 || rval > INT_MAX)
 		experr("bad constant");
 
-	return rval;
+	return (int)rval;
 }
 
 /*
diff -ruN --exclude=CVS current/misc.c my/misc.c
--- current/misc.c	Mon Jul 15 04:15:12 2002
+++ my/misc.c	Sun May 22 20:51:51 2005
@@ -122,21 +122,53 @@
 }
 
 /*
- *  pbnum - convert number to string, push back on input.
+ *  pbnum_radix - convert number to string, push back on input.
  */
 void
-pbnum(int n)
+pbnum_radix(int n,int radix,int length)
 {
-	int num;
+	int num,i;
+
+	if (n < 0) {
+		num = -n;
+		length--;
+	} else {
+		num = n;
+	}
+
+	if (radix < 2)
+		radix = 10;
+	if (radix > 36) 
+		radix = 10;
+	if (length < 0)
+		length = 0;
 
-	num = (n < 0) ? -n : n;
 	do {
-		putback(num % 10 + '0');
+		i = num % radix;
+		if (i<10)
+			putback(i+'0');
+		else
+			putback(i-10+'A');		
+		if (length > 0)
+			length--;
 	}
-	while ((num /= 10) > 0);
+	while ((num /= radix) > 0);
 
+	while (length > 0) {
+		putback('0');
+		length--;
+	}
 	if (n < 0)
 		putback('-');
+}
+
+/*
+ *  pbnum - convert number to string, push back on input.
+ */
+void
+pbnum(int n)
+{
+	pbnum_radix(n,10,0);
 }
 
 /*

>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20050612192912.13F80678E6>