1 // This file defines some functions to make it easy to do formatted text
2 // without using printf style specifiers:
4 // print(...) - print text
5 // fprint(file, ...) - print text to file
6 // print_err(...) - print an error message and exit with EXIT_FAILURE
7 // String(...) - return an allocated string
18 #include <sys/param.h>
21 #include "datatypes.h"
24 // GCC lets you define macro-like functions which are always inlined and never
25 // compiled using this combination of flags. See: https://gcc.gnu.org/onlinedocs/gcc/Inline.html
28 #define PRINT_FN static inline __attribute__((gnu_inline, always_inline)) int
30 #define PRINT_FN extern inline __attribute__((gnu_inline, always_inline)) int
40 #define hex(x, ...) ((hex_format_t){.n = x, __VA_ARGS__})
45 #define hex_double(x, ...) ((hex_double_t){.d = x, __VA_ARGS__})
52 #define oct(x, ...) ((oct_format_t){.n = x, __VA_ARGS__})
57 #define quoted(s) ((quoted_t){s})
63 #define string_slice(...) ((string_slice_t){__VA_ARGS__})
69 #define repeated_char(ch, len) ((repeated_char_t){.c = ch, .length = len})
71 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
77 int _print_int(FILE *f, int64_t x);
78 int _print_uint(FILE *f, uint64_t x);
79 int _print_double(FILE *f, double x);
80 int _print_hex(FILE *f, hex_format_t hex);
81 int _print_hex_double(FILE *f, hex_double_t hex);
82 int _print_oct(FILE *f, oct_format_t oct);
83 PRINT_FN _print_float(FILE *f, float x) {
84 return _print_double(f, (double)x);
86 PRINT_FN _print_pointer(FILE *f, void *p) {
87 return _print_hex(f, hex((uint64_t)p));
89 PRINT_FN _print_bool(FILE *f, bool b) {
90 return fputs(b ? "yes" : "no", f);
92 PRINT_FN _print_str(FILE *f, const char *s) {
93 return fputs(s ? s : "(null)", f);
95 int _print_char(FILE *f, char c);
96 int _print_quoted(FILE *f, quoted_t quoted);
97 PRINT_FN _print_string_slice(FILE *f, string_slice_t slice) {
98 return slice.str ? fwrite(slice.str, 1, slice.length, f) : (size_t)fputs("(null)", f);
100 PRINT_FN _print_repeated_char(FILE *f, repeated_char_t repeated) {
102 for (int n = 0; n < repeated.length; n++)
103 len += fputc(repeated.c, f);
107 extern int Text$print(FILE *stream, Text_t text);
108 extern int Int$print(FILE *f, Int_t i);
110 #define _fprint1(f, x) \
112 char *: _print_str, \
113 const char *: _print_str, \
116 int64_t: _print_int, \
117 int32_t: _print_int, \
118 int16_t: _print_int, \
119 int8_t: _print_int, \
120 uint64_t: _print_uint, \
121 uint32_t: _print_uint, \
122 uint16_t: _print_uint, \
123 uint8_t: _print_uint, \
124 float: _print_float, \
125 double: _print_double, \
126 hex_format_t: _print_hex, \
127 hex_double_t: _print_hex_double, \
128 oct_format_t: _print_oct, \
129 quoted_t: _print_quoted, \
130 string_slice_t: _print_string_slice, \
131 repeated_char_t: _print_repeated_char, \
132 Text_t: Text$print, \
134 void *: _print_pointer)(f, x)
143 FILE *gc_memory_stream(char **buf, size_t *size);
145 #define _print(x) _n += _fprint1(_printing, x)
146 #define _fprint(f, ...) \
148 FILE *_printing = f; \
150 MAP_LIST(_print, __VA_ARGS__); \
153 #define fprint(f, ...) _fprint(f, __VA_ARGS__, "\n")
154 #define print(...) fprint(stdout, __VA_ARGS__)
155 #define fprint_inline(f, ...) _fprint(f, __VA_ARGS__)
156 #define print_inline(...) fprint_inline(stdout, __VA_ARGS__)
157 #define String(...) \
161 FILE *_stream = gc_memory_stream(&_buf, &_size); \
163 _fprint(_stream, __VA_ARGS__); \
167 #define print_err(...) \
169 fprint(stderr, "\033[31;1m", __VA_ARGS__, "\033[m"); \
170 exit(EXIT_FAILURE); \