aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-04-20 20:09:10 -0700
committerKaz Kylheku <kaz@kylheku.com>2022-04-20 20:09:10 -0700
commit6d53169644fb83f367f01369ec01f0ccf297b4cd (patch)
tree6c68e7e31308eedc5456cb2a6de725de3cd755cd
parent3334ef7fc25ce04647f12a3a887637e1bb6aec17 (diff)
downloadcppawk-6d53169644fb83f367f01369ec01f0ccf297b4cd.tar.gz
cppawk-6d53169644fb83f367f01369ec01f0ccf297b4cd.tar.bz2
cppawk-6d53169644fb83f367f01369ec01f0ccf297b4cd.zip
New man page: cppawk-varg.
-rw-r--r--README.md8
-rw-r--r--cppawk-include/varg.h1
-rw-r--r--cppawk-varg.1326
3 files changed, 330 insertions, 5 deletions
diff --git a/README.md b/README.md
index a77e366..e35440b 100644
--- a/README.md
+++ b/README.md
@@ -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.