aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmil Williams2026-02-18 00:56:45 +0000
committerEmil Williams2026-02-18 01:02:35 +0000
commit2b39c39421648cdd65987934e5432d5a12d097b0 (patch)
tree136c7415cfe1cc268ffbd36f0f6a5ea60bcdfd4f
parent42541df62871aaf403c0d62de1fdb44c862f2ea5 (diff)
downloadlibchad-2b39c39421648cdd65987934e5432d5a12d097b0.tar.xz
libchad-2b39c39421648cdd65987934e5432d5a12d097b0.tar.zst
should work without peru
-rw-r--r--Makefile3
-rw-r--r--chad.h8
-rw-r--r--chad/dictate.h371
-rw-r--r--chad/experimental/bits.h2
-rw-r--r--chad/qx.h36
-rw-r--r--chad/remove_all.h11
-rw-r--r--chad/sds.h172
-rw-r--r--chad/sdsalloc.h47
-rw-r--r--test/test.c5
9 files changed, 649 insertions, 6 deletions
diff --git a/Makefile b/Makefile
index e6d9d5d..b07c89c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,8 @@
+CFLAGS := -std=c23
SOURCE := $(wildcard chad/*.c extern/*.c)
so:
- ${CC} -fPIC -shared ${SOURCE} -o object/libchad.so
+ ${CC} ${CFLAGS} -fPIC -shared ${SOURCE} -o object/libchad.so
dist:
-mkdir object/chad/ 2> /dev/null
diff --git a/chad.h b/chad.h
index 4595c66..4ac39ac 100644
--- a/chad.h
+++ b/chad.h
@@ -1,16 +1,16 @@
#ifndef CHAD_H
#define CHAD_H
// internal code
-#include "chad/bits.h"
-#include "chad/terminal.h"
+#include "chad/experimental/bits.h"
+#include "chad/experimental/terminal.h"
#include "chad/dictate.h"
#include "chad/qx.h"
#include "chad/terry.h"
// external code
#include "chad/sds.h"
-#include "chad/kvec.h"
-#include "chad/klist.h"
+//#include "chad/kvec.h"
+//#include "chad/klist.h"
#include "chad/remove_all.h"
#endif
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/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/test/test.c b/test/test.c
new file mode 100644
index 0000000..8dd4996
--- /dev/null
+++ b/test/test.c
@@ -0,0 +1,5 @@
+// @BAKE @CC -std=c23 ../object/libchad.so
+#include "../chad.h"
+int main () {
+ dictate ( "cogito ergo sum\n" );
+}