diff options
Diffstat (limited to 'cppawk-narg.1')
-rw-r--r-- | cppawk-narg.1 | 89 |
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 , |