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}{ty}[struct kwval]
{struct kwval \{ \\ \ind
const char *kw; \\
const void *val; \-\\
the actual argument type.)
\end{describe}
-\begin{describe}[struct kwtab]{type}
+\begin{describe}{ty}[struct kwtab]
{struct kwtab \{ \\ \ind
const struct kwval *v; \\
size_t n; \-\\
keyword names and argument values, as described above, including the first
keyword name. (This is therefore different from the convention used when
calling keyword argument parser functions: see the description of the
- \descref{KWSET_PARSEFN}[macro]{mac} for more details about these.) The
+ \descref{mac}{KWSET_PARSEFN}[macro] for more details about these.) The
argument tail may itself contain the special keywords.
\item[kw.tab] This special keyword is followed by \emph{two} argument values:
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.
- In C89, macro actual arguments are not permitted to be empty; if there are
- no keyword arguments to provide, and you're using a C89 compiler, then use
- @|NO_KWARGS| (below) instead. If your compiler supports C99 or later, it's
- fine to just write @|KWARGS()| instead.
+ If there are no keyword arguments, use @|NO_KWARGS| (below) instead.
\end{describe}
\begin{describe}{mac}{NO_KWARGS}
A marker, to be written instead of a @|KWARGS| invocation, to indicate that
no keyword arguments are to be passed to a function.
- This is unnecessary with compilers which support C99 or later, since once
- can use @|KWARGS()| with an empty @<body> argument.
+ Using this macro instead of @|KWARGS| if there are no arguments does two
+ things:
+ \begin{itemize}
+
+ \item C89 doesn't permit empty macro arguments for some reason, so
+ @|NO_KWARGS| is necessary when using a C89 compiler.
+
+ \item Omitting the null terminator is a common mistake, so @|<keyword.h>|
+ tries to get the compiler to warn if you miss it. However, the
+ \descref{mac}{KWTAIL}[macro] introduces an extra real argument
+ @|kwfirst_|, because it's not possible to scan a variable-length argument
+ tail if there are no mandatory arguments. If you use @|KWARGS()|, with
+ an empty argument list, then the null terminator is passed as @|kwfirst_|
+ and the variable-length tail ends up empty, which might trigger a
+ compiler warning about the missing terminator. @|NO_KWARGS| passes
+ \emph{two} null terminators: a real one to indicate that there are no
+ keyword arguments, and a dummy one to placate the compiler.
+
+ (Sod method entry functions don't have this extra argument, so
+ @|KWARGS()| would work fine for sending Sod messages with keyword
+ arguments if you're using C99 or later, but it's probably best to use the
+ version which always works.)
+
+ \end{itemize}
\end{describe}
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.
*kwfirst_| (to collect the first keyword name), and a variable-length
argument tail.
- The \descref{KWPARSE}[macro]{mac} assumes that the enclosing function's
+ The \descref{mac}{KWPARSE}[macro] assumes that the enclosing function's
argument list ends with a @|KWTAIL| marker.
\end{describe}
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 function also handles the special @|kw.valist| and @|kw.tab| arguments
described above (\xref{sec:runtime.keywords.calling}). If an unrecognized
- keyword argument is encountered, then \descref{kw_unknown}{fun} is called.
+ keyword argument is encountered, then \descref{fun}{kw_unknown} is called.
\end{describe}
\subsubsection{Parsing keywords}
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
final keyword argument; a null pointer; and the value zero (signifying an
empty keyword-argument vector).
- If the variable @<kw> was declared using \descref{KWDECL}{mac} and the
+ If the variable @<kw> was declared using \descref{mac}{KWDECL} and the
function @|@<set>{}_kwparse| has been defined using
- \descref{KWSET_PARSEFN}{mac} then the effect is to parse the keyword
+ \descref{mac}{KWSET_PARSEFN} then the effect is to parse the keyword
arguments passed to the function and set the members of @<kw>
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
+ \descref{mac}{KWDECL} and \descref{mac}{KW_PARSE}. It declares and
initializes a keyword argument structure variable with the fixed name
@|kw|, and parses the keyword arguments provided to the enclosing function,
storing the results in @|kw|. It assumes that the first keyword name is in
an argument named @|kwfirst_|, as set up by the
- \descref{KWTAIL}[marker]{mac}.
+ \descref{mac}{KWTAIL}[marker].
The macro expands both to a variable declaration and a statement: in C89,
declarations must precede statements, so under C89 rules this macro must
\end{describe}
As mentioned above, it is not permitted to define an empty keyword set.
-(Specifically, invoking \descref{KWSET_STRUCT}{mac} for an empty keyword set
+(Specifically, invoking \descref{mac}{KWSET_STRUCT} for an empty keyword set
would result in attempting to define a structure with no members, which C
doesn't allow.) On the other hand, keyword arguments are a useful extension
mechanism, and it's useful to be able to define a function which doesn't
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>);}
- This is an analogue to \descref{KW_PARSE}{mac} which checks the keyword
+\begin{describe}{mac}[KW_PARSE_EMPTY]{KW_PARSE_EMPTY(@<set>, @<kwfirst>);}
+ This is an analogue to \descref{mac}{KW_PARSE} which checks the keyword
argument list for a function which accepts no keyword arguments.
- It calls the \descref{kw_parseempty}[function]{fun} with five arguments:
+ It calls the \descref{fun}{kw_parseempty}[function] with five arguments:
the @<set> name, as a string; the string pointer @<kwfirst>; the address of
a temporary argument-tail cursor object of type @|va_list|, constructed on
the assumption that @<kwfirst> is the enclosing function's final keyword
other than the special predefined ones.
\end{describe}
-\begin{describe}[KWPARSE_EMPTY]{mac}{KWPARSE_EMPTY(@<set>);}
- This is an analogue to \descref{KWPARSE}{mac} which checks that the
+\begin{describe}{mac}[KWPARSE_EMPTY]{KWPARSE_EMPTY(@<set>);}
+ This is an analogue to \descref{mac}{KWPARSE} 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}.
+ argument named @|kwfirst_|, as set up by the \descref{mac}{KWTAIL}[marker].
\end{describe}
-\begin{describe}[kw_parseempty]{fun}
+\begin{describe}{fun}[kw_parseempty]
{void kw_parseempty%
(\=const char *@<set>,
const char *@<kwfirst>, va_list *@<ap>, \+\\
\xref{sec:runtime.keywords.calling}).
The @<set> argument should point to a null-terminated string: this will be
- reported as the keyword set name to \descref{kw_unknown}{fun}, though it
+ reported as the keyword set name to \descref{fun}{kw_unknown}, though it
need not (and likely will not) refer to any defined keyword set. The
remaining arguments are as for the keyword parsing functions defined by the
- \descref{KWSET_PARSEFN}[macro]{mac}.
+ \descref{mac}{KWSET_PARSEFN}[macro].
\end{describe}
\subsection{Function wrappers} \label{sec:runtime.keywords.wrappers}
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
in this case is meaningless.
In this situation, the parser functions generated by
-\descref{KWSET_PARSEFN}{mac} (and the \descref{kw_parseempty}[function]{fun})
+\descref{mac}{KWSET_PARSEFN} (and the \descref{fun}{kw_parseempty}[function])
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
keyword set expected by the caller, as a null-terminated string; and @<kw>
is the unknown keyword which was encountered. All that @|kw_unknown| does
is invoke the function whose address is stored in the global variable
- \descref{kw_unkhook}{var} with the same arguments.
+ \descref{var}{kw_unkhook} with the same arguments.
This function never returns to its caller: if the @|kw_unkhook| function
returns (which it shouldn't) then @|kw_unknown| writes a fatal error
message to the standard error stream and calls \man{abort}{3}.
\end{describe}
-\begin{describe}[kw_unkhookfn]{type}
+\begin{describe}{ty}[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
need different arrangements. The author is willing to coordinate any
such efforts.} %
holds the current unknown-keyword handler function. It will be invoked by
- \descref{kw_unknown}{fun}. The function may take whatever action seems
+ \descref{fun}{kw_unknown}. The function may take whatever action seems
appropriate, but should not return to its caller.
Initially, this variable points to the
- \descref{kw_defunknown}[function]{fun}.
+ \descref{fun}{kw_defunknown}[function].
\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
calls \man{abort}{3}.
- This function is the default value of the \descref{kw_unkhook}[hook
- variable]{var}.
+ This function is the default value of the \descref{var}{kw_unkhook}[hook
+ variable].
\end{describe}
As an example of the kind of special effect which can be achieved using this
While the translator can (at some effort) support alternative roots, they
will require different run-time support machinery.
+\begin{describe}{feat}{SOD_RECKLESS}
+ Some of Sod's macros include runtime checking by default. This checking
+ can be disabled if you value performance more than early diagnosis of
+ problems. Define @|SOD_RECKLESS| to a nonzero value before including
+ @|<sod/sod.h>| to inhibit the runtime checking.
+\end{describe}
+
\subsection{Layout utilities} \label{sec:runtime.object.layout}
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>.
Keyword arguments for the initialization message may be provided. The
@|SOD_INIT| macro expects a single preprocessor-time argument which is
- a use of one of \descref{KWARGS}{mac} or \descref{NO_KWARGS}{mac}; the
+ a use of one of \descref*{mac}{KWARGS} or \descref{mac}{NO_KWARGS}; the
@|sod_init| function expects the keywords as a variable-length argument
tail; and @|sod_initv| expects the keywords to be passed indirectly,
through the captured argument-tail cursor @<ap>.
\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|
- message. See the description of that message
- (page~\pageref{msg:obj.teardown}) and \xref{sec:concepts.lifecycle.death}
+ This function is a very thin wrapper around sending the
+ \descref*{msg}{obj.teardown} message. See the description of that message
+ (\autopageref{msg:obj.teardown}) and \xref{sec:concepts.lifecycle.death}
for details.
\end{describe}
\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
Keyword arguments for the initialization message may be provided. The
macro expects a single preprocessor-time argument which is a use of one of
- \descref{KWARGS}{mac} or \descref{NO_KWARGS}{mac}.
+ \descref*{mac}{KWARGS} or \descref{mac}{NO_KWARGS}.
The instance has automatic storage duration: pointers to it will become
invalid when control exits the scope of the declaration. If necessary, the
instance should be torn down before this happens, using the
- \descref{sod_teardown}[function]{fun}.
+ \descref{fun}{sod_teardown}[function]. It may be appropriate to @|assert|
+ that the object is ready for deallocation at this time.
+
+ By default, this macro will abort the program if the size allocated for the
+ instance doesn't match the size required by the class object; set
+ \descref{feat}{SOD_RECKLESS} to inhibit this check.
\end{describe}
\subsubsection{Dynamic allocation}
@|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>.
Keyword arguments for the initialization message may be provided. The
@|SOD_MAKE| macro expects a single preprocessor-time argument which is
- a use of one of \descref{KWARGS}{mac} or \descref{NO_KWARGS}{mac}; the
+ a use of one of \descref*{mac}{KWARGS} or \descref{mac}{NO_KWARGS}; the
@|sod_make| function expects the keywords as a variable-length argument
tail; and @|sod_makev| expects the keywords to be passed indirectly,
through the captured argument-tail cursor @<ap>.
Storage for the new instance will have been allocated using the standard
@|malloc| function. The easiest way to destroy the instance, when it is no
longer needed, is probably to call the
- \descref{sod_destroy}[function]{fun}.
+ \descref{fun}{sod_destroy}[function].
The return value is an instance pointer for the class @<cls>; the
@|SOD_MAKE| macro will have converted it to the correct type, so it should
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
an instance's chains. The instance is torn down, by sending it the
- \descref{obj.teardown}[message]{msg}. If the instance reports itself ready
+ \descref{msg}{obj.teardown}[message]. If the instance reports itself ready
for deallocation, then its storage is released using @|free|. The return
value is the value returned by the @|obj.teardown| message.
\end{describe}