Module Name:    src
Committed By:   rillig
Date:           Sat Mar 15 10:31:28 UTC 2025

Modified Files:
        src/bin/expr: expr.y
        src/tests/bin/expr: t_expr.sh

Log Message:
expr: don't evaluate irrelevant conditions


To generate a diff of this commit:
cvs rdiff -u -r1.49 -r1.50 src/bin/expr/expr.y
cvs rdiff -u -r1.10 -r1.11 src/tests/bin/expr/t_expr.sh

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/bin/expr/expr.y
diff -u src/bin/expr/expr.y:1.49 src/bin/expr/expr.y:1.50
--- src/bin/expr/expr.y:1.49	Sat Mar 15 10:00:56 2025
+++ src/bin/expr/expr.y	Sat Mar 15 10:31:28 2025
@@ -1,4 +1,4 @@
-/* $NetBSD: expr.y,v 1.49 2025/03/15 10:00:56 rillig Exp $ */
+/* $NetBSD: expr.y,v 1.50 2025/03/15 10:31:28 rillig Exp $ */
 
 /*-
  * Copyright (c) 2000, 2025 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
 
 %{
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: expr.y,v 1.49 2025/03/15 10:00:56 rillig Exp $");
+__RCSID("$NetBSD: expr.y,v 1.50 2025/03/15 10:31:28 rillig Exp $");
 
 #include <sys/types.h>
 
@@ -47,6 +47,7 @@ __RCSID("$NetBSD: expr.y,v 1.49 2025/03/
 #include <string.h>
 
 static const char * const *av;
+static unsigned skip_level;
 
 static void yyerror(const char *, ...) __dead;
 static int yylex(void);
@@ -78,29 +79,41 @@ exp:	expr {
 ;
 
 expr:	item
-|	expr SPEC_OR expr {
-		if (!is_empty_or_zero($1))
+|	expr SPEC_OR {
+		$$ = is_empty_or_zero($1) ? NULL : "1";
+		if ($$)
+			skip_level++;
+	} expr {
+		if ($3)
 			$$ = $1;
 		else
-			$$ = $3;
-	}
-|	expr SPEC_AND expr {
-		if (!is_empty_or_zero($1) && !is_empty_or_zero($3))
+			$$ = $4;
+		if ($3)
+			skip_level--;
+	}
+|	expr SPEC_AND {
+		$$ = is_empty_or_zero($1) ? NULL : "1";
+		if (!$$)
+			skip_level++;
+	} expr {
+		if ($3 && !is_empty_or_zero($4))
 			$$ = $1;
 		else
 			$$ = "0";
+		if (!$3)
+			skip_level--;
 	}
 |	expr SPEC_REG expr {
-		$$ = eval_match($1, $3);
+		$$ = skip_level == 0 ? eval_match($1, $3) : "";
 	}
 |	expr ADD_SUB_OPERATOR expr {
-		$$ = eval_arith($1, $2, $3);
+		$$ = skip_level == 0 ? eval_arith($1, $2, $3) : "";
 	}
 |	expr MUL_DIV_MOD_OPERATOR expr {
-		$$ = eval_arith($1, $2, $3);
+		$$ = skip_level == 0 ? eval_arith($1, $2, $3) : "";
 	}
 |	expr COMPARE expr {
-		$$ = eval_compare($1, $2, $3) ? "1" : "0";
+		$$ = skip_level == 0 && eval_compare($1, $2, $3) ? "1" : "0";
 	}
 |	LEFT_PARENT expr RIGHT_PARENT {
 		$$ = $2;

Index: src/tests/bin/expr/t_expr.sh
diff -u src/tests/bin/expr/t_expr.sh:1.10 src/tests/bin/expr/t_expr.sh:1.11
--- src/tests/bin/expr/t_expr.sh:1.10	Sat Mar 15 07:02:07 2025
+++ src/tests/bin/expr/t_expr.sh	Sat Mar 15 10:31:28 2025
@@ -1,4 +1,4 @@
-# $NetBSD: t_expr.sh,v 1.10 2025/03/15 07:02:07 rillig Exp $
+# $NetBSD: t_expr.sh,v 1.11 2025/03/15 10:31:28 rillig Exp $
 #
 # Copyright (c) 2007 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -272,11 +272,11 @@ short_circuit_head() {
 }
 short_circuit_body() {
 	test_expr 0 \| 1 / 0 "expr: second argument to '/' must not be zero"
-	# FIXME: The right-hand side of '|' must not be evaluated.
-	test_expr 123 \| 1 / 0 "expr: second argument to '/' must not be zero"
+	test_expr 123 \| 1 / 0 '123'
+	test_expr 123 \| a : '***' '123'
 
-	# FIXME: The right-hand side of '&' must not be evaluated.
-	test_expr 0 \& 1 / 0 "expr: second argument to '/' must not be zero"
+	test_expr 0 \& 1 / 0 '0'
+	test_expr 0 \& a : '***' '0'
 	test_expr 123 \& 1 / 0 "expr: second argument to '/' must not be zero"
 
 	test_finish

Reply via email to