Mercurial > pub > dyncall > dyncall
changeset 432:167faab0c0be
first usable version of test suite for aggregates, handling only non-nested struct params, at the moment;
still missing:
- unions
- arrays
- aggregates as return values
author | Tassilo Philipp |
---|---|
date | Fri, 21 Jan 2022 15:42:29 +0100 |
parents | 1cb8a65ea27f |
children | 45662241d9cd |
files | test/suite_aggrs/CMakeLists.txt test/suite_aggrs/Makefile.embedded test/suite_aggrs/Makefile.generic test/suite_aggrs/Nmakefile test/suite_aggrs/README.txt test/suite_aggrs/cases.c test/suite_aggrs/cases.h test/suite_aggrs/cases.txt test/suite_aggrs/config.lua test/suite_aggrs/design.txt test/suite_aggrs/globals.c test/suite_aggrs/globals.h test/suite_aggrs/main.c test/suite_aggrs/mk-cases.lua test/suite_aggrs/mkfile test/suite_aggrs/rand-sig.lua |
diffstat | 16 files changed, 966 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/suite_aggrs/CMakeLists.txt Fri Jan 21 15:42:29 2022 +0100 @@ -0,0 +1,4 @@ +add_executable(suite_aggrs globals.c cases.c main.c) +target_link_libraries(suite_aggrs dyncall_s) + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/suite_aggrs/Makefile.embedded Fri Jan 21 15:42:29 2022 +0100 @@ -0,0 +1,25 @@ +TARGET = suite_aggrs ${OBJS} +OBJS = globals.o cases.o main.o + +SRCDIR = ../.. +BLDDIR = ${SRCDIR} +LUA = lua + +CPPFLAGS += -I${SRCDIR}/dyncall +LDFLAGS += -L${BLDDIR}/dyncall +LDLIBS += -ldyncall_s + +.PHONY: all clean config config-random + +all: ${TARGET} +suite_aggrs: ${OBJS} + ${CC} ${OBJS} ${LDFLAGS} ${LDLIBS} -o $@ +config: + ${LUA} mk-cases.lua <design.txt >cases.h +config-random: + ${LUA} rand-sig.lua >cases.txt + ${LUA} mk-cases.lua <cases.txt >cases.h +cases.o: cases.h +clean: + rm -f ${TARGET} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/suite_aggrs/Makefile.generic Fri Jan 21 15:42:29 2022 +0100 @@ -0,0 +1,21 @@ +APP = suite_aggrs +OBJS = globals.o cases.o main.o +SRCTOP = ${VPATH}/../.. +BLDTOP = ../.. +CFLAGS += -I${SRCTOP}/dyncall +LDLIBS += -L${BLDTOP}/dyncall -ldyncall_s +LUA = lua +.PHONY: all clean install config config-random +all: ${APP} +${APP}: ${OBJS} + ${CC} ${CFLAGS} ${LDFLAGS} ${OBJS} ${LDLIBS} -o ${APP} +clean: + rm -f ${APP} ${OBJS} +install: + mkdir -p ${PREFIX}/test + cp ${APP} ${PREFIX}/test +config: + ${LUA} mk-cases.lua <design.txt >cases.h +config-random: + ${LUA} rand-sig.lua >cases.txt + ${LUA} mk-cases.lua <cases.txt >cases.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/suite_aggrs/Nmakefile Fri Jan 21 15:42:29 2022 +0100 @@ -0,0 +1,68 @@ +#////////////////////////////////////////////////////////////////////////////// +# +# Copyright (c) 2022 Tassilo Philipp <tphilipp@potion-studios.com> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +#////////////////////////////////////////////////////////////////////////////// + +#/////////////////////////////////////////////////// +# +# nmake makefile +# Nmakefile +# +#/////////////////////////////////////////////////// + + +TOP = ..\.. + +!INCLUDE $(TOP)\buildsys\nmake\prolog.nmake + + +AUTOS = cases.h + + +!IF "$(BUILD_OS)" == "windows" + +TARGETS = suite_aggrs.exe +OBJS = main.obj cases.obj globals.obj + +$(TARGETS): $(OBJS) + echo Linking $@ ... + $(LD) /OUT:"$@" $(LDFLAGS) $(OBJS) $(TOP)\dyncall\dyncall_s.lib + + +!ELSE IF "$(BUILD_OS)" == "nds" + +TARGETS = suite_aggrs.nds +OBJS = main.o cases.o globals.o + +$(TARGETS): $(OBJS) + echo Linking $@ ... + $(LD) $(LDFLAGS) $(OBJS) $(DEVKITPRO_PATH)\libnds\lib\libnds9.a $(TOP)/dyncall/libdyncall_s.a -o "$(@B).elf" + $(OCP) -O binary "$(@B).elf" "$(@B).arm9" + ndstool -c "$@" -9 "$(@B).arm9" + del "$(@B).elf" "$(@B).arm9" + +!ENDIF + + + +$(OBJS): $(AUTOS) + +$(AUTOS): mk-cases.lua + lua mk-cases.lua <cases.txt >cases.h + + +!INCLUDE $(TOP)\buildsys\nmake\epilog.nmake +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/suite_aggrs/README.txt Fri Jan 21 15:42:29 2022 +0100 @@ -0,0 +1,6 @@ +suite_aggrs for dyncall written in C and Lua. + +Tests aggregates (structs, unions and arrays) passed by value, along with other, non-aggregate args. + +@@@ unions and arrays missing +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/suite_aggrs/cases.c Fri Jan 21 15:42:29 2022 +0100 @@ -0,0 +1,54 @@ +/* + + Package: dyncall + Library: test + File: test/call_aggrs/cases.c + Description: + License: + + Copyright (c) 2022 Tassilo Philipp <tphilipp@potion-studios.com> + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +*/ + +#include "globals.h" + +#define ret_v(X) +#define ret_c(X) return(K_c[X]); +#define ret_s(X) return(K_s[X]); +#define ret_i(X) return(K_i[X]); +#define ret_j(X) return(K_j[X]); +#define ret_l(X) return(K_l[X]); +#define ret_p(X) return(K_p[X]); +#define ret_f(X) return(K_f[X]); +#define ret_d(X) return(K_d[X]); +#define ret_a(X) return(K_a[X]); + +#define v void +#define c char +#define s short +#define i int +#define j long +#define l long long +#define p void* +#define f float +#define d double +#define a void* /* all generated aggregates */ + +#include "dyncall_struct.h" +#include "cases.h" + +int G_ncases = sizeof(G_sigtab)/sizeof(G_sigtab[0]); +int G_naggs = sizeof(G_agg_sigs)/sizeof(G_agg_sigs[0]); +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/suite_aggrs/cases.h Fri Jan 21 15:42:29 2022 +0100 @@ -0,0 +1,175 @@ +/* {ici} */ +struct A2{ i m0; c m1; i m2; }; +void f_cpA2(struct A2 *x, const struct A2 *y) { x->m0 = y->m0; x->m1 = y->m1; x->m2 = y->m2; }; +int f_cmpA2(const struct A2 *x, const struct A2 *y) { return x->m0 == y->m0 && x->m1 == y->m1 && x->m2 == y->m2; }; +DCstruct* f_newdcstA2() { DCstruct* st = dcNewStruct(3, sizeof(struct A2), 0, 1); dcStructField(st, 'i', offsetof(struct A2, m0), 1); dcStructField(st, 'c', offsetof(struct A2, m1), 1); dcStructField(st, 'i', offsetof(struct A2, m2), 1); dcCloseStruct(st); return st; }; +/* {ii} */ +struct A1{ i m0; i m1; }; +void f_cpA1(struct A1 *x, const struct A1 *y) { x->m0 = y->m0; x->m1 = y->m1; }; +int f_cmpA1(const struct A1 *x, const struct A1 *y) { return x->m0 == y->m0 && x->m1 == y->m1; }; +DCstruct* f_newdcstA1() { DCstruct* st = dcNewStruct(2, sizeof(struct A1), 0, 1); dcStructField(st, 'i', offsetof(struct A1, m0), 1); dcStructField(st, 'i', offsetof(struct A1, m1), 1); dcCloseStruct(st); return st; }; +/* {ps} */ +struct A5{ p m0; s m1; }; +void f_cpA5(struct A5 *x, const struct A5 *y) { x->m0 = y->m0; x->m1 = y->m1; }; +int f_cmpA5(const struct A5 *x, const struct A5 *y) { return x->m0 == y->m0 && x->m1 == y->m1; }; +DCstruct* f_newdcstA5() { DCstruct* st = dcNewStruct(2, sizeof(struct A5), 0, 1); dcStructField(st, 'p', offsetof(struct A5, m0), 1); dcStructField(st, 's', offsetof(struct A5, m1), 1); dcCloseStruct(st); return st; }; +/* {iiii} */ +struct A9{ i m0; i m1; i m2; i m3; }; +void f_cpA9(struct A9 *x, const struct A9 *y) { x->m0 = y->m0; x->m1 = y->m1; x->m2 = y->m2; x->m3 = y->m3; }; +int f_cmpA9(const struct A9 *x, const struct A9 *y) { return x->m0 == y->m0 && x->m1 == y->m1 && x->m2 == y->m2 && x->m3 == y->m3; }; +DCstruct* f_newdcstA9() { DCstruct* st = dcNewStruct(4, sizeof(struct A9), 0, 1); dcStructField(st, 'i', offsetof(struct A9, m0), 1); dcStructField(st, 'i', offsetof(struct A9, m1), 1); dcStructField(st, 'i', offsetof(struct A9, m2), 1); dcStructField(st, 'i', offsetof(struct A9, m3), 1); dcCloseStruct(st); return st; }; +/* {iii} */ +struct A8{ i m0; i m1; i m2; }; +void f_cpA8(struct A8 *x, const struct A8 *y) { x->m0 = y->m0; x->m1 = y->m1; x->m2 = y->m2; }; +int f_cmpA8(const struct A8 *x, const struct A8 *y) { return x->m0 == y->m0 && x->m1 == y->m1 && x->m2 == y->m2; }; +DCstruct* f_newdcstA8() { DCstruct* st = dcNewStruct(3, sizeof(struct A8), 0, 1); dcStructField(st, 'i', offsetof(struct A8, m0), 1); dcStructField(st, 'i', offsetof(struct A8, m1), 1); dcStructField(st, 'i', offsetof(struct A8, m2), 1); dcCloseStruct(st); return st; }; +/* {li} */ +struct A4{ l m0; i m1; }; +void f_cpA4(struct A4 *x, const struct A4 *y) { x->m0 = y->m0; x->m1 = y->m1; }; +int f_cmpA4(const struct A4 *x, const struct A4 *y) { return x->m0 == y->m0 && x->m1 == y->m1; }; +DCstruct* f_newdcstA4() { DCstruct* st = dcNewStruct(2, sizeof(struct A4), 0, 1); dcStructField(st, 'l', offsetof(struct A4, m0), 1); dcStructField(st, 'i', offsetof(struct A4, m1), 1); dcCloseStruct(st); return st; }; +/* {} */ +struct A6{ }; +void f_cpA6(struct A6 *x, const struct A6 *y) { 1; }; +int f_cmpA6(const struct A6 *x, const struct A6 *y) { return 1; }; +DCstruct* f_newdcstA6() { DCstruct* st = dcNewStruct(0, sizeof(struct A6), 0, 1); dcCloseStruct(st); return st; }; +/* {i} */ +struct A7{ i m0; }; +void f_cpA7(struct A7 *x, const struct A7 *y) { x->m0 = y->m0; }; +int f_cmpA7(const struct A7 *x, const struct A7 *y) { return x->m0 == y->m0; }; +DCstruct* f_newdcstA7() { DCstruct* st = dcNewStruct(1, sizeof(struct A7), 0, 1); dcStructField(st, 'i', offsetof(struct A7, m0), 1); dcCloseStruct(st); return st; }; +/* {il} */ +struct A3{ i m0; l m1; }; +void f_cpA3(struct A3 *x, const struct A3 *y) { x->m0 = y->m0; x->m1 = y->m1; }; +int f_cmpA3(const struct A3 *x, const struct A3 *y) { return x->m0 == y->m0 && x->m1 == y->m1; }; +DCstruct* f_newdcstA3() { DCstruct* st = dcNewStruct(2, sizeof(struct A3), 0, 1); dcStructField(st, 'i', offsetof(struct A3, m0), 1); dcStructField(st, 'l', offsetof(struct A3, m1), 1); dcCloseStruct(st); return st; }; +/* 0:viiiii{ii} */ v f0(i a1,i a2,i a3,i a4,i a5,struct A1 a6){V_i[1]=a1;V_i[2]=a2;V_i[3]=a3;V_i[4]=a4;V_i[5]=a5;f_cpA1(V_a[6],&a6);ret_v(6)} +/* 1:viiiii{ici} */ v f1(i a1,i a2,i a3,i a4,i a5,struct A2 a6){V_i[1]=a1;V_i[2]=a2;V_i[3]=a3;V_i[4]=a4;V_i[5]=a5;f_cpA2(V_a[6],&a6);ret_v(6)} +/* 2:viiiii{il} */ v f2(i a1,i a2,i a3,i a4,i a5,struct A3 a6){V_i[1]=a1;V_i[2]=a2;V_i[3]=a3;V_i[4]=a4;V_i[5]=a5;f_cpA3(V_a[6],&a6);ret_v(6)} +/* 3:vfiiiii{il} */ v f3(f a1,i a2,i a3,i a4,i a5,i a6,struct A3 a7){V_f[1]=a1;V_i[2]=a2;V_i[3]=a3;V_i[4]=a4;V_i[5]=a5;V_i[6]=a6;f_cpA3(V_a[7],&a7);ret_v(7)} +/* 4:viiiiif{il} */ v f4(i a1,i a2,i a3,i a4,i a5,f a6,struct A3 a7){V_i[1]=a1;V_i[2]=a2;V_i[3]=a3;V_i[4]=a4;V_i[5]=a5;V_f[6]=a6;f_cpA3(V_a[7],&a7);ret_v(7)} +/* 5:viiiiif{li} */ v f5(i a1,i a2,i a3,i a4,i a5,f a6,struct A4 a7){V_i[1]=a1;V_i[2]=a2;V_i[3]=a3;V_i[4]=a4;V_i[5]=a5;V_f[6]=a6;f_cpA4(V_a[7],&a7);ret_v(7)} +/* 6:viiiii{il}f */ v f6(i a1,i a2,i a3,i a4,i a5,struct A3 a6,f a7){V_i[1]=a1;V_i[2]=a2;V_i[3]=a3;V_i[4]=a4;V_i[5]=a5;f_cpA3(V_a[6],&a6);V_f[7]=a7;ret_v(7)} +/* 7:viiiii{li}f */ v f7(i a1,i a2,i a3,i a4,i a5,struct A4 a6,f a7){V_i[1]=a1;V_i[2]=a2;V_i[3]=a3;V_i[4]=a4;V_i[5]=a5;f_cpA4(V_a[6],&a6);V_f[7]=a7;ret_v(7)} +/* 8:viiffiii{ps} */ v f8(i a1,i a2,f a3,f a4,i a5,i a6,i a7,struct A5 a8){V_i[1]=a1;V_i[2]=a2;V_f[3]=a3;V_f[4]=a4;V_i[5]=a5;V_i[6]=a6;V_i[7]=a7;f_cpA5(V_a[8],&a8);ret_v(8)} +/* 9:viiiiiff{li} */ v f9(i a1,i a2,i a3,i a4,i a5,f a6,f a7,struct A4 a8){V_i[1]=a1;V_i[2]=a2;V_i[3]=a3;V_i[4]=a4;V_i[5]=a5;V_f[6]=a6;V_f[7]=a7;f_cpA4(V_a[8],&a8);ret_v(8)} +/* 10:viiiiiff{il} */ v f10(i a1,i a2,i a3,i a4,i a5,f a6,f a7,struct A3 a8){V_i[1]=a1;V_i[2]=a2;V_i[3]=a3;V_i[4]=a4;V_i[5]=a5;V_f[6]=a6;V_f[7]=a7;f_cpA3(V_a[8],&a8);ret_v(8)} +/* 11:viiiii{il}ff */ v f11(i a1,i a2,i a3,i a4,i a5,struct A3 a6,f a7,f a8){V_i[1]=a1;V_i[2]=a2;V_i[3]=a3;V_i[4]=a4;V_i[5]=a5;f_cpA3(V_a[6],&a6);V_f[7]=a7;V_f[8]=a8;ret_v(8)} +/* 12:viiiii{li}ff */ v f12(i a1,i a2,i a3,i a4,i a5,struct A4 a6,f a7,f a8){V_i[1]=a1;V_i[2]=a2;V_i[3]=a3;V_i[4]=a4;V_i[5]=a5;f_cpA4(V_a[6],&a6);V_f[7]=a7;V_f[8]=a8;ret_v(8)} +/* 13:i */ i f13(){ret_i(0)} +/* 14:i{} */ i f14(struct A6 a1){f_cpA6(V_a[1],&a1);ret_i(1)} +/* 15:i{i} */ i f15(struct A7 a1){f_cpA7(V_a[1],&a1);ret_i(1)} +/* 16:i{ii} */ i f16(struct A1 a1){f_cpA1(V_a[1],&a1);ret_i(1)} +/* 17:i{iii} */ i f17(struct A8 a1){f_cpA8(V_a[1],&a1);ret_i(1)} +/* 18:i{iiii} */ i f18(struct A9 a1){f_cpA9(V_a[1],&a1);ret_i(1)} +/* 19:f */ f f19(){ret_f(0)} +/* 20:f{} */ f f20(struct A6 a1){f_cpA6(V_a[1],&a1);ret_f(1)} +/* 21:f{i} */ f f21(struct A7 a1){f_cpA7(V_a[1],&a1);ret_f(1)} +/* 22:f{ii} */ f f22(struct A1 a1){f_cpA1(V_a[1],&a1);ret_f(1)} +/* 23:d{ii} */ d f23(struct A1 a1){f_cpA1(V_a[1],&a1);ret_d(1)} +/* 24:f{iii} */ f f24(struct A8 a1){f_cpA8(V_a[1],&a1);ret_f(1)} +/* 25:f{iiii} */ f f25(struct A9 a1){f_cpA9(V_a[1],&a1);ret_f(1)} +/* 26:ss{ii} */ s f26(s a1,struct A1 a2){V_s[1]=a1;f_cpA1(V_a[2],&a2);ret_s(2)} +funptr G_funtab[] = { + (funptr)&f0, + (funptr)&f1, + (funptr)&f2, + (funptr)&f3, + (funptr)&f4, + (funptr)&f5, + (funptr)&f6, + (funptr)&f7, + (funptr)&f8, + (funptr)&f9, + (funptr)&f10, + (funptr)&f11, + (funptr)&f12, + (funptr)&f13, + (funptr)&f14, + (funptr)&f15, + (funptr)&f16, + (funptr)&f17, + (funptr)&f18, + (funptr)&f19, + (funptr)&f20, + (funptr)&f21, + (funptr)&f22, + (funptr)&f23, + (funptr)&f24, + (funptr)&f25, + (funptr)&f26, +}; +char const * G_sigtab[] = { + "viiiii{ii}", + "viiiii{ici}", + "viiiii{il}", + "vfiiiii{il}", + "viiiiif{il}", + "viiiiif{li}", + "viiiii{il}f", + "viiiii{li}f", + "viiffiii{ps}", + "viiiiiff{li}", + "viiiiiff{il}", + "viiiii{il}ff", + "viiiii{li}ff", + "i", + "i{}", + "i{i}", + "i{ii}", + "i{iii}", + "i{iiii}", + "f", + "f{}", + "f{i}", + "f{ii}", + "d{ii}", + "f{iii}", + "f{iiii}", + "ss{ii}", +}; +const char* G_agg_sigs[] = { + "{ici}", + "{ii}", + "{ps}", + "{iiii}", + "{iii}", + "{li}", + "{}", + "{i}", + "{il}" +}; +int G_agg_sizes[] = { + sizeof(struct A2), + sizeof(struct A1), + sizeof(struct A5), + sizeof(struct A9), + sizeof(struct A8), + sizeof(struct A4), + sizeof(struct A6), + sizeof(struct A7), + sizeof(struct A3) +}; +funptr G_agg_newdcstfuncs[] = { + (funptr)&f_newdcstA2, + (funptr)&f_newdcstA1, + (funptr)&f_newdcstA5, + (funptr)&f_newdcstA9, + (funptr)&f_newdcstA8, + (funptr)&f_newdcstA4, + (funptr)&f_newdcstA6, + (funptr)&f_newdcstA7, + (funptr)&f_newdcstA3 +}; +funptr G_agg_cmpfuncs[] = { + (funptr)&f_cmpA2, + (funptr)&f_cmpA1, + (funptr)&f_cmpA5, + (funptr)&f_cmpA9, + (funptr)&f_cmpA8, + (funptr)&f_cmpA4, + (funptr)&f_cmpA6, + (funptr)&f_cmpA7, + (funptr)&f_cmpA3 +}; +int G_maxargs = 8;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/suite_aggrs/cases.txt Fri Jan 21 15:42:29 2022 +0100 @@ -0,0 +1,13 @@ +viiiii{ii} +viiiii{ici} +viiiii{il} +vfiiiii{il} +viiiiif{il} +viiiiif{li} +viiiii{il}f +viiiii{li}f +viiffiii{ps} +viiiiiff{li} +viiiiiff{il} +viiiii{il}ff +viiiii{li}ff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/suite_aggrs/config.lua Fri Jan 21 15:42:29 2022 +0100 @@ -0,0 +1,18 @@ +-- user config for rand-sig.lua: +minargs = 0 +maxargs = 32 +maxaggrdepth = 3 -- max nesting depth of aggregates, 1 = no nesting +ncases = 400 +types = "csijlpfd{}" +seed = 2108 + +-- specify types more than once to increase relative occurance, e.g.: + +-- this favors non-struct args, especially ints (and also increases avg num of struct fields): +--types = "ccssiiiiijjllpfd{}" + +-- this heavily favors nested structs: +--types = "csijlpfd{{{{{{}" + +-- this heavily favors flat and short/empty structs: +--types = "csijlpfd{}}}}}}"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/suite_aggrs/design.txt Fri Jan 21 15:42:29 2022 +0100 @@ -0,0 +1,27 @@ +viiiii{ii} +viiiii{ici} +viiiii{il} +vfiiiii{il} +viiiiif{il} +viiiiif{li} +viiiii{il}f +viiiii{li}f +viiffiii{ps} +viiiiiff{li} +viiiiiff{il} +viiiii{il}ff +viiiii{li}ff +i +i{} +i{i} +i{ii} +i{iii} +i{iiii} +f +f{} +f{i} +f{ii} +d{ii} +f{iii} +f{iiii} +ss{ii}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/suite_aggrs/globals.c Fri Jan 21 15:42:29 2022 +0100 @@ -0,0 +1,83 @@ +/* + + Package: dyncall + Library: test + File: test/call_aggrs/globals.c + Description: + License: + + Copyright (c) 2022 Tassilo Philipp <tphilipp@potion-studios.com> + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +*/ + +#include <stdlib.h> +#include "globals.h" +#include <float.h> + +#define X(CH,T) T *V_##CH; T *K_##CH; +DEF_TYPES +#undef X + +static double rand_d() { return ( ( (double) rand() ) / ( (double) RAND_MAX ) ); } +static void rand_mem(void* p, size_t s) { for(int i=0; i<s; ++i) ((char*)p)[i] = (char)rand(); } + +static int calc_max_aggr_size() +{ + int i, s = 0; + for(i=0; i<G_naggs; ++i) + if(G_agg_sizes[i] > s) + s = G_agg_sizes[i]; + return s; +} + +void init_K() +{ + int i; + int maxaggrsize = calc_max_aggr_size(); +#define X(CH,T) V_##CH = (T*) malloc(sizeof(T)*(G_maxargs+1)); K_##CH = (T*) malloc(sizeof(T)*(G_maxargs+1)); +DEF_TYPES +#undef X + + + for(i=0;i<G_maxargs+1;++i) { + K_c[i] = (char) (((rand_d()-0.5)*2) * (1<<7)); + K_s[i] = (short) (((rand_d()-0.5)*2) * (1<<(sizeof(short)*8-1))); + K_i[i] = (int) (((rand_d()-0.5)*2) * (1<<(sizeof(int)*8-2))); + K_j[i] = (long) (((rand_d()-0.5)*2) * (1L<<(sizeof(long)*8-2))); + K_l[i] = (long long) (((rand_d()-0.5)*2) * (1LL<<(sizeof(long long)*8-2))); + K_p[i] = (void*) (long) (((rand_d()-0.5)*2) * (1LL<<(sizeof(void*)*8-1))); + K_f[i] = (float) (rand_d() * FLT_MAX); + K_d[i] = (double) (((rand_d()-0.5)*2) * 1.7976931348623157E+308/*__DBL_MAX__*/); /* Plan9 doesn't know the macro. */ + K_a[i] = malloc(maxaggrsize); rand_mem(K_a[i], maxaggrsize); + } +} + +void clear_V() +{ + static int aggr_init = 0; + int maxaggrsize = calc_max_aggr_size(); + + int i; + for(i=0;i<G_maxargs+1;++i) { + if(aggr_init) + free(V_a[i]); +#define X(CH,T) V_##CH[i] = (T) 0; +DEF_TYPES +#undef X + V_a[i] = malloc(maxaggrsize); + } + aggr_init = 1; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/suite_aggrs/globals.h Fri Jan 21 15:42:29 2022 +0100 @@ -0,0 +1,48 @@ +/* + + Package: dyncall + Library: test + File: test/call_aggrs/globals.h + Description: + License: + + Copyright (c) 2022 Tassilo Philipp <tphilipp@potion-studios.com> + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +*/ + + +/* the 'a'ggregate type points to memory with random data that is big enough to hold all different struct types */ +#define DEF_TYPES X(c,char) X(s,short) X(i,int) X(j,long) X(l,long long) X(p,void*) X(f,float) X(d,double) X(a,void*) + +#define X(CH,T) extern T *K_##CH; extern T *V_##CH; +DEF_TYPES +#undef X + +typedef void (*funptr)(); + +extern funptr G_funtab[]; +extern char const * G_sigtab[]; +extern int G_ncases; +extern int G_maxargs; +extern char const * G_agg_sigs[]; +extern int G_agg_sizes[]; +extern funptr G_agg_newdcstfuncs[]; +extern funptr G_agg_cmpfuncs[]; +extern int G_naggs; + +void init_K(); +void init_T(); +void clear_V(); +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/suite_aggrs/main.c Fri Jan 21 15:42:29 2022 +0100 @@ -0,0 +1,179 @@ +/* + + Package: dyncall + Library: test + File: test/call_aggrs/main.c + Description: + License: + + Copyright (c) 2022 Tassilo Philipp <tphilipp@potion-studios.com> + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +*/ + +#include "dyncall.h" +#include "dyncall_struct.h" +#include "globals.h" +#include <string.h> +#include "../common/platformInit.h" +#include "../common/platformInit.c" /* Impl. for functions only used in this translation unit */ + + +void* G_callvm; + + +static int find_agg_idx(int* len, const char* sig) +{ + for(int i=0; i<G_naggs; ++i) { + const char* agg_sig = G_agg_sigs[i]; + *len = strlen(agg_sig); + if(strncmp(agg_sig, sig, *len) == 0) + return i; + } + return -1; +} + +int invoke(char const* signature, void* t) +{ + DCCallVM * p = (DCCallVM*) G_callvm; + char const * sig = signature; + char rtype; + char atype; + int pos = 0; + int s = 0; + + clear_V(); + + rtype = *sig++; + dcReset(p); + + while ( (atype = *sig) != '\0') { + pos++; + switch(atype) { + case 'c': dcArgChar (p,K_c[pos]); break; + case 's': dcArgShort (p,K_s[pos]); break; + case 'i': dcArgInt (p,K_i[pos]); break; + case 'j': dcArgLong (p,K_j[pos]); break; + case 'l': dcArgLongLong(p,K_l[pos]); break; + case 'p': dcArgPointer (p,K_p[pos]); break; + case 'f': dcArgFloat (p,K_f[pos]); break; + case 'd': dcArgDouble (p,K_d[pos]); break; + case '{': { + /* find struct sig */ + int len; + int i = find_agg_idx(&len, sig); + if(i == -1) { + printf("unknown sig at '%s' ;", sig); + return 0; + } + DCstruct *st = ((DCstruct*(*)())G_agg_newdcstfuncs[i])(); + dcArgStruct(p, st, K_a[pos]); + sig += len-1; /* advance to next arg char */ + break; + } + default: printf("unknown atype '%c' (1) ;", atype); return 0; + } + ++sig; + } + + switch(rtype) + { + case 'v': dcCallVoid(p,t); s=1; /*TODO:check that no return-arg was touched.*/ break; + case 'c': s = (dcCallChar (p,t) == K_c[pos]) ; break; + case 's': s = (dcCallShort (p,t) == K_s[pos]) ; break; + case 'i': s = (dcCallInt (p,t) == K_i[pos]) ; break; + case 'j': s = (dcCallLong (p,t) == K_j[pos]) ; break; + case 'l': s = (dcCallLongLong(p,t) == K_l[pos]) ; break; + case 'p': s = (dcCallPointer (p,t) == K_p[pos]) ; break; + case 'f': s = (dcCallFloat (p,t) == K_f[pos]) ; break; + case 'd': s = (dcCallDouble (p,t) == K_d[pos]) ; break; + //@@@ handle return types case '{': @@@ ; break; + default: printf("unknown rtype '%c'", rtype); return 0; + } + + if (!s) { printf("rval wrong;"); return 0; } + /* test: */ + sig = signature+1; + pos = 1; + while ( (atype = *sig) != '\0') { + switch(atype) { + case 'c': s = ( V_c[pos] == K_c[pos] ); if (!s) printf("'c':%d: %d != %d ; ", pos, V_c[pos], K_c[pos]); break; + case 's': s = ( V_s[pos] == K_s[pos] ); if (!s) printf("'s':%d: %d != %d ; ", pos, V_s[pos], K_s[pos]); break; + case 'i': s = ( V_i[pos] == K_i[pos] ); if (!s) printf("'i':%d: %d != %d ; ", pos, V_i[pos], K_i[pos]); break; + case 'j': s = ( V_j[pos] == K_j[pos] ); if (!s) printf("'j':%d: %ld != %ld ; ", pos, V_j[pos], K_j[pos]); break; + case 'l': s = ( V_l[pos] == K_l[pos] ); if (!s) printf("'l':%d: %lld != %lld ; ", pos, V_l[pos], K_l[pos]); break; + case 'p': s = ( V_p[pos] == K_p[pos] ); if (!s) printf("'p':%d: %lld != %lld ; ", pos, (long long) V_p[pos], (long long) K_p[pos]); break; + case 'f': s = ( V_f[pos] == K_f[pos] ); if (!s) printf("'f':%d: %f != %f ; ", pos, V_f[pos], K_f[pos]); break; + case 'd': s = ( V_d[pos] == K_d[pos] ); if (!s) printf("'d':%d: %f != %f ; ", pos, V_d[pos], K_d[pos]); break; + case '{': { + /* no check: guaranteed to exist, or invoke func would've exited when passing args, above */ + int len; + int i = find_agg_idx(&len, sig); + s = ((int(*)())G_agg_cmpfuncs[i])(V_a[pos], K_a[pos]); + if (!s) printf("'{':%d: %lld != %lld ; ", pos, (long long) V_a[pos], (long long) K_a[pos]); + sig += len-1; /* advance to next arg char */ + break; + } + default: printf("unknown atype '%c' ; ", atype); return 0; + } + if (!s) { + printf("arg mismatch at %d ; ", pos); + return 0; + } + ++sig; + ++pos; + } + return 1; +} + +int run_test(int i) +{ + char const * sig; + void * target; + int success; + sig = G_sigtab[i]; + target = (void*) G_funtab[i]; + printf("%d:%s:",i,sig); + success = invoke(sig,target); + printf("%d\n",success); + return success; +} + +int run_all() +{ + int i; + int failure = 0; + for(i=0;i<G_ncases;++i) + failure |= !( run_test(i) ); + + return !failure; +} + +int main(int argc, char* argv[]) +{ + int total; + + dcTest_initPlatform(); + + init_K(G_maxargs); + G_callvm = (DCCallVM*) dcNewCallVM(32768); + dcReset(G_callvm); + total = run_all(); + printf("result: call_aggrs: %d\n", total); + + dcTest_deInitPlatform(); + + return !total; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/suite_aggrs/mk-cases.lua Fri Jan 21 15:42:29 2022 +0100 @@ -0,0 +1,155 @@ +require"math" +local max = math.max +local maxargs = 0 + +local n_aggrs = 0 +local seen_aggrs = { } + + +function trim(l) return l:gsub("^%s+",""):gsub("%s+$","") end +function mkcase(id,sig) + local sig = trim(sig) + -- @@@ return value hard-guessed by first char, doesn't hold anymore + local h = { "/* ",id,":",sig," */ ",sig:sub(1,1), " f", id,"(","" } + local t = { "" } + local pos = 1 + local n_nest = 0 + local aggr + local aggr_sig = '' + for i = 2, #sig do + local name = "a"..pos + local ch = sig:sub(i,i) + + aggr_sig = aggr_sig..ch + + -- aggregate nest level change? + if ch == '{' then + n_nest = n_nest + 1 + aggr = { } + aggr_sig = ch -- @@@ handle nesting + else + if ch == '}' then -- @@@ handle nesting, here, by reusing structs + n_nest = n_nest - 1 + -- aggr sig complete? + if n_nest == 0 then + -- register yet unseen aggregates, key is sig, val is body and name + if seen_aggrs[aggr_sig] == nil then + n_aggrs = n_aggrs + 1 + ch = 'A'..n_aggrs + seen_aggrs[aggr_sig] = { aggr, ch } + end + ch = seen_aggrs[aggr_sig][2] + end + else + if n_nest > 0 then + aggr[#aggr+1] = ch + aggr[#aggr+1] = 'm'..(#aggr >> 1) + end + end + end + + if n_nest == 0 then + -- struct types (more than one char) need copying via a func + if #ch > 1 then + h[#h+1] = 'struct '..ch.." "..name + t[#t+1] = 'f_cp'..ch..'(V_a['..pos.."],&"..name..");" + else + h[#h+1] = ch.." "..name + t[#t+1] = "V_"..ch.."["..pos.."]="..name..";" + end + h[#h+1] = "," + + pos = pos + 1 + end + end + maxargs = max(maxargs, pos-1) + h[#h] = "){" + t[#t+1] = "ret_"..sig:sub(1,1).."("..(pos-1)..")}\n" + return table.concat(h,"")..table.concat(t,"") +end + +function mkfuntab(n) + local s = { "funptr G_funtab[] = {\n"} + for i = 0, n-1 do + s[#s+1] = "\t(funptr)&f"..i..",\n" + end + s[#s+1] = "};\n" + return table.concat(s,"") +end + +function mksigtab(sigs) + local s = { "char const * G_sigtab[] = {\n"} + for k,v in pairs(sigs) do + s[#s+1] = '\t"'..v..'",\n' + end + s[#s+1] = "};\n" + return table.concat(s,"") +end + +function mkall() + local lineno = 0 + local sigtab = { } + local cases = '' + for line in io.lines() do + local sig = trim(line) + cases = cases..mkcase(lineno,sig) + sigtab[#sigtab+1] = sig + lineno = lineno + 1 + end + + agg_sizes = {} + agg_sigs = {} + agg_names = {} + for k, v in pairs(seen_aggrs) do + st = 'struct '..v[2] + + agg_sizes[#agg_sizes + 1] = 'sizeof('..st..')' + agg_sigs [#agg_sigs + 1] = k + agg_names[#agg_names + 1] = v[2] + + -- struct def + io.write('/* '..k..' */\n') + io.write(st..'{ ') + for i = 1, #v[1], 2 do + io.write(v[1][i]..' '..v[1][i+1]..'; ') + end + io.write("};\n") + + -- struct cp and cmp funcs + s = { + 'void f_cp'..v[2]..'('..st..' *x, const '..st..' *y) { ', + 'int f_cmp'..v[2]..'(const '..st..' *x, const '..st..' *y) { return ' + } + o = { '=', '==', '; ', ' && ' } + for t = 1, 2 do + io.write(s[t]) + b = {} + for i = 1, #v[1], 2 do + b[#b+1] = 'x->'..v[1][i+1]..' '..o[t]..' y->'..v[1][i+1]; + end + if #b == 0 then + b[1] = '1' -- to handle empty structs + end + io.write(table.concat(b,o[t+2]).."; };\n") + end + + -- convenient dcnewstruct helper funcs + io.write('DCstruct* f_newdcst'..v[2]..'() { DCstruct* st = dcNewStruct('..(#v[1]>>1)..', sizeof('..st..'), 0, 1); ') + for i = 1, #v[1], 2 do + io.write("dcStructField(st, '"..v[1][i].."', offsetof("..st..', '..v[1][i+1]..'), 1); ') + end + io.write(" dcCloseStruct(st); return st; };\n") + end + + io.write(cases) + io.write(mkfuntab(lineno)) + io.write(mksigtab(sigtab)) + io.write('const char* G_agg_sigs[] = {\n\t"'..table.concat(agg_sigs, '",\n\t"')..'"\n};\n') + io.write('int G_agg_sizes[] = {\n\t'..table.concat(agg_sizes, ',\n\t')..'\n};\n') + io.write('funptr G_agg_newdcstfuncs[] = {\n\t(funptr)&f_newdcst'..table.concat(agg_names, ',\n\t(funptr)&f_newdcst')..'\n};\n') + io.write('funptr G_agg_cmpfuncs[] = {\n\t(funptr)&f_cmp'..table.concat(agg_names, ',\n\t(funptr)&f_cmp')..'\n};\n') + io.write("int G_maxargs = "..maxargs..";\n") +end + +mkall() +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/suite_aggrs/mkfile Fri Jan 21 15:42:29 2022 +0100 @@ -0,0 +1,36 @@ +#////////////////////////////////////////////////////////////////////////////// +# +# Copyright (c) 2022 Tassilo Philipp <tphilipp@potion-studios.com> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +#////////////////////////////////////////////////////////////////////////////// + + +TOP = ../.. +<$TOP/buildsys/mk/prolog.mk + + +UNITS = globals cases main +APPLICATION = call_aggrs +LIBS = $TOP/dyncall/libdyncall_s.a$O + +#.PHONY: config +#config: mkconfig.lua rand-sig.lua mk-cases.lua +# echo Generating test cases... +# lua mk-config.lua >config.h +# lua rand-sig.lua >cases.txt +# lua mk-cases.lua <cases.txt >cases.h + + +<$TOP/buildsys/mk/epilog.mk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/suite_aggrs/rand-sig.lua Fri Jan 21 15:42:29 2022 +0100 @@ -0,0 +1,54 @@ +require"config" + +-- assure aggr chars are present in pairs (can be weighted, though), to avoid +-- inf loops +if string.match(types,'{') and not string.match(types,'}') then types = types..'}' end + +rtypes = "v"..types + + +function mkstruct(n_nest) + local s = "{" + + repeat + local id = math.random(#types) + local t = types:sub(id,id) + s = s..mktype(t, n_nest) + until t == '}' + + return s +end + +function mktype(t, n_nest) + -- ignore new structs if above depth limit + if t == '{' then + if n_nest < maxaggrdepth then + return mkstruct(n_nest + 1) + else + return '' + end + end + + -- if '}', without any open, use empty struct + if n_nest == 0 and t == '}' then + return "{}" + end + + return t +end + + +math.randomseed(seed) +local id +for i = 1, ncases do + id = math.random(#rtypes) + local nargs = math.random(minargs,maxargs) + local sig = { mktype(rtypes:sub(id,id), 0) } + for j = 1, nargs do + id = math.random(#types) + sig[#sig+1] = mktype(types:sub(id,id), 0) + end + io.write(table.concat(sig)) + io.write("\n") +end +