diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2022-04-20 20:09:10 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2022-04-20 20:09:10 -0700 |
commit | 6d53169644fb83f367f01369ec01f0ccf297b4cd (patch) | |
tree | 6c68e7e31308eedc5456cb2a6de725de3cd755cd | |
parent | 3334ef7fc25ce04647f12a3a887637e1bb6aec17 (diff) | |
download | cppawk-6d53169644fb83f367f01369ec01f0ccf297b4cd.tar.gz cppawk-6d53169644fb83f367f01369ec01f0ccf297b4cd.tar.bz2 cppawk-6d53169644fb83f367f01369ec01f0ccf297b4cd.zip |
New man page: cppawk-varg.
-rw-r--r-- | README.md | 8 | ||||
-rw-r--r-- | cppawk-include/varg.h | 1 | ||||
-rw-r--r-- | cppawk-varg.1 | 326 |
3 files changed, 330 insertions, 5 deletions
@@ -144,15 +144,13 @@ There are currently function calls. Note: there are bugs in GNU Awk's indirect function calls feature that are present right through 5.1.1. +* [`<varg.h>`](../tree/cppawk-varg.1): utilities for working with + variadic functions in Awk, as well as with optional arguments. + Several unreleased headers are in the development queue: * `<field.h>`: utilities for manipulating fields. -* `<varg.h>`: utilities for writing variadic functions in Awk; - the private API version of this is used in existing work, but does - not have separate test cases, and doesn't have a public, documented - version. - * `<array.h>`: some associative array utilities. * `<alist.h>`: Lisp-like assoc lists: addendum to `<cons.h>`. diff --git a/cppawk-include/varg.h b/cppawk-include/varg.h index e58642d..c0ff036 100644 --- a/cppawk-include/varg.h +++ b/cppawk-include/varg.h @@ -37,6 +37,7 @@ #endif #define restargs __rest +#define arg(n) __r ## n #define present(arg) __present(arg) #define argcount __argcount #define arglist __arglist diff --git a/cppawk-varg.1 b/cppawk-varg.1 new file mode 100644 index 0000000..aefdf18 --- /dev/null +++ b/cppawk-varg.1 @@ -0,0 +1,326 @@ +.\" cppawk: C preprocessor wrapper around awk +.\" Copyright 2022 Kaz Kylheku <kaz@kylheku.com> +.\" +.\" BSD-2 License +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright notice, +.\" this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright notice, +.\" this list of conditions and the following disclaimer in the documentation +.\" and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +.\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.de bk +.IP " " +.PP +.. +.TH CPPAWK-VARG 1 "19 April 2022" "cppawk Libraries" "Variadic Functions" + +.SH NAME +varg \- support functions with optional and variadic parameters + +.SH SYNOPSIS + +.ft B + #include <varg.h> + + present(\fIarg\fP) \fI// test whether arg is present\fP + restargs \fI// declarator for variadic params\fP + arg(\fIn\fP) \fI// access n-th arg, literal n\fP + argcount(\fIfname\fP, restargs) \fI// count of variadic arguments\fP + arglist(\fIfname\fP, restargs) \fI// list of variadic arguments\fP + argarray(\fIfname\fP, \fIarr\fP, restargs) \fI// list of variadic arguments\fP +.ft R + +.SH DESCRIPTION +.bk +The +.B <varg.h> +header provides some utilities for working with optional and variable +arguments in Awk. + +In Awk, any function may be called with fewer than the declared number +of arguments. The arguments which are not passed take on unassigned +values. The +.B present +macro tests whether its argument +.I arg +is an undefined value, returning 1 if it is defined, otherwise 0. + +.B Example: + +.ft B + #include <varg.h> + + function f(\fIa\fP, \fIb\fP) + { + if (present(\fIa\fP)) + print "a is present, with value", \fIa\fP + else + print "a is missing" + + if (present(\fIb\fP)) + print "b is present, with value", \fIb\fP + else + print "b is missing" + + } + + BEGIN { + print "test1" + f() + print "test2" + f(1) + print "test3" + f(1, 2) + print "test4" + f(undef, 2) + } +.ft R + +.B Output: + +.ft B + test1 + a is missing + b is missing + test2 + a is present, with value 1 + b is missing + test3 + a is present, with value 1 + b is present, with value 2 + test4 + a is missing + b is present, with value 2 +.ft R + +Note the trick used in +.BR test4 : +the unassigned variable +.B undef +was used to explicitly pass the unset value as argument +.IR a , +while passing a defined value as +.IR b . + +That concludes the topic of optional arguments. The remainder of the +.B <varg.h> +functionality revolves around variadic functions. + +A variadic function is defined by including the +.B restargs +macro in the argument list, as if it were an argument. The following +function has two fixed parameters +.I x +and +.IR y , +followed by variadic arguments. + +.ft B + #include <varg.h> + + fun f(\fIx\fP, \fIy\fP, restargs) + { + + } +.ft R + +The +.B restarts +"super parameter" +is capable of capturing up to 32 arguments. + +Within a variadic function, the +.B arg +macro may be used to access a variadic argument by a positional +number ranging from 1 to 32. The +.B present +macro may be used to check whether the argument is present, +The argument of +.B arg +must be an decimal integer literal constant. Computed access +to argument by position is not supported; but the arguments +may be converted to an array or list: + +.ft B + #include <varg.h> + + function f(\fIx\fP, \fIy\fP, restargs) + { + if (present(arg(3))) { + print "variadic arg 3 is present, value = ", arg(3) + } else { + print "variadic arg 3 is missing" + } + } +.ft R + +The +.B argcount +function calculates how many variadic arguments there are. +The first argument of +.B argcount +is the name of the calling function, used for error reporting: + +.ft B + #include <varg.h> + + function f(\fIx\fP, \fIy\fP, restargs, + \fIcount\fP) + { + \fIcount\fP = argcount("f", restargs); + + print "f was called with", \fIcount\fP, "variadic arguments" + } +.ft P + +Note: +.B argcount +has no way to obtain the value directly from Awk. It works by +receiving all of the arguments, and performing a binary search +to find the first undefined one. The assumption is that there +are no gaps among the variadic arguments. No undefined argument +is followed by a defined one. + +The +.B arglist +function returns a list containing the arguments. Lists are +defined in the header. Like in the case of +.BR argcount , +the first argument is the name of the calling function, +used for error reporting: + +.ft B + #include <varg.h> + #include <cons.h> + + function f(\fIx\fP, \fIy\fP, restargs, + \fIlist\fP) + { + \fIlist\fP = arglist("f", restargs); + + print "f was called with these trailing args", sexp(list) + + \fI// also return the list\fP + return list + } +.ft R + +Lastly, the +.B argarray +function stuffs the variadic arguments into an associative array, +which is indexed by the argument positions: 1, 2, 3, ... +The first argument is the calling function's name, used for +error reporting. The second argument is the destination array. +The variadic arguments follow: + +.ft B + #include <varg.h> + #include <cons.h> + + function f(\fIx\fP, \fIy\fP, restargs, + \fIarr\fP, \fIi\fP) + { + \fI// get arguments into arr\fP + argarray("f", \fIarr\fP, restargs); + + print "f was called with these trailing args" + + for (i in arr) + print "arg", i, "=", arr[i] + } +.ft R + +What happens if more than 32 arguments are passed? Those arguments +will "crash" into the local variable area. All of the above functions +provide error detection for this case, according to the following pattern: + +.ft B + #include <varg.h> + + function f(\fIx\fP, \fIy\fP, restargs, + \fIcount\fP) + { + \fIcount\fP = argcount("f", restargs, \fIcount\fP); + + print "f was called with", \fIcount\fP, "variadic arguments" + } +.ft R + +In the above example, the first local variable which follows the +.B restargs +list is +.IR count . +That variable is passed as an extra argument to the +.B argcount +function. The +.B argcount +function expects this extra argument to be undefined. If it has an +assigned value, it will terminate Awk with a diagnostic message. +The only way +.I count +can have an assigned value at the time +.B argcount +is called is if +.B f +was called with so many trailing parameters, that +.I count +was given a value in the function call, and so if that is the case, +the 32 limit on the number of variadic arguments has been exceeded. + +If this issue is not caught, functions which rely on their local +variables to be initially unassigned may malfunction. Also, variadic +arguments beyond 32 will end up silently ignored: not taken into account by +.B argcount +and so forth. + +The +.B arglist +and +.B argarray +functions also take an extra argument for this purpose. +If the extra argument is not passed, then there is no error checking. +Functions which don't have any local variables after +.B restargs +don't require it. Awk itself will diagnose the situation when more than +32 variadic parameters are passed in that case. + +.SH "SEE ALSO" + +cppawk(1), cppawk-cons(1) + +.SH BUGS + +The 32 argument limitation is a flaw; ideally, there should be no +such limitations. + +The argument overflow detection is only good up to 48 arguments. That +is to say, if more than 32 arguments are passed, up to 48, the situation +can be detected by +.BR argcount , +.B arglist +and +.B argarray +using the extra argument mechanism. Beyond 48 variadic arguments, the +behavior of these functions is unspecified. + +.SH AUTHOR +Kaz Kylheku <kaz@kylheku.com> + +.SH COPYRIGHT +Copyright 2022, BSD2 License. |