aboutsummaryrefslogtreecommitdiffstats
path: root/cppawk-varg.1
blob: aefdf186a0912aa8be945e1f57a0750507528126 (plain)
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)