"Fossies" - the Fresh Open Source Software Archive

Member "s-nail-14.9.19/include/su/code.h" (26 Apr 2020, 45721 Bytes) of package /linux/misc/s-nail-14.9.19.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "code.h" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 14.9.18_vs_14.9.19.

    1 /*@ Code of the basic infrastructure (POD types, macros etc.) and functions.
    2  *@ And main documentation entry point, as below.
    3  *@ - Reacts upon su_HAVE_DEBUG, su_HAVE_DEVEL, and NDEBUG.
    4  *@   The latter is a precondition for su_HAVE_INLINE; dependent upon compiler
    5  *@   __OPTIMIZE__ (and __OPTIMIZE_SIZE__) may be looked at in addition, then.
    6  *@   su_HAVE_DEVEL is meant as a possibility to enable test paths with
    7  *@   debugging disabled.
    8  *@ - Some macros require su_FILE to be defined to a literal.
    9  *@ - Define su_MASTER to inject what is to be injected once; for example,
   10  *@   it enables su_M*CTA() compile time assertions.
   11  *
   12  * Copyright (c) 2001 - 2020 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
   13  * SPDX-License-Identifier: ISC
   14  *
   15  * Permission to use, copy, modify, and/or distribute this software for any
   16  * purpose with or without fee is hereby granted, provided that the above
   17  * copyright notice and this permission notice appear in all copies.
   18  *
   19  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   20  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   21  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   22  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   23  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   24  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   25  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   26  */
   27 #ifndef su_CODE_H
   28 #define su_CODE_H
   29 #include <su/config.h>
   30 /* CONFIG {{{ */
   31 #ifdef DOXYGEN
   32    /* Features */
   33 # define su_HAVE_NSPC
   34 # define su_HAVE_DEBUG
   35 # define su_HAVE_DEVEL
   36 # define su_HAVE_DOCSTRINGS
   37 # define su_HAVE_MEM_BAG_AUTO
   38 # define su_HAVE_MEM_BAG_LOFI
   39 # define su_HAVE_MEM_CANARIES_DISABLE
   40 # define su_HAVE_SMP
   41 # define su_HAVE_MT
   42    /* Values */
   43 # define su_PAGE_SIZE
   44 #endif
   45 /* CONFIG }}} */
   46 /* OS {{{ */
   47 #define su_OS_CYGWIN 0
   48 #define su_OS_DARWIN 0
   49 #define su_OS_DRAGONFLY 0
   50 #define su_OS_EMX 0
   51 #define su_OS_FREEBSD 0
   52 #define su_OS_LINUX 0
   53 #define su_OS_MINIX 0
   54 #define su_OS_MSDOS 0
   55 #define su_OS_NETBSD 0
   56 #define su_OS_OPENBSD 0
   57 #define su_OS_SOLARIS 0
   58 #define su_OS_SUNOS 0
   59 #define su_OS_WIN32 0
   60 #define su_OS_WIN64 0
   61 #if 0
   62 #elif defined __CYGWIN__
   63 # undef su_OS_CYGWIN
   64 # define su_OS_CYGWIN 1
   65 #elif defined DARWIN || defined _DARWIN
   66 # undef su_OS_DARWIN
   67 # define su_OS_DARWIN 1
   68 #elif defined __DragonFly__
   69 # undef su_OS_DRAGONFLY
   70 # define su_OS_DRAGONFLY 1
   71 #elif defined __EMX__
   72 # undef su_OS_EMX
   73 # define su_OS_EMX 1
   74 #elif defined __FreeBSD__
   75 # undef su_OS_FREEBSD
   76 # define su_OS_FREEBSD 1
   77 #elif defined __linux__ || defined __linux
   78 # undef su_OS_LINUX
   79 # define su_OS_LINUX 1
   80 #elif defined __minix
   81 # undef su_OS_MINIX
   82 # define su_OS_MINIX 1
   83 #elif defined __MSDOS__
   84 # undef su_OS_MSDOS
   85 # define su_OS_MSDOS 1
   86 #elif defined __NetBSD__
   87 # undef su_OS_NETBSD
   88 # define su_OS_NETBSD 1
   89 #elif defined __OpenBSD__
   90 # undef su_OS_OPENBSD
   91 # define su_OS_OPENBSD 1
   92 #elif defined __solaris__ || defined __sun
   93 # if defined __SVR4 || defined __svr4__
   94 #  undef su_OS_SOLARIS
   95 #  define su_OS_SOLARIS 1
   96 # else
   97 #  undef su_OS_SUNOS
   98 #  define su_OS_SUNOS 1
   99 # endif
  100 #endif
  101 /* OS }}} */
  102 /* LANG {{{ */
  103 #ifndef __cplusplus
  104 # define su_C_LANG 1
  105 # define su_C_DECL_BEGIN
  106 # define su_C_DECL_END
  107    /* Casts */
  108 # define su_S(T,I) ((T)(I))
  109 # define su_R(T,I) ((T)(I))
  110 # define su_C(T,I) ((T)su_R(su_up,I))
  111 # define su_NIL ((void*)0)
  112 #else
  113 # define su_C_LANG 0
  114 # define su_C_DECL_BEGIN extern "C" {
  115 # define su_C_DECL_END }
  116 # ifdef su_HAVE_NSPC
  117 #  define su_NSPC_BEGIN(X) namespace X {
  118 #  define su_NSPC_END(X) }
  119 #  define su_NSPC_USE(X) using namespace X;
  120 #  define su_NSPC(X) X::
  121 # else
  122 #  define su_NSPC_BEGIN(X) /**/
  123 #  define su_NSPC_END(X) /**/
  124 #  define su_NSPC_USE(X) /**/
  125 #  define su_NSPC(X) /**/::
  126 # endif
  127    /* Disable copy-construction and assignment of class */
  128 # define su_CLASS_NO_COPY(C) private:C(C const &);C &operator=(C const &);
  129    /* If C++ class inherits from a C class, and the C class "return self", we
  130     * have to waste a return register even if self==this */
  131 # define su_SELFTHIS_RET(X) /* return *(X); */ X; return *this
  132    /* C++ only allows those at the declaration, not the definition */
  133 # define su_PUB
  134 # define su_PRO
  135 # define su_PRI
  136 # define su_STA
  137 # define su_VIR
  138 # define su_OVR
  139    /* This is for the declarator only */
  140 # if __cplusplus +0 < 201103L
  141 #  define su_OVRX
  142 # else
  143 #  define su_OVRX override
  144 # endif
  145    /* Casts */
  146 # define su_S(T,I) static_cast<T>(I)
  147 # define su_R(T,I) reinterpret_cast<T>(I)
  148 # define su_C(T,I) const_cast<T>(I)
  149 # define su_NIL (0L)
  150 #endif /* __cplusplus */
  151 #define su_SHADOW
  152 /* "su_EXPORT myfun()", "class su_EXPORT myclass" */
  153 #if su_OS_WIN32 || su_OS_WIN64
  154 # define su_EXPORT __declspec((dllexport))
  155 # define su_EXPORT_DATA __declspec((dllexport))
  156 # define su_IMPORT __declspec((dllimport))
  157 # define su_IMPORT_DATA __declspec((dllimport))
  158 #else
  159 # define su_EXPORT /*extern*/
  160 # define su_EXPORT_DATA extern
  161 # define su_IMPORT /*extern*/
  162 # define su_IMPORT_DATA extern
  163 #endif
  164 /* Compile-Time-Assert
  165  * Problem is that some compilers warn on unused local typedefs, so add
  166  * a special local CTA to overcome this */
  167 #if (!su_C_LANG && __cplusplus +0 >= 201103L) || defined DOXYGEN
  168 # define su_CTA(T,M) static_assert(T, M)
  169 # define su_LCTA(T,M) static_assert(T, M)
  170 #elif 0 /* unusable! */ && \
  171       defined __STDC_VERSION__ && __STDC_VERSION__ +0 >= 201112L
  172 # define su_CTA(T,M) _Static_assert(T, M)
  173 # define su_LCTA(T,M) _Static_assert(T, M)
  174 #else
  175 # define su_CTA(T,M) su__CTA_1(T, su_FILE, __LINE__)
  176 # define su_LCTA(T,M) su__LCTA_1(T, su_FILE, __LINE__)
  177 # define su__CTA_1(T,F,L) su__CTA_2(T, F, L)
  178 # define su__CTA_2(T,F,L) \
  179       typedef char ASSERTION_failed_file_ ## F ## _line_ ## L[(T) ? 1 : -1]
  180 # define su__LCTA_1(T,F,L) su__LCTA_2(T, F, L)
  181 # define su__LCTA_2(T,F,L) \
  182 do{\
  183    typedef char ASSERT_failed_file_ ## F ## _line_ ## L[(T) ? 1 : -1];\
  184    ASSERT_failed_file_ ## F ## _line_ ## L __i_am_unused__;\
  185    su_UNUSED(__i_am_unused__);\
  186 }while(0)
  187 #endif
  188 #define su_CTAV(T) su_CTA(T, "Unexpected value of constant")
  189 #define su_LCTAV(T) su_LCTA(T, "Unexpected value of constant")
  190 #ifdef su_MASTER
  191 # define su_MCTA(T,M) su_CTA(T, M);
  192 #else
  193 # define su_MCTA(T,M)
  194 #endif
  195 /* LANG }}} */
  196 /* CC {{{ */
  197 #define su_CC_CLANG 0
  198 #define su_CC_VCHECK_CLANG(X,Y) 0
  199 #define su_CC_GCC 0
  200 #define su_CC_VCHECK_GCC(X,Y) 0
  201 #define su_CC_PCC 0
  202 #define su_CC_VCHECK_PCC(X,Y) 0
  203 #define su_CC_SUNPROC 0
  204 #define su_CC_VCHECK_SUNPROC(X,Y) 0
  205 #define su_CC_TINYC 0
  206 #define su_CC_VCHECK_TINYC(X,Y) 0
  207 #ifdef __clang__
  208 # undef su_CC_CLANG
  209 # undef su_CC_VCHECK_CLANG
  210 # define su_CC_CLANG 1
  211 # define su_CC_VCHECK_CLANG(X,Y) \
  212       (__clang_major__ +0 > (X) || \
  213        (__clang_major__ +0 == (X) && __clang_minor__ +0 >= (Y)))
  214 # define su_CC_EXTEN __extension__
  215 # define su_CC_PACKED __attribute__((packed))
  216 # if !defined su_CC_BOM &&\
  217       defined __BYTE_ORDER__ && defined __ORDER_LITTLE_ENDIAN__ &&\
  218       defined __ORDER_BIG_ENDIAN
  219 #  if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  220 #   define su_CC_BOM su_CC_BOM_LITTLE
  221 #  elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  222 #   define su_CC_BOM su_CC_BOM_BIG
  223 #  else
  224 #   error Unsupported __BYTE_ORDER__
  225 #  endif
  226 # endif
  227 /* __GNUC__ after some other Unix compilers which also define __GNUC__ */
  228 #elif defined __PCC__ /* __clang__ */
  229 # undef su_CC_PCC
  230 # undef su_CC_VCHECK_PCC
  231 # define su_CC_PCC 1
  232 # define su_CC_VCHECK_PCC(X,Y) \
  233       (__PCC__ +0 > (X) || (__PCC__ +0 == (X) && __PCC_MINOR__ +0 >= (Y)))
  234 # define su_CC_EXTEN __extension__
  235 # define su_CC_PACKED __attribute__((packed))
  236 # if !defined su_CC_BOM &&\
  237       defined __BYTE_ORDER__ && defined __ORDER_LITTLE_ENDIAN__ &&\
  238       defined __ORDER_BIG_ENDIAN
  239 #  if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  240 #   define su_CC_BOM su_CC_BOM_LITTLE
  241 #  elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  242 #   define su_CC_BOM su_CC_BOM_BIG
  243 #  else
  244 #   error Unsupported __BYTE_ORDER__
  245 #  endif
  246 # endif
  247 #elif defined __SUNPRO_C /* __PCC__ */
  248 # undef su_CC_SUNPROC
  249 # define su_CC_SUNPROC 1
  250 # define su_CC_PACKED TODO: PACKED attribute not supported for SunPro C
  251 #elif defined __TINYC__ /* __SUNPRO_C */
  252 # undef su_CC_TINYC
  253 # define su_CC_TINYC 1
  254 # define su_CC_EXTEN /* __extension__ (ignored) */
  255 # define su_CC_PACKED __attribute__((packed))
  256 #elif defined __GNUC__ /* __TINYC__ */
  257 # undef su_CC_GCC
  258 # undef su_CC_VCHECK_GCC
  259 # define su_CC_GCC 1
  260 # define su_CC_VCHECK_GCC(X,Y) \
  261       (__GNUC__ +0 > (X) || (__GNUC__ +0 == (X) && __GNUC_MINOR__ +0 >= (Y)))
  262 # define su_CC_EXTEN __extension__
  263 # define su_CC_PACKED __attribute__((packed))
  264 # if !defined su_CC_BOM &&\
  265       defined __BYTE_ORDER__ && defined __ORDER_LITTLE_ENDIAN__ &&\
  266       defined __ORDER_BIG_ENDIAN
  267 #  if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  268 #   define su_CC_BOM su_CC_BOM_LITTLE
  269 #  elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  270 #   define su_CC_BOM su_CC_BOM_BIG
  271 #  else
  272 #   error Unsupported __BYTE_ORDER__
  273 #  endif
  274 # endif
  275 #elif !defined su_CC_IGNORE_UNKNOWN
  276 # error SU: This compiler is not yet supported.
  277 # error SU: To continue with your CFLAGS etc., define su_CC_IGNORE_UNKNOWN.
  278 # error SU: It may be necessary to define su_CC_PACKED to a statement that
  279 # error SU: enables structure packing; it may not be a #pragma, but a _Pragma
  280 #endif
  281 #ifndef su_CC_EXTEN
  282 # define su_CC_EXTEN
  283 #endif
  284 #ifndef su_CC_PACKED
  285 # define su_CC_PACKED TODO: PACKED attribute not supported for this compiler
  286 #endif
  287 #if defined su_CC_BOM || defined DOXYGEN
  288 # ifdef DOXYGEN
  289 #  define su_CC_BOM
  290 # endif
  291 # define su_CC_BOM_LITTLE 1234
  292 # define su_CC_BOM_BIG 4321
  293 #endif
  294 #if !defined su_CC_UZ_TYPE && defined __SIZE_TYPE__
  295 # define su_CC_UZ_TYPE __SIZE_TYPE__
  296 #endif
  297 /* Function name */
  298 #if defined __STDC_VERSION__ && __STDC_VERSION__ +0 >= 199901L
  299 # define su_FUN __func__
  300 #elif su_CC_CLANG || su_CC_VCHECK_GCC(3, 4) || su_CC_PCC || su_CC_TINYC
  301 # define su_FUN __extension__ __FUNCTION__
  302 #else
  303 # define su_FUN su_empty /* Something that is not a literal */
  304 #endif
  305 /* inline keyword */
  306 #define su_HAVE_INLINE
  307 #if su_C_LANG
  308 # ifdef DOXYGEN
  309 #  define su_INLINE inline
  310 #  define su_SINLINE inline
  311 # elif su_CC_GCC
  312    /* After lots of trouble with OpenBSD/gcc 4.2.1 and SunOS/gcc 3.4.3 */
  313 #  if !su_CC_VCHECK_GCC(3, 2) /* Unsure: only used C++ at that time */
  314 #   define su_INLINE extern __inline
  315 #   define su_SINLINE static __inline
  316 #  elif !su_CC_VCHECK_GCC(4, 3)
  317 #   define su_INLINE extern __inline __attribute__((always_inline))
  318 #   define su_SINLINE static __inline __attribute__((always_inline))
  319    /* xxx gcc 8.3.0 bug: does not truly inline with -Os */
  320 #  elif !su_CC_VCHECK_GCC(8, 3) || !defined __OPTIMIZE__ ||\
  321       !defined __STDC_VERSION__ || __STDC_VERSION__ +0 < 199901L
  322 #   define su_INLINE extern __inline __attribute__((gnu_inline))
  323 #   define su_SINLINE static __inline __attribute__((gnu_inline))
  324 #  elif !defined NDEBUG || !defined __OPTIMIZE__
  325 #   define su_INLINE static inline
  326 #   define su_SINLINE static inline
  327 #  else
  328 #   define su_INLINE inline
  329 #   define su_SINLINE static inline
  330 #  endif
  331 # elif su_CC_CLANG || su_CC_PCC
  332 #  if defined __STDC_VERSION__ && __STDC_VERSION__ +0 >= 199901L
  333 #   if !defined NDEBUG || !defined __OPTIMIZE__
  334 #    define su_INLINE static inline
  335 #    define su_SINLINE static inline
  336 #   else
  337      /* clang does not like inline with <-O2 */
  338 #    define su_INLINE inline __attribute__((always_inline))
  339 #    define su_SINLINE static inline __attribute__((always_inline))
  340 #   endif
  341 #  else
  342 #   define su_INLINE static __inline
  343 #   define su_SINLINE static __inline
  344 #  endif
  345 # else
  346 #  define su_INLINE static /* TODO __attribute__((unused)) alike? */
  347 #  define su_SINLINE static /* TODO __attribute__((unused)) alike? */
  348 #  undef su_HAVE_INLINE
  349 # endif
  350 #else
  351 # define su_INLINE inline
  352 # define su_SINLINE static inline
  353 #endif
  354 #ifndef NDEBUG
  355 # undef su_HAVE_INLINE
  356 #endif
  357 #if defined __predict_true && defined __predict_false
  358 # define su_LIKELY(X) __predict_true((X) != 0)
  359 # define su_UNLIKELY(X) __predict_false((X) != 0)
  360 #elif su_CC_CLANG || su_CC_VCHECK_GCC(2, 96) || su_CC_PCC || su_CC_TINYC
  361 # define su_LIKELY(X) __builtin_expect((X) != 0, 1)
  362 # define su_UNLIKELY(X) __builtin_expect((X) != 0, 0)
  363 #else
  364 # define su_LIKELY(X) ((X) != 0)
  365 # define su_UNLIKELY(X) ((X) != 0)
  366 #endif
  367 /* CC }}} */
  368 /* SUPPORT MACROS+ {{{ */
  369 /* USECASE_XY_DISABLED for tagging unused files:
  370  * git rm `git grep ^su_USECASE_MX_DISABLED` */
  371 #ifdef su_USECASE_MX
  372 # define su_USECASE_MX_DISABLED This file is not a (valid) compilation unit
  373 #endif
  374 #ifndef su_USECASE_MX_DISABLED
  375 # define su_USECASE_MX_DISABLED
  376 #endif
  377 /* Basic support macros, with side effects */
  378 #define su_ABS(A) ((A) < 0 ? -(A) : (A))
  379 #define su_CLIP(X,A,B) (((X) <= (A)) ? (A) : (((X) >= (B)) ? (B) : (X)))
  380 #define su_IS_POW2(X) ((((X) - 1) & (X)) == 0)
  381 #define su_MAX(A,B) ((A) < (B) ? (B) : (A))
  382 #define su_MIN(A,B) ((A) < (B) ? (A) : (B))
  383 #define su_ROUND_DOWN(X,BASE) (((X) / (BASE)) * (BASE))
  384 #define su_ROUND_DOWN2(X,BASE) ((X) & (~((BASE) - 1)))
  385 #define su_ROUND_UP(X,BASE) ((((X) + ((BASE) - 1)) / (BASE)) * (BASE))
  386 #define su_ROUND_UP2(X,BASE) (((X) + ((BASE) - 1)) & (~((BASE) - 1)))
  387 /* Alignment.  Note: su_uz POW2 asserted in POD section below! */
  388 /* Commented out: "_Alignof() applied to an expression is a GNU extension" */
  389 #if 0 && defined __STDC_VERSION__ && __STDC_VERSION__ +0 >= 201112L
  390 # include <stdalign.h>
  391 # define su_ALIGNOF(X) _Alignof(X)
  392 #else
  393 # define su_ALIGNOF(X) su_ROUND_UP2(sizeof(X), su__ZAL_L)
  394 #endif
  395 #define su_P_ALIGN(DTYPE,OTYPE,MEM) \
  396    su_R(DTYPE,\
  397       su_IS_POW2(su_ALIGNOF(OTYPE))\
  398          ? su_ROUND_UP2(su_R(su_up,MEM), su_ALIGNOF(OTYPE))\
  399          : su_ROUND_UP(su_R(su_up,MEM), su_ALIGNOF(OTYPE)))
  400 /* Roundup/align an integer;  Note: POW2 asserted in POD section below! */
  401 #define su_Z_ALIGN_OVER(X) su_ROUND_UP2(su_S(su_uz,X), 2 * su__ZAL_L)
  402 #define su_Z_ALIGN(X) su_ROUND_UP2(su_S(su_uz,X), su__ZAL_L)
  403 #define su_Z_ALIGN_PZ(X) su_ROUND_UP2(su_S(su_uz,X), su__ZAL_S)
  404 /* (These are below MCTA()d to be of equal size[, however].)
  405  * _L must adhere to the minimum aligned claimed in the \mainpage */
  406 # define su__ZAL_S su_MAX(sizeof(su_uz), sizeof(void*))
  407 # define su__ZAL_L su_MAX(su__ZAL_S, sizeof(su_u64))/* XXX FP,128bit */
  408 /* Variants of ASSERT */
  409 #if defined NDEBUG || defined DOXYGEN
  410 # define su_ASSERT_INJ(X)
  411 # define su_ASSERT_INJOR(X,Y) Y
  412 # define su_ASSERT_NB(X) ((void)0)
  413 # define su_ASSERT(X) do{}while(0)
  414 # define su_ASSERT_LOC(X,FNAME,LNNO) do{}while(0)
  415 # define su_ASSERT_EXEC(X,S) do{}while(0)
  416 # define su_ASSERT_EXEC_LOC(X,S,FNAME,LNNO) do{}while(0)
  417 # define su_ASSERT_JUMP(X,L) do{}while(0)
  418 # define su_ASSERT_JUMP_LOC(X,L,FNAME,LNNO) do{}while(0)
  419 # define su_ASSERT_RET(X,Y) do{}while(0)
  420 # define su_ASSERT_RET_LOC(X,Y,FNAME,LNNO) do{}while(0)
  421 # define su_ASSERT_RET_VOID(X) do{}while(0)
  422 # define su_ASSERT_RET_VOID_LOC(X,Y,FNAME,LNNO) do{}while(0)
  423 # define su_ASSERT_NYD_EXEC(X,Y) do{}while(0)
  424 # define su_ASSERT_NYD_EXEC_LOC(X,FNAME,LNNO) do{}while(0)
  425 # define su_ASSERT_NYD(X) do{}while(0)
  426 # define su_ASSERT_NYD_LOC(X,FNAME,LNNO) do{}while(0)
  427 #else
  428 # define su_ASSERT_INJ(X) X
  429 # define su_ASSERT_INJOR(X,Y) X
  430 # define su_ASSERT_NB(X) \
  431    su_R(void,((X) ? su_TRU1 \
  432       : su_assert(su_STRING(X), __FILE__, __LINE__, su_FUN, su_TRU1), su_FAL0))
  433 # define su_ASSERT(X) su_ASSERT_LOC(X, __FILE__, __LINE__)
  434 # define su_ASSERT_LOC(X,FNAME,LNNO) \
  435 do if(!(X))\
  436    su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_TRU1);\
  437 while(0)
  438 # define su_ASSERT_EXEC(X,S) su_ASSERT_EXEC_LOC(X, S, __FILE__, __LINE__)
  439 # define su_ASSERT_EXEC_LOC(X,S,FNAME,LNNO) \
  440 do if(!(X)){\
  441    su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
  442    S;\
  443 }while(0)
  444 # define su_ASSERT_JUMP(X,L) su_ASSERT_JUMP_LOC(X, L, __FILE__, __LINE__)
  445 # define su_ASSERT_JUMP_LOC(X,L,FNAME,LNNO) \
  446 do if(!(X)){\
  447    su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
  448    goto L;\
  449 }while(0)
  450 # define su_ASSERT_RET(X,Y) su_ASSERT_RET_LOC(X, Y, __FILE__, __LINE__)
  451 # define su_ASSERT_RET_LOC(X,Y,FNAME,LNNO) \
  452 do if(!(X)){\
  453    su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
  454    return Y;\
  455 }while(0)
  456 # define su_ASSERT_RET_VOID(X) su_ASSERT_RET_VOID_LOC(X, __FILE__, __LINE__)
  457 # define su_ASSERT_RET_VOID_LOC(X,FNAME,LNNO) \
  458 do if(!(X)){\
  459    su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
  460    return;\
  461 }while(0)
  462 # define su_ASSERT_NYD_EXEC(X,Y) \
  463    su_ASSERT_NYD_EXEC_LOC(X, Y, __FILE__, __LINE__)
  464 # define su_ASSERT_NYD_EXEC_LOC(X,Y,FNAME,LNNO) \
  465 do if(!(X)){\
  466    su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
  467    Y; goto su_NYD_OU_LABEL;\
  468 }while(0)
  469 # define su_ASSERT_NYD(X) su_ASSERT_NYD_LOC(X, __FILE__, __LINE__)
  470 # define su_ASSERT_NYD_LOC(X,FNAME,LNNO) \
  471 do if(!(X)){\
  472    su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
  473    goto su_NYD_OU_LABEL;\
  474 }while(0)
  475 #endif /* defined NDEBUG || defined DOXYGEN */
  476 #define su_BITENUM_IS(X,Y) X
  477 #define su_BITENUM_MASK(LO,HI) (((1u << ((HI) + 1)) - 1) & ~((1u << (LO)) - 1))
  478 #define su_COMMA ,
  479 /* Debug injections */
  480 #if defined su_HAVE_DEBUG && !defined NDEBUG
  481 # define su_DBG(X) X
  482 # define su_NDBG(X)
  483 # define su_DBGOR(X,Y) X
  484 #else
  485 # define su_DBG(X)
  486 # define su_NDBG(X) X
  487 # define su_DBGOR(X,Y) Y
  488 #endif
  489 /* Debug file location arguments.  (For an usage example see su/mem.h.) */
  490 #if defined su_HAVE_DEVEL || defined su_HAVE_DEBUG
  491 # define su_HAVE_DBG_LOC_ARGS
  492 # define su_DBG_LOC_ARGS_FILE su__dbg_loc_args_file
  493 # define su_DBG_LOC_ARGS_LINE su__dbg_loc_args_line
  494 # define su_DBG_LOC_ARGS_DECL_SOLE \
  495    char const *su_DBG_LOC_ARGS_FILE, su_u32 su_DBG_LOC_ARGS_LINE
  496 # define su_DBG_LOC_ARGS_DECL , su_DBG_LOC_ARGS_DECL_SOLE
  497 # define su_DBG_LOC_ARGS_INJ_SOLE __FILE__, __LINE__
  498 # define su_DBG_LOC_ARGS_INJ , su_DBG_LOC_ARGS_INJ_SOLE
  499 # define su_DBG_LOC_ARGS_USE_SOLE su_DBG_LOC_ARGS_FILE, su_DBG_LOC_ARGS_LINE
  500 # define su_DBG_LOC_ARGS_USE , su_DBG_LOC_ARGS_USE_SOLE
  501 # define su_DBG_LOC_ARGS_ORUSE su_DBG_LOC_ARGS_FILE, su_DBG_LOC_ARGS_LINE
  502 # define su_DBG_LOC_ARGS_UNUSED() \
  503 do{\
  504    su_UNUSED(su_DBG_LOC_ARGS_FILE);\
  505    su_UNUSED(su_DBG_LOC_ARGS_LINE);\
  506 }while(0)
  507 #else
  508 # define su_DBG_LOC_ARGS_FILE "unused"
  509 # define su_DBG_LOC_ARGS_LINE 0
  510 #
  511 # define su_DBG_LOC_ARGS_DECL_SOLE
  512 # define su_DBG_LOC_ARGS_DECL
  513 # define su_DBG_LOC_ARGS_INJ_SOLE
  514 # define su_DBG_LOC_ARGS_INJ
  515 # define su_DBG_LOC_ARGS_USE_SOLE
  516 # define su_DBG_LOC_ARGS_USE
  517 # define su_DBG_LOC_ARGS_ORUSE su_DBG_LOC_ARGS_FILE, su_DBG_LOC_ARGS_LINE
  518 # define su_DBG_LOC_ARGS_UNUSED() do{}while(0)
  519 #endif /* su_HAVE_DEVEL || su_HAVE_DEBUG */
  520 /* Development injections */
  521 #if defined su_HAVE_DEVEL || defined su_HAVE_DEBUG /* Not: !defined NDEBUG) */\
  522       || defined DOXYGEN
  523 # define su_DVL(X) X
  524 # define su_NDVL(X)
  525 # define su_DVLOR(X,Y) X
  526 #else
  527 # define su_DVL(X)
  528 # define su_NDVL(X) X
  529 # define su_DVLOR(X,Y) Y
  530 #endif
  531 #define su_EMPTY_FILE() typedef int su_CONCAT(su_notempty_shall_b_, su_FILE);
  532 /* C field init */
  533 #if (su_C_LANG && defined __STDC_VERSION__ && \
  534       __STDC_VERSION__ +0 >= 199901L) || defined DOXYGEN
  535 # define su_FIELD_INITN(N) .N =
  536 # define su_FIELD_INITI(I) [I] =
  537 #else
  538 # define su_FIELD_INITN(N)
  539 # define su_FIELD_INITI(I)
  540 #endif
  541 /* XXX offsetof+: clang,pcc check faked! */
  542 #if su_CC_VCHECK_CLANG(5, 0) || su_CC_VCHECK_GCC(4, 1) ||\
  543       su_CC_VCHECK_PCC(1, 2) || defined DOXYGEN
  544 # define su_FIELD_OFFSETOF(T,F) __builtin_offsetof(T, F)
  545 #else
  546 # define su_FIELD_OFFSETOF(T,F) \
  547       su_S(su_uz,su_S(su_up,&(su_R(T *,0x1)->F)) - 1)
  548 #endif
  549 #define su_FIELD_RANGEOF(T,S,E) \
  550       (su_FIELD_OFFSETOF(T, E) - su_FIELD_OFFSETOF(T, S))
  551 #define su_FIELD_SIZEOF(T,F) sizeof(su_S(T *,su_NIL)->F)
  552 /* Multithread injections */
  553 #ifdef su_HAVE_MT
  554 # define su_MT(X) X
  555 #else
  556 # define su_MT(X)
  557 #endif
  558 #define su_NELEM(A) (sizeof(A) / sizeof((A)[0]))
  559 #define su_NYD_OU_LABEL su__nydou
  560 #define su_P2UZ(X) su_S(su_uz,(su_up)(X))
  561 #define su_PCMP(A,C,B) (su_R(su_up,A) C su_R(su_up,B))
  562 /* SMP injections */
  563 #ifdef su_HAVE_SMP
  564 # define su_SMP(X) X
  565 #else
  566 # define su_SMP(X)
  567 #endif
  568 /* String stuff.
  569  * __STDC_VERSION__ is ISO C99, so also use __STDC__, which should work */
  570 #if defined __STDC__ || defined __STDC_VERSION__ || su_C_LANG || \
  571       defined DOXYGEN
  572 # define su_STRING(X) #X
  573 # define su_XSTRING(X) su_STRING(X)
  574 # define su_CONCAT(S1,S2) su__CONCAT_1(S1, S2)
  575 # define su__CONCAT_1(S1,S2) S1 ## S2
  576 #else
  577 # define su_STRING(X) "X"
  578 # define su_XSTRING STRING
  579 # define su_CONCAT(S1,S2) S1/* will no work out though */S2
  580 #endif
  581 #if su_C_LANG || defined DOXYGEN
  582 # define su_UCMP(T,A,C,B) (su_S(su_ ## u ## T,A) C su_S(su_ ## u ## T,B))
  583 #else
  584 # define su_UCMP(T,A,C,B) \
  585       (su_S(su_NSPC(su) u ## T,A) C su_S(su_NSPC(su) u ## T,B))
  586 #endif
  587 #define su_UNCONST(T,P) su_R(T,su_R(su_up,su_S(void const*,P)))
  588 #define su_UNVOLATILE(T,P) su_R(T,su_R(su_up,su_S(void volatile*,P)))
  589 #define su_UNALIGN(T,P) su_R(T,su_R(su_up,P))
  590 #define su_UNXXX(T,C,P) su_R(T,su_R(su_up,su_S(C,P)))
  591 /* Avoid "may be used uninitialized" warnings */
  592 #if (defined NDEBUG && !(defined su_HAVE_DEBUG || defined su_HAVE_DEVEL)) || \
  593       defined DOYGEN
  594 # define su_UNINIT(N,V) su_S(void,0)
  595 # define su_UNINIT_DECL(V)
  596 #else
  597 # define su_UNINIT(N,V) N = V
  598 # define su_UNINIT_DECL(V) = V
  599 #endif
  600 #define su_UNUSED(X) ((void)(X))
  601 #if (su_C_LANG && defined __STDC_VERSION__ && \
  602       __STDC_VERSION__ +0 >= 199901L) || defined DOXYGEN
  603 # define su_VFIELD_SIZE(X)
  604 # define su_VSTRUCT_SIZEOF(T,F) sizeof(T)
  605 #else
  606 # define su_VFIELD_SIZE(X) \
  607       ((X) == 0 ? sizeof(su_uz) \
  608       : (su_S(su_sz,X) < 0 ? sizeof(su_uz) - su_ABS(X) : su_S(su_uz,X)))
  609 # define su_VSTRUCT_SIZEOF(T,F) (sizeof(T) - su_FIELD_SIZEOF(T, F))
  610 #endif
  611 /* SUPPORT MACROS+ }}} */
  612 /* We are ready to start using our own style */
  613 #ifndef su_CC_SIZE_TYPE
  614 # include <sys/types.h> /* TODO create config time script, */
  615 #endif
  616 #include <inttypes.h> /* TODO query infos and drop */
  617 #include <limits.h> /* TODO those includes! */
  618 #define su_HEADER
  619 #include <su/code-in.h>
  620 C_DECL_BEGIN
  621 /* POD TYPE SUPPORT TODO maybe configure-time, from a su/config.h?! {{{ */
  622 /* TODO Note: the PRI* series will go away once we have FormatCtx! */
  623 /* First some shorter aliases for "normal" integers */
  624 typedef unsigned long su_ul;
  625 typedef unsigned int su_ui;
  626 typedef unsigned short su_us;
  627 typedef unsigned char su_uc;
  628 typedef signed long su_sl;
  629 typedef signed int su_si;
  630 typedef signed short su_ss;
  631 typedef signed char su_sc;
  632 #if defined UINT8_MAX || defined DOXYGEN
  633 # define su_U8_MAX UINT8_MAX
  634 # define su_S8_MIN INT8_MIN
  635 # define su_S8_MAX INT8_MAX
  636 typedef uint8_t su_u8;
  637 typedef int8_t su_s8;
  638 #elif UCHAR_MAX != 255
  639 # error UCHAR_MAX must be 255
  640 #else
  641 # define su_U8_MAX UCHAR_MAX
  642 # define su_S8_MIN CHAR_MIN
  643 # define su_S8_MAX CHAR_MAX
  644 typedef unsigned char su_u8;
  645 typedef signed char su_s8;
  646 #endif
  647 #if !defined PRIu8 || !defined PRId8
  648 # undef PRIu8
  649 # undef PRId8
  650 # define PRIu8 "hhu"
  651 # define PRId8 "hhd"
  652 #endif
  653 #if defined UINT16_MAX || defined DOXYGEN
  654 # define su_U16_MAX UINT16_MAX
  655 # define su_S16_MIN INT16_MIN
  656 # define su_S16_MAX INT16_MAX
  657 typedef uint16_t su_u16;
  658 typedef int16_t su_s16;
  659 #elif USHRT_MAX != 0xFFFFu
  660 # error USHRT_MAX must be 0xFFFF
  661 #else
  662 # define su_U16_MAX USHRT_MAX
  663 # define su_S16_MIN SHRT_MIN
  664 # define su_S16_MAX SHRT_MAX
  665 typedef unsigned short su_u16;
  666 typedef signed short su_s16;
  667 #endif
  668 #if !defined PRIu16 || !defined PRId16
  669 # undef PRIu16
  670 # undef PRId16
  671 # if su_U16_MAX == UINT_MAX
  672 #  define PRIu16 "u"
  673 #  define PRId16 "d"
  674 # else
  675 #  define PRIu16 "hu"
  676 #  define PRId16 "hd"
  677 # endif
  678 #endif
  679 #if defined UINT32_MAX || defined DOXYGEN
  680 # define su_U32_MAX UINT32_MAX
  681 # define su_S32_MIN INT32_MIN
  682 # define su_S32_MAX INT32_MAX
  683 typedef uint32_t su_u32;
  684 typedef int32_t su_s32;
  685 #elif ULONG_MAX == 0xFFFFFFFFu
  686 # define su_U32_MAX ULONG_MAX
  687 # define su_S32_MIN LONG_MIN
  688 # define su_S32_MAX LONG_MAX
  689 typedef unsigned long int su_u32;
  690 typedef signed long int su_s32;
  691 #elif UINT_MAX != 0xFFFFFFFFu
  692 # error UINT_MAX must be 0xFFFFFFFF
  693 #else
  694 # define su_U32_MAX UINT_MAX
  695 # define su_S32_MIN INT_MIN
  696 # define su_S32_MAX INT_MAX
  697 typedef unsigned int su_u32;
  698 typedef signed int su_s32;
  699 #endif
  700 #if !defined PRIu32 || !defined PRId32
  701 # undef PRIu32
  702 # undef PRId32
  703 # if su_U32_MAX == ULONG_MAX
  704 #  define PRIu32 "lu"
  705 #  define PRId32 "ld"
  706 # else
  707 #  define PRIu32 "u"
  708 #  define PRId32 "d"
  709 # endif
  710 #endif
  711 #if defined UINT64_MAX || defined DOXYGEN
  712 # define su_U64_MAX UINT64_MAX
  713 # define su_S64_MIN INT64_MIN
  714 # define su_S64_MAX INT64_MAX
  715 # define su_S64_C(C) INT64_C(C)
  716 # define su_U64_C(C) UINT64_C(C)
  717 typedef uint64_t su_u64;
  718 typedef int64_t su_s64;
  719 #elif ULONG_MAX <= 0xFFFFFFFFu
  720 # if !defined ULLONG_MAX
  721 #  error We need a 64 bit integer
  722 # else
  723 #  define su_U64_MAX ULLONG_MAX
  724 #  define su_S64_MIN LLONG_MIN
  725 #  define su_S64_MAX LLONG_MAX
  726 #  define su_S64_C(C) su_CONCAT(C, ll)
  727 #  define su_U64_C(C) su_CONCAT(C, ull)
  728 su_CC_EXTEN typedef unsigned long long su_u64;
  729 su_CC_EXTEN typedef signed long long su_s64;
  730 # endif
  731 #else
  732 # define su_U64_MAX ULONG_MAX
  733 # define su_S64_MIN LONG_MIN
  734 # define su_S64_MAX LONG_MAX
  735 # define su_S64_C(C) su_CONCAT(C, l)
  736 # define su_U64_C(C) su_CONCAT(C, ul)
  737 typedef unsigned long su_u64;
  738 typedef signed long su_s64;
  739 #endif
  740 #if !defined PRIu64 || !defined PRId64 || !defined PRIX64 || !defined PRIo64
  741 # undef PRIu64
  742 # undef PRId64
  743 # undef PRIX64
  744 # undef PRIo64
  745 # if defined ULLONG_MAX && su_U64_MAX == ULLONG_MAX
  746 #  define PRIu64 "llu"
  747 #  define PRId64 "lld"
  748 #  define PRIX64 "llX"
  749 #  define PRIo64 "llo"
  750 # else
  751 #  define PRIu64 "lu"
  752 #  define PRId64 "ld"
  753 #  define PRIX64 "lX"
  754 #  define PRIo64 "lo"
  755 # endif
  756 #endif
  757 /* (So that we can use UCMP() for size_t comparison, too) */
  758 #ifdef su_CC_SIZE_TYPE
  759 typedef su_CC_SIZE_TYPE su_uz;
  760 #else
  761 typedef size_t su_uz;
  762 #endif
  763 #undef PRIuZ
  764 #undef PRIdZ
  765 #if (defined __STDC_VERSION__ && __STDC_VERSION__ +0 >= 199901L) ||\
  766       defined DOXYGEN
  767 # define PRIuZ "zu"
  768 # define PRIdZ "zd"
  769 # define su_UZ_MAX SIZE_MAX
  770 #elif defined SIZE_MAX
  771    /* UnixWare has size_t as unsigned as required but uses a signed limit
  772     * constant (which is thus false!) */
  773 # if SIZE_MAX == su_U64_MAX || SIZE_MAX == su_S64_MAX
  774 #  define PRIuZ PRIu64
  775 #  define PRIdZ PRId64
  776 MCTA(sizeof(size_t) == sizeof(u64),
  777    "Format string mismatch, compile with ISO C99 compiler (-std=c99)!")
  778 # elif SIZE_MAX == su_U32_MAX || SIZE_MAX == su_S32_MAX
  779 #  define PRIuZ PRIu32
  780 #  define PRIdZ PRId32
  781 MCTA(sizeof(size_t) == sizeof(u32),
  782    "Format string mismatch, compile with ISO C99 compiler (-std=c99)!")
  783 # else
  784 #  error SIZE_MAX is neither su_U64_MAX nor su_U32_MAX (please report this)
  785 # endif
  786 # define su_UZ_MAX SIZE_MAX
  787 #endif
  788 #if !defined PRIuZ && !defined DOXYGEN
  789 # define PRIuZ "lu"
  790 # define PRIdZ "ld"
  791 MCTA(sizeof(size_t) == sizeof(unsigned long),
  792    "Format string mismatch, compile with ISO C99 compiler (-std=c99)!")
  793 #endif
  794 /* The signed equivalence is not really compliant to the standard */
  795 #if su_UZ_MAX == su_U32_MAX || su_UZ_MAX == su_S32_MAX || defined DOXYGEN
  796 # define su_SZ_MIN su_S32_MIN
  797 # define su_SZ_MAX su_S32_MAX
  798 # define su_UZ_BITS 32u
  799 # define su_64(X)
  800 # define su_32(X) X
  801 # define su_6432(X,Y) Y
  802 typedef su_s32 su_sz;
  803 #elif su_UZ_MAX == su_U64_MAX
  804 # define su_SZ_MIN su_S64_MIN
  805 # define su_SZ_MAX su_S64_MAX
  806 # define su_UZ_BITS 64u
  807 # define su_64(X) X
  808 # define su_32(X)
  809 # define su_6432(X,Y) X
  810 typedef su_s64 su_sz;
  811 #else
  812 # error I cannot handle this maximum value of size_t
  813 #endif
  814 MCTA(sizeof(su_uz) == sizeof(void*),
  815    "SU cannot handle sizeof(su_uz) != sizeof(void*)")
  816 /* Regardless of P2UZ provide this one; only use it rarely */
  817 #if defined UINTPTR_MAX || defined DOXYGEN
  818 typedef uintptr_t su_up;
  819 typedef intptr_t su_sp;
  820 #else
  821 # ifdef SIZE_MAX
  822 typedef su_uz su_up;
  823 typedef su_sz su_sp;
  824 # else
  825 typedef su_ul su_up;
  826 typedef su_sl su_sp;
  827 # endif
  828 #endif
  829 enum{
  830    su_FAL0,
  831    su_TRU1,
  832    su_TRU2,
  833    su_TRUM1 = -1
  834 };
  835 typedef su_s8 su_boole;
  836 /* POD TYPE SUPPORT }}} */
  837 /* BASIC TYPE TRAITS {{{ */
  838 struct su_toolbox;
  839 /* plus PTF typedefs */
  840 typedef void *(*su_new_fun)(u32 estate);
  841 typedef void *(*su_clone_fun)(void const *t, u32 estate);
  842 typedef void (*su_delete_fun)(void *self);
  843 typedef void *(*su_assign_fun)(void *self, void const *t, u32 estate);
  844 typedef su_sz (*su_compare_fun)(void const *a, void const *b);
  845 typedef su_uz (*su_hash_fun)(void const *self);
  846 /* Needs to be binary compatible with \c{su::{toolbox,type_toolbox<T>}}! */
  847 struct su_toolbox{
  848    su_clone_fun tb_clone;
  849    su_delete_fun tb_delete;
  850    su_assign_fun tb_assign;
  851    su_compare_fun tb_compare;
  852    su_hash_fun tb_hash;
  853 };
  854 /* Use C-style casts, not and ever su_R()! */
  855 #define su_TOOLBOX_I9R(CLONE,DELETE,ASSIGN,COMPARE,HASH) \
  856 {\
  857    su_FIELD_INITN(tb_clone) (su_clone_fun)(CLONE),\
  858    su_FIELD_INITN(tb_delete) (su_delete_fun)(DELETE),\
  859    su_FIELD_INITN(tb_assign) (su_assign_fun)(ASSIGN),\
  860    su_FIELD_INITN(tb_compare) (su_compare_fun)(COMPARE),\
  861    su_FIELD_INITN(tb_hash) (su_hash_fun)(HASH)\
  862 }
  863 /* BASIC TYPE TRAITS }}} */
  864 /* BASIC C INTERFACE (SYMBOLS) {{{ */
  865 #define su_BOM 0xFEFFu
  866 /* su_state.. machinery: first byte: global log instance.. */
  867 enum su_log_level{
  868    su_LOG_EMERG,
  869    su_LOG_ALERT,
  870    su_LOG_CRIT,
  871    su_LOG_ERR,
  872    su_LOG_WARN,
  873    su_LOG_NOTICE,
  874    su_LOG_INFO,
  875    su_LOG_DEBUG
  876 };
  877 enum{
  878    su__LOG_MAX = su_LOG_DEBUG,
  879    su__LOG_SHIFT = 8,
  880    su__LOG_MASK = (1u << su__LOG_SHIFT) - 1
  881 };
  882 MCTA(1u<<su__LOG_SHIFT > su__LOG_MAX, "Bit ranges may not overlap")
  883 enum su_log_flags{
  884    su_LOG_F_CORE = 1u<<(su__LOG_SHIFT+0)
  885 };
  886 enum su_state_log_flags{
  887    su_STATE_LOG_SHOW_LEVEL = 1u<<4,
  888    su_STATE_LOG_SHOW_PID = 1u<<5
  889 };
  890 /* ..second byte: hardening errors.. */
  891 enum su_state_err_type{
  892    su_STATE_ERR_NOMEM = 1u<<8,
  893    su_STATE_ERR_OVERFLOW = 1u<<9
  894 };
  895 enum su_state_err_flags{
  896    su_STATE_ERR_TYPE_MASK = su_STATE_ERR_NOMEM | su_STATE_ERR_OVERFLOW,
  897    su_STATE_ERR_PASS = su_STATE_ERR_TYPE_MASK,
  898    su_STATE_ERR_NOPASS = 1u<<12,
  899    su_STATE_ERR_NOERRNO = 1u<<13,
  900    su_STATE_ERR_NIL_IS_VALID_OBJECT = 1u<<14,
  901    su_STATE_ERR_NILISVALO = su_STATE_ERR_NIL_IS_VALID_OBJECT,
  902    su_STATE_ERR_MASK = su_STATE_ERR_TYPE_MASK |
  903          su_STATE_ERR_PASS | su_STATE_ERR_NOPASS | su_STATE_ERR_NOERRNO |
  904          su_STATE_ERR_NIL_IS_VALID_OBJECT
  905 };
  906 /* ..third byte: misc flags */
  907 enum su_state_flags{
  908    su_STATE_NONE,
  909    su_STATE_DEBUG = 1u<<16,
  910    su_STATE_VERBOSE = 1u<<17,
  911    su_STATE_REPRODUCIBLE = 1u<<18
  912 };
  913 enum su__state_flags{
  914    /* enum su_log_level is first "member" */
  915    su__STATE_LOG_MASK = 0x0Fu,
  916    su__STATE_D_V = su_STATE_DEBUG | su_STATE_VERBOSE,
  917    /* What is not allowed in the global state machine */
  918    su__STATE_GLOBAL_MASK = 0x00FFFFFFu & ~(su__STATE_LOG_MASK |
  919          (su_STATE_ERR_MASK & ~su_STATE_ERR_TYPE_MASK))
  920 };
  921 MCTA(S(uz,su_LOG_DEBUG) <= S(uz,su__STATE_LOG_MASK),
  922    "Bit ranges may not overlap")
  923 MCTA((S(uz,su_STATE_ERR_MASK) & ~0xFF00) == 0, "Bits excess documented bounds")
  924 #ifdef su_HAVE_MT
  925 enum su__glock_type{
  926    su__GLOCK_STATE,
  927    su__GLOCK_LOG,
  928    su__GLOCK_MAX = su__GLOCK_LOG
  929 };
  930 #endif
  931 enum su_err_number{
  932 #ifdef DOXYGEN
  933    su_ERR_NONE,
  934    su_ERR_NOTOBACCO
  935 #else
  936    su__ERR_NUMBER_ENUM_C
  937 # undef su__ERR_NUMBER_ENUM_C
  938 #endif
  939 };
  940 union su__bom_union{
  941    char bu_buf[2];
  942    u16 bu_val;
  943 };
  944 /* Known endianness bom versions, see su_bom_little, su_bom_big */
  945 EXPORT_DATA union su__bom_union const su__bom_little;
  946 EXPORT_DATA union su__bom_union const su__bom_big;
  947 /* (Not yet) Internal enum su_state_* bit carrier */
  948 EXPORT_DATA uz su__state;
  949 EXPORT_DATA u16 const su_bom;
  950 #define su_bom_little su__bom_little.bu_val
  951 #define su_bom_big su__bom_big.bu_val
  952 #if defined su_CC_BOM || defined DOXYGEN
  953 # define su_BOM_IS_BIG() (su_CC_BOM == su_CC_BOM_BIG)
  954 # define su_BOM_IS_LITTLE() (su_CC_BOM == su_CC_BOM_LITTLE)
  955 #else
  956 # define su_BOM_IS_BIG() (su_bom == su_bom_big)
  957 # define su_BOM_IS_LITTLE() (su_bom == su_bom_little)
  958 #endif
  959 EXPORT_DATA char const su_empty[1];
  960 EXPORT_DATA char const su_reproducible_build[];
  961 EXPORT_DATA char const *su_program;
  962 /**/
  963 #ifdef su_HAVE_MT
  964 EXPORT void su__glock(enum su__glock_type gt);
  965 EXPORT void su__gunlock(enum su__glock_type gt);
  966 #endif
  967 INLINE u32 su_state_get(void){
  968    return (su__state & su__STATE_GLOBAL_MASK);
  969 }
  970 INLINE boole su_state_has(uz flags){
  971    flags &= su__STATE_GLOBAL_MASK;
  972    return ((su__state & flags) == flags);
  973 }
  974 INLINE void su_state_set(uz flags){
  975    MT( su__glock(su__GLOCK_STATE); )
  976    su__state |= flags & su__STATE_GLOBAL_MASK;
  977    MT( su__gunlock(su__GLOCK_STATE); )
  978 }
  979 INLINE void su_state_clear(uz flags){
  980    MT( su__glock(su__GLOCK_STATE); )
  981    su__state &= ~(flags & su__STATE_GLOBAL_MASK);
  982    MT( su__gunlock(su__GLOCK_STATE); )
  983 }
  984 EXPORT s32 su_state_err(enum su_state_err_type err, uz state,
  985       char const *msg_or_nil);
  986 EXPORT s32 su_err_no(void);
  987 EXPORT s32 su_err_set_no(s32 eno);
  988 EXPORT char const *su_err_doc(s32 eno);
  989 EXPORT char const *su_err_name(s32 eno);
  990 EXPORT s32 su_err_from_name(char const *name);
  991 EXPORT s32 su_err_no_via_errno(void);
  992 INLINE enum su_log_level su_log_get_level(void){
  993    return S(enum su_log_level,su__state & su__STATE_LOG_MASK);
  994 }
  995 INLINE void su_log_set_level(enum su_log_level nlvl){
  996    uz lvl;
  997    /*MT( su__glock(su__GLOCK_STATE); )*/
  998    lvl = S(uz,nlvl) & su__STATE_LOG_MASK;
  999    su__state = (su__state & su__STATE_GLOBAL_MASK) | lvl;
 1000    /*MT( su__gunlock(su__GLOCK_STATE); )*/
 1001 }
 1002 INLINE boole su_log_would_write(enum su_log_level lvl){
 1003    return ((S(u32,lvl) & su__LOG_MASK) <= (su__state & su__STATE_LOG_MASK) ||
 1004       (su__state & su__STATE_D_V));
 1005 }
 1006 EXPORT void su_log_write(BITENUM_IS(u32,su_log_level) lvl,
 1007       char const *fmt, ...);
 1008 EXPORT void su_log_vwrite(BITENUM_IS(u32,su_log_level) lvl,
 1009       char const *fmt, void *vp);
 1010 EXPORT void su_perr(char const *msg, s32 eno_or_0);
 1011 INLINE void su_log_lock(void){
 1012    MT( su__glock(su__GLOCK_LOG); )
 1013 }
 1014 INLINE void su_log_unlock(void){
 1015    MT( su__gunlock(su__GLOCK_LOG); )
 1016 }
 1017 #if !defined su_ASSERT_EXPAND_NOTHING || defined DOXYGEN
 1018 EXPORT void su_assert(char const *expr, char const *file, u32 line,
 1019       char const *fun, boole crash);
 1020 #else
 1021 # define su_assert(EXPR,FILE,LINE,FUN,CRASH)
 1022 #endif
 1023 #if DVLOR(1, 0)
 1024 EXPORT void su_nyd_set_disabled(boole disabled);
 1025 EXPORT void su_nyd_reset_level(u32 nlvl);
 1026 EXPORT void su_nyd_chirp(u8 act, char const *file, u32 line, char const *fun);
 1027 EXPORT void su_nyd_dump(void (*ptf)(up cookie, char const *buf, uz blen),
 1028       up cookie);
 1029 #endif
 1030 /* BASIC C INTERFACE (SYMBOLS) }}} */
 1031 C_DECL_END
 1032 #include <su/code-ou.h>
 1033 #if !su_C_LANG || defined CXX_DOXYGEN
 1034 # define su_CXX_HEADER
 1035 # include <su/code-in.h>
 1036 NSPC_BEGIN(su)
 1037 /* POD TYPE SUPPORT {{{ */
 1038 // All instanceless static encapsulators.
 1039 class min;
 1040 class max;
 1041 // Define in-namespace wrappers for C types.  code-in/ou do not define short
 1042 // names for POD when used from within C++
 1043 typedef su_ul ul;
 1044 typedef su_ui ui;
 1045 typedef su_us us;
 1046 typedef su_uc uc;
 1047 typedef su_sl sl;
 1048 typedef su_si si;
 1049 typedef su_ss ss;
 1050 typedef su_sc sc;
 1051 typedef su_u8 u8;
 1052 typedef su_s8 s8;
 1053 typedef su_u16 u16;
 1054 typedef su_s16 s16;
 1055 typedef su_u32 u32;
 1056 typedef su_s32 s32;
 1057 typedef su_u64 u64;
 1058 typedef su_s64 s64;
 1059 typedef su_uz uz;
 1060 typedef su_sz sz;
 1061 typedef su_up up;
 1062 typedef su_sp sp;
 1063 typedef su_boole boole;
 1064 enum{
 1065    FAL0 = su_FAL0,
 1066    TRU1 = su_TRU1,
 1067    TRU2 = su_TRU2,
 1068    TRUM1 = su_TRUM1
 1069 };
 1070 /* Place the mentioned alignment CTAs */
 1071 MCTA(IS_POW2(sizeof(uz)), "Must be power of two")
 1072 MCTA(IS_POW2(su__ZAL_S), "Must be power of two")
 1073 MCTA(IS_POW2(su__ZAL_L), "Must be power of two")
 1074 class min{
 1075 public:
 1076    static NSPC(su)s8 const s8 = su_S8_MIN;
 1077    static NSPC(su)s16 const s16 = su_S16_MIN;
 1078    static NSPC(su)s32 const s32 = su_S32_MIN;
 1079    static NSPC(su)s64 const s64 = su_S64_MIN;
 1080    static NSPC(su)sz const sz = su_SZ_MIN;
 1081 };
 1082 class max{
 1083 public:
 1084    static NSPC(su)s8 const s8 = su_S8_MAX;
 1085    static NSPC(su)s16 const s16 = su_S16_MAX;
 1086    static NSPC(su)s32 const s32 = su_S32_MAX;
 1087    static NSPC(su)s64 const s64 = su_S64_MAX;
 1088    static NSPC(su)sz const sz = su_SZ_MAX;
 1089    static NSPC(su)u8 const u8 = su_U8_MAX;
 1090    static NSPC(su)u16 const u16 = su_U16_MAX;
 1091    static NSPC(su)u32 const u32 = su_U32_MAX;
 1092    static NSPC(su)u64 const u64 = su_U64_MAX;
 1093    static NSPC(su)uz const uz = su_UZ_MAX;
 1094 };
 1095 /* POD TYPE SUPPORT }}} */
 1096 /* BASIC TYPE TRAITS {{{ */
 1097 template<class T> class type_traits;
 1098 template<class T> struct type_toolbox;
 1099 // Plus C wrapper typedef
 1100 // External forward, defined in a-t-t.h.
 1101 template<class T> class auto_type_toolbox;
 1102 typedef su_toolbox toolbox;
 1103 template<class T>
 1104 class type_traits{
 1105 public:
 1106    typedef T type;
 1107    typedef T *tp;
 1108    typedef T const type_const;
 1109    typedef T const *tp_const;
 1110    typedef NSPC(su)type_toolbox<type> type_toolbox;
 1111    typedef NSPC(su)auto_type_toolbox<type> auto_type_toolbox;
 1112    static boole const ownguess = TRU1;
 1113    static boole const ownguess_key = TRU1;
 1114    static void *to_vp(tp_const t) {return C(void*,S(void const*,t));}
 1115    static void const *to_const_vp(tp_const t) {return t;}
 1116    static tp to_tp(void const *t) {return C(tp,S(tp_const,t));}
 1117    static tp_const to_const_tp(void const *t) {return S(tp_const,t);}
 1118 };
 1119 // Some specializations
 1120 template<class T>
 1121 class type_traits<T const>{ // (ugly, but required for some node based colls..)
 1122 public:
 1123    typedef T type;
 1124    typedef T *tp;
 1125    typedef T const type_const;
 1126    typedef T const *tp_const;
 1127    typedef NSPC(su)type_toolbox<type> type_toolbox;
 1128    typedef NSPC(su)auto_type_toolbox<type> auto_type_toolbox;
 1129    static boole const ownguess = FAL0;
 1130    static boole const ownguess_key = TRU1;
 1131    static void *to_vp(tp_const t) {return C(tp,t);}
 1132    static void const *to_const_vp(tp_const t) {return t;}
 1133    static tp to_tp(void const *t) {return C(tp,S(tp_const,t));}
 1134    static tp_const to_const_tp(void const *t) {return S(tp_const,t);}
 1135 };
 1136 template<class T>
 1137 class type_traits<T *>{
 1138 public:
 1139    typedef T type;
 1140    typedef T *tp;
 1141    typedef T const type_const;
 1142    typedef T const *tp_const;
 1143    typedef NSPC(su)type_toolbox<type> type_toolbox;
 1144    typedef NSPC(su)auto_type_toolbox<type> auto_type_toolbox;
 1145    static boole const ownguess = FAL0;
 1146    static boole const ownguess_key = TRU1;
 1147    static void *to_vp(tp_const t) {return C(tp,t);}
 1148    static void const *to_const_vp(tp_const t) {return t;}
 1149    static tp to_tp(void const *t) {return C(tp,S(tp_const,t));}
 1150    static tp_const to_const_tp(void const *t) {return S(tp_const,t);}
 1151 };
 1152 template<>
 1153 class type_traits<void *>{
 1154 public:
 1155    typedef void *type;
 1156    typedef void *tp;
 1157    typedef void const *type_const;
 1158    typedef void const *tp_const;
 1159    typedef NSPC(su)toolbox type_toolbox;
 1160    typedef NSPC(su)auto_type_toolbox<void *> auto_type_toolbox;
 1161    static boole const ownguess = FAL0;
 1162    static boole const ownguess_key = FAL0;
 1163    static void *to_vp(tp_const t) {return C(tp,t);}
 1164    static void const *to_const_vp(tp_const t) {return t;}
 1165    static tp to_tp(void const *t) {return C(tp,S(tp_const,t));}
 1166    static tp_const to_const_tp(void const *t) {return S(tp_const,t);}
 1167 };
 1168 template<>
 1169 class type_traits<void const *>{
 1170 public:
 1171    typedef void const *type;
 1172    typedef void const *tp;
 1173    typedef void const *type_const;
 1174    typedef void const *tp_const;
 1175    typedef NSPC(su)toolbox type_toolbox;
 1176    typedef NSPC(su)auto_type_toolbox<void const *> auto_type_toolbox;
 1177    static boole const ownguess = FAL0;
 1178    static boole const ownguess_key = FAL0;
 1179    static void *to_vp(tp_const t) {return C(void*,t);}
 1180    static void const *to_const_vp(tp_const t) {return t;}
 1181    static tp to_tp(void const *t) {return C(void*,t);}
 1182    static tp_const to_const_tp(void const *t) {return t;}
 1183 };
 1184 template<>
 1185 class type_traits<char *>{
 1186 public:
 1187    typedef char *type;
 1188    typedef char *tp;
 1189    typedef char const *type_const;
 1190    typedef char const *tp_const;
 1191    typedef NSPC(su)type_toolbox<type> type_toolbox;
 1192    typedef NSPC(su)auto_type_toolbox<type> auto_type_toolbox;
 1193    static boole const ownguess = FAL0;
 1194    static boole const ownguess_key = TRU1;
 1195    static void *to_vp(tp_const t) {return C(tp,t);}
 1196    static void const *to_const_vp(tp_const t) {return t;}
 1197    static tp to_tp(void const *t) {return C(tp,S(tp_const,t));}
 1198    static tp_const to_const_tp(void const *t) {return S(tp_const,t);}
 1199 };
 1200 template<>
 1201 class type_traits<char const *>{
 1202 public:
 1203    typedef char const *type;
 1204    typedef char const *tp;
 1205    typedef char const *type_const;
 1206    typedef char const *tp_const;
 1207    typedef NSPC(su)type_toolbox<type> type_toolbox;
 1208    typedef NSPC(su)auto_type_toolbox<type> auto_type_toolbox;
 1209    static boole const ownguess = FAL0;
 1210    static boole const ownguess_key = TRU1;
 1211    static void *to_vp(tp_const t) {return C(char*,t);}
 1212    static void const *to_const_vp(tp_const t) {return t;}
 1213    static tp to_tp(void const *t) {return C(char*,S(tp_const,t));}
 1214    static tp_const to_const_tp(void const *t) {return S(tp_const,t);}
 1215 };
 1216 template<class T>
 1217 struct type_toolbox{
 1218    typedef NSPC(su)type_traits<T> type_traits;
 1219    typedef typename type_traits::tp (*clone_fun)(
 1220          typename type_traits::tp_const t, u32 estate);
 1221    typedef void (*delete_fun)(typename type_traits::tp self);
 1222    typedef typename type_traits::tp (*assign_fun)(
 1223          typename type_traits::tp self, typename type_traits::tp_const t,
 1224          u32 estate);
 1225    typedef sz (*compare_fun)(typename type_traits::tp_const self,
 1226          typename type_traits::tp_const t);
 1227    typedef uz (*hash_fun)(typename type_traits::tp_const self);
 1228    clone_fun ttb_clone;
 1229    delete_fun ttb_delete;
 1230    assign_fun ttb_assign;
 1231    compare_fun ttb_compare;
 1232    hash_fun ttb_hash;
 1233 };
 1234 #define su_TYPE_TOOLBOX_I9R(CLONE,DELETE,ASSIGN,COMPARE,HASH) \
 1235       { CLONE, DELETE, ASSIGN, COMPARE, HASH }
 1236 // abc,clip,max,min,pow2 -- the C macros are in SUPPORT MACROS+
 1237 template<class T> inline T get_abs(T const &a) {return su_ABS(a);}
 1238 template<class T>
 1239 inline T const &get_clip(T const &a, T const &min, T const &max){
 1240    return su_CLIP(a, min, max);
 1241 }
 1242 template<class T>
 1243 inline T const &get_max(T const &a, T const &b) {return su_MAX(a, b);}
 1244 template<class T>
 1245 inline T const &get_min(T const &a, T const &b) {return su_MIN(a, b);}
 1246 template<class T>
 1247 inline T const &get_round_down(T const &a, T const &b){
 1248    return su_ROUND_DOWN(a, b);
 1249 }
 1250 template<class T>
 1251 inline T const &get_round_down2(T const &a, T const &b){
 1252    return su_ROUND_DOWN2(a, b);
 1253 }
 1254 template<class T>
 1255 inline T const &get_round_up(T const &a, T const &b){
 1256    return su_ROUND_UP(a, b);
 1257 }
 1258 template<class T>
 1259 inline T const &get_round_up2(T const &a, T const &b){
 1260    return su_ROUND_UP2(a, b);
 1261 }
 1262 template<class T> inline int is_pow2(T const &a) {return su_IS_POW2(a);}
 1263 /* BASIC TYPE TRAITS }}} */
 1264 /* BASIC C++ INTERFACE (SYMBOLS) {{{ */
 1265 // FIXME C++ does not yet expose the public C EXPORT_DATA symbols
 1266 // All instanceless static encapsulators.
 1267 class bom;
 1268 class err;
 1269 class log;
 1270 class state;
 1271 class bom{
 1272 public:
 1273    static u16 host(void) {return su_BOM;}
 1274    static u16 little(void) {return su_bom_little;}
 1275    static u16 big(void) {return su_bom_big;}
 1276 };
 1277 class err{
 1278 public:
 1279    enum err_number{
 1280 #ifdef DOXYGEN
 1281       enone,
 1282       enotobacco
 1283 #else
 1284       su__CXX_ERR_NUMBER_ENUM
 1285 # undef su__CXX_ERR_NUMBER_ENUM
 1286 #endif
 1287    };
 1288    static s32 no(void) {return su_err_no();}
 1289    static void set_no(s32 eno) {su_err_set_no(eno);}
 1290    static char const *doc(s32 eno) {return su_err_doc(eno);}
 1291    static char const *name(s32 eno) {return su_err_name(eno);}
 1292    static s32 from_name(char const *name) {return su_err_from_name(name);}
 1293    static s32 no_via_errno(void) {return su_err_no_via_errno();}
 1294 };
 1295 class log{
 1296 public:
 1297    enum level{
 1298       emerg = su_LOG_EMERG,
 1299       alert = su_LOG_ALERT,
 1300       crit = su_LOG_CRIT,
 1301       err = su_LOG_ERR,
 1302       warn = su_LOG_WARN,
 1303       notice = su_LOG_NOTICE,
 1304       info = su_LOG_INFO,
 1305       debug = su_LOG_DEBUG
 1306    };
 1307    enum flags{
 1308       f_core = su_LOG_F_CORE,
 1309    };
 1310    // Log functions of various sort.
 1311    // Regardless of the level these also log if state_debug|state_verbose.
 1312    // The vp is a &va_list
 1313    static level get_level(void) {return S(level,su_log_get_level());}
 1314    static void set_level(level lvl) {su_log_set_level(S(su_log_level,lvl));}
 1315    static boole get_show_level(void){
 1316       return su_state_has(su_STATE_LOG_SHOW_LEVEL);
 1317    }
 1318    static void set_show_level(boole on){
 1319       if(on)
 1320          su_state_set(su_STATE_LOG_SHOW_LEVEL);
 1321       else
 1322          su_state_clear(su_STATE_LOG_SHOW_LEVEL);
 1323    }
 1324    static boole get_show_pid(void){
 1325       return su_state_has(su_STATE_LOG_SHOW_PID);
 1326    }
 1327    static void set_show_pid(boole on){
 1328       if(on)
 1329          su_state_set(su_STATE_LOG_SHOW_PID);
 1330       else
 1331          su_state_clear(su_STATE_LOG_SHOW_PID);
 1332    }
 1333    static boole would_write(level lvl){
 1334       return su_log_would_write(S(su_log_level,lvl));
 1335    }
 1336    static void write(BITENUM_IS(u32,level) lvl, char const *fmt, ...);
 1337    static void vwrite(BITENUM_IS(u32,level) lvl, char const *fmt, void *vp){
 1338       su_log_vwrite(lvl, fmt, vp);
 1339    }
 1340    static void perr(char const *msg, s32 eno_or_0) {su_perr(msg, eno_or_0);}
 1341    static void lock(void) {su_log_lock();}
 1342    static void unlock(void) {su_log_unlock();}
 1343 };
 1344 class state{
 1345 public:
 1346    enum err_type{
 1347       err_nomem = su_STATE_ERR_NOMEM,
 1348       err_overflow = su_STATE_ERR_OVERFLOW
 1349    };
 1350    enum err_flags{
 1351       err_type_mask = su_STATE_ERR_TYPE_MASK,
 1352       err_pass = su_STATE_ERR_PASS,
 1353       err_nopass = su_STATE_ERR_NOPASS,
 1354       err_noerrno = su_STATE_ERR_NOERRNO,
 1355       err_mask = su_STATE_ERR_MASK
 1356    };
 1357    enum flags{
 1358       none = su_STATE_NONE,
 1359       debug = su_STATE_DEBUG,
 1360       verbose = su_STATE_VERBOSE,
 1361       reproducible = su_STATE_REPRODUCIBLE
 1362    };
 1363    static char const *get_program(void) {return su_program;}
 1364    static void set_program(char const *name) {su_program = name;}
 1365    static boole get(void) {return su_state_get();}
 1366    static boole has(uz state) {return su_state_has(state);}
 1367    static void set(uz state) {su_state_set(state);}
 1368    static void clear(uz state) {su_state_clear(state);}
 1369    static s32 err(err_type err, uz state, char const *msg_or_nil=NIL){
 1370       return su_state_err(S(su_state_err_type,err), state, msg_or_nil);
 1371    }
 1372 };
 1373 /* BASIC C++ INTERFACE (SYMBOLS) }}} */
 1374 NSPC_END(su)
 1375 #include <su/code-ou.h>
 1376 #endif /* !C_LANG || CXX_DOXYGEN */
 1377 /* MORE DOXYGEN TOP GROUPS {{{ */
 1378 /* MORE DOXYGEN TOP GROUPS }}} */
 1379 #endif /* !su_CODE_H */
 1380 /* s-it-mode */