1 /*
2 
3  Package: dyncall
4  Library: test
5  File: test/plain/test_structs.c
6  Description:
7  License:
8 
9    Copyright (c) 2010-2015 Olivier Chafik <olivier.chafik@gmail.com>
10                       2019 Tassilo Philipp <tphilipp@potion-studios.com>
11 
12    Permission to use, copy, modify, and distribute this software for any
13    purpose with or without fee is hereby granted, provided that the above
14    copyright notice and this permission notice appear in all copies.
15 
16    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
17    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
18    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
19    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
21    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
22    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 
24 */
25 
26 
27 
28 
29 #include "../../dyncall/dyncall.h"
30 #include "../../dyncall/dyncall_signature.h"
31 #include "../../dyncall/dyncall_struct.h"
32 #include "../common/platformInit.h"
33 
34 #define DC_TEST_STRUCT_SIZE(sig, type, s) { \
35 	DCsize expected = sizeof(type), computed = dcStructSize(s);\
36 	printf("struct_%s size: expected = %d, computed = %d: %d\n", sig, (int)expected, (int)computed, (expected == computed)); \
37 	ret = (expected == computed) && ret; \
38 }
39 
40 /* @@@ incomplete and should be makde generally available in dyncall once struct support will make it in */
41 #if defined(DC__OS_Plan9)
42 #  define DEFAULT_STRUCT_ALIGNMENT 4
43 #else
44 #  define DEFAULT_STRUCT_ALIGNMENT DEFAULT_ALIGNMENT
45 #endif
46 
testStructSizes()47 int testStructSizes()
48 {
49 	int ret = 1;
50 
51 	{
52 		typedef struct {
53 			char a, b;
54 		} S;
55 
56 		size_t size;
57 		DCstruct* s = dcNewStruct(2, DEFAULT_STRUCT_ALIGNMENT);
58 		dcStructField(s, DC_SIGCHAR_CHAR, DEFAULT_ALIGNMENT, 1);
59 		dcStructField(s, DC_SIGCHAR_CHAR, DEFAULT_ALIGNMENT, 1);
60 		dcCloseStruct(s);
61 
62 		DC_TEST_STRUCT_SIZE("cc", S, s);
63 		dcFreeStruct(s);
64 	}
65 	{
66 		typedef struct {
67 			char a, b, c;
68 		} S;
69 
70 		size_t size;
71 		DCstruct* s = dcNewStruct(3, DEFAULT_STRUCT_ALIGNMENT);
72 		dcStructField(s, DC_SIGCHAR_CHAR, DEFAULT_ALIGNMENT, 1);
73 		dcStructField(s, DC_SIGCHAR_CHAR, DEFAULT_ALIGNMENT, 1);
74 		dcStructField(s, DC_SIGCHAR_CHAR, DEFAULT_ALIGNMENT, 1);
75 		dcCloseStruct(s);
76 
77 		DC_TEST_STRUCT_SIZE("ccc", S, s);
78 		dcFreeStruct(s);
79 	}
80 	{
81 		typedef struct {
82 			char a;
83 			short b;
84 		} S;
85 
86 		size_t size;
87 		DCstruct* s = dcNewStruct(2, DEFAULT_STRUCT_ALIGNMENT);
88 		dcStructField(s, DC_SIGCHAR_CHAR, DEFAULT_ALIGNMENT, 1);
89 		dcStructField(s, DC_SIGCHAR_SHORT, DEFAULT_ALIGNMENT, 1);
90 		dcCloseStruct(s);
91 
92 		DC_TEST_STRUCT_SIZE("cs", S, s);
93 		dcFreeStruct(s);
94 	}
95 	{
96 		typedef struct {
97 			double a, b, c, d;
98 		} S;
99 
100 		size_t size;
101 		DCstruct* s = dcNewStruct(4, DEFAULT_STRUCT_ALIGNMENT);
102 		dcStructField(s, DC_SIGCHAR_DOUBLE, DEFAULT_ALIGNMENT, 1);
103 		dcStructField(s, DC_SIGCHAR_DOUBLE, DEFAULT_ALIGNMENT, 1);
104 		dcStructField(s, DC_SIGCHAR_DOUBLE, DEFAULT_ALIGNMENT, 1);
105 		dcStructField(s, DC_SIGCHAR_DOUBLE, DEFAULT_ALIGNMENT, 1);
106 		dcCloseStruct(s);
107 
108 		DC_TEST_STRUCT_SIZE("dddd", S, s);
109 		dcFreeStruct(s);
110 	}
111 	{
112 		typedef struct {
113 			char a, b;
114 			void* p[3];
115 		} S;
116 
117 		size_t size;
118 		DCstruct* s = dcNewStruct(3, DEFAULT_STRUCT_ALIGNMENT);
119 		dcStructField(s, DC_SIGCHAR_CHAR, DEFAULT_ALIGNMENT, 1);
120 		dcStructField(s, DC_SIGCHAR_CHAR, DEFAULT_ALIGNMENT, 1);
121 		dcStructField(s, DC_SIGCHAR_POINTER, DEFAULT_ALIGNMENT, 3);
122 		dcCloseStruct(s);
123 
124 		DC_TEST_STRUCT_SIZE("cc[ppp]", S, s);
125 		dcFreeStruct(s);
126 	}
127 	{
128 		typedef struct {
129 			short a;
130 			struct {
131 			char a, b;
132 			void* p[3];
133 			} sub;
134 			short b;
135 		} S;
136 
137 		size_t size;
138 		DCstruct* s = dcNewStruct(3, DEFAULT_STRUCT_ALIGNMENT);
139 		dcStructField(s, DC_SIGCHAR_SHORT, DEFAULT_ALIGNMENT, 1);
140 		dcSubStruct(s, 3, DEFAULT_STRUCT_ALIGNMENT, 1);
141 		dcStructField(s, DC_SIGCHAR_CHAR, DEFAULT_ALIGNMENT, 1);
142 		dcStructField(s, DC_SIGCHAR_CHAR, DEFAULT_ALIGNMENT, 1);
143 		dcStructField(s, DC_SIGCHAR_POINTER, DEFAULT_ALIGNMENT, 3);
144 		dcCloseStruct(s);
145 		dcStructField(s, DC_SIGCHAR_SHORT, DEFAULT_ALIGNMENT, 1);
146 		dcCloseStruct(s);
147 
148 		DC_TEST_STRUCT_SIZE("s{cc[ppp]}s", S, s);
149 		dcFreeStruct(s);
150 	}
151 
152 #define TEST_MONO_STRUCT(sig, type, sigchar) \
153 	{ \
154 		typedef struct { \
155 			type v; \
156 		} S; \
157 		 \
158 		DCstruct* s = dcNewStruct(1, DEFAULT_STRUCT_ALIGNMENT); \
159 		dcStructField(s, sigchar, DEFAULT_ALIGNMENT, 1); \
160 		dcCloseStruct(s); \
161 		 \
162 		DC_TEST_STRUCT_SIZE(sig, S, s); \
163 		dcFreeStruct(s); \
164 	}
165 
166 	TEST_MONO_STRUCT("c", char,               DC_SIGCHAR_CHAR);      // 4 on plan 9 |
167 	TEST_MONO_STRUCT("C", unsigned char,      DC_SIGCHAR_UCHAR);     // 4 on plan 9 |
168 	TEST_MONO_STRUCT("s", short,              DC_SIGCHAR_SHORT);     // 4 on plan 9 |  minimal size of a struct, period?
169 	TEST_MONO_STRUCT("S", unsigned short,     DC_SIGCHAR_USHORT);    // 4 on plan 9 |
170 	TEST_MONO_STRUCT("i", int,                DC_SIGCHAR_INT);
171 	TEST_MONO_STRUCT("I", unsigned int,       DC_SIGCHAR_UINT);
172 	TEST_MONO_STRUCT("j", long,               DC_SIGCHAR_LONG);
173 	TEST_MONO_STRUCT("J", unsigned long,      DC_SIGCHAR_ULONG);
174 	TEST_MONO_STRUCT("l", long long,          DC_SIGCHAR_LONGLONG);
175 	TEST_MONO_STRUCT("L", unsigned long long, DC_SIGCHAR_ULONGLONG);
176 	TEST_MONO_STRUCT("p", void*,              DC_SIGCHAR_POINTER);
177 	TEST_MONO_STRUCT("f", float,              DC_SIGCHAR_FLOAT);
178 	TEST_MONO_STRUCT("d", double,             DC_SIGCHAR_DOUBLE);
179 
180 	return ret;
181 }
182 
183 
184 
185 typedef struct
186 {
187 	char a, b, c;
188 } FewValues;
189 
sum_FewValues(FewValues values)190 double sum_FewValues(FewValues values)
191 {
192 	printf("sum_FewValues(a = %d, b = %d, c = %d)\n", (int)values.a, (int)values.b, (int)values.c);
193 	return ((double)values.a) + ((double)values.b) + ((double)values.c);
194 }
195 
196 
197 typedef struct
198 {
199 	char a, b;
200 	double p[10];
201 } SomeValues;
202 
sum_SomeValues(SomeValues values)203 double sum_SomeValues(SomeValues values)
204 {
205 	return ((double)values.a) + ((double)values.b) + values.p[0] + values.p[1] + values.p[2];
206 }
207 
208 
209 /*int testCallStructs()
210 {
211 	int ret = 1;
212 
213 	DCCallVM* pc = dcNewCallVM(4096);
214 	{
215 		FewValues values;
216 		double calledSum, expectedSum;
217 		DCstruct* s = dcNewStruct(3, DEFAULT_STRUCT_ALIGNMENT);
218 		dcStructField(s, DC_SIGCHAR_CHAR, DEFAULT_ALIGNMENT, 1);
219 		dcStructField(s, DC_SIGCHAR_CHAR, DEFAULT_ALIGNMENT, 1);
220 		dcStructField(s, DC_SIGCHAR_CHAR, DEFAULT_ALIGNMENT, 1);
221 		dcCloseStruct(s);
222 
223 		DC_TEST_STRUCT_SIZE("ccc", FewValues, s);
224 
225 		values.a = 1;
226 		values.b = 2;
227 		values.c = 3;
228 
229 		dcMode(pc, DC_CALL_C_DEFAULT);
230 		dcReset(pc);
231 		printf("BEFORE dcArgStruct\n");
232 		dcArgStruct(pc, s, &values);
233 		printf("AFTER dcArgStruct\n");
234 		calledSum = dcCallDouble(pc, (DCpointer)&sum_FewValues);
235 		expectedSum = sum_FewValues(values);
236 
237 		DC_TEST_INT_EQUAL(expectedSum, calledSum);
238 		dcFreeStruct(s);
239 	}
240 	{
241 		SomeValues values;
242 		double calledSum, expectedSum;
243 		DCstruct* s = dcNewStruct(3, DEFAULT_STRUCT_ALIGNMENT);
244 		dcStructField(s, DC_SIGCHAR_CHAR, DEFAULT_ALIGNMENT, 1);
245 		dcStructField(s, DC_SIGCHAR_CHAR, DEFAULT_ALIGNMENT, 1);
246 		dcStructField(s, DC_SIGCHAR_DOUBLE, DEFAULT_ALIGNMENT, 10);
247 		dcCloseStruct(s);
248 
249 		DC_TEST_STRUCT_SIZE("ccd", SomeValues, s);
250 
251 		values.a = 1;
252 		values.b = 2;
253 		values.p[0] = 10;
254 		values.p[1] = 11;
255 		values.p[2] = 12;
256 
257 		dcMode(pc, DC_CALL_C_DEFAULT);
258 		dcReset(pc);
259 		dcArgStruct(pc, s, &values);
260 		calledSum = dcCallDouble(pc, (DCpointer) &sum_SomeValues);
261 		expectedSum = sum_SomeValues(values);
262 
263 		DC_TEST_INT_EQUAL(expectedSum, calledSum);
264 		dcFreeStruct(s);
265 	}
266 
267 	dcFree(pc);
268 
269 	return ret;
270 }*/
271 
272