On 2019-05-12, Markus Wichmann <nullp...@gmx.net> wrote: > On Sat, May 11, 2019 at 08:52:32PM +0100, Piotr Oleskiewicz wrote: >> I would prefer to >> write >> >> X(int, i, 1) >> >> rather than >> >> X(int, i, atoi, "%d", 1) >> >> Many thanks, >> Piotr >> > > That is going to be tough, as in C in a macro, there is no way to really > determine what type name you were given. The only thing standard C has > to offer to help is "sizeof", but that doesn't help you, obviously. > (sizeof(float) == sizeof(int)).
What about _Generic in C11? This allows you to choose an expression based on the type of another expression. So I think something like the following should work: diff --git a/kv.h b/kv.h index 4a0be52..57facce 100644 --- a/kv.h +++ b/kv.h @@ -23,7 +23,7 @@ atoc(char *str) { return strlen(str) > 0 ? str[0] : '\0'; } -#define X(type, name, parse, format, init) \ +#define X(type, name, init) \ type name; typedef struct { KV @@ -33,7 +33,7 @@ typedef struct { kv kv_init() { kv c; -#define X(type, name, parse, format, init) \ +#define X(type, name, init) \ c.name = init; KV #undef X @@ -42,8 +42,13 @@ kv_init() { void kv_print(FILE *f, kv c) { -#define X(type, name, parse, format, init) \ - fprintf(f, "%s = "format"\n", #name, c.name); +#define X(type, name, init) \ + fprintf(f, _Generic((type){0}, \ + char *: "%s = %s\n", \ + double: "%s = %f\n", \ + int: "%s = %d\n", \ + bool: "%s = %d\n" \ + ), #name, c.name); KV #undef X } @@ -51,9 +56,14 @@ kv_print(FILE *f, kv c) { void kv_read(FILE *f, kv *c) { char k[MAXLEN], v[MAXLEN]; -#define X(type, name, parse, format, init) \ +#define X(type, name, init) \ if(strncmp(k, #name, MAX(strlen(k), strlen(#name))) == 0) \ - c->name = parse(v); + c->name = _Generic((type){0}, \ + char *: strdup, \ + double: atof, \ + int: atoi, \ + bool: atob \ + )(v); while(fscanf(f, "%s = %s\n", k, v) == 2) { KV }