aboutsummaryrefslogtreecommitdiff
path: root/bin/expr
diff options
context:
space:
mode:
authorSimon J. Gerraty <sjg@FreeBSD.org>2015-05-27 01:19:58 +0000
committerSimon J. Gerraty <sjg@FreeBSD.org>2015-05-27 01:19:58 +0000
commit98e0ffaefb0f241cda3a72395d3be04192ae0d47 (patch)
tree55c065b6730aaac2afb6c29933ee6ec5fa4c4249 /bin/expr
parentb17ff922d4072ae132ece458f5b5d74a236880ac (diff)
parente81032ad243db32b8fd615b2d55ee94b9f6a5b6a (diff)
downloadsrc-98e0ffaefb0f241cda3a72395d3be04192ae0d47.tar.gz
src-98e0ffaefb0f241cda3a72395d3be04192ae0d47.zip
Merge sync of head
Notes
Notes: svn path=/projects/bmake/; revision=283595
Diffstat (limited to 'bin/expr')
-rw-r--r--bin/expr/Makefile9
-rw-r--r--bin/expr/expr.18
-rw-r--r--bin/expr/expr.y20
-rw-r--r--bin/expr/tests/Makefile16
4 files changed, 45 insertions, 8 deletions
diff --git a/bin/expr/Makefile b/bin/expr/Makefile
index b86cf6686ab0..1d741b7e0b6d 100644
--- a/bin/expr/Makefile
+++ b/bin/expr/Makefile
@@ -1,9 +1,18 @@
# $FreeBSD$
+.include <src.opts.mk>
+
PROG= expr
SRCS= expr.y
YFLAGS=
+# expr relies on signed integer wrapping
+CFLAGS+= -fwrapv
+
NO_WMISSING_VARIABLE_DECLARATIONS=
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
+
.include <bsd.prog.mk>
diff --git a/bin/expr/expr.1 b/bin/expr/expr.1
index 34be0b8fa9de..d02105561fde 100644
--- a/bin/expr/expr.1
+++ b/bin/expr/expr.1
@@ -90,17 +90,17 @@ Return the evaluation of
.Ar expr1
if neither expression evaluates to an empty string or zero;
otherwise, returns zero.
-.It Ar expr1 Li "{=, >, >=, <, <=, !=}" Ar expr2
+.It Ar expr1 Bro =, >, >=, <, <=, != Brc Ar expr2
Return the results of integer comparison if both arguments are integers;
otherwise, returns the results of string comparison using the locale-specific
collation sequence.
The result of each comparison is 1 if the specified relation is true,
or 0 if the relation is false.
-.It Ar expr1 Li "{+, -}" Ar expr2
+.It Ar expr1 Bro +, - Brc Ar expr2
Return the results of addition or subtraction of integer-valued arguments.
-.It Ar expr1 Li "{*, /, %}" Ar expr2
+.It Ar expr1 Bro *, /, % Brc Ar expr2
Return the results of multiplication, integer division, or remainder of integer-valued arguments.
-.It Ar expr1 Li : Ar expr2
+.It Ar expr1 Li \&: Ar expr2
The
.Dq Li \&:
operator matches
diff --git a/bin/expr/expr.y b/bin/expr/expr.y
index 1856ec84d0f7..0ddf3990d2a8 100644
--- a/bin/expr/expr.y
+++ b/bin/expr/expr.y
@@ -444,14 +444,26 @@ op_minus(struct val *a, struct val *b)
return (r);
}
+/*
+ * We depend on undefined behaviour giving a result (in r).
+ * To test this result, pass it as volatile. This prevents
+ * optimizing away of the test based on the undefined behaviour.
+ */
void
-assert_times(intmax_t a, intmax_t b, intmax_t r)
+assert_times(intmax_t a, intmax_t b, volatile intmax_t r)
{
/*
- * if first operand is 0, no overflow is possible,
- * else result of division test must match second operand
+ * If the first operand is 0, no overflow is possible,
+ * else the result of the division test must match the
+ * second operand.
+ *
+ * Be careful to avoid overflow in the overflow test, as
+ * in assert_div(). Overflow in division would kill us
+ * with a SIGFPE before getting the test wrong. In old
+ * buggy versions, optimization used to give a null test
+ * instead of a SIGFPE.
*/
- if (a != 0 && r / a != b)
+ if ((a == -1 && b == INTMAX_MIN) || (a != 0 && r / a != b))
errx(ERR_EXIT, "overflow");
}
diff --git a/bin/expr/tests/Makefile b/bin/expr/tests/Makefile
new file mode 100644
index 000000000000..80c130c3df20
--- /dev/null
+++ b/bin/expr/tests/Makefile
@@ -0,0 +1,16 @@
+# $FreeBSD$
+
+OBJTOP= ${.OBJDIR}/../../..
+SRCTOP= ${.CURDIR}/../../..
+TESTSRC= ${SRCTOP}/contrib/netbsd-tests/bin/expr
+
+TESTSDIR= ${TESTSBASE}/bin/expr
+
+NETBSD_ATF_TESTS_SH= expr_test
+
+ATF_TESTS_SH_SED_expr_test+= -e 's/eval expr/eval expr --/g'
+ATF_TESTS_SH_SED_expr_test+= -e 's/"expr: integer overflow or underflow occurred for operation.*"/"expr: overflow"/g'
+
+.include <netbsd-tests.test.mk>
+
+.include <bsd.test.mk>