m4: Forloop
1
1 6.4 Iteration by counting
1 =========================
1
1 Here is an example of a loop macro that implements a simple for loop.
1
1 -- Composite: forloop (ITERATOR, START, END, TEXT)
1 Takes the name in ITERATOR, which must be a valid macro name, and
1 successively assign it each integer value from START to END,
1 inclusive. For each assignment to ITERATOR, append TEXT to the
1 expansion of the 'forloop'. TEXT may refer to ITERATOR. Any
1 definition of ITERATOR prior to this invocation is restored.
1
1 It can, for example, be used for simple counting:
1
1 $ m4 -I examples
1 include(`forloop.m4')
1 =>
1 forloop(`i', `1', `8', `i ')
1 =>1 2 3 4 5 6 7 8
1
1 For-loops can be nested, like:
1
1 $ m4 -I examples
1 include(`forloop.m4')
1 =>
1 forloop(`i', `1', `4', `forloop(`j', `1', `8', ` (i, j)')
1 ')
1 => (1, 1) (1, 2) (1, 3) (1, 4) (1, 5) (1, 6) (1, 7) (1, 8)
1 => (2, 1) (2, 2) (2, 3) (2, 4) (2, 5) (2, 6) (2, 7) (2, 8)
1 => (3, 1) (3, 2) (3, 3) (3, 4) (3, 5) (3, 6) (3, 7) (3, 8)
1 => (4, 1) (4, 2) (4, 3) (4, 4) (4, 5) (4, 6) (4, 7) (4, 8)
1 =>
1
1 The implementation of the 'forloop' macro is fairly straightforward.
1 The 'forloop' macro itself is simply a wrapper, which saves the previous
1 definition of the first argument, calls the internal macro '_forloop',
1 and re-establishes the saved definition of the first argument.
1
1 The macro '_forloop' expands the fourth argument once, and tests to
1 see if the iterator has reached the final value. If it has not
1 finished, it increments the iterator (using the predefined macro 'incr',
1 ⇒Incr), and recurses.
1
1 Here is an actual implementation of 'forloop', distributed as
1 'm4-1.4.18/examples/forloop.m4' in this package:
1
1 $ m4 -I examples
1 undivert(`forloop.m4')dnl
1 =>divert(`-1')
1 =># forloop(var, from, to, stmt) - simple version
1 =>define(`forloop', `pushdef(`$1', `$2')_forloop($@)popdef(`$1')')
1 =>define(`_forloop',
1 => `$4`'ifelse($1, `$3', `', `define(`$1', incr($1))$0($@)')')
1 =>divert`'dnl
1
1 Notice the careful use of quotes. Certain macro arguments are left
1 unquoted, each for its own reason. Try to find out _why_ these
1 arguments are left unquoted, and see what happens if they are quoted.
1 (As presented, these two macros are useful but not very robust for
1 general use. They lack even basic error handling for cases like START
1 less than END, END not numeric, or ITERATOR not being a macro name. See
1 if you can improve these macros; or ⇒Answers Improved forloop.).
1