This section describes the types, macros, and functions exposed in the
@|<sod/keyword.h>| header file which provides support for defining and
-calling functions which make use of keyword arguments; see \xref{sec:concepts.keywords}.
+calling functions which make use of keyword arguments; see
+\xref{sec:concepts.keywords}.
\subsection{Type definitions} \label{sec:sec:runtime.keywords.types}
The header file defines two simple structure types, and a function type which
will be described later.
-\begin{describe}[struct kwval]{type}
+\begin{describe}{type}[struct kwval]
{struct kwval \{ \\ \ind
const char *kw; \\
const void *val; \-\\
the actual argument type.)
\end{describe}
-\begin{describe}[struct kwtab]{type}
+\begin{describe}{type}[struct kwtab]
{struct kwtab \{ \\ \ind
const struct kwval *v; \\
size_t n; \-\\
The following macros are intended to help with constructing keyword argument
lists. Their use is not essential, but may help prevent errors.
-\begin{describe}[KWARGS]{mac}{KWARGS(@<body>)}
+\begin{describe}{mac}[KWARGS]{KWARGS(@<body>)}
The @<body> encloses a sequence of keyword arguments expressed as calls to
argument consists of a sequence of calls to the keyword-argument macros
described below, one after another without any separation.
The following keyword-argument macros can be used within the @|KWARGS|
@<body> argument.
-\begin{describe}[K]{mac}{K(@<name>, @<value>)}
+\begin{describe}{mac}[K]{K(@<name>, @<value>)}
Passes a keyword @<name> and its corresponding @<value>, as a pair of
arguments. The @<name> should be a single identifier (not a quoted
string). The @<value> may be any C expression of the appropriate type.
\end{describe}
-\begin{describe}[K_VALIST]{mac}{K_VALIST(@<ap>)}
+\begin{describe}{mac}[K_VALIST]{K_VALIST(@<ap>)}
Passes an indirect variable-length argument tail. The argument @<ap>
should be an lvalue of type @|va_list|, which will be passed by reference.
\end{describe}
-\begin{describe}[K_TAB]{mac}{K_TAB(@<v>, @<n>)}
+\begin{describe}{mac}[K_TAB]{K_TAB(@<v>, @<n>)}
Passes a vector of keyword arguments. The argument @<v> should be the base
address of the vector, and @<n> should be the number of elements in the
vector.
\end{prog}
with no separation between them. For example:
\begin{prog}
- \#define example_KWSET(_) @\\ \\ \ind
- _(int, x, 0) @\\ \\
+ \#define example_KWSET(_) \macsl \\ \ind
+ _(int, x, 0) \macsl \\
_(const char *, y, NULL)
\end{prog}
The following macros define data types and functions used for collecting
keyword arguments.
-\begin{describe}[KWSET_STRUCT]{mac}{KWSET_STRUCT(@<set>);}
+\begin{describe}{mac}[KWSET_STRUCT]{KWSET_STRUCT(@<set>);}
The @|KWSET_STRUCT| macro defines a \emph{keyword structure} named @|struct
@<set>{}_kwargs|. For each argument defined in the keyword set, this
structure contains two members: one has exactly the @<name> and @<type>
type @|unsigned int| named @|@<name>{}_suppliedp|.
\end{describe}
-\begin{describe}[KWDECL]{mac}
+\begin{describe}{mac}[KWDECL]
{@<declaration-specifiers> KWDECL(@<set>, @<kw>);}
The macro declares and initializes a keyword argument structure variable
named @<kw> for the named keyword @<set>. The optional
corresponding defaults from the keyword-set definition.
\end{describe}
-\begin{describe}[KWSET_PARSEFN]{mac}
+\begin{describe}{mac}[KWSET_PARSEFN]
{@<declaration-specifiers> KWSET_PARSEFN(@<set>)}
The macro @|KWSET_PARSEFN| defines a keyword argument \emph{parser
which expects keyword arguments, but don't supply any and forget the null
pointer which terminates the (empty) list.} %
If @<kwfirst> is a null pointer, then @<ap> need not be a valid pointer;
- otherwise, the cursor object @|* @<ap>| will be modified as the function
+ otherwise, the cursor object @|*@<ap>| will be modified as the function
extracts successive arguments from the tail.
The keyword vector is read from the vector of @|kwval| structures starting
The following macros make use of the definitions described above to actually
make a function's keyword arguments available to it.
-\begin{describe}[KW_PARSE]{mac}{KW_PARSE(@<set>, @<kw>, @<kwfirst>);}
+\begin{describe}{mac}[KW_PARSE]{KW_PARSE(@<set>, @<kw>, @<kwfirst>);}
The @|KW_PARSE| macro invokes a keyword argument parsing function. The
@<set> argument should name a keyword set; @<kw> should be an lvalue of
type @|struct @<set>{}_kwargs|; and @<kwfirst> should be the name of the
appropriately.
\end{describe}
-\begin{describe}[KWPARSE]{mac}{KWPARSE(@<set>);}
+\begin{describe}{mac}[KWPARSE]{KWPARSE(@<set>);}
The macro @|KWPARSE| (note the lack of underscore) combines
\descref{KWDECL}{mac} and \descref{KW_PARSE}{mac}. It declares and
initializes a keyword argument structure variable with the fixed name
currently accept any keywords, but which might in the future be extended to
allow keyword arguments.
-\begin{describe}[KW_PARSE_EMPTY]{mac}{KW_PARSE_EMPTY(@<set>, @<kwfirst>);}
+\begin{describe}{mac}[KW_PARSE_EMPTY]{KW_PARSE_EMPTY(@<set>, @<kwfirst>);}
This is an analogue to \descref{KW_PARSE}{mac} which checks the keyword
argument list for a function which accepts no keyword arguments.
other than the special predefined ones.
\end{describe}
-\begin{describe}[KWPARSE_EMPTY]{mac}{KWPARSE_EMPTY(@<set>);}
+\begin{describe}{mac}[KWPARSE_EMPTY]{KWPARSE_EMPTY(@<set>);}
This is an analogue to \descref{KWPARSE}{mac} which checks that the
enclosing function has been passed no keyword arguments other than the
special predefined ones. It assumes that the first keyword name is in an
argument named @|kwfirst_|, as set up by the \descref{KWTAIL}[marker]{mac}.
\end{describe}
-\begin{describe}[kw_parseempty]{fun}
+\begin{describe}{fun}[kw_parseempty]
{void kw_parseempty%
(\=const char *@<set>,
const char *@<kwfirst>, va_list *@<ap>, \+\\
A few macros are provided to make this task easier.
-\begin{describe}[KW_COUNT]{mac}{KW_COUNT(@<set>)}
+\begin{describe}{mac}[KW_COUNT]{KW_COUNT(@<set>)}
Returns the number of keywords defined in a keyword set named @<set>.
\end{describe}
-\begin{describe}[KW_COPY]{mac}
+\begin{describe}{mac}[KW_COPY]
{KW_COPY(@<fromset>, @<toset>, @<kw>, @<v>, @<n>);}
The macro @|KW_COPY| populates a vector of @|kwval| structures from a
\descref{KWSET_PARSEFN}{mac} (and the \descref{kw_parseempty}[function]{fun})
call @|kw_unknown|.
-\begin{describe}[kw_unknown]{fun}
+\begin{describe}{fun}[kw_unknown]
{void kw_unknown(const char *@<set>, const char *@<kw>);}
This is a function of two arguments: @<set> points to the name of the
message to the standard error stream and calls \man{abort}{3}.
\end{describe}
-\begin{describe}[kw_unkhookfn]{type}
+\begin{describe}{type}[kw_unkhookfn]
{typedef void kw_unkhookfn(const char *@<set>, const char *@<kw>);}
The @|kw_unkhookfn| type is the type of unknown-keyword handler functions.
and @<kw> is the name of the offending unknown keyword.
\end{describe}
-\begin{describe}[kw_unkhook]{var}{kw_unkhookfn *kw_unkhook}
+\begin{describe}{var}[kw_unkhook]{kw_unkhookfn *kw_unkhook}
This variable\footnote{%
Having a single global hook variable is obviously inadequate for a modern
library, but dealing with multiple threads isn't currently possible
\descref{kw_defunknown}[function]{fun}.
\end{describe}
-\begin{describe}[kw_defunknown]{fun}
+\begin{describe}{fun}[kw_defunknown]
{void kw_defunknown(const char *@<set>, const char *@<kw>);}
This function simply writes a message to standard error, to the effect that
the keyword named by @<kw> is not known in the keyword set @<set>, and
else longjmp(kw_test_jmp, 2); \-\\
\} \\+
- \#define KW_TEST(flag, set, call) do \{ @\\ \\ \ind
- kw_unkhookfn *oldunk = kw_unkhook; @\\ \\
- kw_unkhook = kw_test_unknown; @\\ \\
- switch (setjmp(kw_test_jmp)) \{ @\\ \\ \ind
- case 0: call; abort(); @\\ \\
- case 1: flag = 1; break; @\\ \\
- case 2: flag = 0; break; @\\ \\
- default: abort(); @\\ \-\\
- \} @\\ \\
- kw_unkhook = oldunk; @\\ \-\\
+ \#define KW_TEST(flag, set, call) do \{ \macsl \\ \ind
+ kw_unkhookfn *oldunk = kw_unkhook; \macsl \\
+ kw_unkhook = kw_test_unknown; \macsl \\
+ switch (setjmp(kw_test_jmp)) \{ \macsl \\ \ind
+ case 0: call; abort(); \macsl \\
+ case 1: flag = 1; break; \macsl \\
+ case 2: flag = 0; break; \macsl \\
+ default: abort(); \macsl\-\\
+ \} \macsl \\
+ kw_unkhook = oldunk; \macsl\-\\
\} while (0) \\+
@/* Example of use */ \\
tricky to understand and use correctly and can't really be recommended for
general use.
-\begin{describe}[SOD_OFFSETDIFF]{mac}
+\begin{describe}{mac}[SOD_OFFSETDIFF]
{ptrdiff_t SOD_OFFSETDIFF(@<type>, @<member>_1, @<member>_2);}
Returns the signed offset between two members of a structure or union type.
to be very useful elsewhere.
\end{describe}
-\begin{describe}[SOD_ILAYOUT]{mac}
+\begin{describe}{mac}[SOD_ILAYOUT]
{@<cls>{}__ilayout *SOD_ILAYOUT(@<cls>, @<chead>, const void *@<obj>);}
Recovers the instance layout base address from a pointer to one of its
instance chains.
@|SOD_INSTBASE| macro (described below) is more suited to general use.
\end{describe}
-\begin{describe}[SOD_INSTBASE]{mac}{void *SOD_INSTBASE(const @<cls> *@<obj>)}
+\begin{describe}{mac}[SOD_INSTBASE]{void *SOD_INSTBASE(const @<cls> *@<obj>)}
Finds the base address of an instance's layout.
Given a pointer @<obj> to an instance, @|SOD_INSTBASE| returns the base
The following macros and functions query the runtime relationships between
instances and classes.
-\begin{describe}[SOD_CLASSOF]{mac}
+\begin{describe}{mac}[SOD_CLASSOF]
{const SodClass *SOD_CLASSOF(const @<cls> *@<obj>);}
Returns the class object describing an instance's dynamic class.
for @<cls> itself, it's called @|@<cls>{}__class|.)
\end{describe}
-\begin{describe}[sod_subclassp]{fun}
+\begin{describe}{fun}[sod_subclassp]
{int sod_subclassp(const SodClass *@<sub>, const SodClass *@<super>);}
Decide whether one class @<sub> is actually a subclass of another class
some (static) type into instance pointers of other static types to the same
instance.
-\begin{describe}[SOD_XCHAIN]{mac}
- {void *SOD_CHAIN(@<chead>, const @<cls> *@<obj>);}
+\begin{describe}{mac}[SOD_XCHAIN]
+ {void *SOD_XCHAIN(@<chead>, const @<cls> *@<obj>);}
Performs a `cross-chain upcast'.
Given a pointer @<obj> to an instance of a class of type @<cls> and the
\end{describe}
\begin{describe*}
- {\dhead[SOD_CONVERT]{mac}
+ {\dhead{mac}[SOD_CONVERT]
{@<cls> *SOD_CONVERT(@<cls>, const void *@<obj>);}
- \dhead[sod_convert]{fun}
+ \dhead{fun}[sod_convert]
{void *sod_convert(const SodClass *@<cls>, const void *@<obj>);}}
Perform general conversions (up-, down-, and cross-casts) on instance
pointers.
deallocation, and applications are free to use any suitable mechanism.
\begin{describe*}
- {\dhead[SOD_INIT]{mac}
+ {\dhead{mac}[SOD_INIT]
{@<cls> *SOD_INIT(@<cls>, void *@<p>, @<keywords>);}
- \dhead[sod_init]{fun}
+ \dhead{fun}[sod_init]
{void *sod_init(const SodClass *@<cls>, void *@<p>, \dots);}
- \dhead[sod_initv]{fun}
+ \dhead{fun}[sod_initv]
{void *sod_initv(const SodClass *@<cls>, void *@<p>, va_list @<ap>);}}
Imprints and initializes an instance of a class @<cls> in the storage
starting at address~@<p>.
\xref{sec:structures.layout.instance}.
\end{describe*}
-\begin{describe}[sod_teardown]{fun}{int sod_teardown(void *@<p>);}
+\begin{describe}{fun}[sod_teardown]{int sod_teardown(void *@<p>);}
Tears down an instance of a class, releasing any resources it holds.
This function is a very thin wrapper around sending the @|obj.teardown|
\subsubsection{Automatic storage duration}
The following macro constructs an instance with automatic storage duration.
-\begin{describe}[SOD_DECL]{mac}{SOD_DECL(@<cls>, @<var>, @<keywords>);}
+\begin{describe}{mac}[SOD_DECL]{SOD_DECL(@<cls>, @<var>, @<keywords>);}
Declares and initializes an instance with automatic storage duration.
Given a class name @<cls> and an identifier @<var>, @|SOD_DECL| declares
@|malloc| and @|free| are not available.
\begin{describe*}
- {\dhead[SOD_MAKE]{mac}{@<cls> *SOD_MAKE(@<cls>, @<keywords>);}
- \dhead[sod_make]{fun}{void *sod_make(const SodClass *@<cls>, \dots);}
- \dhead[sod_makev]{fun}
+ {\dhead{mac}[SOD_MAKE]{@<cls> *SOD_MAKE(@<cls>, @<keywords>);}
+ \dhead{fun}[sod_make]{void *sod_make(const SodClass *@<cls>, \dots);}
+ \dhead{fun}[sod_makev]
{void *sod_makev(const SodClass *@<cls>, va_list @<ap>);}}
Constructs and returns a pointer to a new instance of @<cls>.
probably be used where possible.
\end{describe*}
-\begin{describe}[sod_destroy]{fun}{int sod_destroy(void *@<p>);}
+\begin{describe}{fun}[sod_destroy]{int sod_destroy(void *@<p>);}
Tears down and frees an instance allocated using @|malloc|.
The pointer @<p> should be an instance pointer, i.e., a pointer to any of