chiark / gitweb /
lib/keyword.3: Fix some minor formatting errors.
[sod] / lib / keyword.3
CommitLineData
9e91c8e7
MW
1.\" -*-nroff-*-
2.\"
3.\" Keyword argument support
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.\" Highlight using terminal escapes, rather than overstriking.
28.\"\X'tty: sgr 1'
29.
30.\" String definitions and font selection.
31.ie t \{\
32. ds o \(bu
33. if \n(.g .fam P
34.\}
35.el \{\
36. ds o o
37.\}
38.
39.\" .hP TEXT -- start an indented paragraph with TEXT hanging off to the left
40.de hP
41.IP
42\h'-\w'\fB\\$1\ \fP'u'\fB\\$1\ \fP\c
43..
44.
45.de t(
46'in +\\n(.ku
47..
48.de t)
49.in
50..
51.
52.\"--------------------------------------------------------------------------
53.TH keyword 3 "16 December 2015" "Straylight/Edgeware" "Sensible Object Design"
54.
55.SH NAME
56keyword \- keyword argument support library
57.
58.\"--------------------------------------------------------------------------
59.SH SYNOPSIS
60.B #include <sod/keyword.h>
61.PP
62.B "struct kwval { const char *kw; const void *val; };"
63.br
64.B "struct kwtab { const struct kwval *v; size_t n; };"
65.br
66.BI "typedef void kw_unkhookfn(const char *" set ", const char *" kw ");"
67.PP
68.BI "#define " set "_KWSET(_) \e"
69.in +4m
70.BI "_(" name ", " type ", " default ") \e"
71.br
72\&...
73.in
74.IB declaration-specifiers " KWSET_STRUCT(" set ");"
75.br
76.IB declaration-specifiers " KWSET_PARSEFN(" set ")"
77.PP
78.B KWCALL
79.IB type0 " " func "(" type1 " " arg1 ,
80.RB ... ,
81.IB typen " " argn ,
82.B "KWTAIL);"
83.br
84.BI "KWDECL(" set ", " kw ");"
85.br
86.BI "KW_PARSE(" set ", " kw ", " kwfirst ");"
87.br
88.BI "KW_PARSE_EMPTY(" set ", " kwfirst ");"
89.br
90.BI "KWPARSE(" set ");"
91.br
92.BI "KWPARSE_EMPTY(" set ");"
93.PP
94.I val
95.B =
96.IB func "(" arg1 ,
97.RB ... ,
98.IB argn ,
99.BI "KWARGS(" \c
100.t(
101.BI "K(" name ", " value ")"
102.br
103.BI "K_VALIST(" ap ")"
104.br
105.BI "K_TAB(" v ", " n ")"
106.br
107.RB ... );
108.t)
109.br
110.I val
111.B =
112.IB func "(" arg1 ,
113.RB ... ,
114.IB argn ,
115.B "NO_KWARGS);"
116.PP
117.B unsigned
118.BI "KW_COUNT(" set ");"
119.br
120.B void
121.BI "KW_COPY(" \c
122.t(
123.IB fromset ", " toset ","
124.br
125.BI "const struct " fromset "_kwset *" kw ","
126.br
127.BI "struct kwval *" v ", size_t " n ");"
128.t)
129.PP
130.BI "void kw_unknown(const char *" set ", const char *" kw );
131.br
132.BI "void kw_parseempty(\fP" \c
133.t(
134.BI "const char *" set ,
135.BI "const char *" kwfirst ,
136.BI "va_list *" ap ,
137.br
138.BI "const struct kwval *" v ,
139.BI "size_t " n );
140.t)
141.PP
142.B "kw_unkhookfn *kw_unkhook;"
143.br
144.B "kw_unkhookfn kw_defunknown;"
145.
146.\"--------------------------------------------------------------------------
147.SH DESCRIPTION
148.
149.SS Theory
150In standard C,
151the actual arguments provided to a function
152are matched up with the formal arguments
153given in the function definition
154according to their ordering in a list.
155Unless the (rather cumbersome) machinery for dealing with
156variable-length argument tails
157.RB ( <stdarg.h> )
158is used,
159exactly the correct number of arguments must be supplied,
160and in the correct order.
161.PP
162A
163.I keyword argument
164is matched by its distinctive
165.IR name ,
166rather than by its position in a list.
167Keyword arguments may be
168.IR omitted ,
169causing some default behaviour by the function.
170A function can detect whether
171a particular keyword argument was supplied:
172so the default behaviour need not be the same as
173that caused by any specific value of the argument.
174.PP
175Keyword arguments can be provided in three ways.
176.hP 1.
177Directly, as a variable-length argument tail,
178consisting (for the most part \(en see below) of alternating
179keyword names, as pointers to null-terminated strings, and
180argument values, and
181terminated by a null pointer.
182This is somewhat error-prone,
183and the support library defines some macros
184which help ensure that keyword argument lists are well formed.
185.hP 2.
186Indirectly, through a
187.B va_list
188object capturing a variable-length argument tail
189passed to some other function.
190Such indirect argument tails have the same structure as
191the direct argument tails described above.
192Because
193.B va_list
194objects are hard to copy,
195the keyword-argument support library consistently passes
196.B va_list
197objects
198.I by reference
199throughout its programming interface.
200.hP 3.
201Indirectly, through a vector of
202.B struct kwval
203objects,
204each of which contains
205a keyword name, as a pointer to a null-terminated string, and
206the
207.I address
208of a corresponding argument value.
209(This indirection is necessary so that
210the items in the vector can be of uniform size.)
211Argument vectors are rather inconvenient to use,
212but are the only practical way in which a caller can decide at runtime
213which arguments to include in a call,
214which is useful when writing wrapper functions.
215.
216.SS Type definitions
217The header file defines two simple structure types.
218.PP
219.IP
220.nf
221.ft B
222struct kwval {
223 const char *kw;
224 const void *val;
225};
226.fi
227.PP
228The
229.B kwval
230structure describes a keyword argument name/value pair.
231The
232.B kw
233member points to the name,
234as a null-terminated string.
235The
236.B val
237member always contains the
238.I address
239of the value.
240(This somewhat inconvenient arrangement
241makes the size of a
242.B kwval
243object independent of the actual argument type.)
244.PP
245.IP
246.nf
247.ft B
248struct kwtab {
249 const struct kwval *v;
250 size_t n;
251};
252.fi
253.PP
254The
255.B kwtab
256structure describes a list of keyword arguments,
257represented as a vector of
258.B kwval
259structures.
260The
261.B v
262member points to the start of the vector;
263the
264.B n
265member contains the number of elements in the vector.
266.PP
267The
268.B kw_unkhookfn
269type is the type of
270unknown-keyword handler functions.
271See the descriptions of
272.B kw_unknown
273and
274.B kw_unkhook
275below.
276.
277.SS Calling functions with keyword arguments
278Functions which accept keyword arguments are ordinary C functions
279with variable-length argument tails.
280Hence, they can be called using ordinary C (of the right kind)
281and all will be well.
282However, argument lists must follow certain rules
283(which will be described in full below);
284failure to do this will result in
285.IR "undefined behaviour" .
286The header file provides integration with some C compilers
287in the form of macros which can be used to help the compiler diagnose
288errors in calls to keyword-accepting functions;
289but such support is rather limited at the moment.
290Some additional macros are provided for use in calls to such functions,
291and it is recommended that, where possible, these are used.
292In particular, it's all too easy to forget the trailing null terminator
293which marks the end of a list of keyword arguments.
294.PP
295That said, the underlying machinery is presented first,
296and the convenience macros are described later.
297.PP
298The argument tail,
299following the mandatory arguments,
300consists of a sequence of zero or more alternating
301keyword names,
302as pointers to null-terminated strings
303(with type
304.BR "const char *" ),
305and their argument values.
306This sequence is finally terminated by a null pointer
307(again with type
308.BR "const char *" )
309in place of a keyword name.
310.PP
311Each function may define for itself which keyword names it accepts,
312and what types the corresponding argument values should have.
313There are also (currently) three special keyword names.
314.TP
315.B kw.valist
316This special keyword is followed by a pointer to
317a variable-length argument tail cursor object, of type
318.BR "va_list *" .
319This cursor object will be modified as the function extracts
320successive arguments from the tail.
321The argument tail should consist of alternating
322keyword names and argument values, as described above,
323including the first keyword name.
324(This is therefore different from the convention used when calling
325keyword argument parser functions:
326see the description of the
327.B KW_PARSEFN
328macro below for more details about these.)
329The argument tail may itself contain the special keywords.
330.TP
331.B kw.tab
332This special keyword is followed by
333.I two
334argument values:
335a pointer to the base of a vector of
336.B kwval
337structures,
338and the number of elements in this vector
339(as a
340.BR size_t ).
341Each element of the vector describes a single keyword argument:
342the
343.B kw
344member points to the keyword's name, and
345the
346.B val
347member points to the value.
348The vector may contain special keywords.
349The
350.B val
351pointer for a
352.B kw.valist
353argument should contain the address of an object of type
354.B "va_list *"
355(and not point directly to the cursor object,
356since
357.B val
358is has type
359.B "const void *"
360but the cursor will be modified as its argument tail is traversed).
361The
362.B val
363pointer for a
364.B kw.tab
365argument should contain the address of a
366.B kwtab
367structure which itself contains the base address and length of
368the argument vector to be processed.
369.TP
370.B kw.unknown
371This keyword is never accepted by any function.
372If it is encountered,
373the
374.B kw_unknown
375function is called to report the situation as an error;
376see below.
377.PP
378It is possible to construct a circular structure
379of indirect argument lists
380(in a number of ways).
381Don't try to pass such a structure to a function:
382the result will be unbounded recursion
383or some other bad outcome.
384.PP
385The macro
386.BI "KWARGS(" body ")"
387wraps up a sequence of keyword arguments.
388The single
389.I body
390argument consists of a sequence of calls to
391the keyword-argument macros described below,
392one after another without any separation.
393.PP
394In C89, macro actual arguments are not permitted to be empty;
395if there are no keyword arguments to provide,
396then the argument-less macro
397.B NO_KWARGS
398should be used instead.
399If you're using C99 or later,
400it's fine to just write
401.B KWARGS()
402instead.
403.PP
404The following keyword-argument macros can be used
405within
406.BR KWARGS 's
407.I body
408argument.
409.TP
410.BI "K(" name ", " value ")"
411Passes a keyword name and its corresponding value,
412as a pair of arguments.
413The
414.I name
415should be a single identifier
416(not a quoted string).
417The
418.I value
419may be any C expression
420of the appropriate type.
421.TP
422.BI "K_VALIST(" ap ")"
423Passes an indirect variable-length argument tail.
424The argument
425.I ap
426should be an lvalue of type
427.B va_list
428which will be passed by reference.
429.TP
430.BI "K_TAB(" v ", " n ")"
431Passes a vector of keyword arguments.
432The argument
433.I v
434should be the base address of the vector, and
435.I n
436should be the number of elements in the vector.
437.
438.SS Defining functions with keyword arguments
439A
440.I "keyword set"
441defines the collection of keyword arguments
442accepted by a particular function.
443The same keyword set may be used by several functions.
444(If your function currently accepts no keyword arguments,
445but you plan to add some later,
446do not define a keyword set,
447and use the
448.B KWPARSE_EMPTY
449macro described below.)
450.PP
451Each keyword set has a name,
452which is a C identifier.
453It's good to choose meaningful and distinctive names for keyword sets.
454Keyword set names are meaningful at runtime:
455they are used as part of the
456.B kw_unknown
457protocol (described below),
458and may be examined by handler functions,
459or reported to a user in error messages.
460For a keyword set which is used only by a single function,
461it is recommended that the set be given the same name as the function.
462.PP
463The keyword arguments for a keyword set named
464.I set
465are described by a `list macro' named
466.IB set _KWSET \fR.
467This macro takes a single argument,
468conventionally named
469.RB ` _ '.
470It should expand to a sequence of one or more list items of the form
471.IP
472.BI "_(" type ", " name ", " default ")"
473.PP
474with no separation between them.
475.PP
476For example:
477.IP
478.nf
479.ft B
480#define example_KWSET(_) \e
481.in +4m
482_(int, x, 0) \e
483_(const char *, y, NULL)
484.fi
485.ft P
486.PP
487Each
488.I name
489should be a distinct C identifier;
490they will be used to name structure members.
491An argument
492.I name
493should not end with the suffix
494.RB ` _suppliedp '
495(for reasons which will soon become apparent).
496.PP
497Each
498.I type
499should be a C
500.I type-name
501such that
502.IP
503.IB type " " name ;
504.PP
505is a valid declaration:
506so it may consist of declaration specifiers and
507(possibly qualified) pointer declarator markers,
508but not array or function markers
509(since they must be placed after the
510.IR name ).
511This is the same requirement made by the standard
512.BR va_arg (3)
513macro.
514.PP
515Each
516.I default
517should be an initializer expression
518or brace-enclosed list,
519suitable for use in an aggregate initializer
520for a variable with automatic storage duration.
521(In C89, aggregate initializers may contain only constant expressions;
522this restriction was lifted in C99.)
523.PP
524The macro
525.B KWTAIL
526is expected to be used at the end of function parameter type list
527to indicate that the function accepts keyword arguments;
528if there are preceding mandatory arguments
529then the
530.B KWTAIL
531marker should be separated from them with a comma
532.RB ` , '.
533(It is permitted for a function parameter type list to contain
534only a
535.B KWTAIL
536marker.)
537.PP
538Specifically,
539the macro declares a mandatory argument
540.B const char *kwfirst_
541(to collect the first keyword name),
542and a variable-length argument tail.
543.PP
544The macro
545.B KWPARSE
546(described below)
547assumes that the enclosing function's argument list ends with a
548.B KWTAIL
549marker.
550The marker should be included both in the function's definition and
551in any declarations, e.g., in the corresponding header file.
552.PP
553The
554.B KWCALL
555macro acts as a declaration specifier for
556functions which accept keyword arguments.
557Its effect is to arrange for the compiler to check,
558as far as is possible,
559that calls to the function are well-formed
560according to the keyword-argument rules.
561The exact checking performed depends on the compiler's abilities
562(and how well supported the compiler is):
563it may check that every other argument is a string;
564it may check that the list is terminated with a null pointer;
565it may not do anything at all.
566Again, this marker should be included in a function's definition and
567in any declarations.
568.PP
569The
570.B KWSET_STRUCT
571macro defines a
572.IR "keyword structure" .
573If
574.I set
575is a keyword-set name then
576.IP
577.BI "KWSET_STRUCT(" set ");"
578.PP
579declares a structure
580.B struct
581.IB set _kwargs \fR.
582For each argument defined in the keyword set,
583this structure contains two members:
584one has exactly the
585.I name
586and
587.I type
588listed in the keyword set definition;
589the other is a 1-bit-wide bitfield of type
590.B "unsigned int"
591named
592.IB name _suppliedp \fR.
593.PP
594The macro
595.B KWDECL
596declares and initializes a keyword argument structure variable.
597If
598.I set
599is a keyword-set name then
600.IP
601.I declaration-specifiers
602.BI "KWDECL(" set ", " kw ");"
603.PP
604declares a variable of type
605.B struct
606.IB set _kwargs
607named
608.IR kw .
609The optional
610.I declaration-specifiers
611may provide additional storage-class,
612qualifiers,
613or other declaration specifiers.
614The
615.RB ` _suppliedp '
616flags are initialized to zero;
617the other members are initialized with the corresponding defaults
618from the keyword-set definition.
619.PP
620The macro
621.B KWSET_PARSEFN
622defines a keyword argument
623.IR "parser function" .
624If
625.I set
626is a keyword-set name then
627.IP
628.I declaration-specifiers
629.BI "KWSET_PARSEFN(" set ")"
630.PP
631(no trailing semicolon!)
632defines a function
633.IP
634.B void
635.IB set _kwparse( \c
636.t(
637.BI "struct " set "_kwargs *" kw ","
638.br
639.BI "const char *" kwfirst ", va_list *" ap ","
640.br
641.BI "const struct kwval *" v ", size_t " n ");"
642.t)
643.PP
644The macro call can
645(and usually will)
646be preceded by storage class specifiers such as
647.BR static ,
648for example to adjust the linkage of the name.
649(I don't recommend declaring parser functions
650.BR inline :
651parser functions are somewhat large, and
652modern compilers are pretty good at
653figuring out whether to inline static functions.)
654.PP
655The function's behaviour is as follows.
656It parses keyword arguments from
657a variable-length argument tail, and/or
658a vector of
659.B kwval
660structures.
661When a keyword argument is recognized,
662for some keyword
663.IR name ,
664the keyword argument structure pointed to by
665.I kw
666is updated:
667the flag
668.IB name _suppliedp
669is set to 1;
670and the argument value is stored (by simple assignment) in the
671.I name
672member.
673Hence, if the
674.RB ` _suppliedp '
675members are initialized to zero,
676the caller can determine which keyword arguments were supplied.
677It is not possible to discover whether two or more arguments
678have the same keyword:
679in this case,
680the value from the last such argument is left
681in the keyword argument structure,
682and any values from earlier arguments are lost.
683(For this purpose,
684the argument vector
685.I v
686is scanned
687.I after
688the variable-length argument tail captured in
689.IR ap .)
690.PP
691The variable-argument tail is read from the list described by
692.BI * ap \fR.
693The argument tail is expected to consist of alternating
694keyword strings (as ordinary null-terminated strings)
695and the corresponding values,
696terminated by a null pointer of type
697.B "const char *"
698in place of a keyword;
699except that the first keyword
700(or terminating null pointer, if no arguments are provided)
701is expected to have been extracted already
702and provided as the
703.I kwfirst
704argument;
705the first argument retrieved using the
706.B va_list
707cursor object should then be the value
708corresponding to the keyword named by
709.IR kwfirst .
710(This slightly unusual convention makes it possible for a function to
711collect the first keyword as a separate mandatory argument,
712which is essential if there are no other mandatory arguments.
713It also means that the compiler will emit a diagnostic
714if you attempt to call a function which expects keyword arguments,
715but don't supply any and
716forget the null pointer which terminates the (empty) list.)
717If
718.I kwfirst
719is a null pointer,
720then
721.I ap
722need not be a valid pointer;
723otherwise, the cursor object
724.BI * ap
725will be modified as the function extracts
726successive arguments from the tail.
727.PP
728The keyword vector is read from the vector of
729.B kwval
730structures starting at address
731.I v
732and containing the following
733.I n
734items.
735If
736.I n
737is zero then
738.I v
739need not be a valid pointer.
740.PP
741The function also handles the special
742.B kw.valist
743and
744.B kw.tab
745arguments described above.
746If an unrecognized keyword argument is encountered,
747then
748.B kw_unknown
749is called:
750see below for details.
751.PP
752The
753.B KW_PARSE
754macro invokes a keyword argument parsing function.
755If
756.I set
757is a keyword-set name,
758.I kw
759names a keyword argument structure variable of type
760.B struct
761.IB set _kwargs \fR,
762and
763.I kwfirst
764is the name of the enclosing function's last mandatory argument,
765which must have type
766.BR "const char *" ,
767then
768.IP
769.BI "KW_PARSE(" set ", " kw ", " kwfirst ");"
770.PP
771calls the function
772.IB set _kwparse
773with five arguments:
774the address of the keyword argument structure
775.IR kw ;
776the string pointer
777.IR kwfirst ;
778the address of a temporary argument-tail cursor object of type
779.BR va_list ,
780constructed on the assumption that
781.I kwfirst
782is the enclosing function's final keyword argument;
783a null pointer; and
784the value zero (signifying an empty keyword-argument vector).
785If the variable
786.I kw
787was declared using
788.B KWDECL
789and the function
790.IB set _kwparse
791has been defined using
792.B KWSET_PARSEFN
793then the effect is to parse the keyword arguments passed to the function
794and set the members of
795.I kw
796appropriately.
797.PP
798The macro
799.B KWPARSE
800(note the lack of underscore)
801combines
802.B KWDECL
803and
804.BR KW_PARSE .
805If
806.I set
807is a keyword-set name then
808.IP
809.BI "KWPARSE(" set ");"
810.PP
811declares and initializes a keyword argument structure variable
812with the fixed name
813.BR kw ,
814and parses the keyword arguments provided to the enclosing function,
815storing the results in
816.BR kw .
817It assumes that the first keyword name
818is in an argument named
819.BR kwfirst_ ,
820as set up by
5d3d5970
MW
821.B KWTAIL
822marker described above.
9e91c8e7
MW
823.PP
824The macro expands both to a variable declaration and a statement:
825in C89, declarations must precede statements,
826so under C89 rules this macro must appear exactly between
827the declarations at the head of a brace-enclosed block
828(typically the function body)
829and the statements at the end.
830This restriction was lifted in C99,
831so the macro may appear anywhere in the function body.
832However, it is recommended that callers avoid taking actions
833which might require cleanup
834before attempting to parse their keyword arguments,
835since keyword argument parsing functions invoke the
836.B kw_unknown
837handler if they encounter an unknown keyword,
838and the calling function will not get a chance
839to tidy up after itself if this happens.
840.PP
841As mentioned above,
842it is not permitted to define an empty keyword set.
843(Specifically, invoking
844.B KWSET_STRUCT
845for an empty keyword set would result in attempting to define
846a structure with no members, which C doesn't allow.)
847On the other hand, keyword arguments are a useful extension mechanism,
848and it's useful to be able to define a function which doesn't
849currently accept any keywords,
850but which might in the future be extended to allow keyword arguments.
851The macros
852.B KW_PARSE_EMPTY
853and
854.B KWPARSE_EMPTY
855are analogues of
856.B KW_PARSE
857and
858.B KWPARSE
859respectively,
860and handle this case.
861These macros take a keyword-set name as an argument,
862but this name is used only in diagnostic messages
863(e.g., if an unknown keyword name is encountered)
864and need not
865(and probably should not)
866correspond to a defined keyword set.
867.PP
868If
869.I set
870is an identifier then
871.IP
872.BI "KW_PARSE_EMPTY(" set ", " kwfirst ");"
873.PP
874calls the function
875.B kw_parseempty
876with five arguments:
877the
878.I set
879name, as a string;
880the string pointer
881.IR kwfirst ;
882the address of a temporary argument-tail cursor object of type
883.BR va_list ,
884constructed on the assumption that
885.I kwfirst
886is the enclosing function's final keyword argument;
887a null pointer; and
888the value zero (signifying an empty keyword-argument vector).
889The effect is to check that the argument tail contains
890no keyword arguments other than the special predefined ones.
891.PP
892If
893.I set
894is an identifier then
895.IP
5d3d5970 896.BI "KWPARSE_EMPTY(" set ");"
9e91c8e7
MW
897.PP
898(note the lack of underscore)
899checks that the enclosing function has been passed
900no keyword arguments other than the special predefined ones.
901It assumes that the function's parameter type list ends with the
902.B KWTAIL
903marker described above.
904.PP
905The
906.B kw_parseempty
907function checks an keyword argument list
908to make sure that contains no keyword arguments
909(other than the special ones described above).
910.PP
911The
912.I set
913argument should point to a null-terminated string:
914this will be reported as the keyword set name to
915.BR kw_unknown ,
916though it need not
917(and likely will not)
918refer to any defined keyword set.
919The remaining arguments are as for
920the keyword parsing functions
921defined by the
922.B KWSET_PARSEFN
923macro.
924.
925.SS "Wrapper functions"
926Most users will not need the hairy machinery involving argument vectors.
927Their main use is in defining
928.IR "wrapper functions" .
929Suppose there is a function
930.I f
931which accepts some keyword arguments,
932and we want to write a function
933.I g
934which accepts the same keywords recognized by
935.I f
936and some additional ones.
937Unfortunately
938.I f
939may behave differently depending on whether or not
940a particular keyword argument is supplied at all, but
941it's not possible to synthesize a valid
942.B va_list
943other than by simply capturing a live argument tail,
944and it's not possible to decide at runtime
945whether or not to include some arguments in a function call.
946It's still possible to write
947.IR g ,
948by building a vector of keyword arguments,
949collected one-by-one depending on the corresponding
950.RB ` _suppliedp '
951flags (see below).
952A few macros are provided to make this task easier.
953.PP
954The macro
955.B KW_COUNT
956returns the number of keywords defined in a keyword set.
957If
958.I set
959is a keyword-set name, then
960.IP
961.BI "KW_COUNT(" set ")"
962.PP
963returns the number of keywords defined by
964.IR set ,
965as a constant expression of type
966.BR "unsigned int" .
967.PP
968The macro
969.B KW_COPY
970populates a vector of
971.B kwval
972structures from a keyword-argument structure.
973If
974.I fromset
975and
976.I toset
977are two keyword-set names then
978.IP
979.BI "KW_COPY(" fromset ", " toset ", " kw ", " v ", " n ");"
980.PP
981will populate the vector
982.IR v ,
983taking argument values from
984.IR kw .
985The
986.I toset
987must be a subset of
988.IR fromset :
989i.e., for every keyword defined in
990.I toset
991there is a keyword defined in
992.I fromset
993with the same name and type.
994The remaining arguments are as follows:
995.I kw
996is a pointer to a
997.BI "struct " fromset "_kwset"
998keyword-argument structure which has been filled in,
999e.g., by the keyword-argument parsing function
1000.IB fromset _kwparse \fR;
1001.I v
1002is a pointer to a sufficiently large vector of
1003.B "struct kwval"
1004objects;
1005and
1006.I n
1007is an lvalue designating an object of integer type.
1008Successive elements of
1009.IR v ,
1010starting at index
1011.IR n ,
1012are filled in to refer to
1013the keyword arguments defined in
1014.I toset
1015whose
1016.RB ` _suppliedp '
1017flag is set in the argument structure pointed to by
1018.IR kw ;
1019for each such argument,
1020a pointer to the keyword name is stored in
1021the corresponding vector element's
1022.B kw
1023member, and
1024a pointer to the argument value,
1025held in the keyword argument structure,
1026is stored in the vector element's
1027.B val
1028member.
1029At the end of this,
1030the index
1031.I n
1032is advanced so as to contain the index of the first unused element of
1033.IR v .
1034Hence, at most
1035.BI KW_COUNT( toset )
1036elements of
1037.I v
1038will be used.
1039.
1040.SS Handling unknown-keyword errors
1041When parsing a variable-length argument tail,
1042it is not possible to continue after
1043encountering an unknown keyword name.
1044This is because it is necessary
1045to know the (promoted) type of the following argument value
1046in order to skip past it;
1047but the only clue provided as to the type is the keyword name,
1048which in this case is meaningless.
1049.PP
1050In this situation,
1051the parser functions generated by
1052.B KW_PARSEFN
1053(and the
1054.B kw_parseempty
1055function)
1056call
1057.BR kw_unknown .
1058This is a function of two arguments:
1059.I set
1060points to the name of the keyword set expected by the caller,
1061as a null-terminated string; and
1062.I kw
1063is the unknown keyword which was encountered.
1064All that
1065.B kw_unknown
1066does is invoke the function whose address is stored in
1067the global variable
1068.B kw_unkhook
1069with the same arguments.
1070The
1071.B kw_unknown
1072function never returns to its caller:
1073if the
1074.B kw_unkhook
1075function returns (which it shouldn't)
1076then
1077.B kw_unknown
1078writes a fatal error message to standard error
1079and calls
1080.BR abort (3).
1081.PP
1082By default
1083.B kw_unkhook
1084points to the function
1085.BR kw_defunknown ,
1086which just writes an error message
1087quoting the keyword set name
1088and offending keyword
1089to standard error
1090and calls
1091.BR abort (3).
1092.PP
1093(In freestanding environments,
1094the behaviour may be somewhat different:
1095porting the library to such environments involves
1096choosing appropriate behaviour for the target platform.)
1097.PP
1098As an example of the kind of special effect
1099which can be achieved using this hook,
1100the following hacking answers whether
1101a function recognizes a particular keyword argument.
1102.IP
1103.nf
1104.ft B
1105#define KWARGS_TEST(k, val) KWARGS(K(k, val) K(kw.unknown, 0))
1106
1107static jmp_buf kw_test_jmp;
1108
1109static void kw_test_unknown(const char *set, const char *kw)
1110{
1111 if (strcmp(kw, "kw.unknown")) longjmp(kw_test_jmp, 1);
1112 else longjmp(kw_test_jmp, 2);
1113}
1114
1115#define KW_TEST(flag, set, call) do { \e
1116 kw_unkhookfn *oldunk = kw_unkhook; \e
1117 kw_unkhook = kw_test_unknown; \e
1118 switch (setjmp(kw_test_jmp)) { \e
1119 case 0: call; abort(); \e
1120 case 1: flag = 1; break; \e
1121 case 2: flag = 0; break; \e
1122 default: abort(); \e
1123 } \e
1124 kw_unkhook = oldunk; \e
1125} while (0)
1126
1127/* Example of use */
1128int f;
1129KW_TEST(f, somefunc(1, "two", 3, KWARGS_TEST("shiny", 68.7)));
1130/* now f is nonzero if `somefunc' accepts the `shiny' keyword
1131 * (which we hope wants a double argument)
1132 */
1133.ft P
1134.fi
1135.
1136.\"--------------------------------------------------------------------------
1137.SH BUGS
1138.
1139The unknown-keyword hook is inadequate for a modern library,
1140but dealing with multiple threads isn't currently possible
1141without writing (moderately complex) system-specific code.
1142The author's intention is that the hook variable
1143.B kw_unkhook
1144be `owned' by some external library
1145which can make its functionality available to client programs
1146in a safer and more convenient way.
1147On Unix-like platforms
1148(including Cygwin)
1149that library will be (a later version) of
1150.BR mLib ;
1151other platforms will likely need different arrangements.
1152The author is willing to coordinate any such efforts.
1153.PP
1154The whole interface is rather clunky.
1155Working with keyword-argument vectors is especially unpleasant.
1156The remarkable thing is not that it's done well,
1157but that it can be done at all.
1158.
1159.\"--------------------------------------------------------------------------
1160.SH SEE ALSO
1161.
1162.BR va_start (3),
1163.BR va_arg (3),
1164.BR va_end (3).
1165.
1166.\"--------------------------------------------------------------------------
1167.SH AUTHOR
1168.
1169Mark Wooding,
1170<mdw@distorted.org.uk>
1171.
1172.\"----- That's all, folks --------------------------------------------------