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>
