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
su_state_get(void)967 INLINE u32 su_state_get(void){
968    return (su__state & su__STATE_GLOBAL_MASK);
969 }
su_state_has(uz flags)970 INLINE boole su_state_has(uz flags){
971    flags &= su__STATE_GLOBAL_MASK;
972    return ((su__state & flags) == flags);
973 }
su_state_set(uz flags)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 }
su_state_clear(uz flags)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);
su_log_get_level(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 }
su_log_set_level(enum su_log_level nlvl)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 }
su_log_would_write(enum su_log_level lvl)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);
su_log_lock(void)1011 INLINE void su_log_lock(void){
1012    MT( su__glock(su__GLOCK_LOG); )
1013 }
su_log_unlock(void)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 /* MORE DOXYGEN TOP GROUPS {{{ */
1034 /* MORE DOXYGEN TOP GROUPS }}} */
1035 #endif /* !su_CODE_H */
1036 /* s-it-mode */
1037