Mercurial > pub > dyncall > dyncall
comparison 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 |
comparison
equal
deleted
inserted
replaced
484:74a4f682d1ef | 485:0c68b3f91367 |
---|---|
1 /* | |
2 | |
3 Package: dyncall | |
4 Library: test | |
5 File: test/call_suite_aggrs/main.c | |
6 Description: | |
7 License: | |
8 | |
9 Copyright (c) 2022 Tassilo Philipp <tphilipp@potion-studios.com> | |
10 | |
11 Permission to use, copy, modify, and distribute this software for any | |
12 purpose with or without fee is hereby granted, provided that the above | |
13 copyright notice and this permission notice appear in all copies. | |
14 | |
15 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
16 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
17 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
18 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
21 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
22 | |
23 */ | |
24 | |
25 #include "dyncall.h" | |
26 #include "globals.h" | |
27 #include <string.h> | |
28 #include "../common/platformInit.h" | |
29 #include "../common/platformInit.c" /* Impl. for functions only used in this translation unit */ | |
30 | |
31 | |
32 static void* G_callvm; | |
33 | |
34 | |
35 static int find_agg_idx(int* len, const char* sig) | |
36 { | |
37 int i; | |
38 for(i=0; i<G_naggs; ++i) { | |
39 const char* agg_sig = G_agg_sigs[i]; | |
40 *len = strlen(agg_sig); | |
41 if(strncmp(agg_sig, sig, *len) == 0) | |
42 return i; | |
43 } | |
44 return -1; | |
45 } | |
46 | |
47 static int invoke(char const* signature, void* t) | |
48 { | |
49 DCCallVM * p = (DCCallVM*) G_callvm; | |
50 char const * sig = signature; | |
51 char const * sig_args; | |
52 char rtype; | |
53 DCaggr * rtype_a = NULL; | |
54 int rtype_size = 0; | |
55 funptr rtype_a_cmp = NULL; | |
56 char atype; | |
57 int pos = 0; | |
58 int s = 0; | |
59 | |
60 clear_V(); | |
61 | |
62 dcReset(p); | |
63 | |
64 if(*sig == '{' || *sig == '<') { | |
65 int len; | |
66 int i = find_agg_idx(&len, sig); | |
67 if(i == -1) { | |
68 printf("unknown rtype sig at '%s' ;", sig); | |
69 return 0; | |
70 } | |
71 rtype = *sig; | |
72 sig += len; | |
73 | |
74 rtype_size = G_agg_sizes[i]; | |
75 rtype_a_cmp = G_agg_cmpfuncs[i]; | |
76 rtype_a = ((DCaggr*(*)())G_agg_touchdcstfuncs[i])(); | |
77 dcBeginCallAggr(p, rtype_a); | |
78 } | |
79 else | |
80 rtype = *sig++; | |
81 | |
82 sig_args = sig; | |
83 | |
84 while ( (atype = *sig) != '\0') { | |
85 pos++; | |
86 switch(atype) { | |
87 case 'c': dcArgChar (p,K_c[pos]); break; | |
88 case 's': dcArgShort (p,K_s[pos]); break; | |
89 case 'i': dcArgInt (p,K_i[pos]); break; | |
90 case 'j': dcArgLong (p,K_j[pos]); break; | |
91 case 'l': dcArgLongLong(p,K_l[pos]); break; | |
92 case 'p': dcArgPointer (p,K_p[pos]); break; | |
93 case 'f': dcArgFloat (p,K_f[pos]); break; | |
94 case 'd': dcArgDouble (p,K_d[pos]); break; | |
95 case '<': /* union */ | |
96 case '{': /* struct */ | |
97 { | |
98 /* find aggregate sig */ | |
99 int len; | |
100 DCaggr *ag; | |
101 int i = find_agg_idx(&len, sig); | |
102 if(i == -1) { | |
103 printf("unknown sig at '%s' ;", sig); | |
104 return 0; | |
105 } | |
106 ag = ((DCaggr*(*)())G_agg_touchdcstfuncs[i])(); | |
107 dcArgAggr(p, ag, K_a[pos]); | |
108 sig += len-1; /* advance to next arg char */ | |
109 break; | |
110 } | |
111 default: printf("unknown atype '%c' (1) ;", atype); return 0; | |
112 } | |
113 ++sig; | |
114 } | |
115 | |
116 switch(rtype) | |
117 { | |
118 case 'v': dcCallVoid(p,t); s=1; /*TODO:check that no return-arg was touched.*/ break; | |
119 case 'c': s = (dcCallChar (p,t) == K_c[pos]) ; break; | |
120 case 's': s = (dcCallShort (p,t) == K_s[pos]) ; break; | |
121 case 'i': s = (dcCallInt (p,t) == K_i[pos]) ; break; | |
122 case 'j': s = (dcCallLong (p,t) == K_j[pos]) ; break; | |
123 case 'l': s = (dcCallLongLong(p,t) == K_l[pos]) ; break; | |
124 case 'p': s = (dcCallPointer (p,t) == K_p[pos]) ; break; | |
125 case 'f': s = (dcCallFloat (p,t) == K_f[pos]) ; break; | |
126 case 'd': s = (dcCallDouble (p,t) == K_d[pos]) ; break; | |
127 case '<': /* union */ | |
128 case '{': /* struct */ | |
129 { | |
130 /* bound check memory adjacent to returned aggregate, to check for overflows by dcCallAggr */ | |
131 long long* adj_ll = (get_max_aggr_size() - rtype_size) > sizeof(long long) ? (long long*)((char*)V_a[0] + rtype_size) : NULL; | |
132 if(adj_ll) | |
133 *adj_ll = 0x0123456789abcdef; | |
134 | |
135 s = ((int(*)(const void*,const void*))rtype_a_cmp)(dcCallAggr(p, t, rtype_a, V_a[0]), K_a[pos]); | |
136 | |
137 if(adj_ll && *adj_ll != 0x0123456789abcdef) { | |
138 printf("writing rval overflowed into adjacent memory;"); | |
139 return 0; | |
140 } | |
141 break; | |
142 } | |
143 default: printf("unknown rtype '%c'", rtype); return 0; | |
144 } | |
145 | |
146 if (!s) { printf("rval wrong;"); return 0; } | |
147 | |
148 /* test V_* array against values passed to func: */ | |
149 sig = sig_args; | |
150 pos = 1; | |
151 while ( (atype = *sig) != '\0') { | |
152 switch(atype) { | |
153 case 'c': s = ( V_c[pos] == K_c[pos] ); if (!s) printf("'c':%d: %d != %d ; ", pos, V_c[pos], K_c[pos]); break; | |
154 case 's': s = ( V_s[pos] == K_s[pos] ); if (!s) printf("'s':%d: %d != %d ; ", pos, V_s[pos], K_s[pos]); break; | |
155 case 'i': s = ( V_i[pos] == K_i[pos] ); if (!s) printf("'i':%d: %d != %d ; ", pos, V_i[pos], K_i[pos]); break; | |
156 case 'j': s = ( V_j[pos] == K_j[pos] ); if (!s) printf("'j':%d: %ld != %ld ; ", pos, V_j[pos], K_j[pos]); break; | |
157 case 'l': s = ( V_l[pos] == K_l[pos] ); if (!s) printf("'l':%d: %lld != %lld ; ", pos, V_l[pos], K_l[pos]); break; | |
158 case 'p': s = ( V_p[pos] == K_p[pos] ); if (!s) printf("'p':%d: %p != %p ; ", pos, V_p[pos], K_p[pos]); break; | |
159 case 'f': s = ( V_f[pos] == K_f[pos] ); if (!s) printf("'f':%d: %f != %f ; ", pos, V_f[pos], K_f[pos]); break; | |
160 case 'd': s = ( V_d[pos] == K_d[pos] ); if (!s) printf("'d':%d: %f != %f ; ", pos, V_d[pos], K_d[pos]); break; | |
161 case '<': /* union */ | |
162 case '{': /* struct */ | |
163 { | |
164 /* no check: guaranteed to exist, or invoke func would've exited when passing args, above */ | |
165 int len; | |
166 int i = find_agg_idx(&len, sig); | |
167 s = ((int(*)(const void*,const void*))G_agg_cmpfuncs[i])(V_a[pos], K_a[pos]); | |
168 if (!s) printf("'%c':%d: *%p != *%p ; ", atype, pos, V_a[pos], K_a[pos]); | |
169 sig += len-1; /* advance to next arg char */ | |
170 break; | |
171 } | |
172 default: printf("unknown atype '%c' ; ", atype); return 0; | |
173 } | |
174 if (!s) { | |
175 printf("arg mismatch at %d ; ", pos); | |
176 return 0; | |
177 } | |
178 ++sig; | |
179 ++pos; | |
180 } | |
181 return 1; | |
182 } | |
183 | |
184 int run_test(int i) | |
185 { | |
186 char const * sig; | |
187 void * target; | |
188 int success; | |
189 sig = G_sigtab[i]; | |
190 target = (void*) G_funtab[i]; | |
191 printf("%d:%s:",i,sig); | |
192 success = invoke(sig,target); | |
193 printf("%d\n",success); | |
194 return success; | |
195 } | |
196 | |
197 int run_all() | |
198 { | |
199 int i; | |
200 int failure = 0; | |
201 for(i=0;i<G_ncases;++i) | |
202 failure |= !( run_test(i) ); | |
203 | |
204 return !failure; | |
205 } | |
206 | |
207 int main(int argc, char* argv[]) | |
208 { | |
209 int total, i; | |
210 | |
211 dcTest_initPlatform(); | |
212 | |
213 init_test_data(G_maxargs); | |
214 G_callvm = (DCCallVM*) dcNewCallVM(32768); | |
215 | |
216 dcReset(G_callvm); | |
217 total = run_all(); | |
218 | |
219 /* free all DCaggrs created on the fly */ | |
220 for(i=0; i<G_naggs; ++i) | |
221 dcFreeAggr(((DCaggr*(*)())G_agg_touchdcstfuncs[i])()); | |
222 | |
223 dcFree(G_callvm); | |
224 deinit_test_data(G_maxargs); | |
225 | |
226 printf("result: call_suite_aggrs: %d\n", total); | |
227 | |
228 dcTest_deInitPlatform(); | |
229 | |
230 return !total; | |
231 } | |
232 |