autoconf: Balancing Parentheses
1
1 8.1.7 Dealing with unbalanced parentheses
1 -----------------------------------------
1
1 One of the pitfalls of portable shell programming is that `case'
11 statements require unbalanced parentheses (⇒Limitations of Shell
Builtins case.). With syntax highlighting editors, the presence of
1 unbalanced `)' can interfere with editors that perform syntax
1 highlighting of macro contents based on finding the matching `('.
1 Another concern is how much editing must be done when transferring code
1 snippets between shell scripts and macro definitions. But most
1 importantly, the presence of unbalanced parentheses can introduce
1 expansion bugs.
1
1 For an example, here is an underquoted attempt to use the macro
1 `my_case', which happens to expand to a portable `case' statement:
1
1 AC_DEFUN([my_case],
1 [case $file_name in
1 *.c) echo "C source code";;
1 esac])
1 AS_IF(:, my_case)
1
1 In the above example, the `AS_IF' call underquotes its arguments. As a
1 result, the unbalanced `)' generated by the premature expansion of
1 `my_case' results in expanding `AS_IF' with a truncated parameter, and
1 the expansion is syntactically invalid:
1
1 if :; then
1 case $file_name in
1 *.c
1 fi echo "C source code";;
1 esac)
1
1 If nothing else, this should emphasize the importance of the quoting
1 arguments to macro calls. On the other hand, there are several
1 variations for defining `my_case' to be more robust, even when used
1 without proper quoting, each with some benefits and some drawbacks.
1
1 Creative literal shell comment
1 AC_DEFUN([my_case],
1 [case $file_name in #(
1 *.c) echo "C source code";;
1 esac])
1 This version provides balanced parentheses to several editors, and
1 can be copied and pasted into a terminal as is. Unfortunately, it
1 is still unbalanced as an Autoconf argument, since `#(' is an M4
1 comment that masks the normal properties of `('.
1
1 Quadrigraph shell comment
1 AC_DEFUN([my_case],
1 [case $file_name in @%:@(
1 *.c) echo "C source code";;
1 esac])
1 This version provides balanced parentheses to even more editors,
1 and can be used as a balanced Autoconf argument. Unfortunately,
1 it requires some editing before it can be copied and pasted into a
1 terminal, and the use of the quadrigraph `@%:@' for `#' reduces
1 readability.
1
1 Quoting just the parenthesis
1 AC_DEFUN([my_case],
1 [case $file_name in
1 *.c[)] echo "C source code";;
1 esac])
1 This version quotes the `)', so that it can be used as a balanced
1 Autoconf argument. As written, this is not balanced to an editor,
1 but it can be coupled with `[#(]' to meet that need, too.
1 However, it still requires some edits before it can be copied and
1 pasted into a terminal.
1
1 Double-quoting the entire statement
1 AC_DEFUN([my_case],
1 [[case $file_name in #(
1 *.c) echo "C source code";;
1 esac]])
1 Since the entire macro is double-quoted, there is no problem with
1 using this as an Autoconf argument; and since the double-quoting
1 is over the entire statement, this code can be easily copied and
1 pasted into a terminal. However, the double quoting prevents the
1 expansion of any macros inside the case statement, which may cause
1 its own set of problems.
1
1 Using `AS_CASE'
1 AC_DEFUN([my_case],
1 [AS_CASE([$file_name],
1 [*.c], [echo "C source code"])])
1 This version avoids the balancing issue altogether, by relying on
1 `AS_CASE' (⇒Common Shell Constructs); it also allows for the
1 expansion of `AC_REQUIRE' to occur prior to the entire case
1 statement, rather than within a branch of the case statement that
1 might not be taken. However, the abstraction comes with a penalty
1 that it is no longer a quick copy, paste, and edit to get back to
1 shell code.
1