Parser tests: Make LIST_* macros type safe
With the varargs approach that was used before, it was very easy to add a list item of the wrong type, which would (hopefully) result in an assertion violation, because va_arg() then read some senseless data.
This commit is contained in:
parent
5712d7f4ff
commit
3759813ed9
1 changed files with 14 additions and 21 deletions
|
|
@ -1,5 +1,4 @@
|
|||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "apfl.h"
|
||||
#include "resizable.h"
|
||||
|
|
@ -125,48 +124,42 @@ enum listbuilder_cmd {
|
|||
};
|
||||
|
||||
#define LISTBUILDER_NAME(n) listbuilder_##n
|
||||
#define LISTBUILDER_ITEM_NAME(n) listbuilder_item_##n
|
||||
#define MKLISTBUILDER(name, listtype, itemtype, items_memb, len_memb) \
|
||||
struct LISTBUILDER_ITEM_NAME(name) { \
|
||||
bool has_item; \
|
||||
itemtype item; \
|
||||
}; \
|
||||
listtype \
|
||||
LISTBUILDER_NAME(name)(struct parser_test *pt, ...) \
|
||||
{ \
|
||||
LISTBUILDER_NAME(name)( \
|
||||
struct parser_test *pt, \
|
||||
struct LISTBUILDER_ITEM_NAME(name) items[] \
|
||||
) { \
|
||||
listtype body; \
|
||||
size_t cap = 0; \
|
||||
\
|
||||
apfl_resizable_init((void **)&body.items_memb, &body.len_memb, &cap); \
|
||||
\
|
||||
va_list ap; \
|
||||
va_start(ap, pt); \
|
||||
\
|
||||
for (;;) { \
|
||||
enum listbuilder_cmd cmd = va_arg(ap, enum listbuilder_cmd); \
|
||||
if (cmd == LISTBUILDER_STOP) { \
|
||||
break; \
|
||||
} \
|
||||
assert(cmd == LISTBUILDER_ADD); \
|
||||
itemtype item = va_arg(ap, itemtype); \
|
||||
\
|
||||
for (items++; items->has_item; items++) { \
|
||||
if (!apfl_resizable_append( \
|
||||
sizeof(itemtype), \
|
||||
(void **)&body.items_memb, \
|
||||
&body.len, \
|
||||
&cap, \
|
||||
&item, \
|
||||
&items->item, \
|
||||
1 \
|
||||
)) { \
|
||||
va_end(ap); \
|
||||
test_fatalf(pt->t, "Failed appending"); \
|
||||
assert(false); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
va_end(ap); \
|
||||
\
|
||||
return body; \
|
||||
} \
|
||||
|
||||
#define LIST_BEGIN(pt, builder) (LISTBUILDER_NAME(builder)(pt,
|
||||
#define LIST_END LISTBUILDER_STOP))
|
||||
#define LIST_ADD LISTBUILDER_ADD,
|
||||
#define LIST_BEGIN(pt, builder) (LISTBUILDER_NAME(builder)(pt, (struct LISTBUILDER_ITEM_NAME(builder)[]) {{.has_item=false
|
||||
#define LIST_END }, {.has_item = false}}))
|
||||
#define LIST_ADD }, {.has_item = true, .item =
|
||||
|
||||
MKLISTBUILDER(list, struct apfl_expr_list, struct apfl_expr_list_item, items, len)
|
||||
MKLISTBUILDER(body, struct apfl_expr_body, struct apfl_expr, items, len)
|
||||
|
|
|
|||
Loading…
Reference in a new issue