Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 9 Jul 2011 12:14:57 +0000 (UTC)
From:      Stefan Esser <se@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r223882 - head/bin/expr
Message-ID:  <201107091214.p69CEvfw099918@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: se
Date: Sat Jul  9 12:14:57 2011
New Revision: 223882
URL: http://svn.freebsd.org/changeset/base/223882

Log:
  Some refactoring for easier maintenance of the code. This is a follow-up
  to re-establishment of 64bit arithmetic, but is committed separately, to
  not obscure that conversion. This commit does not change the observed
  behaviour of expr in any way. Style will be fixed in a follow-up commit.

Modified:
  head/bin/expr/expr.y

Modified: head/bin/expr/expr.y
==============================================================================
--- head/bin/expr/expr.y	Sat Jul  9 12:05:53 2011	(r223881)
+++ head/bin/expr/expr.y	Sat Jul  9 12:14:57 2011	(r223882)
@@ -40,13 +40,16 @@ struct val {
 	} u;
 } ;
 
+char		**av;
+int		nonposix;
 struct val *result;
 
 void		assert_to_integer(struct val *);
-int		chk_div(intmax_t, intmax_t);
-int		chk_minus(intmax_t, intmax_t, intmax_t);
-int		chk_plus(intmax_t, intmax_t, intmax_t);
-int		chk_times(intmax_t, intmax_t, intmax_t);
+void		assert_div(intmax_t, intmax_t);
+void		assert_minus(intmax_t, intmax_t, intmax_t);
+void		assert_plus(intmax_t, intmax_t, intmax_t);
+void		assert_times(intmax_t, intmax_t, intmax_t);
+int		compare_vals(struct val *, struct val *);
 void		free_value(struct val *);
 int		is_integer(const char *);
 int		isstring(struct val *);
@@ -73,8 +76,6 @@ int		yyerror(const char *);
 int		yylex(void);
 int		yyparse(void);
 
-static int	nonposix;
-char **av;
 %}
 
 %union
@@ -344,138 +345,77 @@ op_and(struct val *a, struct val *b)
 	}
 }
 
-struct val *
-op_eq(struct val *a, struct val *b)
+int
+compare_vals(struct val *a, struct val *b)
 {
-	struct val *r;
+	int r;
 
-	if (isstring (a) || isstring (b)) {
-		to_string (a);
-		to_string (b);	
-		r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) == 0));
+	if (isstring(a) || isstring(b)) {
+		to_string(a);
+		to_string(b);
+		r = strcoll(a->u.s, b->u.s);
 	} else {
 		assert_to_integer(a);
 		assert_to_integer(b);
-		r = make_integer ((intmax_t)(a->u.i == b->u.i));
+		if (a->u.i > b->u.i)
+			r = 1;
+		else if (a->u.i < b->u.i)
+			r = -1;
+		else
+			r = 0;
 	}
 
-	free_value (a);
-	free_value (b);
-	return r;
+	free_value(a);
+	free_value(b);
+	return (r);
 }
 
 struct val *
-op_gt(struct val *a, struct val *b)
+op_eq(struct val *a, struct val *b)
 {
-	struct val *r;
-
-	if (isstring (a) || isstring (b)) {
-		to_string (a);
-		to_string (b);
-		r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) > 0));
-	} else {
-		assert_to_integer(a);
-		assert_to_integer(b);
-		r = make_integer ((intmax_t)(a->u.i > b->u.i));
-	}
+	return (make_integer((intmax_t)(compare_vals(a, b) == 0)));
+}
 
-	free_value (a);
-	free_value (b);
-	return r;
+struct val *
+op_gt(struct val *a, struct val *b)
+{
+	return (make_integer((intmax_t)(compare_vals(a, b) > 0)));
 }
 
 struct val *
 op_lt(struct val *a, struct val *b)
 {
-	struct val *r;
-
-	if (isstring (a) || isstring (b)) {
-		to_string (a);
-		to_string (b);
-		r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) < 0));
-	} else {
-		assert_to_integer(a);
-		assert_to_integer(b);
-		r = make_integer ((intmax_t)(a->u.i < b->u.i));
-	}
-
-	free_value (a);
-	free_value (b);
-	return r;
+	return (make_integer((intmax_t)(compare_vals(a, b) < 0)));
 }
 
 struct val *
 op_ge(struct val *a, struct val *b)
 {
-	struct val *r;
-
-	if (isstring (a) || isstring (b)) {
-		to_string (a);
-		to_string (b);
-		r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) >= 0));
-	} else {
-		assert_to_integer(a);
-		assert_to_integer(b);
-		r = make_integer ((intmax_t)(a->u.i >= b->u.i));
-	}
-
-	free_value (a);
-	free_value (b);
-	return r;
+	return (make_integer((intmax_t)(compare_vals(a, b) >= 0)));
 }
 
 struct val *
 op_le(struct val *a, struct val *b)
 {
-	struct val *r;
-
-	if (isstring (a) || isstring (b)) {
-		to_string (a);
-		to_string (b);
-		r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) <= 0));
-	} else {
-		assert_to_integer(a);
-		assert_to_integer(b);
-		r = make_integer ((intmax_t)(a->u.i <= b->u.i));
-	}
-
-	free_value (a);
-	free_value (b);
-	return r;
+	return (make_integer((intmax_t)(compare_vals(a, b) <= 0)));
 }
 
 struct val *
 op_ne(struct val *a, struct val *b)
 {
-	struct val *r;
-
-	if (isstring (a) || isstring (b)) {
-		to_string (a);
-		to_string (b);
-		r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) != 0));
-	} else {
-		assert_to_integer(a);
-		assert_to_integer(b);
-		r = make_integer ((intmax_t)(a->u.i != b->u.i));
-	}
-
-	free_value (a);
-	free_value (b);
-	return r;
+	return (make_integer((intmax_t)(compare_vals(a, b) != 0)));
 }
 
