chiark / gitweb /
doc/structures.tex, lib/sod-structs.3: Fix in-chain ichain exemplar.
[sod] / lib / sod.h
index 360afa83907a9c1b4e2eccae023308eefdb9f633..faffb2091b6fd8b1d481fe4154b5d74d51aeb7dd 100644 (file)
--- a/lib/sod.h
+++ b/lib/sod.h
 
 /*----- Preliminary utilities ---------------------------------------------*/
 
+/* Various hacks for checking compiler versions. */
+#define SOD__GCC_P(maj, min)                                           \
+       (__GNUC__ > (maj) || (__GNUC__ == (maj) && __GNUC_MINOR__ >= (min)))
+
+#ifdef __GNUC__
+#  define SOD__EXTENSION __extension__
+#else
+#  define SOD__EXTENSION
+#endif
+
 /* --- @SOD__HAVE_VARARGS_MACROS@ --- *
  *
  * Use:                Defined if the compiler supports C99-style variadic macros.
@@ -49,7 +59,7 @@
 
 #  define SOD__HAVE_VARARGS_MACROS
 
-#elif __GNUC__ >= 3
+#elif SOD__GCC_P(3, 0)
    /* We're using GCC, which is trying to deny it but we don't believe it.
     * Unfortunately there's a fly in the ointment: if `-pedantic' -- or,
     * worse, `-pedantic-errors' -- is set, then GCC will warn about these
 /* We're going to want to make use of this ourselves. */
 SOD__VARARGS_MACROS_PREAMBLE
 
+/* --- @SOD__ALIGNOF@ --- *
+ *
+ * Arguments:  @type@ = a C type name, consisting of declaration specifiers
+ *                     and `*[QUALIFIERS]' declarator operators
+ *
+ * Returns:    A sufficient alignment for objects of the given @type@, as a
+ *             @size_t@.
+ */
+
+#if __STDC_VERSION__ >= 201112
+#  define SOD__ALIGNOF(type) _Alignof(type)
+#elif SOD__GCC_P(4, 7)
+#  define SOD__ALIGNOF(type) __extension__ _Alignof(type)
+#elif defined(__GNUC__)
+#  define SOD__ALIGNOF(type) __alignof__(type)
+#else
+#  define SOD__ALIGNOF(type)                                           \
+offsetof(struct { char sod__x; type sod__y; }, sod__y)
+#endif
+
+/* --- @SOD__IGNORE@ --- *
+ *
+ * Arguments:  @var@ = some variable name
+ *
+ * Use:                Suppress any warning that @var@ isn't used.
+ */
+
+#define SOD__IGNORE(var) ((void)(var))
+
 /* --- @SOD__CAR@ --- *
  *
  * Arguments:  @...@ = a nonempty list of arguments
@@ -85,7 +124,7 @@ SOD__VARARGS_MACROS_PREAMBLE
  */
 
 #ifdef SOD__HAVE_VARARGS_MACROS
-#  define SOD__CAR(...) SOD__CARx(__VA_LIST__, _)
+#  define SOD__CAR(...) SOD__CARx(__VA_ARGS__, _)
 #  define SOD__CARx(a, ...) a
 #endif
 
@@ -94,6 +133,7 @@ SOD__VARARGS_MACROS_PREAMBLE
 #include <stdarg.h>
 #include <stddef.h>
 
+#include "keyword.h"
 #include "sod-base.h"
 
 /*----- Data structures ---------------------------------------------------*/
