Commit | Line | Data |
---|---|---|
9e91c8e7 MW |
1 | /* -*-c-*- |
2 | * | |
3 | * Keyword argument handling | |
4 | * | |
5 | * (c) 2015 Straylight/Edgeware | |
6 | */ | |
7 | ||
8 | /*----- Licensing notice --------------------------------------------------* | |
9 | * | |
10 | * This file is part of the Sensible Object Design, an object system for C. | |
11 | * | |
12 | * SOD is free software; you can redistribute it and/or modify | |
13 | * it under the terms of the GNU Library General Public License as | |
14 | * published by the Free Software Foundation; either version 2 of the | |
15 | * License, or (at your option) any later version. | |
16 | * | |
17 | * SOD is distributed in the hope that it will be useful, | |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | * GNU Library General Public License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU Library General Public | |
23 | * License along with SOD; if not, write to the Free | |
24 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, | |
25 | * MA 02111-1307, USA. | |
26 | */ | |
27 | ||
28 | #ifndef KEYWORD_H | |
29 | #define KEYWORD_H | |
30 | ||
31 | #ifdef __cplusplus | |
32 | extern "C" { | |
33 | #endif | |
34 | ||
35 | /*----- Header files ------------------------------------------------------*/ | |
36 | ||
37 | #include <stdarg.h> | |
38 | #include <stddef.h> | |
39 | #include <string.h> | |
40 | ||
41 | /*----- Function annotations ----------------------------------------------*/ | |
42 | ||
43 | /* Some macros are defined for annotating functions. They may improve | |
44 | * compiler diagnostics when used properly. They should be included as part | |
45 | * of the function's declaration specifiers. | |
46 | * | |
47 | * * @KWCALL@ marks a function as expecting keyword arguments. The | |
48 | * compiler may check that there are an odd number of arguments, that the | |
49 | * even-numbered (starting from zero) arguments have pointer-to-character | |
50 | * type, and that the final argument is null. | |
51 | * | |
52 | * * @KW__NORETURN@ marks a function as never returning. Applied to | |
53 | * @kw_unknown@ and its various friends. Users are not expected to use | |
54 | * this. | |
55 | */ | |
56 | ||
57 | #if defined(__GNUC__) | |
58 | # define KW__GCC_VERSION_P(maj, min) \ | |
59 | (__GNUC__ > (maj) || (__GNUC__ == (maj) && __GNUC_MINOR__ >= (min))) | |
60 | # if KW__GCC_VERSION_P(2, 5) | |
61 | # define KW__NORETURN __attribute__((__noreturn__)) | |
62 | # endif | |
63 | # if KW__GCC_VERSION_P(4, 0) | |
64 | # define KWCALL __attribute__((__sentinel__)) | |
65 | # endif | |
66 | #endif | |
67 | ||
68 | /* --- Trivial definitions, if we don't have compiler support --- */ | |
69 | ||
70 | #ifndef KW__NORETURN | |
71 | # define KW__NORETURN | |
72 | #endif | |
73 | ||
74 | #ifndef KWCALL | |
75 | # define KWCALL | |
76 | #endif | |
77 | ||
78 | /*----- Type definitions --------------------------------------------------*/ | |
79 | ||
80 | /* A keyword/value pair. A vector of these can be passed as the value of the | |
81 | * special keyword `kw.tab'. This is a rather cumbersome way of constructing | |
82 | * lists of keyword arguments for a function in a programmatic way. | |
83 | */ | |
84 | struct kwval { | |
85 | const char *kw; /* The keyword name, as a string */ | |
86 | const void *val; /* A pointer to the keyword value */ | |
87 | }; | |
88 | ||
89 | /* A table of keyword/value pairs. This is used as the value of a `kw.tab' | |
90 | * argument which is itself in a @struct kwval@ table, since it's not | |
91 | * possible to store both the vector and length directly. | |
92 | */ | |
93 | struct kwtab { | |
94 | const struct kwval *v; /* The address of the vector */ | |
95 | size_t n; /* The number of keywords */ | |
96 | }; | |
97 | ||
98 | /* The type of unknown-keyword handler functions. */ | |
99 | typedef void kw_unkhookfn(const char */*set*/, const char */*kw*/); | |
100 | ||
101 | /*----- Global variables --------------------------------------------------*/ | |
102 | ||
103 | /* A global hook function for handling unknown-keyword errors. The default | |
104 | * function prints a message to the standard error stream and aborts. | |
105 | * | |
106 | * The hook function must not return. It's not possible to recover from an | |
107 | * unknown-keyword error while parsing a variable-length argument tail, since | |
108 | * it's impossible to find out what type the corresponding argument value is. | |
109 | * | |
110 | * Having a single global hook isn't really very satisfactory, but a fully | |
111 | * adequate solution gets complicated quickly. An external library will | |
112 | * eventually be available to pick up the slack. | |
113 | */ | |
114 | extern kw_unkhookfn *kw_unkhook; | |
115 | ||
4c7784e5 MW |
116 | /*----- Atoms -------------------------------------------------------------*/ |
117 | ||
118 | #ifdef __arm__ | |
119 | # define KW__SECTTY "%" | |
120 | #else | |
121 | # define KW__SECTTY "@" | |
122 | #endif | |
123 | ||
124 | #if defined(__GNUC__) && defined(__ELF__) && 0 | |
125 | # define KWATOM_DECL(id, name) \ | |
126 | __asm__( ".ifndef " #id "\n" \ | |
127 | ".pushsection .rodata." #id ", " \ | |
128 | "\"aGS\", " KW__SECTTY "progbits, " \ | |
129 | ".rodata." #id ", comdat\n" \ | |
130 | ".globl " #id "\n" \ | |
131 | #id ": .asciz " #name "\n" \ | |
132 | ".popsection\n" \ | |
133 | ".endif"); \ | |
134 | extern const char id[] | |
135 | #endif | |
136 | ||
137 | #ifdef KWATOM_DECL | |
138 | # define KW_ATOM(id, name) id | |
139 | #else | |
140 | # define KWATOM_DECL(id, name) extern int kw__fake_##id | |
141 | # define KW_ATOM(id, name) (name + 0*sizeof(kw__fake_##id)) | |
142 | #endif | |
143 | ||
144 | #define KADECL(atom) KWATOM_DECL(kw__atom__##atom, #atom) | |
145 | #define KA(atom) KW_ATOM(kw__atom__##atom, #atom) | |
146 | #define KA_TAB KW_ATOM(kw__atom_kw_tab, "kw.tab") | |
147 | #define KA_UNKNOWN KW_ATOM(kw__atom_kw_unknown, "kw.unknown") | |
148 | #define KA_VALIST KW_ATOM(kw__atom_kw_valist, "kw.valist") | |
149 | ||
150 | KWATOM_DECL(kw__atom_kw_tab, "kw.tab"); | |
151 | KWATOM_DECL(kw__atom_kw_unknown, "kw.unknown"); | |
152 | KWATOM_DECL(kw__atom_kw_valist, "kw.valist"); | |
153 | ||
9e91c8e7 MW |
154 | /*----- Argument list macros ----------------------------------------------*/ |
155 | ||
a79bc435 | 156 | /* These macros are intended to be conveniences rather than a proper |
9e91c8e7 MW |
157 | * abstraction. Functions with more complicated interfaces, and their |
158 | * callers, will have to make their own arrangements. | |
159 | */ | |
160 | ||
161 | /* --- @KWTAIL@ --- * | |
162 | * | |
163 | * Arguments: --- | |
164 | * | |
165 | * Use: Marker to be included in a function prototype (at the end of | |
166 | * the argument list) to indicate that the function accepts | |
167 | * keyword arguments. It is acceptable for the @KWTAIL@ marker | |
168 | * to be only thing in the argument list. | |
169 | */ | |
170 | ||
171 | #define KWTAIL const char *kwfirst_, ... | |
172 | ||
173 | /* --- @KWARGS@ --- * | |
174 | * | |
175 | * Arguments: @body@ = a sequence of @K(kw, value)@ macro calls, without | |
176 | * separators | |
177 | * | |
178 | * Use: A package of actual keyword arguments. In C89, the @body@ | |
179 | * must not be empty: to pass no keywords, use @NO_KWARGS@ | |
180 | * instead. | |
181 | */ | |
182 | ||
183 | #define KWARGS(body) body KW__END | |
184 | #define KW__END ((const char *)0) | |
185 | ||
a79bc435 | 186 | /* --- @NO_KWARGS@ --- * |
9e91c8e7 MW |
187 | * |
188 | * Arguments: --- | |
189 | * | |
190 | * Use: Special marker to include in an actual argument list to | |
191 | * indicate that no keyword arguments are to be passed. See | |
192 | * @KWARGS@ above. | |
193 | */ | |
194 | ||
195 | #define NO_KWARGS KW__END, KW__END | |
196 | /* Slight hack. The @KWCALL@ macro sets GCC and similar compilers up to | |
197 | * check for a sentinal null pointer at the end of the variable-length | |
198 | * argument tail. Alas, if there are no keywords at all, then the null | |
c5161e0a | 199 | * terminator ends up in the @kwfirst_@ argument, and the tail is properly |
9e91c8e7 MW |
200 | * empty, with the result that the compiler gives an annoying warning. |
201 | * Supplying an extra argument here is obviously harmless, and makes the | |
202 | * otherwise useful warning go away in this case where it's not wanted. | |
203 | */ | |
204 | ||
a79bc435 | 205 | /* --- @K@ --- * |
9e91c8e7 MW |
206 | * |
207 | * Arguments: @kw@ = keyword name, as an unquoted token list | |
208 | * @val@ = keyword value, as an expression | |
209 | * | |
210 | * Use: Bundles a keyword @kw@ and value @val@ together. | |
211 | */ | |
212 | ||
4c7784e5 | 213 | #define K(kw, val) KA(kw), (val), |
9e91c8e7 | 214 | |
dcb086e9 | 215 | /* --- @K_VALIST@ --- * |
9e91c8e7 MW |
216 | * |
217 | * Arguments: @va_list ap@ = argument-list extraction state | |
218 | * | |
219 | * Use: Passes a reified variable-length argument tail into a keyword | |
220 | * function. | |
221 | */ | |
222 | ||
4c7784e5 | 223 | #define K_VALIST(ap) KA_VALIST, &(ap), |
9e91c8e7 | 224 | |
dcb086e9 | 225 | /* --- @K_TAB@ --- * |
9e91c8e7 MW |
226 | * |
227 | * Arguments: @const struct kwval *v@ = base address of argument vector | |
228 | * @size_t n@ = length of argument vector | |
229 | * | |
230 | * Use: Passes an vector of keyword arguments into a keyword | |
231 | * function. | |
232 | */ | |
233 | ||
4c7784e5 | 234 | #define K_TAB(v, n) KA_TAB, (v), (size_t)(n), |
9e91c8e7 MW |
235 | |
236 | /*----- Keyword set definitions -------------------------------------------* | |
237 | * | |
238 | * A `keyword set' describes the collection of keyword arguments to be | |
239 | * accepted by a function (or group of functions). Keyword sets have names, | |
240 | * which are C identifiers. A keyword set must not be empty: use | |
241 | * @kw_parseempty@ instead of this machinery when defining a function which | |
242 | * may later accept keyword arguments but which currently doesn't define any. | |
243 | * | |
244 | * A keyword set definition is a macro of a single argument, conventionally | |
245 | * named `@_@'. The macro for a keyword set called @foo@ is named | |
246 | * @foo_KWSET@. It should consist of a triple @_(type, key, dflt)@ for each | |
247 | * keyword argument, where @type@ is the C type of the argument, @key@ is the | |
248 | * name of the argument (as a C identifier), and @dflt@ is an expression | |
249 | * (valid to use in an aggregate initializer) to provide the default value | |
250 | * for the argument. The @type@ must be such that @type *@ is the type of a | |
251 | * pointer to object of @type@. | |
252 | */ | |
253 | ||
254 | /* --- @KWSET_STRUCT@ --- * | |
255 | * | |
256 | * Arguments: @set@ = the keyword set name | |
257 | * | |
258 | * Use: Defines the keyword set argument structure @struct | |
259 | * set_kwargs@. | |
260 | * | |
261 | * The structure is used to communicate argument values between | |
262 | * a function accepting keyword arguments and the argument | |
263 | * parsing function constructed by @KWSET_PARSEFN@. It contains | |
264 | * two members for each keyword argument: one with the name of | |
265 | * the argument and the appropriate type to hold its value; the | |
266 | * other is a one-bit-wide bitfield named with a `_suppliedp' | |
267 | * suffix, and is set to indicate whether the caller provided a | |
268 | * a value for the corresponding keyword argument. | |
269 | */ | |
270 | ||
271 | #define KWSET_STRUCT(set) \ | |
272 | struct set##_kwargs { \ | |
273 | set##_KWSET(KWSET__SUPPLIEDP) \ | |
274 | set##_KWSET(KWSET__STRUCTMEM) \ | |
275 | } | |
fd040f06 | 276 | #define KWSET__SUPPLIEDP(type, name, dflt) unsigned name##_suppliedp: 1; |
9e91c8e7 MW |
277 | #define KWSET__STRUCTMEM(type, name, dflt) type name; |
278 | ||
279 | /* --- @KWSET_PARSEFN@ --- * | |
280 | * | |
281 | * Arguments: @set@ = the keyword set name | |
282 | * | |
283 | * Use: Defines the keyword argument parsing function @set_kwparse@. | |
284 | * A call to this macro may be preceded by a storage-class | |
285 | * specifier, e.g., @static@, to specify the linkage for the | |
286 | * parsing function's name. | |
287 | * | |
288 | * This function takes five arguments: | |
289 | * | |
290 | * @struct set_kwargs *kw@ = pointer to keyword set argument | |
291 | * structure to fill in | |
292 | * @const char *kwfirst@ = first keyword argument name from the | |
293 | * variable-length argument tail, or null if the | |
294 | * argument tail is empty | |
295 | * @va_list *ap@ = pointer to variable-length tail extraction | |
296 | * state object | |
297 | * @const struct kwval *v@ = base address of argument vector | |
298 | * @size_t n@ = length of argument vector | |
299 | * | |
300 | * The `kwparse' function extracts keyword arguments from the | |
301 | * argument tail (via @*ap@), and then the vector @v@; it | |
302 | * updates the structure @*kw@ with their values, and sets the | |
303 | * `_suppliedp' flags accordingly. It's unusual to call the | |
304 | * `kwparse' function with both a nontrivial argument tail and | |
305 | * vector, but the effect is nonetheless well-defined. | |
306 | * | |
307 | * The argument tail consists of alternating keyword argument | |
308 | * names (as pointers to null-terminated strings) and values, | |
309 | * terminated by a null pointer. The argument values are simply | |
310 | * copied into the structure. Passing the @kwfirst@ argument | |
311 | * separately allows functions to declare an explicit positional | |
312 | * argument for the first keyword name, which is useful if the | |
313 | * function has no other positional arguments. | |
314 | * | |
315 | * The argument vector consists of @struct kwval@ items, each of | |
316 | * which contains a keyword name (as a pointer to a null- | |
317 | * terminated string) and the address of its value. Argument | |
318 | * values are again copied into the structure. Note that a | |
319 | * vector doesn't store the arguments directly. This makes them | |
320 | * rather cumbersome to set up, but the benefit is a simple and | |
321 | * uniform approach for all keyword arguments. | |
322 | * | |
323 | * The main application for argument vectors is for `front-end' | |
324 | * functions which want to pass on some subset of their keywords | |
325 | * to another function. There isn't currently any macrology | |
326 | * provided for achieving this, but it's not especially | |
327 | * difficult. | |
328 | * | |
329 | * There are (currently) two special keyword arguments, whose | |
330 | * names are not valid identifiers. Future additions will also | |
331 | * have names beginning `kw.'. | |
332 | * | |
333 | * * `kw.valist' -- the corresponding argument has type | |
334 | * @va_list *@, and represents an entire variable-length | |
335 | * argument tail to process, including the first keyword | |
336 | * name. | |
337 | * | |
338 | * * `kw.tab' -- the corresponding argument is a vector of | |
339 | * @struct kwval@ items to process. In a variable-length | |
340 | * argument tail, this is passed as two arguments: the base | |
341 | * address of the vector, and the length (as a @size_t@). | |
342 | * In an argument vector, this is passed instead as a value | |
343 | * of type @struct kwtab@. | |
344 | * | |
345 | * If an unknown keyword is encountered while parsing, the | |
346 | * function @kw_unknown@ is called. | |
347 | * | |
348 | * The keyword argument `kw.unknown' will never be defined. | |
349 | */ | |
350 | ||
351 | #define KWSET_PARSEFN(set) \ | |
352 | void set##_kwparse(struct set##_kwargs *kw, \ | |
353 | const char *kwfirst, va_list *ap, \ | |
354 | const struct kwval *v, size_t n) \ | |
355 | { \ | |
356 | const char *k, *kk; \ | |
357 | va_list *aap; \ | |
358 | const struct kwtab *t; \ | |
359 | const struct kwval *vv; \ | |
360 | size_t nn; \ | |
361 | \ | |
362 | for (k = kwfirst; k; k = va_arg(*ap, const char *)) { \ | |
0f3e4dbf MW |
363 | set##_KWSET(KWSET__ARGVA) \ |
364 | /*else*/ if (!strcmp(k, "kw.valist")) { \ | |
9e91c8e7 MW |
365 | aap = va_arg(*ap, va_list *); \ |
366 | kk = va_arg(*aap, const char *); \ | |
367 | set##_kwparse(kw, kk, aap, 0, 0); \ | |
368 | } else if (!strcmp(k, "kw.tab")) { \ | |
369 | vv = va_arg(*ap, const struct kwval *); \ | |
370 | nn = va_arg(*ap, size_t); \ | |
371 | set##_kwparse(kw, 0, 0, vv, nn); \ | |
0f3e4dbf | 372 | } else kw_unknown(#set, k); \ |
9e91c8e7 MW |
373 | } \ |
374 | \ | |
375 | while (n) { \ | |
0f3e4dbf MW |
376 | set##_KWSET(KWSET__ARGTAB) \ |
377 | /*else*/ if (!strcmp(v->kw, "kw.valist")) { \ | |
9e91c8e7 MW |
378 | aap = *(va_list *const *)v->val; \ |
379 | kk = va_arg(*aap, const char *); \ | |
380 | set##_kwparse(kw, kk, aap, 0, 0); \ | |
381 | } else if (!strcmp(v->kw, "kw.tab")) { \ | |
382 | t = (const struct kwtab *)v->val; \ | |
383 | set##_kwparse(kw, 0, 0, t->v, t->n); \ | |
0f3e4dbf | 384 | } else kw_unknown(#set, v->kw); \ |
9e91c8e7 MW |
385 | v++; n--; \ |
386 | } \ | |
387 | } | |
0f3e4dbf | 388 | |
9e91c8e7 | 389 | #define KWSET__ARGVA(type, name, dflt) \ |
0f3e4dbf | 390 | if (!strcmp(k, #name)) { \ |
9e91c8e7 MW |
391 | kw->name##_suppliedp = 1; \ |
392 | kw->name = va_arg(*ap, type); \ | |
0f3e4dbf | 393 | } else |
9e91c8e7 | 394 | #define KWSET__ARGTAB(type, name, dflt) \ |
0f3e4dbf | 395 | if (!strcmp(v->kw, #name)) { \ |
9e91c8e7 MW |
396 | kw->name##_suppliedp = 1; \ |
397 | kw->name = *(type const *)v->val; \ | |
0f3e4dbf | 398 | } else |
9e91c8e7 | 399 | |
4c7784e5 MW |
400 | #define KWSET_PARSEFN_ATOMS(set) \ |
401 | void set##_kwparse(struct set##_kwargs *kw, \ | |
402 | const char *kwfirst, va_list *ap, \ | |
403 | const struct kwval *v, size_t n) \ | |
404 | { \ | |
405 | const char *k, *kk; \ | |
406 | va_list *aap; \ | |
407 | const struct kwtab *t; \ | |
408 | const struct kwval *vv; \ | |
409 | size_t nn; \ | |
410 | \ | |
411 | for (k = kwfirst; k; k = va_arg(*ap, const char *)) { \ | |
412 | set##_KWSET(KWSET__ARGVA_ATOM) \ | |
413 | /*else*/ if (k == KA_VALIST) { \ | |
414 | aap = va_arg(*ap, va_list *); \ | |
415 | kk = va_arg(*aap, const char *); \ | |
416 | set##_kwparse(kw, kk, aap, 0, 0); \ | |
417 | } else if (k == KA_TAB) { \ | |
418 | vv = va_arg(*ap, const struct kwval *); \ | |
419 | nn = va_arg(*ap, size_t); \ | |
420 | set##_kwparse(kw, 0, 0, vv, nn); \ | |
421 | } else set##_KWSET(KWSET__ARGVA) \ | |
422 | /*else*/ if (!strcmp(k, KA_VALIST)) { \ | |
423 | aap = va_arg(*ap, va_list *); \ | |
424 | kk = va_arg(*aap, const char *); \ | |
425 | set##_kwparse(kw, kk, aap, 0, 0); \ | |
426 | } else if (!strcmp(k, KA_TAB)) { \ | |
427 | vv = va_arg(*ap, const struct kwval *); \ | |
428 | nn = va_arg(*ap, size_t); \ | |
429 | set##_kwparse(kw, 0, 0, vv, nn); \ | |
430 | } else kw_unknown(#set, k); \ | |
431 | } \ | |
432 | \ | |
433 | while (n) { \ | |
434 | set##_KWSET(KWSET__ARGTAB) \ | |
435 | /*else*/ if (!strcmp(v->kw, KA_VALIST)) { \ | |
436 | aap = *(va_list *const *)v->val; \ | |
437 | kk = va_arg(*aap, const char *); \ | |
438 | set##_kwparse(kw, kk, aap, 0, 0); \ | |
439 | } else if (!strcmp(v->kw, KA_TAB)) { \ | |
440 | t = (const struct kwtab *)v->val; \ | |
441 | set##_kwparse(kw, 0, 0, t->v, t->n); \ | |
442 | } else kw_unknown(#set, v->kw); \ | |
443 | v++; n--; \ | |
444 | } \ | |
445 | } | |
446 | ||
447 | #define KWSET__ARGVA_ATOM(type, name, dflt) \ | |
448 | if (k == KA(name)) { \ | |
449 | kw->name##_suppliedp = 1; \ | |
450 | kw->name = va_arg(*ap, type); \ | |
451 | } else | |
452 | #define KWSET__ARGTAB_ATOM(type, name, dflt) \ | |
453 | if (v->kw == KA(name)) { \ | |
454 | kw->name##_suppliedp = 1; \ | |
455 | kw->name = *(type const *)v->val; \ | |
456 | } else | |
457 | ||
458 | #define KWSET__ARGVA(type, name, dflt) \ | |
459 | if (!strcmp(k, #name)) { \ | |
460 | kw->name##_suppliedp = 1; \ | |
461 | kw->name = va_arg(*ap, type); \ | |
462 | } else | |
463 | #define KWSET__ARGTAB(type, name, dflt) \ | |
464 | if (!strcmp(v->kw, #name)) { \ | |
465 | kw->name##_suppliedp = 1; \ | |
466 | kw->name = *(type const *)v->val; \ | |
467 | } else | |
468 | ||
9e91c8e7 MW |
469 | /*----- Defining keyword-accepting functions ------------------------------*/ |
470 | ||
471 | /* --- @KWDECL@ --- * | |
472 | * | |
473 | * Arguments: @set@ = the keyword set name | |
474 | * @kw@ = the name for the keyword argument structure value | |
475 | * | |
476 | * Use: Declares and initializes a keyword argument structure object | |
477 | * @kw@. The `_suppliedp' members are initially all zero; the | |
478 | * argument value members are set to their default values as | |
479 | * specified in the keyword set definition macro. | |
480 | */ | |
481 | ||
482 | #define KWDECL(set, kw) \ | |
483 | struct set##_kwargs kw = \ | |
484 | { set##_KWSET(KWSET__SPINIT) set##_KWSET(KWSET__DFLT) } | |
485 | #define KWSET__SPINIT(type, name, dflt) 0, | |
486 | #define KWSET__DFLT(type, name, dflt) dflt, | |
487 | ||
488 | /* --- @KW_PARSE@, @KW_PARSE_EMPTY@ --- * | |
489 | * | |
490 | * Arguments: @set@ = the keyword set name | |
491 | * @kw@ = the name of the keyword argument structure | |
492 | * @kwfirst@ = the first keyword argument name from the | |
493 | * variable-length argument tail (and, therefore, the | |
494 | * final positional argument) | |
495 | * | |
496 | * Use: Invokes the appropriate `kwparse' function to process the | |
497 | * function's variable-length argument tail as keyword | |
498 | * arguments. | |
499 | * | |
500 | * It is recommended that functions avoid allocating resources | |
501 | * or making observable changes to program state until they have | |
502 | * successfully parsed their keyword arguments. | |
503 | * | |
504 | * It is not possible to define an empty keyword argument set. | |
505 | * If a function currently accepts no keyword argumets, but | |
506 | * wants to reserve the ability to accept them later, then it | |
507 | * should use @KW_PARSE_EMPTY@ (or, better, @KWPARSE_EMPTY@ | |
508 | * below). The keyword argument set name here is used only for | |
509 | * diagnostic purposes, and need not (and probably should not) | |
510 | * correspond to a keyword-set definition macro. | |
511 | */ | |
512 | ||
513 | #define KW_PARSE(set, kw, kwfirst) do { \ | |
514 | va_list ap_; \ | |
515 | va_start(ap_, kwfirst); \ | |
516 | set##_kwparse(&(kw), kwfirst, &ap_, 0, 0); \ | |
517 | va_end(ap_); \ | |
518 | } while (0) | |
519 | ||
520 | #define KW_PARSE_EMPTY(set, kwfirst) do { \ | |
521 | va_list ap_; \ | |
522 | va_start(ap_, kwfirst); \ | |
523 | kw_parseempty(#set, kwfirst, &ap, 0, 0); \ | |
524 | va_end(ap_); \ | |
525 | } while (0) | |
526 | ||
527 | /* --- @KWPARSE@, @KWPARSE_EMPTY@ --- * | |
528 | * | |
529 | * Arguments: @set@ = the keyword set name | |
530 | * | |
531 | * Use: All-in-one keyword parsing for simple cases. | |
532 | * | |
533 | * This declares a keyword argument structure literally named | |
534 | * @kw@, and parses the function's variable-length argument tail | |
535 | * on the assumption that the function's argument list prototype | |
536 | * contains a @KWTAIL@ marker. | |
537 | * | |
538 | * It is recommended that functions avoid allocating resources | |
539 | * or making observable changes to program state until they have | |
540 | * successfully parsed their keyword arguments. | |
541 | * | |
542 | * In C89, this macro must be placed precisely between the | |
543 | * declarations at the start of the function body, and the | |
544 | * statements after them. | |
545 | * | |
546 | * It is not possible to define an empty keyword argument set. | |
547 | * If a function currently accepts no keyword argumets, but | |
548 | * wants to reserve the ability to accept them later, then it | |
549 | * should use @KWPARSE_EMPTY@. The keyword argument set name | |
550 | * here is used only for diagnostic purposes, and need not (and | |
551 | * probably should not) correspond to a keyword-set definition | |
552 | * macro. | |
553 | */ | |
554 | ||
555 | #define KWPARSE(set) KWDECL(set, kw); KW_PARSE(set, kw, kwfirst_) | |
556 | ||
557 | #define KWPARSE_EMPTY(set) KW_PARSE_EMPTY(set, kwfirst_) | |
558 | ||
559 | /* --- @KW_COUNT@ --- * | |
560 | * | |
561 | * Arguments: @set@ = the keyword set name | |
562 | * | |
563 | * Use: Expands to the number of keywords defined in the @set@. | |
564 | */ | |
565 | ||
566 | #define KW_COUNT(set) (0u set##_KWSET(KW__COUNT)) | |
567 | #define KW__COUNT(type, name, dflt) + 1u | |
568 | ||
569 | /* --- @KW_COPY@ --- * | |
570 | * | |
571 | * Arguments: @fromset@ = the source keyword set name | |
572 | * @toset@ = the destination keyword set name | |
573 | * @kw@ = the source keyword argument structure | |
574 | * @v@ = the destination vector | |
575 | * @n@ = next free index in vector | |
576 | * | |
577 | * Use: Copies arguments from the source structure @kw@ into the | |
578 | * vector @v@. The structure @kw@ must have type @struct | |
579 | * fromset_kwargs *@. The argument @v@ must have type @struct | |
dcb086e9 MW |
580 | * kwval *@ (after array-to-pointer decay), and there must be a |
581 | * variable @n@ of sufficiently large integral type suitably | |
9e91c8e7 MW |
582 | * initialized. Elements of the vector, starting with element |
583 | * @n@, will be filled in with those keyword arguments defined | |
584 | * in @toset@ -- which must be a subset of @srcsrc@ from @kw@ | |
585 | * for which the `_suppliedp' flags are set. The @val@ members | |
586 | * will point directly into the @kw@ structure. The @n@ | |
587 | * counter will be updated, and on completion will contain the | |
588 | * index of the first unused entry in the vector. | |
589 | */ | |
590 | ||
591 | #define KW_COPY(fromset, toset, kw, v, n) do { \ | |
592 | const struct fromset##_kwargs *kw_ = &(kw); \ | |
593 | struct kwval *v_ = (v); \ | |
594 | size_t n_ = (n); \ | |
595 | toset##_KWSET(KW__COPY) \ | |
596 | (n) = n_; \ | |
597 | } while (0) | |
598 | ||
599 | #define KW__COPY(type, name, dflt) \ | |
600 | if (kw_->name##_suppliedp) { \ | |
601 | v_[n_].kw = #name; \ | |
602 | v_[n_].val = &kw_->name; \ | |
603 | n_++; \ | |
604 | } | |
605 | ||
606 | /*----- Functions provided ------------------------------------------------*/ | |
607 | ||
608 | /* --- @kw_unknown@ --- * | |
609 | * | |
610 | * Arguments: @const char *set@ = the keyword set name, as a string | |
611 | * @const char *kw@ = the unknown keyword argument, as a string | |
612 | * | |
613 | * Returns: Doesn't. | |
614 | * | |
615 | * Use: Called when an unrecognized keyword argument is encountered | |
616 | * during parsing. This calls the @kw_unkhook@ with the same | |
617 | * arguments. Recovery via @longjmp@ or a similar machanism is | |
618 | * acceptable. | |
619 | */ | |
620 | ||
621 | extern KW__NORETURN void kw_unknown(const char */*set*/, const char */*kw*/); | |
622 | ||
623 | /* --- @kw_defunknown@ --- * | |
624 | * | |
625 | * Arguments: @const char *set@ = keyword set name | |
626 | * @const char *kw@ = the offending keyword name | |
627 | * | |
628 | * Returns: Doesn't. | |
629 | * | |
630 | * Use: This is the default @kw_unkhook@ hook function. | |
631 | * | |
632 | * In a hosted implementation, this function reports an internal | |
633 | * error to stderr about the unknown keyword and calls @abort@. | |
634 | * It is an implementation responsibility for freestanding | |
635 | * implementations wanting to use this keyword argument | |
636 | * mechanism. | |
637 | */ | |
638 | ||
639 | extern KW__NORETURN kw_unkhookfn kw_defunknown; | |
640 | ||
641 | /* --- @kw__hookfailed@ --- * | |
642 | * | |
643 | * Arguments: --- | |
644 | * | |
645 | * Returns: Doesn't. | |
646 | * | |
647 | * Use: Called by @kw_unknown@ if the @kw_unkhook@ hook function | |
648 | * returns. | |
649 | * | |
650 | * User code is not expected to call this function. It exists | |
651 | * as an implementation respensibility for freestanding | |
652 | * implementations wanting to use this keyword argument | |
653 | * mechanism. | |
654 | */ | |
655 | ||
656 | extern KW__NORETURN void kw__hookfailed(void); | |
657 | ||
658 | /* --- @kw_parseempty@ --- * | |
659 | * | |
660 | * Arguments: @const char *set@ = the keyword set name, as a string | |
661 | * @const char *kwfirst@ = the first keyword argument name | |
662 | * @va_list *ap@ = pointer to argument-tail extraction state | |
663 | * @const struct kwval *v@ = base address of argument vector | |
664 | * @size_t n@ = size of argument vector | |
665 | * | |
666 | * Returns: --- | |
667 | * | |
668 | * Use: Goes through the motions of parsing keyword arguments, but | |
669 | * doesn't in fact handle any other than the standard ones | |
670 | * described above (see @KWSET_PARSEFN@). This is useful when a | |
671 | * function doesn't currently define any keyword arguments but | |
672 | * wants to reserve the right to define some in the future. | |
673 | * (The usual machinery can't be used in this case, since the | |
674 | * argument structure would be empty. Besides, it would be | |
675 | * pointless to include multiple copies of the same boilerplate | |
676 | * code in a program.) | |
677 | */ | |
678 | ||
679 | extern void kw_parseempty(const char */*set*/, | |
680 | const char */*kwfirst*/, va_list */*ap*/, | |
681 | const struct kwval */*v*/, size_t /*n*/); | |
682 | ||
683 | /*----- That's all, folks -------------------------------------------------*/ | |
684 | ||
685 | #ifdef __cplusplus | |
686 | } | |
687 | #endif | |
688 | ||
689 | #endif |