m4: Changequote
1
1 8.2 Changing the quote characters
1 =================================
1
1 The default quote delimiters can be changed with the builtin
1 'changequote':
1
1 -- Builtin: changequote ([START = '`'], [END = '''])
1 This sets START as the new begin-quote delimiter and END as the new
1 end-quote delimiter. If both arguments are missing, the default
1 quotes ('`' and ''') are used. If START is void, then quoting is
1 disabled. Otherwise, if END is missing or void, the default
1 end-quote delimiter (''') is used. The quote delimiters can be of
1 any length.
1
1 The expansion of 'changequote' is void.
1
1 changequote(`[', `]')
1 =>
1 define([foo], [Macro [foo].])
1 =>
1 foo
1 =>Macro foo.
1
1 The quotation strings can safely contain eight-bit characters. If no
1 single character is appropriate, START and END can be of any length.
1 Other implementations cap the delimiter length to five characters, but
1 GNU has no inherent limit.
1
1 changequote(`[[[', `]]]')
1 =>
1 define([[[foo]]], [[[Macro [[[[[foo]]]]].]]])
1 =>
1 foo
1 =>Macro [[foo]].
1
1 Calling 'changequote' with START as the empty string will effectively
1 disable the quoting mechanism, leaving no way to quote text. However,
1 using an empty string is not portable, as some other implementations of
1 'm4' revert to the default quoting, while others preserve the prior
1 non-empty delimiter. If START is not empty, then an empty END will use
1 the default end-quote delimiter of ''', as otherwise, it would be
1 impossible to end a quoted string. Again, this is not portable, as some
1 other 'm4' implementations reuse START as the end-quote delimiter, while
1 others preserve the previous non-empty value. Omitting both arguments
1 restores the default begin-quote and end-quote delimiters; fortunately
1 this behavior is portable to all implementations of 'm4'.
1
1 define(`foo', `Macro `FOO'.')
1 =>
1 changequote(`', `')
1 =>
1 foo
1 =>Macro `FOO'.
1 `foo'
1 =>`Macro `FOO'.'
1 changequote(`,)
1 =>
1 foo
1 =>Macro FOO.
1
1 There is no way in 'm4' to quote a string containing an unmatched
1 begin-quote, except using 'changequote' to change the current quotes.
1
1 If the quotes should be changed from, say, '[' to '[[', temporary
1 quote characters have to be defined. To achieve this, two calls of
1 'changequote' must be made, one for the temporary quotes and one for the
1 new quotes.
1
1 Macros are recognized in preference to the begin-quote string, so if
1 a prefix of START can be recognized as part of a potential macro name,
1 the quoting mechanism is effectively disabled. Unless you use
1 'changeword' (⇒Changeword), this means that START should not
1 begin with a letter, digit, or '_' (underscore). However, even though
1 quoted strings are not recognized, the quote characters can still be
1 discerned in macro expansion and in trace output.
1
1 define(`echo', `$@')
1 =>
1 define(`hi', `HI')
1 =>
1 changequote(`q', `Q')
1 =>
1 q hi Q hi
1 =>q HI Q HI
1 echo(hi)
1 =>qHIQ
1 changequote
1 =>
1 changequote(`-', `EOF')
1 =>
1 - hi EOF hi
1 => hi HI
1 changequote
1 =>
1 changequote(`1', `2')
1 =>
1 hi1hi2
1 =>hi1hi2
1 hi 1hi2
1 =>HI hi
1
1 Quotes are recognized in preference to argument collection. In
1 particular, if START is a single '(', then argument collection is
1 effectively disabled. For portability with other implementations, it is
1 a good idea to avoid '(', ',', and ')' as the first character in START.
1
1 define(`echo', `$#:$@:')
1 =>
1 define(`hi', `HI')
1 =>
1 changequote(`(',`)')
1 =>
1 echo(hi)
1 =>0::hi
1 changequote
1 =>
1 changequote(`((', `))')
1 =>
1 echo(hi)
1 =>1:HI:
1 echo((hi))
1 =>0::hi
1 changequote
1 =>
1 changequote(`,', `)')
1 =>
1 echo(hi,hi)bye)
1 =>1:HIhibye:
1
1 However, if you are not worried about portability, using '(' and ')'
1 as quoting characters has an interesting property--you can use it to
1 compute a quoted string containing the expansion of any quoted text, as
1 long as the expansion results in both balanced quotes and balanced
1 parentheses. The trick is realizing 'expand' uses '$1' unquoted, to
1 trigger its expansion using the normal quoting characters, but uses
1 extra parentheses to group unquoted commas that occur in the expansion
1 without consuming whitespace following those commas. Then '_expand'
1 uses 'changequote' to convert the extra parentheses back into quoting
1 characters. Note that it takes two more 'changequote' invocations to
1 restore the original quotes. Contrast the behavior on whitespace when
1 using '$*', via 'quote', to attempt the same task.
1
1 changequote(`[', `]')dnl
1 define([a], [1, (b)])dnl
1 define([b], [2])dnl
1 define([quote], [[$*]])dnl
1 define([expand], [_$0(($1))])dnl
1 define([_expand],
1 [changequote([(], [)])$1changequote`'changequote(`[', `]')])dnl
1 expand([a, a, [a, a], [[a, a]]])
1 =>1, (2), 1, (2), a, a, [a, a]
1 quote(a, a, [a, a], [[a, a]])
1 =>1,(2),1,(2),a, a,[a, a]
1
1 If END is a prefix of START, the end-quote will be recognized in
1 preference to a nested begin-quote. In particular, changing the quotes
1 to have the same string for START and END disables nesting of quotes.
1 When quote nesting is disabled, it is impossible to double-quote strings
1 across macro expansions, so using the same string is not done very
1 often.
1
1 define(`hi', `HI')
1 =>
1 changequote(`""', `"')
1 =>
1 ""hi"""hi"
1 =>hihi
1 ""hi" ""hi"
1 =>hi hi
1 ""hi"" "hi"
1 =>hi" "HI"
1 changequote
1 =>
1 `hi`hi'hi'
1 =>hi`hi'hi
1 changequote(`"', `"')
1 =>
1 "hi"hi"hi"
1 =>hiHIhi
1
1 It is an error if the end of file occurs within a quoted string.
1
1 `hello world'
1 =>hello world
1 `dangling quote
1 ^D
1 error->m4:stdin:2: ERROR: end of file in string
1
1 ifelse(`dangling quote
1 ^D
1 error->m4:stdin:1: ERROR: end of file in string
1