@@ -226,18 +266,42 @@ struct sod_chain {
 
 #define SOD_CONVERT(cls, obj) ((cls *)sod_convert(cls##__class, (obj)))
 
+/* --- @SOD_INIT@ --- *
+ *
+ * Arguments:  @cls@ = a class type name
+ *             @p@ = pointer to storage to initialize
+ *             @keys@ = a @KWARGS(...)@ keyword argument sequence
+ *
+ * Use:                Initializes raw storage as an instance of @cls@.
+ */
+
+#define SOD_INIT(cls, p, keys) ((cls *)sod_init(cls##__class, (p), keys))
+
+/* --- @SOD_MAKE@ --- *
+ *
+ * Arguments:  @cls@ = a class type name
+ *             @keys@ = a @KWARGS(...)@ keyword argument sequence
+ *
+ * Use:                Allocates (using @malloc@) eand initializes storage to be an
+ *             instance of @cls@.  Returns a null pointer if allocation
+ *             fails.  Use @sod_destroy@ to release the instance.
+ */
+
+#define SOD_MAKE(cls, keys) ((cls *)sod_make(cls##__class, keys))
+
 /* --- @SOD_DECL@ --- *
  *
- * Arguments:  @cls_@ = a class type name
- *             @var_@ = a variable name
+ * Arguments:  @cls@ = a class type name
+ *             @var@ = a variable name
+ *             @keys@ = a @KWARGS(...)@ keyword argument sequence
  *
- * Use:                Declare @var_@ as a pointer to an initialized instance of
- *             @cls_@ with automatic lifetime.
+ * Use:                Declare @var@ as a pointer to an initialized instance of
+ *             @cls@ with automatic lifetime.
  */
 
-#define SOD_DECL(cls_, var_)                                           \
-  struct cls_##__ilayout var_##__layout;                               \
-  cls_ *var_ = cls_##__class->cls.init(&var_##__layout)
+#define SOD_DECL(cls, var, keys)                                       \
+  struct cls##__ilayout var##__layout;                                 \
+  cls *var = (cls *)sod_init(cls##__class, &var##__layout, keys)
 
 /*----- Functions provided ------------------------------------------------*/
 
@@ -278,6 +342,95 @@ extern int sod_subclassp(const SodClass */*sub*/, const SodClass */*super*/);
 
 extern void *sod_convert(const SodClass */*cls*/, const void */*obj*/);
 
+/* --- @sod_init@, @sod_initv@ --- *
+ *
+ * Arguments:  @const SodClass *cls@ = class object for new instance
+ *             @void *p@ = pointer to storage for new instance
+ *             @va_list ap, ...@ = initialization keyword arguments
+ *
+ * Returns:    Pointer to the initialized instance.
+ *
+ * Use:                Initializes an instance in pre-allocated storage, and returns
+ *             a pointer to it.
+ *
+ *             This function will imprint the storage, and then send an
+ *             `initialize' message to the fresh instance containing the
+ *             provided keyword arguments.
+ *
+ *             It's usually convenient to use the macro @SOD_INIT@ rather
+ *             than calling @sod_init@ directly.
+ */
+
+extern KWCALL void *sod_init(const SodClass */*cls*/, void */*p*/, ...);
+extern void *sod_initv(const SodClass */*cls*/, void */*p*/, va_list /*ap*/);
+
+/* --- @sod_make@, @sod_makev@ --- *
+ *
+ * Arguments:  @const SodClass *cls@ = class object for new instance
+ *             @va_list ap, ...@ = initialization keyword arguments
+ *
+ * Returns:    Pointer to the newly-allocated initialized instance, or null.
+ *
+ * Use:                Allocates storage for a new instance, initializes it, and
+ *             returns a pointer to it.  If allocation fails, a null pointer
+ *             is returned instead.
+ *
+ *             This function will allocate the storage using @malloc@, and
+ *             then initialize it as for @sod_init@.
+ *
+ *             It's usually convenient to use the macro @SOD_MAKE@ rather
+ *             than calling @sod_make@ directly.
+ *
+ *             (This function is not available in freestanding environments
+ *             lacking @malloc@ and @free@.)
+ */
+
+extern KWCALL void *sod_make(const SodClass */*cls*/, ...);
+extern void *sod_makev(const SodClass */*cls*/, va_list /*ap*/);
+
+/* --- @sod_teardown@ --- *
+ *
+ * Arguments:  @void *p@ = pointer to an instance to be torn down
+ *
+ * Returns:    Zero if the object is torn down; nonzero if it refused for
+ *             some reason.
+ *
+ * Use:                Invokes the instance's `teardown' method to release any held
+ *             resources.
+ *
+ *             If this function returns nonzero, then the object is still
+ *             active, and may still hold important resources.  This is not
+ *             intended to be a failure condition: failures in teardown are
+ *             usually unrecoverable (or very hard to recover from) and
+ *             should probably cause the program to abort.  A refusal, on
+ *             the other hand, means that the object is still live and
+ *             shouldn't be deallocated, but that this is a normal situation
+ *             and the caller shouldn't worry about it.
+ */
+
+extern int sod_teardown(void */*p*/);
+
+/* --- @sod_destroy@ --- *
+ *
+ * Arguments:  @void *p@ = pointer to an instance to be torn down, or null
+ *
+ * Returns:    Zero if the object was freed; nonzero if it refused for some
+ *             reason.
+ *
+ * Use:                Invokes the instance's `teardown' method to release any held
+ *             resources, and then calls @free@ to release the instance's
+ *             storage.  See @sod_teardown@ for details, especially
+ *             regarding the return value's meaning.
+ *
+ *             If @p@ is null, then this function does nothing except
+ *             returns zero.
+ *
+ *             (This function is not available in freestanding environments
+ *             lacking @malloc@ and @free@.)
+ */
+
+extern int sod_destroy(void */*p*/);
+
 /*----- That's all, folks -------------------------------------------------*/
 
 #ifdef __cplusplus