1 module allegro5.internal.da5;
2 
3 /*
4  * Issue: MinGW 4.5 and below has a bizzare calling convention when
5  * returning structs. ColorWrapper takes care of the difference in
6  * calling convention. If this wrapper is necessary, then D programs
7  * that use DAllegro5 should link against allegro_color even when they
8  * never call any allegro_color function.
9  *
10  * The following toolchains (to compile Allegro DLLs) are free of this issue:
11  *  - MSVC,
12  *  - maybe MinGW 4.6.
13  * ColorWrapper resolves to a mere binding on all systems that don't
14  * need the caretaking, and allegro_color needs not be linked against
15  * then unless you call a function from allegro_color.
16  *
17  * ColorWrapper is private to DAllegro5. Call ColorWrapper in DAllegro5
18  * outside any "nothrow @nogc extern (C)" because ColorWrapper will
19  * insert attributes itself.
20  */
21 string ColorWrapper(string prefix, string func, string arg_decls, string arg_names)()
22 {
23 	static if (NeedsMinGW4CallingConvention)
24 	{
25 		// Implement a new D function to wrap Allegro's C function,
26 		// fixing the calling convention (see comment for ColorWrapper above).
27 		return
28 			`nothrow @nogc ALLEGRO_COLOR ` ~ func ~ `(` ~ arg_decls ~ `)
29 			{
30 				auto ret = ` ~ prefix ~ func ~ `(` ~ arg_names ~ `);
31 				asm nothrow @nogc
32 				{
33 					sub ESP, 4;
34 				}
35 				return ret;
36 			}`;
37 	}
38 	else
39 	{
40 		// Declare function as a normal C binding.
41 		return
42 			`nothrow @nogc extern (C)
43 			ALLEGRO_COLOR ` ~ func ~ `(` ~ arg_decls ~ `);`;
44 	}
45 }
46 
47 bool NeedsMinGW4CallingConvention() pure nothrow @nogc
48 {
49 	version(ALLEGRO_MINGW_4_5)
50 	{
51 		return true;
52 	}
53 	else
54 	{
55 		return false;
56 	}
57 }