[PATCH] m4sh: allow trailing newlines in shell conditions

Eric Blake <[email protected]>
Newsgroups gmane.comp.sysutils.autoconf.patches
Message-ID <[email protected]>
Dimitrios Apostolou reported confusion in understanding why
his configure.ac was generating a shell syntax error with:

AM_CONDITIONAL([HAVE_LIBXML2],
    [test "x$with_libxml2" != xno &&
     test "x$ac_cv_lib_xml2_xmlFirstElementChild" = xyes]
)

Root cause was that his trailing newline, coupled with a
'if $2; then' construct in the macro body, resulted in
configure containing:
if test ... xyes
; then
where the semicolon is a syntax error in shell.

While that macro is not under our control, it does highlight
the fact that the shell can use either ; or newline to
terminate a conditional prior to the next keyword in a compound
statement.  If we use newline, we gain two benefits - the
configure file is slightly smaller (more lines, but fewer
bytes), and any user that doesn't realize that unquoted
trailing newlines in a macro argument are still significant
can still generate valid shell code when their argument is
used in a shell compound statement.

* lib/m4sugar/m4sh.m4 (AS_IF, _AS_IF, _AS_CLEAN_DIR): Prefer
newline over semicolon to end user-supplied conditionals.
* lib/autoconf/general.m4 (AC_CONFIG_AUX_DIRS): Likewise.
* lib/autoconf/libs.m4 (AC_SEARCH_LIBS): Likewise.
* lib/autoconf/programs.m4 (_AC_PATH_PROGS_FEATURE_CHECK):
Likewise.
* tests/m4sh.at (AS_IF and AS_CASE): Test it.

Signed-off-by: Eric Blake <[email protected]>
---
 lib/autoconf/general.m4  |  3 ++-
 lib/autoconf/libs.m4     |  3 ++-
 lib/autoconf/programs.m4 |  3 ++-
 lib/m4sugar/m4sh.m4      | 15 ++++++++++-----
 tests/m4sh.at            |  4 ++++
 5 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/lib/autoconf/general.m4 b/lib/autoconf/general.m4
index 696a9a1..59d204f 100644
--- a/lib/autoconf/general.m4
+++ b/lib/autoconf/general.m4
@@ -1700,7 +1700,8 @@ AC_DEFUN([AC_CONFIG_AUX_DIR_DEFAULT],
 # do not automatically need to distribute the other auxiliary files.
 AC_DEFUN([AC_CONFIG_AUX_DIRS],
 [ac_aux_dir=
-for ac_dir in $1; do
+for ac_dir in $1
+do
   if test -f "$ac_dir/install-sh"; then
     ac_aux_dir=$ac_dir
     ac_install_sh="$ac_aux_dir/install-sh -c"
diff --git a/lib/autoconf/libs.m4 b/lib/autoconf/libs.m4
index 50143d3..55e9468 100644
--- a/lib/autoconf/libs.m4
+++ b/lib/autoconf/libs.m4
@@ -49,7 +49,8 @@ AC_DEFUN([AC_SEARCH_LIBS],
 AC_CACHE_CHECK([for library containing $1], [ac_Search],
 [ac_func_search_save_LIBS=$LIBS
 AC_LANG_CONFTEST([AC_LANG_CALL([], [$1])])
-for ac_lib in '' $2; do
+for ac_lib in '' $2
+do
   if test -z "$ac_lib"; then
     ac_res="none required"
   else
diff --git a/lib/autoconf/programs.m4 b/lib/autoconf/programs.m4
index cdd86ea..32f737a 100644
--- a/lib/autoconf/programs.m4
+++ b/lib/autoconf/programs.m4
@@ -421,7 +421,8 @@ m4_define([_AC_PATH_PROGS_FEATURE_CHECK],
   ac_path_$1_found=false
   # Loop through the user's path and test for each of PROGNAME-LIST
   _AS_PATH_WALK([$5],
-  [for ac_prog in $2; do
+  [for ac_prog in $2
+   do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_$1="$as_dir$ac_prog$ac_exec_ext"
       AS_EXECUTABLE_P(["$ac_path_$1"]) || continue
diff --git a/lib/m4sugar/m4sh.m4 b/lib/m4sugar/m4sh.m4
index 91cdeac..a94999e 100644
--- a/lib/m4sugar/m4sh.m4
+++ b/lib/m4sugar/m4sh.m4
@@ -618,9 +618,11 @@ done[]_m4_popdef([$1])])
 # AS_IF(TEST1, [IF-TRUE1 = :]...[IF-FALSE = :])
 # ---------------------------------------------
 # Expand into
-# | if TEST1; then
+# | if TEST1
+# | then
 # |   IF-TRUE1
-# | elif TEST2; then
+# | elif TEST2
+# | then
 # |   IF-TRUE2
 # [...]
 # | else
@@ -629,7 +631,8 @@ done[]_m4_popdef([$1])])
 # with simplifications when IF-TRUE1 and/or IF-FALSE are empty.
 #
 m4_define([_AS_IF],
-[elif $1; then :
+[elif $1
+then :
   $2
 ])
 m4_define([_AS_IF_ELSE],
@@ -639,7 +642,8 @@ m4_define([_AS_IF_ELSE],
 ])])

 m4_defun([AS_IF],
-[if $1; then :
+[if $1
+then :
   $2
 m4_map_args_pair([_$0], [_$0_ELSE], m4_shift2($@))]dnl
 [fi[]])# AS_IF
@@ -1389,7 +1393,8 @@ _ASBOX])
 # Remove all contents from within DIR, including any unwritable
 # subdirectories, but leave DIR itself untouched.
 m4_define([_AS_CLEAN_DIR],
-[if test -d $1; then
+[if test -d $1
+then
   find $1 -type d ! -perm -700 -exec chmod u+rwx {} \;
   rm -fr $1/* $1/.[[!.]] $1/.??*
 fi])
diff --git a/tests/m4sh.at b/tests/m4sh.at
index 5d3b194..5893389 100644
--- a/tests/m4sh.at
+++ b/tests/m4sh.at
@@ -1244,6 +1244,9 @@ AS_IF([false], [:], [ ]) && AS_CASE([foo], [foo], []
 ) && echo seventeen
 m4_define([empty])AS_IF([:], [empty]
 ) && AS_CASE([foo], [foo], [empty]) && echo eighteen
+dnl Allow for users that don't know to avoid trailing whitespace
+AS_IF([:
+], [echo nineteen])
 dnl We can't handle AS_IF([false], [:], [empty]) unless m4_expand is
 dnl taught how to handle m4_require.  The user is responsible for
 dnl avoiding the syntax error in that case.
@@ -1301,6 +1304,7 @@ fifteen
 sixteen
 seventeen
 eighteen
+nineteen
 foo1=1 bar1=1
 foo2=2 bar2=
 foo3=3 bar3=
-- 
1.9.3
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.