X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/7d21069e791a4d164c1eb1fc4f1ae661fe08ffbe..2b2252cc8d730004a1c95f227a0024a28b65087c:/lib/sod.h diff --git a/lib/sod.h b/lib/sod.h index 594e343..360afa8 100644 --- a/lib/sod.h +++ b/lib/sod.h @@ -7,7 +7,7 @@ /*----- Licensing notice --------------------------------------------------* * - * This file is part of the Sensble Object Design, an object system for C. + * This file is part of the Sensible Object Design, an object system for C. * * The SOD Runtime Library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as @@ -32,6 +32,63 @@ extern "C" { #endif +/*----- Preliminary utilities ---------------------------------------------*/ + +/* --- @SOD__HAVE_VARARGS_MACROS@ --- * + * + * Use: Defined if the compiler supports C99-style variadic macros. + * + * This is more complicated than just checking the value of + * @__STDC_VERSION__@ because GCC has traditionally claimed C89 + * by default, but provides the functionality anyway unless it's + * been explicitly turned off. + */ + +#if __STDC_VERSION__ >= 199901 + /* The feature exists. All is well with the world. */ + +# define SOD__HAVE_VARARGS_MACROS + +#elif __GNUC__ >= 3 + /* 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 + * macros being defined, and there isn't a way to detect pedantry from the + * preprocessor. + * + * We must deploy bodges. There doesn't seem to be a good way to suppress + * particular warnings from the preprocessor: in particular, messing about + * with `pragma GCC diagnostic' doesn't help. So we're left with this + * hack: just declare all Sod-generated header files which try to do + * varargs macro things to be `system headers', which means that GCC's + * preprocessor will let them get away with all manner of nefarious stuff. + */ + +# define SOD__HAVE_VARARGS_MACROS +# define SOD__VARARGS_MACROS_PREAMBLE _Pragma("GCC system_header") + +#endif + +/* Make sure this gratuitous hack is understood, at least vacuously. */ +#ifndef SOD__VARARGS_MACROS_PREAMBLE +# define SOD__VARARGS_MACROS_PREAMBLE +#endif + +/* We're going to want to make use of this ourselves. */ +SOD__VARARGS_MACROS_PREAMBLE + +/* --- @SOD__CAR@ --- * + * + * Arguments: @...@ = a nonempty list of arguments + * + * Returns: The first argument only. + */ + +#ifdef SOD__HAVE_VARARGS_MACROS +# define SOD__CAR(...) SOD__CARx(__VA_LIST__, _) +# define SOD__CARx(a, ...) a +#endif + /*----- Header files ------------------------------------------------------*/ #include @@ -53,7 +110,7 @@ struct sod_vtable { * these. */ struct sod_instance { - struct sod_vtable *_vt; /* Pointer to (chain's) vtable */ + const struct sod_vtable *_vt; /* Pointer to (chain's) vtable */ }; /* Information about a particular chain of superclasses. In each class, @@ -76,14 +133,15 @@ struct sod_chain { * Arguments: @chead@ = nickname of target chain's head * @obj@ = pointer to an instance chain * - * Returns: Pointer to target chain, as a @char *@. + * Returns: Pointer to target chain, as a @void *@. * * Use: Utility for implementing cross-chain upcasts. It's probably * not that clever to use this macro directly; it's used to make * the automatically-generated upcast macros more palatable. */ -#define SOD_XCHAIN(chead, obj) ((char *)(obj) + (obj)->_vt->_off_##chead) +#define SOD_XCHAIN(chead, obj) \ + ((void *)((char *)(obj) + (obj)->_vt->_off_##chead)) /* --- @SOD_OFFSETDIFF@ --- * * @@ -130,7 +188,7 @@ struct sod_chain { * * Arguments: @p@ = pointer to an instance chain * - * Returns: A pointer to the instance's class, as a const SodClass. + * Returns: A pointer to the instance's class, as a @const SodClass *@. */ #define SOD_CLASSOF(obj) ((const SodClass *)(obj)->_vt->_class) @@ -168,6 +226,19 @@ struct sod_chain { #define SOD_CONVERT(cls, obj) ((cls *)sod_convert(cls##__class, (obj))) +/* --- @SOD_DECL@ --- * + * + * Arguments: @cls_@ = a class type name + * @var_@ = a variable name + * + * 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) + /*----- Functions provided ------------------------------------------------*/ /* --- @sod_subclassp@ --- *