Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Created example with alternative approach to parse args #22

Merged
merged 9 commits into from
Sep 17, 2024
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"name": "(lldb) Launch - Macos",
"type": "cppdbg",
"request": "launch",
"program": "${fileDirname}/value_ffi_test",
"program": "${fileDirname}/c_print_args",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
Expand Down
1 change: 0 additions & 1 deletion examples/c_ffi_call/value_ffi.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ static int _val_to_ffi_type(metac_entry_t * p_entry, metac_flag_t variadic, ffi_
return -ENOMEM;
}
#if __linux__
va_list x;
p_ffi_type->type = FFI_TYPE_STRUCT;
p_ffi_type->size = sizeof(void*);
p_ffi_type->alignment = p_ffi_type->size;
Expand Down
1 change: 1 addition & 0 deletions examples/c_print_args_alt/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
c_print_args
39 changes: 39 additions & 0 deletions examples/c_print_args_alt/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
ifeq ($(M),)
METAC_ROOT=../..

all: target test

target:
$(MAKE) -C $(METAC_ROOT) M=$(PWD) $(PWD)/c_print_args

clean:
$(MAKE) -C $(METAC_ROOT) M=$(PWD) clean

test:
$(MAKE) -C $(METAC_ROOT) M=$(PWD) test

.PHONY: all clean
endif

CFLAGS+=-Wno-varargs -g3

rules+=\
c_print_args \
_meta_c_print_args \
main.reflect.c

TPL-c_print_args:=bin_target
IN-c_print_args=main.o main.reflect.o
LDFLAGS-c_print_args=-Lsrc -lmetac
DEPS-c_print_args=src/libmetac.a

TPL-_meta_c_print_args:=bin_target
IN-_meta_c_print_args=main.meta.o
LDFLAGS-_meta_c_print_args=-Lsrc -lmetac
DEPS-_meta_c_print_args=src/libmetac.a
POST-_meta_c_print_args=$(METAC_POST_META)

TPL-main.reflect.c:=metac_target
METACFLAGS-main.reflect.c+=run metac-reflect-gen $(METAC_OVERRIDE_IN_TYPE)
IN-main.reflect.c=_meta_c_print_args

9 changes: 9 additions & 0 deletions examples/c_print_args_alt/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
This is an alternative approach to the c_print_args

The original approach requires some non-documented capabilities of va_arg to work with structures and
va_list (it's not easy to extract struct or va_list from va_list which we used as a storage).
The current approach in its turn requires `typeof` compiler extension.
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
which is mentioned as a minimum supported number of arguments in C in some referenses.
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
to find a construction which can be universal. Added TODO there.
84 changes: 84 additions & 0 deletions examples/c_print_args_alt/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@

#include "print_args.h"

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

int test_function1_with_args(int a, short b){
printf("called\n");
return a + b + 6;
}
METAC_GSYM_LINK(test_function1_with_args);

typedef struct list_s{
double x;
struct list_s * p_next;
}list_t;

double test_function3_with_args(list_t *p_list) {
double sum = 0.0;
while(p_list != NULL) {
sum += p_list->x;
p_list->x += 1;

p_list = p_list->p_next;
}
printf("!!!result is %f %Lf!!!\n", sum, (long double)sum);
return sum;
}
METAC_GSYM_LINK(test_function3_with_args);

int my_printf(const char * format, ...) {
va_list l;
va_start(l, format);
int res = vprintf(format, l);
va_end(l);
return res;
}
METAC_GSYM_LINK(my_printf);

enum x {
xOne = 1,
xTwo = 2,
xMinusOne = -1,
};
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);

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) |
METAC_TAG_MAP_ENTRY_CATEGORY_MASK(METAC_TEC_func_parameter) |
METAC_TAG_MAP_ENTRY_CATEGORY_MASK(METAC_TEC_member) |
METAC_TAG_MAP_ENTRY_CATEGORY_MASK(METAC_TEC_final),},)
/* start tags for all types */

METAC_TAG_MAP_ENTRY(METAC_GSYM_LINK_ENTRY(my_printf))
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({.i = 1}),
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));

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));

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));

metac_tag_map_delete(p_tagmap);
return 0;
}
27 changes: 27 additions & 0 deletions examples/c_print_args_alt/mr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// taken from https://github.com/alexanderchuranov/Metaresc/blob/master/src/metaresc.h

#ifndef MR_H_
#define MR_H_

#include "mr_pp.generated.h"

/* internal macros for arguments evaluation and concatination */
#define MR_PASTE2(...) MR_PASTE2_ (__VA_ARGS__)
#define MR_PASTE2_(_0, _1) _0 ## _1
#define MR_PASTE3(...) MR_PASTE3_ (__VA_ARGS__)
#define MR_PASTE3_(_0, _1, _2) _0 ## _1 ## _2
#define MR_PASTE4(...) MR_PASTE4_ (__VA_ARGS__)
#define MR_PASTE4_(_0, _1, _2, _3) _0 ## _1 ## _2 ## _3
#define MR_PASTE5(...) MR_PASTE5_ (__VA_ARGS__)
#define MR_PASTE5_(_0, _1, _2, _3, _4) _0 ## _1 ## _2 ## _3 ## _4

/* Interface macros for unrolled loops from mr_pp.h */
#define MR_FOREACH(X, ...) MR_PASTE2 (MR_FOREACH, MR_NARG (__VA_ARGS__)) (X, __VA_ARGS__)
#define MR_FOR(NAME, N, OP, FUNC, ...) MR_PASTE2 (MR_FOR, N) (NAME, OP, FUNC, __VA_ARGS__)

// like car/cdr in lisp
#define MR_FIRST(_FIRST_, ...) _FIRST_
#define MR_REST(_FIRST_, ...) __VA_ARGS__
#define MR_FOREACH_EX(X, ...) MR_PASTE2 (MR_FOREACH_EX_, MR_NARG (__VA_ARGS__)) (X, __VA_ARGS__)

#endif
Loading
Loading