Bump S-nail v14.9.25.ar ("Lubimy Gorod"), 2024-06-27
[s-mailx.git] / include / su / code.h
blobc7a2af35bd747323778f4bfac36da00ad59a65fd
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.
12 * Copyright (c) 2001 - 2020 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
13 * SPDX-License-Identifier: ISC
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.
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.
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_CLANG || su_CC_GCC || su_CC_PCC
312 # if defined __STDC_VERSION__ && __STDC_VERSION__ +0 >= 199901l
313 # if !defined NDEBUG || !defined __OPTIMIZE__
314 # define su_INLINE static inline
315 # define su_SINLINE static inline
316 # else
317 /* clang does not like inline with <-O2 */
318 # define su_INLINE inline __attribute__((always_inline))
319 # define su_SINLINE static inline __attribute__((always_inline))
320 # endif
321 # else
322 # if su_CC_VCHECK_GCC(3, 1)
323 # define su_INLINE static __inline __attribute__((always_inline))
324 # define su_SINLINE static __inline __attribute__((always_inline))
325 # else
326 # define su_INLINE static __inline
327 # define su_SINLINE static __inline
328 # endif
329 # endif
330 # else
331 # define su_INLINE static /* TODO __attribute__((unused)) alike? */
332 # define su_SINLINE static /* TODO __attribute__((unused)) alike? */
333 # undef su_HAVE_INLINE
334 # endif
335 #else
336 # define su_INLINE inline
337 # define su_SINLINE static inline
338 #endif
339 #ifndef NDEBUG
340 # undef su_HAVE_INLINE
341 #endif
342 #if defined __predict_true && defined __predict_false
343 # define su_LIKELY(X) __predict_true((X) != 0)
344 # define su_UNLIKELY(X) __predict_false((X) != 0)
345 #elif su_CC_CLANG || su_CC_VCHECK_GCC(2, 96) || su_CC_PCC || su_CC_TINYC
346 # define su_LIKELY(X) __builtin_expect((X) != 0, 1)
347 # define su_UNLIKELY(X) __builtin_expect((X) != 0, 0)
348 #else
349 # define su_LIKELY(X) ((X) != 0)
350 # define su_UNLIKELY(X) ((X) != 0)
351 #endif
352 /* CC }}} */
353 /* SUPPORT MACROS+ {{{ */
354 /* USECASE_XY_DISABLED for tagging unused files:
355 * git rm `git grep ^su_USECASE_MX_DISABLED` */
356 #ifdef su_USECASE_MX
357 # define su_USECASE_MX_DISABLED This file is not a (valid) compilation unit
358 #endif
359 #ifndef su_USECASE_MX_DISABLED
360 # define su_USECASE_MX_DISABLED
361 #endif
362 /* Basic support macros, with side effects */
363 #define su_ABS(A) ((A) < 0 ? -(A) : (A))
364 #define su_CLIP(X,A,B) (((X) <= (A)) ? (A) : (((X) >= (B)) ? (B) : (X)))
365 #define su_IS_POW2(X) ((((X) - 1) & (X)) == 0)
366 #define su_MAX(A,B) ((A) < (B) ? (B) : (A))
367 #define su_MIN(A,B) ((A) < (B) ? (A) : (B))
368 #define su_ROUND_DOWN(X,BASE) (((X) / (BASE)) * (BASE))
369 #define su_ROUND_DOWN2(X,BASE) ((X) & (~((BASE) - 1)))
370 #define su_ROUND_UP(X,BASE) ((((X) + ((BASE) - 1)) / (BASE)) * (BASE))
371 #define su_ROUND_UP2(X,BASE) (((X) + ((BASE) - 1)) & (~((BASE) - 1)))
372 /* Alignment. Note: su_uz POW2 asserted in POD section below! */
373 /* Commented out: "_Alignof() applied to an expression is a GNU extension" */
374 #if 0 && defined __STDC_VERSION__ && __STDC_VERSION__ +0 >= 201112L
375 # include <stdalign.h>
376 # define su_ALIGNOF(X) _Alignof(X)
377 #else
378 # define su_ALIGNOF(X) su_ROUND_UP2(sizeof(X), su__ZAL_L)
379 #endif
380 #define su_P_ALIGN(DTYPE,OTYPE,MEM) \
381 su_R(DTYPE,\
382 su_IS_POW2(su_ALIGNOF(OTYPE))\
383 ? su_ROUND_UP2(su_R(su_up,MEM), su_ALIGNOF(OTYPE))\
384 : su_ROUND_UP(su_R(su_up,MEM), su_ALIGNOF(OTYPE)))
385 /* Roundup/align an integer; Note: POW2 asserted in POD section below! */
386 #define su_Z_ALIGN_OVER(X) su_ROUND_UP2(su_S(su_uz,X), 2 * su__ZAL_L)
387 #define su_Z_ALIGN(X) su_ROUND_UP2(su_S(su_uz,X), su__ZAL_L)
388 #define su_Z_ALIGN_PZ(X) su_ROUND_UP2(su_S(su_uz,X), su__ZAL_S)
389 /* (These are below MCTA()d to be of equal size[, however].)
390 * _L must adhere to the minimum aligned claimed in the \mainpage */
391 # define su__ZAL_S su_MAX(sizeof(su_uz), sizeof(void*))
392 # define su__ZAL_L su_MAX(su__ZAL_S, sizeof(su_u64))/* XXX FP,128bit */
393 /* Variants of ASSERT */
394 #if defined NDEBUG || defined DOXYGEN
395 # define su_ASSERT_INJ(X)
396 # define su_ASSERT_INJOR(X,Y) Y
397 # define su_ASSERT_NB(X) ((void)0)
398 # define su_ASSERT(X) do{}while(0)
399 # define su_ASSERT_LOC(X,FNAME,LNNO) do{}while(0)
400 # define su_ASSERT_EXEC(X,S) do{}while(0)
401 # define su_ASSERT_EXEC_LOC(X,S,FNAME,LNNO) do{}while(0)
402 # define su_ASSERT_JUMP(X,L) do{}while(0)
403 # define su_ASSERT_JUMP_LOC(X,L,FNAME,LNNO) do{}while(0)
404 # define su_ASSERT_RET(X,Y) do{}while(0)
405 # define su_ASSERT_RET_LOC(X,Y,FNAME,LNNO) do{}while(0)
406 # define su_ASSERT_RET_VOID(X) do{}while(0)
407 # define su_ASSERT_RET_VOID_LOC(X,Y,FNAME,LNNO) do{}while(0)
408 # define su_ASSERT_NYD_EXEC(X,Y) do{}while(0)
409 # define su_ASSERT_NYD_EXEC_LOC(X,FNAME,LNNO) do{}while(0)
410 # define su_ASSERT_NYD(X) do{}while(0)
411 # define su_ASSERT_NYD_LOC(X,FNAME,LNNO) do{}while(0)
412 #else
413 # define su_ASSERT_INJ(X) X
414 # define su_ASSERT_INJOR(X,Y) X
415 # define su_ASSERT_NB(X) \
416 su_R(void,((X) ? su_TRU1 \
417 : su_assert(su_STRING(X), __FILE__, __LINE__, su_FUN, su_TRU1), su_FAL0))
418 # define su_ASSERT(X) su_ASSERT_LOC(X, __FILE__, __LINE__)
419 # define su_ASSERT_LOC(X,FNAME,LNNO) \
420 do if(!(X))\
421 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_TRU1);\
422 while(0)
423 # define su_ASSERT_EXEC(X,S) su_ASSERT_EXEC_LOC(X, S, __FILE__, __LINE__)
424 # define su_ASSERT_EXEC_LOC(X,S,FNAME,LNNO) \
425 do if(!(X)){\
426 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
428 }while(0)
429 # define su_ASSERT_JUMP(X,L) su_ASSERT_JUMP_LOC(X, L, __FILE__, __LINE__)
430 # define su_ASSERT_JUMP_LOC(X,L,FNAME,LNNO) \
431 do if(!(X)){\
432 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
433 goto L;\
434 }while(0)
435 # define su_ASSERT_RET(X,Y) su_ASSERT_RET_LOC(X, Y, __FILE__, __LINE__)
436 # define su_ASSERT_RET_LOC(X,Y,FNAME,LNNO) \
437 do if(!(X)){\
438 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
439 return Y;\
440 }while(0)
441 # define su_ASSERT_RET_VOID(X) su_ASSERT_RET_VOID_LOC(X, __FILE__, __LINE__)
442 # define su_ASSERT_RET_VOID_LOC(X,FNAME,LNNO) \
443 do if(!(X)){\
444 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
445 return;\
446 }while(0)
447 # define su_ASSERT_NYD_EXEC(X,Y) \
448 su_ASSERT_NYD_EXEC_LOC(X, Y, __FILE__, __LINE__)
449 # define su_ASSERT_NYD_EXEC_LOC(X,Y,FNAME,LNNO) \
450 do if(!(X)){\
451 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
452 Y; goto su_NYD_OU_LABEL;\
453 }while(0)
454 # define su_ASSERT_NYD(X) su_ASSERT_NYD_LOC(X, __FILE__, __LINE__)
455 # define su_ASSERT_NYD_LOC(X,FNAME,LNNO) \
456 do if(!(X)){\
457 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
458 goto su_NYD_OU_LABEL;\
459 }while(0)
460 #endif /* defined NDEBUG || defined DOXYGEN */
461 #define su_BITENUM_IS(X,Y) X
462 #define su_BITENUM_MASK(LO,HI) (((1u << ((HI) + 1)) - 1) & ~((1u << (LO)) - 1))
463 #define su_COMMA ,
464 /* Debug injections */
465 #if defined su_HAVE_DEBUG && !defined NDEBUG
466 # define su_DBG(X) X
467 # define su_NDBG(X)
468 # define su_DBGOR(X,Y) X
469 #else
470 # define su_DBG(X)
471 # define su_NDBG(X) X
472 # define su_DBGOR(X,Y) Y
473 #endif
474 /* Debug file location arguments. (For an usage example see su/mem.h.) */
475 #if defined su_HAVE_DEVEL || defined su_HAVE_DEBUG
476 # define su_HAVE_DBG_LOC_ARGS
477 # define su_DBG_LOC_ARGS_FILE su__dbg_loc_args_file
478 # define su_DBG_LOC_ARGS_LINE su__dbg_loc_args_line
479 # define su_DBG_LOC_ARGS_DECL_SOLE \
480 char const *su_DBG_LOC_ARGS_FILE, su_u32 su_DBG_LOC_ARGS_LINE
481 # define su_DBG_LOC_ARGS_DECL , su_DBG_LOC_ARGS_DECL_SOLE
482 # define su_DBG_LOC_ARGS_INJ_SOLE __FILE__, __LINE__
483 # define su_DBG_LOC_ARGS_INJ , su_DBG_LOC_ARGS_INJ_SOLE
484 # define su_DBG_LOC_ARGS_USE_SOLE su_DBG_LOC_ARGS_FILE, su_DBG_LOC_ARGS_LINE
485 # define su_DBG_LOC_ARGS_USE , su_DBG_LOC_ARGS_USE_SOLE
486 # define su_DBG_LOC_ARGS_ORUSE su_DBG_LOC_ARGS_FILE, su_DBG_LOC_ARGS_LINE
487 # define su_DBG_LOC_ARGS_UNUSED() \
488 do{\
489 su_UNUSED(su_DBG_LOC_ARGS_FILE);\
490 su_UNUSED(su_DBG_LOC_ARGS_LINE);\
491 }while(0)
492 #else
493 # define su_DBG_LOC_ARGS_FILE "unused"
494 # define su_DBG_LOC_ARGS_LINE 0
496 # define su_DBG_LOC_ARGS_DECL_SOLE
497 # define su_DBG_LOC_ARGS_DECL
498 # define su_DBG_LOC_ARGS_INJ_SOLE
499 # define su_DBG_LOC_ARGS_INJ
500 # define su_DBG_LOC_ARGS_USE_SOLE
501 # define su_DBG_LOC_ARGS_USE
502 # define su_DBG_LOC_ARGS_ORUSE su_DBG_LOC_ARGS_FILE, su_DBG_LOC_ARGS_LINE
503 # define su_DBG_LOC_ARGS_UNUSED() do{}while(0)
504 #endif /* su_HAVE_DEVEL || su_HAVE_DEBUG */
505 /* Development injections */
506 #if defined su_HAVE_DEVEL || defined su_HAVE_DEBUG /* Not: !defined NDEBUG) */\
507 || defined DOXYGEN
508 # define su_DVL(X) X
509 # define su_NDVL(X)
510 # define su_DVLOR(X,Y) X
511 #else
512 # define su_DVL(X)
513 # define su_NDVL(X) X
514 # define su_DVLOR(X,Y) Y
515 #endif
516 #define su_EMPTY_FILE() typedef int su_CONCAT(su_notempty_shall_b_, su_FILE);
517 /* C field init */
518 #if (su_C_LANG && defined __STDC_VERSION__ && \
519 __STDC_VERSION__ +0 >= 199901L) || defined DOXYGEN
520 # define su_FIELD_INITN(N) .N =
521 # define su_FIELD_INITI(I) [I] =
522 #else
523 # define su_FIELD_INITN(N)
524 # define su_FIELD_INITI(I)
525 #endif
526 /* XXX offsetof+: clang,pcc check faked! */
527 #if su_CC_VCHECK_CLANG(5, 0) || su_CC_VCHECK_GCC(4, 1) ||\
528 su_CC_VCHECK_PCC(1, 2) || defined DOXYGEN
529 # define su_FIELD_OFFSETOF(T,F) __builtin_offsetof(T, F)
530 #else
531 # define su_FIELD_OFFSETOF(T,F) \
532 su_S(su_uz,su_S(su_up,&(su_R(T *,0x1)->F)) - 1)
533 #endif
534 #define su_FIELD_RANGEOF(T,S,E) \
535 (su_FIELD_OFFSETOF(T, E) - su_FIELD_OFFSETOF(T, S))
536 #define su_FIELD_SIZEOF(T,F) sizeof(su_S(T *,su_NIL)->F)
537 /* Multithread injections */
538 #ifdef su_HAVE_MT
539 # define su_MT(X) X
540 #else
541 # define su_MT(X)
542 #endif
543 #define su_NELEM(A) (sizeof(A) / sizeof((A)[0]))
544 #define su_NYD_OU_LABEL su__nydou
545 #define su_P2UZ(X) su_S(su_uz,(su_up)(X))
546 #define su_PCMP(A,C,B) (su_R(su_up,A) C su_R(su_up,B))
547 /* SMP injections */
548 #ifdef su_HAVE_SMP
549 # define su_SMP(X) X
550 #else
551 # define su_SMP(X)
552 #endif
553 /* String stuff.
554 * __STDC_VERSION__ is ISO C99, so also use __STDC__, which should work */
555 #if defined __STDC__ || defined __STDC_VERSION__ || su_C_LANG || \
556 defined DOXYGEN
557 # define su_STRING(X) #X
558 # define su_XSTRING(X) su_STRING(X)
559 # define su_CONCAT(S1,S2) su__CONCAT_1(S1, S2)
560 # define su__CONCAT_1(S1,S2) S1 ## S2
561 #else
562 # define su_STRING(X) "X"
563 # define su_XSTRING STRING
564 # define su_CONCAT(S1,S2) S1/* will no work out though */S2
565 #endif
566 #if su_C_LANG || defined DOXYGEN
567 # define su_UCMP(T,A,C,B) (su_S(su_ ## u ## T,A) C su_S(su_ ## u ## T,B))
568 #else
569 # define su_UCMP(T,A,C,B) \
570 (su_S(su_NSPC(su) u ## T,A) C su_S(su_NSPC(su) u ## T,B))
571 #endif
572 #define su_UNCONST(T,P) su_R(T,su_R(su_up,su_S(void const*,P)))
573 #define su_UNVOLATILE(T,P) su_R(T,su_R(su_up,su_S(void volatile*,P)))
574 #define su_UNALIGN(T,P) su_R(T,su_R(su_up,P))
575 #define su_UNXXX(T,C,P) su_R(T,su_R(su_up,su_S(C,P)))
576 /* Avoid "may be used uninitialized" warnings */
577 #if (defined NDEBUG && !(defined su_HAVE_DEBUG || defined su_HAVE_DEVEL)) || \
578 defined DOYGEN
579 # define su_UNINIT(N,V) su_S(void,0)
580 # define su_UNINIT_DECL(V)
581 #else
582 # define su_UNINIT(N,V) N = V
583 # define su_UNINIT_DECL(V) = V
584 #endif
585 #define su_UNUSED(X) ((void)(X))
586 #if (su_C_LANG && defined __STDC_VERSION__ && \
587 __STDC_VERSION__ +0 >= 199901L) || defined DOXYGEN
588 # define su_VFIELD_SIZE(X)
589 # define su_VSTRUCT_SIZEOF(T,F) sizeof(T)
590 #else
591 # define su_VFIELD_SIZE(X) \
592 ((X) == 0 ? sizeof(su_uz) \
593 : (su_S(su_sz,X) < 0 ? sizeof(su_uz) - su_ABS(X) : su_S(su_uz,X)))
594 # define su_VSTRUCT_SIZEOF(T,F) (sizeof(T) - su_FIELD_SIZEOF(T, F))
595 #endif
596 /* SUPPORT MACROS+ }}} */
597 /* We are ready to start using our own style */
598 #ifndef su_CC_SIZE_TYPE
599 # include <sys/types.h> /* TODO create config time script, */
600 #endif
601 #include <inttypes.h> /* TODO query infos and drop */
602 #include <limits.h> /* TODO those includes! */
603 #define su_HEADER
604 #include <su/code-in.h>
605 C_DECL_BEGIN
606 /* POD TYPE SUPPORT TODO maybe configure-time, from a su/config.h?! {{{ */
607 /* TODO Note: the PRI* series will go away once we have FormatCtx! */
608 /* First some shorter aliases for "normal" integers */
609 typedef unsigned long su_ul;
610 typedef unsigned int su_ui;
611 typedef unsigned short su_us;
612 typedef unsigned char su_uc;
613 typedef signed long su_sl;
614 typedef signed int su_si;
615 typedef signed short su_ss;
616 typedef signed char su_sc;
617 #if defined UINT8_MAX || defined DOXYGEN
618 # define su_U8_MAX UINT8_MAX
619 # define su_S8_MIN INT8_MIN
620 # define su_S8_MAX INT8_MAX
621 typedef uint8_t su_u8;
622 typedef int8_t su_s8;
623 #elif UCHAR_MAX != 255
624 # error UCHAR_MAX must be 255
625 #else
626 # define su_U8_MAX UCHAR_MAX
627 # define su_S8_MIN CHAR_MIN
628 # define su_S8_MAX CHAR_MAX
629 typedef unsigned char su_u8;
630 typedef signed char su_s8;
631 #endif
632 #if !defined PRIu8 || !defined PRId8
633 # undef PRIu8
634 # undef PRId8
635 # define PRIu8 "hhu"
636 # define PRId8 "hhd"
637 #endif
638 #if defined UINT16_MAX || defined DOXYGEN
639 # define su_U16_MAX UINT16_MAX
640 # define su_S16_MIN INT16_MIN
641 # define su_S16_MAX INT16_MAX
642 typedef uint16_t su_u16;
643 typedef int16_t su_s16;
644 #elif USHRT_MAX != 0xFFFFu
645 # error USHRT_MAX must be 0xFFFF
646 #else
647 # define su_U16_MAX USHRT_MAX
648 # define su_S16_MIN SHRT_MIN
649 # define su_S16_MAX SHRT_MAX
650 typedef unsigned short su_u16;
651 typedef signed short su_s16;
652 #endif
653 #if !defined PRIu16 || !defined PRId16
654 # undef PRIu16
655 # undef PRId16
656 # if su_U16_MAX == UINT_MAX
657 # define PRIu16 "u"
658 # define PRId16 "d"
659 # else
660 # define PRIu16 "hu"
661 # define PRId16 "hd"
662 # endif
663 #endif
664 #if defined UINT32_MAX || defined DOXYGEN
665 # define su_U32_MAX UINT32_MAX
666 # define su_S32_MIN INT32_MIN
667 # define su_S32_MAX INT32_MAX
668 typedef uint32_t su_u32;
669 typedef int32_t su_s32;
670 #elif ULONG_MAX == 0xFFFFFFFFu
671 # define su_U32_MAX ULONG_MAX
672 # define su_S32_MIN LONG_MIN
673 # define su_S32_MAX LONG_MAX
674 typedef unsigned long int su_u32;
675 typedef signed long int su_s32;
676 #elif UINT_MAX != 0xFFFFFFFFu
677 # error UINT_MAX must be 0xFFFFFFFF
678 #else
679 # define su_U32_MAX UINT_MAX
680 # define su_S32_MIN INT_MIN
681 # define su_S32_MAX INT_MAX
682 typedef unsigned int su_u32;
683 typedef signed int su_s32;
684 #endif
685 #if !defined PRIu32 || !defined PRId32
686 # undef PRIu32
687 # undef PRId32
688 # if su_U32_MAX == ULONG_MAX
689 # define PRIu32 "lu"
690 # define PRId32 "ld"
691 # else
692 # define PRIu32 "u"
693 # define PRId32 "d"
694 # endif
695 #endif
696 #if defined UINT64_MAX || defined DOXYGEN
697 # define su_U64_MAX UINT64_MAX
698 # define su_S64_MIN INT64_MIN
699 # define su_S64_MAX INT64_MAX
700 # define su_S64_C(C) INT64_C(C)
701 # define su_U64_C(C) UINT64_C(C)
702 typedef uint64_t su_u64;
703 typedef int64_t su_s64;
704 #elif ULONG_MAX <= 0xFFFFFFFFu
705 # if !defined ULLONG_MAX
706 # error We need a 64 bit integer
707 # else
708 # define su_U64_MAX ULLONG_MAX
709 # define su_S64_MIN LLONG_MIN
710 # define su_S64_MAX LLONG_MAX
711 # define su_S64_C(C) su_CONCAT(C, ll)
712 # define su_U64_C(C) su_CONCAT(C, ull)
713 su_CC_EXTEN typedef unsigned long long su_u64;
714 su_CC_EXTEN typedef signed long long su_s64;
715 # endif
716 #else
717 # define su_U64_MAX ULONG_MAX
718 # define su_S64_MIN LONG_MIN
719 # define su_S64_MAX LONG_MAX
720 # define su_S64_C(C) su_CONCAT(C, l)
721 # define su_U64_C(C) su_CONCAT(C, ul)
722 typedef unsigned long su_u64;
723 typedef signed long su_s64;
724 #endif
725 #if !defined PRIu64 || !defined PRId64 || !defined PRIX64 || !defined PRIo64
726 # undef PRIu64
727 # undef PRId64
728 # undef PRIX64
729 # undef PRIo64
730 # if defined ULLONG_MAX && su_U64_MAX == ULLONG_MAX
731 # define PRIu64 "llu"
732 # define PRId64 "lld"
733 # define PRIX64 "llX"
734 # define PRIo64 "llo"
735 # else
736 # define PRIu64 "lu"
737 # define PRId64 "ld"
738 # define PRIX64 "lX"
739 # define PRIo64 "lo"
740 # endif
741 #endif
742 /* (So that we can use UCMP() for size_t comparison, too) */
743 #ifdef su_CC_SIZE_TYPE
744 typedef su_CC_SIZE_TYPE su_uz;
745 #else
746 typedef size_t su_uz;
747 #endif
748 #undef PRIuZ
749 #undef PRIdZ
750 #if (defined __STDC_VERSION__ && __STDC_VERSION__ +0 >= 199901L) ||\
751 defined DOXYGEN
752 # define PRIuZ "zu"
753 # define PRIdZ "zd"
754 # define su_UZ_MAX SIZE_MAX
755 #elif defined SIZE_MAX
756 /* UnixWare has size_t as unsigned as required but uses a signed limit
757 * constant (which is thus false!) */
758 # if SIZE_MAX == su_U64_MAX || SIZE_MAX == su_S64_MAX
759 # define PRIuZ PRIu64
760 # define PRIdZ PRId64
761 MCTA(sizeof(size_t) == sizeof(u64),
762 "Format string mismatch, compile with ISO C99 compiler (-std=c99)!")
763 # elif SIZE_MAX == su_U32_MAX || SIZE_MAX == su_S32_MAX
764 # define PRIuZ PRIu32
765 # define PRIdZ PRId32
766 MCTA(sizeof(size_t) == sizeof(u32),
767 "Format string mismatch, compile with ISO C99 compiler (-std=c99)!")
768 # else
769 # error SIZE_MAX is neither su_U64_MAX nor su_U32_MAX (please report this)
770 # endif
771 # define su_UZ_MAX SIZE_MAX
772 #endif
773 #if !defined PRIuZ && !defined DOXYGEN
774 # define PRIuZ "lu"
775 # define PRIdZ "ld"
776 MCTA(sizeof(size_t) == sizeof(unsigned long),
777 "Format string mismatch, compile with ISO C99 compiler (-std=c99)!")
778 #endif
779 /* The signed equivalence is not really compliant to the standard */
780 #if su_UZ_MAX == su_U32_MAX || su_UZ_MAX == su_S32_MAX || defined DOXYGEN
781 # define su_SZ_MIN su_S32_MIN
782 # define su_SZ_MAX su_S32_MAX
783 # define su_UZ_BITS 32u
784 # define su_64(X)
785 # define su_32(X) X
786 # define su_6432(X,Y) Y
787 typedef su_s32 su_sz;
788 #elif su_UZ_MAX == su_U64_MAX
789 # define su_SZ_MIN su_S64_MIN
790 # define su_SZ_MAX su_S64_MAX
791 # define su_UZ_BITS 64u
792 # define su_64(X) X
793 # define su_32(X)
794 # define su_6432(X,Y) X
795 typedef su_s64 su_sz;
796 #else
797 # error I cannot handle this maximum value of size_t
798 #endif
799 MCTA(sizeof(su_uz) == sizeof(void*),
800 "SU cannot handle sizeof(su_uz) != sizeof(void*)")
801 /* Regardless of P2UZ provide this one; only use it rarely */
802 #if defined UINTPTR_MAX || defined DOXYGEN
803 typedef uintptr_t su_up;
804 typedef intptr_t su_sp;
805 #else
806 # ifdef SIZE_MAX
807 typedef su_uz su_up;
808 typedef su_sz su_sp;
809 # else
810 typedef su_ul su_up;
811 typedef su_sl su_sp;
812 # endif
813 #endif
814 enum{
815 su_FAL0,
816 su_TRU1,
817 su_TRU2,
818 su_TRUM1 = -1
820 typedef su_s8 su_boole;
821 /* POD TYPE SUPPORT }}} */
822 /* BASIC TYPE TRAITS {{{ */
823 struct su_toolbox;
824 /* plus PTF typedefs */
825 typedef void *(*su_new_fun)(u32 estate);
826 typedef void *(*su_clone_fun)(void const *t, u32 estate);
827 typedef void (*su_delete_fun)(void *self);
828 typedef void *(*su_assign_fun)(void *self, void const *t, u32 estate);
829 typedef su_sz (*su_compare_fun)(void const *a, void const *b);
830 typedef su_uz (*su_hash_fun)(void const *self);
831 /* Needs to be binary compatible with \c{su::{toolbox,type_toolbox<T>}}! */
832 struct su_toolbox{
833 su_clone_fun tb_clone;
834 su_delete_fun tb_delete;
835 su_assign_fun tb_assign;
836 su_compare_fun tb_compare;
837 su_hash_fun tb_hash;
839 /* Use C-style casts, not and ever su_R()! */
840 #define su_TOOLBOX_I9R(CLONE,DELETE,ASSIGN,COMPARE,HASH) \
842 su_FIELD_INITN(tb_clone) (su_clone_fun)(CLONE),\
843 su_FIELD_INITN(tb_delete) (su_delete_fun)(DELETE),\
844 su_FIELD_INITN(tb_assign) (su_assign_fun)(ASSIGN),\
845 su_FIELD_INITN(tb_compare) (su_compare_fun)(COMPARE),\
846 su_FIELD_INITN(tb_hash) (su_hash_fun)(HASH)\
848 /* BASIC TYPE TRAITS }}} */
849 /* BASIC C INTERFACE (SYMBOLS) {{{ */
850 #define su_BOM 0xFEFFu
851 /* su_state.. machinery: first byte: global log instance.. */
852 enum su_log_level{
853 su_LOG_EMERG,
854 su_LOG_ALERT,
855 su_LOG_CRIT,
856 su_LOG_ERR,
857 su_LOG_WARN,
858 su_LOG_NOTICE,
859 su_LOG_INFO,
860 su_LOG_DEBUG
862 enum{
863 su__LOG_MAX = su_LOG_DEBUG,
864 su__LOG_SHIFT = 8,
865 su__LOG_MASK = (1u << su__LOG_SHIFT) - 1
867 MCTA(1u<<su__LOG_SHIFT > su__LOG_MAX, "Bit ranges may not overlap")
868 enum su_log_flags{
869 su_LOG_F_CORE = 1u<<(su__LOG_SHIFT+0)
871 enum su_state_log_flags{
872 su_STATE_LOG_SHOW_LEVEL = 1u<<4,
873 su_STATE_LOG_SHOW_PID = 1u<<5
875 /* ..second byte: hardening errors.. */
876 enum su_state_err_type{
877 su_STATE_ERR_NOMEM = 1u<<8,
878 su_STATE_ERR_OVERFLOW = 1u<<9
880 enum su_state_err_flags{
881 su_STATE_ERR_TYPE_MASK = su_STATE_ERR_NOMEM | su_STATE_ERR_OVERFLOW,
882 su_STATE_ERR_PASS = su_STATE_ERR_TYPE_MASK,
883 su_STATE_ERR_NOPASS = 1u<<12,
884 su_STATE_ERR_NOERRNO = 1u<<13,
885 su_STATE_ERR_NIL_IS_VALID_OBJECT = 1u<<14,
886 su_STATE_ERR_NILISVALO = su_STATE_ERR_NIL_IS_VALID_OBJECT,
887 su_STATE_ERR_MASK = su_STATE_ERR_TYPE_MASK |
888 su_STATE_ERR_PASS | su_STATE_ERR_NOPASS | su_STATE_ERR_NOERRNO |
889 su_STATE_ERR_NIL_IS_VALID_OBJECT
891 /* ..third byte: misc flags */
892 enum su_state_flags{
893 su_STATE_NONE,
894 su_STATE_DEBUG = 1u<<16,
895 su_STATE_VERBOSE = 1u<<17,
896 su_STATE_REPRODUCIBLE = 1u<<18
898 enum su__state_flags{
899 /* enum su_log_level is first "member" */
900 su__STATE_LOG_MASK = 0x0Fu,
901 su__STATE_D_V = su_STATE_DEBUG | su_STATE_VERBOSE,
902 /* What is not allowed in the global state machine */
903 su__STATE_GLOBAL_MASK = 0x00FFFFFFu & ~(su__STATE_LOG_MASK |
904 (su_STATE_ERR_MASK & ~su_STATE_ERR_TYPE_MASK))
906 MCTA(S(uz,su_LOG_DEBUG) <= S(uz,su__STATE_LOG_MASK),
907 "Bit ranges may not overlap")
908 MCTA((S(uz,su_STATE_ERR_MASK) & ~0xFF00) == 0, "Bits excess documented bounds")
909 #ifdef su_HAVE_MT
910 enum su__glock_type{
911 su__GLOCK_STATE,
912 su__GLOCK_LOG,
913 su__GLOCK_MAX = su__GLOCK_LOG
915 #endif
916 enum su_err_number{
917 #ifdef DOXYGEN
918 su_ERR_NONE,
919 su_ERR_NOTOBACCO
920 #else
921 su__ERR_NUMBER_ENUM_C
922 # undef su__ERR_NUMBER_ENUM_C
923 #endif
925 union su__bom_union{
926 char bu_buf[2];
927 u16 bu_val;
929 /* Known endianness bom versions, see su_bom_little, su_bom_big */
930 EXPORT_DATA union su__bom_union const su__bom_little;
931 EXPORT_DATA union su__bom_union const su__bom_big;
932 /* (Not yet) Internal enum su_state_* bit carrier */
933 EXPORT_DATA uz su__state;
934 EXPORT_DATA u16 const su_bom;
935 #define su_bom_little su__bom_little.bu_val
936 #define su_bom_big su__bom_big.bu_val
937 #if defined su_CC_BOM || defined DOXYGEN
938 # define su_BOM_IS_BIG() (su_CC_BOM == su_CC_BOM_BIG)
939 # define su_BOM_IS_LITTLE() (su_CC_BOM == su_CC_BOM_LITTLE)
940 #else
941 # define su_BOM_IS_BIG() (su_bom == su_bom_big)
942 # define su_BOM_IS_LITTLE() (su_bom == su_bom_little)
943 #endif
944 EXPORT_DATA char const su_empty[1];
945 EXPORT_DATA char const su_reproducible_build[];
946 EXPORT_DATA char const *su_program;
947 /**/
948 #ifdef su_HAVE_MT
949 EXPORT void su__glock(enum su__glock_type gt);
950 EXPORT void su__gunlock(enum su__glock_type gt);
951 #endif
952 INLINE u32 su_state_get(void){
953 return (su__state & su__STATE_GLOBAL_MASK);
955 INLINE boole su_state_has(uz flags){
956 flags &= su__STATE_GLOBAL_MASK;
957 return ((su__state & flags) == flags);
959 INLINE void su_state_set(uz flags){
960 MT( su__glock(su__GLOCK_STATE); )
961 su__state |= flags & su__STATE_GLOBAL_MASK;
962 MT( su__gunlock(su__GLOCK_STATE); )
964 INLINE void su_state_clear(uz flags){
965 MT( su__glock(su__GLOCK_STATE); )
966 su__state &= ~(flags & su__STATE_GLOBAL_MASK);
967 MT( su__gunlock(su__GLOCK_STATE); )
969 EXPORT s32 su_state_err(enum su_state_err_type err, uz state,
970 char const *msg_or_nil);
971 EXPORT s32 su_err_no(void);
972 EXPORT s32 su_err_set_no(s32 eno);
973 EXPORT char const *su_err_doc(s32 eno);
974 EXPORT char const *su_err_name(s32 eno);
975 EXPORT s32 su_err_from_name(char const *name);
976 EXPORT s32 su_err_no_via_errno(void);
977 INLINE enum su_log_level su_log_get_level(void){
978 return S(enum su_log_level,su__state & su__STATE_LOG_MASK);
980 INLINE void su_log_set_level(enum su_log_level nlvl){
981 uz lvl;
982 /*MT( su__glock(su__GLOCK_STATE); )*/
983 lvl = S(uz,nlvl) & su__STATE_LOG_MASK;
984 su__state = (su__state & su__STATE_GLOBAL_MASK) | lvl;
985 /*MT( su__gunlock(su__GLOCK_STATE); )*/
987 INLINE boole su_log_would_write(enum su_log_level lvl){
988 return ((S(u32,lvl) & su__LOG_MASK) <= (su__state & su__STATE_LOG_MASK) ||
989 (su__state & su__STATE_D_V));
991 EXPORT void su_log_write(BITENUM_IS(u32,su_log_level) lvl,
992 char const *fmt, ...);
993 EXPORT void su_log_vwrite(BITENUM_IS(u32,su_log_level) lvl,
994 char const *fmt, void *vp);
995 EXPORT void su_perr(char const *msg, s32 eno_or_0);
996 INLINE void su_log_lock(void){
997 MT( su__glock(su__GLOCK_LOG); )
999 INLINE void su_log_unlock(void){
1000 MT( su__gunlock(su__GLOCK_LOG); )
1002 #if !defined su_ASSERT_EXPAND_NOTHING || defined DOXYGEN
1003 EXPORT void su_assert(char const *expr, char const *file, u32 line,
1004 char const *fun, boole crash);
1005 #else
1006 # define su_assert(EXPR,FILE,LINE,FUN,CRASH)
1007 #endif
1008 #if DVLOR(1, 0)
1009 EXPORT void su_nyd_set_disabled(boole disabled);
1010 EXPORT void su_nyd_reset_level(u32 nlvl);
1011 EXPORT void su_nyd_chirp(u8 act, char const *file, u32 line, char const *fun);
1012 EXPORT void su_nyd_dump(void (*ptf)(up cookie, char const *buf, uz blen),
1013 up cookie);
1014 #endif
1015 /* BASIC C INTERFACE (SYMBOLS) }}} */
1016 C_DECL_END
1017 #include <su/code-ou.h>
1018 /* MORE DOXYGEN TOP GROUPS {{{ */
1019 /* MORE DOXYGEN TOP GROUPS }}} */
1020 #endif /* !su_CODE_H */
1021 /* s-it-mode */