src/final.lisp: Slightly tweak `clear-the-decks' usage.
[sod] / doc / runtime.tex
index 0a44f91..a4a15ed 100644 (file)
@@ -43,9 +43,9 @@ The header file defines two simple structure types, and a function type which
 will be described later.
 
 \begin{describe}[struct kwval]{type}
 will be described later.
 
 \begin{describe}[struct kwval]{type}
-    {struct kwval \{ \\ \ind
-       const char *kw; \\
-       const void *val; \- \\
+    {struct kwval \{                                            \\ \ind
+       const char *kw;                                          \\
+       const void *val;                                       \-\\
      \};}
 
   The @|kwval| structure describes a keyword argument name/value pair.  The
      \};}
 
   The @|kwval| structure describes a keyword argument name/value pair.  The
@@ -56,9 +56,9 @@ will be described later.
 \end{describe}
 
 \begin{describe}[struct kwtab]{type}
 \end{describe}
 
 \begin{describe}[struct kwtab]{type}
-    {struct kwtab \{ \\ \ind
-       const struct kwval *v; \\
-       size_t n; \- \\
+    {struct kwtab \{                                            \\ \ind
+       const struct kwval *v;                                   \\
+       size_t n;                                              \-\\
      \};}
 
   The @|kwtab| structure describes a list of keyword arguments, represented
      \};}
 
   The @|kwtab| structure describes a list of keyword arguments, represented
@@ -203,8 +203,8 @@ list items of the form
 \end{prog}
 with no separation between them.  For example:
 \begin{prog}
 \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}
 
     _(const char *, y, NULL)
 \end{prog}
 
@@ -285,9 +285,10 @@ keyword arguments.
   The macro @|KWSET_PARSEFN| defines a keyword argument \emph{parser
   function}
   \begin{prog}
   The macro @|KWSET_PARSEFN| defines a keyword argument \emph{parser
   function}
   \begin{prog}
-    void @<set>{}_kwparse(\=struct @<set>{}_kwargs *@<kw>,
-                            const char *@<kwfirst>, va_list *@<ap>, \+ \\
-                            const struct kwval *@<v>, size_t @<n>);
+    void @<set>{}_kwparse%
+      (\=struct @<set>{}_kwargs *@<kw>,
+         const char *@<kwfirst>, va_list *@<ap>,              \+\\
+         const struct kwval *@<v>, size_t @<n>);
   \end{prog}
   The macro call can (and usually will) be preceded by storage class
   specifiers such as @|static|, for example to adjust the linkage of the
   \end{prog}
   The macro call can (and usually will) be preceded by storage class
   specifiers such as @|static|, for example to adjust the linkage of the
@@ -311,7 +312,7 @@ keyword arguments.
   purpose, the argument vector @<v> is scanned \emph{after} the
   variable-length argument tail captured in @<ap>.)
 
   purpose, the argument vector @<v> is scanned \emph{after} the
   variable-length argument tail captured in @<ap>.)
 
-  The variable-argument tail is read from the list described by @|* @<ap>|.
+  The variable-argument tail is read from the list described by @|*@<ap>|.
   The argument tail is expected to consist of alternating keyword strings (as
   ordinary null-terminated strings) and the corresponding values, terminated
   by a null pointer of type @|const char~*| in place of a keyword; except
   The argument tail is expected to consist of alternating keyword strings (as
   ordinary null-terminated strings) and the corresponding values, terminated
   by a null pointer of type @|const char~*| in place of a keyword; except
@@ -327,7 +328,7 @@ keyword arguments.
     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;
     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
   extracts successive arguments from the tail.
 
   The keyword vector is read from the vector of @|kwval| structures starting
@@ -417,9 +418,10 @@ allow keyword arguments.
 \end{describe}
 
 \begin{describe}[kw_parseempty]{fun}
 \end{describe}
 
 \begin{describe}[kw_parseempty]{fun}
-    {void kw_parseempty(\=const char *@<set>,
-                          const char *@<kwfirst>, va_list *@<ap>, \+ \\
-                          const struct kwval *@<v>, size_t @<n>);}
+    {void kw_parseempty%
+      (\=const char *@<set>,
+         const char *@<kwfirst>, va_list *@<ap>,              \+\\
+         const struct kwval *@<v>, size_t @<n>);}
   This function checks an keyword argument list to make sure that contains no
   keyword arguments (other than the special ones described in
   \xref{sec:runtime.keywords.calling}).
   This function checks an keyword argument list to make sure that contains no
   keyword arguments (other than the special ones described in
   \xref{sec:runtime.keywords.calling}).
@@ -551,32 +553,33 @@ particular keyword argument.
 
 \begin{prog}
   \#define KWARGS_TEST(k, val) KWARGS(K(k, val) K(kw.unknown, 0))
 
 \begin{prog}
   \#define KWARGS_TEST(k, val) KWARGS(K(k, val) K(kw.unknown, 0))
-  \\+
+                                                                \\+
   static jmp_buf kw_test_jmp;
   static jmp_buf kw_test_jmp;
-  \\+
-  static void kw_test_unknown(const char *set, const char *kw) \\
-  \{ \\ \ind
-    if (strcmp(kw, "kw.unknown")) longjmp(kw_test_jmp, 1); \\
-    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; \- @\\ \\
-  \} while (0)
-  \\+
-  /* Example of use */ \\
-  int f; \\
+                                                                \\+
+  static void kw_test_unknown(const char *set, const char *kw)  \\
+  \{                                                            \\ \ind
+    if (strcmp(kw, "kw.unknown")) longjmp(kw_test_jmp, 1);      \\
+    else longjmp(kw_test_jmp, 2);                             \-\\
+  \}                                                            \\+
+
+  \#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 */                                         \\
+  int f;                                                        \\
   KW_TEST(f, somefunc(1, "two", 3, KWARGS_TEST("shiny", 68.7))); \\
   KW_TEST(f, somefunc(1, "two", 3, KWARGS_TEST("shiny", 68.7))); \\
-  /\=* now f is nonzero if `somefunc' accepts the `shiny' keyword \+ \\
-   {}* (which we hope wants a double argument) \\
+  /\=* \comment{now @|f| is nonzero if @|somefunc| accepts the
+        @|shiny| keyword}                                     \+\\
+   {}* \comment{(which we hope wants a @|double| argument)}     \\
    {}*/
 \end{prog}
 
    {}*/
 \end{prog}
 
