1 #ifndef MX_H
2 #define MX_H
3 
4 /*
5   mx -- Marc's eXtension modules for Python: basic macros
6 
7   This file is only meant to be included by the extension modules.
8   DO NOT include it in the extension module's header file, since it
9   will definitely cause troubles then.
10 
11   To enable debugging ceratin things, define one of these before
12   including this file:
13 
14   MAL_REF_DEBUG -- debug reference counts (Py_MY_xxx) [this file]
15   MAL_DEBUG     -- enable debug output (DPRINTF) [mxstdlib.h]
16   MAL_MEM_DEBUG -- enable malloc output (new,cnew,free,...) [mxstdlib.h]
17 
18   Copyright (c) 2000, Marc-Andre Lemburg; mailto:mal@lemburg.com
19   Copyright (c) 2000-2002, eGenix.com Software GmbH; mailto:info@egenix.com
20   See the documentation for further copyright information or contact
21   the author.
22 
23 */
24 
25 /* --- Platform or compiler specific tweaks ------------------------------- */
26 
27 /* Add some platform specific symbols to enable work-arounds for the
28    static forward declaration of type definitions; note that the GNU C
29    compiler does not have this problem.
30 
31    Many thanks to all who have contributed to this list.
32 
33 */
34 #if (!defined(__GNUC__))
35 # if (defined(NeXT) || defined(sgi) || defined(_AIX) || (defined(__osf__) && defined(__DECC)) || defined(TrueCompaq64) || defined(__VMS))
36 #  define BAD_STATIC_FORWARD
37 # endif
38 #endif
39 
40 /* Some more tweaks for various platforms. */
41 
42 /* VMS needs this define. Thanks to Jean-François PIÉRONNE */
43 #if defined(__VMS)
44 # define __SC__
45 #endif
46 
47 /* xlC on AIX doesn't like the Python work-around for static forwards
48    in ANSI mode (default), so we switch on extended mode. Thanks to
49    Albert Chin-A-Young */
50 #if defined(__xlC__)
51 # pragma langlvl extended
52 #endif
53 
54 /* --- Standard header files ---------------------------------------------- */
55 
56 /* Include the generic mx header file */
57 #include "mxh.h"
58 
59 /* Include nearly all Python symbols & definitions */
60 #include "Python.h"
61 
62 /* Include other standard stuff */
63 #include "mxstdlib.h"
64 
65 /* Include Python backward compatibility stuff */
66 #include "mxpyapi.h"
67 
68 /* --- Compiler support --------------------------------------------------- */
69 
70 /* Support for compilers which don't like static forward declarations
71    of arrays; Python 2.3 removed the support for BAD_STATIC_FORWARD
72    which is why we now use our own little helpers here. */
73 #undef staticforward
74 #undef statichere
75 #ifdef BAD_STATIC_FORWARD
76 # define staticforward extern
77 # define statichere static
78 #else
79 # define staticforward static
80 # define statichere static
81 #endif
82 
83 /* --- Declare macros ----------------------------------------------------- */
84 
85 #define Py_NONE (Py_INCREF(Py_None),Py_None)
86 
87 #ifdef MAL_REF_DEBUG
88 # define printref(x) printf("* refcount for "#x" = %i\n",(long) x->ob_refcnt);
89 #else
90 # define printref(x)
91 #endif
92 
93 /* --- Error handling ----------------------------------------------------- */
94 
95 #define Py_Do(x) {if (!(x)) goto onError;}
96 #define Py_ReturnOnError(errortype,errorstr) {PyErr_SetString(errortype,errorstr);return NULL;}
97 
98 #define Py_Assert(x,errortype,errorstr) {if (!(x)) {PyErr_SetString(errortype,errorstr);goto onError;}}
99 #define Py_AssertWithArg(x,errortype,errorstr,a1) {if (!(x)) {PyErr_Format(errortype,errorstr,a1);goto onError;}}
100 #define Py_AssertWith2Args(x,errortype,errorstr,a1,a2) {if (!(x)) {PyErr_Format(errortype,errorstr,a1,a2);goto onError;}}
101 #define Py_AssertWith3Args(x,errortype,errorstr,a1,a2,a3) {if (!(x)) {PyErr_Format(errortype,errorstr,a1,a2,a3);goto onError;}}
102 
103 #define Py_Error(errortype,errorstr) {PyErr_SetString(errortype,errorstr);goto onError;}
104 #define Py_ErrorWithArg(errortype,errorstr,a1) {PyErr_Format(errortype,errorstr,a1);goto onError;}
105 #define Py_ErrorWith2Args(errortype,errorstr,a1,a2) {PyErr_Format(errortype,errorstr,a1,a2);goto onError;}
106 #define Py_ErrorWith3Args(errortype,errorstr,a1,a2,a3) {PyErr_Format(errortype,errorstr,a1,a2,a3);goto onError;}
107 
108 /* --- Reference counting ------------------------------------------------- */
109 
110 #ifdef MAL_REF_DEBUG
111 
mx_Py_INCREF(PyObject * v,char * name,char * filename,int lineno)112 static void mx_Py_INCREF(PyObject *v,
113 			 char *name,
114 			 char *filename,
115 			 int lineno)
116 {
117     if (!Py_DebugFlag) {
118 	Py_XINCREF(v);
119 	return;
120     }
121     if (!v)
122 	mxDebugPrintf("[%s:%5i] Py_XINCREF( %-8s == NULL );\n",
123 		      filename,lineno,name);
124     else {
125 	Py_INCREF(v);;
126 	mxDebugPrintf("[%s:%5i] Py_XINCREF( %-8s at 0x%x [%s]); "
127 		      "new refcount = %i\n",
128 		      filename,lineno,name,(int)v,Py_TYPE(v)->tp_name,
129 		      v->ob_refcnt);
130     }
131 }
132 
mx_Py_DECREF(PyObject * v,char * name,char * filename,int lineno)133 static void mx_Py_DECREF(PyObject *v,
134 			 char *name,
135 			 char *filename,
136 			 int lineno)
137 {
138     if (!Py_DebugFlag) {
139 	Py_XDECREF(v);
140 	return;
141     }
142     if (!v)
143 	mxDebugPrintf("[%s:%5i] Py_XDECREF( %-8s == NULL );\n",
144 		      filename,lineno,name);
145     else {
146 	int refcnt = v->ob_refcnt;
147 	Py_DECREF(v);
148 	if (refcnt <= 1)
149 	    mxDebugPrintf("[%s:%5i] Py_XDECREF( %-8s at 0x%x [%s]); "
150 			  "object deleted\n",
151 			  filename,lineno,name,(int)v,Py_TYPE(v)->tp_name);
152 	else
153 	    mxDebugPrintf("[%s:%5i] Py_XDECREF( %-8s at 0x%x [%s]); "
154 			  "new refcount = %i\n",
155 			  filename,lineno,name,(int)v,Py_TYPE(v)->tp_name,
156 			  v->ob_refcnt);
157     }
158 }
159 
mx_Py_PRINT_REFCOUNT(PyObject * v,char * name,char * filename,int lineno)160 static void mx_Py_PRINT_REFCOUNT(PyObject *v,
161 				 char *name,
162 				 char *filename,
163 				 int lineno)
164 {
165     if (!v)
166 	mxDebugPrintf("[%s:%5i] Py_PRINT_REFCOUNT( %-8s == NULL );\n",
167 		      filename,lineno,name);
168     else {
169 	mxDebugPrintf("[%s:%5i] Py_PRINT_REFCOUNT( %-8s at 0x%x [%s]) = %i;\n",
170 		      filename,lineno,name,(int)v,Py_TYPE(v)->tp_name,
171 		      v->ob_refcnt);
172     }
173 }
174 
175 # undef Py_INCREF
176 # define Py_INCREF(x) mx_Py_INCREF((PyObject *)x,#x,__FILE__,__LINE__)
177 # undef Py_DECREF
178 # define Py_DECREF(x) mx_Py_DECREF((PyObject *)x,#x,__FILE__,__LINE__)
179 # undef Py_XINCREF
180 # define Py_XINCREF(x) mx_Py_INCREF((PyObject *)x,#x,__FILE__,__LINE__)
181 # undef Py_XDECREF
182 # define Py_XDECREF(x) mx_Py_DECREF((PyObject *)x,#x,__FILE__,__LINE__)
183 # define Py_DELETE(x) {if (x->ob_refcnt > 1) mxDebugPrintf("[%s:%5i] Py_DELETE( "#x" ) WARNING: Refcount = %i > 1\n",__FILE__,__LINE__,(int)x->ob_refcnt);Py_DECREF(x);}
184 # define Py_PRINT_REFCOUNT(x) mx_Py_PRINT_REFCOUNT((PyObject *)x,#x,__FILE__,__LINE__)
185 #else
186 # define Py_DELETE(x) Py_DECREF(x)
187 # define Py_PRINT_REFCOUNT(x)
188 #endif
189 
190 #define Py_DEC_REF(x) {Py_XDECREF(x); x=0;} /* doing this once too often doesn't hurt */
191 
192 /* Unreference a Python object. This is only used in Python debug
193    builds and needed to keep track of all allocated references. Use in
194    object constructors or free list implementations.  */
195 #ifndef _Py_DEC_REFTOTAL
196 # ifdef Py_REF_DEBUG
197 #  define _Py_DEC_REFTOTAL _Py_RefTotal--
198 # else
199 #  define _Py_DEC_REFTOTAL
200 # endif
201 #endif
202 #define mxPy_UNREF(x) _Py_DEC_REFTOTAL
203 
204 /* --- Argument passing and checking -------------------------------------- */
205 
206 /* No arguments expected; also use Py_MethodListEntryNoArgs() for this
207    kind of fct; this check is no longer needed in Python 2.3 and
208    later */
209 #if PY_VERSION_HEX >= 0x02030000
210 # define Py_NoArgsCheck() {if (0) goto onError;}
211 #else
212 # define Py_NoArgsCheck() {if (!PyArg_NoArgs(args)) goto onError;}
213 #endif
214 
215 /* For functions with old style args (Py_MethodListEntrySingleArg) */
216 #define Py_GetArgObject(a) {a = args; if (!a) {PyErr_SetString(PyExc_TypeError,"function/method requires an argument"); goto onError;}}
217 #define Py_GetSingleArg(format,a1) {if (!PyArg_Parse(args,format,&a1)) goto onError;}
218 
219 /* For functions with new style args: */
220 #define Py_GetArg(format,a1) {if (!PyArg_ParseTuple(args,format,&a1)) goto onError;}
221 #define Py_Get2Args(format,a1,a2) {if (!PyArg_ParseTuple(args,format,&a1,&a2)) goto onError;}
222 #define Py_Get3Args(format,a1,a2,a3) {if (!PyArg_ParseTuple(args,format,&a1,&a2,&a3)) goto onError;}
223 #define Py_Get4Args(format,a1,a2,a3,a4) {if (!PyArg_ParseTuple(args,format,&a1,&a2,&a3,&a4)) goto onError;}
224 #define Py_Get5Args(format,a1,a2,a3,a4,a5) {if (!PyArg_ParseTuple(args,format,&a1,&a2,&a3,&a4,&a5)) goto onError;}
225 #define Py_Get6Args(format,a1,a2,a3,a4,a5,a6) {if (!PyArg_ParseTuple(args,format,&a1,&a2,&a3,&a4,&a5,&a6)) goto onError;}
226 #define Py_Get7Args(format,a1,a2,a3,a4,a5,a6,a7) {if (!PyArg_ParseTuple(args,format,&a1,&a2,&a3,&a4,&a5,&a6,&a7)) goto onError;}
227 #define Py_Get8Args(format,a1,a2,a3,a4,a5,a6,a7,a8) {if (!PyArg_ParseTuple(args,format,&a1,&a2,&a3,&a4,&a5,&a6,&a7,&a8)) goto onError;}
228 
229 /* For functions with keywords -- the first macro parameter must be
230    the keywords array given as e.g.
231 
232    static char *keywords[] = {"first","second","third", 0};
233 
234    with an entry for every argument (in the correct order). The
235    functions must be included in the method list using
236    Py_MethodWithKeywordsListEntry() and be declared as
237    Py_C_Function_WithKeywords().
238 
239 */
240 #define Py_KeywordGetArg(keywords,format,a1) {if (!PyArg_ParseTupleAndKeywords(args,kws,format,keywords,&a1)) goto onError;}
241 #define Py_KeywordGet2Args(keywords,format,a1,a2) {if (!PyArg_ParseTupleAndKeywords(args,kws,format,keywords,&a1,&a2)) goto onError;}
242 #define Py_KeywordGet3Args(keywords,format,a1,a2,a3) {if (!PyArg_ParseTupleAndKeywords(args,kws,format,keywords,&a1,&a2,&a3)) goto onError;}
243 #define Py_KeywordGet4Args(keywords,format,a1,a2,a3,a4) {if (!PyArg_ParseTupleAndKeywords(args,kws,format,keywords,&a1,&a2,&a3,&a4)) goto onError;}
244 #define Py_KeywordGet5Args(keywords,format,a1,a2,a3,a4,a5) {if (!PyArg_ParseTupleAndKeywords(args,kws,format,keywords,&a1,&a2,&a3,&a4,&a5)) goto onError;}
245 #define Py_KeywordGet6Args(keywords,format,a1,a2,a3,a4,a5,a6) {if (!PyArg_ParseTupleAndKeywords(args,kws,format,keywords,&a1,&a2,&a3,&a4,&a5,&a6)) goto onError;}
246 #define Py_KeywordGet7Args(keywords,format,a1,a2,a3,a4,a5,a6,a7) {if (!PyArg_ParseTupleAndKeywords(args,kws,format,keywords,&a1,&a2,&a3,&a4,&a5,&a6,&a7)) goto onError;}
247 #define Py_KeywordGet8Args(keywords,format,a1,a2,a3,a4,a5,a6,a7,a8) {if (!PyArg_ParseTupleAndKeywords(args,kws,format,keywords,&a1,&a2,&a3,&a4,&a5,&a6,&a7,&a8)) goto onError;}
248 
249 /* New style macros fof functions supporting keywords -- the C
250    variable names are used as template for the keyword list, i.e. they
251    must match the Python keyword parameter names.
252 
253    Note that format strings with special parameters (e.g. "#s") are
254    not allowed since they would cause the keyword list to be out of
255    sync.
256 
257    The functions must be included in the method list using
258    Py_MethodWithKeywordsListEntry() and be declared as
259    Py_C_Function_WithKeywords().
260 
261    Example:
262 
263     Py_C_Function_WithKeywords(
264         myfunction,
265 	"myfunction(filename,dupkeys=0,filemode=0,sectorsize=512)\n\n"
266 	"Returns a myobject"
267 	)
268     {
269 	char *filename;
270 	int sectorsize = 512;
271 	int dupkeys = 0;
272 	int filemode = 0;
273 
274 	Py_KeywordsGet4Args("s|iii",
275 			    filename,dupkeys,filemode,sectorsize);
276 
277 	return (PyObject *)myobject_New(filename,
278 	                                filemode,
279 					sectorsize,
280 					dupkeys);
281      onError:
282 	return NULL;
283     }
284 
285 */
286 #define Py_KeywordsGetArg(format,a1) {static char *kwslist[] = {#a1,NULL}; if (!PyArg_ParseTupleAndKeywords(args,kws,format,kwslist,&a1)) goto onError;}
287 #define Py_KeywordsGet2Args(format,a1,a2) {static char *kwslist[] = {#a1,#a2,NULL}; if (!PyArg_ParseTupleAndKeywords(args,kws,format,kwslist,&a1,&a2)) goto onError;}
288 #define Py_KeywordsGet3Args(format,a1,a2,a3) {static char *kwslist[] = {#a1,#a2,#a3,NULL}; if (!PyArg_ParseTupleAndKeywords(args,kws,format,kwslist,&a1,&a2,&a3)) goto onError;}
289 #define Py_KeywordsGet4Args(format,a1,a2,a3,a4) {static char *kwslist[] = {#a1,#a2,#a3,#a4,NULL}; if (!PyArg_ParseTupleAndKeywords(args,kws,format,kwslist,&a1,&a2,&a3,&a4)) goto onError;}
290 #define Py_KeywordsGet5Args(format,a1,a2,a3,a4,a5) {static char *kwslist[] = {#a1,#a2,#a3,#a4,#a5,NULL}; if (!PyArg_ParseTupleAndKeywords(args,kws,format,kwslist,&a1,&a2,&a3,&a4,&a5)) goto onError;}
291 #define Py_KeywordsGet6Args(format,a1,a2,a3,a4,a5,a6) {static char *kwslist[] = {#a1,#a2,#a3,#a4,#a5,#a6,NULL}; if (!PyArg_ParseTupleAndKeywords(args,kws,format,kwslist,&a1,&a2,&a3,&a4,&a5,&a6)) goto onError;}
292 #define Py_KeywordsGet7Args(format,a1,a2,a3,a4,a5,a6,a7) {static char *kwslist[] = {#a1,#a2,#a3,#a4,#a5,#a6,#a7,NULL}; if (!PyArg_ParseTupleAndKeywords(args,kws,format,kwslist,&a1,&a2,&a3,&a4,&a5,&a6,&a7)) goto onError;}
293 #define Py_KeywordsGet8Args(format,a1,a2,a3,a4,a5,a6,a7,a8) {static char *kwslist[] = {#a1,#a2,#a3,#a4,#a5,#a6,#a7,#a8,NULL}; if (!PyArg_ParseTupleAndKeywords(args,kws,format,kwslist,&a1,&a2,&a3,&a4,&a5,&a6,&a7,&a8)) goto onError;}
294 
295 /* --- Returning values to Python ----------------------------------------- */
296 
297 /* XXX Don't always work: every time you have an 'O' in the BuildValue format
298        string, you need to DECREF the variable *after* the tuple has been
299        built !!!
300 */
301 
302 #define Py_ReturnNone() {Py_INCREF(Py_None);return Py_None;}
303 #define Py_ReturnTrue() {Py_INCREF(Py_True);return Py_True;}
304 #define Py_ReturnFalse() {Py_INCREF(Py_False);return Py_False;}
305 #define Py_ReturnArg(format,a1) return Py_BuildValue(format,a1);
306 #define Py_Return Py_ReturnArg
307 #define Py_Return2Args(format,a1,a2) return Py_BuildValue(format,a1,a2);
308 #define Py_Return2 Py_Return2Args
309 #define Py_Return3Args(format,a1,a2,a3) return Py_BuildValue(format,a1,a2,a3);
310 #define Py_Return3 Py_Return3Args
311 #define Py_Return4Args(format,a1,a2,a3) return Py_BuildValue(format,a1,a2,a3,a4);
312 #define Py_Return5Args(format,a1,a2,a3) return Py_BuildValue(format,a1,a2,a3,a4,a5);
313 #define Py_Return6Args(format,a1,a2,a3) return Py_BuildValue(format,a1,a2,a3,a4,a5,a6);
314 #define Py_Return7Args(format,a1,a2,a3) return Py_BuildValue(format,a1,a2,a3,a4,a5,a6,a7);
315 
316 /* Build values */
317 
318 #define Py_BuildNone() Py_NONE
319 #define Py_Build(format,x) Py_BuildValue(format,x)
320 #define Py_Build2(format,x,y) Py_BuildValue(format,x,y)
321 #define Py_Build3(format,x,y,z) Py_BuildValue(format,x,y,z)
322 
323 /* --- Declaring Python builtin functions/methods ------------------------- */
324 
325 /* Declare C function/method fct, having docstring docstr; may use vargargs */
326 #define Py_C_Function(fct,docstr) \
327         static char fct##_docstring[] = docstr;\
328         static PyObject *fct(PyObject *self, PyObject *args)
329 
330 /* Declare C function/method fct, having keywords keywordsarray and a
331    docstring docstr; may use vargargs & keywords */
332 #define Py_C_Function_WithKeywords(fct,docstr) \
333         static char fct##_docstring[] = docstr;\
334         static PyObject *fct(PyObject *self, PyObject *args, PyObject *kws)
335 
336 /* These declare: self -- instance pointer for methods, NULL for functions
337                   args -- argument tuple
338 		  kws  -- keywords dict (if applicable)
339    plus as statics:
340                   <function name>_docstring -- the docstring as given
341 		  <function name>_keywords  -- the keyword array as given
342 
343    Note: use the Py_GetArg macros for functions without keywords,
344              and Py_KeywordGetArg macros for functions with keywords
345 */
346 
347 /* --- Method list entries for builtin functions/methods ------------------ */
348 
349 /* Add a C function/method cname to the module dict as pyname; no
350    doc-string */
351 #define Py_MethodListEntryAny(pyname,cname) {pyname,(PyCFunction)cname,METH_VARARGS}
352 
353 /* Add a C function/method cname to the module dict as pyname; the
354    function can use varargs */
355 #define Py_MethodListEntry(pyname,cname) {pyname,(PyCFunction)cname,METH_VARARGS,cname##_docstring}
356 
357 /* Add a C function/method cname to the module dict as pyname; the
358    function takes no args; in Python 2.3 a new flag was added for
359    these which implements the no args check in the interpreter
360    itself. */
361 #ifdef METH_NOARGS
362 # define Py_MethodListEntryNoArgs(pyname,cname) {pyname,(PyCFunction)cname,METH_NOARGS,cname##_docstring}
363 #else
364 # define Py_MethodListEntryNoArgs(pyname,cname) {pyname,(PyCFunction)cname,0,cname##_docstring}
365 #endif
366 
367 /* Add a C function/method cname to the module dict as pyname; the
368    function takes one argument: the object is passed in directly
369    (without wrapping it into a tuple first), i.e. don't use
370    the Py_GetArg-macros or PyArg_ParseTuple().
371 
372    This breaks on Python 3.8, where functions get checked such that
373    we can't do this kind of hackery... but the real question is
374    how did this work before? Like how could you call these functions
375    when the calling mechanism itself wasn't something Python
376    understood.
377    */
378 #define Py_MethodListEntrySingleArg(pyname,cname) {pyname,(PyCFunction)cname,0,cname##_docstring}
379 
380 /* Add a C function/method that uses keywords to the module dict */
381 #define Py_MethodWithKeywordsListEntry(pyname,cname) {pyname,(PyCFunction)cname,METH_VARARGS | METH_KEYWORDS,cname##_docstring}
382 
383 
384 /* --- Sequence slicing --------------------------------------------------- */
385 
386 /* Check a given slice and apply the usual rules for negative indices */
387 #define Py_CheckSequenceSlice(len,start,stop) {	\
388 	    if (stop > len)			\
389 		stop = len;			\
390 	    else {				\
391 		if (stop < 0)			\
392 		    stop += len;		\
393 		if (stop < 0)			\
394 		    stop = 0;			\
395 	    }					\
396 	    if (start < 0) {			\
397 		start += len;			\
398 		if (start < 0)			\
399 		    start = 0;			\
400 	    }					\
401 	    if (stop < start)			\
402 		start = stop;			\
403 	}
404 
405 /* --- Text macros -------------------------------------------------------- */
406 
407 /* Check a given text slice and apply the usual rules for negative
408    indices */
409 #define Py_CheckBufferSlice(textlen,start,stop) \
410         Py_CheckSequenceSlice(textlen,start,stop)
411 
412 /* Dito for string objects */
413 #define Py_CheckStringSlice(textobj,start,stop) \
414         Py_CheckSequenceSlice(PyString_GET_SIZE(textobj),start,stop)
415 
416 /* For b/w compatibility */
417 #define Py_CheckSlice(textobj,start,stop) \
418         Py_CheckStringSlice(textobj,start,stop)
419 
420 /* Dito for Unicode objects */
421 #ifdef PyUnicode_GET_SIZE
422 # define Py_CheckUnicodeSlice(unicode,start,stop) \
423          Py_CheckSequenceSlice(PyUnicode_GET_SIZE(unicode),start,stop)
424 #endif
425 
426 /* This assumes that fixed is a constant char array; the strcmp
427    function is only called in case the attribute name length exceeds
428    10 characters and the first 10 characters match; optimizing
429    compilers should eliminate any unused parts of this comparison
430    automatically.
431 
432    Note: The latest egcs compiler warns about the subscripts being out
433    of range for shorter fixed strings; since no code is generated for
434    those comparisons, these warning can safely be ignored. Still, they
435    are annoying. See the Py_StringsCompareEqual() macro below for a
436    way to work around this.
437 
438 */
439 #define Py_StringsCompareEqualEx(var,fixed,fixedsize)			\
440      (var[0] == fixed[0] &&						\
441       (fixed[0] == 0 ||							\
442        (fixedsize >= 1 && (var[1] == fixed[1] &&			\
443 	(fixed[1] == 0 ||						\
444 	 (fixedsize >= 2 && (var[2] == fixed[2] &&			\
445 	  (fixed[2] == 0 ||						\
446 	   (fixedsize >= 3 && (var[3] == fixed[3] &&			\
447 	    (fixed[3] == 0 ||					       	\
448 	     (fixedsize >= 4 && (var[4] == fixed[4] &&			\
449 	      (fixed[4] == 0 ||						\
450 	       (fixedsize >= 5 && (var[5] == fixed[5] &&		\
451 		(fixed[5] == 0 ||					\
452 		 (fixedsize >= 6 && (var[6] == fixed[6] &&		\
453 		  (fixed[6] == 0 ||					\
454 		   (fixedsize >= 7 && (var[7] == fixed[7] &&		\
455 		    (fixed[7] == 0 ||					\
456 		     (fixedsize >= 8 && (var[8] == fixed[8] &&		\
457 		      (fixed[8] == 0 ||					\
458 		       (fixedsize >= 9 && (var[9] == fixed[9] &&	\
459 			(fixed[9] == 0 ||				\
460 			 (fixedsize >= 10 &&				\
461 			  strcmp(&var[10],&fixed[10]) == 0		\
462 			 ))))))))))))))))))))))))))))))
463 
464 /* This assumes that fixed is a constant char array.
465 
466    The appended string snippet is to shut up the warnings produced by
467    newer egcs/gcc compilers about offsets being outside bounds.
468 
469    Note that some compilers do the inlining by themselves or don't
470    like the above trick (OpenVMS is one such platform). For these we
471    simply use the standard way.
472 
473 */
474 
475 #ifndef __VMS
476 # define Py_StringsCompareEqual(var,fixed)				\
477      Py_StringsCompareEqualEx(var,fixed"\0\0\0\0\0\0\0\0\0\0",sizeof(fixed))
478 #else
479 # define Py_StringsCompareEqual(var,fixed) (strcmp(var, fixed) == 0)
480 #endif
481 
482 /* Fast character set member check; set must be a "static unsigned
483    *char set" array of exactly 32 bytes length generated with
484    TextTools.set() */
485 #define Py_CharInSet(chr,set)					\
486         (((unsigned char)(set)[(unsigned char)(chr) >> 3] & 	\
487 	  (1 << ((unsigned char)(chr) & 7))) != 0)
488 
489 /* --- SWIG addons -------------------------------------------------------- */
490 
491 /* Throw this error after having set the correct Python exception
492    using e.g. PyErr_SetString(); */
493 #define mxSWIGError "mxSWIGError"
494 
495 /* EOF */
496 #endif
497 
498