aboutsummaryrefslogtreecommitdiffstats
path: root/cppawk-narg.1
diff options
context:
space:
mode:
Diffstat (limited to 'cppawk-narg.1')
-rw-r--r--cppawk-narg.1105
1 files changed, 54 insertions, 51 deletions
diff --git a/cppawk-narg.1 b/cppawk-narg.1
index f802f39..409a602 100644
--- a/cppawk-narg.1
+++ b/cppawk-narg.1
@@ -1,32 +1,35 @@
.TH CPPAWK-NARG 1 "29 March 2022" "cppawk Libraries" "Case Macro"
.SH NAME
-narg \- macros for writing variable argument macros
+.I narg
+\- macros for writing variable argument macros
.SH SYNOPSIS
+.ft B
#include <narg.h>
#define narg(...)
#define splice(args)
#define varexpand(first_mac, rest_mac, ...)
#define revarg(...)
+.ft R
.SH DESCRIPTION
The
-.B <narg.h>
+.I <narg.h>
header provides several macros which are useful to macro writers.
In particular, these macros make it easy to develop variable argument
macros which take one or more argument, and have complex expansions.
In this manual, the
-.BI ->
+.B ->
(arrow) notation means "expands to". For instance
foo(bar) -> 42 // the macro call foo(bar) expands to 42
A description of each macro follows:
-.IP narg
+.IP \fBnarg\fR
This macro takes one or more arguments, and expands to a decimal integer which
indicates how many arguments there are.
@@ -35,20 +38,20 @@ indicates how many arguments there are.
narg(x, y, z) -> 3
The
-.BI narg
+.B narg
macro can be called with up to 32 (thirty-two) arguments. If it is called
with between 33 to 48 arguments, it expands to an unspecified token
sequence which generates a syntax error in Awk. The token sequence begins
with an identifier and therefore may appear as the right operand of the
token-pasting
-.BI ##
+.B ##
operator, opposite to an identifier token.
If more than 48 arguments are given, the behavior is unspecified.
-.IP splice
+.IP \fBsplice\fR
The
-.BI splice
+.B splice
macro provides a shim for inserting a parenthesized argument into
a macro expansion, such that the argument turns into individual
arguments. Suppose we have a macro like this:
@@ -60,19 +63,19 @@ For some reason, we need to write fixed a macro like this:
#define fmac(x, y, args) vmac(x, y, ???)
where the
-.BI args
+.B args
argument is a parenthesized list of arguments that must become the
-.BI ...
+.I ...
argument of the
-.BI vmac
+.B vmac
macro. That is to say,
-.BI fmac
+.B fmac
is to be invoked like this, with the indicated expansion:
fmac(1, 2, (3, 4, 5)) -> vmac(1, 2, 3, 4, 5)
The
-.BI splice
+.B splice
macro solves the question of what to write into the position
indicated by the ??? question marks to achieve this:
@@ -84,17 +87,17 @@ Example: produce the following macro:
sqrt(sumsq(x, y)))
This is a trick example:
-.BI splice
+.B splice
is not required at all:
#define csum(left, right) (sqrt(sumsq left) + \e
sqrt(sumsq right))
The
-.BI splice
+.B splice
macro is not required because the parenthesized arguments constitute
the entire argument list of
-.BI sumsq.
+.BR sumsq .
However, suppose the requirement is this, requiring the parenthesized
arguments to be inserted into an argument list containing other arguments:
@@ -108,7 +111,7 @@ Now we need:
sumsq(parm, \e
splice(right))))
-.IP revarg
+.IP \fBrevarg\fR
This macro expands to a comma-separated list of its arguments, which
appear in reverse.
@@ -117,31 +120,31 @@ appear in reverse.
revarg(1, 2, 3) -> 3, 2, 1
Like
-.BI narg,
+.BR narg ,
the
-.BI revarg
+.B revarg
macro can be called with up to 32 arguments, beyond which there is
some overflow detection up to 48 arguments, followed by unspecified behavior
for 49 or more arguments.
-.IP varexpand
+.IP \fBvarexpand\fR
The most complex macro in the
-.B <narg.h>
+.I <narg.h>
header is
-.BI varexpand.
+.BR varexpand .
This macro is used for writing variadic macros with complex expansions,
using a compact specification.
The
-.BI varexpand
+.B varexpand
macro uses "higher order macro" programming: it has arguments which are
themselves macros. To understand
-.BI varexpand
+.B varexpand
it helps to understand the Lisp
-.BI reduce
+.B reduce
function, or the similar
-.BI fold
+.B fold
function found in functional languages. Recall that the prototype of the
.BI varexpand
macro is this:
@@ -149,27 +152,27 @@ macro is this:
#define varexpand(first_mac, rest_mac, ...)
To use
-.BI varexpand
+.B varexpand
you must first write two macros: a one-argument macro whose name is passed
as the
-.BI first_mac
+.B first_mac
argument, and two argument macro to be used as the
-.BI rest_mac
+.B rest_mac
argument.
Most variadic macros written with
-.BI varexpand
+.B varexpand
will pass through their
-.BI __VA_ARGS__
+.B __VA_ARGS__
list as the
-.BI ...
+.I ...
parameter; however, the
-.BI splice
+.B splice
macro can also be used to place parenthesized argument lists
into that position
Up to 32 variadic arguments are accepted by
-.BI varexpand
+.B varexpand
beyond which there is overflow detection up to 48 arguments,
followed by unspecified behavior for 49 or more arguments.
@@ -192,15 +195,15 @@ argument. The right argument is the next argument to be added to the expansion.
For instance, if the arguments 1, 2 have already been expanded to 1 + 2
and the next argument is 3, then
-.BI acc
+.B acc
takes on the tokens 1 + 2, and
-.BI x
+.B x
takes on 3. Thus the expansion is:
add_next(1 + 2, 3) -> 1 + 2 + 3
With these two macros, we can then write
-.BI add
+.B add
like this:
#define add(...) varexpand(add_first, add_next, __VA_ARGS__)
@@ -219,9 +222,9 @@ the products. We write the helper macros like this:
#define sumsq_next(a, x) a + sumsq_first(x)
Note that
-.BI sumsq_next
+.B sumsq_next
reuses
-.BI sumsq_first
+.B sumsq_first
to avoid repeating the (x)*(x) term. Then we complete the implementation:
#define sumsq(...) (varexpand(sumsq_first, \e
@@ -229,9 +232,9 @@ to avoid repeating the (x)*(x) term. Then we complete the implementation:
__VA_ARGS__))
The outer parentheses are written around the
-.BI varexpand
+.B varexpand
call. In general,
-.BI varexpand
+.B varexpand
can be just a small component of a larger macro expansion, and
can be used more than one time in a macro expansion.
@@ -257,34 +260,34 @@ association, rather than in reverse? So that is to say:
list(1, 2, 3) -> cons(1, cons(2, cons(3, nil)))
Here we simply take advantage of the
-.BI revarg
+.B revarg
macro to reverse the arguments:
#define list(...) rlist(revarg(__VA_ARG__))
.SH BUGS
As noted in the DESCRIPTION, the
-.BI narg,
-.BI revarg,
+.BR narg ,
+.B revarg
and
-.BI varexpand
+.B varexpand
macros are limited to handling 32 variadic arguments, beyond
which there is a 16 argument safety margin with error detection,
followed by unspecified behavior.
The C preprocessor doesn't support macro recursion, which forbids
some complex uses of
-.BI varexpand
+.B varexpand
whereby the
-.BI first_mac
+.B first_mac
and
-.BI next_mac
+.B next_mac
macros themselves make use of
-.BI varexpand.
+.BR varexpand .
A possible workaround is to clone the implementation of
-.BI varexpand
+.B varexpand
to produce an identical macro called
-.BI varexpand2.
+.BR varexpand2 .
This then allows for two "recursion" levels, whereby each one uses
the macro under a different name.