@@ -732,10 +735,51 @@ instance.
 The following macros and functions manage the standard steps along an
 instance's lifecycle.
 
 The following macros and functions manage the standard steps along an
 instance's lifecycle.
 
+\subsubsection{Low-level operations}
+The following macros and functions are agnostic with respect to storage
+allocation strategies.  They don't concern themselves with allocation or
+deallocation, and applications are free to use any suitable mechanism.
+
+\begin{describe*}
+    {\dhead[SOD_INIT]{mac}
+       {@<cls> *SOD_INIT(@<cls>, void *@<p>, @<keywords>);}
+     \dhead[sod_init]{fun}
+       {void *sod_init(const SodClass *@<cls>, void *@<p>, \dots);}
+     \dhead[sod_initv]{fun}
+       {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>.
+
+  The direct class for the new instance is specified as a class name to
+  @|SOD_INIT|, or a pointer to a class object to the functions.
+
+  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
+  @|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>.
+
+  The return value is an instance pointer for the class @<cls>; the
+  @|SOD_INIT| macro will have converted it to the correct type, so it should
+  probably be used where possible.  In fact, this is guaranteed to be equal
+  to @<p> by the layout rules described in
+  \xref{sec:structures.layout.instance}.
+\end{describe*}
+
+\begin{describe}[sod_teardown]{fun}{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}
+  for details.
+\end{describe}
+
 \subsubsection{Automatic storage duration}
 The following macro constructs an instance with automatic storage duration.
 
 \subsubsection{Automatic storage duration}
 The following macro constructs an instance with automatic storage duration.
 
-\begin{describe}[SOD_DECL]{mac}{SOD_DECL(@<cls>, @<var>);}
+\begin{describe}[SOD_DECL]{mac}{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
   Declares and initializes an instance with automatic storage duration.
 
   Given a class name @<cls> and an identifier @<var>, @|SOD_DECL| declares
@@ -744,8 +788,56 @@ The following macro constructs an instance with automatic storage duration.
   up, and slots for which initializers are defined are set to the appropriate
   initial values.
 
   up, and slots for which initializers are defined are set to the appropriate
   initial values.
 
+  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}.
+
   The instance has automatic storage duration: pointers to it will become
   The instance has automatic storage duration: pointers to it will become
-  invalid when control exits the scope of the declaration.
+  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}.
+\end{describe}
+
+\subsubsection{Dynamic allocation}
+The following macros and functions deal with objects allocated from the
+standard C heap.  They don't work in freestanding implementations where
+@|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}
+       {void *sod_makev(const SodClass *@<cls>, va_list @<ap>);}}
+  Constructs and returns a pointer to a new instance of @<cls>.
+
+  The direct class for the new instance is specified as a class name to
+  @|SOD_MAKE|, or a class object to the functions.
+
+  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
+  @|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}.
+
+  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>);}
+  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
+  for deallocation, then its storage is released using @|free|.  The return
+  value is the value returned by the @|obj.teardown| message.
 \end{describe}
 
 %%%----- That's all, folks --------------------------------------------------
 \end{describe}
 
 %%%----- That's all, folks --------------------------------------------------