blob: 43c64414cb1cfc7335b9f517cae02b8b98d05cad [file] [log] [blame]
Barry Warsawe886ea91997-01-17 00:01:33 +00001/* This module exports the C API to such Pure Software Inc. (tm) (now
2 * called Pure Atria Corporation) products as Purify (tm) and Quantify
3 * (tm). Other packages could be added, but I didn't have those products
4 * and thus lack the API documentation.
5 *
6 * Currently supported: Quantify 2.x, Purify 3.x
7 *
8 * You need to decide which products you want to incorporate into the
9 * module when you compile this file. The way to do this is to edit
10 * <Python>/Modules/Setup to pass the appropriate flags to the compiler.
11 * -DWITH_PURIFY compiles in the Purify support, and -DWITH_QUANTIFY
12 * compiles in the Quantify support. -DWITH_ALL_PURE compiles in both.
13 * You can also build a Purify'd or Quantify'd interpreter by passing in
14 * the LINKCC variable to make. E.g. if you want to build a Purify'd
15 * interpreter and are using gcc, build Python with this command:
16 *
17 * make LINKCC='purify gcc'
18 *
19 * It would be nice (and probably easy) to provide this file as a shared
20 * library, however since it doesn't appear that Pure gives us shared
21 * libraries of the stubs, it doesn't really matter. For now, you have to
22 * link this file in statically.
23 *
24 * Major bogosity. The purify.h header file exports purify_exit(), but
25 * guess what? It is not defined in the libpurify_stubs.a file! I tried
26 * to fake one here, hoping the Pure linker would Do The Right Thing when
27 * instrumented for Purify, but it doesn't seem to, so I don't export
28 * purify_exit() to the Python layer. In Python you should raise a
29 * SystemExit exception anyway.
30 *
31 * The actual purify.h and quantify.h files which embody the APIs are
32 * copyrighted by Pure Software, Inc. and are only attainable through them.
33 * This module assumes you have legally installed licenses of their
34 * software. Contact them on the Web via <http://www.pureatria.com/>
35 *
36 * Author: Barry Warsaw <bwarsaw@python.org>
37 * <bwarsaw@cnri.reston.va.us>
38 */
39
40#include "Python.h"
41
42#if defined(WITH_PURIFY) || defined(WITH_ALL_PURE)
43# include <purify.h>
44# define HAS_PURIFY_EXIT 0 /* See note at top of file */
45# define PURE_PURIFY_VERSION 3 /* not provided by purify.h */
46#endif
47#if defined(WITH_QUANTIFY) || defined(WITH_ALL_PURE)
48# include <quantify.h>
49# define PURE_QUANTIFY_VERSION 2 /* not provided by quantify.h */
50#endif
51#if defined(PURIFY_H) || defined(QUANTIFY_H)
52# define COMMON_PURE_FUNCTIONS
53#endif /* PURIFY_H || QUANTIFY_H */
54
55typedef int (*VoidArgFunc)(void);
56typedef int (*StringArgFunc)(char*);
57typedef int (*PrintfishFunc)(const char*, ...);
58typedef int (*StringIntArgFunc)(const char*, int);
59
60
61
62static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +000063call_voidarg_function(VoidArgFunc func, PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +000064{
65 int status;
66
67 if (!PyArg_ParseTuple(args, ""))
68 return NULL;
69
70 status = func();
71 return Py_BuildValue("i", status);
72}
73
74static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +000075call_stringarg_function(StringArgFunc func, PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +000076{
77 int status;
78 char* stringarg;
79
80 if (!PyArg_ParseTuple(args, "s", &stringarg))
81 return NULL;
82
83 status = func(stringarg);
84 return Py_BuildValue("i", status);
85}
86
87static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +000088call_stringorint_function(StringArgFunc func, PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +000089{
90 int status;
91 int intarg;
92 char* stringarg;
93
94 /* according to the quantify.h file, the argument to
95 * quantify_*_recording_system_call can be an integer or a string,
96 * but the functions are prototyped as taking a single char*
97 * argument. Yikes!
98 */
99 if (PyArg_ParseTuple(args, "i", &intarg))
100 /* func is prototyped as int(*)(char*)
101 * better shut up the compiler
102 */
103 status = func((char*)intarg);
104
105 else {
106 PyErr_Clear();
107 if (!PyArg_ParseTuple(args, "s", &stringarg))
108 return NULL;
109 else
110 status = func(stringarg);
111 }
112 return Py_BuildValue("i", status);
113}
114
115static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000116call_printfish_function(PrintfishFunc func, PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000117{
118 /* we support the printf() style vararg functions by requiring the
119 * formatting be done in Python. At the C level we pass just a string
120 * to the printf() style function.
121 */
122 int status;
123 char* argstring;
124
125 if (!PyArg_ParseTuple(args, "s", &argstring))
126 return NULL;
127
128 status = func("%s", argstring);
129 return Py_BuildValue("i", status);
130}
131
132static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000133call_intasaddr_function(StringArgFunc func, PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000134{
135 long memrep;
136 int id;
137
138 if (!PyArg_ParseTuple(args, "l", &memrep))
139 return NULL;
140
141 id = func((char*)memrep);
142 return Py_BuildValue("i", id);
143}
144
145static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000146call_stringandint_function(StringIntArgFunc func, PyObject *self,
147 PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000148{
149 long srcrep;
150 int size;
151 int status;
152
153 if (!PyArg_ParseTuple(args, "li", &srcrep, &size))
154 return NULL;
155
156 status = func((char*)srcrep, size);
157 return Py_BuildValue("i", status);
158}
159
160
161
162/* functions common to all products
163 *
164 * N.B. These printf() style functions are a bit of a kludge. Since the
165 * API doesn't provide vprintf versions of them, we can't call them
166 * directly. They don't support all the standard printf % modifiers
167 * anyway. The way to use these is to use Python's % string operator to do
168 * the formatting. By the time these functions get the thing to print,
169 * it's already a string, and they just use "%s" as the format string.
170 */
171
172#ifdef COMMON_PURE_FUNCTIONS
173
174static PyObject*
175pure_pure_logfile_printf(PyObject* self, PyObject* args)
176{
177 return call_printfish_function(pure_logfile_printf, self, args);
178}
179
180static PyObject*
181pure_pure_printf(PyObject* self, PyObject* args)
182{
183 return call_printfish_function(pure_printf, self, args);
184}
185
186static PyObject*
187pure_pure_printf_with_banner(PyObject* self, PyObject* args)
188{
189 return call_printfish_function(pure_printf_with_banner, self, args);
190}
191
192
193#endif /* COMMON_PURE_FUNCTIONS */
194
195
196
197/* Purify functions
198 *
199 * N.B. There are some interfaces described in the purify.h file that are
200 * not described in the manual.
201 *
202 * Unsigned longs purify_report_{address,number,type,result} are not
203 * accessible from the Python layer since they seem mostly useful when
204 * purify_stop_here() is called by the (C) debugger. The same is true of
205 * the purify_stop_here_internal() function so it isn't exported either.
206 * And purify_stop_here() should never be called directly.
207 *
208 * The header file says purify_{new,all,clear_new}_reports() are obsolete
209 * so they aren't exported.
210 *
211 * None of the custom dynamic loader functions are exported.
212 *
213 * purify_unsafe_memcpy() isn't exported.
214 *
215 * purify_{start,size}_of_block() aren't exported.
216 *
217 * The manual that I have says that the prototype for the second argument
218 * to purify_map_pool is:
219 *
220 * void (*fn)(char*)
221 *
222 * but the purify.h file declares it as:
223 *
224 * void (*fn)(char*, int, void*)
225 *
226 * and does not explain what the other arguments are for. I support the
227 * latter but I don't know if I do it right or usefully.
228 *
229 * The header file says that purify_describe() returns a char* which is the
230 * pointer passed to it. The manual says it returns an int, but I believe
231 * that is a typo.
232 */
233#ifdef PURIFY_H
234
235static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000236pure_purify_all_inuse(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000237{
238 return call_voidarg_function(purify_all_inuse, self, args);
239}
240static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000241pure_purify_all_leaks(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000242{
243 return call_voidarg_function(purify_all_leaks, self, args);
244}
245static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000246pure_purify_new_inuse(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000247{
248 return call_voidarg_function(purify_new_inuse, self, args);
249}
250static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000251pure_purify_new_leaks(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000252{
253 return call_voidarg_function(purify_new_leaks, self, args);
254}
255static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000256pure_purify_clear_inuse(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000257{
258 return call_voidarg_function(purify_clear_inuse, self, args);
259}
260static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000261pure_purify_clear_leaks(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000262{
263 return call_voidarg_function(purify_clear_leaks, self, args);
264}
265static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000266pure_purify_all_fds_inuse(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000267{
268 return call_voidarg_function(purify_all_fds_inuse, self, args);
269}
270static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000271pure_purify_new_fds_inuse(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000272{
273 return call_voidarg_function(purify_new_fds_inuse, self, args);
274}
275static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000276pure_purify_printf_with_call_chain(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000277{
278 return call_printfish_function(purify_printf_with_call_chain,
279 self, args);
280}
281static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000282pure_purify_set_pool_id(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000283{
284 long memrep;
285 int id;
286
Guido van Rossum43713e52000-02-29 13:59:29 +0000287 if (!PyArg_ParseTuple(args, "li:purify_set_pool_id", &memrep, &id))
Barry Warsawe886ea91997-01-17 00:01:33 +0000288 return NULL;
289
290 purify_set_pool_id((char*)memrep, id);
291 Py_INCREF(Py_None);
292 return Py_None;
293}
294static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000295pure_purify_get_pool_id(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000296{
297 return call_intasaddr_function(purify_get_pool_id, self, args);
298}
299static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000300pure_purify_set_user_data(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000301{
302 long memrep;
303 long datarep;
304
Guido van Rossum43713e52000-02-29 13:59:29 +0000305 if (!PyArg_ParseTuple(args, "ll:purify_set_user_data", &memrep, &datarep))
Barry Warsawe886ea91997-01-17 00:01:33 +0000306 return NULL;
307
308 purify_set_user_data((char*)memrep, (void*)datarep);
309 Py_INCREF(Py_None);
310 return Py_None;
311}
312static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000313pure_purify_get_user_data(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000314{
315 /* can't use call_intasaddr_function() since purify_get_user_data()
316 * returns a void*
317 */
318 long memrep;
319 void* data;
320
Guido van Rossum43713e52000-02-29 13:59:29 +0000321 if (!PyArg_ParseTuple(args, "l:purify_get_user_data", &memrep))
Barry Warsawe886ea91997-01-17 00:01:33 +0000322 return NULL;
323
324 data = purify_get_user_data((char*)memrep);
325 return Py_BuildValue("l", (long)data);
326}
327
328
329/* this global variable is shared by both mapping functions:
330 * pure_purify_map_pool() and pure_purify_map_pool_id(). Since they cache
331 * this variable it should be safe in the face of recursion or cross
332 * calling.
333 *
334 * Further note that the prototype for the callback function is wrong in
335 * the Purify manual. The manual says the function takes a single char*,
336 * but the header file says it takes an additional int and void*. I have
337 * no idea what these are for!
338 */
339static PyObject* MapCallable = NULL;
340
341static void
Barry Warsawf0879602000-08-18 05:13:47 +0000342map_pool_callback(char* mem, int user_size, void *user_aux_data)
Barry Warsawe886ea91997-01-17 00:01:33 +0000343{
344 long memrep = (long)mem;
345 long user_aux_data_rep = (long)user_aux_data;
346 PyObject* result;
347 PyObject* memobj = Py_BuildValue("lil", memrep, user_size,
348 user_aux_data_rep);
349
350 if (memobj == NULL)
351 return;
352
353 result = PyEval_CallObject(MapCallable, memobj);
354 Py_DECREF(result);
355 Py_DECREF(memobj);
356}
357
358static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000359pure_purify_map_pool(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000360{
361 /* cache global variable in case of recursion */
362 PyObject* saved_callable = MapCallable;
363 PyObject* arg_callable;
364 int id;
365
Guido van Rossum43713e52000-02-29 13:59:29 +0000366 if (!PyArg_ParseTuple(args, "iO:purify_map_pool", &id, &arg_callable))
Barry Warsawe886ea91997-01-17 00:01:33 +0000367 return NULL;
368
369 if (!PyCallable_Check(arg_callable)) {
370 PyErr_SetString(PyExc_TypeError,
371 "Second argument must be callable");
372 return NULL;
373 }
374 MapCallable = arg_callable;
375 purify_map_pool(id, map_pool_callback);
376 MapCallable = saved_callable;
377
378 Py_INCREF(Py_None);
379 return Py_None;
380}
381
382static void
Barry Warsawf0879602000-08-18 05:13:47 +0000383PurifyMapPoolIdCallback(int id)
Barry Warsawe886ea91997-01-17 00:01:33 +0000384{
385 PyObject* result;
386 PyObject* intobj = Py_BuildValue("i", id);
387
388 if (intobj == NULL)
389 return;
390
391 result = PyEval_CallObject(MapCallable, intobj);
392 Py_DECREF(result);
393 Py_DECREF(intobj);
394}
395
396static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000397pure_purify_map_pool_id(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000398{
399 /* cache global variable in case of recursion */
400 PyObject* saved_callable = MapCallable;
401 PyObject* arg_callable;
402
Guido van Rossum43713e52000-02-29 13:59:29 +0000403 if (!PyArg_ParseTuple(args, "O:purify_map_pool_id", &arg_callable))
Barry Warsawe886ea91997-01-17 00:01:33 +0000404 return NULL;
405
406 if (!PyCallable_Check(arg_callable)) {
407 PyErr_SetString(PyExc_TypeError, "Argument must be callable.");
408 return NULL;
409 }
410
411 MapCallable = arg_callable;
412 purify_map_pool_id(PurifyMapPoolIdCallback);
413 MapCallable = saved_callable;
414
415 Py_INCREF(Py_None);
416 return Py_None;
417}
418
419
420
421static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000422pure_purify_new_messages(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000423{
424 return call_voidarg_function(purify_new_messages, self, args);
425}
426static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000427pure_purify_all_messages(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000428{
429 return call_voidarg_function(purify_all_messages, self, args);
430}
431static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000432pure_purify_clear_messages(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000433{
434 return call_voidarg_function(purify_clear_messages, self, args);
435}
436static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000437pure_purify_clear_new_messages(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000438{
439 return call_voidarg_function(purify_clear_new_messages, self, args);
440}
441static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000442pure_purify_start_batch(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000443{
444 return call_voidarg_function(purify_start_batch, self, args);
445}
446static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000447pure_purify_start_batch_show_first(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000448{
449 return call_voidarg_function(purify_start_batch_show_first,
450 self, args);
451}
452static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000453pure_purify_stop_batch(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000454{
455 return call_voidarg_function(purify_stop_batch, self, args);
456}
457static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000458pure_purify_name_thread(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000459{
460 /* can't strictly use call_stringarg_function since
461 * purify_name_thread takes a const char*, not a char*
462 */
463 int status;
464 char* stringarg;
465
Guido van Rossum43713e52000-02-29 13:59:29 +0000466 if (!PyArg_ParseTuple(args, "s:purify_name_thread", &stringarg))
Barry Warsawe886ea91997-01-17 00:01:33 +0000467 return NULL;
468
469 status = purify_name_thread(stringarg);
470 return Py_BuildValue("i", status);
471}
472static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000473pure_purify_watch(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000474{
475 return call_intasaddr_function(purify_watch, self, args);
476}
477static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000478pure_purify_watch_1(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000479{
480 return call_intasaddr_function(purify_watch_1, self, args);
481}
482static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000483pure_purify_watch_2(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000484{
485 return call_intasaddr_function(purify_watch_2, self, args);
486}
487static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000488pure_purify_watch_4(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000489{
490 return call_intasaddr_function(purify_watch_4, self, args);
491}
492static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000493pure_purify_watch_8(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000494{
495 return call_intasaddr_function(purify_watch_8, self, args);
496}
497static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000498pure_purify_watch_w_1(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000499{
500 return call_intasaddr_function(purify_watch_w_1, self, args);
501}
502static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000503pure_purify_watch_w_2(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000504{
505 return call_intasaddr_function(purify_watch_w_2, self, args);
506}
507static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000508pure_purify_watch_w_4(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000509{
510 return call_intasaddr_function(purify_watch_w_4, self, args);
511}
512static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000513pure_purify_watch_w_8(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000514{
515 return call_intasaddr_function(purify_watch_w_8, self, args);
516}
517static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000518pure_purify_watch_r_1(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000519{
520 return call_intasaddr_function(purify_watch_r_1, self, args);
521}
522static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000523pure_purify_watch_r_2(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000524{
525 return call_intasaddr_function(purify_watch_r_2, self, args);
526}
527static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000528pure_purify_watch_r_4(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000529{
530 return call_intasaddr_function(purify_watch_r_4, self, args);
531}
532static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000533pure_purify_watch_r_8(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000534{
535 return call_intasaddr_function(purify_watch_r_8, self, args);
536}
537static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000538pure_purify_watch_rw_1(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000539{
540 return call_intasaddr_function(purify_watch_rw_1, self, args);
541}
542static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000543pure_purify_watch_rw_2(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000544{
545 return call_intasaddr_function(purify_watch_rw_2, self, args);
546}
547static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000548pure_purify_watch_rw_4(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000549{
550 return call_intasaddr_function(purify_watch_rw_4, self, args);
551}
552static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000553pure_purify_watch_rw_8(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000554{
555 return call_intasaddr_function(purify_watch_rw_8, self, args);
556}
557
558static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000559pure_purify_watch_n(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000560{
561 long addrrep;
562 unsigned int size;
563 char* type;
564 int status;
565
Guido van Rossum43713e52000-02-29 13:59:29 +0000566 if (!PyArg_ParseTuple(args, "lis:purify_watch_n", &addrrep, &size, &type))
Barry Warsawe886ea91997-01-17 00:01:33 +0000567 return NULL;
568
569 status = purify_watch_n((char*)addrrep, size, type);
570 return Py_BuildValue("i", status);
571}
572
573static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000574pure_purify_watch_info(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000575{
576 return call_voidarg_function(purify_watch_info, self, args);
577}
578
579static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000580pure_purify_watch_remove(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000581{
582 int watchno;
583 int status;
584
Guido van Rossum43713e52000-02-29 13:59:29 +0000585 if (!PyArg_ParseTuple(args, "i:purify_watch_remove", &watchno))
Barry Warsawe886ea91997-01-17 00:01:33 +0000586 return NULL;
587
588 status = purify_watch_remove(watchno);
589 return Py_BuildValue("i", status);
590}
591
592static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000593pure_purify_watch_remove_all(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000594{
595 return call_voidarg_function(purify_watch_remove_all, self, args);
596}
597static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000598pure_purify_describe(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000599{
600 long addrrep;
601 char* rtn;
602
Guido van Rossum43713e52000-02-29 13:59:29 +0000603 if (!PyArg_ParseTuple(args, "l:purify_describe", &addrrep))
Barry Warsawe886ea91997-01-17 00:01:33 +0000604 return NULL;
605
606 rtn = purify_describe((char*)addrrep);
607 return Py_BuildValue("l", (long)rtn);
608}
609
610static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000611pure_purify_what_colors(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000612{
613 long addrrep;
614 unsigned int size;
615 int status;
616
Guido van Rossum43713e52000-02-29 13:59:29 +0000617 if (!PyArg_ParseTuple(args, "li:purify_what_colors", &addrrep, &size))
Barry Warsawe886ea91997-01-17 00:01:33 +0000618 return NULL;
619
620 status = purify_what_colors((char*)addrrep, size);
621 return Py_BuildValue("i", status);
622}
623
624static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000625pure_purify_is_running(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000626{
627 return call_voidarg_function(purify_is_running, self, args);
628}
629
630static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000631pure_purify_assert_is_readable(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000632{
633 return call_stringandint_function(purify_assert_is_readable,
634 self, args);
635}
636static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000637pure_purify_assert_is_writable(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000638{
639 return call_stringandint_function(purify_assert_is_writable,
640 self, args);
641}
642
643#if HAS_PURIFY_EXIT
644
645/* I wish I could include this, but I can't. See the notes at the top of
646 * the file.
647 */
648
649static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000650pure_purify_exit(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000651{
652 int status;
653
Guido van Rossum43713e52000-02-29 13:59:29 +0000654 if (!PyArg_ParseTuple(args, "i:purify_exit", &status))
Barry Warsawe886ea91997-01-17 00:01:33 +0000655 return NULL;
656
657 /* purify_exit doesn't always act like exit(). See the manual */
658 purify_exit(status);
659 Py_INCREF(Py_None);
660 return Py_None;
661}
662#endif /* HAS_PURIFY_EXIT */
663
664#endif /* PURIFY_H */
665
666
667
668/* Quantify functions
669 *
670 * N.B. Some of these functions are only described in the quantify.h file,
671 * not in the version of the hardcopy manual that I had. If you're not
672 * sure what some of these do, check the header file, it is documented
673 * fairly well.
674 *
675 * None of the custom dynamic loader functions are exported.
676 *
677 */
678#ifdef QUANTIFY_H
679
680static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000681pure_quantify_is_running(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000682{
683 return call_voidarg_function(quantify_is_running, self, args);
684}
685static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000686pure_quantify_help(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000687{
688 return call_voidarg_function(quantify_help, self, args);
689}
690static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000691pure_quantify_print_recording_state(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000692{
693 return call_voidarg_function(quantify_print_recording_state,
694 self, args);
695}
696static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000697pure_quantify_start_recording_data(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000698{
699 return call_voidarg_function(quantify_start_recording_data,
700 self, args);
701}
702static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000703pure_quantify_stop_recording_data(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000704{
705 return call_voidarg_function(quantify_stop_recording_data, self, args);
706}
707static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000708pure_quantify_is_recording_data(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000709{
710 return call_voidarg_function(quantify_is_recording_data, self, args);
711}
712static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000713pure_quantify_start_recording_system_calls(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000714{
715 return call_voidarg_function(quantify_start_recording_system_calls,
716 self, args);
717}
718static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000719pure_quantify_stop_recording_system_calls(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000720{
721 return call_voidarg_function(quantify_stop_recording_system_calls,
722 self, args);
723}
724static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000725pure_quantify_is_recording_system_calls(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000726{
727 return call_voidarg_function(quantify_is_recording_system_calls,
728 self, args);
729}
730static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000731pure_quantify_start_recording_system_call(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000732{
733 return call_stringorint_function(quantify_start_recording_system_call,
734 self, args);
735}
736static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000737pure_quantify_stop_recording_system_call(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000738{
739 return call_stringorint_function(quantify_stop_recording_system_call,
740 self, args);
741}
742static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000743pure_quantify_is_recording_system_call(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000744{
745 return call_stringorint_function(quantify_is_recording_system_call,
746 self, args);
747}
748static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000749pure_quantify_start_recording_dynamic_library_data(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000750{
751 return call_voidarg_function(
752 quantify_start_recording_dynamic_library_data,
753 self, args);
754}
755static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000756pure_quantify_stop_recording_dynamic_library_data(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000757{
758 return call_voidarg_function(
759 quantify_stop_recording_dynamic_library_data,
760 self, args);
761}
762static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000763pure_quantify_is_recording_dynamic_library_data(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000764{
765 return call_voidarg_function(
766 quantify_is_recording_dynamic_library_data,
767 self, args);
768}
769static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000770pure_quantify_start_recording_register_window_traps(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000771{
772 return call_voidarg_function(
773 quantify_start_recording_register_window_traps,
774 self, args);
775}
776static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000777pure_quantify_stop_recording_register_window_traps(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000778{
779 return call_voidarg_function(
780 quantify_stop_recording_register_window_traps,
781 self, args);
782}
783static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000784pure_quantify_is_recording_register_window_traps(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000785{
786 return call_voidarg_function(
787 quantify_is_recording_register_window_traps,
788 self, args);
789}
790static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000791pure_quantify_disable_recording_data(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000792{
793 return call_voidarg_function(quantify_disable_recording_data,
794 self, args);
795}
796static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000797pure_quantify_clear_data(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000798{
799 return call_voidarg_function(quantify_clear_data, self, args);
800}
801static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000802pure_quantify_save_data(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000803{
804 return call_voidarg_function(quantify_save_data, self, args);
805}
806static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000807pure_quantify_save_data_to_file(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000808{
809 return call_stringarg_function(quantify_save_data_to_file, self, args);
810}
811static PyObject*
Barry Warsawf0879602000-08-18 05:13:47 +0000812pure_quantify_add_annotation(PyObject *self, PyObject *args)
Barry Warsawe886ea91997-01-17 00:01:33 +0000813{
814 return call_stringarg_function(quantify_add_annotation, self, args);
815}
816
817#endif /* QUANTIFY_H */
818
819
820
821/* external interface
822 */
823static struct PyMethodDef
824pure_methods[] = {
825#ifdef COMMON_PURE_FUNCTIONS
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000826 {"pure_logfile_printf", pure_pure_logfile_printf, METH_VARARGS},
827 {"pure_printf", pure_pure_printf, METH_VARARGS},
828 {"pure_printf_with_banner", pure_pure_printf_with_banner, METH_VARARGS},
Barry Warsawe886ea91997-01-17 00:01:33 +0000829#endif /* COMMON_PURE_FUNCTIONS */
830#ifdef PURIFY_H
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000831 {"purify_all_inuse", pure_purify_all_inuse, METH_VARARGS},
832 {"purify_all_leaks", pure_purify_all_leaks, METH_VARARGS},
833 {"purify_new_inuse", pure_purify_new_inuse, METH_VARARGS},
834 {"purify_new_leaks", pure_purify_new_leaks, METH_VARARGS},
835 {"purify_clear_inuse", pure_purify_clear_inuse, METH_VARARGS},
836 {"purify_clear_leaks", pure_purify_clear_leaks, METH_VARARGS},
837 {"purify_all_fds_inuse", pure_purify_all_fds_inuse, METH_VARARGS},
838 {"purify_new_fds_inuse", pure_purify_new_fds_inuse, METH_VARARGS},
Barry Warsawe886ea91997-01-17 00:01:33 +0000839 /* see purify.h */
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000840 {"purify_logfile_printf", pure_pure_logfile_printf, METH_VARARGS},
841 {"purify_printf", pure_pure_printf, METH_VARARGS},
842 {"purify_printf_with_banner", pure_pure_printf_with_banner, METH_VARARGS},
Barry Warsawe886ea91997-01-17 00:01:33 +0000843 /**/
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000844 {"purify_printf_with_call_chain", pure_purify_printf_with_call_chain, METH_VARARGS},
845 {"purify_set_pool_id", pure_purify_set_pool_id, METH_VARARGS},
846 {"purify_get_pool_id", pure_purify_get_pool_id, METH_VARARGS},
847 {"purify_set_user_data", pure_purify_set_user_data, METH_VARARGS},
848 {"purify_get_user_data", pure_purify_get_user_data, METH_VARARGS},
849 {"purify_map_pool", pure_purify_map_pool, METH_VARARGS},
850 {"purify_map_pool_id", pure_purify_map_pool_id, METH_VARARGS},
851 {"purify_new_messages", pure_purify_new_messages, METH_VARARGS},
852 {"purify_all_messages", pure_purify_all_messages, METH_VARARGS},
853 {"purify_clear_messages", pure_purify_clear_messages, METH_VARARGS},
854 {"purify_clear_new_messages", pure_purify_clear_new_messages, METH_VARARGS},
855 {"purify_start_batch", pure_purify_start_batch, METH_VARARGS},
856 {"purify_start_batch_show_first", pure_purify_start_batch_show_first, METH_VARARGS},
857 {"purify_stop_batch", pure_purify_stop_batch, METH_VARARGS},
858 {"purify_name_thread", pure_purify_name_thread, METH_VARARGS},
859 {"purify_watch", pure_purify_watch, METH_VARARGS},
860 {"purify_watch_1", pure_purify_watch_1, METH_VARARGS},
861 {"purify_watch_2", pure_purify_watch_2, METH_VARARGS},
862 {"purify_watch_4", pure_purify_watch_4, METH_VARARGS},
863 {"purify_watch_8", pure_purify_watch_8, METH_VARARGS},
864 {"purify_watch_w_1", pure_purify_watch_w_1, METH_VARARGS},
865 {"purify_watch_w_2", pure_purify_watch_w_2, METH_VARARGS},
866 {"purify_watch_w_4", pure_purify_watch_w_4, METH_VARARGS},
867 {"purify_watch_w_8", pure_purify_watch_w_8, METH_VARARGS},
868 {"purify_watch_r_1", pure_purify_watch_r_1, METH_VARARGS},
869 {"purify_watch_r_2", pure_purify_watch_r_2, METH_VARARGS},
870 {"purify_watch_r_4", pure_purify_watch_r_4, METH_VARARGS},
871 {"purify_watch_r_8", pure_purify_watch_r_8, METH_VARARGS},
872 {"purify_watch_rw_1", pure_purify_watch_rw_1, METH_VARARGS},
873 {"purify_watch_rw_2", pure_purify_watch_rw_2, METH_VARARGS},
874 {"purify_watch_rw_4", pure_purify_watch_rw_4, METH_VARARGS},
875 {"purify_watch_rw_8", pure_purify_watch_rw_8, METH_VARARGS},
876 {"purify_watch_n", pure_purify_watch_n, METH_VARARGS},
877 {"purify_watch_info", pure_purify_watch_info, METH_VARARGS},
878 {"purify_watch_remove", pure_purify_watch_remove, METH_VARARGS},
879 {"purify_watch_remove_all", pure_purify_watch_remove_all, METH_VARARGS},
880 {"purify_describe", pure_purify_describe, METH_VARARGS},
881 {"purify_what_colors", pure_purify_what_colors, METH_VARARGS},
882 {"purify_is_running", pure_purify_is_running, METH_VARARGS},
883 {"purify_assert_is_readable", pure_purify_assert_is_readable, METH_VARARGS},
884 {"purify_assert_is_writable", pure_purify_assert_is_writable, METH_VARARGS},
Barry Warsawe886ea91997-01-17 00:01:33 +0000885#if HAS_PURIFY_EXIT
886 /* I wish I could include this, but I can't. See the notes at the
887 * top of the file.
888 */
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000889 {"purify_exit", pure_purify_exit, METH_VARARGS},
Barry Warsawe886ea91997-01-17 00:01:33 +0000890#endif /* HAS_PURIFY_EXIT */
891#endif /* PURIFY_H */
892#ifdef QUANTIFY_H
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000893 {"quantify_is_running", pure_quantify_is_running, METH_VARARGS},
894 {"quantify_help", pure_quantify_help, METH_VARARGS},
895 {"quantify_print_recording_state", pure_quantify_print_recording_state, METH_VARARGS},
896 {"quantify_start_recording_data", pure_quantify_start_recording_data, METH_VARARGS},
897 {"quantify_stop_recording_data", pure_quantify_stop_recording_data, METH_VARARGS},
898 {"quantify_is_recording_data", pure_quantify_is_recording_data, METH_VARARGS},
Barry Warsawe886ea91997-01-17 00:01:33 +0000899 {"quantify_start_recording_system_calls",
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000900 pure_quantify_start_recording_system_calls, METH_VARARGS},
Barry Warsawe886ea91997-01-17 00:01:33 +0000901 {"quantify_stop_recording_system_calls",
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000902 pure_quantify_stop_recording_system_calls, METH_VARARGS},
Barry Warsawe886ea91997-01-17 00:01:33 +0000903 {"quantify_is_recording_system_calls",
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000904 pure_quantify_is_recording_system_calls, METH_VARARGS},
Barry Warsawe886ea91997-01-17 00:01:33 +0000905 {"quantify_start_recording_system_call",
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000906 pure_quantify_start_recording_system_call, METH_VARARGS},
Barry Warsawe886ea91997-01-17 00:01:33 +0000907 {"quantify_stop_recording_system_call",
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000908 pure_quantify_stop_recording_system_call, METH_VARARGS},
Barry Warsawe886ea91997-01-17 00:01:33 +0000909 {"quantify_is_recording_system_call",
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000910 pure_quantify_is_recording_system_call, METH_VARARGS},
Barry Warsawe886ea91997-01-17 00:01:33 +0000911 {"quantify_start_recording_dynamic_library_data",
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000912 pure_quantify_start_recording_dynamic_library_data, METH_VARARGS},
Barry Warsawe886ea91997-01-17 00:01:33 +0000913 {"quantify_stop_recording_dynamic_library_data",
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000914 pure_quantify_stop_recording_dynamic_library_data, METH_VARARGS},
Barry Warsawe886ea91997-01-17 00:01:33 +0000915 {"quantify_is_recording_dynamic_library_data",
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000916 pure_quantify_is_recording_dynamic_library_data, METH_VARARGS},
Barry Warsawe886ea91997-01-17 00:01:33 +0000917 {"quantify_start_recording_register_window_traps",
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000918 pure_quantify_start_recording_register_window_traps, METH_VARARGS},
Barry Warsawe886ea91997-01-17 00:01:33 +0000919 {"quantify_stop_recording_register_window_traps",
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000920 pure_quantify_stop_recording_register_window_traps, METH_VARARGS},
Barry Warsawe886ea91997-01-17 00:01:33 +0000921 {"quantify_is_recording_register_window_traps",
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000922 pure_quantify_is_recording_register_window_traps, METH_VARARGS},
Barry Warsawe886ea91997-01-17 00:01:33 +0000923 {"quantify_disable_recording_data",
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000924 pure_quantify_disable_recording_data, METH_VARARGS},
925 {"quantify_clear_data", pure_quantify_clear_data, METH_VARARGS},
926 {"quantify_save_data", pure_quantify_save_data, METH_VARARGS},
927 {"quantify_save_data_to_file", pure_quantify_save_data_to_file, METH_VARARGS},
928 {"quantify_add_annotation", pure_quantify_add_annotation, METH_VARARGS},
Barry Warsawe886ea91997-01-17 00:01:33 +0000929#endif /* QUANTIFY_H */
930 {NULL, NULL} /* sentinel */
931};
932
933
934
935static void
936ins(d, name, val)
937 PyObject *d;
938 char* name;
939 long val;
940{
941 PyObject *v = PyInt_FromLong(val);
942 if (v) {
943 (void)PyDict_SetItemString(d, name, v);
944 Py_DECREF(v);
945 }
946}
947
948
949void
950initpure()
951{
952 PyObject *m, *d;
953
954 m = Py_InitModule("pure", pure_methods);
955 d = PyModule_GetDict(m);
956
957 /* this is bogus because we should be able to find this information
958 * out from the header files. Pure's current versions don't
959 * include this information!
960 */
961#ifdef PURE_PURIFY_VERSION
962 ins(d, "PURIFY_VERSION", PURE_PURIFY_VERSION);
963#else
964 PyDict_SetItemString(d, "PURIFY_VERSION", Py_None);
965#endif
966
967 /* these aren't terribly useful because purify_exit() isn't
968 * exported correctly. See the note at the top of the file.
969 */
970#ifdef PURIFY_EXIT_ERRORS
971 ins(d, "PURIFY_EXIT_ERRORS", PURIFY_EXIT_ERRORS);
972#endif
973#ifdef PURIFY_EXIT_LEAKS
974 ins(d, "PURIFY_EXIT_LEAKS", PURIFY_EXIT_LEAKS);
975#endif
976#ifdef PURIFY_EXIT_PLEAKS
977 ins(d, "PURIFY_EXIT_PLEAKS", PURIFY_EXIT_PLEAKS);
978#endif
979
980
981#ifdef PURE_QUANTIFY_VERSION
982 ins(d, "QUANTIFY_VERSION", PURE_QUANTIFY_VERSION);
983#else
984 PyDict_SetItemString(d, "QUANTIFY_VERSION", Py_None);
985#endif
Barry Warsawe886ea91997-01-17 00:01:33 +0000986}