From: Eric Blake Date: Fri, 21 Nov 2008 13:35:35 +0000 (-0700) Subject: Move case statement style discussion to m4 quoting section. X-Git-Tag: v2.63b~79 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=54dd8a93795219ca8e51bb58963be5ea64e48d34;p=thirdparty%2Fautoconf.git Move case statement style discussion to m4 quoting section. * doc/autoconf.texi (Limitations of Builtins): Move comparison of quoting styles... (Balancing Parentheses): ...to this new node. Suggested by Ralf Wildenhues. Signed-off-by: Eric Blake --- diff --git a/ChangeLog b/ChangeLog index 83816884c..2ab17570c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2008-11-21 Eric Blake + + Move case statement style discussion to m4 quoting section. + * doc/autoconf.texi (Limitations of Builtins): Move comparison of + quoting styles... + (Balancing Parentheses): ...to this new node. + Suggested by Ralf Wildenhues. + 2008-11-20 Eric Blake Factor more common code out of AT_CHECK into shell function. diff --git a/doc/autoconf.texi b/doc/autoconf.texi index 7a154b796..b3628fb5b 100644 --- a/doc/autoconf.texi +++ b/doc/autoconf.texi @@ -445,6 +445,7 @@ M4 Quotation * Quotation and Nested Macros:: Macros calling macros * Changequote is Evil:: Worse than INTERCAL: M4 + changequote * Quadrigraphs:: Another way to escape special characters +* Balancing Parentheses:: Dealing with unbalanced parentheses * Quotation Rule Of Thumb:: One parenthesis, one quote Using @command{autom4te} @@ -9292,6 +9293,7 @@ former helps one to follow the latter. * Quotation and Nested Macros:: Macros calling macros * Changequote is Evil:: Worse than INTERCAL: M4 + changequote * Quadrigraphs:: Another way to escape special characters +* Balancing Parentheses:: Dealing with unbalanced parentheses * Quotation Rule Of Thumb:: One parenthesis, one quote @end menu @@ -9778,6 +9780,126 @@ invention, and I suppose it could have been a common pun around the Cambridge University computer lab at the time. @end quotation + +@node Balancing Parentheses +@subsection Dealing with unbalanced parentheses +@cindex balancing parentheses +@cindex parentheses, balancing +@cindex unbalanced parentheses, managing + +One of the pitfalls of portable shell programming is that @command{case} +statements require unbalanced parentheses (@pxref{Limitations of +Builtins, , Limitations of Shell Builtins}). With syntax highlighting +editors, the presence of unbalanced @samp{)} can interfere with editors +that perform syntax highlighting of macro contents based on finding the +matching @samp{(}. 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 +@code{my_case}, which happens to expand to a portable @command{case} +statement: + +@example +AC_DEFUN([my_case], +[case $file_name in + *.c) echo "C source code";; +esac]) +AS_IF(:, my_case) +@end example + +@noindent +In the above example, the @code{AS_IF} call underquotes its arguments. +As a result, the unbalanced @samp{)} generated by the premature +expansion of @code{my_case} results in expanding @code{AS_IF} with a +truncated parameter, and the expansion is syntactically invalid: + +@example +if :; then + case $file_name in + *.c +fi echo "C source code";; +esac) +@end example + +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 @code{my_case} to be more robust, even when used +without proper quoting, each with some benefits and some drawbacks. + +@itemize @asis +@item Creative literal shell comment +@example +AC_DEFUN([my_case], +[case $file_name in #( + *.c) echo "C source code";; +esac]) +@end example +@noindent +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 @samp{#(} is an M4 comment +that masks the normal properties of @samp{(}. + +@item Quadrigraph shell comment +@example +AC_DEFUN([my_case], +[case $file_name in @@%:@@( + *.c) echo "C source code";; +esac]) +@end example +@noindent +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 @samp{@@%:@@} for @samp{#} reduces readability. + +@item Quoting just the parenthesis +@example +AC_DEFUN([my_case], +[case $file_name in + *.c[)] echo "C source code";; +esac]) +@end example +@noindent +This version quotes the @samp{)}, 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 @samp{[#(]} to meet that need, too. However, it +still requires some edits before it can be copied and pasted into a +terminal. + +@item Double-quoting the entire statement +@example +AC_DEFUN([my_case], +[[case $file_name in #( + *.c) echo "C source code";; +esac]]) +@end example +@noindent +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. + +@item Using @code{AS_CASE} +@example +AC_DEFUN([my_case], +[AS_CASE([$file_name], + [*.c], [echo "C source code"])]) +@end example +@noindent +This version avoids the balancing issue altogether, by relying on +@code{AS_CASE} (@pxref{Common Shell Constructs}); it also allows for the +expansion of @code{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. +@end itemize + + @node Quotation Rule Of Thumb @subsection Quotation Rule Of Thumb @@ -14901,113 +15023,13 @@ $ @kbd{case foo in (foo) echo foo;; esac} @end example @noindent -@cindex balancing parentheses -@cindex parentheses, balancing The leading @samp{(} can be omitted safely. Unfortunately, there are contexts where unbalanced parentheses cause other problems, such as when using a syntax-highlighting editor that searches for the balancing counterpart, or more importantly, when using a case statement as an -underquoted argument to an Autoconf macro: - -@example -AC_DEFUN([my_case], -[case $file_name in - *.c) echo "C source code";; -esac]) -AS_IF(:, my_case) -@end example - -@noindent -In the above example, the unbalanced @samp{)} in the premature expansion -of @code{my_case} results in expanding @code{AS_IF} with a truncated -parameter, and the expansion is syntactically invalid: - -@example -if :; then - case $file_name in - *.c -fi echo "C source code";; -esac) -@end example - -@noindent -If nothing else, this should emphasize the importance of the quoting -rule of thumb (@pxref{Quotation Rule Of Thumb}), that you should single -quote all macro arguments that might be re-expanded, and double-quote -macro arguments that are literal text. On the other hand, there are -several variations for defining @code{my_case} to be more robust, each -with some benefits and some drawbacks. - -@table @asis -@item Creative literal shell comment -@example -AC_DEFUN([my_case], -[case $file_name in #( - *.c) echo "C source code";; -esac]) -@end example -@noindent -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 @samp{#(} is an M4 comment -that masks the normal properties of @samp{(}. - -@item Quadrigraph shell comment -@example -AC_DEFUN([my_case], -[case $file_name in @@%:@@( - *.c) echo "C source code";; -esac]) -@end example -@noindent -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 @samp{@@%:@@} for @samp{#} reduces readability. - -@item Quoting just the parenthesis -@example -AC_DEFUN([my_case], -[case $file_name in - *.c[)] echo "C source code";; -esac]) -@end example -@noindent -This version quotes the @samp{)}, 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 @samp{[#(]} to meet that need, too. However, it -still requires some edits before it can be copied and pasted into a -terminal. - -@item Double-quoting the entire statement -@example -AC_DEFUN([my_case], -[[case $file_name in #( - *.c) echo "C source code";; -esac]]) -@end example -@noindent -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. - -@item Using @code{AS_CASE} -@example -AC_DEFUN([my_case], -[AS_CASE([$file_name], - [*.c], [echo "C source code"])]) -@end example -@noindent -This version avoids the balancing issue altogether, by relying on -@code{AS_CASE} (@pxref{Common Shell Constructs}); it also allows for the -expansion of @code{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. -@end table +underquoted argument to an Autoconf macro. @xref{Balancing +Parentheses}, for tradeoffs involved in various styles of dealing with +unbalanced @samp{)}. Zsh handles pattern fragments derived from parameter expansions or command substitutions as though quoted: