Skip to content

Commit 02bef28

Browse files
committed
Add _Generic() support
1 parent 0fdf4ba commit 02bef28

File tree

6 files changed

+487
-40
lines changed

6 files changed

+487
-40
lines changed

.clang-format

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ BreakConstructorInitializersBeforeComma: false
5757
BreakConstructorInitializers: BeforeComma
5858
BreakAfterJavaFieldAnnotations: false
5959
BreakStringLiterals: false
60-
ColumnLimit: 114514
60+
ColumnLimit: 114
6161
CommentPragmas: '^ IWYU pragma:'
6262
CompactNamespaces: false
6363
ConstructorInitializerAllOnOneLineOrOnePerLine: false

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ all :
88
format :
99
clang-format -i include/cprintf.h cprintf.c test.c main.c
1010
test :
11-
$(CC) -O0 -ggdb -fsanitize=address cprintf.c test.c
11+
$(CC) -O0 -Wall -Wextra -Wgnu -std=c23 -pedantic -ggdb -fsanitize=address cprintf.c test.c

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
# New in v2.0:
2+
Say hello to `T()` `F()` macro with _Generic() support!
3+
Usage:
4+
```C
5+
int i = 0;
6+
cprintf("{}\n", T(i)); // Equal to printf("%d\n", i);
7+
cprintf("{}\n", F(i,"06")); // Equal to printf("%06d\n", i);
8+
```
9+
And, now we have `csprintf()`, it supports T() F() but don't support color.
10+
On linux, cprintf() and cfprintf() will auto disable color when output to a pipe.
111
# Let's make a colorful world!
212
# What's this?
313
We often use ASCII color like `\033[0m` when developing. But it's hard to remember them.

cprintf.c

