M4KWARGS - keyword argument support for m4 macros ================================================= M4kwargs is a macro package that implements keyword arguments for m4 macros. It relies on the patsubst builtin, which is available at least in GNU m4 and in FreeBSD m4. This package has been tested with these two implementations. Installation ============ After unpacking the tarball, run "make check". If all tests pass, proceed to installation. Otherwise, feel free to send a report to the author. See below for the contact information. To install the package, run "make install". The name of the installation target directory is described in Makefile terms as $(DESTDIR)$(PREFIX)/share/$(M4DIR) Default values for these variables are: $(DESTDIR) (empty) $(PREFIX) /usr/local $(M4DIR) m4kwargs To change the installation directory, override any or all of these in the make command line. E.g. to install to /usr/share/m4, do make install PREFIX=/usr M4DIR=m4 Another noteworthy installation variable is BRACKETQUOTES. By default, m4kwargs assumes standard m4 quotes (`'). You can change them to [] when installing the package by declaring BRACKETQUOTES=1: make install BRACKETQUOTES=1 Usage ===== It is supposed that the pathname of the installation directory is added to the m4 search path using the -I command line option, if your version of m4 supports it. If not, run m4 from the installation directory. Include the file kwargs.m4 at the top of your source file: include(kwargs.m4) This will do the following: 1. Check if m4 provides the patsubst builtin. If not, an error message will be printed and m4 will terminate with exit status 1. 2. Check if patsubst takes a basic or extended regular expression as its second argument. 3. Prefix all built-in m4 identifiers with m4_. Note to GNU m4 users: don't use the -P (--prefix-builtins) option, as it will interfere with this step. 4. Load the package macros. All these steps are performed in a diversion, so that they add nothing to the output. The basic way of declaring keyword arguments is by using the KWARGS_ASGN macro. This macro takes as its arguments a comma-delimited list of keyword=value assignments. Its expansion is empty. Suppose you want to write a macro INCR, that takes a single numeric argument and expands to its value incremented by one. If a keyword argument `delta' is supplied, the macro will expand to its argument incremented by that value, so that INCR(4) => 5 INCR(4,delta=2) => 6 Here is how to declare such macro: m4_define(`INCR', `KWARGS_ASGN(m4_shift($@))m4_eval($1 + KWARG_VALUE(`delta',1))') The KWARG_VALUE macro expands to the value of the keyword argument named by its first parameter, if it is defined, and to its second parameter otherwise. This definition has a drawback that keywords assigned by KWARGS_ASGN will remain in effect after the macro has been expanded. To avoid this, use the KWARGS_PUSH/KWARGS_POP pair, as shown below: m4_define(`INCR', `KWARGS_PUSH(m4_shift($@))m4_eval($1 + KWARG_VALUE(`delta',1))KWARGS_POP') The package provides a special macro KW_DEFINE, for defining macros that make use of keyword arguments. The basic usage is the same as for m4_define: KW_DEFINE(NAME, TEXT) The KW_DEFINE macro takes care to wrap the expansion of TEXT in KWARGS_PUSH and KWARGS_POP. There is one special thing about it: TEXT should refer to positional arguments using the notation KW_ARGV(N), instead of the familiar $N. Here is how to define INCR using KW_DEFINE: KW_DEFINE(`INCR', `m4_eval(KW_ARGV(1) + KWARG_VALUE(`delta',1))') Macros ====== This section describes the macros provided by this package. They are ordered by category. Debugging --------- KWARGS_DUMP([DELIM],[EXP]) For each defined keyword argument, produce the following expansion: EXP(`KW=VAL')DELIM DELIM defaults to newline, EXP - to m4_quote, Keyword arguments access macros ------------------------------- KWARG_IFSET(NAME,IF-SET,IF-NOT-SET) If the argument NAME is set, expands to IF-SET, otherwise expands to IF-NOT-SET. KWARGS_SWITCH(NAME1,IF-SET1,NAME2,IF-SET2,...,IF-NOT-SET) If NAME1 is set, expands to IF-SET1. Otherwise, if NAME2 is set, expands to IF-SET2. The process continues for all name-if-set pairs within `...'. If none of the names is set, expands to IF-NOT-SET. KWARGS_SWITCH_VALUE(NAME, VAL1, CASE1, VAL2, CASE2,..., OTHERWISE) If keyword argument NAME has value VAL1, expands to CASE1. Otherwise, if NAME has value VAL2, expands to CASE2, etc. If no matching value is listed, expands to OTHERWISE. KWARG_VALUE(NAME [,DEFAULT]) Expands to the value of argument NAME, if it is defined, or to DEFAULT otherwise. KWARGS_FOREACH(ITERATOR, TEXT) Takes the name in ITERATOR, which must be a valid identifier, and successively assigns it each keyword name. For each assignment to ITERATOR, TEXT is appended to the expansion of KWARGS_FOREACH. TEXT may refer to ITERATOR. Any definition of ITERATOR prior to this invocation is restored. KWARGS_LIST() Expand to a comma-delimited list of quoted keyword arguments, suitable for use as argument list to a macro. Expansion in keyword argument context ------------------------------------- KWARGS_APPLY(MACRO,[ARGS...]) Split ARGS into positional and keyword arguments and expand to MACRO(PARGS), where PARGS are positional arguments. MACRO can refer to keyword arguments using the macros discussed above. KWARGS_WITH(TEXT,ARGS...) Split ARGS into positional and keyword arguments and expand to TEXT. To refer to the positional arguments from TEXT, use the following notation: KW_ARGV(1) instead of $1 KW_ARGV(2) instead of $* ... KW_ARGV instead of $* KW_ARGQ instead of $@ KW_ARGC instead of $# KWARGS_DEFINE(NAME,TEXT) Defines NAME to expand to TEXT. Upon expansion, the argument list is split into positional arguments and keyword arguments as in KWARGS_WITH. TEXT should refer to positional arguments using the macros described above. Keyword argument manipulation ----------------------------- KWARGS_ASGN(ARGS...) Assign arguments. ARGS is a comma-separated list of keyword[=value] pairs. KWARGS_UNASGN(ARGS...]) Unassign keywords. ARGS is the same as for KWARGS_ASGN. KWARGS_PUSH([ARGS...]) Push current keyword arguments on stack, clear the keyword argument table and reset keyword arguments using KWARGS_ASGN(ARGS). KWARGS_POP() Pop keyword argument definitions from stack. KWARGS_DUP() Push current keyword arguments on stack and retain their definitions. This can be used to augment or override keyword arguments. To restore previous arguments, use KWARGS_POP. The normal usage pattern is: KWARGS_PUSH() KWARGS_ASGN($@) ... KWARGS_POP Low-level interface ------------------- KWARGS_PARSE(ARGS...) Split ARGS in positional and keyword arguments. Define the latter, expand to the former. KWARG_SET(NAME [, VALUE]) Sets argument NAME to VALUE KWARG_CLR(NAME) Clears the keyword argument NAME. KWARG_ASGN(NAME[=VAL]) Assigns VAL to NAME. If VAL is absent, equivalent to KWARG_SET(NAME). KWARG_UNASGN(NAME[=VAL]) Unassign argument. Optional VAL is ignored. Bug-reporting ============= Please send your bug reports and suggestions to Sergey Poznyakoff .