diff --git a/examples/c_print_args_alt/main.c b/examples/c_print_args_alt/main.c index 9b87969..5dd55ff 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, @@ -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) | @@ -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)); @@ -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; } \ No newline at end of file diff --git a/examples/c_print_args_alt/print_args.h b/examples/c_print_args_alt/print_args.h index 223adba..fa9b357 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)); \ @@ -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 */ \ @@ -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); \ \ @@ -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; \ @@ -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; \