diff options
Diffstat (limited to 'chad')
| -rw-r--r-- | chad/dictate.h | 371 | ||||
| -rw-r--r-- | chad/experimental/bits.h | 2 | ||||
| -rw-r--r-- | chad/klist.h | 135 | ||||
| -rw-r--r-- | chad/kvec.h | 90 | ||||
| -rw-r--r-- | chad/qx.h | 36 | ||||
| -rw-r--r-- | chad/remove_all.h | 11 | ||||
| -rw-r--r-- | chad/sds.h | 172 | ||||
| -rw-r--r-- | chad/sdsalloc.h | 47 | ||||
| -rw-r--r-- | chad/terry.h | 178 |
9 files changed, 1041 insertions, 1 deletions
diff --git a/chad/dictate.h b/chad/dictate.h new file mode 100644 index 0000000..5905a03 --- /dev/null +++ b/chad/dictate.h @@ -0,0 +1,371 @@ +/* # Dictate + * Dictate is a family of output functions with the designed to be comfortable, not robust. + * It's intended use-case is within the terminal. + */ + +#define DICTATE_PRINTER_COMMON_ARGS FILE * const f, [[ maybe_unused ]] const char * const m, [[ maybe_unused ]] int h, [[ maybe_unused ]] int n + +#ifndef DICTATE_H +#define DICTATE_H + +/* Require C23. + * NOTE: It would be possible to backport to C11. + */ +#if __STDC_VERSION__ < 202000 //202311L /*it appears that its not defined while partially implemented?*/ +# error "C23 or newer is required" +#endif + +/* ## State + * Dictate has thread local global state for convenience. + */ +/* Flush after every print. + * Useful for debugging when the process could terminate unexpectedly. + */ +void dictate_pedantic_flush(bool b); +/* Enable or disable the processing of color sequences (see below). + * When colors are disabled, color sequences are not printed at all. + * ### Colors sequences: + * $r -> Red + * $g -> Green + * $b -> Blue + * $y -> Yellow + * $m -> Magenta + * $c -> Cyan + * $d -> black ("dark") + * $w -> white + * $B -> Bold + * $I -> Italic + * $0 -> Reset + */ +void dictate_color_enabled(bool b); +/* XXX + */ +//void dictate_quoting_enabled(bool b); + +/* ## Dictate functions + * Dictate functions are generic and variadic. + * The idea is that you pass in whatever and it just prints it. + * All primitive types are supported out of the box. + * Margins and colors are parsed appropriately from C strings. + * + * <TARGET> [m] dictate + * + * m -> margin; specifies a prefix inserted before each line + * + * TARGET: + * %empty -> stdout + * f -> FILE * + * + * NOTE: what you can see below are pseudo-declarations for macro functions + */ +#if 0 +void dictate(...); +void mdictate(const char * margin, ...); +void fdictate(FILE * f, ...); +void fmdictate(FILE * f, const char * margin, ...); +#endif + +// ################################ +// ### MOVE ALONG; MAGICK AHEAD ### +// ################################ +#include <stdarg.h> +#include <stdio.h> + +#define DICTATE_NARG(...) DICTATE_PP_NARG_(__VA_ARGS__,DICTATE_PP_RSEQ_N()) +#define DICTATE_PP_NARG_(...) DICTATE_PP_128TH_ARG(__VA_ARGS__) +#define DICTATE_PP_128TH_ARG( \ + _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,N,...) N +#define DICTATE_PP_RSEQ_N() \ + 127,126,125,124,123,122,121,120,\ + 119,118,117,116,115,114,113,112,\ + 111,110,109,108,107,106,105,104,\ + 103,102,101,100, 99, 98, 97, 96,\ + 95, 94, 93, 92, 91, 90, 89, 88,\ + 87, 86, 85, 84, 83, 82, 81, 80,\ + 79, 78, 77, 76, 75, 74, 73, 72,\ + 71, 70, 69, 68, 67, 66, 65, 64,\ + 63, 62, 61, 60, 59, 58, 57, 56,\ + 55, 54, 53, 52, 51, 50, 49, 48,\ + 47, 46, 45, 44, 43, 42, 41, 40,\ + 39, 38, 37, 36, 35, 34, 33, 32,\ + 31, 30, 29, 28, 27, 26, 25, 24,\ + 23, 22, 21, 20, 19, 18, 17, 16,\ + 15, 14, 13, 12, 11, 10, 9, 8,\ + 7, 6, 5, 4, 3, 2, 1, 0 + +// trivial type printers +static inline void dictate_bool (DICTATE_PRINTER_COMMON_ARGS, const bool i) { fprintf(f, i ? "true" : "false"); } +static inline void dictate_char (DICTATE_PRINTER_COMMON_ARGS, const char i) { fprintf(f, "%c", i); } +static inline void dictate_uchar (DICTATE_PRINTER_COMMON_ARGS, const unsigned char i) { fprintf(f, "%c", i); } +static inline void dictate_short (DICTATE_PRINTER_COMMON_ARGS, const short i) { fprintf(f, "%hd", i); } +static inline void dictate_ushort (DICTATE_PRINTER_COMMON_ARGS, const unsigned short i) { fprintf(f, "%hu", i); } +static inline void dictate_int (DICTATE_PRINTER_COMMON_ARGS, const int i) { fprintf(f, "%d", i); } +static inline void dictate_uint (DICTATE_PRINTER_COMMON_ARGS, const unsigned int i) { fprintf(f, "%u", i); } +static inline void dictate_long (DICTATE_PRINTER_COMMON_ARGS, const long i) { fprintf(f, "%ld", i); } +static inline void dictate_ulong (DICTATE_PRINTER_COMMON_ARGS, const unsigned long i) { fprintf(f, "%lu", i); } +static inline void dictate_llong (DICTATE_PRINTER_COMMON_ARGS, const long long i) { fprintf(f, "%lld", i); } +static inline void dictate_ullong (DICTATE_PRINTER_COMMON_ARGS, const unsigned long long i) { fprintf(f, "%llu", i); } +static inline void dictate_float (DICTATE_PRINTER_COMMON_ARGS, const float i) { fprintf(f, "%f", i); } +static inline void dictate_double (DICTATE_PRINTER_COMMON_ARGS, const double i) { fprintf(f, "%lf", i); } +static inline void dictate_ldouble (DICTATE_PRINTER_COMMON_ARGS, const long double i) { fprintf(f, "%Lf", i); } +static inline void dictate_ptr (DICTATE_PRINTER_COMMON_ARGS, const void * i) { fprintf(f, "%p", i); } +// trivial type pointer printers +#define DICTATE_TYPE_POINTER_WRAP(F, t) \ +static inline void F ## _ptr (DICTATE_PRINTER_COMMON_ARGS, t * i) { dictate_ptr(f,m,h,n,(void*)i); fputc(' ',f); F(f,m,h,n,*i); } +DICTATE_TYPE_POINTER_WRAP(dictate_bool, bool) +DICTATE_TYPE_POINTER_WRAP(dictate_char, char) +DICTATE_TYPE_POINTER_WRAP(dictate_uchar, unsigned char) +DICTATE_TYPE_POINTER_WRAP(dictate_short, short) +DICTATE_TYPE_POINTER_WRAP(dictate_ushort, unsigned short) +DICTATE_TYPE_POINTER_WRAP(dictate_int, int) +DICTATE_TYPE_POINTER_WRAP(dictate_uint, unsigned int) +DICTATE_TYPE_POINTER_WRAP(dictate_long, long) +DICTATE_TYPE_POINTER_WRAP(dictate_ulong, unsigned long) +DICTATE_TYPE_POINTER_WRAP(dictate_llong, long long) +DICTATE_TYPE_POINTER_WRAP(dictate_ullong, unsigned long long) +DICTATE_TYPE_POINTER_WRAP(dictate_float, float) +DICTATE_TYPE_POINTER_WRAP(dictate_double, double) +DICTATE_TYPE_POINTER_WRAP(dictate_ldouble, long double) + +// complex type printers +extern void dictate_str(DICTATE_PRINTER_COMMON_ARGS, const char * const str); + +// null object type to fool _Generic into our plot +struct dictatenullt { const void * x; }; + +/* Here we try our best to optimize away all costs of our macro magick. + * + * GCC is always 0 cost like this. + * + * Clang also optimizes away the calls, but without -O1 or higher, + * it still constructs a swarm of our null objects. + * An empty struct is non-standard, yet clang can handle it, + * however it still allocates 1 byte for them each, + * so thats a non-solution. + */ +#ifdef __GNUC__ +# ifdef __clang__ +# define _DICATATE_NOOP_ATTRIBUTES __attribute__((always_inline)) +# else // gcc +# define _DICATATE_NOOP_ATTRIBUTES __attribute__((optimize(3))) +# endif +#else +# define _DICATATE_NOOP_ATTRIBUTES +#endif + +static inline _DICATATE_NOOP_ATTRIBUTES +void noop( + [[ maybe_unused ]] const FILE * const f, + [[ maybe_unused ]] const char * const m, + [[ maybe_unused ]] int h, + [[ maybe_unused ]] int n, + [[ maybe_unused ]] const struct dictatenullt i +) { + return; +} + +#ifndef DICTATE_USER_TYPES +# define DICTATE_USER_TYPES +#endif + +#define DICTATE_SWITCH(f, m, h, n, t) _Generic((t) \ + /* special */ \ + , default: noop \ + , void*: dictate_ptr \ + , char*: dictate_str \ + /* primitives */ \ + , bool: dictate_bool \ + , char: dictate_char \ + , unsigned char: dictate_uchar \ + , short: dictate_short \ + , unsigned short: dictate_ushort \ + , int: dictate_int \ + , unsigned int: dictate_uint \ + , long: dictate_long \ + , unsigned long: dictate_ulong \ + , long long: dictate_llong \ + , unsigned long long: dictate_ullong \ + , float: dictate_float \ + , double: dictate_double \ + , long double: dictate_ldouble \ + /* primitive pointers */ \ + , bool*: dictate_bool_ptr \ + , unsigned char*: dictate_uchar_ptr \ + , short*: dictate_short_ptr \ + , unsigned short*: dictate_ushort_ptr \ + , int*: dictate_int_ptr \ + , unsigned int*: dictate_uint_ptr \ + , long*: dictate_long_ptr \ + , unsigned long*: dictate_ulong_ptr \ + , long long*: dictate_llong_ptr \ + , unsigned long long*: dictate_ullong_ptr \ + , float*: dictate_float_ptr \ + , double*: dictate_double_ptr \ + , long double*: dictate_ldouble_ptr \ + /* user types */ \ + DICTATE_USER_TYPES \ + )(f, m, h, n, t) + +#define DICTATE_BIG_GUY(\ + n, f, m, _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, \ + ...\ + ) \ + DICTATE_SWITCH(f,m, 1,n,_4); \ + DICTATE_SWITCH(f,m, 2,n,_5); DICTATE_SWITCH(f,m, 3,n,_6); DICTATE_SWITCH(f,m, 4,n,_7); DICTATE_SWITCH(f,m, 5,n,_8); \ + DICTATE_SWITCH(f,m, 6,n,_9); DICTATE_SWITCH(f,m, 7,n,_10); DICTATE_SWITCH(f,m, 8,n,_11); DICTATE_SWITCH(f,m, 9,n,_12); \ + DICTATE_SWITCH(f,m, 10,n,_13); DICTATE_SWITCH(f,m, 11,n,_14); DICTATE_SWITCH(f,m, 12,n,_15); DICTATE_SWITCH(f,m, 13,n,_16); \ + DICTATE_SWITCH(f,m, 14,n,_17); DICTATE_SWITCH(f,m, 15,n,_18); DICTATE_SWITCH(f,m, 16,n,_19); DICTATE_SWITCH(f,m, 17,n,_20); \ + DICTATE_SWITCH(f,m, 18,n,_21); DICTATE_SWITCH(f,m, 19,n,_22); DICTATE_SWITCH(f,m, 20,n,_23); DICTATE_SWITCH(f,m, 21,n,_24); \ + DICTATE_SWITCH(f,m, 22,n,_25); DICTATE_SWITCH(f,m, 23,n,_26); DICTATE_SWITCH(f,m, 24,n,_27); DICTATE_SWITCH(f,m, 25,n,_28); \ + DICTATE_SWITCH(f,m, 26,n,_29); DICTATE_SWITCH(f,m, 27,n,_30); DICTATE_SWITCH(f,m, 28,n,_31); DICTATE_SWITCH(f,m, 29,n,_32); \ + DICTATE_SWITCH(f,m, 30,n,_33); DICTATE_SWITCH(f,m, 31,n,_34); DICTATE_SWITCH(f,m, 32,n,_35); DICTATE_SWITCH(f,m, 33,n,_36); \ + DICTATE_SWITCH(f,m, 34,n,_37); DICTATE_SWITCH(f,m, 35,n,_38); DICTATE_SWITCH(f,m, 36,n,_39); DICTATE_SWITCH(f,m, 37,n,_40); \ + DICTATE_SWITCH(f,m, 38,n,_41); DICTATE_SWITCH(f,m, 39,n,_42); DICTATE_SWITCH(f,m, 40,n,_43); DICTATE_SWITCH(f,m, 41,n,_44); \ + DICTATE_SWITCH(f,m, 42,n,_45); DICTATE_SWITCH(f,m, 43,n,_46); DICTATE_SWITCH(f,m, 44,n,_47); DICTATE_SWITCH(f,m, 45,n,_48); \ + DICTATE_SWITCH(f,m, 46,n,_49); DICTATE_SWITCH(f,m, 47,n,_50); DICTATE_SWITCH(f,m, 48,n,_51); DICTATE_SWITCH(f,m, 49,n,_52); \ + DICTATE_SWITCH(f,m, 50,n,_53); DICTATE_SWITCH(f,m, 51,n,_54); DICTATE_SWITCH(f,m, 52,n,_55); DICTATE_SWITCH(f,m, 53,n,_56); \ + DICTATE_SWITCH(f,m, 54,n,_57); DICTATE_SWITCH(f,m, 55,n,_58); DICTATE_SWITCH(f,m, 56,n,_59); DICTATE_SWITCH(f,m, 57,n,_60); \ + DICTATE_SWITCH(f,m, 58,n,_61); DICTATE_SWITCH(f,m, 59,n,_62); DICTATE_SWITCH(f,m, 60,n,_63); DICTATE_SWITCH(f,m, 61,n,_64); \ + DICTATE_SWITCH(f,m, 62,n,_65); DICTATE_SWITCH(f,m, 63,n,_66); DICTATE_SWITCH(f,m, 64,n,_67); DICTATE_SWITCH(f,m, 65,n,_68); \ + DICTATE_SWITCH(f,m, 66,n,_69); DICTATE_SWITCH(f,m, 67,n,_70); DICTATE_SWITCH(f,m, 68,n,_71); DICTATE_SWITCH(f,m, 69,n,_72); \ + DICTATE_SWITCH(f,m, 70,n,_73); DICTATE_SWITCH(f,m, 71,n,_74); DICTATE_SWITCH(f,m, 72,n,_75); DICTATE_SWITCH(f,m, 73,n,_76); \ + DICTATE_SWITCH(f,m, 74,n,_77); DICTATE_SWITCH(f,m, 75,n,_78); DICTATE_SWITCH(f,m, 76,n,_79); DICTATE_SWITCH(f,m, 77,n,_80); \ + DICTATE_SWITCH(f,m, 78,n,_81); DICTATE_SWITCH(f,m, 79,n,_82); DICTATE_SWITCH(f,m, 80,n,_83); DICTATE_SWITCH(f,m, 81,n,_84); \ + DICTATE_SWITCH(f,m, 82,n,_85); DICTATE_SWITCH(f,m, 83,n,_86); DICTATE_SWITCH(f,m, 84,n,_87); DICTATE_SWITCH(f,m, 85,n,_88); \ + DICTATE_SWITCH(f,m, 86,n,_89); DICTATE_SWITCH(f,m, 87,n,_90); DICTATE_SWITCH(f,m, 88,n,_91); DICTATE_SWITCH(f,m, 89,n,_92); \ + DICTATE_SWITCH(f,m, 90,n,_93); DICTATE_SWITCH(f,m, 91,n,_94); DICTATE_SWITCH(f,m, 92,n,_95); DICTATE_SWITCH(f,m, 93,n,_96); \ + DICTATE_SWITCH(f,m, 94,n,_97); DICTATE_SWITCH(f,m, 95,n,_98); DICTATE_SWITCH(f,m, 96,n,_99); DICTATE_SWITCH(f,m, 97,n,_100); \ + DICTATE_SWITCH(f,m, 98,n,_101); DICTATE_SWITCH(f,m, 99,n,_102); DICTATE_SWITCH(f,m,100,n,_103); DICTATE_SWITCH(f,m,101,n,_104); \ + DICTATE_SWITCH(f,m,102,n,_105); DICTATE_SWITCH(f,m,103,n,_106); DICTATE_SWITCH(f,m,104,n,_107); DICTATE_SWITCH(f,m,105,n,_108); \ + DICTATE_SWITCH(f,m,106,n,_109); DICTATE_SWITCH(f,m,107,n,_110); DICTATE_SWITCH(f,m,108,n,_111); DICTATE_SWITCH(f,m,109,n,_112); \ + DICTATE_SWITCH(f,m,110,n,_113); DICTATE_SWITCH(f,m,111,n,_114); DICTATE_SWITCH(f,m,112,n,_115); DICTATE_SWITCH(f,m,113,n,_116); \ + DICTATE_SWITCH(f,m,114,n,_117); DICTATE_SWITCH(f,m,115,n,_118); DICTATE_SWITCH(f,m,116,n,_119); DICTATE_SWITCH(f,m,117,n,_120); \ + DICTATE_SWITCH(f,m,118,n,_121); DICTATE_SWITCH(f,m,119,n,_122); DICTATE_SWITCH(f,m,120,n,_123); DICTATE_SWITCH(f,m,121,n,_124); \ + DICTATE_SWITCH(f,m,122,n,_125); DICTATE_SWITCH(f,m,123,n,_126); DICTATE_SWITCH(f,m,124,n,_127); + +#define _nfmdictate(...) do { DICTATE_BIG_GUY(__VA_ARGS__, \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), \ + ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}), ((struct dictatenullt){0}) \ + )} while (0) +#define fmdictate(f, m, ...) do { _nfmdictate(DICTATE_NARG(__VA_ARGS__), f, m, __VA_ARGS__); } while (0) +#define fdictate(f, ...) do { _nfmdictate(DICTATE_NARG(__VA_ARGS__), f, NULL, __VA_ARGS__); } while (0) +#define mdictate(m, ...) do { _nfmdictate(DICTATE_NARG(__VA_ARGS__), stdout, m, __VA_ARGS__); } while (0) +#define dictate(...) do { _nfmdictate(DICTATE_NARG(__VA_ARGS__), stdout, NULL, __VA_ARGS__); } while (0) +// ################################ +// ################################ +// ################################ + +/* ## Dictatef functions + * Dictatef functions follow a similar paradigm as <stdio.h>. + * + * [va] <TARGET> [m] dictatef + * + * va -> take a va_list (instead of varargs) + * m -> margin; specifies a prefix inserted before each line + * + * TARGET: + * %empty -> stdout + * f -> FILE * + * + * ### Format + * Dictatef supports the most common subset of printf formats. + * - Width specification (hard coded number or *). + * - Placeholders: + * %d -> Decimal signed long long + * %x -> Hexadecimal number + * %s -> C string + * %c -> Single character + */ +void dictatef(const char * const fmt, ...); +void vadictatef(const char * const fmt, va_list args); +void fdictatef(FILE * const f, const char * const fmt, ...); +void vafdictatef(FILE * const f, const char * const fmt, va_list args); + +void mdictatef(const char * const margin, const char * const fmt, ...); +void vamdictatef(const char * const margin, const char * const fmt, va_list args); +void fmdictatef(FILE * const f, const char * const margin, const char * const fmt, ...); +void vafmdictatef(FILE * f, const char * const margin, const char * const fmt, va_list args); // NOTE: core function + +/* ## Dictate debugging functions + */ +#ifdef DEBUG +# ifndef DICTATENDEBUG +# define debug_dictate dictate +# define debug_mdictate mdictate +# define debug_fdictate fdictate +# define debug_fmdictate fmdictate +# define debug_dictatef dictatef +# define debug_vadictatef vadictatef +# define debug_fdictatef fdictatef +# define debug_vafdictatef vafdictatef +# define debug_mdictatef mdictatef +# define debug_vamdictatef vamdictatef +# define debug_fmdictatef fmdictatef +# define debug_vafmdictatef vafmdictatef +# endif +#else +# define debug_dictate(...) +# define debug_mdictate(...) +# define debug_fdictate(...) +# define debug_fmdictate(...) +# define debug_dictatef(...) +# define debug_vadictatef(...) +# define debug_fdictatef(...) +# define debug_vafdictatef(...) +# define debug_mdictatef(...) +# define debug_vamdictatef(...) +# define debug_fmdictatef(...) +# define debug_vafmdictatef(...) +#endif + +// Dictate is in the Public Domain, and if you say this is not a legal notice, I will sue you. +#endif diff --git a/chad/experimental/bits.h b/chad/experimental/bits.h index 05ed66c..a369ded 100644 --- a/chad/experimental/bits.h +++ b/chad/experimental/bits.h @@ -2,7 +2,7 @@ #define CHAD_BITS_H #include <stdbool.h> -#include <iso646> +#include <iso646.h> #define UNUSED(x) ((void)x) diff --git a/chad/klist.h b/chad/klist.h new file mode 100644 index 0000000..adc3db1 --- /dev/null +++ b/chad/klist.h @@ -0,0 +1,135 @@ +/* The MIT License + + Copyright (c) 2008-2009, by Attractive Chaos <attractor@live.co.uk> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#ifndef _AC_KLIST_H +#define _AC_KLIST_H + +#include <stdlib.h> + +#ifndef klib_unused +#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3) +#define klib_unused __attribute__ ((__unused__)) +#else +#define klib_unused +#endif +#endif /* klib_unused */ + +#define KMEMPOOL_INIT2(SCOPE, name, kmptype_t, kmpfree_f) \ + typedef struct { \ + size_t cnt, n, max; \ + kmptype_t **buf; \ + } kmp_##name##_t; \ + SCOPE kmp_##name##_t *kmp_init_##name(void) { \ + return calloc(1, sizeof(kmp_##name##_t)); \ + } \ + SCOPE void kmp_destroy_##name(kmp_##name##_t *mp) { \ + size_t k; \ + for (k = 0; k < mp->n; ++k) { \ + kmpfree_f(mp->buf[k]); free(mp->buf[k]); \ + } \ + free(mp->buf); free(mp); \ + } \ + SCOPE kmptype_t *kmp_alloc_##name(kmp_##name##_t *mp) { \ + ++mp->cnt; \ + if (mp->n == 0) return calloc(1, sizeof(kmptype_t)); \ + return mp->buf[--mp->n]; \ + } \ + SCOPE void kmp_free_##name(kmp_##name##_t *mp, kmptype_t *p) { \ + --mp->cnt; \ + if (mp->n == mp->max) { \ + mp->max = mp->max? mp->max<<1 : 16; \ + mp->buf = realloc(mp->buf, sizeof(kmptype_t *) * mp->max); \ + } \ + mp->buf[mp->n++] = p; \ + } + +#define KMEMPOOL_INIT(name, kmptype_t, kmpfree_f) \ + KMEMPOOL_INIT2(static inline klib_unused, name, kmptype_t, kmpfree_f) + +#define kmempool_t(name) kmp_##name##_t +#define kmp_init(name) kmp_init_##name() +#define kmp_destroy(name, mp) kmp_destroy_##name(mp) +#define kmp_alloc(name, mp) kmp_alloc_##name(mp) +#define kmp_free(name, mp, p) kmp_free_##name(mp, p) + +#define KLIST_INIT2(SCOPE, name, kltype_t, kmpfree_t) \ + struct __kl1_##name { \ + kltype_t data; \ + struct __kl1_##name *next; \ + }; \ + typedef struct __kl1_##name kl1_##name; \ + KMEMPOOL_INIT2(SCOPE, name, kl1_##name, kmpfree_t) \ + typedef struct { \ + kl1_##name *head, *tail; \ + kmp_##name##_t *mp; \ + size_t size; \ + } kl_##name##_t; \ + SCOPE kl_##name##_t *kl_init_##name(void) { \ + kl_##name##_t *kl = calloc(1, sizeof(kl_##name##_t)); \ + kl->mp = kmp_init(name); \ + kl->head = kl->tail = kmp_alloc(name, kl->mp); \ + kl->head->next = 0; \ + return kl; \ + } \ + SCOPE void kl_destroy_##name(kl_##name##_t *kl) { \ + kl1_##name *p; \ + for (p = kl->head; p != kl->tail; p = p->next) \ + kmp_free(name, kl->mp, p); \ + kmp_free(name, kl->mp, p); \ + kmp_destroy(name, kl->mp); \ + free(kl); \ + } \ + SCOPE kltype_t *kl_pushp_##name(kl_##name##_t *kl) { \ + kl1_##name *q, *p = kmp_alloc(name, kl->mp); \ + q = kl->tail; p->next = 0; kl->tail->next = p; kl->tail = p; \ + ++kl->size; \ + return &q->data; \ + } \ + SCOPE int kl_shift_##name(kl_##name##_t *kl, kltype_t *d) { \ + kl1_##name *p; \ + if (kl->head->next == 0) return -1; \ + --kl->size; \ + p = kl->head; kl->head = kl->head->next; \ + if (d) *d = p->data; \ + kmp_free(name, kl->mp, p); \ + return 0; \ + } + +#define KLIST_INIT(name, kltype_t, kmpfree_t) \ + KLIST_INIT2(static inline klib_unused, name, kltype_t, kmpfree_t) + +#define kliter_t(name) kl1_##name +#define klist_t(name) kl_##name##_t +#define kl_val(iter) ((iter)->data) +#define kl_next(iter) ((iter)->next) +#define kl_begin(kl) ((kl)->head) +#define kl_end(kl) ((kl)->tail) + +#define kl_init(name) kl_init_##name() +#define kl_destroy(name, kl) kl_destroy_##name(kl) +#define kl_pushp(name, kl) kl_pushp_##name(kl) +#define kl_shift(name, kl, d) kl_shift_##name(kl, d) + +#endif diff --git a/chad/kvec.h b/chad/kvec.h new file mode 100644 index 0000000..676be8b --- /dev/null +++ b/chad/kvec.h @@ -0,0 +1,90 @@ +/* The MIT License + + Copyright (c) 2008, by Attractive Chaos <attractor@live.co.uk> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +/* + An example: + +#include "kvec.h" +int main() { + kvec_t(int) array; + kv_init(array); + kv_push(int, array, 10); // append + kv_a(int, array, 20) = 5; // dynamic + kv_A(array, 20) = 4; // static + kv_destroy(array); + return 0; +} +*/ + +/* + 2008-09-22 (0.1.0): + + * The initial version. + +*/ + +#ifndef AC_KVEC_H +#define AC_KVEC_H + +#include <stdlib.h> + +#define kv_roundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) + +#define kvec_t(type) struct { size_t n, m; type *a; } +#define kv_init(v) ((v).n = (v).m = 0, (v).a = 0) +#define kv_destroy(v) free((v).a) +#define kv_A(v, i) ((v).a[(i)]) +#define kv_pop(v) ((v).a[--(v).n]) +#define kv_size(v) ((v).n) +#define kv_max(v) ((v).m) + +#define kv_resize(type, v, s) ((v).m = (s), (v).a = (type*)realloc((v).a, sizeof(type) * (v).m)) + +#define kv_copy(type, v1, v0) do { \ + if ((v1).m < (v0).n) kv_resize(type, v1, (v0).n); \ + (v1).n = (v0).n; \ + memcpy((v1).a, (v0).a, sizeof(type) * (v0).n); \ + } while (0) \ + +#define kv_push(type, v, x) do { \ + if ((v).n == (v).m) { \ + (v).m = (v).m? (v).m<<1 : 2; \ + (v).a = (type*)realloc((v).a, sizeof(type) * (v).m); \ + } \ + (v).a[(v).n++] = (x); \ + } while (0) + +#define kv_pushp(type, v) (((v).n == (v).m)? \ + ((v).m = ((v).m? (v).m<<1 : 2), \ + (v).a = (type*)realloc((v).a, sizeof(type) * (v).m), 0) \ + : 0), ((v).a + ((v).n++)) + +#define kv_a(type, v, i) (((v).m <= (size_t)(i)? \ + ((v).m = (v).n = (i) + 1, kv_roundup32((v).m), \ + (v).a = (type*)realloc((v).a, sizeof(type) * (v).m), 0) \ + : (v).n <= (size_t)(i)? (v).n = (i) + 1 \ + : 0), (v).a[(i)]) + +#endif diff --git a/chad/qx.h b/chad/qx.h new file mode 100644 index 0000000..817eaff --- /dev/null +++ b/chad/qx.h @@ -0,0 +1,36 @@ +#ifndef QX_H +#define QX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* # qx + * + * ## NAME + * qx - execute system commands receive back the output + * + * ## SYNOPSIS + */ +extern char * qx(const char * const cmd); +/* ## DESCRIPTION + * `qx()` is a small wrapper function to replicate Perl's `qx` in C. + * It is intended for developer convenience. + * The command argument is a pointer to a null-terminated + * string containing a shell command line. + * This command is passed to `/bin/sh` using the `-c` flag; interpretation, + * if any, is performed by the shell. + * + * ## RETURN VALUE + * Upon successful return, the captured `stdout` and `stderr` of `cmd` is returned + * in a dynamic string. Calling `free()` is the programmer's responsibility. + * + * If an error is encountered `NULL` is returned. + * The shell returning a non-zero exit value is not considered an error. + */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/chad/remove_all.h b/chad/remove_all.h new file mode 100644 index 0000000..2c218b1 --- /dev/null +++ b/chad/remove_all.h @@ -0,0 +1,11 @@ +#ifndef REMOVE_ALL_H +#define REMOVE_ALL_H + +/* C imitation of `std::filesystem::remove_all()` from C++17. + * Unlike standard C remove(3), it can remove recursively. + */ +int remove_all(const char * const p); + +// The contents of this file are Public Domain. + +#endif diff --git a/chad/sds.h b/chad/sds.h new file mode 100644 index 0000000..7cf552b --- /dev/null +++ b/chad/sds.h @@ -0,0 +1,172 @@ +/* SDSLib 2.3 -- A C dynamic strings library + * + * Copyright (c) 2006-2015, Salvatore Sanfilippo <antirez at gmail dot com> + * Copyright (c) 2015, Oran Agra + * Copyright (c) 2015, Redis Labs, Inc + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Redis nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SDS_H +#define __SDS_H + +#define SDS_MAX_PREALLOC (1024*1024) +extern const char *SDS_NOINIT; + +#include <sys/types.h> +#include <stdarg.h> +#include <stdint.h> + +#ifdef _MSC_VER +#include <BaseTsd.h> +#define ssize_t SSIZE_T + +#define SDS_PACKED_PRE __pragma(pack(push, 1)) +#define SDS_PACKED_ATTR +#define SDS_PACKED_POST __pragma( pack(pop)) +#else // _MSC_VER +#define SDS_PACKED_PRE +#define SDS_PACKED_ATTR __attribute__((__packed__)) +#define SDS_PACKED_POST +#endif // _MSC_VER + +typedef char *sds; + +SDS_PACKED_PRE + +/* Note: sdshdr5 is never used, we just access the flags byte directly. + * However is here to document the layout of type 5 SDS strings. */ +struct SDS_PACKED_ATTR sdshdr5 { + unsigned char flags; /* 3 lsb of type, and 5 msb of string length */ + char buf[]; +}; +struct SDS_PACKED_ATTR sdshdr8 { + uint8_t len; /* used */ + uint8_t alloc; /* excluding the header and null terminator */ + unsigned char flags; /* 3 lsb of type, 5 unused bits */ + char buf[]; +}; +struct SDS_PACKED_ATTR sdshdr16 { + uint16_t len; /* used */ + uint16_t alloc; /* excluding the header and null terminator */ + unsigned char flags; /* 3 lsb of type, 5 unused bits */ + char buf[]; +}; +struct SDS_PACKED_ATTR sdshdr32 { + uint32_t len; /* used */ + uint32_t alloc; /* excluding the header and null terminator */ + unsigned char flags; /* 3 lsb of type, 5 unused bits */ + char buf[]; +}; +struct SDS_PACKED_ATTR sdshdr64 { + uint64_t len; /* used */ + uint64_t alloc; /* excluding the header and null terminator */ + unsigned char flags; /* 3 lsb of type, 5 unused bits */ + char buf[]; +}; + +SDS_PACKED_POST + +#define SDS_TYPE_5 0 +#define SDS_TYPE_8 1 +#define SDS_TYPE_16 2 +#define SDS_TYPE_32 3 +#define SDS_TYPE_64 4 +#define SDS_TYPE_MASK 7 +#define SDS_TYPE_BITS 3 +#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (void*)((s)-(sizeof(struct sdshdr##T))); +#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T)))) +#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS) + +size_t sdslen(const sds s); +size_t sdsavail(const sds s); +void sdssetlen(sds s, size_t newlen); +void sdsinclen(sds s, size_t inc); +size_t sdsalloc(const sds s); +void sdssetalloc(sds s, size_t newlen); + +sds sdsnewlen(const void *init, size_t initlen); +sds sdsnew(const char *init); +sds sdsempty(void); +sds sdsdup(const sds s); +void sdsfree(sds s); +sds sdsgrowzero(sds s, size_t len); +sds sdscatlen(sds s, const void *t, size_t len); +sds sdscat(sds s, const char *t); +sds sdscatsds(sds s, const sds t); +sds sdscpylen(sds s, const char *t, size_t len); +sds sdscpy(sds s, const char *t); + +sds sdscatvprintf(sds s, const char *fmt, va_list ap); +#ifdef __GNUC__ +sds sdscatprintf(sds s, const char *fmt, ...) + __attribute__((format(printf, 2, 3))); +#else +sds sdscatprintf(sds s, const char *fmt, ...); +#endif + +sds sdscatfmt(sds s, char const *fmt, ...); +void sdstrim(sds s, const char *cset); +void sdssubstr(sds s, size_t start, size_t len); +void sdsrange(sds s, ssize_t start, ssize_t end); +void sdsupdatelen(sds s); +void sdsclear(sds s); +int sdscmp(const sds s1, const sds s2); +sds *sdssplitlen(const char *s, ssize_t len, const char *sep, int seplen, int *count); +void sdsfreesplitres(sds *tokens, int count); +void sdstolower(sds s); +void sdstoupper(sds s); +sds sdsfromlonglong(long long value); +sds sdscatrepr(sds s, const char *p, size_t len); +sds *sdssplitargs(const char *line, int *argc); +sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen); +sds sdsjoin(char **argv, int argc, char *sep); +sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen); +int sdsneedsrepr(const sds s); + +/* Low level functions exposed to the user API */ +sds sdsMakeRoomFor(sds s, size_t addlen); +void sdsIncrLen(sds s, ssize_t incr); +sds sdsRemoveFreeSpace(sds s, int would_regrow); +sds sdsResize(sds s, size_t size, int would_regrow); +size_t sdsAllocSize(sds s); +void *sdsAllocPtr(sds s); + +/* Export the allocator used by SDS to the program using SDS. + * Sometimes the program SDS is linked to, may use a different set of + * allocators, but may want to allocate or free things that SDS will + * respectively free or allocate. */ +void *sds_malloc(size_t size); +void *sds_realloc(void *ptr, size_t size); +void sds_free(void *ptr); + +#ifdef REDIS_TEST +int sdsTest(void); +#endif + +#undef inline + +#endif diff --git a/chad/sdsalloc.h b/chad/sdsalloc.h new file mode 100644 index 0000000..2eff946 --- /dev/null +++ b/chad/sdsalloc.h @@ -0,0 +1,47 @@ +/* SDSLib 2.2 -- A C dynamic strings library + * + * Copyright (c) 2006-2015, Salvatore Sanfilippo <antirez at gmail dot com> + * Copyright (c) 2015, Oran Agra + * Copyright (c) 2015, Redis Labs, Inc + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Redis nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* SDS allocator selection. + * + * This file is used in order to change the SDS allocator at compile time. + * Just define the following defines to what you want to use. Also add + * the include of your alternate allocator if needed (not needed in order + * to use the default libc allocator). */ + +#ifndef __SDS_ALLOC_H__ +#define __SDS_ALLOC_H__ + +#define s_malloc malloc +#define s_realloc realloc +#define s_free free + +#endif diff --git a/chad/terry.h b/chad/terry.h new file mode 100644 index 0000000..a1616ec --- /dev/null +++ b/chad/terry.h @@ -0,0 +1,178 @@ +#ifndef TERRY_H +#define TERRY_H + +#if 0 + Promises the most accurate primitives as are allowable by (recent) compiler version and C standard. + Primitivie types: + signed int : i8>i128, s8>s128 + unsigned int : u8>u128 + float : f, f32 + double : fl, f64 + long double : fll, f128 + + NO_128_TYPES will not be defined if i128, s128, u128 exist. + NO_F_TYPE_NAME will remove hazardous declarations of f, fl, and fll. + + all floating bitmarked types will have F<NUM>_PRECISE defined + if they are specified to that precise number of bits. + + Tested to work with gcc 14.2.0 and clang 19.1.7 on Debian + Backwards compat for gcc 14.2.0 + Not robustly tested, please report issues. + + --- Definitions --- + + Defining the following will change behavior within the typesystem. + the IMPRECISE groupings will always be provided with their respective types are present in full. + +#define TERRY_FLOAT_IMPRECISE /* supergroup of the below two groups */ +#define TERRY_SMALL_FLOAT_IMPRECISE /* groups the two below together */ +#define FLOAT_IS_F32 +#define DOUBLE_IS_F64 +#define TERRY_LARGE_FLOAT_IMPRECISE /* groups the two below together */ +#define LONG_DOUBLE_IS_F80 +#define LONG_DOUBLE_IS_F128 +#define NO_128_TYPES /* removes 128 declarations */ +#define NO_F_TYPE_NAME /* removes hazardous f, fl, fll */ +#endif + +/* --- */ + +#include <stdint.h> + +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; + +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +#ifndef NO_F_TYPE_NAME +typedef float f; +typedef double fl; +typedef long double fll; +#endif + +#ifndef NO_128_TYPES +# if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000L && defined(__GNUC__) && !defined(__clang__)) \ + || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) +# define PRECISE_128 + typedef signed _BitInt(128) i128; + typedef signed _BitInt(128) s128; + typedef unsigned _BitInt(128) u128; +# else +# if __SIZEOF_INT128__ /* compiler specific macro */ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpedantic" +# define PRECISE_128 + typedef signed __int128 i128; + typedef signed __int128 s128; + typedef unsigned __int128 u128; +# pragma GCC diagnostic pop +# else +# define NO_128_TYPES +# endif +# endif +#endif + +#if !(defined(__STDC_IEC_60559_BFP__) && defined(__STDC_IEC_60559_TYPES__)) +#define TERRY_FLOAT_IMPRECISE +#endif + +#ifdef TERRY_FLOAT_IMPRECISE +# define TERRY_SMALL_FLOAT_IMPRECISE +# define TERRY_LARGE_FLOAT_IMPRECISE +#endif + +#ifdef TERRY_SMALL_FLOAT_IMPRECISE +# define FLOAT_IS_F32 +# define DOUBLE_IS_F64 +#endif + +#ifdef TERRY_LARGE_FLOAT_IMPRECISE +# define LONG_DOUBLE_IS_F80 +# define LONG_DOUBLE_IS_F128 +#endif + +/* You can treat floats like _Float32, and doubles like _Float64, however *THEY ARE NOT THE SAME THING*. */ +/* go ask WG14 for the "why." GCC/Clang may complain but will work as expected. */ + +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000L && defined(__GNUC__) && !defined(__clang__)) \ +|| (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) +# if defined(FLOAT_IS_F32) || defined(TERRY_SMALL_FLOAT_IMPRECISE) + typedef float f32; +# else +# define F32_PRECISE + typedef _Float32 f32; +# endif + +# if defined(DOUBLE_IS_F64) || defined(TERRY_LARGE_FLOAT_IMPRECISE) + typedef double f64; +# else +# define F64_PRECISE + typedef _Float64 f64; +# endif + +# if defined(__GNUC__) && !defined(__clang__) +# define F80_PRECISE + typedef __float80 f80; +# else + #define LONG_DOUBLE_IS_F80 + typedef long double f80; +# endif + +# if defined(LONG_DOUBLE_IS_F128) || defined(TERRY_LARGE_FLOAT_IMPRECISE) + typedef long double f128; +# else +# define F128_PRECISE + typedef _Float128 f128; +# endif +#else +/* the below f32/64 definitions may behave erratically, as float != f32 && double != f64. + * We're just doing this for the sake of defining something that will *probably* work in most cases. + * Use newer C versions. */ +# if defined(__GNUC__) && !defined(__clang__) +# define TERRY_SMALL_FLOAT_IMPRECISE + +# define FLOAT_IS_F32 + typedef float f32; +# define DOUBLE_IS_F64 + typedef double f64; + +# if defined(LONG_DOUBLE_IS_F80) + typedef long double f80; +# else +# define F80_PRECISE + typedef __float80 f80; +# endif + +# if defined(LONG_DOUBLE_IS_F128) + typedef long double f128; +# else +# define F128_PRECISE + typedef __float128 f128; +# endif +# else +# define TERRY_FLOAT_IMPRECISE +# define TERRY_SMALL_FLOAT_IMPRECISE +# define TERRY_LARGE_FLOAT_IMPRECISE +# define FLOAT_IS_F32 + typedef float f32; +# define DOUBLE_IS_F64 + typedef double f64; + /* Usually 10-bytes with 128-bit alignment */ +# define LONG_DOUBLE_IS_F80 + typedef long double f80; +# define LONG_DOUBLE_IS_F128 + typedef long double f128; +# endif +#endif +#endif |