-int
-chk_plus(intmax_t a, intmax_t b, intmax_t r)
+void
+assert_plus(intmax_t a, intmax_t b, intmax_t r)
 {
-
-	/* sum of two positive numbers must be positive */
-	if (a > 0 && b > 0 && r <= 0)
-		return 1;
-	/* sum of two negative numbers must be negative */
-	if (a < 0 && b < 0 && r >= 0)
-		return 1;
-	/* all other cases are OK */
-	return 0;
+	/*
+	 * sum of two positive numbers must be positive,
+	 * sum of two negative numbers must be negative
+	 */
+	if ((a > 0 && b > 0 && r <= 0) ||
+	    (a < 0 && b < 0 && r >= 0))
+		errx(ERR_EXIT, "overflow");
 }
 
 struct val *
@@ -487,28 +427,22 @@ op_plus(struct val *a, struct val *b)
 	assert_to_integer(b);
 
 	r = make_integer(a->u.i + b->u.i);
-	if (chk_plus(a->u.i, b->u.i, r->u.i)) {
-		errx(ERR_EXIT, "overflow");
-	}
+	assert_plus(a->u.i, b->u.i, r->u.i);
 
 	free_value (a);
 	free_value (b);
 	return r;
 }
 
-int
-chk_minus(intmax_t a, intmax_t b, intmax_t r)
+void
+assert_minus(intmax_t a, intmax_t b, intmax_t r)
 {
 
 	/* special case subtraction of INTMAX_MIN */
-	if (b == INTMAX_MIN) {
-		if (a >= 0)
-			return 1;
-		else
-			return 0;
-	}
-	/* this is allowed for b != INTMAX_MIN */
-	return chk_plus (a, -b, r);
+	if (b == INTMAX_MIN && a < 0)
+		errx(ERR_EXIT, "overflow");
+	/* check addition of negative subtrahend */
+	assert_plus(a, -b, r);
 }
 
 struct val *
@@ -520,25 +454,22 @@ op_minus(struct val *a, struct val *b)
 	assert_to_integer(b);
 
 	r = make_integer(a->u.i - b->u.i);
-	if (chk_minus(a->u.i, b->u.i, r->u.i)) {
-		errx(ERR_EXIT, "overflow");
-	}
+	assert_minus(a->u.i, b->u.i, r->u.i);
 
 	free_value (a);
 	free_value (b);
 	return r;
 }
 
-int
-chk_times(intmax_t a, intmax_t b, intmax_t r)
+void
+assert_times(intmax_t a, intmax_t b, intmax_t r)
 {
-	/* special case: first operand is 0, no overflow possible */
-	if (a == 0)
-		return 0;
-	/* verify that result of division matches second operand */
-	if (r / a != b)
-		return 1;
-	return 0;
+	/*
+	 * if first operand is 0, no overflow is possible,
+	 * else result of division test must match second operand
+	 */
+	if (a != 0 && r / a != b)
+		errx(ERR_EXIT, "overflow");
 }
 
 struct val *
@@ -550,24 +481,21 @@ op_times(struct val *a, struct val *b)
 	assert_to_integer(b);
 
 	r = make_integer(a->u.i * b->u.i);
-	if (chk_times(a->u.i, b->u.i, r->u.i)) {
-		errx(ERR_EXIT, "overflow");
-	}
+	assert_times(a->u.i, b->u.i, r->u.i);
 
 	free_value (a);
 	free_value (b);
 	return (r);
 }
 
-int
-chk_div(intmax_t a, intmax_t b)
+void
+assert_div(intmax_t a, intmax_t b)
 {
-	/* div by zero has been taken care of before */
+	if (b == 0)
+		errx(ERR_EXIT, "division by zero");
 	/* only INTMAX_MIN / -1 causes overflow */
 	if (a == INTMAX_MIN && b == -1)
-		return 1;
-	/* everything else is OK */
-	return 0;
+		errx(ERR_EXIT, "overflow");
 }
 
 struct val *
@@ -578,12 +506,8 @@ op_div(struct val *a, struct val *b)
 	assert_to_integer(a);
 	assert_to_integer(b);
 
-	if (b->u.i == 0) {
-		errx(ERR_EXIT, "division by zero");
-	}
-	if (chk_div(a->u.i, b->u.i)) {
-		errx(ERR_EXIT, "overflow");
-	}
+	/* assert based on operands only, not on result */
+	assert_div(a->u.i, b->u.i);
 	r = make_integer(a->u.i / b->u.i);
 
 	free_value (a);
@@ -598,9 +522,8 @@ op_rem(struct val *a, struct val *b)
 
 	assert_to_integer(a);
 	assert_to_integer(b);
-	if (b->u.i == 0) {
-		errx(ERR_EXIT, "division by zero");
-	}
+	/* pass a=1 to only check for div by zero */
+	assert_div(1, b->u.i);
 	r = make_integer(a->u.i % b->u.i);
 
 	free_value (a);



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