Lines changed: 290 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,294 @@
2828
*
2929
*/
3030
#include "include/cprintf.h"
31+
#define cprintf_strlen(f) (f == NULL ? 0 : strlen(f))
32+
#define cprintf_avoid_null(f) (f == NULL ? "" : f)
33+
#define cprintf_buf_len(f, d) (f != NULL ? (size_t)snprintf(NULL, 0, f, d) : 0)
34+
static char **cprintf_buffer = NULL;
35+
static size_t cprintf_buf_count = 0;
36+
static void cprintf_mark_buf(char *b)
37+
{
38+
cprintf_buffer = realloc(cprintf_buffer, (cprintf_buf_count + 1) * sizeof(char *));
39+
cprintf_buffer[cprintf_buf_count] = b;
40+
cprintf_buf_count++;
41+
}
42+
void cprintf_free_buf(void)
43+
{
44+
for (size_t i = 0; i < cprintf_buf_count; i++) {
45+
free(cprintf_buffer[i]);
46+
}
47+
free(cprintf_buffer);
48+
cprintf_buffer = NULL;
49+
cprintf_buf_count = 0;
50+
}
51+
char *cprintf_regen_format(const char *f)
52+
{
53+
char *ret = strdup(cprintf_avoid_null(f));
54+
int j = 0;
55+
size_t len = cprintf_strlen(f);
56+
if (len == 0) {
57+
cprintf_mark_buf(ret);
58+
return ret;
59+
}
60+
for (size_t i = 0; i < len - 1; i++) {
61+
if (f[i] == '{' && f[i + 1] == '}') {
62+
ret[j] = '%';
63+
ret[j + 1] = 's';
64+
j += 2;
65+
i++;
66+
} else {
67+
ret[j] = f[i];
68+
j++;
69+
}
70+
}
71+
ret[j] = '\0';
72+
if (f[len - 1] != '}') {
73+
ret[j] = f[len - 1];
74+
ret[j + 1] = '\0';
75+
}
76+
cprintf_mark_buf(ret);
77+
return ret;
78+
}
79+
char *cprintf_get_fmt_unknown(const char *f)
80+
{
81+
(void)f; // Unused parameter
82+
return NULL;
83+
}
84+
char *cprintf_get_fmt_bool(const char *f)
85+
{
86+
(void)f; // Unused parameter
87+
return NULL;
88+
}
89+
char *cprintf_get_fmt_char(const char *f)
90+
{
91+
char *b = malloc(cprintf_strlen(f) + 16);
92+
sprintf(b, "%%%sc", cprintf_avoid_null(f));
93+
return b;
94+
}
95+
char *cprintf_get_fmt_schar(const char *f)
96+
{
97+
char *b = malloc(cprintf_strlen(f) + 16);
98+
sprintf(b, "%%%sd", cprintf_avoid_null(f));
99+
return b;
100+
}
101+
char *cprintf_get_fmt_uchar(const char *f)
102+
{
103+
char *b = malloc(cprintf_strlen(f) + 16);
104+
sprintf(b, "%%%sd", cprintf_avoid_null(f));
105+
return b;
106+
}
107+
char *cprintf_get_fmt_short(const char *f)
108+
{
109+
char *b = malloc(cprintf_strlen(f) + 16);
110+
sprintf(b, "%%%shd", cprintf_avoid_null(f));
111+
return b;
112+
}
113+
char *cprintf_get_fmt_ushort(const char *f)
114+
{
115+
char *b = malloc(cprintf_strlen(f) + 16);
116+
sprintf(b, "%%%shu", cprintf_avoid_null(f));
117+
return b;
118+
}
119+
char *cprintf_get_fmt_int(const char *f)
120+
{
121+
char *b = malloc(cprintf_strlen(f) + 16);
122+
sprintf(b, "%%%sd", cprintf_avoid_null(f));
123+
return b;
124+
}
125+
char *cprintf_get_fmt_uint(const char *f)
126+
{
127+
char *b = malloc(cprintf_strlen(f) + 16);
128+
sprintf(b, "%%%su", cprintf_avoid_null(f));
129+
return b;
130+
}
131+
char *cprintf_get_fmt_long(const char *f)
132+
{
133+
char *b = malloc(cprintf_strlen(f) + 16);
134+
sprintf(b, "%%%sld", cprintf_avoid_null(f));
135+
return b;
136+
}
137+
char *cprintf_get_fmt_ulong(const char *f)
138+
{
139+
char *b = malloc(cprintf_strlen(f) + 16);
140+
sprintf(b, "%%%slu", cprintf_avoid_null(f));
141+
return b;
142+
}
143+
char *cprintf_get_fmt_llong(const char *f)
144+
{
145+
char *b = malloc(cprintf_strlen(f) + 16);
146+
sprintf(b, "%%%slld", cprintf_avoid_null(f));
147+
return b;
148+
}
149+
char *cprintf_get_fmt_ullong(const char *f)
150+
{
151+
char *b = malloc(cprintf_strlen(f) + 16);
152+
sprintf(b, "%%%sllu", cprintf_avoid_null(f));
153+
return b;
154+
}
155+
char *cprintf_get_fmt_float(const char *f)
156+
{
157+
char *b = malloc(cprintf_strlen(f) + 16);
158+
sprintf(b, "%%%sf", cprintf_avoid_null(f));
159+
return b;
160+
}
161+
char *cprintf_get_fmt_double(const char *f)
162+
{
163+
char *b = malloc(cprintf_strlen(f) + 16);
164+
sprintf(b, "%%%sf", cprintf_avoid_null(f));
165+
return b;
166+
}
167+
char *cprintf_get_fmt_ldouble(const char *f)
168+
{
169+
char *b = malloc(cprintf_strlen(f) + 16);
170+
sprintf(b, "%%%sLf", cprintf_avoid_null(f));
171+
return b;
172+
}
173+
char *cprintf_get_fmt_ptr(const char *f)
174+
{
175+
char *b = malloc(cprintf_strlen(f) + 16);
176+
sprintf(b, "%%%sp", cprintf_avoid_null(f));
177+
return b;
178+
}
179+
180+
char *cprintf_get_string_bool(char *f, bool d)
181+
{
182+
char *buf = malloc(32);
183+
sprintf(buf, "%s", d ? "true" : "false");
184+
free(f);
185+
cprintf_mark_buf(buf);
186+
return buf;
187+
}
188+
char *cprintf_get_string_char(char *f, char d)
189+
{
190+
char *buf = malloc(cprintf_buf_len(f, d) + 32);
191+
sprintf(buf, f, d);
192+
free(f);
193+
cprintf_mark_buf(buf);
194+
return buf;
195+
}
196+
char *cprintf_get_string_schar(char *f, signed char d)
197+
{
198+
char *buf = malloc(cprintf_buf_len(f, d) + 32);
199+
sprintf(buf, f, d);
200+
free(f);
201+
cprintf_mark_buf(buf);
202+
return buf;
203+
}
204+
char *cprintf_get_string_uchar(char *f, unsigned char d)
205+
{
206+
char *buf = malloc(cprintf_buf_len(f, d) + 32);
207+
sprintf(buf, f, d);
208+
free(f);
209+
cprintf_mark_buf(buf);
210+
return buf;
211+
}
212+
char *cprintf_get_string_short(char *f, short d)
213+
{
214+
char *buf = malloc(cprintf_buf_len(f, d) + 32);
215+
sprintf(buf, f, d);
216+
free(f);
217+
cprintf_mark_buf(buf);
218+
return buf;
219+
}
220+
char *cprintf_get_string_ushort(char *f, unsigned short d)
221+
{
222+
char *buf = malloc(cprintf_buf_len(f, d) + 32);
223+
sprintf(buf, f, d);
224+
free(f);
225+
cprintf_mark_buf(buf);
226+
return buf;
227+
}
228+
char *cprintf_get_string_int(char *f, int d)
229+
{
230+
char *buf = malloc(cprintf_buf_len(f, d) + 32);
231+
sprintf(buf, f, d);
232+
free(f);
233+
cprintf_mark_buf(buf);
234+
return buf;
235+
}
236+
char *cprintf_get_string_uint(char *f, unsigned int d)
237+
{
238+
char *buf = malloc(cprintf_buf_len(f, d) + 32);
239+
sprintf(buf, f, d);
240+
free(f);
241+
cprintf_mark_buf(buf);
242+
return buf;
243+
}
244+
char *cprintf_get_string_long(char *f, long d)
245+
{
246+
char *buf = malloc(cprintf_buf_len(f, d) + 32);
247+
sprintf(buf, f, d);
248+
free(f);
249+
cprintf_mark_buf(buf);
250+
return buf;
251+
}
252+
char *cprintf_get_string_ulong(char *f, unsigned long d)
253+
{
254+
char *buf = malloc(cprintf_buf_len(f, d) + 32);
255+
sprintf(buf, f, d);
256+
free(f);
257+
cprintf_mark_buf(buf);
258+
return buf;
259+
}
260+
char *cprintf_get_string_llong(char *f, long long d)
261+
{
262+
char *buf = malloc(cprintf_buf_len(f, d) + 32);
263+
sprintf(buf, f, d);
264+
free(f);
265+
cprintf_mark_buf(buf);
266+
return buf;
267+
}
268+
char *cprintf_get_string_ullong(char *f, unsigned long long d)
269+
{
270+
char *buf = malloc(cprintf_buf_len(f, d) + 32);
271+
sprintf(buf, f, d);
272+
free(f);
273+
cprintf_mark_buf(buf);
274+
return buf;
275+
}
276+
char *cprintf_get_string_float(char *f, float d)
277+
{
278+
char *buf = malloc(cprintf_buf_len(f, d) + 32);
279+
sprintf(buf, f, d);
280+
free(f);
281+
cprintf_mark_buf(buf);
282+
return buf;
283+
}
284+
char *cprintf_get_string_double(char *f, double d)
285+
{
286+
char *buf = malloc(cprintf_buf_len(f, d) + 32);
287+
sprintf(buf, f, d);
288+
free(f);
289+
cprintf_mark_buf(buf);
290+
return buf;
291+
}
292+
char *cprintf_get_string_ldouble(char *f, long double d)
293+
{
294+
char *buf = malloc(cprintf_buf_len(f, d) + 32);
295+
sprintf(buf, f, d);
296+
free(f);
297+
cprintf_mark_buf(buf);
298+
return buf;
299+
}
300+
char *cprintf_get_string_ptr(char *f, void *d)
301+
{
302+
char *buf = malloc(cprintf_buf_len(f, d) + 32);
303+
sprintf(buf, f, d);
304+
free(f);
305+
cprintf_mark_buf(buf);
306+
return buf;
307+
}
308+
char *cprintf_get_string_unknown(char *f, ...)
309+
{
310+
char *buf = malloc(32);
311+
sprintf(buf, "%s", "{unknown type}");
312+
free(f);
313+
cprintf_mark_buf(buf);
314+
return buf;
315+
}
31316
char *cprintf_base_color = "254;228;208";
32317
bool cprintf_print_color_if_not_fifo = true;
318+
#ifdef _GNU_SOURCE
33319
#define fprintf_if_not_fifo(stream, ...) \
34320
{ \
35321
if (!cprintf_print_color_if_not_fifo) { \
@@ -41,6 +327,9 @@ bool cprintf_print_color_if_not_fifo = true;
41327
} \
42328
} \
43329
}
330+
#else
331+
#define fprintf_if_not_fifo(stream, ...) fprintf(stream, __VA_ARGS__)
332+
#endif
44333
static void fprint_rgb_fg_color(FILE *_Nonnull stream, const char *_Nonnull color)
45334
{
46335
/*
@@ -223,7 +512,7 @@ void cprintf__(const char *_Nonnull buf)
223512
p = &(p[1]);
224513
}
225514
// We will always reset the color in the end.
226-
printf("\033[0m");
515+
fprintf_if_not_fifo(stdout, "\033[0m");
227516
fflush(stdout);
228517
}
229518
void cfprintf__(FILE *_Nonnull stream, const char *_Nonnull buf)

0 commit comments

Comments
 (0)