Skip to content

Commit

Permalink
Support for more arg types (#23)
Browse files Browse the repository at this point in the history
* check generics to avoid issue with different types of args

* structs work ok

* va_list works on mac

* test another way for linux
  • Loading branch information
aodinokov authored Sep 29, 2024
1 parent df96840 commit 958b0e4
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 15 deletions.
32 changes: 31 additions & 1 deletion examples/c_print_args_alt/main.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

#include "print_args.h"
#include "metac/backend/va_list_ex.h"

#include <stdlib.h> /*free*/

Expand Down Expand Up @@ -36,6 +37,11 @@ int my_printf(const char * format, ...) {
}
METAC_GSYM_LINK(my_printf);

int my_vprintf(const char * format, va_list l) {
return vprintf(format, l);
}
METAC_GSYM_LINK(my_vprintf);

enum x {
xOne = 1,
xTwo = 2,
Expand All @@ -46,6 +52,11 @@ int test_function4_with_enum_args(enum x arg0, enum x arg1, enum x arg2) {
}
METAC_GSYM_LINK(test_function4_with_enum_args);

int test_function4_with_struct_args(list_t x) {
return 0;
}
METAC_GSYM_LINK(test_function4_with_struct_args);

metac_tag_map_t * p_tagmap = NULL;
METAC_TAG_MAP_NEW(va_args_tag_map, NULL, {.mask =
METAC_TAG_MAP_ENTRY_CATEGORY_MASK(METAC_TEC_variable) |
Expand All @@ -63,13 +74,22 @@ METAC_TAG_MAP_NEW(va_args_tag_map, NULL, {.mask =
)
METAC_TAG_MAP_ENTRY_END

METAC_TAG_MAP_ENTRY(METAC_GSYM_LINK_ENTRY(my_vprintf))
METAC_TAG_MAP_SET_TAG(0, METAC_TEO_entry, 0, METAC_TAG_MAP_ENTRY_PARAMETER({.n = "format"}),
METAC_ZERO_ENDED_STRING()
)
METAC_TAG_MAP_SET_TAG(0, METAC_TEO_entry, 0, METAC_TAG_MAP_ENTRY_PARAMETER({.n = "l"}),
METAC_FORMAT_BASED_VA_ARG()
)
METAC_TAG_MAP_ENTRY_END

METAC_TAG_MAP_END
//

int main() {
p_tagmap = va_args_tag_map();

printf("fn returned: %i\n", METAC_WRAP_FN_RES(NULL, test_function1_with_args,10, 22));
printf("fn returned: %i\n", METAC_WRAP_FN_RES(NULL, test_function1_with_args, 10, 22));

list_t * p_list = (list_t[]){{.x = 42.42, .p_next = (list_t[]){{ .x = 45.4, .p_next = NULL}}}};
printf("fn returned: %f\n", METAC_WRAP_FN_RES(NULL, test_function3_with_args, p_list));
Expand All @@ -79,6 +99,16 @@ int main() {
printf("fn returned: %i\n", METAC_WRAP_FN_RES(p_tagmap, test_function4_with_enum_args, xOne, xTwo, xMinusOne));
printf("fn returned: %i\n", METAC_WRAP_FN_RES(p_tagmap, test_function4_with_enum_args, 1, 2, -1));

printf("fn returned: %i\n", METAC_WRAP_FN_RES(p_tagmap, test_function4_with_struct_args, *p_list));

#if __linux__
#else
WITH_VA_LIST_CONTAINER(c,
VA_LIST_CONTAINER(c, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
printf("fn returned: %i\n", METAC_WRAP_FN_RES(p_tagmap, my_vprintf, "%d %d %d %d %d %d %d %d %d %d\n", c.parameters));
);
#endif

metac_tag_map_delete(p_tagmap);
return 0;
}
72 changes: 58 additions & 14 deletions examples/c_print_args_alt/print_args.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,18 @@
#include "metac/backend/value.h"
#include "mr.h"

static int _process_unspecified_params(
static int _process_unspecified_params_cntr(
//context
metac_parameter_storage_t * p_param_storage,
metac_value_t * p_val,
metac_entry_t *p_param_entry,
metac_tag_map_t * p_tag_map,
metac_num_t param_id,
// and all params
int n, ...) {
int n,
struct va_list_container * p_cntr) {

metac_recursive_iterator_t * p_iter = metac_new_recursive_iterator(p_val);

struct va_list_container cntr = {};
va_start(cntr.parameters, p_tag_map);

metac_value_t * p = (metac_value_t *)metac_recursive_iterator_next(p_iter); /* value itself */
metac_entry_tag_t * p_tag = metac_tag_map_tag(p_tag_map, p_param_entry);
Expand All @@ -28,7 +26,7 @@ static int _process_unspecified_params(
.type = METAC_RQVST_va_list,
.va_list_param_id = param_id,
.p_return_value = metac_parameter_storage_new_param_value(p_param_storage, param_id),
.p_va_list_container = &cntr,
.p_va_list_container = p_cntr,
};
if (ev.p_return_value == NULL) {
metac_recursive_iterator_fail(p_iter);
Expand All @@ -42,14 +40,40 @@ static int _process_unspecified_params(
metac_recursive_iterator_fail(p_iter);
}

va_end(cntr.parameters);

int failed = 0;
metac_recursive_iterator_get_out(p_iter, NULL, &failed);
metac_recursive_iterator_free(p_iter);
return failed;
}

static int _process_unspecified_params(
//context
metac_parameter_storage_t * p_param_storage,
metac_value_t * p_val,
metac_entry_t *p_param_entry,
metac_tag_map_t * p_tag_map,
metac_num_t param_id,
// and all params
int n, ...) {
struct va_list_container cntr = {};
va_start(cntr.parameters, p_tag_map);

int failed = _process_unspecified_params_cntr(
p_param_storage,
p_val,
p_param_entry,
p_tag_map,
param_id,
n, &cntr);

va_end(cntr.parameters);
return failed;
}

static void _va_list_cp_to_container(struct va_list_container * dst, va_list src) {
va_copy(dst->parameters, src);
}

#define _process_bt_(arg, _type_, _pseudoname_, _short_type_name_) \
if (strcmp(param_base_type_name, #_pseudoname_) == 0 && param_entry_byte_size == sizeof(_type_)) { \
metac_value_set_##_short_type_name_(p_param_value, *((_type_*)arg)); \
Expand All @@ -66,7 +90,16 @@ static int _process_unspecified_params(
#define _QSTRING_ARG(_args) \
_QSTRING(_args)

// #if __linux__
// #define _init_x_val(arg) \
// typeof(arg) _x_val = _Generic(arg, va_list: dummy, default: arg);
// #else
#define _init_x_val(arg) \
typeof(arg) _x_val = arg;
//#endif

#define _APPEND_PARAM(_NEXT_, _N_, args...) if (failure == 0) { \
va_list dummy; \
metac_entry_t *p_param_entry = metac_entry_by_paremeter_id(p_val_entry, param_id); \
if (metac_entry_is_unspecified_parameter(p_param_entry) == 0 && metac_entry_is_va_list_parameter(p_param_entry) == 0) { \
/* normal argument */ \
Expand All @@ -82,7 +115,8 @@ static int _process_unspecified_params(
failure = 2; \
break; \
} \
typeof(MR_FIRST(args)) _x_val = MR_FIRST(args); \
/*typeof(MR_FIRST(args)) _x_val = _Generic(MR_FIRST(args), char*:MR_FIRST(args), default: MR_FIRST(args)); */ \
_init_x_val(MR_FIRST(args)) \
if (metac_parameter_storage_append_by_buffer(p_param_storage, p_param_entry, param_entry_byte_size) == 0) { \
metac_value_t * p_param_value = metac_parameter_storage_new_param_value(p_param_storage, param_id); \
\
Expand Down Expand Up @@ -115,12 +149,14 @@ static int _process_unspecified_params(
/* ensure arg isn't string constant */ \
char _s_arg[] = _QSTRING_ARG(MR_FIRST(args)); \
if (_s_arg[0] == '\"') { \
/* TODO: can't handle structs, va_list as arguments because of this line */ \
char * s = ((char*)MR_FIRST(args)); \
/* can't handle structs, va_list as arguments because of this line */ \
char * s = ((char*)_Generic(MR_FIRST(args), char*: MR_FIRST(args), default: NULL)); \
memcpy(metac_value_addr(p_param_value), &s, param_entry_byte_size); \
} else { \
memcpy(metac_value_addr(p_param_value), &_x_val, param_entry_byte_size); \
} \
} else if (metac_entry_has_members(p_param_type_entry) != 0) { \
memcpy(metac_value_addr(p_param_value), &_x_val, param_entry_byte_size); \
} else { \
/* not supported */ \
failure = 3; \
Expand All @@ -131,9 +167,17 @@ static int _process_unspecified_params(
metac_value_delete(p_param_value); \
} \
} else if (metac_entry_is_va_list_parameter(p_param_entry) != 0) { \
/* not supported */ \
failure = 4; \
break; \
struct va_list_container cntr = {}; \
_va_list_cp_to_container(&cntr, _Generic(MR_FIRST(args), va_list: MR_FIRST(args), default: dummy)); \
if (metac_parameter_storage_append_by_parameter_storage(p_param_storage, p_param_entry) != 0) { \
failure = 5; \
break; \
} \
if (_process_unspecified_params_cntr(p_param_storage, p_val, p_param_entry, p_tag_map, param_id, _N_ , &cntr) != 0) { \
failure = 6; \
break; \
} \
va_end(cntr.parameters); \
} else if (metac_entry_is_unspecified_parameter(p_param_entry) != 0) { \
if (metac_parameter_storage_append_by_parameter_storage(p_param_storage, p_param_entry) != 0) { \
failure = 5; \
Expand Down

0 comments on commit 958b0e4

Please sign in to comment.