Next: , Previous: Conditional constructs, Up: Programming in M4sugar


8.3.5 Looping constructs

The following macros are useful in implementing recursive algorithms in M4, including loop operations. An M4 list is formed by quoting a list of quoted elements; generally the lists are comma-separated, although m4_foreach_w is whitespace-separated. For example, the list `[[a], [b,c]]' contains two elements: `[a]' and `[b,c]'. It is common to see lists with unquoted elements when those elements are not likely to be macro names, as in `[fputc_unlocked, fgetc_unlocked]'.

— Macro: m4_car (list)

Expands to the quoted first element of the comma-separated quoted list. Often used with m4_cdr to recursively iterate through a list. Generally, when using quoted lists of quoted elements, m4_car should be called without any extra quotes.

— Macro: m4_cdr (list)

Expands to a quoted list of all but the first element of the comma-separated quoted list, or the empty string if list had only one element. Generally, when using quoted lists of quoted elements, m4_cdr should be called without any extra quotes.

For example, this is a simple implementation of m4_map; note how each iteration checks for the end of recursion, then merely applies the first argument to the first element of the list, then repeats with the rest of the list. (The actual implementation in M4sugar is a bit more involved, to gain some speed and share code with m4_map_sep).

          m4_define([m4_map], [m4_ifval([$2],
            [m4_apply([$1], m4_car($2))[]$0([$1], m4_cdr($2))])])dnl
          m4_map([ m4_eval], [[[1]], [[1+1]], [[10],[16]]])
          => 1 2 a
     
— Macro: m4_for (var, first, last, [step], expression)

Loop over the numeric values between first and last including bounds by increments of step. For each iteration, expand expression with the numeric value assigned to var. If step is omitted, it defaults to `1' or `-1' depending on the order of the limits. If given, step has to match this order.

— Macro: m4_foreach (var, list, expression)

Loop over the comma-separated M4 list list, assigning each value to var, and expand expression. The following example outputs two lines:

          m4_foreach([myvar], [[foo], [bar, baz]],
                     [echo myvar
          ])dnl
          =>echo foo
          =>echo bar, baz
     

— Macro: m4_foreach_w (var, list, expression)

Loop over the white-space-separated list list, assigning each value to var, and expand expression.

The deprecated macro AC_FOREACH is an alias of m4_foreach_w.

— Macro: m4_map (macro, list)
— Macro: m4_map_sep (macro, separator, list)

Loop over the comma separated quoted list of argument descriptions in list, and invoke macro with the arguments. An argument description is in turn a comma-separated quoted list of quoted elements, suitable for m4_apply, making it possible to invoke macro without arguments if an argument description is empty. m4_map_sep additionally outputs separator between macro invocations, with no additional expansion of the separator.

          m4_map([m4_count], [])
          =>
          m4_map([ m4_count], [[],
                               [[1]],
                               [[1], [2]]])
          => 0 1 2
          m4_map_sep([m4_eval], [,], [[[1+2]],
                                      [[10], [16]]])
          =>3,a
     
— Macro: m4_shiftn (count, ...)
— Macro: m4_shift2 (...)
— Macro: m4_shift3 (...)

m4_shiftn performs count iterations of m4_shift, along with validation that enough arguments were passed in to match the shift count, and that the count is positive. m4_shift2 and m4_shift3 are specializations of m4_shiftn, introduced in Autoconf 2.62, and are more efficient for two and three shifts, respectively.