A.4 Replicate m4 Macros

The main documentation of the Replicate m4 Macros contains additional explanation of this code listing.

```dnl
dnl Author: Michael L. Hall
dnl         P.O. Box 1663, MS-D409, LANL
dnl         Los Alamos, NM 87545
dnl         ph: 505-665-4312
dnl         email: hall@lanl.gov
dnl
dnl Created on: 12/04/98
dnl Date:       03/21/00, 17:18:38
dnl Version:    4.9

dnl Define the REPLICATE macro.

define([REPLICATE],[
forloop([i], 0, 7, [define([REP_NUMBER],[i]) REPLICATE_ROUTINE(i)])
])

dnl Define the REPLICATE_ARRAYS macro.

define([REPLICATE_ARRAYS],[
forloop([i], 1, 7, [define([REP_NUMBER],[i]) REPLICATE_ROUTINE(i)])
])

dnl Define the ARRAY_ONLY macro.

define([ARRAY_ONLY],
[ifelse(
[0], REP_NUMBER,
[!],
[])])

dnl Define the SCALAR_ONLY macro.

define([SCALAR_ONLY],
[ifelse(
[0], REP_NUMBER,
[],
[!])])

dnl Define the REP_EXPAND command, which expands text with a glorified do-loop.
dnl The arguments are:
dnl
dnl   REP_NUMBER - The number of iterations.
dnl   \$1 - Beginning text that is present if the iteration count is non-zero.
dnl   \$2 - The text to be repeated in each iteration. The iteration variable,
dnl        i, may be used in this text.
dnl   \$3 - Separator text to be put between iterations.
dnl   \$4 - Final text that is present if the iteration count is non-zero.
dnl
dnl So, an iteration count of "0" yields no output, and an iteration count
dnl of "4" yields:
dnl
dnl   \$1\$2\$3\$2\$3\$2\$3\$2\$4
dnl
dnl Note that the separator text (\$3) appears only 3 times.

define([REP_EXPAND],
[ifelse([0], REP_NUMBER,
[],
[\$1[]forloop([i], 1, 1, [\$2])])dnl
ifelse(m4_eval(REP_NUMBER >= 2), 1,
[forloop([i], 2, REP_NUMBER, [\$3][\$2])])dnl
ifelse([0], REP_NUMBER,
[],
[\$4])])

dnl Define the REPLICATE_INTERFACE macro.

define([REPLICATE_INTERFACE],[
interface \$1
forloop([i], 0, 7, [    module procedure \$2_[]i
])dnl
end interface
])

dnl Define some useful macros based on the REP_EXPAND macro.

dnl REP_DECLARE:    form -->  real :: var1, var2, var3
dnl
dnl  \$1 - Declaration type (everything up to the double colon).
dnl  \$2 - Variable name to replicate, which should contain an "i"
dnl       for the iteration number.

define([REP_DECLARE],
[REP_EXPAND([\$1 :: ], [\$2], [, ], [])])

dnl REP_ALLOCATE:   form -->  ALLOCATE(R(var1, var2, var3))
dnl
dnl  \$1 - Variable to allocate.
dnl  \$2 - Dimensioning variable name to replicate, which should
dnl       contain an "i" for the iteration number.
dnl  \$3 - Name for the status variable.

define([REP_ALLOCATE],
[REP_EXPAND([ALLOCATE(\$1(], [\$2], [, ], [), stat=\$3)])])

dnl REP_ARGS:     form -->  , var1, var2, var3
dnl
dnl  \$1 - Variable name to replicate, which should contain an "i"
dnl       for the iteration number.

define([REP_ARGS],
[REP_EXPAND([, ], [\$1], [, ], [])])

dnl Input text used to generate documentation:

dnl module test_replicate
dnl   REPLICATE_INTERFACE([Generic_Routine], [Specific_Routine])
dnl contains
dnl
dnl define([REPLICATE_ROUTINE],[
dnl   function Specific_Routine_\$1 (R[]REP_ARGS([var[]i]))
dnl     type(real,\$1) :: R
dnl     REP_DECLARE([type(integer)], [var[]i])
dnl     REP_ALLOCATE(R, [var[]i], [status])
dnl     ARRAY_ONLY DEALLOCATE(R)
dnl     SCALAR_ONLY R = 999.
dnl     <other routine contents>
dnl   end function Specific_Routine_\$1
dnl
dnl ])
dnl REPLICATE
dnl end module test_replicate
```

Michael L. Hall