Re: set -e causes AS_IF to exit in else clause

Paul Eggert <[email protected]>
Newsgroups gmane.comp.sysutils.autoconf.bugs
Organization UCLA Computer Science Department
Message-ID <[email protected]>
Thanks for reporting that regression. I installed the attached patch.
0001-Fix-bug-with-AS_IF-and-set-e.patch (text/x-patch, 4.9 KB)
From 1684650184aea9ed51ded79680bb1b4fcb098f26 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Thu, 31 Mar 2022 22:29:05 -0700
Subject: [PATCH] =?UTF-8?q?Fix=20bug=20with=20AS=5FIF=20and=20=E2=80=98set?=
 =?UTF-8?q?=20-e=E2=80=99?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Problem reported by Peter Johansson in:
https://lists.gnu.org/r/bug-autoconf/2022-03/msg00009.html
The bug was introduced in 2020-11-15T18:56:[email protected]
with commit message saying “If anyone has a better idea for how to
make this work I will be glad to hear it”, and this patch uses a
trick with ‘case’ that should be a better idea.
* lib/m4sugar/m4sh.m4 (as_nop, as_fn_nop, _AS_EMPTY_ELSE_PREPARE):
Remove.  All uses removed.
(_AS_IF_ELSE): Wrap the non-blank IF-ELSE inside a no-op case,
which works since a case branch can be empty in the shell.
* tests/m4sh.at (AS_IF and AS_CASE): Test the fix.
---
 lib/m4sugar/m4sh.m4 | 44 +++++++++++++-------------------------------
 tests/m4sh.at       |  4 ++++
 2 files changed, 17 insertions(+), 31 deletions(-)

diff --git a/lib/m4sugar/m4sh.m4 b/lib/m4sugar/m4sh.m4
index b2075315..e6067ecf 100644
--- a/lib/m4sugar/m4sh.m4
+++ b/lib/m4sugar/m4sh.m4
@@ -98,10 +98,9 @@ _$0
 # _AS_BOURNE_COMPATIBLE
 # ---------------------
 # This is the part of AS_BOURNE_COMPATIBLE which has to be repeated inside
-# each instance.  See _AS_EMPTY_ELSE_PREPARE for explanation of as_nop.
+# each instance.
 m4_define([_AS_BOURNE_COMPATIBLE],
-[as_nop=:
-AS_IF([test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1],
+[AS_IF([test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1],
  [emulate sh
   NULLCMD=:
   [#] Pre-4.2 versions of Zsh do word splitting on ${1+"$[@]"}, which
@@ -352,8 +351,7 @@ m4_defun([_AS_PREPARE],
 [m4_pushdef([AS_MESSAGE_LOG_FD], [-1])]dnl
 [_AS_ERROR_PREPARE
 _m4_popdef([AS_MESSAGE_LOG_FD])]dnl
-[_AS_EMPTY_ELSE_PREPARE
-_AS_EXIT_PREPARE
+[_AS_EXIT_PREPARE
 _AS_UNSET_PREPARE
 _AS_VAR_APPEND_PREPARE
 _AS_VAR_ARITH_PREPARE
@@ -389,7 +387,6 @@ AS_REQUIRE([_AS_CR_PREPARE])
 AS_REQUIRE([_AS_LINENO_PREPARE])
 AS_REQUIRE([_AS_ECHO_N_PREPARE])
 AS_REQUIRE([_AS_EXIT_PREPARE])
-AS_REQUIRE([_AS_EMPTY_ELSE_PREPARE])
 AS_REQUIRE([_AS_LN_S_PREPARE])
 AS_REQUIRE([_AS_MKDIR_P_PREPARE])
 AS_REQUIRE([_AS_TEST_PREPARE])
@@ -672,18 +669,13 @@ done[]_m4_popdef([$1])])
 # | fi
 # with simplifications when IF-TRUE1 and/or IF-FALSE are empty.
 #
-# Note: IF-TRUEn and IF_FALSE may be nonempty but, after further macro
-# expansion, leave no actual shell code.  We can't detect this, so we
-# include a no-op statement in each clause to prevent it becoming a shell
-# syntax error.  For the IF-TRUEn this can simply be ':' at the beginning of
-# the clause.  IF-FALSE is harder because it must preserve the value of $?
-# from the conditional expression.  The most practical way to do this is
-# with a shell function whose body is 'return $?' but AS_IF is used before
-# it's safe to use shell functions.  To deal with *that*, there is a shell
-# variable $as_fn_nop that expands to ':' before the nop shell function is
-# defined, and invokes the nop shell function afterward.  Early uses of
-# AS_IF (which are all under our control) must not use the value of $? from
-# the conditional expression in an else clause.
+# Note: IF-TRUEn and IF-FALSE may be nonempty but, after further macro
+# expansion, leave no actual shell code.  We can't detect this, so
+# surround each clause with appropriate shell syntax so that it is valid
+# even if it is empty.  For the IF-TRUEn this can simply be ':' before
+# the clause.  IF-FALSE is harder because it might use the value of $?
+# from the conditional expression.  One way to do this is to write
+# 'case e in e) IF-FALSE ;; esac' which is valid even if IF-FALSE is empty.
 m4_define([_AS_IF],
 [elif $1
 then :
@@ -691,9 +683,9 @@ then :
 ])
 m4_defun([_AS_IF_ELSE],
 [m4_ifnblank([$1],
-[m4_append_uniq([_AS_CLEANUP], [AS_REQUIRE([_AS_EMPTY_ELSE_PREPARE])])]dnl
-[else $as_nop
-  $1
+[else case e in @%:@(
+  e) $1 ;;
+esac
 ])])
 
 m4_defun([AS_IF],
@@ -703,16 +695,6 @@ then :
 m4_map_args_pair([_$0], [_$0_ELSE], m4_shift2($@))]dnl
 [fi[]])# AS_IF
 
-m4_defun([_AS_EMPTY_ELSE_PREPARE],
-[m4_divert_text([M4SH-INIT-FN],
-[AS_FUNCTION_DESCRIBE([as_fn_nop], [],
-  [Do nothing but, unlike ":", preserve the value of $][?.])
-as_fn_nop ()
-{
-  return $[]?
-}
-as_nop=as_fn_nop])])
-
 
 # AS_SET_STATUS(STATUS)
 # ---------------------
diff --git a/tests/m4sh.at b/tests/m4sh.at
index a20b8b13..a5c2272d 100644
--- a/tests/m4sh.at
+++ b/tests/m4sh.at
@@ -1423,6 +1423,9 @@ m4_define([empty])AS_IF([:], [empty]
 dnl Allow for users that don't know to avoid trailing whitespace
 AS_IF([:
 ], [echo nineteen])
+set -e
+AS_IF([false], [], [echo twenty])
+set +e
 
 # check that require works correctly
 m4_for([n], 1, 9, [],
@@ -1478,6 +1481,7 @@ sixteen
 seventeen
 eighteen
 nineteen
+twenty
 foo1=1 bar1=1
 foo2=2 bar2=
 foo3=3 bar3=
-- 
2.32.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.