|
1 /* 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 |
|
55 typedef int (*VoidArgFunc)(void); |
|
56 typedef int (*StringArgFunc)(char*); |
|
57 typedef int (*PrintfishFunc)(const char*, ...); |
|
58 typedef int (*StringIntArgFunc)(const char*, int); |
|
59 |
|
60 |
|
61 |
|
62 static PyObject* |
|
63 call_voidarg_function(VoidArgFunc func, PyObject *self, PyObject *args) |
|
64 { |
|
65 int status; |
|
66 |
|
67 if (!PyArg_ParseTuple(args, "")) |
|
68 return NULL; |
|
69 |
|
70 status = func(); |
|
71 return Py_BuildValue("i", status); |
|
72 } |
|
73 |
|
74 static PyObject* |
|
75 call_stringarg_function(StringArgFunc func, PyObject *self, PyObject *args) |
|
76 { |
|
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 |
|
87 static PyObject* |
|
88 call_stringorint_function(StringArgFunc func, PyObject *self, PyObject *args) |
|
89 { |
|
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 |
|
115 static PyObject* |
|
116 call_printfish_function(PrintfishFunc func, PyObject *self, PyObject *args) |
|
117 { |
|
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 |
|
132 static PyObject* |
|
133 call_intasaddr_function(StringArgFunc func, PyObject *self, PyObject *args) |
|
134 { |
|
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 |
|
145 static PyObject* |
|
146 call_stringandint_function(StringIntArgFunc func, PyObject *self, |
|
147 PyObject *args) |
|
148 { |
|
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 |
|
174 static PyObject* |
|
175 pure_pure_logfile_printf(PyObject* self, PyObject* args) |
|
176 { |
|
177 return call_printfish_function(pure_logfile_printf, self, args); |
|
178 } |
|
179 |
|
180 static PyObject* |
|
181 pure_pure_printf(PyObject* self, PyObject* args) |
|
182 { |
|
183 return call_printfish_function(pure_printf, self, args); |
|
184 } |
|
185 |
|
186 static PyObject* |
|
187 pure_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 |
|
235 static PyObject* |
|
236 pure_purify_all_inuse(PyObject *self, PyObject *args) |
|
237 { |
|
238 return call_voidarg_function(purify_all_inuse, self, args); |
|
239 } |
|
240 static PyObject* |
|
241 pure_purify_all_leaks(PyObject *self, PyObject *args) |
|
242 { |
|
243 return call_voidarg_function(purify_all_leaks, self, args); |
|
244 } |
|
245 static PyObject* |
|
246 pure_purify_new_inuse(PyObject *self, PyObject *args) |
|
247 { |
|
248 return call_voidarg_function(purify_new_inuse, self, args); |
|
249 } |
|
250 static PyObject* |
|
251 pure_purify_new_leaks(PyObject *self, PyObject *args) |
|
252 { |
|
253 return call_voidarg_function(purify_new_leaks, self, args); |
|
254 } |
|
255 static PyObject* |
|
256 pure_purify_clear_inuse(PyObject *self, PyObject *args) |
|
257 { |
|
258 return call_voidarg_function(purify_clear_inuse, self, args); |
|
259 } |
|
260 static PyObject* |
|
261 pure_purify_clear_leaks(PyObject *self, PyObject *args) |
|
262 { |
|
263 return call_voidarg_function(purify_clear_leaks, self, args); |
|
264 } |
|
265 static PyObject* |
|
266 pure_purify_all_fds_inuse(PyObject *self, PyObject *args) |
|
267 { |
|
268 return call_voidarg_function(purify_all_fds_inuse, self, args); |
|
269 } |
|
270 static PyObject* |
|
271 pure_purify_new_fds_inuse(PyObject *self, PyObject *args) |
|
272 { |
|
273 return call_voidarg_function(purify_new_fds_inuse, self, args); |
|
274 } |
|
275 static PyObject* |
|
276 pure_purify_printf_with_call_chain(PyObject *self, PyObject *args) |
|
277 { |
|
278 return call_printfish_function(purify_printf_with_call_chain, |
|
279 self, args); |
|
280 } |
|
281 static PyObject* |
|
282 pure_purify_set_pool_id(PyObject *self, PyObject *args) |
|
283 { |
|
284 long memrep; |
|
285 int id; |
|
286 |
|
287 if (!PyArg_ParseTuple(args, "li:purify_set_pool_id", &memrep, &id)) |
|
288 return NULL; |
|
289 |
|
290 purify_set_pool_id((char*)memrep, id); |
|
291 Py_INCREF(Py_None); |
|
292 return Py_None; |
|
293 } |
|
294 static PyObject* |
|
295 pure_purify_get_pool_id(PyObject *self, PyObject *args) |
|
296 { |
|
297 return call_intasaddr_function(purify_get_pool_id, self, args); |
|
298 } |
|
299 static PyObject* |
|
300 pure_purify_set_user_data(PyObject *self, PyObject *args) |
|
301 { |
|
302 long memrep; |
|
303 long datarep; |
|
304 |
|
305 if (!PyArg_ParseTuple(args, "ll:purify_set_user_data", &memrep, &datarep)) |
|
306 return NULL; |
|
307 |
|
308 purify_set_user_data((char*)memrep, (void*)datarep); |
|
309 Py_INCREF(Py_None); |
|
310 return Py_None; |
|
311 } |
|
312 static PyObject* |
|
313 pure_purify_get_user_data(PyObject *self, PyObject *args) |
|
314 { |
|
315 /* can't use call_intasaddr_function() since purify_get_user_data() |
|
316 * returns a void* |
|
317 */ |
|
318 long memrep; |
|
319 void* data; |
|
320 |
|
321 if (!PyArg_ParseTuple(args, "l:purify_get_user_data", &memrep)) |
|
322 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 */ |
|
339 static PyObject* MapCallable = NULL; |
|
340 |
|
341 static void |
|
342 map_pool_callback(char* mem, int user_size, void *user_aux_data) |
|
343 { |
|
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 |
|
358 static PyObject* |
|
359 pure_purify_map_pool(PyObject *self, PyObject *args) |
|
360 { |
|
361 /* cache global variable in case of recursion */ |
|
362 PyObject* saved_callable = MapCallable; |
|
363 PyObject* arg_callable; |
|
364 int id; |
|
365 |
|
366 if (!PyArg_ParseTuple(args, "iO:purify_map_pool", &id, &arg_callable)) |
|
367 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 |
|
382 static void |
|
383 PurifyMapPoolIdCallback(int id) |
|
384 { |
|
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 |
|
396 static PyObject* |
|
397 pure_purify_map_pool_id(PyObject *self, PyObject *args) |
|
398 { |
|
399 /* cache global variable in case of recursion */ |
|
400 PyObject* saved_callable = MapCallable; |
|
401 PyObject* arg_callable; |
|
402 |
|
403 if (!PyArg_ParseTuple(args, "O:purify_map_pool_id", &arg_callable)) |
|
404 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 |
|
421 static PyObject* |
|
422 pure_purify_new_messages(PyObject *self, PyObject *args) |
|
423 { |
|
424 return call_voidarg_function(purify_new_messages, self, args); |
|
425 } |
|
426 static PyObject* |
|
427 pure_purify_all_messages(PyObject *self, PyObject *args) |
|
428 { |
|
429 return call_voidarg_function(purify_all_messages, self, args); |
|
430 } |
|
431 static PyObject* |
|
432 pure_purify_clear_messages(PyObject *self, PyObject *args) |
|
433 { |
|
434 return call_voidarg_function(purify_clear_messages, self, args); |
|
435 } |
|
436 static PyObject* |
|
437 pure_purify_clear_new_messages(PyObject *self, PyObject *args) |
|
438 { |
|
439 return call_voidarg_function(purify_clear_new_messages, self, args); |
|
440 } |
|
441 static PyObject* |
|
442 pure_purify_start_batch(PyObject *self, PyObject *args) |
|
443 { |
|
444 return call_voidarg_function(purify_start_batch, self, args); |
|
445 } |
|
446 static PyObject* |
|
447 pure_purify_start_batch_show_first(PyObject *self, PyObject *args) |
|
448 { |
|
449 return call_voidarg_function(purify_start_batch_show_first, |
|
450 self, args); |
|
451 } |
|
452 static PyObject* |
|
453 pure_purify_stop_batch(PyObject *self, PyObject *args) |
|
454 { |
|
455 return call_voidarg_function(purify_stop_batch, self, args); |
|
456 } |
|
457 static PyObject* |
|
458 pure_purify_name_thread(PyObject *self, PyObject *args) |
|
459 { |
|
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 |
|
466 if (!PyArg_ParseTuple(args, "s:purify_name_thread", &stringarg)) |
|
467 return NULL; |
|
468 |
|
469 status = purify_name_thread(stringarg); |
|
470 return Py_BuildValue("i", status); |
|
471 } |
|
472 static PyObject* |
|
473 pure_purify_watch(PyObject *self, PyObject *args) |
|
474 { |
|
475 return call_intasaddr_function(purify_watch, self, args); |
|
476 } |
|
477 static PyObject* |
|
478 pure_purify_watch_1(PyObject *self, PyObject *args) |
|
479 { |
|
480 return call_intasaddr_function(purify_watch_1, self, args); |
|
481 } |
|
482 static PyObject* |
|
483 pure_purify_watch_2(PyObject *self, PyObject *args) |
|
484 { |
|
485 return call_intasaddr_function(purify_watch_2, self, args); |
|
486 } |
|
487 static PyObject* |
|
488 pure_purify_watch_4(PyObject *self, PyObject *args) |
|
489 { |
|
490 return call_intasaddr_function(purify_watch_4, self, args); |
|
491 } |
|
492 static PyObject* |
|
493 pure_purify_watch_8(PyObject *self, PyObject *args) |
|
494 { |
|
495 return call_intasaddr_function(purify_watch_8, self, args); |
|
496 } |
|
497 static PyObject* |
|
498 pure_purify_watch_w_1(PyObject *self, PyObject *args) |
|
499 { |
|
500 return call_intasaddr_function(purify_watch_w_1, self, args); |
|
501 } |
|
502 static PyObject* |
|
503 pure_purify_watch_w_2(PyObject *self, PyObject *args) |
|
504 { |
|
505 return call_intasaddr_function(purify_watch_w_2, self, args); |
|
506 } |
|
507 static PyObject* |
|
508 pure_purify_watch_w_4(PyObject *self, PyObject *args) |
|
509 { |
|
510 return call_intasaddr_function(purify_watch_w_4, self, args); |
|
511 } |
|
512 static PyObject* |
|
513 pure_purify_watch_w_8(PyObject *self, PyObject *args) |
|
514 { |
|
515 return call_intasaddr_function(purify_watch_w_8, self, args); |
|
516 } |
|
517 static PyObject* |
|
518 pure_purify_watch_r_1(PyObject *self, PyObject *args) |
|
519 { |
|
520 return call_intasaddr_function(purify_watch_r_1, self, args); |
|
521 } |
|
522 static PyObject* |
|
523 pure_purify_watch_r_2(PyObject *self, PyObject *args) |
|
524 { |
|
525 return call_intasaddr_function(purify_watch_r_2, self, args); |
|
526 } |
|
527 static PyObject* |
|
528 pure_purify_watch_r_4(PyObject *self, PyObject *args) |
|
529 { |
|
530 return call_intasaddr_function(purify_watch_r_4, self, args); |
|
531 } |
|
532 static PyObject* |
|
533 pure_purify_watch_r_8(PyObject *self, PyObject *args) |
|
534 { |
|
535 return call_intasaddr_function(purify_watch_r_8, self, args); |
|
536 } |
|
537 static PyObject* |
|
538 pure_purify_watch_rw_1(PyObject *self, PyObject *args) |
|
539 { |
|
540 return call_intasaddr_function(purify_watch_rw_1, self, args); |
|
541 } |
|
542 static PyObject* |
|
543 pure_purify_watch_rw_2(PyObject *self, PyObject *args) |
|
544 { |
|
545 return call_intasaddr_function(purify_watch_rw_2, self, args); |
|
546 } |
|
547 static PyObject* |
|
548 pure_purify_watch_rw_4(PyObject *self, PyObject *args) |
|
549 { |
|
550 return call_intasaddr_function(purify_watch_rw_4, self, args); |
|
551 } |
|
552 static PyObject* |
|
553 pure_purify_watch_rw_8(PyObject *self, PyObject *args) |
|
554 { |
|
555 return call_intasaddr_function(purify_watch_rw_8, self, args); |
|
556 } |
|
557 |
|
558 static PyObject* |
|
559 pure_purify_watch_n(PyObject *self, PyObject *args) |
|
560 { |
|
561 long addrrep; |
|
562 unsigned int size; |
|
563 char* type; |
|
564 int status; |
|
565 |
|
566 if (!PyArg_ParseTuple(args, "lis:purify_watch_n", &addrrep, &size, &type)) |
|
567 return NULL; |
|
568 |
|
569 status = purify_watch_n((char*)addrrep, size, type); |
|
570 return Py_BuildValue("i", status); |
|
571 } |
|
572 |
|
573 static PyObject* |
|
574 pure_purify_watch_info(PyObject *self, PyObject *args) |
|
575 { |
|
576 return call_voidarg_function(purify_watch_info, self, args); |
|
577 } |
|
578 |
|
579 static PyObject* |
|
580 pure_purify_watch_remove(PyObject *self, PyObject *args) |
|
581 { |
|
582 int watchno; |
|
583 int status; |
|
584 |
|
585 if (!PyArg_ParseTuple(args, "i:purify_watch_remove", &watchno)) |
|
586 return NULL; |
|
587 |
|
588 status = purify_watch_remove(watchno); |
|
589 return Py_BuildValue("i", status); |
|
590 } |
|
591 |
|
592 static PyObject* |
|
593 pure_purify_watch_remove_all(PyObject *self, PyObject *args) |
|
594 { |
|
595 return call_voidarg_function(purify_watch_remove_all, self, args); |
|
596 } |
|
597 static PyObject* |
|
598 pure_purify_describe(PyObject *self, PyObject *args) |
|
599 { |
|
600 long addrrep; |
|
601 char* rtn; |
|
602 |
|
603 if (!PyArg_ParseTuple(args, "l:purify_describe", &addrrep)) |
|
604 return NULL; |
|
605 |
|
606 rtn = purify_describe((char*)addrrep); |
|
607 return Py_BuildValue("l", (long)rtn); |
|
608 } |
|
609 |
|
610 static PyObject* |
|
611 pure_purify_what_colors(PyObject *self, PyObject *args) |
|
612 { |
|
613 long addrrep; |
|
614 unsigned int size; |
|
615 int status; |
|
616 |
|
617 if (!PyArg_ParseTuple(args, "li:purify_what_colors", &addrrep, &size)) |
|
618 return NULL; |
|
619 |
|
620 status = purify_what_colors((char*)addrrep, size); |
|
621 return Py_BuildValue("i", status); |
|
622 } |
|
623 |
|
624 static PyObject* |
|
625 pure_purify_is_running(PyObject *self, PyObject *args) |
|
626 { |
|
627 return call_voidarg_function(purify_is_running, self, args); |
|
628 } |
|
629 |
|
630 static PyObject* |
|
631 pure_purify_assert_is_readable(PyObject *self, PyObject *args) |
|
632 { |
|
633 return call_stringandint_function(purify_assert_is_readable, |
|
634 self, args); |
|
635 } |
|
636 static PyObject* |
|
637 pure_purify_assert_is_writable(PyObject *self, PyObject *args) |
|
638 { |
|
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 |
|
649 static PyObject* |
|
650 pure_purify_exit(PyObject *self, PyObject *args) |
|
651 { |
|
652 int status; |
|
653 |
|
654 if (!PyArg_ParseTuple(args, "i:purify_exit", &status)) |
|
655 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 |
|
680 static PyObject* |
|
681 pure_quantify_is_running(PyObject *self, PyObject *args) |
|
682 { |
|
683 return call_voidarg_function(quantify_is_running, self, args); |
|
684 } |
|
685 static PyObject* |
|
686 pure_quantify_help(PyObject *self, PyObject *args) |
|
687 { |
|
688 return call_voidarg_function(quantify_help, self, args); |
|
689 } |
|
690 static PyObject* |
|
691 pure_quantify_print_recording_state(PyObject *self, PyObject *args) |
|
692 { |
|
693 return call_voidarg_function(quantify_print_recording_state, |
|
694 self, args); |
|
695 } |
|
696 static PyObject* |
|
697 pure_quantify_start_recording_data(PyObject *self, PyObject *args) |
|
698 { |
|
699 return call_voidarg_function(quantify_start_recording_data, |
|
700 self, args); |
|
701 } |
|
702 static PyObject* |
|
703 pure_quantify_stop_recording_data(PyObject *self, PyObject *args) |
|
704 { |
|
705 return call_voidarg_function(quantify_stop_recording_data, self, args); |
|
706 } |
|
707 static PyObject* |
|
708 pure_quantify_is_recording_data(PyObject *self, PyObject *args) |
|
709 { |
|
710 return call_voidarg_function(quantify_is_recording_data, self, args); |
|
711 } |
|
712 static PyObject* |
|
713 pure_quantify_start_recording_system_calls(PyObject *self, PyObject *args) |
|
714 { |
|
715 return call_voidarg_function(quantify_start_recording_system_calls, |
|
716 self, args); |
|
717 } |
|
718 static PyObject* |
|
719 pure_quantify_stop_recording_system_calls(PyObject *self, PyObject *args) |
|
720 { |
|
721 return call_voidarg_function(quantify_stop_recording_system_calls, |
|
722 self, args); |
|
723 } |
|
724 static PyObject* |
|
725 pure_quantify_is_recording_system_calls(PyObject *self, PyObject *args) |
|
726 { |
|
727 return call_voidarg_function(quantify_is_recording_system_calls, |
|
728 self, args); |
|
729 } |
|
730 static PyObject* |
|
731 pure_quantify_start_recording_system_call(PyObject *self, PyObject *args) |
|
732 { |
|
733 return call_stringorint_function(quantify_start_recording_system_call, |
|
734 self, args); |
|
735 } |
|
736 static PyObject* |
|
737 pure_quantify_stop_recording_system_call(PyObject *self, PyObject *args) |
|
738 { |
|
739 return call_stringorint_function(quantify_stop_recording_system_call, |
|
740 self, args); |
|
741 } |
|
742 static PyObject* |
|
743 pure_quantify_is_recording_system_call(PyObject *self, PyObject *args) |
|
744 { |
|
745 return call_stringorint_function(quantify_is_recording_system_call, |
|
746 self, args); |
|
747 } |
|
748 static PyObject* |
|
749 pure_quantify_start_recording_dynamic_library_data(PyObject *self, PyObject *args) |
|
750 { |
|
751 return call_voidarg_function( |
|
752 quantify_start_recording_dynamic_library_data, |
|
753 self, args); |
|
754 } |
|
755 static PyObject* |
|
756 pure_quantify_stop_recording_dynamic_library_data(PyObject *self, PyObject *args) |
|
757 { |
|
758 return call_voidarg_function( |
|
759 quantify_stop_recording_dynamic_library_data, |
|
760 self, args); |
|
761 } |
|
762 static PyObject* |
|
763 pure_quantify_is_recording_dynamic_library_data(PyObject *self, PyObject *args) |
|
764 { |
|
765 return call_voidarg_function( |
|
766 quantify_is_recording_dynamic_library_data, |
|
767 self, args); |
|
768 } |
|
769 static PyObject* |
|
770 pure_quantify_start_recording_register_window_traps(PyObject *self, PyObject *args) |
|
771 { |
|
772 return call_voidarg_function( |
|
773 quantify_start_recording_register_window_traps, |
|
774 self, args); |
|
775 } |
|
776 static PyObject* |
|
777 pure_quantify_stop_recording_register_window_traps(PyObject *self, PyObject *args) |
|
778 { |
|
779 return call_voidarg_function( |
|
780 quantify_stop_recording_register_window_traps, |
|
781 self, args); |
|
782 } |
|
783 static PyObject* |
|
784 pure_quantify_is_recording_register_window_traps(PyObject *self, PyObject *args) |
|
785 { |
|
786 return call_voidarg_function( |
|
787 quantify_is_recording_register_window_traps, |
|
788 self, args); |
|
789 } |
|
790 static PyObject* |
|
791 pure_quantify_disable_recording_data(PyObject *self, PyObject *args) |
|
792 { |
|
793 return call_voidarg_function(quantify_disable_recording_data, |
|
794 self, args); |
|
795 } |
|
796 static PyObject* |
|
797 pure_quantify_clear_data(PyObject *self, PyObject *args) |
|
798 { |
|
799 return call_voidarg_function(quantify_clear_data, self, args); |
|
800 } |
|
801 static PyObject* |
|
802 pure_quantify_save_data(PyObject *self, PyObject *args) |
|
803 { |
|
804 return call_voidarg_function(quantify_save_data, self, args); |
|
805 } |
|
806 static PyObject* |
|
807 pure_quantify_save_data_to_file(PyObject *self, PyObject *args) |
|
808 { |
|
809 return call_stringarg_function(quantify_save_data_to_file, self, args); |
|
810 } |
|
811 static PyObject* |
|
812 pure_quantify_add_annotation(PyObject *self, PyObject *args) |
|
813 { |
|
814 return call_stringarg_function(quantify_add_annotation, self, args); |
|
815 } |
|
816 |
|
817 #endif /* QUANTIFY_H */ |
|
818 |
|
819 |
|
820 |
|
821 /* external interface |
|
822 */ |
|
823 static struct PyMethodDef |
|
824 pure_methods[] = { |
|
825 #ifdef COMMON_PURE_FUNCTIONS |
|
826 {"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}, |
|
829 #endif /* COMMON_PURE_FUNCTIONS */ |
|
830 #ifdef PURIFY_H |
|
831 {"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}, |
|
839 /* see purify.h */ |
|
840 {"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}, |
|
843 /**/ |
|
844 {"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}, |
|
885 #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 */ |
|
889 {"purify_exit", pure_purify_exit, METH_VARARGS}, |
|
890 #endif /* HAS_PURIFY_EXIT */ |
|
891 #endif /* PURIFY_H */ |
|
892 #ifdef QUANTIFY_H |
|
893 {"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}, |
|
899 {"quantify_start_recording_system_calls", |
|
900 pure_quantify_start_recording_system_calls, METH_VARARGS}, |
|
901 {"quantify_stop_recording_system_calls", |
|
902 pure_quantify_stop_recording_system_calls, METH_VARARGS}, |
|
903 {"quantify_is_recording_system_calls", |
|
904 pure_quantify_is_recording_system_calls, METH_VARARGS}, |
|
905 {"quantify_start_recording_system_call", |
|
906 pure_quantify_start_recording_system_call, METH_VARARGS}, |
|
907 {"quantify_stop_recording_system_call", |
|
908 pure_quantify_stop_recording_system_call, METH_VARARGS}, |
|
909 {"quantify_is_recording_system_call", |
|
910 pure_quantify_is_recording_system_call, METH_VARARGS}, |
|
911 {"quantify_start_recording_dynamic_library_data", |
|
912 pure_quantify_start_recording_dynamic_library_data, METH_VARARGS}, |
|
913 {"quantify_stop_recording_dynamic_library_data", |
|
914 pure_quantify_stop_recording_dynamic_library_data, METH_VARARGS}, |
|
915 {"quantify_is_recording_dynamic_library_data", |
|
916 pure_quantify_is_recording_dynamic_library_data, METH_VARARGS}, |
|
917 {"quantify_start_recording_register_window_traps", |
|
918 pure_quantify_start_recording_register_window_traps, METH_VARARGS}, |
|
919 {"quantify_stop_recording_register_window_traps", |
|
920 pure_quantify_stop_recording_register_window_traps, METH_VARARGS}, |
|
921 {"quantify_is_recording_register_window_traps", |
|
922 pure_quantify_is_recording_register_window_traps, METH_VARARGS}, |
|
923 {"quantify_disable_recording_data", |
|
924 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}, |
|
929 #endif /* QUANTIFY_H */ |
|
930 {NULL, NULL} /* sentinel */ |
|
931 }; |
|
932 |
|
933 |
|
934 |
|
935 static void |
|
936 ins(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 |
|
949 void |
|
950 initpure() |
|
951 { |
|
952 PyObject *m, *d; |
|
953 |
|
954 if (PyErr_WarnPy3k("the pure module has been removed in " |
|
955 "Python 3.0", 2) < 0) |
|
956 return; |
|
957 |
|
958 m = Py_InitModule("pure", pure_methods); |
|
959 if (m == NULL) |
|
960 return; |
|
961 d = PyModule_GetDict(m); |
|
962 |
|
963 /* this is bogus because we should be able to find this information |
|
964 * out from the header files. Pure's current versions don't |
|
965 * include this information! |
|
966 */ |
|
967 #ifdef PURE_PURIFY_VERSION |
|
968 ins(d, "PURIFY_VERSION", PURE_PURIFY_VERSION); |
|
969 #else |
|
970 PyDict_SetItemString(d, "PURIFY_VERSION", Py_None); |
|
971 #endif |
|
972 |
|
973 /* these aren't terribly useful because purify_exit() isn't |
|
974 * exported correctly. See the note at the top of the file. |
|
975 */ |
|
976 #ifdef PURIFY_EXIT_ERRORS |
|
977 ins(d, "PURIFY_EXIT_ERRORS", PURIFY_EXIT_ERRORS); |
|
978 #endif |
|
979 #ifdef PURIFY_EXIT_LEAKS |
|
980 ins(d, "PURIFY_EXIT_LEAKS", PURIFY_EXIT_LEAKS); |
|
981 #endif |
|
982 #ifdef PURIFY_EXIT_PLEAKS |
|
983 ins(d, "PURIFY_EXIT_PLEAKS", PURIFY_EXIT_PLEAKS); |
|
984 #endif |
|
985 |
|
986 |
|
987 #ifdef PURE_QUANTIFY_VERSION |
|
988 ins(d, "QUANTIFY_VERSION", PURE_QUANTIFY_VERSION); |
|
989 #else |
|
990 PyDict_SetItemString(d, "QUANTIFY_VERSION", Py_None); |
|
991 #endif |
|
992 } |