Initial refactoring of callback macros to make sure all compilers are supported
[freeglut] / src / fg_callback_macros.h
1 /*
2  * fg_callback_macros.h
3  *
4  * The freeglut library callback macro file.
5  *
6  * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
7  * Written by Pawel W. Olszta, <olszta@sourceforge.net>
8  * Creation date: Thu Dec 2 1999
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23  * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
24  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  */
27
28 #ifndef FREEGLUT_CALLBACK_MACROS_H
29 #define FREEGLUT_CALLBACK_MACROS_H
30
31 #ifndef FREEGLUT_INTERNAL_H
32 #error "fg_internal.h needs to be included before this header"
33 #endif
34
35 #if 0 /* old. Remove once other testing is complete */
36 /*
37  * EXPAND_WCB() is used as:
38  * 
39  *     EXPAND_WCB arg_list
40  * 
41  * ... where {(arg_list)} is the parameter list.
42  *
43  * This will take the arg_list and extend it by one argument, adding
44  * the argument "userData" to the end of the list.
45  * 
46  * All additional args are to get around trailing ',', argument counts,
47  * and not needing a GCC extension to make this work.
48  *
49  * Minor modification of:
50  * http://stackoverflow.com/questions/5355241/generating-function-declaration-using-a-macro-iteration/5355946#5355946
51  *
52  * Supports up to five arguments
53  */
54
55 /* GCC-specific design that doesn't require per-callback defines */
56
57 #define PP_HAS_ARGS_IMPL2(_0, _1, _2, _3, _4, _5, N, ...) N
58 #define PP_HAS_ARGS_SOURCE() \
59     ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ZERO
60
61 #define PP_HAS_ARGS_IMPL(...) \
62     PP_HAS_ARGS_IMPL2(__VA_ARGS__)
63 #define PP_HAS_ARGS(...) \
64     PP_HAS_ARGS_IMPL(NOT_EXIST, ##__VA_ARGS__, PP_HAS_ARGS_SOURCE())
65
66 #define EXPAND_WCB_ZERO(x) \
67     (userData)
68 #define EXPAND_WCB_ONE_OR_MORE(...) \
69     (__VA_ARGS__, userData)
70
71 #define EXPAND_WCB_DISAMBIGUATE2(has_args, ...) \
72     EXPAND_WCB_ ## has_args (__VA_ARGS__)
73 #define EXPAND_WCB_DISAMBIGUATE(has_args, ...) \
74     EXPAND_WCB_DISAMBIGUATE2(has_args, __VA_ARGS__)
75 #define EXPAND_WCB(...) \
76     EXPAND_WCB_DISAMBIGUATE(PP_HAS_ARGS(__VA_ARGS__), __VA_ARGS__)
77 #endif
78
79 /*
80  * Compiler defines:
81  * FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK: if the compiler supports GCC's varadic macro implementation (AKA, ##__VA_ARGS__)
82  * FG_COMPILER_SUPPORTS_VA_ARGS: if the compiler supports varadic macros
83  */
84
85 #ifdef FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK
86
87  /*
88  * EXPAND_WCB() is used as:
89  *
90  *     EXPAND_WCB arg_list
91  *
92  * ... where {(arg_list)} is the parameter list.
93  *
94  * This will take the arg_list and extend it by one argument, adding
95  * the argument "userData" to the end of the list.
96  *
97  * All additional args are to get around trailing ',', argument counts,
98  * and not needing a GCC extension to make this work.
99  *
100  * Modification of:
101  * http://stackoverflow.com/questions/5355241/generating-function-declaration-using-a-macro-iteration/5355946#5355946
102  *
103  * --------------
104  *
105  * GCC-specific design that doesn't require per-callback defines
106  *
107  * The naming is terrible... and it's very convuluted and complex, but
108  * should not require any modification unless additional arguments are to 
109  * be supported.
110  * 
111  * Supports callbacks up to 5 args (follow the pattern of PP_HAS_ARGS_IMPL2
112  * and PP_HAS_ARGS_SOURCE to add more)
113  *
114  * Edit with care.
115  */
116
117 #define EXPAND_WCB_UNPARAN(...) __VA_ARGS__
118
119 #define PP_HAS_ARGS_IMPL2(_0, _1, _2, _3, _4, _5, N, ...) N
120 #define PP_HAS_ARGS_SOURCE() ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ZERO
121
122 #define PP_HAS_ARGS_IMPL(...) PP_HAS_ARGS_IMPL2( __VA_ARGS__ )
123 #define PP_HAS_ARGS(...) PP_HAS_ARGS_IMPL( NOT_EXIST, ##__VA_ARGS__, PP_HAS_ARGS_SOURCE() )
124
125 #define EXPAND_WCB_ZERO(args, userData) ( userData )
126 #define EXPAND_WCB_ONE_OR_MORE(args, userData) ( EXPAND_WCB_UNPARAN args, userData )
127
128 #define EXPAND_WCB_DISAMBIGUATE(has_args, args, userData) EXPAND_WCB_ ## has_args ( args, userData )
129
130 #define EXPAND_WCB_UNWRAP_ARGS2(args, userData) EXPAND_WCB_DISAMBIGUATE( PP_HAS_ARGS args, args, userData )
131 #define EXPAND_WCB_UNWRAP_ARGS(args) EXPAND_WCB_UNWRAP_ARGS2 args
132
133 #define EXPAND_WCB(cbname) EXPAND_WCB_UNWRAP_ARGS
134
135 #else
136
137 /*
138  * EXPAND_WCB() is used as:
139  * 
140  *     EXPAND_WCB( cbname )(( arg_list, userData ))
141  * 
142  * ... where {(arg_list)} is the parameter list and userData is user
143  * provided data.
144  *
145  * This will take the arg_list and extend it by one argument, adding
146  * the argument "userData" to the end of the list.
147  *
148  * In order for this to work, each callback must have a define that
149  * properly handles the arguments as needed by the callback.
150  * This callback is in the format of EXPAND_WCB_SUB_<cbname>.
151  * Helper functions exist for zero to five parameters: EXPAND_WCB_ZERO,
152  * EXPAND_WCB_ONE, EXPAND_WCB_TWO, EXPAND_WCB_THREE< EXPAND_WCB_FOUR,
153  * and EXPAND_WCB_FIVE. Each handle the callback argument counts.
154  *
155  * An example for the "Entry" callback, where "Entry" is the cbname:
156  * typedef void (* FGCBEntry  )( int );
157  * typedef void (* FGCBEntryUC)( int, FGCBUserData );
158  * #define EXPAND_WCB_SUB_Entry(args) EXPAND_WCB_ONE args
159  */
160
161 #define FG_COMPILER_SUPPORTS_VA_ARGS //XXX (should be compiler defined)
162 #ifdef FG_COMPILER_SUPPORTS_VA_ARGS
163
164 #define EXPAND_WCB_UNPARAN(...) __VA_ARGS__
165 #define EXPAND_WCB_ONE_OR_MORE(args, userData) ( EXPAND_WCB_UNPARAN args, userData )
166
167 #define EXPAND_WCB_ONE(args, userData) EXPAND_WCB_ONE_OR_MORE( args, userData )
168 #define EXPAND_WCB_TWO(args, userData) EXPAND_WCB_ONE_OR_MORE( args, userData )
169 #define EXPAND_WCB_THREE(args, userData) EXPAND_WCB_ONE_OR_MORE( args, userData )
170 #define EXPAND_WCB_FOUR(args, userData) EXPAND_WCB_ONE_OR_MORE( args, userData )
171 #define EXPAND_WCB_FIVE(args, userData) EXPAND_WCB_ONE_OR_MORE( args, userData )
172
173 #else
174
175 //TODO
176 #error "Compiler does not support varadic argument macros"
177
178 #endif
179
180 #define EXPAND_WCB_ZERO(args, userData) ( userData )
181
182 #define EXPAND_WCB(cbname) EXPAND_WCB_SUB_ ## cbname
183
184 /* 
185  * Freeglut callbacks type definitions macros
186  *
187  * Every time a callback is updated in fg_internal.h is updated, this needs updated
188  * if argument counts change, new callbacks are added, or callbacks are removed.
189  */
190
191 #define EXPAND_WCB_SUB_Display(args) EXPAND_WCB_ZERO args
192 #define EXPAND_WCB_SUB_Reshape(args) EXPAND_WCB_TWO args
193 #define EXPAND_WCB_SUB_Position(args) EXPAND_WCB_TWO args
194 #define EXPAND_WCB_SUB_Visibility(args) EXPAND_WCB_ONE args
195 #define EXPAND_WCB_SUB_Keyboard(args) EXPAND_WCB_THREE args
196 #define EXPAND_WCB_SUB_KeyboardUp(args) EXPAND_WCB_THREE args
197 #define EXPAND_WCB_SUB_Special(args) EXPAND_WCB_THREE args
198 #define EXPAND_WCB_SUB_SpecialUp(args) EXPAND_WCB_THREE args
199 #define EXPAND_WCB_SUB_Mouse(args) EXPAND_WCB_FOUR args
200 #define EXPAND_WCB_SUB_MouseWheel(args) EXPAND_WCB_FOUR args
201 #define EXPAND_WCB_SUB_Motion(args) EXPAND_WCB_TWO args
202 #define EXPAND_WCB_SUB_Passive(args) EXPAND_WCB_TWO args
203 #define EXPAND_WCB_SUB_Entry(args) EXPAND_WCB_ONE args
204 #define EXPAND_WCB_SUB_WindowStatus(args) EXPAND_WCB_ONE args
205 #define EXPAND_WCB_SUB_Joystick(args) EXPAND_WCB_FOUR args
206 #define EXPAND_WCB_SUB_OverlayDisplay(args) EXPAND_WCB_ZERO args
207 #define EXPAND_WCB_SUB_SpaceMotion(args) EXPAND_WCB_THREE args
208 #define EXPAND_WCB_SUB_SpaceRotation(args) EXPAND_WCB_THREE args
209 #define EXPAND_WCB_SUB_SpaceButton(args) EXPAND_WCB_TWO args
210 #define EXPAND_WCB_SUB_Dials(args) EXPAND_WCB_TWO args
211 #define EXPAND_WCB_SUB_ButtonBox(args) EXPAND_WCB_TWO args
212 #define EXPAND_WCB_SUB_TabletMotion(args) EXPAND_WCB_TWO args
213 #define EXPAND_WCB_SUB_TabletButton(args) EXPAND_WCB_FOUR args
214 #define EXPAND_WCB_SUB_Destroy(args) EXPAND_WCB_ZERO args
215 #define EXPAND_WCB_SUB_MultiEntry(args) EXPAND_WCB_TWO args
216 #define EXPAND_WCB_SUB_MultiButton(args) EXPAND_WCB_FIVE args
217 #define EXPAND_WCB_SUB_MultiMotion(args) EXPAND_WCB_THREE args
218 #define EXPAND_WCB_SUB_MultiPassive(args) EXPAND_WCB_THREE args
219 #define EXPAND_WCB_SUB_InitContext(args) EXPAND_WCB_ZERO args
220 #define EXPAND_WCB_SUB_AppStatus(args) EXPAND_WCB_ONE args
221
222 #endif
223
224 #endif /* FREEGLUT_CALLBACK_MACROS_H */
225
226 /*** END OF FILE ***/