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