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}{type}[struct kwval]
+\begin{describe}{ty}[struct kwval]
{struct kwval \{ \\ \ind
const char *kw; \\
const void *val; \-\\
the actual argument type.)
\end{describe}
-\begin{describe}{type}[struct kwtab]
+\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:
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|
*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 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}
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}{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
allow keyword arguments.
\begin{describe}{mac}[KW_PARSE_EMPTY]{KW_PARSE_EMPTY(@<set>, @<kwfirst>);}
- This is an analogue to \descref{KW_PARSE}{mac} which checks the keyword
+ 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
\end{describe}
\begin{describe}{mac}[KWPARSE_EMPTY]{KWPARSE_EMPTY(@<set>);}
- This is an analogue to \descref{KWPARSE}{mac} which checks that the
+ 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}{fun}[kw_parseempty]
\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}
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}{fun}[kw_unknown]
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}{type}[kw_unkhookfn]
+\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.
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}{fun}[kw_defunknown]
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}
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>.
\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}
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}
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
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}