aboutsummaryrefslogtreecommitdiffstats
path: root/cppawk-narg.1
diff options
context:
space:
mode:
Diffstat (limited to 'cppawk-narg.1')
-rw-r--r--cppawk-narg.189
1 files changed, 83 insertions, 6 deletions
diff --git a/cppawk-narg.1 b/cppawk-narg.1
index 985ea1c..3c1d8a3 100644
--- a/cppawk-narg.1
+++ b/cppawk-narg.1
@@ -11,6 +11,7 @@
#define narg(...P)
#define splice(\fIargs\fP)
#define varexpand(\fIfirst_mac\fP, \fIrest_mac\fP, ...)
+ #define variexpand(\fIfirst_mac\fP, \fIrest_mac\fP, ...)
#define revarg(...)
.ft R
@@ -150,18 +151,27 @@ some overflow detection up to 48 arguments, followed by unspecified behavior
for 49 or more arguments.
.IP \fBvarexpand\fR
-The most complex macro in the
+The most complex macros in the
.I <narg.h>
-header is
-.BR varexpand .
+header are
+.B varexpand
+and
+.BR variexpand .
-This macro is used for writing variadic macros with complex expansions,
+These macros are used for writing variadic macros with complex expansions,
using a compact specification.
The
.B varexpand
macro uses "higher order macro" programming: it has arguments which are
-themselves macros. To understand
+themselves macros.
+The
+.B variexpand
+macro is a variation on this, explained after a complete description of
+.B varexpand
+is given.
+
+To understand
.B varexpand
it helps to understand the Lisp
.B reduce
@@ -283,7 +293,7 @@ Example:
macro which generates a left-associative nested expression, like this:
.ft B
- rlist(\fI1\fP) \fI->\fP cons(\fI1\fP, Inil)
+ rlist(\fI1\fP) \fI->\fP cons(\fI1\fP, nil)
rlist(\fI1\fP, \fI2\fP) \fI->\fP cons(\fI2\fP, cons(\fI1\fP, nil))
rlist(\fI1\fP, \fI2\fP, \fI3\fP) -> cons(\fI3\fP, cons(\fI2\fP, cons(\fI1\fP, nil)))
.ft R
@@ -313,6 +323,73 @@ macro to reverse the arguments:
#define list(...) rlist(revarg(__VA_ARG__))
.ft R
+.IP \fBvariexpand\fB
+The
+.B variexpand
+macro is very similar to
+.BR varexpand .
+The difference is that
+.B varexpand
+passes an extra argument to both of the
+.B first_mac
+and
+.BR rest_mac
+macros. This argument is a decimal integer token indicating the master argument
+position being expanded.
+
+For instance, suppose we wish to have a macro with the following properties:
+
+.ft B
+ series(\fIa\fP) \fI->\fP \fIa1\fP
+ series(\fIa\fP, \fIb\fP) \fI->\fP \fIa1\fP + \fIb2\fP
+ series(\fIa\fP, \fIb\fP, \fIc\fP) \fI->\fP \fIa1\fP + \fIb2\fP + \fIc3\fP
+.ft R
+
+Note that the numbers do not appear as arguments. The
+.B variexpand
+macro will supply them:
+
+.ft B
+ #define series_first(\fIx\fP, \fIi\fP) \fIx\fP ## \fIi\fP
+ #define series_next(\fIprev\fP, \fIx\fP, \fIi\fP) \fIprev\fP + \fIx\fP ## \fIi\fP
+ #define series(...) variexpand(\fIseries_first\fP, \fIseries_next\fP, \e
+ __VA_ARGS__)
+.ft R
+
+Here,
+.B series_first
+is always called with
+.I i " ="
+1, and
+.B series_next
+is called with
+.I i
+taking on the values 2, 3, ... .
+The value of
+.I i
+indicates the one-based argument position of
+.I x
+in the
+.B series
+macro.
+
+One use for this is the generation of better temporary variables.
+The C preprocessor doesn't have a facility for generating temporary
+variable names. An unsatisfactory substitute is the use of some private
+namespace prefix like
+.B __x
+pasted together with the expansion of the
+.B __LINE__
+macro. However, macros can occur in the same line of code, or
+as arguments of a larger multi-line macro during the expansion of which
+.B __LINE__
+is pinned to the same value. If a large, multi-clause macro is based on
+.BR variexpand ,
+it can pass the argument number to its child clauses, which can combine
+it with
+.B __LINE__
+and a prefix to generate unique variables.
+
.SH BUGS
As noted in the DESCRIPTION, the
.BR narg ,