Mercurial > pub > dyncall > dyncall
diff test/call_suite_aggrs/main.c @ 485:0c68b3f91367
- renamed suite_aggrs to call_suite_aggrs for consistency (callback version will be called callback_suite_aggrs)
author | Tassilo Philipp |
---|---|
date | Thu, 17 Mar 2022 15:41:26 +0100 |
parents | test/suite_aggrs/main.c@0f3b6898078d |
children | 29d09d10ecd9 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/call_suite_aggrs/main.c Thu Mar 17 15:41:26 2022 +0100 @@ -0,0 +1,232 @@ +/* + + Package: dyncall + Library: test + File: test/call_suite_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 "globals.h" +#include <string.h> +#include "../common/platformInit.h" +#include "../common/platformInit.c" /* Impl. for functions only used in this translation unit */ + + +static void* G_callvm; + + +static int find_agg_idx(int* len, const char* sig) +{ + int i; + for(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; +} + +static int invoke(char const* signature, void* t) +{ + DCCallVM * p = (DCCallVM*) G_callvm; + char const * sig = signature; + char const * sig_args; + char rtype; + DCaggr * rtype_a = NULL; + int rtype_size = 0; + funptr rtype_a_cmp = NULL; + char atype; + int pos = 0; + int s = 0; + + clear_V(); + + dcReset(p); + + if(*sig == '{' || *sig == '<') { + int len; + int i = find_agg_idx(&len, sig); + if(i == -1) { + printf("unknown rtype sig at '%s' ;", sig); + return 0; + } + rtype = *sig; + sig += len; + + rtype_size = G_agg_sizes[i]; + rtype_a_cmp = G_agg_cmpfuncs[i]; + rtype_a = ((DCaggr*(*)())G_agg_touchdcstfuncs[i])(); + dcBeginCallAggr(p, rtype_a); + } + else + rtype = *sig++; + + sig_args = sig; + + 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 '<': /* union */ + case '{': /* struct */ + { + /* find aggregate sig */ + int len; + DCaggr *ag; + int i = find_agg_idx(&len, sig); + if(i == -1) { + printf("unknown sig at '%s' ;", sig); + return 0; + } + ag = ((DCaggr*(*)())G_agg_touchdcstfuncs[i])(); + dcArgAggr(p, ag, 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; + case '<': /* union */ + case '{': /* struct */ + { + /* bound check memory adjacent to returned aggregate, to check for overflows by dcCallAggr */ + long long* adj_ll = (get_max_aggr_size() - rtype_size) > sizeof(long long) ? (long long*)((char*)V_a[0] + rtype_size) : NULL; + if(adj_ll) + *adj_ll = 0x0123456789abcdef; + + s = ((int(*)(const void*,const void*))rtype_a_cmp)(dcCallAggr(p, t, rtype_a, V_a[0]), K_a[pos]); + + if(adj_ll && *adj_ll != 0x0123456789abcdef) { + printf("writing rval overflowed into adjacent memory;"); + return 0; + } + break; + } + default: printf("unknown rtype '%c'", rtype); return 0; + } + + if (!s) { printf("rval wrong;"); return 0; } + + /* test V_* array against values passed to func: */ + sig = sig_args; + 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: %p != %p ; ", pos, V_p[pos], 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 '<': /* union */ + case '{': /* struct */ + { + /* 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(*)(const void*,const void*))G_agg_cmpfuncs[i])(V_a[pos], K_a[pos]); + if (!s) printf("'%c':%d: *%p != *%p ; ", atype, pos, V_a[pos], 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, i; + + dcTest_initPlatform(); + + init_test_data(G_maxargs); + G_callvm = (DCCallVM*) dcNewCallVM(32768); + + dcReset(G_callvm); + total = run_all(); + + /* free all DCaggrs created on the fly */ + for(i=0; i<G_naggs; ++i) + dcFreeAggr(((DCaggr*(*)())G_agg_touchdcstfuncs[i])()); + + dcFree(G_callvm); + deinit_test_data(G_maxargs); + + printf("result: call_suite_aggrs: %d\n", total); + + dcTest_deInitPlatform(); + + return !total; +} +