Initial commit
[amiga/OpenBoopsi.git] / include / BoopsiStubs.h
1 #ifndef BOOPSISTUBS_H
2 #define BOOPSISTUBS_H
3 /*
4 **      $Id: boopsistubs.h,v 1.2 2000/07/15 20:45:32 stegerg Exp $
5 **
6 **      Copyright (C) 1997,1999,2000 Bernardo Innocenti <bernie@cosmos.it>
7 **      All rights reserved.
8 **
9 **      Using these inline versions of the amiga.lib boopsi support functions
10 **      results in faster and smaller code against their linked library
11 **      counterparts. When debug is active, these functions will also
12 **      validate the parameters you pass in.
13 */
14
15 /* The USE_BOOPSI_STUBS symbol prevents redefinition of the following stubs with
16  * their amiga.lib equivalents. In AmigaOS, this trick works only if you are using
17  * a patched version of <clib/alib_protos.h>
18  */
19 #ifndef USE_BOOPSI_STUBS
20 #define USE_BOOPSI_STUBS
21 #endif /* USE_BOOPSI_STUBS */
22
23
24 #ifndef INTUITION_CLASSES_H
25 #include <intuition/classes.h>
26 #endif /* INTUITION_CLASSES_H */
27
28 #if defined(_AROS)
29
30         #ifndef AROS_DEBUG_H
31         #include <aros/debug.h>
32         #endif /* AROS_DEBUG_H */
33
34         #ifndef AROS_ASMCALL_H
35         #include <aros/asmcall.h>
36         #endif /* AROS_ASMCALL_H */
37
38         #define _CALL_DISPATCHER(entry, cl, o, msg) \
39                 AROS_UFC3(IPTR, entry, \
40                         AROS_UFCA(Class *, cl, A0), \
41                         AROS_UFCA(Object *, o, A2), \
42                         AROS_UFCA(APTR, msg, A1))
43
44         #ifndef INLINE
45         #define INLINE static inline
46         #endif
47
48 #else /* !_AROS */
49
50         #ifndef COMPILERSPECIFIC_H
51         #include "CompilerSpecific.h"
52         #endif /* COMPILERSPECIFIC_H */
53
54         #ifndef DEBUGMACROS_H
55         #include "DebugMacros.h"
56         #endif /* DEBUGMACROS_H */
57
58         /* the _HookPtr type is a shortcut for a pointer to a hook function */
59         typedef ASMCALL IPTR (*HookPtr)
60                 (REG(a0, Class *), REG(a2, Object *), REG(a1, APTR));
61
62         #define _CALL_DISPATCHER(entry, cl, o, msg) \
63                 ((HookPtr)(entry))(cl, o, msg)
64
65 #endif /* _AROS */
66
67
68
69 /* SAS/C is clever enough to inline these even var-args functions, while gcc and egcs
70  * refuse to do it (yikes!).  The GCC versions of these functions are macro blocks
71  * similar to those  used in the inline/#?.h headers.
72  */
73 #if defined(__SASC) || defined (__STORM__)
74
75         INLINE ULONG CoerceMethodA(Class *cl, Object *o, Msg msg)
76         {
77                 ASSERT_VALID_PTR(cl);
78                 ASSERT_VALID_PTR_OR_NULL(o);
79
80                 return _CALL_DISPATCHER(cl->cl_Dispatcher.h_Entry, cl, o, msg);
81         }
82
83         INLINE ULONG DoSuperMethodA(Class *cl, Object *o, Msg msg)
84         {
85                 ASSERT_VALID_PTR(cl);
86                 ASSERT_VALID_PTR_OR_NULL(o);
87
88                 cl = cl->cl_Super;
89                 return _CALL_DISPATCHER(cl->cl_Dispatcher.h_Entry, cl, o, msg);
90         }
91
92         INLINE ULONG DoMethodA(Object *o, Msg msg)
93         {
94                 Class *cl;
95                 ASSERT_VALID_PTR(o);
96                 cl = OCLASS (o);
97                 ASSERT_VALID_PTR(cl);
98
99                 return _CALL_DISPATCHER(cl->cl_Dispatcher.h_Entry, cl, o, msg);
100         }
101
102         INLINE ULONG CoerceMethod(Class *cl, Object *o, ULONG MethodID, ...)
103         {
104                 ASSERT_VALID_PTR(cl);
105                 ASSERT_VALID_PTR_OR_NULL(o);
106
107                 return ((HookPtr)cl->cl_Dispatcher.h_Entry) ((APTR)cl, (APTR)o, (APTR)&MethodID);
108         }
109
110         INLINE ULONG DoSuperMethod(Class *cl, Object *o, ULONG MethodID, ...)
111         {
112                 ASSERT_VALID_PTR(cl);
113                 ASSERT_VALID_PTR_OR_NULL(o);
114
115                 cl = cl->cl_Super;
116                 return ((HookPtr)cl->cl_Dispatcher.h_Entry) ((APTR)cl, (APTR)o, (APTR)&MethodID);
117         }
118
119         INLINE ULONG DoMethod(Object *o, ULONG MethodID, ...)
120         {
121                 Class *cl;
122
123                 ASSERT_VALID_PTR(o);
124                 cl = OCLASS (o);
125                 ASSERT_VALID_PTR(cl);
126
127                 return ((HookPtr)cl->cl_Dispatcher.h_Entry) ((APTR)cl, (APTR)o, (APTR)&MethodID);
128         }
129
130         /* varargs stub for the OM_NOTIFY method */
131         INLINE void NotifyAttrs(Object *o, struct GadgetInfo *gi, ULONG flags, Tag attr1, ...)
132         {
133                 ASSERT_VALID_PTR(o);
134                 ASSERT_VALID_PTR_OR_NULL(gi);
135
136                 DoMethod(o, OM_NOTIFY, &attr1, gi, flags);
137         }
138
139         /* varargs stub for the OM_UPDATE method */
140         INLINE void UpdateAttrs(Object *o, struct GadgetInfo *gi, ULONG flags, Tag attr1, ...)
141         {
142                 ASSERT_VALID_PTR(o);
143                 ASSERT_VALID_PTR_OR_NULL(gi);
144
145                 DoMethod(o, OM_UPDATE, &attr1, gi, flags);
146         }
147
148         /* varargs stub for the OM_SET method. Similar to SetAttrs(), but allows
149          * to pass the GadgetInfo structure
150          */
151         INLINE void SetAttrsGI(Object *o, struct GadgetInfo *gi, ULONG flags, Tag attr1, ...)
152         {
153                 ASSERT_VALID_PTR(o);
154                 ASSERT_VALID_PTR_OR_NULL(gi);
155
156                 DoMethod(o, OM_SET, &attr1, gi, flags);
157         }
158
159 #elif defined(__GNUC__)
160
161         #define CoerceMethodA(cl, o, msg) \
162         ({ \
163                 ASSERT_VALID_PTR(cl); \
164                 ASSERT_VALID_PTR_OR_NULL(o); \
165                 _CALL_DISPATCHER(cl->cl_Dispatcher.h_Entry, cl, o, msg); \
166         })
167
168         #define DoSuperMethodA(cl, o, msg) \
169         ({ \
170                 Class *_cl; \
171                 ASSERT_VALID_PTR(cl); \
172                 ASSERT_VALID_PTR_OR_NULL(o); \
173                 _cl = cl->cl_Super; \
174                 ASSERT_VALID_PTR(_cl); \
175                 _CALL_DISPATCHER(_cl->cl_Dispatcher.h_Entry, _cl, o, msg); \
176         })
177
178         #define DoMethodA(o, msg) \
179         ({ \
180                 Class *_cl; \
181                 ASSERT_VALID_PTR(o); \
182                 _cl = OCLASS(o); \
183                 ASSERT_VALID_PTR(_cl); \
184                 _CALL_DISPATCHER(_cl->cl_Dispatcher.h_Entry, _cl, o, msg); \
185         })
186
187         #define CoerceMethod(cl, o, msg...) \
188         ({ \
189                 IPTR _msg[] = { msg }; \
190                 ASSERT_VALID_PTR(cl); \
191                 ASSERT_VALID_PTR_OR_NULL(o); \
192                 _CALL_DISPATCHER(cl->cl_Dispatcher.h_Entry, cl, o, _msg); \
193         })
194
195         #define DoSuperMethod(cl, o, msg...) \
196         ({ \
197                 Class *_cl; \
198                 IPTR _msg[] = { msg }; \
199                 ASSERT_VALID_PTR(cl); \
200                 ASSERT_VALID_PTR_OR_NULL(o); \
201                 _cl = cl->cl_Super; \
202                 ASSERT_VALID_PTR(_cl); \
203                 _CALL_DISPATCHER(_cl->cl_Dispatcher.h_Entry, _cl, o, _msg); \
204         })
205
206         #define DoMethod(o, msg...) \
207         ({ \
208                 Class *_cl; \
209                 IPTR _msg[] = { msg }; \
210                 ASSERT_VALID_PTR(o); \
211                 _cl = OCLASS(o); \
212                 ASSERT_VALID_PTR_OR_NULL(_cl); \
213                 _CALL_DISPATCHER(_cl->cl_Dispatcher.h_Entry, _cl, o, _msg); \
214         })
215
216         /* Var-args stub for the OM_NOTIFY method */
217         #define NotifyAttrs(o, gi, flags, attrs...) \
218         ({ \
219                 Class *_cl; \
220                 IPTR _attrs[] = { attrs }; \
221                 IPTR _msg[] = { OM_NOTIFY, (IPTR)_attrs, (IPTR)gi, flags }; \
222                 ASSERT_VALID_PTR(o); \
223                 _cl = OCLASS(o); \
224                 ASSERT_VALID_PTR(_cl); \
225                 ASSERT_VALID_PTR_OR_NULL(gi); \
226                 _CALL_DISPATCHER(_cl->cl_Dispatcher.h_Entry, _cl, o, _msg); \
227         })
228
229         /* Var-args stub for the OM_UPDATE method */
230         #define UpdateAttrs(o, gi, flags, attrs...) \
231         ({ \
232                 Class *_cl; \
233                 IPTR _attrs[] = { attrs }; \
234                 IPTR _msg[] = { OM_UPDATE, (IPTR)_attrs, (IPTR)gi, flags }; \
235                 ASSERT_VALID_PTR(o); \
236                 _cl = OCLASS(o); \
237                 ASSERT_VALID_PTR(_cl); \
238                 ASSERT_VALID_PTR_OR_NULL(gi); \
239                 _CALL_DISPATCHER(_cl->cl_Dispatcher.h_Entry, _cl, o, _msg); \
240         })
241 #endif
242
243 #endif /* !BOOPSISTUBS_H */