@@@ mostly bench docs
[mLib] / utils / macros.h
CommitLineData
14d7100d 1/* -*-c-*-
16139d88 2 *
16139d88 3 * Handy macros
14d7100d 4 *
5 * (c) 2003 Straylight/Edgeware
6 */
7
d4efbcd9 8/*----- Licensing notice --------------------------------------------------*
14d7100d 9 *
10 * This file is part of the mLib utilities library.
11 *
12 * mLib is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Library General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
d4efbcd9 16 *
14d7100d 17 * mLib is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
d4efbcd9 21 *
14d7100d 22 * You should have received a copy of the GNU Library General Public
23 * License along with mLib; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 * MA 02111-1307, USA.
26 */
27
14d7100d 28#ifndef MLIB_MACROS_H
29#define MLIB_MACROS_H
30
31#ifdef __cplusplus
32 extern "C" {
33#endif
34
33e3ac90
MW
35/*----- Header files ------------------------------------------------------*/
36
f50c1365
MW
37#include <assert.h>
38
33e3ac90
MW
39#ifndef MLIB_COMPILER_H
40# include "compiler.h"
41#endif
42
3832000d 43/*----- Miscellaneous utility macros --------------------------------------*/
14d7100d 44
6e683a79
MW
45/* --- @N@ --- *
46 *
47 * Arguments: @type v[]@ = an actual array, not a pointer
48 *
49 * Returns: The number of elements in @v@.
50 */
51
c066b1ff 52#define N(v) (sizeof(v)/sizeof(*(v)))
14d7100d 53
6e683a79
MW
54/* --- @STR@ --- *
55 *
56 * Arguments: @x@ = some tokens
57 *
58 * Returns: A string literal containing the macro-expanded text of @x@.
59 */
60
16139d88 61#define MLIB__STR(x) #x
62#define STR(x) MLIB__STR(x)
63
289651a7 64/* --- @GLUE@, @GLUE3@ --- *
6e683a79
MW
65 *
66 * Arguments: @x, y@ = two sequences of tokens
289651a7 67 * @z@ = a third sequence of tokens
6e683a79
MW
68 *
69 * Returns: A single token formed by gluing together the macro-expansions
289651a7 70 * of @x@ and @y@, and @z@ for @GLUE3@.
6e683a79
MW
71 */
72
16139d88 73#define MLIB__GLUE(x, y) x##y
74#define GLUE(x, y) MLIB__GLUE(x, y)
289651a7 75#define GLUE3(x, y, z) GLUE(x, MLIB__GLUE(y, z))
16139d88 76
6e683a79
MW
77/* --- @STATIC_ASSERT@ --- *
78 *
79 * Arguments: @int cond@ = a condition
80 * @msg@ = a string literal message
81 *
82 * Returns: ---
83 *
84 * Use: Fail at compile time unless @cond@ is nonzero. The failure
85 * might report @msg@.
86 */
87
f50c1365 88#ifdef static_assert
dd65cf2d 89# define STATIC_ASSERT(cond, msg) static_assert(!!(cond), msg)
f50c1365
MW
90#else
91# define STATIC_ASSERT(cond, msg) \
b1a20bee 92 IGNORABLE extern char static_assert_failed[1 - 2*!(cond)]
f50c1365
MW
93#endif
94
b1a20bee
MW
95/* --- @CHECK_TYPE@ ---
96 *
97 * Arguments: @expty@ = expected type of @x@
98 * @expty x@ = some object
99 *
100 * Returns: Integer zero.
101 *
102 * Use: Cause a compile-time failure unless the type of @x@ is
103 * assignment-compatible with @expty@.
104 */
105
106#define CHECK_TYPE(expty, x) (!sizeof(*(expty *)0 = (x)))
107
108/* --- @CONVERT_CAREFULLY@ ---
109 *
110 * Arguments: @newty@ = new type for the result
111 * @expty@ = expected type of @x@
112 * @expty x@ = some object
113 *
114 * Returns: @x@, but coerced to type @newty@.
115 *
116 * Use: Like @(newty)x@, except that it checks at compile-time that
117 * @x@ is at least assignment-compatible with type @expty@
118 * before trying.
119 */
120
121#define CONVERT_CAREFULLY(newty, expty, x) \
122 (CHECK_TYPE(expty, x) + (/*unconst unvolatile*/ newty)(x))
123
124/* --- @UNCONST@, @UNVOLATILE@, @UNQUALIFY@ --- *
125 *
126 * Arguments: @type@ = a type name
127 * @type *p@ = a pointer
128 *
129 * Returns: @p@, but without @const@, @volatile@ or both qualifiers.
130 *
131 * Use: Strips qualifiers from pointer types.
132 *
133 * The @UNCONST@ macro strips @const@. It checks that @p@
134 * has type `pointer to @type@ or @const type@'; if not, a
135 * compile-time error results. Otherwise, it returns the value
136 * of @p@, converted to `pointer to (non-constant) @type@'. It
137 * will not silently strip a @volatile@ qualifier.
138 *
139 * The @UNVOLATILE@ macro is similar, except that it strips
140 * @volatile@ instead of @const@. The @UNQUALIFY@ macro strips
141 * both qualifiers.
142 */
143
144#define UNCONST(type, p) CONVERT_CAREFULLY(type *, const type *, p)
145#define UNVOLATILE(type, p) CONVERT_CAREFULLY(type *, volatile type *, p)
146#define UNQUALIFY(type, p) \
147 CONVERT_CAREFULLY(type *, const volatile type *, p)
148
289651a7
MW
149/* --- @EMPTY@ --- *
150 *
151 * Arguments: ---
152 *
153 * Returns: The empty token sequence.
154 */
155
156#define EMPTY
157
6e683a79
MW
158/* --- @COMMA@ --- *
159 *
160 * Arguments: ---
161 *
162 * Returns: A `%|,|%' token, which can be usefully passed to macros to
163 * avoid argument splitting.
164 */
165
e6591bec
MW
166#define COMMA ,
167
36188114
MW
168/*----- String and character hacks ----------------------------------------*/
169
6e683a79
MW
170/* --- @IS...@ --- *
171 *
172 * Arguments: @int ch@ = a character code, but not @EOF@
173 *
174 * Returns: Nonzero if @ch@ is in the relevant @<ctype.h>@ category.
175 *
176 * Use: Classifies characters, but safely even if characters are
177 * signed.
178 *
179 * There is a macro for each of the @<ctype.h>@ @is...@
180 * functions.
181 */
182
36188114
MW
183#define CTYPE_HACK(func, ch) (func((unsigned char)(ch)))
184
185#define ISALNUM(ch) CTYPE_HACK(isalnum, ch)
186#define ISALPHA(ch) CTYPE_HACK(isalpha, ch)
187#define ISASCII(ch) CTYPE_HACK(isascii, ch)
188#define ISBLANK(ch) CTYPE_HACK(isblank, ch)
189#define ISCNTRL(ch) CTYPE_HACK(iscntrl, ch)
190#define ISDIGIT(ch) CTYPE_HACK(isdigit, ch)
191#define ISGRAPH(ch) CTYPE_HACK(isgraph, ch)
192#define ISLOWER(ch) CTYPE_HACK(islower, ch)
193#define ISPRINT(ch) CTYPE_HACK(isprint, ch)
194#define ISPUNCT(ch) CTYPE_HACK(ispunct, ch)
195#define ISSPACE(ch) CTYPE_HACK(isspace, ch)
196#define ISUPPER(ch) CTYPE_HACK(isupper, ch)
197#define ISXDIGIT(ch) CTYPE_HACK(isxdigit, ch)
198
6e683a79
MW
199/* --- @TO...@ --- *
200 *
201 * Arguments: @int ch@ = a character code, but not @EOF@
202 *
203 * Returns: The converted character code.
204 *
205 * Use: Converts characters, but safely even if characters are
206 * signed.
207 *
208 * There is a macro for each of the @<ctype.h>@ @to...@
209 * functions.
210 */
211
36188114
MW
212#define TOASCII(ch) CTYPE_HACK(toascii, ch)
213#define TOLOWER(ch) CTYPE_HACK(tolower, ch)
214#define TOUPPER(ch) CTYPE_HACK(toupper, ch)
215
6e683a79
MW
216/* --- @MEMCMP@, @STRCMP@, @STRNCMP@ --- *
217 *
218 * Arguments: @const type *x, *y@ = pointers to strings
219 * @op@ = a relational operator symbol
220 * @size_t n@ = length of the strings
221 *
222 * Returns: Nonzero if the relationship between the strings satisfies the
223 * operator @op@, otherwise zero.
224 *
225 * Use: These macros mitigate the author's frequent error of failing
226 * to compare the result of the underlying standard functions
227 * against zero, effectively reversing the sense of an intended
228 * test for equality.
229 */
230
36188114
MW
231#define MEMCMP(x, op, y, n) (memcmp((x), (y), (n)) op 0)
232#define STRCMP(x, op, y) (strcmp((x), (y)) op 0)
233#define STRNCMP(x, op, y, n) (strncmp((x), (y), (n)) op 0)
234
6e683a79 235/*----- Compiler-specific definitions -------------------------------------*/
3832000d 236
6e683a79
MW
237/* The descriptions of these are given below, with the fallback
238 * definitions.
239 */
3832000d 240
ff3d3f01 241#if GCC_VERSION_P(2, 5) || CLANG_VERSION_P(3, 3)
2eea6973
MW
242# define NORETURN __attribute__((__noreturn__))
243# define PRINTF_LIKE(fix, aix) __attribute__((__format__(printf, fix, aix)))
244# define SCANF_LIKE(fix, aix) __attribute__((__format__(scanf, fix, aix)))
245# define IGNORABLE __attribute__((__unused__))
d94956b5
MW
246#endif
247
8c470f2a
MW
248#if GCC_VERSION_P(3, 4) || CLANG_VERSION_P(3, 3)
249# define MUST_CHECK __attribute__((__warn_unused_result__))
250#endif
251
ff3d3f01 252#if GCC_VERSION_P(4, 5) || CLANG_VERSION_P(3, 3)
2eea6973 253# define DEPRECATED(msg) __attribute__((__deprecated__(msg)))
d94956b5 254#elif GCC_VERSION_P(3, 1)
2eea6973 255# define DEPRECATED(msg) __attribute__((__deprecated__))
d94956b5
MW
256#endif
257
ff3d3f01 258#if GCC_VERSION_P(4, 0) || CLANG_VERSION_P(3, 3)
2eea6973 259# define EXECL_LIKE(ntrail) __attribute__((__sentinel__(ntrail)))
d94956b5
MW
260#endif
261
c91413e6 262#if GCC_VERSION_P(2, 7) || CLANG_VERSION_P(0, 0)
b64eb60f
MW
263# define LAUNDER(x) \
264 ({ __typeof__(x) _y; __asm__("" : "=g"(_y) : "0"(x)); _y; })
b1a20bee
MW
265# define ADMIRE(x) \
266 ({ __asm__("" : : "g"(x)); })
267# define ADMIRE_BUF(p, sz) \
268 ({ __asm__("" : : "g"(p), "g"(sz)); })
b64eb60f
MW
269# define RELAX do __asm__ __volatile__("" ::: "memory"); while (0)
270#endif
271
ff3d3f01
MW
272#if CLANG_VERSION_P(3, 3)
273
274# define MLIB__PRAGMA_HACK(x) _Pragma(#x)
275# define MLIB__MUFFLE_WARNINGS(warns, body) \
276 _Pragma("clang diagnostic push") \
277 warns \
278 body \
279 _Pragma("clang diagnostic pop")
280# define CLANG_WARNING(warn) \
281 MLIB__PRAGMA_HACK(clang diagnostic ignored warn)
282# define MUFFLE_WARNINGS_DECL(warns, body) \
283 MLIB__MUFFLE_WARNINGS(warns, body)
284# define MUFFLE_WARNINGS_EXPR(warns, body) \
285 __extension__ ({ MLIB__MUFFLE_WARNINGS(warns, (body);) })
286# define MUFFLE_WARNINGS_STMT(warns, body) \
287 do { MLIB__MUFFLE_WARNINGS(warns, body) } while (0)
288
c91413e6
MW
289#endif
290
291#if GCC_VERSION_P(4, 6)
d94956b5
MW
292
293 /* --- Diagnostic suppression in GCC: a tale of woe --- *
294 *
295 * This is extremely unpleasant, largely as a result of bugs in the GCC
296 * preprocessor's handling of @_Pragma@. The fundamental problem is
297 * that it's the preprocessor, and not the compiler proper, which
298 * detects @_Pragma@, emitting @#pragma@ lines into its output; and it
299 * does it during macro expansion, even if the macro is being expanded
300 * during argument collection. Since arguments are expanded before
301 * replacing the macro's invocation with its body, a pragma in an
302 * argument will be emitted %%\emph{before}%% any pragmata in the body,
303 * even if they appear before the argument in the body -- and even if
304 * the argument doesn't actually appear anywhere at all in the body.
305 *
306 * Another, rather less significant, problem is that @_Pragma@'s
307 * argument is a single string literal, recognized in translation phase
308 * 4, before string-literal concatenation in phase 6, so we must build
309 * pragma bodies as token lists and then stringify them.
310 *
311 * As a result, we need some subterfuge here. The @MLIB__PRAGMA_HACK@
312 * macro issues a @_Pragma@ on its argument token list, which it
313 * stringifies; this deals with the second problem. The first is
314 * trickier: we must delay expansion of @MLIB__PRAGMA_HACK@ from the
315 * argument collection phase to the body rescanning phase, and we do
316 * this by splitting the invocations between @GCC_WARNING@ macro calls:
317 * the name is left hanging from the previous call (or from
318 * @MLIB__MUFFLE_WARNINGS@, in the first case) and the body is supplied
319 * by @GCC_WARNING@, which also supplies the next @MLIB__PRAGMA_HACK@.
320 * The remaining problem is to make sure we can dispose of the final
321 * trailing @MLIB__PRAGMA_HACK@ harmlessly, which we do by introducing
322 * an extra argument @emitp@, which may be either @t@ or @nil@; this
323 * dispatches to an appropriate helper macro by means of token-pasting.
324 *
325 * I'm so sorry.
326 */
327
328# define MLIB__PRAGMA_HACK_t(x) _Pragma(#x)
329# define MLIB__PRAGMA_HACK_nil(x)
330# define MLIB__PRAGMA_HACK(emitp, x) MLIB__PRAGMA_HACK_##emitp(x)
331# define MLIB__MUFFLE_WARNINGS(warns, body) \
3832000d
MW
332 _Pragma("GCC diagnostic push") MLIB__PRAGMA_HACK \
333 warns \
334 (nil, nil) \
335 body \
336 _Pragma("GCC diagnostic pop")
d94956b5 337# define GCC_WARNING(warn) \
3832000d 338 (t, GCC diagnostic ignored warn) MLIB__PRAGMA_HACK
d94956b5 339# define MUFFLE_WARNINGS_DECL(warns, body) \
3832000d 340 MLIB__MUFFLE_WARNINGS(warns, body)
d94956b5 341# define MUFFLE_WARNINGS_EXPR(warns, body) \
3832000d 342 __extension__ ({ MLIB__MUFFLE_WARNINGS(warns, (body);) })
d94956b5 343# define MUFFLE_WARNINGS_STMT(warns, body) \
3832000d 344 do { MLIB__MUFFLE_WARNINGS(warns, body) } while (0)
3832000d
MW
345#endif
346
347/* --- Fallback definitions, mostly trivial --- */
348
6e683a79
MW
349/* --- @DISCARD@ --- *
350 *
351 * Arguments: @x@ = a function call
352 *
353 * Returns: ---
354 *
355 * Use: Explicitly discard the result of @x@. This counteracts a
356 * @MUST_CHECK@ attribute on the called function.
357 */
3832000d
MW
358
359#ifndef DISCARD
360# define DISCARD(x) do if (x); while (0)
361#endif
362
6e683a79
MW
363/* --- @IGNORE@ --- *
364 *
365 * Arguments: @x@ = any expression
366 *
367 * Returns: ---
368 *
369 * Use: Ignore the value of @x@, overriding compiler warnings.
370 */
371
3832000d
MW
372#ifndef IGNORE
373# define IGNORE(x) ((void)(x))
374#endif
375
6e683a79
MW
376/* --- @LAUNDER@ --- *
377 *
378 * Arguments: @x@ = some integer expression
379 *
380 * Returns: @x@.
381 *
382 * Use: Causes a compiler to know nothing about the value of @x@,
383 * even if it looks obvious, e.g., it's a constant.
384 */
3832000d 385
6e683a79
MW
386#ifndef LAUNDER
387# define LAUNDER(x) (x)
3832000d
MW
388#endif
389
b1a20bee
MW
390/* --- @ADMIRE@, @ADMIRE_BUF@ --- *
391 *
392 * Arguments: @x@ = some scalar expression
393 * @const void *p@, @size_t sz@ = a pointer and length
394 *
395 * Returns: ---
396 *
397 * Use: Ensures that the compiler generates code to compute @x@ or
398 * the contents of the buffer at @p@.
399 */
400
401#ifndef ADMIRE
402# define ADMIRE(x) ((void)(x))
403#endif
404#ifndef ADMIRE_BUF
405# define ADMIRE_BUF(p, sz) ((void)(p), (void)(sz))
406#endif
407
6e683a79
MW
408/* --- @RELAX@ --- *
409 *
410 * Arguments: ---
411 *
412 * Returns: ---
413 *
414 * Use: Does nothing, but the compiler doesn't know that.
415 */
3832000d 416
6e683a79
MW
417#ifndef RELAX
418# define RELAX
3832000d
MW
419#endif
420
6e683a79
MW
421/* --- @DEPRECATED@, @NORETURN@, @IGNORABLE@, @MUST_CHECK@ --- *
422 *
423 * Use: These are (mostly) function attributes; write them among the
424 * declaration specifiers for a function definition or
425 * declaration. These may not do anything, but the intended
426 * behaviour is as follows.
427 *
428 * * @DEPRECATED(msg)@ -- report a warning, quoting the string
429 * literal @msg@, if the function is called.
430 *
431 * * @NORETURN@ -- promise that the function doesn't return to
432 * its caller: either it kills the process, or it performs
433 * some nonlocal transfer.
434 *
435 * * @IGNORABLE@ -- the item (which might be data rather than
436 * a function) might not be referred to, but that's OK:
437 * don't warn about it.
438 *
439 * @ @MUST_CHECK@ -- warn if the return value of a function is
440 * ignored. Use @DISCARD@ if you really don't care.
441 */
442
443#ifndef DEPRECATED
444# define DEPRECATED(msg)
3832000d
MW
445#endif
446
59eae7fd
MW
447#ifndef NORETURN
448# define NORETURN
449#endif
450
3832000d
MW
451#ifndef IGNORABLE
452# define IGNORABLE
453#endif
454
8c470f2a
MW
455#ifndef MUST_CHECK
456# define MUST_CHECK
457#endif
458
6e683a79
MW
459/* --- @PRINTF_LIKE@, @SCANF_LIKE@, @EXECL_LIKE@ --- *
460 *
461 * Arguments: @int fmtix@ = format string argument index (starting from 1)
462 * @int argix@ = variable format argument tail index (starting
463 * from 1)
464 * @int ntrail@ = number of arguments following terminator
465 *
466 * Use: These are function attributes. Again, they might not do
467 * anything at all. By intention, they give the compiler
468 * information about a variadic function's arguments, so that it
469 * can warn about misuse.
470 *
471 * * @PRINTF_LIKE@ -- the function takes a @printf@-style
472 * format string as argument @fmtix@ and an argument tail
473 * (which may be empty) beginning with argument @argix@.
474 *
475 * * @SCANF_LIKE@ -- the function takes a @scanf@-style
476 * format string as argument @fmtix@ and an argument tail
477 * (which may be empty) beginning with argument @argix@.
478 *
479 * * @EXECL_LIKE@ -- the function takes a sequence of pointer
480 * arguments terminated by a null pointer, followed by
481 * @ntrail@ further arguments.
482 */
483
484#ifndef PRINTF_LIKE
485# define PRINF_LIKE(fmtix, argix)
b64eb60f
MW
486#endif
487
6e683a79
MW
488#ifndef SCANF_LIKE
489# define SCANF_LIKE(fmtix, argix)
b64eb60f
MW
490#endif
491
6e683a79
MW
492#ifndef EXECL_LIKE
493# define EXECL_LIKE(ntrail)
494#endif
495
496/* --- @MUFFLE_WARNINGS_...@ --- *
497 *
498 * Arguments: @warns@ = a sequence of @..._WARNING@ calls (see below)
499 * @body@ = some program text
500 *
501 * Use: Muffle specific warnings within the program text.
502 *
503 * For @MUFFLE_WARNINGS_DECL@, the program text is a
504 * declaration; for @MUFFLE_WARNINGS_EXPR@, it is an expression,
505 * and for @MUFFLE_WARNINGS_STMT@, it is a statement.
506 *
507 * The warnings to be muffled are given as a list of
508 * @..._WARNING@ macros, with no separators. The list can
509 * list warnings from multiple different compilers: entries for
510 * irrelevant compilers will be ignored.
511 */
512
513#ifndef MUFFLE_WARNINGS_DECL
514# define MUFFLE_WARNINGS_DECL(warns, body) body
515#endif
516
517#ifndef MUFFLE_WARNINGS_EXPR
518# define MUFFLE_WARNINGS_EXPR(warns, body) (body)
519#endif
520
521#ifndef MUFFLE_WARNINGS_STMT
522# define MUFFLE_WARNINGS_STMT(warns, body) do { body } while (0)
523#endif
524
525/* --- @GCC_WARNING@ --- *
526 *
527 * Arguments: @warn@ = a string literal naming a warning, with `%|-W...|%'
528 * prefix
529 *
530 * Use: Names a GCC warning: use within @MUFFLE_WARNINGS_...@.
531 *
532 * Note that GCC's warning suppression is very buggy.
533 */
534
3832000d
MW
535#ifndef GCC_WARNING
536# define GCC_WARNING(warn)
537#endif
538
6e683a79
MW
539/* --- @CLANG_WARNING@ --- *
540 *
541 * Arguments: @warn@ = a string literal naming a warning, with `%|-W...|%'
542 * prefix
543 *
544 * Use: Names a Clang warning: use within @MUFFLE_WARNINGS_...@.
545 */
546
ff3d3f01
MW
547#ifndef CLANG_WARNING
548# define CLANG_WARNING(warn)
549#endif
550
14d7100d 551/*----- That's all, folks -------------------------------------------------*/
552
553#ifdef __cplusplus
554 }
555#endif
556
557#endif