Skip to content

Commit fcf6932

Browse files
committed
made support of strings and enums
1 parent f6f79ba commit fcf6932

File tree

4 files changed

+88
-24
lines changed

4 files changed

+88
-24
lines changed

examples/c_print_args_alt/Readme.md renamed to examples/c_print_args_alt/README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ The original approach requires some non-documented capabilities of va_arg to wor
44
va_list (it's not easy to extract struct or va_list from va_list which we used as a storage).
55
The current approach in its turn requires `typeof` compiler extension.
66
Also this apporach has a limitation of number of arguments: it's necessary to regenerate mr_pp.generated.h using mr_pp.sh and provide the maximum number of arguments. For now it's generated with maximum 1024 arguments
7-
which is mentioned as a minimum supported number of arguments in C in some referenses.
7+
which is mentioned as a minimum supported number of arguments in C in some referenses.
8+
And the last limitation is - I wasn't able to find a way to handle arguments with string along with arguments as structs or va_list. When macro unrolls cycle it generates the code which handles each case and I wasn't able
9+
to find a construction which can be universal. Added TODO there.

examples/c_print_args_alt/main.c

+13-2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ int my_printf(const char * format, ...) {
3636
}
3737
METAC_GSYM_LINK(my_printf);
3838

39+
enum x {
40+
xOne = 1,
41+
xTwo = 2,
42+
xMinusOne = -1,
43+
};
44+
int test_function4_with_enum_args(enum x arg0, enum x arg1, enum x arg2) {
45+
return 0;
46+
}
47+
METAC_GSYM_LINK(test_function4_with_enum_args);
3948

4049
metac_tag_map_t * p_tagmap = NULL;
4150
METAC_TAG_MAP_NEW(va_args_tag_map, NULL, {.mask =
@@ -65,8 +74,10 @@ int main() {
6574
list_t * p_list = (list_t[]){{.x = 42.42, .p_next = (list_t[]){{ .x = 45.4, .p_next = NULL}}}};
6675
printf("fn returned: %f\n", METAC_WRAP_FN_RES(NULL, test_function3_with_args, p_list));
6776

68-
// doesn't work yet
69-
//printf("fn returned: %i\n", METAC_WRAP_FN_RES(p_tagmap, my_printf, "%d %d", 10, 22));
77+
printf("fn returned: %i\n", METAC_WRAP_FN_RES(p_tagmap, my_printf, "%d %d\n", 10, 22));
78+
79+
printf("fn returned: %i\n", METAC_WRAP_FN_RES(p_tagmap, test_function4_with_enum_args, xOne, xTwo, xMinusOne));
80+
printf("fn returned: %i\n", METAC_WRAP_FN_RES(p_tagmap, test_function4_with_enum_args, 1, 2, -1));
7081

7182
metac_tag_map_delete(p_tagmap);
7283
return 0;

examples/c_print_args_alt/print_args.h

+72-17
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ static int _process_unspecified_params(
2626
if (p_tag != NULL && p_tag->handler) {
2727
metac_value_event_t ev = {
2828
.type = METAC_RQVST_va_list,
29-
.va_list_param_id = param_id, /* TODO: to remove?*/
29+
.va_list_param_id = param_id,
3030
.p_return_value = metac_parameter_storage_new_param_value(p_param_storage, param_id),
3131
.p_va_list_container = &cntr,
3232
};
@@ -50,51 +50,107 @@ static int _process_unspecified_params(
5050
return failed;
5151
}
5252

53-
#define _APPEND_PARAM_2(_NEXT_, _N_, args...) if (failure == 0) { \
53+
#define _process_bt_(arg, _type_, _pseudoname_, _short_type_name_) \
54+
if (strcmp(param_base_type_name, #_pseudoname_) == 0 && param_entry_byte_size == sizeof(_type_)) { \
55+
metac_value_set_##_short_type_name_(p_param_value, *((_type_*)arg)); \
56+
} else
57+
58+
#define _process_enum_(arg, _type_, _short_type_name_) \
59+
if (param_entry_byte_size == sizeof(_type_)) { \
60+
_type_ v = *((_type_*)arg); \
61+
memcpy(metac_value_addr(p_param_value), &v, param_entry_byte_size); \
62+
} else
63+
64+
#define _QSTRING(_string_...) \
65+
#_string_
66+
#define _QSTRING_ARG(_args) \
67+
_QSTRING(_args)
68+
69+
#define _APPEND_PARAM(_NEXT_, _N_, args...) if (failure == 0) { \
5470
metac_entry_t *p_param_entry = metac_entry_by_paremeter_id(p_val_entry, param_id); \
5571
if (metac_entry_is_unspecified_parameter(p_param_entry) == 0 && metac_entry_is_va_list_parameter(p_param_entry) == 0) { \
5672
/* normal argument */ \
57-
typeof(MR_FIRST(args)) _x_val = MR_FIRST(args); \
5873
metac_entry_t *p_param_entry = metac_entry_by_paremeter_id(p_val_entry, param_id); \
74+
metac_entry_t * p_param_type_entry = metac_entry_parameter_entry(p_param_entry); \
75+
if (p_param_type_entry == NULL) { \
76+
failure = 1; \
77+
break; \
78+
} \
5979
metac_size_t param_entry_byte_size = 0; \
6080
if (metac_entry_byte_size(p_param_entry, &param_entry_byte_size) != 0) { \
6181
printf("param %d metac_entry_byte_size failed\n", param_id); \
62-
failure = 1; \
82+
failure = 2; \
6383
break; \
6484
} \
85+
typeof(MR_FIRST(args)) _x_val = MR_FIRST(args); \
6586
if (metac_parameter_storage_append_by_buffer(p_param_storage, p_param_entry, param_entry_byte_size) == 0) { \
6687
metac_value_t * p_param_value = metac_parameter_storage_new_param_value(p_param_storage, param_id); \
67-
if (p_param_value != NULL) { \
68-
if (param_entry_byte_size != sizeof(_x_val)) { \
69-
printf("param %d got sz %d, expectect sz %d\n", param_id, (int)sizeof(_x_val), (int)param_entry_byte_size); \
70-
/*TODO: - handle that */ \
71-
} \
72-
memcpy(metac_value_addr(p_param_value), &_x_val, param_entry_byte_size); \
88+
\
89+
if (metac_entry_is_base_type(p_param_type_entry) != 0) { \
90+
metac_name_t param_base_type_name = metac_entry_base_type_name(p_param_type_entry); \
91+
_process_bt_(&_x_val, char, char, char) \
92+
_process_bt_(&_x_val, unsigned char, unsigned char, uchar) \
93+
_process_bt_(&_x_val, short, short int, short) \
94+
_process_bt_(&_x_val, unsigned short, unsigned short int, ushort) \
95+
_process_bt_(&_x_val, int, int, int) \
96+
_process_bt_(&_x_val, unsigned int, unsigned int, uint) \
97+
_process_bt_(&_x_val, long, long int, long) \
98+
_process_bt_(&_x_val, unsigned long, unsigned long int, ulong) \
99+
_process_bt_(&_x_val, long long, long long int, llong) \
100+
_process_bt_(&_x_val, unsigned long long, unsigned long long int, ullong) \
101+
_process_bt_(&_x_val, bool, _Bool, bool) \
102+
_process_bt_(&_x_val, float, float, float) \
103+
_process_bt_(&_x_val, double, double, double) \
104+
_process_bt_(&_x_val, long double, long double, ldouble) \
105+
_process_bt_(&_x_val, float complex, complex float, float_complex) \
106+
_process_bt_(&_x_val, double complex, complex double, double_complex) \
107+
_process_bt_(&_x_val, long double complex, long complex double, ldouble_complex); \
108+
} else if (metac_entry_is_enumeration(p_param_type_entry) != 0) { \
109+
_process_enum_(&_x_val, char, char) \
110+
_process_enum_(&_x_val, short, short) \
111+
_process_enum_(&_x_val, int, int) \
112+
_process_enum_(&_x_val, long, long) \
113+
_process_enum_(&_x_val, long long, llong); \
114+
} else if (metac_entry_is_pointer(p_param_type_entry) != 0) { \
115+
/* ensure arg isn't string constant */ \
116+
char _s_arg[] = _QSTRING_ARG(MR_FIRST(args)); \
117+
if (_s_arg[0] == '\"') { \
118+
/* TODO: can't handle structs, va_list as arguments because of this line */ \
119+
char * s = ((char*)MR_FIRST(args)); \
120+
memcpy(metac_value_addr(p_param_value), &s, param_entry_byte_size); \
121+
} else { \
122+
memcpy(metac_value_addr(p_param_value), &_x_val, param_entry_byte_size); \
123+
} \
124+
} else { \
125+
/* not supported */ \
126+
failure = 3; \
73127
metac_value_delete(p_param_value); \
128+
break; \
74129
} \
130+
/*cleanup*/ \
131+
metac_value_delete(p_param_value); \
75132
} \
76133
} else if (metac_entry_is_va_list_parameter(p_param_entry) != 0) { \
134+
/* not supported */ \
135+
failure = 4; \
136+
break; \
77137
} else if (metac_entry_is_unspecified_parameter(p_param_entry) != 0) { \
78138
if (metac_parameter_storage_append_by_parameter_storage(p_param_storage, p_param_entry) != 0) { \
79139
failure = 5; \
80140
break; \
81141
} \
82142
if (_process_unspecified_params(p_param_storage, p_val, p_param_entry, p_tag_map, param_id, _N_ , args) != 0) { \
83-
failure = 4; \
143+
failure = 6; \
84144
break; \
85145
} \
86146
break; \
87-
} else { \
88-
failure = 3; \
89-
break; \
90147
} \
91148
if (failure == 0) { \
92149
++param_id; \
93150
_NEXT_ \
94151
} \
95152
}
96153

97-
98154
// this gets called in the context where p_param_storage is declared
99155
#define _WRAP(_tag_map_, _fn_, _args_...) ({ \
100156
metac_tag_map_t * p_tag_map = _tag_map_; \
@@ -104,11 +160,10 @@ static int _process_unspecified_params(
104160
metac_num_t param_id = 0; \
105161
/* append params*/ \
106162
do { \
107-
MR_FOREACH_EX(_APPEND_PARAM_2, _args_) \
163+
MR_FOREACH_EX(_APPEND_PARAM, _args_) \
108164
} while(0); \
109165
if (failure != 0) { \
110166
printf("failure %d\n", failure); \
111-
/* TODO: */ \
112167
} \
113168
p_val; \
114169
})

include/metac/reflect/value.h

-4
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,6 @@ metac_name_t metac_value_name(metac_value_t * p_val);
143143
/** @brief return value's final entry kind */
144144
metac_kind_t metac_value_final_kind(metac_value_t * p_val, metac_quals_t * p_quals); /* returns actual type kind, skips quals, typedefs, variable */
145145

146-
/* kind = METAC_KND_subroutine_type */
147-
/* metac_flag_t metac_value_is_subroutine(metac_value_t *p_val);
148-
TODO: we may have a call if pointer to subroutine, using libffi */
149-
150146
/* kind = METAC_KND_array */
151147

152148
/** @brief return non-zero if value's final kind is array */

0 commit comments

Comments
 (0)