aboutsummaryrefslogtreecommitdiff
path: root/src/stdlib/print.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-03-27 17:26:51 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-03-27 17:26:51 -0400
commit3c52a756339a2d96824d21a7d3ad5de7fc1085a0 (patch)
treee5299a25ebb76186d6372b700710d7c8c7fe0728 /src/stdlib/print.c
parent2186e84de0c0fd47ba48eaa35f74ea2754c3b81f (diff)
Deprecate custom printf specifiers in favor of print() function that
uses _Generic() to generically convert any value to a string or print as a string.
Diffstat (limited to 'src/stdlib/print.c')
-rw-r--r--src/stdlib/print.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/src/stdlib/print.c b/src/stdlib/print.c
new file mode 100644
index 00000000..023af986
--- /dev/null
+++ b/src/stdlib/print.c
@@ -0,0 +1,76 @@
+// This file defines some of the helper functions used for printing values
+#include "print.h"
+
+#include <stdio.h>
+
+int _print_char(FILE *f, char c)
+{
+#if PRINT_COLOR
+#define ESC(e) "\033[35m'\033[34;1m\\" e "\033[0;35m'\033[m"
+#else
+#define ESC(e) "'\\" e "'"
+#endif
+ const char *named[256] = {['\n']=ESC("n"), ['\t']=ESC("t"), ['\r']=ESC("r"),
+ ['\033']=ESC("e"), ['\v']=ESC("v"), ['\a']=ESC("a"), ['\b']=ESC("b")};
+ const char *name = named[(uint8_t)c];
+ if (name != NULL)
+ return fputs(name, f);
+ else if (isprint(c))
+#if PRINT_COLOR
+ return fprintf(f, "\033[35m'%c'\033[m"), c);
+#else
+ return fprintf(f, "'%c'", c);
+#endif
+ else
+ return fprintf(f, ESC("x%02X"), (uint8_t)c);
+#undef ESC
+}
+
+int _print_quoted(FILE *f, quoted_t quoted)
+{
+#if PRINT_COLOR
+#define ESC(e) "\033[34;1m\\" e "\033[0;35m"
+#else
+#define ESC(e) "\\" e
+#endif
+ const char *named[256] = {['\n']=ESC("n"), ['\t']=ESC("t"), ['\r']=ESC("r"),
+ ['\033']=ESC("e"), ['\v']=ESC("v"), ['\a']=ESC("a"), ['\b']=ESC("b")};
+ int printed = fputs("\033[35m\"", f);
+ for (const char *p = quoted.str; *p; p++) {
+ const char *name = named[(uint8_t)*p];
+ if (name != NULL) {
+ printed += fputs(name, f);
+ } else if (isprint(*p) || (uint8_t)*p > 0x7F) {
+ printed += fputc(*p, f);
+ } else {
+ printed += fprintf(f, ESC("x%02X"), (uint8_t)*p);
+ }
+ }
+ printed += fputs("\"\033[m", f);
+#undef ESC
+ return printed;
+}
+
+static ssize_t _gc_stream_write(void *cookie, const char *buf, size_t size) {
+ gc_stream_t *stream = (gc_stream_t *)cookie;
+ if (stream->position + size + 1 > *stream->size)
+ *stream->buffer = GC_REALLOC(*stream->buffer, (*stream->size += MAX(MAX(16, *stream->size/2), size + 1)));
+ memcpy(&(*stream->buffer)[stream->position], buf, size);
+ stream->position += size;
+ (*stream->buffer)[stream->position] = '\0';
+ return (ssize_t)size;
+}
+
+FILE *gc_memory_stream(char **buf, size_t *size) {
+ gc_stream_t *stream = GC_MALLOC(sizeof(gc_stream_t));
+ stream->size = size;
+ stream->buffer = buf;
+ *stream->size = 16;
+ *stream->buffer = GC_MALLOC_ATOMIC(*stream->size);
+ (*stream->buffer)[0] = '\0';
+ stream->position = 0;
+ cookie_io_functions_t functions = {.write = _gc_stream_write};
+ return fopencookie(stream, "w", functions);
+}
+
+// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0