1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
|
CPPAWK-VARG(1) Variadic Functions CPPAWK-VARG(1)
NAME
varg - support functions with optional and variadic parameters
SYNOPSIS
#include <varg.h>
present(arg) // test whether arg is present
restargs // declarator for variadic params
arg(n) // access n-th arg, literal n
argcount(fname, restargs) // count of variadic arguments
arglist(fname, restargs) // list of variadic arguments
argarray(fname, arr, restargs) // list of variadic arguments
DESCRIPTION
The <varg.h> header provides some utilities for working with optional and variable argu-
ments 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 present macro tests whether
its argument arg is an undefined value, returning 1 if it is defined, otherwise 0.
Example:
#include <varg.h>
function f(a, b)
{
if (present(a))
print "a is present, with value", a
else
print "a is missing"
if (present(b))
print "b is present, with value", b
else
print "b is missing"
}
BEGIN {
print "test1"
f()
print "test2"
f(1)
print "test3"
f(1, 2)
print "test4"
f(undef, 2)
}
Output:
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
Note the trick used in test4: the unassigned variable undef was used to explicitly pass
the unset value as argument a, while passing a defined value as b.
That concludes the topic of optional arguments. The remainder of the <varg.h> functional-
ity revolves around variadic functions.
A variadic function is defined by including the restargs macro in the argument list, as if
it were an argument. The following function has two fixed parameters x and y, followed by
variadic arguments.
#include <varg.h>
fun f(x, y, restargs)
{
}
The restarts "super parameter" is capable of capturing up to 32 arguments.
Within a variadic function, the arg macro may be used to access a variadic argument by a
positional number ranging from 1 to 32. The present macro may be used to check whether the
argument is present, The argument of arg must be an decimal integer literal constant. Com-
puted access to argument by position is not supported; but the arguments may be converted
to an array or list:
#include <varg.h>
function f(x, y, restargs)
{
if (present(arg(3))) {
print "variadic arg 3 is present, value = ", arg(3)
} else {
print "variadic arg 3 is missing"
}
}
The argcount function calculates how many variadic arguments there are. The first argu-
ment of argcount is the name of the calling function, used for error reporting:
#include <varg.h>
function f(x, y, restargs,
count)
{
count = argcount("f", restargs);
print "f was called with", count, "variadic arguments"
}
Note: 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 as-
sumption is that there are no gaps among the variadic arguments. No undefined argument is
followed by a defined one.
The arglist function returns a list containing the arguments. Lists are defined in the
header. Like in the case of argcount, the first argument is the name of the calling func-
tion, used for error reporting:
#include <varg.h>
#include <cons.h>
function f(x, y, restargs,
list)
{
list = arglist("f", restargs);
print "f was called with these trailing args", sexp(list)
// also return the list
return list
}
Lastly, the 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 call-
ing function's name, used for error reporting. The second argument is the destination ar-
ray. The variadic arguments follow:
#include <varg.h>
#include <cons.h>
function f(x, y, restargs,
arr, i)
{
// get arguments into arr
argarray("f", arr, restargs);
print "f was called with these trailing args"
for (i in arr)
print "arg", i, "=", arr[i]
}
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, ac-
cording to the following pattern:
#include <varg.h>
function f(x, y, restargs,
count)
{
count = argcount("f", restargs, count);
print "f was called with", count, "variadic arguments"
}
In the above example, the first local variable which follows the restargs list is count.
That variable is passed as an extra argument to the argcount function. The argcount func-
tion expects this extra argument to be undefined. If it has an assigned value, it will
terminate Awk with a diagnostic message. The only way count can have an assigned value at
the time argcount is called is if f was called with so many trailing parameters, that
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 ig-
nored: not taken into account by argcount and so forth.
The arglist and 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 restargs don't require it. Awk itself will diagnose the situa-
tion when more than 32 variadic parameters are passed in that case.
SEE ALSO
cppawk(1), cppawk-cons(1)
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 argcount, arglist
and argarray using the extra argument mechanism. Beyond 48 variadic arguments, the behav-
ior of these functions is unspecified.
AUTHOR
Kaz Kylheku <kaz@kylheku.com>
COPYRIGHT
Copyright 2022, BSD2 License.
cppawk Libraries 19 April 2022 CPPAWK-VARG(1)
|