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