### Contents of examples/incl.m4 Source: https://www.gnu.org/software/m4/manual/html_node/Include.html Displays the contents of the example file incl.m4 from the m4 distribution, which is used in subsequent examples. It contains the lines 'Include file start', 'foo', and 'Include file end'. ```text $ `cat examples/incl.m4` ⇒Include file start ⇒foo ⇒Include file end ``` -------------------------------- ### Example: Using maketemp and mkstemp to create temporary files Source: https://www.gnu.org/software/m4/manual/html_node/Mkstemp.html Shows the difference between maketemp and mkstemp. The output is random, so the file names will differ. The example also demonstrates how to redefine maketemp to use mkstemp if available, and warns about insecure implementations. ```m4 $ `m4' define(`tmp', `oops') ⇒ maketemp(`/tmp/fooXXXXXX') ⇒/tmp/fooa07346 ifdef(`mkstemp', `define(`maketemp', defn(`mkstemp'))', `define(`mkstemp', defn(`maketemp'))dnl errprint(`warning: potentially insecure maketemp implementation ')') ⇒ mkstemp(`doc') ⇒docQv83Uw ``` -------------------------------- ### Example of m4 example notation Source: https://www.gnu.org/software/m4/manual/html_node/Manual.html Shows a simple example of the fixed-width font used for examples in the manual. ```text This is an example of an example! ``` -------------------------------- ### Example: Comparing maketemp and mkstemp with different templates Source: https://www.gnu.org/software/m4/manual/html_node/Mkstemp.html Demonstrates that maketemp with fewer than six 'X' characters produces a longer result, and that both maketemp and mkstemp generate unique files. The example uses syscmd to remove the created files and checks the exit status. ```m4 $ `m4' define(`foo', `errprint(`oops')') ⇒ syscmd(`rm -f foo-??????')sysval ⇒0 define(`file1', maketemp(`foo-XXXXXX'))dnl ifelse(esyscmd(`echo \` foo-?????? \''), ` foo-?????? ', `no file', `created') ⇒created define(`file2', maketemp(`foo-XX'))dnl define(`file3', mkstemp(`foo-XXXXXX'))dnl ifelse(len(defn(`file1')), len(defn(`file2')), `same length', `different') ⇒same length ifelse(defn(`file1'), defn(`file2'), `same', `different file') ⇒different file ifelse(defn(`file2'), defn(`file3'), `same', `different file') ⇒different file ifelse(defn(`file1'), defn(`file3'), `same', `different file') ⇒different file syscmd(`rm 'defn(`file1') defn(`file2') defn(`file3')) ⇒ sysval ⇒0 ``` -------------------------------- ### Including a file with m4 -I examples Source: https://www.gnu.org/software/m4/manual/html_node/Include.html Shows how to include the file incl.m4 using the -I option to point to the examples directory. The macro foo is defined before inclusion, and the included file's macro call is expanded to FOO. ```m4 $ `m4 -I examples` define(`foo', `FOO') ⇒ include(`incl.m4') ⇒Include file start ⇒FOO ⇒Include file end ⇒ ``` -------------------------------- ### join and joinall usage examples Source: https://www.gnu.org/software/m4/manual/html_node/Shift.html Shows usage of the join and joinall composite macros. join avoids the separator for empty arguments, while joinall always outputs a separator between arguments. The examples are based on the implementation in m4-1.4.20/examples/join.m4. ```m4 $ `m4 -I examples` include(`join.m4') ⇒ join,join(`-'),join(`-', `'),join(`-', `', `') ⇒,,, joinall,joinall(`-'),joinall(`-', `'),joinall(`-', `', `') ⇒,,,- join(`-', `1') ⇒1 join(`-', `1', `2', `3') ⇒1-2-3 join(`', `1', `2', `3') ⇒123 join(`-', `', `1', `', `', `2', `') ⇒1-2 joinall(`-', `', `1', `', `', `2', `') ⇒-1---2- join(`,', `1', `2', `3') ⇒1,2,3 define(`nargs', `$#')dnl nargs(join(`,', `1', `2', `3')) ⇒1 ``` -------------------------------- ### Improved LIFO m4wrap example (wraplifo2.m4) Source: https://www.gnu.org/software/m4/manual/html_node/Improved-m4wrap.html This improved version uses defn to avoid parameter expansion, undefines _m4wrap_text, and reuses a single placeholder. It also emulates GNU M4 by saving all arguments to m4wrap. The example shows the definition and usage, with output demonstrating correct behavior. ```m4 $ `m4 -I examples` include(`wraplifo2.m4') ⇒ undivert(`wraplifo2.m4')dnl ⇒dnl Redefine m4wrap to have LIFO semantics, improved example. ⇒include(`join.m4')dnl ⇒define(`_m4wrap', defn(`m4wrap'))dnl ⇒define(`_arg1', `$1')dnl ⇒define(`m4wrap', ⇒`ifdef(`_$0_text', ⇒ `define(`_$0_text', joinall(` ', $@)defn(`_$0_text'))', ⇒ `_$0(`_arg1(defn(`_$0_text')undefine(`_$0_text'))')dnl ⇒define(`_$0_text', joinall(` ', $@))')')dnl m4wrap(`define(`foo', ``$0:'-$1-$*-$#-')foo(`a', `b') ') ⇒ m4wrap(`lifo text m4wrap(`nested', `', `$@ ') ') ⇒ ^D ⇒lifo text ⇒foo:-a-a,b-2- ⇒nested $@ ``` -------------------------------- ### Gnulib example: gl_STRING_MODULE_INDICATOR macro Source: https://www.gnu.org/software/m4/manual/html_node/Input-processing.html A more complex example from the Gnulib project showing a macro that converts an argument to uppercase and prepends a prefix. The output shows the expansion with leading spaces and the resulting assignment. ```m4 changequote([,])dnl define([gl_STRING_MODULE_INDICATOR], [ dnl comment GNULIB_]translit([$1],[a-z],[A-Z])[=1 ])dnl gl_STRING_MODULE_INDICATOR([strcase]) ⇒ ⇒ GNULIB_strcase=1 ⇒ ``` -------------------------------- ### Usage example of stack_foreach and stack_foreach_lifo Source: https://www.gnu.org/software/m4/manual/html_node/Stacks.html Shows how to use stack_foreach and stack_foreach_lifo to iterate over the definition stack of a macro. The example includes the m4 command line, including the stack.m4 file, defining a macro 'a' with three pushdef definitions, and a show macro that prints each definition. The output demonstrates that stack_foreach visits definitions from oldest to newest, while stack_foreach_lifo visits from newest to oldest. ```m4 $ `m4 -I examples` include(`stack.m4') ⇒ pushdef(`a', `1')pushdef(`a', `2')pushdef(`a', `3') ⇒ define(`show', ``$1' ') ⇒ stack_foreach(`a', `show')dnl ⇒1 ⇒2 ⇒3 stack_foreach_lifo(`a', `show')dnl ⇒3 ⇒2 ⇒1 ``` -------------------------------- ### Macro expansion example with m4 Source: https://www.gnu.org/software/m4/manual/html_node/Macro-expansion.html Demonstrates how defining macros foo and bar results in nested expansion when foo is called. ```bash $ `m4 -Dbar=Hello -Dfoo=bar` foo ⇒Hello ``` -------------------------------- ### Complex foreach example generating a shell case statement Source: https://www.gnu.org/software/m4/manual/html_node/Foreach.html Demonstrates using foreach with a list of lists to generate a shell case statement. The example defines helper macros _case and _cat, then uses foreach to produce the case branches. ```m4 $ `m4 -I examples` include(`foreach.m4') ⇒ define(`_case', ` $1) $2=" $1";; ')dnl define(`_cat', `$1$2')dnl case $`'1 in ⇒case $1 in foreach(`x', `(`(`a', `vara')', `(`b', `varb')', `(`c', `varc')')', `_cat(`_case', x)')dnl ⇒ a) ⇒ vara=" a";; ⇒ b) ⇒ varb=" b";; ⇒ c) ⇒ varc=" c";; esac ⇒esac ``` -------------------------------- ### Trace of original foreachq macro Source: https://www.gnu.org/software/m4/manual/html_node/Improved-foreach.html This example demonstrates the quadratic behavior of the original foreachq implementation by tracing the shift operations. ```m4 $ `m4 -I examples` include(`foreachq.m4') ⇒ traceon(`shift')debugmode(`aq') ⇒ foreachq(`x', ``1', `2', `3', `4'', `x ')dnl ⇒1 error→m4trace: -3- shift(`1', `2', `3', `4') error→m4trace: -2- shift(`1', `2', `3', `4') ⇒2 error→m4trace: -4- shift(`1', `2', `3', `4') error→m4trace: -3- shift(`2', `3', `4') error→m4trace: -3- shift(`1', `2', `3', `4') error→m4trace: -2- shift(`2', `3', `4') ⇒3 error→m4trace: -5- shift(`1', `2', `3', `4') error→m4trace: -4- shift(`2', `3', `4') error→m4trace: -3- shift(`3', `4') error→m4trace: -4- shift(`1', `2', `3', `4') error→m4trace: -3- shift(`2', `3', `4') error→m4trace: -2- shift(`3', `4') ⇒4 error→m4trace: -6- shift(`1', `2', `3', `4') error→m4trace: -5- shift(`2', `3', `4') error→m4trace: -4- shift(`3', `4') error→m4trace: -3- shift(`4') ``` -------------------------------- ### Test foreach and foreachq with various list styles Source: https://www.gnu.org/software/m4/manual/html_node/Improved-foreach.html Run this example with `m4 -I examples` to compare the behavior of `foreach` and `foreachq` on lists with empty elements, commas, unbalanced parentheses, and macros with side effects. The output shows that `foreach` evaluates unquoted list elements once, while `foreachq` from foreachq2.m4 evaluates them twice, which can cause repeated side effects. ```m4 $ `m4 -I examples` include(`foreach2.m4') ⇒ include(`foreachq2.m4') ⇒ dnl 0-element list: foreach(`x', `', `') / foreachq(`x', `', `') ⇒ / dnl 1-element list of empty element foreach(`x', `()', `') / foreachq(`x', ``'', `') ⇒<> / <> dnl 2-element list of empty elements foreach(`x', `(`',`')', `') / foreachq(`x', ``',`'', `') ⇒<><> / <><> dnl 1-element list of a comma foreach(`x', `(`,')', `') / foreachq(`x', ``,'', `') ⇒<,> / <,> dnl 2-element list of unbalanced parentheses foreach(`x', `(`(', `)')', `') / foreachq(`x', ``(', `)'', `') ⇒<(><)> / <(><)> define(`ab', `oops')dnl using defn(`iterator') foreach(`x', `(`a', `b')', `defn(`x')') /dnl foreachq(`x', ``a', `b'', `defn(`x')') ⇒ab / ab define(`active', `ACT, IVE') ⇒ traceon(`active') ⇒ dnl list of unquoted macros; expansion occurs before recursion foreach(`x', `(active, active)', ` ')dnl error→m4trace: -4- active -> `ACT, IVE' error→m4trace: -4- active -> `ACT, IVE' ⇒ ⇒ ⇒ ⇒ foreachq(`x', `active, active', ` ')dnl error→m4trace: -3- active -> `ACT, IVE' error→m4trace: -3- active -> `ACT, IVE' ⇒ error→m4trace: -3- active -> `ACT, IVE' error→m4trace: -3- active -> `ACT, IVE' ⇒ ⇒ ⇒ dnl list of quoted macros; expansion occurs during recursion foreach(`x', `(`active', `active')', ` ')dnl error→m4trace: -1- active -> `ACT, IVE' ⇒ error→m4trace: -1- active -> `ACT, IVE' ⇒ foreachq(`x', ``active', `active'', ` ')dnl error→m4trace: -1- active -> `ACT, IVE' ⇒ error→m4trace: -1- active -> `ACT, IVE' ⇒ dnl list of double-quoted macro names; no expansion foreach(`x', `(``active'', ``active'')', ` ')dnl ⇒ ⇒ foreachq(`x', ```active'', ``active''', ` ')dnl ⇒ ⇒ ``` -------------------------------- ### Redirecting debug output with debugfile Source: https://www.gnu.org/software/m4/manual/html_node/Debug-Output.html Example showing the use of the --debugfile option and the debugfile macro to control trace output destination. ```bash $ `m4 -d` traceon(`divnum') ⇒ divnum(`extra') error→m4:stdin:2: Warning: excess arguments to builtin `divnum' ignored error→m4trace: -1- divnum(`extra') -> `0' ⇒0 debugfile() ⇒ divnum(`extra') error→m4:stdin:4: Warning: excess arguments to builtin `divnum' ignored ⇒0 debugfile ⇒ divnum error→m4trace: -1- divnum -> `0' ⇒0 ``` -------------------------------- ### changequote: Interaction with macro recognition Source: https://www.gnu.org/software/m4/manual/html_node/Changequote.html Macros are recognized in preference to the begin-quote string. If start begins with a letter, digit, or underscore, quoting is effectively disabled. The example shows using 'q', '-', and '1' as start delimiters. ```m4 define(`echo', `$@') ⇒ define(`hi', `HI') ⇒ changequote(`q', `Q') ⇒ q hi Q hi ⇒q HI Q HI echo(hi) ⇒qHIQ changequote ⇒ changequote(`-', `EOF') ⇒ - hi EOF hi ⇒ hi HI changequote ⇒ changequote(`1', `2') ⇒ hi1hi2 ⇒hi1hi2 hi 1hi2 ⇒HI hi ``` -------------------------------- ### Emulate LIFO m4wrap semantics with wraplifo.m4 Source: https://www.gnu.org/software/m4/manual/html_node/M4wrap.html Shows how to include the file m4-1.4.20/examples/wraplifo.m4 to emulate LIFO behavior without using the GNU extension builtin. The example uses undivert to display the file contents, then includes it and demonstrates the LIFO order of saved text. ```m4 $ `m4 -I examples` undivert(`wraplifo.m4')dnl ⇒dnl Redefine m4wrap to have LIFO semantics. ⇒define(`_m4wrap_level', `0')dnl ⇒define(`_m4wrap', defn(`m4wrap'))dnl ⇒define(`m4wrap', ⇒`ifdef(`m4wrap'_m4wrap_level, ⇒ `define(`m4wrap'_m4wrap_level, ⇒ `$1'defn(`m4wrap'_m4wrap_level))', ⇒ `_m4wrap(`define(`_m4wrap_level', incr(_m4wrap_level))dnl ⇒m4wrap'_m4wrap_level)dnl ⇒define(`m4wrap'_m4wrap_level, `$1')')')dnl include(`wraplifo.m4') ⇒ m4wrap(`a`'m4wrap(`c ', `d')')m4wrap(`b') ⇒ ^D ⇒bac ``` -------------------------------- ### Change to m4 installation directory Source: https://www.gnu.org/software/m4/manual/html_node/Manual.html Command to change to the directory where the GNU M4 package was unpacked, as suggested for following along with examples. ```shell $ `cd m4-1.4.20` ``` -------------------------------- ### changecom: Comments take precedence over argument collection Source: https://www.gnu.org/software/m4/manual/html_node/Changecom.html Comments are recognized in preference to argument collection. If start is a single '(', argument collection is effectively disabled. This example shows how different delimiters affect macro argument parsing. ```m4 define(`echo', `$#:$*:$@:') ⇒ define(`hi', `HI') ⇒ changecom(`(',`)') ⇒ echo(hi) ⇒0:::(hi) changecom ⇒ changecom(`((', `))') ⇒ echo(hi) ⇒1:HI:HI: echo((hi)) ⇒0:::((hi)) changecom(`,', `)') ⇒ echo(hi,hi)bye) ⇒1:HI,hi)bye:HI,hi)bye: changecom ⇒ echo(hi,`,`'hi',hi) ⇒3:HI,,HI,HI:HI,,`'hi,HI: echo(hi,`,`'hi',hi`'changecom(`,,', `hi')) ⇒3:HI,,`'hi,HI:HI,,`'hi,HI: ``` -------------------------------- ### format examples with various specifiers Source: https://www.gnu.org/software/m4/manual/html_node/Format.html Shows basic usage of the format builtin with %s, %d, %*.*d, %.0f, %-*X, %010F, %.1A, and %g specifiers. Demonstrates output for each call, including handling of infinity and hexadecimal floating point. Note that format is recognized only with parameters. ```m4 define(`foo', `The brown fox jumped over the lazy dog') ⇒ format(`The string "%s" uses %d characters', foo, len(foo)) ⇒The string "The brown fox jumped over the lazy dog" uses 38 characters format(`%*.*d', `-1', `-1', `1') ⇒1 format(`%.0f', `56789.9876') ⇒56790 len(format(`%-*X', `5000', `1')) ⇒5000 ifelse(format(`%010F', `infinity'), ` INF', `success', format(`%010F', `infinity'), ` INFINITY', `success', format(`%010F', `infinity')) ⇒success ifelse(format(`%.1A', `1.999'), `0X1.0P+1', `success', format(`%.1A', `1.999'), `0X2.0P+0', `success', format(`%.1A', `1.999')) ⇒success format(`%g', `0xa.P+1') ⇒20 ``` -------------------------------- ### Demonstrate curry with stack_foreach and reverse Source: https://www.gnu.org/software/m4/manual/html_node/Composition.html Uses the included examples/curry.m4 and stack.m4 to show currying: stack_foreach provides one argument, and curry appends it to the original arguments to invoke reverse with two arguments. Also shows nested curry calls. ```m4 $ `m4 -I examples' include(`curry.m4')include(`stack.m4') ⇒ define(`reverse', `ifelse(`$#', `0', , `$#', `1', ``$1'', `reverse(shift($@)), `$1'')') ⇒ pushdef(`a', `1')pushdef(`a', `2')pushdef(`a', `3') ⇒ stack_foreach(`a', `:curry(`reverse', `4')') ⇒:1, 4:2, 4:3, 4 curry(`curry', `reverse', `1')(`2')(`3') ⇒3, 2, 1 ``` -------------------------------- ### Tightening lexical rules to prevent accidental builtin calls Source: https://www.gnu.org/software/m4/manual/html_node/Changeword.html Example showing how to restrict macro names to those starting with underscore, preventing accidental calls to builtins like esyscmd. Uses indir to still invoke builtins intentionally. ```m4 ifdef(`changeword', `', `errprint(` skipping: no changeword support ')m4exit(`77')')dnl define(`_indir', defn(`indir')) ⇒ changeword(`_[_a-zA-Z0-9]*') ⇒ esyscmd(`foo') ⇒esyscmd(foo) _indir(`esyscmd', `echo hi') ⇒hi ⇒ ``` -------------------------------- ### changecom([start], [end = '`NL`']) Source: https://www.gnu.org/software/m4/manual/html_node/Changecom.html Sets the begin-comment delimiter to start and the end-comment delimiter to end. If both arguments are missing or start is void, comments are disabled. If end is missing or void, the default end-comment delimiter of newline is used. The expansion is void. ```APIDOC ## changecom([start], [end = '`NL`']) ### Description Sets the begin-comment delimiter to start and the end-comment delimiter to end. If both arguments are missing or start is void, comments are disabled. If end is missing or void, the default end-comment delimiter of newline is used. The expansion is void. ### Method Builtin macro ### Syntax changecom([start], [end = '`NL`']) ### Parameters - **start** (string) - Optional - The new begin-comment delimiter. If missing or void, comments are disabled. - **end** (string) - Optional - The new end-comment delimiter. Defaults to newline if missing or void. ### Behavior - If both arguments are missing, or start is void, comments are disabled. - If end is missing or void, the default end-comment delimiter of newline is used. - The comment delimiters can be of any length. - Comments are recognized in preference to macros and argument collection. - It is an error if the end of file occurs within a comment. ### Expansion Void. ### Examples ``` define(`comment', `COMMENT') ⇒ # A normal comment ⇒# A normal comment changecom(`/*', `*/') ⇒ # Not a comment anymore ⇒# Not a COMMENT anymore But: /* this is a comment now */ while this is not a comment ⇒But: /* this is a comment now */ while this is not a COMMENT ``` ``` define(`comment', `COMMENT') ⇒ changecom ⇒ # Not a comment anymore ⇒# Not a COMMENT anymore changecom(`#', `') ⇒ # comment again ⇒# comment again ``` ``` define(`a', `b') ⇒ «a» ⇒«b» changecom(`«', `»') ⇒ «a» ⇒«a» ``` ``` define(`hi', `HI') ⇒ define(`hi1hi2', `hello') ⇒ changecom(`q', `Q') ⇒ q hi Q hi ⇒q hi Q HI changecom(`1', `2') ⇒ hi1hi2 ⇒hello hi 1hi2 ⇒HI 1hi2 ``` ``` define(`echo', `$#:$*:$@:') ⇒ define(`hi', `HI') ⇒ changecom(`(',`)') ⇒ echo(hi) ⇒0:::(hi) changecom ⇒ changecom(`((', `))') ⇒ echo(hi) ⇒1:HI:HI: echo((hi)) ⇒0:::((hi)) changecom(`,', `)') ⇒ echo(hi,hi)bye) ⇒1:HI,hi)bye:HI,hi)bye: changecom ⇒ echo(hi,`,`'hi',hi) ⇒3:HI,,HI,HI:HI,,`'hi,HI: echo(hi,`,`'hi',hi`'changecom(`,,', `hi')) ⇒3:HI,,`'hi,HI:HI,,`'hi,HI: ``` ### Error Handling - If the end of file occurs within a comment, an error is raised. ``` changecom(`/*', `*/') ⇒ /*dangling comment ^D error→m4:stdin:2: ERROR: end of file in comment ``` ``` -------------------------------- ### Using same start and end quote to disable nesting Source: https://www.gnu.org/software/m4/manual/html_node/Changequote.html Demonstrates that when the end quote is a prefix of the start quote, the end quote is recognized in preference to a nested begin quote, disabling nesting. Using the same string for start and end disables nesting, making it impossible to double-quote strings across macro expansions, so it is not used often. ```m4 define(`hi', `HI') ⇒ changequote(`""', `"') ⇒ ""hi"""hi" ⇒hihi ""hi" ""hi" ⇒hi hi ""hi"" "hi" ⇒hi" "HI" changequote ⇒ `hi`hi'hi' ⇒hi`hi'hi changequote(`"', `"') ⇒ "hi"hi"hi" ⇒hiHIhi ``` -------------------------------- ### Emulate FIFO m4wrap semantics with wrapfifo.m4 Source: https://www.gnu.org/software/m4/manual/html_node/M4wrap.html Shows how to include the file m4-1.4.20/examples/wrapfifo.m4 to emulate POSIX FIFO behavior with older GNU M4 versions. The example uses undivert to display the file contents, then includes it and demonstrates the FIFO order of saved text. ```m4 $ `m4 -I examples` undivert(`wrapfifo.m4')dnl ⇒dnl Redefine m4wrap to have FIFO semantics. ⇒define(`_m4wrap_level', `0')dnl ⇒define(`m4wrap', ⇒`ifdef(`m4wrap'_m4wrap_level, ⇒ `define(`m4wrap'_m4wrap_level, ⇒ defn(`m4wrap'_m4wrap_level)`$1')', ⇒ `builtin(`m4wrap', `define(`_m4wrap_level', ⇒ incr(_m4wrap_level))dnl ⇒m4wrap'_m4wrap_level)dnl ⇒define(`m4wrap'_m4wrap_level, `$1')')')dnl include(`wrapfifo.m4') ⇒ m4wrap(`a`'m4wrap(`c ', `d')')m4wrap(`b') ⇒ ^D ⇒abc ``` -------------------------------- ### Basic usage of foreach and foreachq Source: https://www.gnu.org/software/m4/manual/html_node/Foreach.html Shows how to use foreach and foreachq to iterate over a list and append text for each element. The output displays each word in a sentence. The macros are included from the files foreach.m4 and foreachq.m4. ```m4 $ `m4 -I examples` include(`foreach.m4') ⇒ foreach(`x', (foo, bar, foobar), `Word was: x ')dnl ⇒Word was: foo ⇒Word was: bar ⇒Word was: foobar include(`foreachq.m4') ⇒ foreachq(`x', `foo, bar, foobar', `Word was: x ')dnl ⇒Word was: foo ⇒Word was: bar ⇒Word was: foobar ``` -------------------------------- ### Debug flags not related to macro tracing Source: https://www.gnu.org/software/m4/manual/html_node/Debug-Levels.html This example shows the effects of the debug flags that are not related to macro tracing, using -dip and -I examples. It demonstrates the debug output for input file changes and path search. ```shell $ `m4 -dip -I examples` error→m4debug: input read from stdin include(`foo')dnl error→m4debug: path search for `foo' found `examples/foo' error→m4debug: input read from examples/foo ⇒bar error→m4debug: input reverted to stdin, line 1 ^D error→m4debug: input exhausted ``` -------------------------------- ### divnum example: initial value and after divert Source: https://www.gnu.org/software/m4/manual/html_node/Divnum.html Shows that divnum expands to 0 initially, and after diverting to diversion 1 and 2, divnum expands to 1 and 2 respectively. The example uses the divert builtin to change the current diversion. ```m4 Initial divnum divert(`1') Diversion one: divnum divert(`2') Diversion two: divnum ^D ⇒ ⇒Diversion one: 1 ⇒ ⇒Diversion two: 2 ``` -------------------------------- ### substr(string, from, [length]) Source: https://www.gnu.org/software/m4/manual/html_node/Substr.html Expands to the substring of string starting at index from, extending for length characters or to the end of string if length is omitted. The starting index is 0. Returns empty on error or if from is beyond the end of string or length is negative. ```APIDOC ## substr(string, from, [length]) ### Description Expands to the substring of string, which starts at index from, and extends for length characters, or to the end of string, if length is omitted. The starting index of a string is always 0. The expansion is empty if there is an error parsing from or length, if from is beyond the end of string, or if length is negative. ### Parameters - **string** (string) - Required - The input string from which to extract a substring. - **from** (integer) - Required - The starting index (0-based) of the substring. - **length** (integer) - Optional - The number of characters to extract. If omitted, the substring extends to the end of string. ### Behavior - The macro is recognized only with parameters. - Omitting from evokes a warning, but still produces output. ### Examples ``` substr(`gnus, gnats, and armadillos', `6') ⇒gnats, and armadillos substr(`gnus, gnats, and armadillos', `6', `5') ⇒gnats ``` ### Warning Example ``` substr(`abc') error→m4:stdin:1: Warning: too few arguments to builtin `substr' ⇒abc substr(`abc',) error→m4:stdin:2: empty string treated as 0 in builtin `substr' ⇒abc ``` ``` -------------------------------- ### join.m4 implementation Source: https://www.gnu.org/software/m4/manual/html_node/Shift.html Displays the implementation of join and joinall from the file join.m4, using undivert. It shows the internal helper macros _join and _joinall. ```m4 $ `m4 -I examples` undivert(`join.m4')dnl ⇒divert(`-1') ⇒# join(sep, args) - join each non-empty ARG into a single ⇒# string, with each element separated by SEP define(`join', `ifelse(`$#', `2', ``$2'', `ifelse(`$2', `', `', ``$2'_')$0(`$1', shift(shift($@)))')') define(`_join', `ifelse(`$#$2', `2', `', `ifelse(`$2', `', `', ``$1$2'')$0(`$1', shift(shift($@)))')') ⇒# joinall(sep, args) - join each ARG, including empty ones, ⇒# into a single string, with each element separated by SEP define(`joinall', ``$2'_$0(`$1', shift($@))') define(`_joinall', `ifelse(`$#', `2', `', ``$1$3'$0(`$1', shift(shift($@)))')') ⇒divert`'dnl ``` -------------------------------- ### Define and use define_blind to create blind macros Source: https://www.gnu.org/software/m4/manual/html_node/Composition.html Shows the definition of define_blind and its helper _define_blind, then demonstrates usage: define_blind is itself blind, foo is defined as blind and expands only with arguments, and renaming with defn works. Note the limitation against using defn for builtins. ```m4 $ `m4 -d' define(`define_blind', `ifelse(`$#', `0', ``$0'', `_$0(`$1', `$2', `$'`#', `$'`0')')') ⇒ define(`_define_blind', `define(`$1', `ifelse(`$3', `0', ``$4'', `$2')')') ⇒ define_blind ⇒define_blind define_blind(`foo', `arguments were $*') ⇒ foo ⇒foo foo(`bar') ⇒arguments were bar define(`blah', defn(`foo')) ⇒ blah ⇒blah blah(`a', `b') ⇒arguments were a,b defn(`blah') ⇒ifelse(`$#', `0', ``$0'', `arguments were $*') ``` -------------------------------- ### changequote([start = '`'], [end = ''']) Source: https://www.gnu.org/software/m4/manual/html_node/Changequote.html Sets the begin-quote and end-quote delimiters used by m4. The expansion is void. If both arguments are missing, the default quotes are restored. If start is void, quoting is disabled. If end is missing or void, the default end-quote delimiter is used. ```APIDOC ## changequote([start = '`'], [end = ''']) ### Description Sets the begin-quote and end-quote delimiters used by m4. The expansion is void. If both arguments are missing, the default quotes are restored. If start is void, quoting is disabled. If end is missing or void, the default end-quote delimiter is used. ### Method Builtin ### Parameters - **start** (string) - Optional - The new begin-quote delimiter. Default is '`'. - **end** (string) - Optional - The new end-quote delimiter. Default is '''. ### Behavior - If both arguments are missing, the default quotes (``` and ''') are used. - If start is void, quoting is disabled. - If end is missing or void, the default end-quote delimiter (''') is used. - The quote delimiters can be of any length. - The quotation strings can safely contain non-ASCII characters. - Calling changequote with start as the empty string effectively disables the quoting mechanism. - If start is not empty, an empty end will use the default end-quote delimiter. - Omitting both arguments restores the default begin-quote and end-quote delimiters. ### Expansion void ### Examples ``` changequote(`[', `]') ⇒ define([foo], [Macro [foo].]) ⇒ foo ⇒Macro foo. ``` ``` define(`a', `b') ⇒ «a» ⇒«b» changequote(`«', `»') ⇒ «a» ⇒a ``` ``` changequote(`[[[', `]]]') ⇒ define([[[foo]]], [[[Macro [[[[[foo]]]]].]]]) ⇒ foo ⇒Macro [[foo]]. ``` ``` define(`foo', `Macro `FOO'.') ⇒ changequote(`', `') ⇒ foo ⇒Macro `FOO'. `foo' ⇒`Macro `FOO'.' changequote(`,) ⇒ foo ⇒Macro FOO. ``` ``` define(`echo', `$@') ⇒ define(`hi', `HI') ⇒ changequote(`q', `Q') ⇒ q hi Q hi ⇒q HI Q HI echo(hi) ⇒qHIQ changequote ⇒ changequote(`-', `EOF') ⇒ - hi EOF hi ⇒ hi HI changequote ⇒ changequote(`1', `2') ⇒ hi1hi2 ⇒hi1hi2 hi 1hi2 ⇒HI hi ``` ``` define(`echo', `$#:$@:') ⇒ define(`hi', `HI') ⇒ changequote(`(',`)') ⇒ echo(hi) ⇒0::hi changequote ⇒ changequote(`((', `))') ⇒ echo(hi) ⇒1:HI: echo((hi)) ⇒0::hi changequote ⇒ changequote(`,', `)') ⇒ echo(hi,hi)bye) ⇒1:HIhibye: ``` ``` -------------------------------- ### Location macros with include and -I option Source: https://www.gnu.org/software/m4/manual/html_node/Location.html Demonstrates that __file__ and __line__ reflect the file found via the -I option (here 'examples/incl.m4') and the line number within that file. The example uses the file incl.m4 mentioned earlier. ```m4 $ `m4 -I examples' define(`foo', ``$0' called at __file__:__line__') ⇒ foo ⇒foo called at stdin:2 include(`incl.m4') ⇒Include file start ⇒foo called at examples/incl.m4:2 ⇒Include file end ⇒ ``` -------------------------------- ### Usage of quote, dquote, and dquote_elt macros Source: https://www.gnu.org/software/m4/manual/html_node/Shift.html Demonstrates the behavior of quoting macros when provided with different numbers of arguments. ```m4 $ `m4 -I examples` include(`quote.m4') ⇒ -quote-dquote-dquote_elt- ⇒---- -quote()-dquote()-dquote_elt()-- ⇒--`'-`'- -quote(`1')-dquote(`1')-dquote_elt(`1')- ⇒-1-`1'-`1'- -quote(`1', `2')-dquote(`1', `2')-dquote_elt(`1', `2')- ⇒-1,2-`1',`2'-`1',`2'- define(`n', `$#')dnl -n(quote(`1', `2'))-n(dquote(`1', `2'))-n(dquote_elt(`1', `2'))- ⇒-1-1-2- dquote(dquote_elt(`1', `2')) ⇒``1'',``2'' dquote_elt(dquote(`1', `2')) ⇒``1',`2'' ``` -------------------------------- ### changequote: Disable quoting with empty start Source: https://www.gnu.org/software/m4/manual/html_node/Changequote.html Calling changequote with an empty start disables quoting, leaving no way to quote text. Using an empty string is not portable; other m4 implementations may revert to default or preserve prior delimiters. Omitting both arguments restores defaults portably. ```m4 define(`foo', `Macro `FOO'.') ⇒ changequote(`', `') ⇒ foo ⇒Macro `FOO'. `foo' ⇒`Macro `FOO'.' changequote(`,) ⇒ foo ⇒Macro FOO. ``` -------------------------------- ### builtin with --prefix-builtins option Source: https://www.gnu.org/software/m4/manual/html_node/Builtin.html Demonstrates that `builtin` matches the original builtin name even when the `--prefix-builtins` (or `-P`) option is in effect. The example shows that `m4_builtin` works with the unprefixed name, while `m4_indir` requires the prefixed name. ```m4 $ `m4 -P` m4_builtin(`divnum') ⇒0 m4_builtin(`m4_divnum') error→m4:stdin:2: undefined builtin `m4_divnum' ⇒ m4_indir(`divnum') error→m4:stdin:3: undefined macro `divnum' ⇒ m4_indir(`m4_divnum') ⇒0 ``` -------------------------------- ### m4exit usage example Source: https://www.gnu.org/software/m4/manual/html_node/M4exit.html Demonstrates how m4exit discards wrapped and diverted text when called. ```m4 m4wrap(`This text is lost due to `m4exit'.') ⇒ divert(`1') So is this. divert ⇒ m4exit And this is never read. ``` -------------------------------- ### Implementation of forloop.m4 Source: https://www.gnu.org/software/m4/manual/html_node/Forloop.html The source code for the forloop macro implementation as distributed in the m4 examples package. ```m4 $ `m4 -I examples` undivert(`forloop.m4')dnl ⇒divert(`-1') ⇒# forloop(var, from, to, stmt) - simple version ⇒define(`forloop', `pushdef(`$1', `$2')_forloop($@)popdef(`$1')') ⇒define(`_forloop', ⇒ `$4`'ifelse($1, `$3', `', `define(`$1', incr($1))$0($@)')') ⇒divert`'dnl ```