From 8fd15220be207f356d5332bfb64ae68def9c4a3a Mon Sep 17 00:00:00 2001 From: Alexey Odinokov Date: Mon, 16 Sep 2024 23:45:08 -0500 Subject: [PATCH 1/4] check generics to avoid issue with different types of args --- examples/c_print_args_alt/main.c | 6 +++--- examples/c_print_args_alt/print_args.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/c_print_args_alt/main.c b/examples/c_print_args_alt/main.c index 9b87969..e9f6625 100644 --- a/examples/c_print_args_alt/main.c +++ b/examples/c_print_args_alt/main.c @@ -41,7 +41,7 @@ enum x { xTwo = 2, xMinusOne = -1, }; -int test_function4_with_enum_args(enum x arg0, enum x arg1, enum x arg2) { +int test_function4_with_enum_args(enum x arg0, enum x arg1, enum x arg2, list_t x) { return 0; } METAC_GSYM_LINK(test_function4_with_enum_args); @@ -76,8 +76,8 @@ int main() { printf("fn returned: %i\n", METAC_WRAP_FN_RES(p_tagmap, my_printf, "%d %d\n", 10, 22)); - 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_enum_args, xOne, xTwo, xMinusOne, *p_list)); + printf("fn returned: %i\n", METAC_WRAP_FN_RES(p_tagmap, test_function4_with_enum_args, 1, 2, -1, *p_list)); metac_tag_map_delete(p_tagmap); return 0; diff --git a/examples/c_print_args_alt/print_args.h b/examples/c_print_args_alt/print_args.h index 223adba..2fda585 100644 --- a/examples/c_print_args_alt/print_args.h +++ b/examples/c_print_args_alt/print_args.h @@ -115,8 +115,8 @@ 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); \ From e2a1f2d255466bc84d591510db5dc8ecae5ba102 Mon Sep 17 00:00:00 2001 From: Alexey Odinokov Date: Tue, 17 Sep 2024 21:33:47 -0500 Subject: [PATCH 2/4] structs work ok --- examples/c_print_args_alt/main.c | 14 +++++++++++--- examples/c_print_args_alt/print_args.h | 2 ++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/examples/c_print_args_alt/main.c b/examples/c_print_args_alt/main.c index e9f6625..bb09aef 100644 --- a/examples/c_print_args_alt/main.c +++ b/examples/c_print_args_alt/main.c @@ -41,11 +41,16 @@ enum x { xTwo = 2, xMinusOne = -1, }; -int test_function4_with_enum_args(enum x arg0, enum x arg1, enum x arg2, list_t x) { +int test_function4_with_enum_args(enum x arg0, enum x arg1, enum x arg2) { return 0; } 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) | @@ -76,8 +81,11 @@ int main() { printf("fn returned: %i\n", METAC_WRAP_FN_RES(p_tagmap, my_printf, "%d %d\n", 10, 22)); - printf("fn returned: %i\n", METAC_WRAP_FN_RES(p_tagmap, test_function4_with_enum_args, xOne, xTwo, xMinusOne, *p_list)); - printf("fn returned: %i\n", METAC_WRAP_FN_RES(p_tagmap, test_function4_with_enum_args, 1, 2, -1, *p_list)); + 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)); + metac_tag_map_delete(p_tagmap); return 0; diff --git a/examples/c_print_args_alt/print_args.h b/examples/c_print_args_alt/print_args.h index 2fda585..85885d0 100644 --- a/examples/c_print_args_alt/print_args.h +++ b/examples/c_print_args_alt/print_args.h @@ -121,6 +121,8 @@ static int _process_unspecified_params( } 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; \ From 5c766c57ae94286abef9d387fa80355080816d8d Mon Sep 17 00:00:00 2001 From: Alexey Odinokov Date: Tue, 17 Sep 2024 23:16:00 -0500 Subject: [PATCH 3/4] va_list works on mac --- examples/c_print_args_alt/main.c | 21 +++++++++- examples/c_print_args_alt/print_args.h | 55 ++++++++++++++++++++------ 2 files changed, 64 insertions(+), 12 deletions(-) diff --git a/examples/c_print_args_alt/main.c b/examples/c_print_args_alt/main.c index bb09aef..a3aeb31 100644 --- a/examples/c_print_args_alt/main.c +++ b/examples/c_print_args_alt/main.c @@ -1,5 +1,6 @@ #include "print_args.h" +#include "metac/backend/va_list_ex.h" #include /*free*/ @@ -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, @@ -68,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)); @@ -86,6 +101,10 @@ int main() { printf("fn returned: %i\n", METAC_WRAP_FN_RES(p_tagmap, test_function4_with_struct_args, *p_list)); + 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)); + ); metac_tag_map_delete(p_tagmap); return 0; diff --git a/examples/c_print_args_alt/print_args.h b/examples/c_print_args_alt/print_args.h index 85885d0..c727962 100644 --- a/examples/c_print_args_alt/print_args.h +++ b/examples/c_print_args_alt/print_args.h @@ -6,7 +6,7 @@ #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, @@ -14,12 +14,10 @@ static int _process_unspecified_params( 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); @@ -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); @@ -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)); \ @@ -133,9 +157,18 @@ 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 dummy; \ + _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; \ From 9cb28a24b9d77bd673edf15554b187d5b4dcbf2f Mon Sep 17 00:00:00 2001 From: Alexey Odinokov Date: Tue, 17 Sep 2024 23:32:00 -0500 Subject: [PATCH 4/4] test another way for linux --- examples/c_print_args_alt/main.c | 3 +++ examples/c_print_args_alt/print_args.h | 13 +++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/examples/c_print_args_alt/main.c b/examples/c_print_args_alt/main.c index a3aeb31..5dd55ff 100644 --- a/examples/c_print_args_alt/main.c +++ b/examples/c_print_args_alt/main.c @@ -101,10 +101,13 @@ int main() { 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; diff --git a/examples/c_print_args_alt/print_args.h b/examples/c_print_args_alt/print_args.h index c727962..fa9b357 100644 --- a/examples/c_print_args_alt/print_args.h +++ b/examples/c_print_args_alt/print_args.h @@ -90,7 +90,16 @@ static void _va_list_cp_to_container(struct va_list_container * dst, va_list src #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 */ \ @@ -106,7 +115,8 @@ static void _va_list_cp_to_container(struct va_list_container * dst, va_list src 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); \ \ @@ -158,7 +168,6 @@ static void _va_list_cp_to_container(struct va_list_container * dst, va_list src } \ } else if (metac_entry_is_va_list_parameter(p_param_entry) != 0) { \ struct va_list_container cntr = {}; \ - va_list dummy; \ _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; \