1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
|
#ifndef C23_FALLBACK_H
#define C23_FALLBACK_H
/** @file
** @brief A header file to augment compatibility of older compilers with C23.
**
** This has only been tested with the open source compilers
**
** - gcc
** - clang
**
** and the C libraries
**
** - glibc
** - musl
**
** The newer the version of these compilers or C libraries you can
** get, the better. If you use another compiler or C library and have
** adjustments to make to this file, please share. I will try to
** include such changes in the future.
**
** Commonly supported C23 features that are required are
** - digit separators such as in `0xAB'CD`
** - binary integer literals such as `0b1010` or `0B0101`
** - the new attribute syntax such as `[[deprecated]]`
**
** The first two are not easy to circumvent, so probably you should
** not even try to use C23 enabled code without having support for
** them.
**
** For the attribute syntax there is a feature test
** __has_c_attribute. It can be used with define (or #ifdef) to test
** for the syntax itself and with #if and an argument to test for an
** individual attribute, see below.
**
** Another feature test is __has_include, which similarly can be used
** to test for the preprocessor feature itself and if that is
** available to test for the availability of a specific header. This
** can be used to
**
** - test for optional headers such as <complex.h>, <threads.h>, or
** <stdatomic.h>. This now allows to use the corresponding feature
** test macro (__STDC_NO_COMPLEX__, __STDC_NO_ATOMICS__,
** __STDC_NO_THREADS__) to test for compiler support of these
** features, separately from the availability of library
** interfaces.
**
** - test for new headers that come with C23, namely <stdckdint.h>
** and <stdbit.h>. Even if your C library does not support these,
** their functionality should mostly be available through
** type-generic macros that we emulate. Prefer them over function
** symbols, those may depend on linker symbols that are not yet
** available.
**
** This header here unconditionally includes a bunch of C library
** headers (see below) and augments them with C23 features if
** possible. You should not include them yourself, such that we are
** sure in what we get. This also concerns the new C23 header
** <stdckdint.h>.
**
** Other headers also may be included conditionally, namely
** <threads.h> and <stdatomic.h>.
**
** When emulating the new features, there may be spurious warnings
** that some attributes are misplaced or ignored. This obviously
** means that they are not completely taken into account and that the
** analysis they are expected to provide is not yet fully implemented
** by your compiler. If you are flooded by these, you might switch
** some of the diagnostics off by defining the macro
** `C23_FALLBACK_SILENT` for example by providing the command line
** argument `-DC23_FALLBACK_SILENT`.
**
** But note also, that some errors that are found are actually real
** errors. These are meant as bad code examples and also as tests if
** compilers are able to detect these kind of things. If you stumble
** into these, there should be a code comment close by that explains
** the particular example. Compilers vary widely in what they are
** able to detect, so here the more you see, the better.
**
** And then, ..., there are the bugs. Currently, the code triggers
** one particular bug of gcc-13 in `endianness.c`.
**
** As of March 2024, gcc-14 and clang-18 work with most of the new
** C23 features. Current restrictions are
**
** - clang-18: `constexpr` is not yet implemented
** - both: `#embed` is not yet implemented
**
** As indicated above, some short comings of your C library
** implementation can be worked around, but unfortunately not all. As
** of this writing
**
** - glibc: `printf` and `scanf` support only includes the new %b
** specifier for binary representation, but not the %w length
** modifiers.
**
** - musl: in the current distribution there is no support for C23
** features, so in particular `printf` etc will not work with the
** new formats, yet.
**
** We are currently working to have patches included to musl whence
** the new edition of Modern C and the new standard appear. In the
** mean time I will try to post a patch set and build recipe such
** that you may easily build such modified version of musl with
** complete C23 support on your own. Stay tuned.
**/
#include <limits.h>
/* Needed for musl */
/* #ifdef __has_include */
/* # if __has_include(<stdc-predef.h>) */
/* # include <stdc-predef.h> */
/* # endif */
/* #endif */
#if (__STDC_UTF_16__ != 1) || (__STDC_UTF_32__ != 1)
# ifndef C23_FALLBACK_SILENT
# warning "C23 imposes that char16_t and char32_t use UTF-16 and UTF-32 encodings"
# endif
#endif
/**
** @brief A preprocessor test for the `__VA_OPT__` feature.
**
** Compilers before C23 might not implement `__VA_OPT__`.
** @return This macro should always evaluate to `0` or `1`.
**/
#define __has_va_opt C23_HAS_VA_OPT_I(C23)
#define C23_HAS_VA_OPT_I(...) \
C23_HAS_VA_OPT_IIplus(__VA_OPT__(,) 1, 0,)
#define C23_HAS_VA_OPT_IIplus(_0, _1, ...) _1
#if !__has_va_opt
# ifndef C23_FALLBACK_SILENT
# warning "no support of C23 __VA_OPT__ found"
# endif
#endif
#ifndef BITINT_MAXWIDTH
# ifdef __BITINT_MAXWIDTH__
# define BITINT_MAXWIDTH __BITINT_MAXWIDTH__
# else
# ifndef C23_FALLBACK_SILENT
# warning "no support for _BitInt types found"
# endif
# endif
#endif
/* A simple type-generic conditional. */
#define GENERIC_IF(COND, A, B) \
_Generic((char(*)[1+!!(COND)])0, \
char(*)[2]: (A), \
default: (B))
/* clang has a set of feature tests that are quite comfortable,
__has_feature, to test if a specific feature is implemented
__has_extension, to test if a specific feature is implemented
__is_identifier, to test if a word is an identifier or a keyword.
In the following we construct similar tests for gcc such that we
may use these features independently from the C standard version
that is supported. */
# define __tester2(_0, _1, ...) _1
# define __tester1(...) __tester2(__VA_ARGS__)
#ifndef __has_feature
# define __has_feature(X) __tester1(__has_feature_ ## X 1, 0, )
#endif
#ifndef __has_extension
# define __has_extension(X) __tester1(__has_extension_ ## X 1, 0, )
#endif
#ifndef __is_identifier
# define __is_identifier(X) __tester1(__is_special_ ## X 0, 1, )
# define __is_special_auto ,
# define __is_special_break ,
# define __is_special_case ,
# define __is_special_char ,
# define __is_special_const ,
# define __is_special_continue ,
# define __is_special_default ,
# define __is_special_do ,
# define __is_special_double ,
# define __is_special_else ,
# define __is_special_enum ,
# define __is_special_extern ,
# define __is_special_float ,
# define __is_special_for ,
# define __is_special_goto ,
# define __is_special_if ,
# define __is_special_inline ,
# define __is_special_int ,
# define __is_special_long ,
# define __is_special_register ,
# define __is_special_restrict ,
# define __is_special_return ,
# define __is_special_short ,
# define __is_special_signed ,
# define __is_special_sizeof ,
# define __is_special_static ,
# define __is_special_struct ,
# define __is_special_switch ,
# define __is_special_typedef ,
# define __is_special_union ,
# define __is_special_unsigned ,
# define __is_special_void ,
# define __is_special_volatile ,
# define __is_special_while ,
# define __is_special__Atomic ,
# define __is_special__Complex ,
# define __is_special__Decimal128 ,
# define __is_special__Decimal32 ,
# define __is_special__Decimal64 ,
# define __is_special__Generic ,
# define __is_special__Imaginary ,
# define __is_special__Noreturn ,
# if __GNUC__ > 12 || __STDC_VERSION__ >= 202311L
# define __is_special_nullptr ,
# define __is_special_static_assert ,
# define __is_special_thread_local ,
# define __is_special_constexpr ,
# define __is_special_typeof ,
# define __is_special_typeof_unqual ,
# endif
# if __GNUC__ > 13 || __STDC_VERSION__ >= 202311L
# define __is_special__BitInt ,
# define __is_special_alignas ,
# define __is_special_alignof ,
# define __is_special_bool ,
# define __is_special_false ,
# define __is_special_true ,
# endif
#endif
#if __GNUC__ > 12 || __STDC_VERSION__ >= 202311L
# define __has_feature_c_fixed_enum ,
#endif
// The feature for fixed underlying types for enums has been so long
// in clang, that they don't even seem to have a feature test for it.
#if !__has_feature(c_fixed_enum) && defined(__clang_major__) && (__clang_major__ < 8)
# ifndef C23_FALLBACK_SILENT
# warning "syntax for fixed underlying integer type of enumerations is not supported"
# endif
#endif
#if __is_identifier(constexpr)
# ifndef C23_FALLBACK_SILENT
# warning "constexpr keyword is not supported, emulating as static const"
# endif
# define constexpr static const
#endif
#if __is_identifier(bool)
# ifndef C23_FALLBACK_SILENT
# warning "bool keyword is not supported, emulating as macro"
# endif
# define bool _Bool
#endif
#if __is_identifier(false)
# ifndef C23_FALLBACK_SILENT
# warning "false keyword is not supported, emulating as macro"
# endif
# undef false
# define false ((bool)+0U)
#endif
#if __is_identifier(true)
# ifndef C23_FALLBACK_SILENT
# warning "true keyword is not supported, emulating as macro"
# endif
# undef true
# define true ((bool)+1U)
#endif
#if __is_identifier(thread_local)
// Maybe this is also provided by the C library implementation, but a
// redefinition makes no harm.
#define thread_local _Thread_local
#endif
#if __is_identifier(alignof)
#undef alignof
#define alignof _Alignof
#endif
#if __is_identifier(alignas)
#undef alignas
#define alignas _Alignas
#endif
#if __is_identifier(static_assert)
#undef static_assert
#define static_assert(...) __static_assert(__VA_ARGS__,)
#define __static_assert(E, ...) _Static_assert(E)
#endif
#if __is_identifier(typeof)
# if __GNUC__
# undef typeof
# define typeof __typeof__
# else
# warning "typeof operator only comes with C23"
# endif
#endif
#if __STDC_VERSION__ < 202311L
# if __GNUC__
# if __GNUC__ < 13
# define auto __auto_type
# endif
# else
# warning "auto type inference only comes with C23"
# endif
#endif
#ifndef __has_c_attribute
# define __has_c_attribute(X) 0
#endif
// C23 has nullptr, use a fallback if that is not available. Here we
// use an enumeration type and constant to do that. The idea is that
// such an enumeration may then be used in _Generic as long the cases
// otherwise only have pointer types. The first choice is to use a
// _BitInt type for that, if that is already available, in an effort
// to not clash with standard integer types. If that is not found, we
// use a standard integer type that has the right width.
//
// If possible, we also use an attribute that forces warnings if any
// other value than a null or 0 is assigned to a variable of type
// nullptr_t.
#if !__is_identifier(nullptr)
// Maybe this is also provided by the C library implementation, but a
// redefinition makes no harm.
typedef typeof(nullptr) nullptr_t;
#elif (__STC_VERSION__ < 202311L)
# ifdef BITINT_MAXWIDTH
# ifndef C23_FALLBACK_SILENT
# warning "using fallback for nullptr to enumeration constant based on _BitInt type"
# else
# pragma GCC diagnostic ignored "-Wnon-literal-null-conversion"
# endif
enum
# if __has_c_attribute(clang::enum_extensibility)
[[__clang__::__enum_extensibility__(closed)]]
# endif
nullptr_t :
__typeof__((unsigned _BitInt(sizeof(void*)*CHAR_BIT))0)
{
nullptr,
};
# else
# ifndef C23_FALLBACK_SILENT
# warning "using fallback for nullptr to enumeration constant based on standard integer type"
# endif
enum
# if __has_c_attribute(clang::enum_extensibility)
[[__clang__::__enum_extensibility__(closed)]]
# endif
nullptr_t {
nullptr,
__nullptr_max =
GENERIC_IF((sizeof(void*)==sizeof(int)),
-1U,
GENERIC_IF((sizeof(void*)==sizeof(long)),
-1UL,
-1ULL)),
};
// Unfortunately such an enumeration type is not yet good enough for
// all compilers. In particular some gcc version has nullptr and
// __nullptr_max as different types. Force an expression that is an
// ICE of value 0 and of the enumeration type.
# define nullptr (1 ? nullptr : __nullptr_max)
# endif
#endif
typedef typeof(nullptr) nullptr_t;
static_assert(_Generic(nullptr, nullptr_t: true));
static_assert(sizeof(void*)==sizeof(nullptr));
static_assert(sizeof(void*)==sizeof(nullptr_t));
/**********************************************************************************************/
#include <inttypes.h>
#include <setjmp.h>
#include <signal.h>
#include <stdalign.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <wchar.h>
/**********************************************************************************************/
// for call_once
#ifndef ONCE_FLAG_INIT
# ifdef __has_include
# if __has_include(<threads.h>)
# ifndef C23_FALLBACK_SILENT
# warning "including call_once function from <threads.h> instead of <stdlib.h>"
# endif
# include <threads.h>
# endif
# endif
#endif
// If call_once has not been found we construct a function that is
// based on atomics.
#ifndef ONCE_FLAG_INIT
# ifdef __has_include
# if __has_include(<stdatomic.h>)
# include <stdatomic.h>
# ifndef C23_FALLBACK_SILENT
# warning "emulating call_once function by using atomics"
# endif
enum { once_initial, once_inter, once_final, };
# define ONCE_FLAG_INIT once_initial
typedef _Atomic(unsigned) once_flag;
# if __has_c_attribute(__gnu__::__noinline__)
[[__gnu__::__noinline__]]
# endif
static inline
void call_once(once_flag* flag, void callback(void)) {
if (*flag != once_final) {
unsigned expected = once_initial;
if (atomic_compare_exchange_strong(flag, &expected, once_inter)) {
callback();
*flag = once_final;
} else {
while (*flag != once_final) {
//
}
}
} else {
// We know already that the implementation does not support threads,
// so the only available fence is this:
atomic_signal_fence(memory_order_seq_cst);
}
}
# endif
# endif
#endif
/**********************************************************************************************/
// We assume that the compiler is already able to handle the new
// attribute syntax such as [[deprecated]]. Nevertheless, maybe
// certain attributes themselves might not yet be implemented. We
// provide fallback macros to corresponding gnu attributes. Here we
// use the "safe" names for these features with double underscores, so
// they don't interfere with application names.
#if !__has_c_attribute(__unsequenced__)
# ifndef C23_FALLBACK_SILENT
# warning "unsequenced attribute not yet implemented"
# endif
# define __unsequenced__
# if __has_c_attribute(__gnu__::__const__)
# ifndef C23_FALLBACK_SILENT
# warning "unsequenced attribute could be emulated via gnu attribute by using c23_unsequenced"
# endif
# define c23_unsequenced __attribute__((__const__))
# endif
#endif
#if !__has_c_attribute(__reproducible__)
# ifndef C23_FALLBACK_SILENT
# warning "reproducible attribute not yet implemented"
# endif
# define __reproducible__
# if __has_c_attribute(__gnu__::__pure__)
# ifndef C23_FALLBACK_SILENT
# warning "reproducible attribute could be emulated via gnu attribute by using c23_reproducible"
# endif
# define c23_reproducible __attribute__((__pure__))
# endif
#endif
#if !__has_c_attribute(__deprecated__) && __has_c_attribute(__gnu__::__deprecated__)
# ifndef C23_FALLBACK_SILENT
# warning "emulating deprecated attribute via gnu attribute"
# endif
# define __deprecated__ __gnu__::__deprecated__
#endif
#if !__has_c_attribute(__nodiscard__) && __has_c_attribute(__gnu__::__warn_unused_result__)
# ifndef C23_FALLBACK_SILENT
# warning "emulating nodiscard attribute via gnu attribute"
# endif
# define __nodiscard__ __gnu__::__warn_unused_result__
#endif
#if !__has_c_attribute(__maybe_unused__) && __has_c_attribute(__gnu__::__unused__)
# ifndef C23_FALLBACK_SILENT
# warning "emulating maybe_unused attribute via gnu attribute"
# endif
# define __maybe_unused__ __gnu__::__unused__
#endif
#if !__has_c_attribute(noreturn) && __has_c_attribute(__gnu__::__noreturn__)
# ifndef C23_FALLBACK_SILENT
# warning "emulating noreturn attribute via gnu attribute"
# endif
# define noreturn __gnu__::__noreturn__
#endif
#if !__has_c_attribute(__fallthrough__) && __has_c_attribute(__gnu__::__fallthrough__)
# warning "emulating fallthrough attribute via gnu attribute"
# define __fallthrough__ __gnu__::__fallthrough__
#endif
#if __has_c_attribute(__deprecated__) || defined(__deprecated__)
// Deprecate two interfaces in <time.h>
[[__deprecated__]] char *asctime(const struct tm*);
[[__deprecated__]] char *ctime(const time_t*);
#endif
// Gnu compilers have a malloc attribute that comes in two different
// forms. Without argument it just certifies that a function returns a
// pointer value that has not been seen before, and thus the pointer
// target will not alias with anything known. The second form receives
// one or two arguments and specifies a function that should be used
// analogous to free. Unfortunately, clang didn't follow that second
// development, yet. But we suppose that there will be at least a
// partial solution in clang-18 final.
#if __has_c_attribute(__gnu__::__malloc__) && !(defined(__clang_major__) && __clang_major__ <= 19)
# define __gnu_free__(...) __gnu__::__malloc__(__VA_ARGS__)
#else
# define __gnu_free__(...)
#endif
/**********************************************************************************************/
/* C23 allows to omit the second argument of va_start */
#if __STDC_VERSION_STDARG_H__ < 202311L
#undef va_start
#define va_start(...) __va_start1(__VA_ARGS__ , 0, )
#define __va_start1(...) __va_start2(__VA_ARGS__)
#define __va_start2(v, l, ...) __builtin_va_start(v, l)
#endif
/**********************************************************************************************/
/* C23 has three new tg interfaces in the new <stdkdint.h> header.
They are modeled after similar gcc features. They are meant to do
arithmetic with overflow check by using everything the compiler can
get from instruction flags that already exist on most CPU.
*/
#ifdef __has_include
# if __has_include(<stdckdint.h>)
# include <stdckdint.h>
# endif
#endif
/* If we don't have the header, yet, we may easily emulate it if we
are on a compiler claiming compatibility with gcc. */
#ifndef ckd_add
# ifdef __GNUC__
# ifndef C23_FALLBACK_SILENT
# warning "emulating stdckdint.h interfaces via gnu builtins"
# endif
# define ckd_add(R, A, B) __builtin_add_overflow ((A), (B), (R))
# define ckd_sub(R, A, B) __builtin_sub_overflow ((A), (B), (R))
# define ckd_mul(R, A, B) __builtin_mul_overflow ((A), (B), (R))
# else
# warning "checked integer arithmetic as of C23 is not yet implemented"
# endif
#endif
/**********************************************************************************************/
// C23 has the unreachable macro in <stdlib.h>, use a fallback if that
// is not available
#ifndef unreachable
# ifndef C23_FALLBACK_SILENT
# warning "using fallback for unreachable macro"
# endif
# define unreachable() __builtin_unreachable()
#endif
/**********************************************************************************************/
// C23 provides macros for the width of integer types. Provide a
// fallback if they are not available
#ifndef BOOL_WIDTH
# define BOOL_WIDTH 1
#endif
#ifndef CHAR_WIDTH
# define CHAR_WIDTH CHAR_BIT
#endif
#ifndef UCHAR_WIDTH
# define UCHAR_WIDTH CHAR_BIT
#endif
#ifndef SCHAR_WIDTH
# define SCHAR_WIDTH CHAR_BIT
#endif
#ifndef USHRT_WIDTH
# if USHRT_MAX <= 0xFFFFU
# define USHRT_WIDTH 16
# define SHRT_WIDTH 16
# else
# if USHRT_MAX <= 0xFFFFFFFFU
# define USHRT_WIDTH 32
# define SHRT_WIDTH 32
# else
# if USHRT_MAX <= 0xFFFFFFFFFFFFFFFFU
# define USHRT_WIDTH 64
# define SHRT_WIDTH 64
# else
// This doesn't use #elif but nested #if/#else because the value might
// be too large for the preprocessor
# if USHRT_MAX <= 0xFFFFFFFFFFFFFFFFFFFFFFFFU
# define USHRT_WIDTH 96
# define SHRT_WIDTH 96
# else
// This doesn't use #elif but nested #if/#else because the value might
// be too large for the preprocessor
# if USHRT_MAX <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFU
# define USHRT_WIDTH 128
# define SHRT_WIDTH 128
# endif
# endif
# endif
# endif
# endif
#endif
// unsigned int has a width of at least 16.
#ifndef UINT_WIDTH
# if UINT_MAX <= 0xFFFFU
# define UINT_WIDTH 16
# define INT_WIDTH 16
# else
# if UINT_MAX <= 0xFFFFFFFFU
# define UINT_WIDTH 32
# define INT_WIDTH 32
# else
# if UINT_MAX <= 0xFFFFFFFFFFFFFFFFU
# define UINT_WIDTH 64
# define INT_WIDTH 64
# else
// This doesn't use #elif but nested #if/#else because the value might
// be too large for the preprocessor
# if UINT_MAX <= 0xFFFFFFFFFFFFFFFFFFFFFFFFU
# define UINT_WIDTH 96
# define INT_WIDTH 96
# else
// This doesn't use #elif but nested #if/#else because the value might
// be too large for the preprocessor
# if UINT_MAX <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFU
# define UINT_WIDTH 128
# define INT_WIDTH 128
# endif
# endif
# endif
# endif
# endif
#endif
// size_t has a width of at least 16.
#ifndef SIZE_WIDTH
# if SIZE_MAX <= 0xFFFFU
# define SIZE_WIDTH 16
# else
# if SIZE_MAX <= 0xFFFFFFFFU
# define SIZE_WIDTH 32
# else
# if SIZE_MAX <= 0xFFFFFFFFFFFFFFFFU
# define SIZE_WIDTH 64
# else
// This doesn't use #elif but nested #if/#else because the value might
// be too large for the preprocessor
# if SIZE_MAX <= 0xFFFFFFFFFFFFFFFFFFFFFFFFU
# define SIZE_WIDTH 96
# else
// This doesn't use #elif but nested #if/#else because the value might
// be too large for the preprocessor
# if SIZE_MAX <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFU
# define SIZE_WIDTH 128
# endif
# endif
# endif
# endif
# endif
#endif
// unsigned long has a width of at least 32
#ifndef ULONG_WIDTH
# if ULONG_MAX <= 0xFFFFFFFFUL
# define ULONG_WIDTH 32
# define LONG_WIDTH 32
# else
# if ULONG_MAX <= 0xFFFFFFFFFFFFFFFFUL
# define ULONG_WIDTH 64
# define LONG_WIDTH 64
# else
// This doesn't use #elif but nested #if/#else because the value might
// be too large for the preprocessor
# if ULONG_MAX <= 0xFFFFFFFFFFFFFFFFFFFFFFFFUL
# define ULONG_WIDTH 96
# define LONG_WIDTH 96
# else
// This doesn't use #elif but nested #if/#else because the value might
// be too large for the preprocessor
# if ULONG_MAX <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFUL
# define ULONG_WIDTH 128
# define LONG_WIDTH 128
# endif
# endif
# endif
# endif
#endif
// unsigned long long has a width of at least 64.
#ifndef ULLONG_WIDTH
# if ULLONG_MAX <= 0xFFFFFFFFFFFFFFFFULL
# define ULLONG_WIDTH 64
# define LLONG_WIDTH 64
# else
// This doesn't use #elif but nested #if/#else because the value might
// be too large for the preprocessor
# if ULLONG_MAX <= 0xFFFFFFFFFFFFFFFFFFFFFFFFULL
# define ULLONG_WIDTH 96
# define LLONG_WIDTH 96
# else
// This doesn't use #elif but nested #if/#else because the value might
// be too large for the preprocessor
# if ULLONG_MAX <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFULL
# define ULLONG_WIDTH 128
# define LLONG_WIDTH 128
# endif
# endif
# endif
#endif
// In most cases the [u]intmax_t types will just be the long long
// types.
#ifndef UINTMAX_WIDTH
# if UINTMAX_MAX == ULLONG_MAX
# define UINTMAX_WIDTH ULLONG_WIDTH
# define INTMAX_WIDTH LLONG_WIDTH
# endif
#endif
#ifndef UINT128_MAX
# ifdef __SIZEOF_INT128__
# if defined(__clang_major__) && (__clang_major__ < 18)
# ifndef C23_FALLBACK_SILENT
# warning "not using compiler intrinsic for int128_t, please upgrade to clang version ≥ 18"
# endif
# else
# define __has_int128
# endif
# endif
#endif
#ifndef UINT256_MAX
# ifdef __SIZEOF_INT256__
# if defined(__clang_major__) && (__clang_major__ < 18)
# ifndef C23_FALLBACK_SILENT
# warning "not using compiler intrinsic for int256_t, please upgrade to clang version ≥ 18"
# endif
# else
# define __has_int256
# endif
# endif
#endif
// In C23 uint128_t may exist, even if it is wider than
// uintmax_t. Provide it if the compiler supports it.
#ifndef UINT128_MAX
# ifdef __has_int128
typedef signed __int128 int128_t;
typedef unsigned __int128 uint128_t;
# define UINT128_WIDTH 128
# define INT128_WIDTH 128
# define UINT128_MAX ((uint128_t)-1)
# define INT128_MAX ((int128_t)(((uint128_t)-1)>>1))
# define INT128_MIN (-INT128_MAX-1)
# if BITINT_MAXWIDTH >= 128
# define UINT128_C(X) ((uint128_t)+(X ## wbu))
# define INT128_C(X) ((int128_t)+(X ## wb))
# endif
# endif
#endif
// In C23 uint256_t may exist, even if it is wider than
// uintmax_t. Provide it if the compiler supports it.
#ifndef UINT256_MAX
# ifdef __has_int256
typedef signed __int256 int256_t;
typedef unsigned __int256 uint256_t;
# define UINT256_WIDTH 256
# define INT256_WIDTH 256
# define UINT256_MAX ((uint256_t)-1)
# define INT256_MAX ((int256_t)(((uint256_t)-1)>>1))
# define INT256_MIN (-INT256_MAX-1)
# if BITINT_MAXWIDTH >= 256
# define UINT256_C(X) ((uint256_t)+(X ## wbu))
# define INT256_C(X) ((int256_t)+(X ## wb))
# endif
# endif
#endif
/**********************************************************************************************/
#if __STDC_VERSION_INTTYPES_H__ < 202311L
# ifndef C23_FALLBACK_SILENT
# warning "native C23 library support for %b printf or scanf formats may be missing"
# endif
# ifndef PRIb32
# if __GLIBC__ > 1 && defined(__PRI64_PREFIX)
# ifndef C23_FALLBACK_SILENT
# warning "no C23 support for %b printf formats found, emulating with glibc features"
# endif
# define PRIB16 "B"
# define PRIB32 "B"
# define PRIB64 __PRI64_PREFIX "B"
# define PRIB8 "B"
# define PRIBFAST16 __PRIPTR_PREFIX "B"
# define PRIBFAST32 __PRIPTR_PREFIX "B"
# define PRIBFAST64 __PRI64_PREFIX "B"
# define PRIBFAST8 "B"
# define PRIBLEAST16 "B"
# define PRIBLEAST32 "B"
# define PRIBLEAST64 __PRI64_PREFIX "B"
# define PRIBLEAST8 "B"
# define PRIBMAX __PRI64_PREFIX "B"
# define PRIBPTR __PRIPTR_PREFIX "B"
# define PRIb16 "b"
# define PRIb32 "b"
# define PRIb64 __PRI64_PREFIX "b"
# define PRIb8 "b"
# define PRIbFAST16 __PRIPTR_PREFIX "b"
# define PRIbFAST32 __PRIPTR_PREFIX "b"
# define PRIbFAST64 __PRI64_PREFIX "b"
# define PRIbFAST8 "b"
# define PRIbLEAST16 "b"
# define PRIbLEAST32 "b"
# define PRIbLEAST64 __PRI64_PREFIX "b"
# define PRIbLEAST8 "b"
# define PRIbMAX __PRI64_PREFIX "b"
# define PRIbPTR __PRIPTR_PREFIX "b"
# define SCNb16 "hb"
# define SCNb32 "b"
# define SCNb64 __PRI64_PREFIX "b"
# define SCNb8 "hhb"
# define SCNbFAST16 __PRIPTR_PREFIX "b"
# define SCNbFAST32 __PRIPTR_PREFIX "b"
# define SCNbFAST64 __PRI64_PREFIX "b"
# define SCNbFAST8 "hhb"
# define SCNbLEAST16 "hb"
# define SCNbLEAST32 "b"
# define SCNbLEAST64 __PRI64_PREFIX "b"
# define SCNbLEAST8 "hhb"
# define SCNbMAX __PRI64_PREFIX "b"
# define SCNbPTR __PRIPTR_PREFIX "b"
# else
# ifndef C23_FALLBACK_SILENT
# warning "no C23 support for %b printf formats found"
# endif
# endif
# endif
#endif
/**********************************************************************************************/
// Complex arithmetic without <complex.h> header
#ifndef __STDC_NO_COMPLEX__
// gcc and related compilers implement an "I" or "i" suffix for
// floating point constants since ages.
# ifdef __GNUC__
# define I (__extension__ 1.0IF)
# define _COMPLEX_I (0.0F + I)
// Otherwise use the new constexpr construct to produce a named
// constant of complex type.
# else
typedef union _C23_complex _C23_complex;
union _C23_complex {
// These two are guaranteed to have the same representation.
float _C23_v[2];
_Complex float _C23_c;
};
// Use static const. Best would be to have constexpr, but using a
// different member than was initialized is not defined for them,
// unfortunately.
static _C23_complex const _C23_I = { { 0.0F, 1.0F, }, };
# define _COMPLEX_I (_C23_I._C23_c)
# endif
#define iscomplex(X) (sizeof(1.0F*(X)) == sizeof(1.0F*(X)+_COMPLEX_I))
#define isimaginary(X) (sizeof(1.0F*(X)+0.0F) == 2*sizeof(1.0F*(X)))
# define _C23_float_Complex_CASE float _Complex: true,
# define _C23_double_Complex_CASE double _Complex: true,
# define _C23_long_double_Complex_CASE long double _Complex: true,
#else
# define _C23_float_Complex_CASE
# define _C23_double_Complex_CASE
# define _C23_long_double_Complex_CASE
#endif
/**********************************************************************************************/
// Testing for presence of decimal floating types
#if defined(__DEC32_MAX__)
# define _C23_Decimal32_CASE _Decimal32: true,
#else
# define _C23_Decimal32_CASE
#endif
#if defined(__DEC64_MAX__)
# define _C23_Decimal64_CASE _Decimal64: true,
#else
# define _C23_Decimal64_CASE
#endif
#if defined(__DEC128_MAX__)
# define _C23_Decimal128_CASE _Decimal128: true,
#else
# define _C23_Decimal128_CASE
#endif
#define isdecimalfloating(...) (_Generic((__VA_ARGS__)+0, _C23_Decimal32_CASE _C23_Decimal64_CASE _C23_Decimal128_CASE default: false))
#ifndef iscomplex
# define iscomplex(...) (_Generic((__VA_ARGS__)+0, _C23_float_Complex_CASE _C23_double_Complex_CASE _C23_long_double_Complex_CASE default: false))
#endif
#define isstandardrealfloating(...) (_Generic((__VA_ARGS__)+0, float: true, double: true, long double: true, default: false))
#define isstandardfloating(...) ((bool)(isstandardrealfloating(__VA_ARGS__)||iscomplex(__VA_ARGS__)))
#ifndef isfloating
# define isfloating(...) ((bool)(isstandardfloating(__VA_ARGS__)||isdecimalfloating(__VA_ARGS__)))
#endif
/**********************************************************************************************/
// various tg-conversions and type traits
#ifndef totype
# define totype(Y, ...) ((typeof(__VA_ARGS__))Y)
#endif
#ifndef tominusone
# define tominusone(...) totype(-1, __VA_ARGS__)
#endif
#ifndef tozero
# define tozero(...) totype(0, __VA_ARGS__)
#endif
#ifndef toone
# define toone(...) totype(1, __VA_ARGS__)
#endif
#ifndef iscompatible
# define iscompatible(X, Y) (_Generic((X), typeof(Y): true, default: false))
#endif
#ifndef is_potentially_negative
# define is_potentially_negative(...) (tominusone(__VA_ARGS__) < 0)
#endif
#ifndef is_const_target
# define is_const_target(...) (_Generic((1 ? (__VA_ARGS__) : (void*)1), void const*: true, void const volatile*: true, default: false))
#endif
#ifndef is_volatile_target
# define is_volatile_target(...) (_Generic((1 ? (__VA_ARGS__) : (void*)1), void volatile*: true, void const volatile*: true, default: false))
#endif
#ifndef is_const
# define is_const(...) is_const_target(&(typeof(__VA_ARGS__)){ 0 })
#endif
#ifndef is_volatile
# define is_volatile(...) is_volatile_target(&(typeof(__VA_ARGS__)){ 0 })
#endif
#ifndef is_null_pointer_constant
struct do_not_use_this_otherwise;
# define is_null_pointer_constant(...) \
(_Generic((1 ? (struct do_not_use_this_otherwise*)nullptr : (__VA_ARGS__)), \
struct do_not_use_this_otherwise*: true, \
default: false))
#endif
#ifndef is_zero_ice
# define is_zero_ice(...) is_null_pointer_constant((void*)(uintptr_t)(!!(__VA_ARGS__)))
#endif
#ifndef isinteger
# define isinteger(...) is_zero_ice(tozero(__VA_ARGS__))
#endif
#ifndef issigned
# define issigned(...) ((bool)(is_potentially_negative(__VA_ARGS__) && isinteger(__VA_ARGS__) && !iscompatible(__VA_ARGS__, char)))
#endif
#ifndef isunsigned
# define isunsigned(...) ((bool)(!is_potentially_negative(__VA_ARGS__) && isinteger(__VA_ARGS__) && !iscompatible(__VA_ARGS__, char)))
#endif
#ifndef isice
# define isice(...) is_zero_ice(!((__VA_ARGS__) || 1))
#endif
#ifndef isvla
# define isvla(...) ((bool)!isice(sizeof(__VA_ARGS__)))
#endif
#ifndef isxwide
# define isxwide(...) \
((bool)( \
isinteger(__VA_ARGS__) \
&&_Generic((__VA_ARGS__)+0ULL, \
unsigned long long: false, \
default: true)))
#endif
#ifndef is_pointer
struct do_not_use_this_otherwise { char c; };
# define get_fla(...) \
GENERIC_IF(isvla(__VA_ARGS__), \
(struct do_not_use_this_otherwise[1]){ 0 }, \
(__VA_ARGS__))
# define is_pointer_nvla(...) \
(_Generic((typeof(__VA_ARGS__)*)0, \
typeof(get_fla(*(__VA_ARGS__)))**: true, \
default: false))
# define is_pointer_vla(...) \
(_Generic((typeof(get_fla(*(__VA_ARGS__)))*)0, \
typeof(struct do_not_use_this_otherwise[1])*: true, \
default: false))
# define is_pointer(...) ((bool)(is_pointer_nvla(__VA_ARGS__)||is_pointer_vla(__VA_ARGS__)))
#endif
#ifndef is_array
# define is_array(...) ((bool)!is_pointer(__VA_ARGS__))
#endif
#ifndef is_fla
# define is_fla(...) ((bool)(is_array(__VA_ARGS__)&&!isvla(__VA_ARGS__)))
#endif
#ifndef is_void_pointer
# define is_void_pointer(...) \
_Generic((typeof(*(__VA_ARGS__))const volatile*)nullptr, \
void const volatile*: true, \
default: false)
#endif
/**********************************************************************************************/
/* Const preserving functions as of C23. */
/* These are not exactly according to the book, because the return
type of the string functions could sometimes be a pointer to a void
type and not a character type.*/
#if __STDC_VERSION_STRING_H__ < 202311L
//QVoid *memchr(QVoid *s, int c, size_t n);
# ifndef memchr
# define memchr(S, C, N) ((typeof(1 ? S : (void*)1))memchr((S), (C), (N)))
# endif
// QChar *strchr(QChar *s, int c);
# ifndef strchr
# define strchr(S, C) ((typeof(S))strchr((S), (C)))
# endif
// QChar *strpbrk(QChar *s1, const char *s2);
# ifndef strpbrk
# define strpbrk(S1, S2) ((typeof(S1))strpbrk((S1), (S2)))
# endif
// QChar *strrchr(QChar *s, int c);
# ifndef strrchr
# define strrchr(S, C) ((typeof(S))strrchr((S), (C)))
# endif
// QChar *strstr(QChar *s1, const char *s2);
# ifndef strstr
# define strstr(S1, S2) ((typeof(S1))strstr((S1), (S2)))
# endif
#endif
#if __STDC_VERSION_WCHAR_H__ < 202311L
//QWchar *wmemchr(QWchar *s, int c, size_t n);
# ifndef wmemchr
# define wmemchr(S, C, N) ((typeof(S))wmemchr((S), (C), (N)))
# endif
// QWchar *wcschr(QWchar *s, wchar_t c);
# ifndef wcschr
# define wcschr(S, C) ((typeof(S))wcschr((S), (C)))
# endif
// QWchar *wcspbrk(QWchar *s1, const wchar_t *s2);
# ifndef wcspbrk
# define wcspbrk(S1, S2) ((typeof(S1))wcspbrk((S1), (S2)))
# endif
// QWchar *wcsrchr(QWchar *s, wchar_t c);
# ifndef wcsrchr
# define wcsrchr(S, C) ((typeof(S))wcsrchr((S), (C)))
# endif
// QWchar *wcswcs(QWchar *s1, const wchar_t *s2);
# ifndef wcsstr
# define wcsstr(S1, S2) ((typeof(S1))wcsstr((S1), (S2)))
# endif
#endif
#if __STDC_VERSION_STDLIB_H__ < 202311L
// QVoid *bsearch(const void *key, QVoid *base, size_t nmemb, size_t size,
// int (*compar)(const void *, const void *));
# ifndef bsearch
# define bsearch(KEY, BASE, NMEMB, SIZE, COMPAR) ((typeof(1 ? (BASE) : (void*)1))bsearch((KEY), (BASE), (NMEMB), (SIZE), (COMPAR)))
# endif
#endif
#endif
/**********************************************************************************************/
#ifdef __has_include
# if __has_include(<stdbit.h>)
# include <stdbit.h>
# define __has_feature_c_stdbit_h ,
# endif
#endif
#ifndef __STDC_ENDIAN_LITTLE__
# ifdef __GNUC__
# define __STDC_ENDIAN_LITTLE__ __ORDER_LITTLE_ENDIAN__
# endif
#endif
#ifndef __STDC_ENDIAN_BIG__
# ifdef __GNUC__
# define __STDC_ENDIAN_BIG__ __ORDER_BIG_ENDIAN__
# endif
#endif
#ifndef __STDC_ENDIAN_NATIVE__
# ifdef __GNUC__
# define __STDC_ENDIAN_NATIVE__ __BYTE_ORDER__
# else
# ifndef C23_FALLBACK_SILENT
# warning "native endian could not be determined"
# endif
# endif
#endif
/**********************************************************************************************/
/* This adds the 14 type-generic bit interfaces that are added by
C23. The use of the other type-specific interfaces is of less
interest.
generic_return_type stdc_leading_zeros(generic_value_type value);
generic_return_type stdc_leading_ones(generic_value_type value);
generic_return_type stdc_trailing_zeros(generic_value_type value);
generic_return_type stdc_trailing_ones(generic_value_type value);
generic_return_type stdc_first_leading_zero(generic_value_type value);
generic_return_type stdc_first_leading_one(generic_value_type value);
generic_return_type stdc_first_trailing_zero(generic_value_type value);
generic_return_type stdc_count_zeros(generic_value_type value);
generic_return_type stdc_count_ones(generic_value_type value);
bool stdc_has_single_bit(generic_value_type value);
generic_return_type stdc_bit_width(generic_value_type value);
generic_value_type stdc_bit_floor(generic_value_type value);
generic_value_type stdc_bit_ceil(generic_value_type value);
*/
/*
An auxiliary macro that shifts right by ULLONG_WIDTH, regardless
whether the type has a width smaller than that. For most types this
will just be a zero of the same type.
*/
#define shift_xright(...) \
GENERIC_IF(isxwide(__VA_ARGS__), \
(__VA_ARGS__)>>GENERIC_IF(isxwide(__VA_ARGS__), \
ULLONG_WIDTH, \
0), \
tozero(__VA_ARGS__))
#ifndef stdc_count_ones
# ifdef __GNUC__
# define stdc_trailing_zeros(...) \
({ \
auto s_t_z_x = (__VA_ARGS__); \
static_assert(isunsigned(s_t_z_x), "bit operation needs unsigned type"); \
(s_t_z_x) \
? _Generic((s_t_z_x), \
bool: __builtin_ctz((unsigned)s_t_z_x), \
unsigned char: __builtin_ctz((unsigned)s_t_z_x), \
unsigned short: __builtin_ctz((unsigned)s_t_z_x), \
unsigned: __builtin_ctz(s_t_z_x), \
unsigned long: __builtin_ctzl(s_t_z_x), \
unsigned long long: __builtin_ctzll(s_t_z_x), \
default: ({ \
size_t s_t_z_ret = 0; \
while (s_t_z_x) { \
unsigned long long s_t_z_z = s_t_z_x; \
if (s_t_z_z) { \
s_t_z_ret += __builtin_ctzll(s_t_z_z); \
s_t_z_x = 0; \
} else { \
s_t_z_ret += ULLONG_WIDTH; \
s_t_z_x = shift_xright(s_t_z_x); \
} \
} \
s_t_z_ret; \
})) \
: stdc_count_ones(tominusone(s_t_z_x)); \
})
/* This counts the least significant 1-bits of the specific type of the
argument. Therefor we complement all bits. To take narrow types
into account, that result has to be cast back to the original
type. */
# define stdc_trailing_ones(...) stdc_trailing_zeros((typeof(__VA_ARGS__))~(__VA_ARGS__))
# define stdc_leading_zeros(...) \
({ \
auto s_l_o_x = (__VA_ARGS__); \
static_assert(isunsigned(s_l_o_x), "bit operation needs unsigned type"); \
(s_l_o_x) \
? _Generic((s_l_o_x), \
unsigned char: __builtin_clz((unsigned)s_l_o_x) - __builtin_clz((unsigned)tominusone(s_l_o_x)), \
unsigned short: __builtin_clz((unsigned)s_l_o_x) - __builtin_clz((unsigned)tominusone(s_l_o_x)), \
unsigned: __builtin_clz(s_l_o_x), \
unsigned long: __builtin_clzl(s_l_o_x), \
unsigned long long: __builtin_clzll(s_l_o_x), \
default: \
((!isxwide(s_l_o_x)) \
/* Should only trigger for _BitInt types. */ \
? (__builtin_clzll(s_l_o_x) - __builtin_clzll(tominusone(s_l_o_x))) \
/* determine the long long word with highest 1-bit . */ \
: ({ \
size_t s_l_o_w = stdc_count_ones(tominusone(s_l_o_x)) - ULLONG_WIDTH; \
while ((s_l_o_x+0UL) > ULLONG_MAX) { \
s_l_o_x = shift_xright(s_l_o_x); \
s_l_o_w -= ULLONG_WIDTH; \
} \
__builtin_clzll(s_l_o_x) + s_l_o_w; \
}))) \
/* This should resolve to a compile time constant. */ \
: stdc_count_ones(tominusone(s_l_o_x)); \
})
/* This counts the most significant 1-bits of the specific type of the
argument. Therefor we complement all bits. To take narrow types
into account, that result has to be cast back to the original
type. */
# define stdc_leading_ones(...) stdc_leading_zeros((typeof(__VA_ARGS__))~(__VA_ARGS__))
# define stdc_count_ones(...) \
_Generic((__VA_ARGS__), \
bool: __builtin_popcount((unsigned)(__VA_ARGS__)), \
unsigned char: __builtin_popcount((unsigned)(__VA_ARGS__)), \
unsigned short: __builtin_popcount((unsigned)(__VA_ARGS__)), \
unsigned: __builtin_popcount((unsigned)(__VA_ARGS__)), \
unsigned long: __builtin_popcountl((unsigned long)(__VA_ARGS__)), \
unsigned long long: __builtin_popcountll((unsigned long long)(__VA_ARGS__)), \
default: ({ \
auto s_c_o_x = (__VA_ARGS__); \
static_assert(isunsigned(s_c_o_x), "bit operation needs unsigned type"); \
size_t s_c_o_ret = 0; \
while (s_c_o_x) { \
s_c_o_ret += __builtin_popcountll((unsigned long long)s_c_o_x); \
s_c_o_x = shift_xright(s_c_o_x); \
} \
s_c_o_ret; \
}))
/* This counts the 0-bits of the specific type of the
argument. Therefor we complement all bits. To take narrow types
into account, that result has to be cast back to the original
type. */
# define stdc_count_zeros(...) stdc_count_ones((typeof(__VA_ARGS__))~(__VA_ARGS__))
# define stdc_has_single_bit(...) \
({ \
auto s_h_s_b_x = (__VA_ARGS__); \
static_assert(isunsigned(s_h_s_b_x), "bit operation needs unsigned type"); \
(bool)(s_h_s_b_x && !((s_h_s_b_x != 1) && (s_h_s_b_x & (s_h_s_b_x - 1)))); \
})
# define stdc_bit_width(...) \
({ \
auto s_b_w_x = (__VA_ARGS__); \
static_assert(isunsigned(s_b_w_x), "bit operation needs unsigned type"); \
stdc_count_ones(tominusone(s_b_w_x))-stdc_leading_zeros(s_b_w_x); \
})
# define stdc_bit_floor(...) \
({ \
auto s_b_f_x = (__VA_ARGS__); \
static_assert(isunsigned(s_b_f_x), "bit operation needs unsigned type"); \
(!s_b_f_x) \
? 0 \
: (toone(s_b_f_x)<<(stdc_bit_width(s_b_f_x)-1)); \
})
# define stdc_bit_ceil(...) \
(toone(__VA_ARGS__)<<stdc_bit_width(__VA_ARGS__))
# endif
#endif
|