puremodule.c 31.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
/* This module exports the C API to such Pure Software Inc. (tm) (now
 * called Pure Atria Corporation) products as Purify (tm) and Quantify
 * (tm).  Other packages could be added, but I didn't have those products
 * and thus lack the API documentation.
 *
 * Currently supported: Quantify 2.x, Purify 3.x
 *
 * You need to decide which products you want to incorporate into the
 * module when you compile this file.  The way to do this is to edit
 * <Python>/Modules/Setup to pass the appropriate flags to the compiler.
 * -DWITH_PURIFY compiles in the Purify support, and -DWITH_QUANTIFY
 * compiles in the Quantify support.  -DWITH_ALL_PURE compiles in both.
 * You can also build a Purify'd or Quantify'd interpreter by passing in
 * the LINKCC variable to make.  E.g. if you want to build a Purify'd
 * interpreter and are using gcc, build Python with this command:
 *
 * make LINKCC='purify gcc'
 *
 * It would be nice (and probably easy) to provide this file as a shared
 * library, however since it doesn't appear that Pure gives us shared
 * libraries of the stubs, it doesn't really matter.  For now, you have to
 * link this file in statically.
 *
 * Major bogosity.  The purify.h header file exports purify_exit(), but
 * guess what?  It is not defined in the libpurify_stubs.a file!  I tried
 * to fake one here, hoping the Pure linker would Do The Right Thing when
 * instrumented for Purify, but it doesn't seem to, so I don't export
 * purify_exit() to the Python layer.  In Python you should raise a
 * SystemExit exception anyway.
 *
 * The actual purify.h and quantify.h files which embody the APIs are
 * copyrighted by Pure Software, Inc. and are only attainable through them.
 * This module assumes you have legally installed licenses of their
 * software.  Contact them on the Web via <http://www.pureatria.com/>
 *
 * Author: Barry Warsaw <bwarsaw@python.org>
 *                      <bwarsaw@cnri.reston.va.us>
 */

#include "Python.h"

#if defined(WITH_PURIFY) || defined(WITH_ALL_PURE)
#    include <purify.h>
#    define HAS_PURIFY_EXIT 0                /* See note at top of file */
#    define PURE_PURIFY_VERSION 3            /* not provided by purify.h */
#endif
#if defined(WITH_QUANTIFY) || defined(WITH_ALL_PURE)
#    include <quantify.h>
#    define PURE_QUANTIFY_VERSION 2          /* not provided by quantify.h */
#endif
#if defined(PURIFY_H) || defined(QUANTIFY_H)
#    define COMMON_PURE_FUNCTIONS
#endif /* PURIFY_H || QUANTIFY_H */

typedef int (*VoidArgFunc)(void);
typedef int (*StringArgFunc)(char*);
typedef int (*PrintfishFunc)(const char*, ...);
typedef int (*StringIntArgFunc)(const char*, int);


61

62
static PyObject*
63
call_voidarg_function(VoidArgFunc func, PyObject *self, PyObject *args)
64
{
65
    int status;
66

67 68
    if (!PyArg_ParseTuple(args, ""))
        return NULL;
69

70 71
    status = func();
    return Py_BuildValue("i", status);
72 73 74
}

static PyObject*
75
call_stringarg_function(StringArgFunc func, PyObject *self, PyObject *args)
76
{
77 78
    int status;
    char* stringarg;
79

80 81
    if (!PyArg_ParseTuple(args, "s", &stringarg))
        return NULL;
82

83 84
    status = func(stringarg);
    return Py_BuildValue("i", status);
85 86 87
}

static PyObject*
88
call_stringorint_function(StringArgFunc func, PyObject *self, PyObject *args)
89
{
90 91 92
    int status;
    int intarg;
    char* stringarg;
93

94 95 96 97 98 99 100 101
    /* according to the quantify.h file, the argument to
     * quantify_*_recording_system_call can be an integer or a string,
     * but the functions are prototyped as taking a single char*
     * argument. Yikes!
     */
    if (PyArg_ParseTuple(args, "i", &intarg))
        /* func is prototyped as int(*)(char*)
         * better shut up the compiler
102
         */
103
        status = func((char*)intarg);
104

105 106 107 108 109 110 111 112
    else {
        PyErr_Clear();
        if (!PyArg_ParseTuple(args, "s", &stringarg))
            return NULL;
        else
            status = func(stringarg);
    }
    return Py_BuildValue("i", status);
113 114 115
}

static PyObject*
116
call_printfish_function(PrintfishFunc func, PyObject *self, PyObject *args)
117
{
118 119 120 121 122 123
    /* we support the printf() style vararg functions by requiring the
     * formatting be done in Python.  At the C level we pass just a string
     * to the printf() style function.
     */
    int status;
    char* argstring;
124

125 126
    if (!PyArg_ParseTuple(args, "s", &argstring))
        return NULL;
127

128 129
    status = func("%s", argstring);
    return Py_BuildValue("i", status);
130 131 132
}

static PyObject*
133
call_intasaddr_function(StringArgFunc func, PyObject *self, PyObject *args)
134
{
135 136
    long memrep;
    int id;
137

138 139
    if (!PyArg_ParseTuple(args, "l", &memrep))
        return NULL;
140

141 142
    id = func((char*)memrep);
    return Py_BuildValue("i", id);
143 144 145
}

static PyObject*
146
call_stringandint_function(StringIntArgFunc func, PyObject *self,
147
                           PyObject *args)
148
{
149 150 151
    long srcrep;
    int size;
    int status;
152

153 154
    if (!PyArg_ParseTuple(args, "li", &srcrep, &size))
        return NULL;
155

156 157
    status = func((char*)srcrep, size);
    return Py_BuildValue("i", status);
158 159 160
}


161

162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
/* functions common to all products
 *
 * N.B. These printf() style functions are a bit of a kludge.  Since the
 * API doesn't provide vprintf versions of them, we can't call them
 * directly.  They don't support all the standard printf % modifiers
 * anyway.  The way to use these is to use Python's % string operator to do
 * the formatting.  By the time these functions get the thing to print,
 * it's already a string, and they just use "%s" as the format string.
 */

#ifdef COMMON_PURE_FUNCTIONS

static PyObject*
pure_pure_logfile_printf(PyObject* self, PyObject* args)
{
177
    return call_printfish_function(pure_logfile_printf, self, args);
178 179 180 181 182
}

static PyObject*
pure_pure_printf(PyObject* self, PyObject* args)
{
183
    return call_printfish_function(pure_printf, self, args);
184 185 186 187 188
}

static PyObject*
pure_pure_printf_with_banner(PyObject* self, PyObject* args)
{
189
    return call_printfish_function(pure_printf_with_banner, self, args);
190 191 192 193 194 195
}


#endif /* COMMON_PURE_FUNCTIONS */


196

197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
/* Purify functions
 *
 * N.B. There are some interfaces described in the purify.h file that are
 * not described in the manual.
 *
 * Unsigned longs purify_report_{address,number,type,result} are not
 * accessible from the Python layer since they seem mostly useful when
 * purify_stop_here() is called by the (C) debugger.  The same is true of
 * the purify_stop_here_internal() function so it isn't exported either.
 * And purify_stop_here() should never be called directly.
 *
 * The header file says purify_{new,all,clear_new}_reports() are obsolete
 * so they aren't exported.
 *
 * None of the custom dynamic loader functions are exported.
 *
 * purify_unsafe_memcpy() isn't exported.
 *
 * purify_{start,size}_of_block() aren't exported.
 *
 * The manual that I have says that the prototype for the second argument
 * to purify_map_pool is:
 *
 *    void (*fn)(char*)
 *
 * but the purify.h file declares it as:
 *
 *    void (*fn)(char*, int, void*)
 *
 * and does not explain what the other arguments are for.  I support the
 * latter but I don't know if I do it right or usefully.
 *
 * The header file says that purify_describe() returns a char* which is the
 * pointer passed to it.  The manual says it returns an int, but I believe
 * that is a typo.
 */
#ifdef PURIFY_H

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 279
    return call_printfish_function(purify_printf_with_call_chain,
                                   self, args);
280 281
}
static PyObject*
282
pure_purify_set_pool_id(PyObject *self, PyObject *args)
283
{
284 285
    long memrep;
    int id;
286

287 288
    if (!PyArg_ParseTuple(args, "li:purify_set_pool_id", &memrep, &id))
        return NULL;
289

290 291 292
    purify_set_pool_id((char*)memrep, id);
    Py_INCREF(Py_None);
    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 303
    long memrep;
    long datarep;
304

305 306
    if (!PyArg_ParseTuple(args, "ll:purify_set_user_data", &memrep, &datarep))
        return NULL;
307

308 309 310
    purify_set_user_data((char*)memrep, (void*)datarep);
    Py_INCREF(Py_None);
    return Py_None;
311 312
}
static PyObject*
313
pure_purify_get_user_data(PyObject *self, PyObject *args)
314
{
315 316 317 318 319
    /* can't use call_intasaddr_function() since purify_get_user_data()
     * returns a void*
     */
    long memrep;
    void* data;
320

321 322
    if (!PyArg_ParseTuple(args, "l:purify_get_user_data", &memrep))
        return NULL;
323

324 325
    data = purify_get_user_data((char*)memrep);
    return Py_BuildValue("l", (long)data);
326 327
}

328

329 330 331 332 333 334 335 336 337 338 339 340 341
/* this global variable is shared by both mapping functions:
 * pure_purify_map_pool() and pure_purify_map_pool_id().  Since they cache
 * this variable it should be safe in the face of recursion or cross
 * calling.
 *
 * Further note that the prototype for the callback function is wrong in
 * the Purify manual.  The manual says the function takes a single char*,
 * but the header file says it takes an additional int and void*.  I have
 * no idea what these are for!
 */
static PyObject* MapCallable = NULL;

static void
342
map_pool_callback(char* mem, int user_size, void *user_aux_data)
343
{
344 345 346 347 348
    long memrep = (long)mem;
    long user_aux_data_rep = (long)user_aux_data;
    PyObject* result;
    PyObject* memobj = Py_BuildValue("lil", memrep, user_size,
                                     user_aux_data_rep);
349

350 351
    if (memobj == NULL)
        return;
352

353 354 355
    result = PyEval_CallObject(MapCallable, memobj);
    Py_DECREF(result);
    Py_DECREF(memobj);
356 357 358
}

static PyObject*
359
pure_purify_map_pool(PyObject *self, PyObject *args)
360
{
361 362 363 364
    /* cache global variable in case of recursion */
    PyObject* saved_callable = MapCallable;
    PyObject* arg_callable;
    int id;
365

366 367
    if (!PyArg_ParseTuple(args, "iO:purify_map_pool", &id, &arg_callable))
        return NULL;
368

369 370 371 372 373 374 375 376
    if (!PyCallable_Check(arg_callable)) {
        PyErr_SetString(PyExc_TypeError,
                        "Second argument must be callable");
        return NULL;
    }
    MapCallable = arg_callable;
    purify_map_pool(id, map_pool_callback);
    MapCallable = saved_callable;
377

378 379
    Py_INCREF(Py_None);
    return Py_None;
380 381 382
}

static void
383
PurifyMapPoolIdCallback(int id)
384
{
385 386
    PyObject* result;
    PyObject* intobj = Py_BuildValue("i", id);
387

388 389
    if (intobj == NULL)
        return;
390

391 392 393
    result = PyEval_CallObject(MapCallable, intobj);
    Py_DECREF(result);
    Py_DECREF(intobj);
394 395 396
}

static PyObject*
397
pure_purify_map_pool_id(PyObject *self, PyObject *args)
398
{
399 400 401
    /* cache global variable in case of recursion */
    PyObject* saved_callable = MapCallable;
    PyObject* arg_callable;
402

403 404
    if (!PyArg_ParseTuple(args, "O:purify_map_pool_id", &arg_callable))
        return NULL;
405

406 407 408 409
    if (!PyCallable_Check(arg_callable)) {
        PyErr_SetString(PyExc_TypeError, "Argument must be callable.");
        return NULL;
    }
410

411 412 413
    MapCallable = arg_callable;
    purify_map_pool_id(PurifyMapPoolIdCallback);
    MapCallable = saved_callable;
414

415 416
    Py_INCREF(Py_None);
    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 450
    return call_voidarg_function(purify_start_batch_show_first,
                                 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 461 462 463 464
    /* can't strictly use call_stringarg_function since
     * purify_name_thread takes a const char*, not a char*
     */
    int status;
    char* stringarg;
465

466 467
    if (!PyArg_ParseTuple(args, "s:purify_name_thread", &stringarg))
        return NULL;
468

469 470
    status = purify_name_thread(stringarg);
    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 562 563 564
    long addrrep;
    unsigned int size;
    char* type;
    int status;
565

566 567
    if (!PyArg_ParseTuple(args, "lis:purify_watch_n", &addrrep, &size, &type))
        return NULL;
568

569 570
    status = purify_watch_n((char*)addrrep, size, type);
    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 583
    int watchno;
    int status;
584

585 586
    if (!PyArg_ParseTuple(args, "i:purify_watch_remove", &watchno))
        return NULL;
587

588 589
    status = purify_watch_remove(watchno);
    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 601
    long addrrep;
    char* rtn;
602

603 604
    if (!PyArg_ParseTuple(args, "l:purify_describe", &addrrep))
        return NULL;
605

606 607
    rtn = purify_describe((char*)addrrep);
    return Py_BuildValue("l", (long)rtn);
608 609 610
}

static PyObject*
611
pure_purify_what_colors(PyObject *self, PyObject *args)
612
{
613 614 615 616 617 618
    long addrrep;
    unsigned int size;
    int status;

    if (!PyArg_ParseTuple(args, "li:purify_what_colors", &addrrep, &size))
        return NULL;
619

620 621
    status = purify_what_colors((char*)addrrep, size);
    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 634
    return call_stringandint_function(purify_assert_is_readable,
                                      self, args);
635 636
}
static PyObject*
637
pure_purify_assert_is_writable(PyObject *self, PyObject *args)
638
{
639 640
    return call_stringandint_function(purify_assert_is_writable,
                                      self, args);
641 642 643 644 645 646 647 648 649
}

#if HAS_PURIFY_EXIT

/* I wish I could include this, but I can't.  See the notes at the top of
 * the file.
 */

static PyObject*
650
pure_purify_exit(PyObject *self, PyObject *args)
651
{
652
    int status;
653

654 655
    if (!PyArg_ParseTuple(args, "i:purify_exit", &status))
        return NULL;
656

657 658 659 660
    /* purify_exit doesn't always act like exit(). See the manual */
    purify_exit(status);
    Py_INCREF(Py_None);
    return Py_None;
661 662 663 664 665 666
}
#endif /* HAS_PURIFY_EXIT */

#endif /* PURIFY_H */


667

668 669 670 671 672 673 674 675 676 677 678 679 680
/* Quantify functions
 *
 * N.B. Some of these functions are only described in the quantify.h file,
 * not in the version of the hardcopy manual that I had.  If you're not
 * sure what some of these do, check the header file, it is documented
 * fairly well.
 *
 * None of the custom dynamic loader functions are exported.
 *
 */
#ifdef QUANTIFY_H

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 694
    return call_voidarg_function(quantify_print_recording_state,
                                 self, args);
695 696
}
static PyObject*
697
pure_quantify_start_recording_data(PyObject *self, PyObject *args)
698
{
699 700
    return call_voidarg_function(quantify_start_recording_data,
                                 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 716
    return call_voidarg_function(quantify_start_recording_system_calls,
                                 self, args);
717 718
}
static PyObject*
719
pure_quantify_stop_recording_system_calls(PyObject *self, PyObject *args)
720
{
721 722
    return call_voidarg_function(quantify_stop_recording_system_calls,
                                 self, args);
723 724
}
static PyObject*
725
pure_quantify_is_recording_system_calls(PyObject *self, PyObject *args)
726
{
727 728
    return call_voidarg_function(quantify_is_recording_system_calls,
                                 self, args);
729 730
}
static PyObject*
731
pure_quantify_start_recording_system_call(PyObject *self, PyObject *args)
732
{
733 734
    return call_stringorint_function(quantify_start_recording_system_call,
                                       self, args);
735 736
}
static PyObject*
737
pure_quantify_stop_recording_system_call(PyObject *self, PyObject *args)
738
{
739 740
    return call_stringorint_function(quantify_stop_recording_system_call,
                                     self, args);
741 742
}
static PyObject*
743
pure_quantify_is_recording_system_call(PyObject *self, PyObject *args)
744
{
745 746
    return call_stringorint_function(quantify_is_recording_system_call,
                                     self, args);
747 748
}
static PyObject*
749
pure_quantify_start_recording_dynamic_library_data(PyObject *self, PyObject *args)
750
{
751 752 753
    return call_voidarg_function(
        quantify_start_recording_dynamic_library_data,
        self, args);
754 755
}
static PyObject*
756
pure_quantify_stop_recording_dynamic_library_data(PyObject *self, PyObject *args)
757
{
758 759 760
    return call_voidarg_function(
        quantify_stop_recording_dynamic_library_data,
        self, args);
761 762
}
static PyObject*
763
pure_quantify_is_recording_dynamic_library_data(PyObject *self, PyObject *args)
764
{
765 766 767
    return call_voidarg_function(
        quantify_is_recording_dynamic_library_data,
        self, args);
768 769
}
static PyObject*
770
pure_quantify_start_recording_register_window_traps(PyObject *self, PyObject *args)
771
{
772 773 774
    return call_voidarg_function(
        quantify_start_recording_register_window_traps,
        self, args);
775 776
}
static PyObject*
777
pure_quantify_stop_recording_register_window_traps(PyObject *self, PyObject *args)
778
{
779 780 781
    return call_voidarg_function(
        quantify_stop_recording_register_window_traps,
        self, args);
782 783
}
static PyObject*
784
pure_quantify_is_recording_register_window_traps(PyObject *self, PyObject *args)
785
{
786 787 788
    return call_voidarg_function(
        quantify_is_recording_register_window_traps,
        self, args);
789 790
}
static PyObject*
791
pure_quantify_disable_recording_data(PyObject *self, PyObject *args)
792
{
793 794
    return call_voidarg_function(quantify_disable_recording_data,
                                 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 818 819
}

#endif /* QUANTIFY_H */


820

821 822 823 824 825
/* external interface
 */
static struct PyMethodDef
pure_methods[] = {
#ifdef COMMON_PURE_FUNCTIONS
826 827 828
    {"pure_logfile_printf",            pure_pure_logfile_printf,            METH_VARARGS},
    {"pure_printf",                    pure_pure_printf,                    METH_VARARGS},
    {"pure_printf_with_banner",        pure_pure_printf_with_banner,        METH_VARARGS},
829 830
#endif /* COMMON_PURE_FUNCTIONS */
#ifdef PURIFY_H
831 832 833 834 835 836 837 838
    {"purify_all_inuse",               pure_purify_all_inuse,               METH_VARARGS},
    {"purify_all_leaks",               pure_purify_all_leaks,               METH_VARARGS},
    {"purify_new_inuse",               pure_purify_new_inuse,               METH_VARARGS},
    {"purify_new_leaks",               pure_purify_new_leaks,               METH_VARARGS},
    {"purify_clear_inuse",             pure_purify_clear_inuse,             METH_VARARGS},
    {"purify_clear_leaks",             pure_purify_clear_leaks,             METH_VARARGS},
    {"purify_all_fds_inuse",           pure_purify_all_fds_inuse,           METH_VARARGS},
    {"purify_new_fds_inuse",           pure_purify_new_fds_inuse,           METH_VARARGS},
839
    /* see purify.h */
840 841 842
    {"purify_logfile_printf",          pure_pure_logfile_printf,            METH_VARARGS},
    {"purify_printf",                  pure_pure_printf,                    METH_VARARGS},
    {"purify_printf_with_banner",      pure_pure_printf_with_banner,        METH_VARARGS},
843
    /**/
844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884
    {"purify_printf_with_call_chain",  pure_purify_printf_with_call_chain,  METH_VARARGS},
    {"purify_set_pool_id",             pure_purify_set_pool_id,             METH_VARARGS},
    {"purify_get_pool_id",             pure_purify_get_pool_id,             METH_VARARGS},
    {"purify_set_user_data",           pure_purify_set_user_data,           METH_VARARGS},
    {"purify_get_user_data",           pure_purify_get_user_data,           METH_VARARGS},
    {"purify_map_pool",                pure_purify_map_pool,                METH_VARARGS},
    {"purify_map_pool_id",             pure_purify_map_pool_id,             METH_VARARGS},
    {"purify_new_messages",            pure_purify_new_messages,            METH_VARARGS},
    {"purify_all_messages",            pure_purify_all_messages,            METH_VARARGS},
    {"purify_clear_messages",          pure_purify_clear_messages,          METH_VARARGS},
    {"purify_clear_new_messages",      pure_purify_clear_new_messages,      METH_VARARGS},
    {"purify_start_batch",             pure_purify_start_batch,             METH_VARARGS},
    {"purify_start_batch_show_first",  pure_purify_start_batch_show_first,  METH_VARARGS},
    {"purify_stop_batch",              pure_purify_stop_batch,              METH_VARARGS},
    {"purify_name_thread",             pure_purify_name_thread,             METH_VARARGS},
    {"purify_watch",                   pure_purify_watch,                   METH_VARARGS},
    {"purify_watch_1",                 pure_purify_watch_1,                 METH_VARARGS},
    {"purify_watch_2",                 pure_purify_watch_2,                 METH_VARARGS},
    {"purify_watch_4",                 pure_purify_watch_4,                 METH_VARARGS},
    {"purify_watch_8",                 pure_purify_watch_8,                 METH_VARARGS},
    {"purify_watch_w_1",               pure_purify_watch_w_1,               METH_VARARGS},
    {"purify_watch_w_2",               pure_purify_watch_w_2,               METH_VARARGS},
    {"purify_watch_w_4",               pure_purify_watch_w_4,               METH_VARARGS},
    {"purify_watch_w_8",               pure_purify_watch_w_8,               METH_VARARGS},
    {"purify_watch_r_1",               pure_purify_watch_r_1,               METH_VARARGS},
    {"purify_watch_r_2",               pure_purify_watch_r_2,               METH_VARARGS},
    {"purify_watch_r_4",               pure_purify_watch_r_4,               METH_VARARGS},
    {"purify_watch_r_8",               pure_purify_watch_r_8,               METH_VARARGS},
    {"purify_watch_rw_1",              pure_purify_watch_rw_1,              METH_VARARGS},
    {"purify_watch_rw_2",              pure_purify_watch_rw_2,              METH_VARARGS},
    {"purify_watch_rw_4",              pure_purify_watch_rw_4,              METH_VARARGS},
    {"purify_watch_rw_8",              pure_purify_watch_rw_8,              METH_VARARGS},
    {"purify_watch_n",                 pure_purify_watch_n,                 METH_VARARGS},
    {"purify_watch_info",              pure_purify_watch_info,              METH_VARARGS},
    {"purify_watch_remove",            pure_purify_watch_remove,            METH_VARARGS},
    {"purify_watch_remove_all",        pure_purify_watch_remove_all,        METH_VARARGS},
    {"purify_describe",                pure_purify_describe,                METH_VARARGS},
    {"purify_what_colors",             pure_purify_what_colors,             METH_VARARGS},
    {"purify_is_running",              pure_purify_is_running,              METH_VARARGS},
    {"purify_assert_is_readable",      pure_purify_assert_is_readable,      METH_VARARGS},
    {"purify_assert_is_writable",      pure_purify_assert_is_writable,      METH_VARARGS},
885 886 887 888
#if HAS_PURIFY_EXIT
    /* I wish I could include this, but I can't.  See the notes at the
     * top of the file.
     */
889
    {"purify_exit",                    pure_purify_exit,                    METH_VARARGS},
890 891 892
#endif /* HAS_PURIFY_EXIT */
#endif /* PURIFY_H */
#ifdef QUANTIFY_H
893 894 895 896 897 898
    {"quantify_is_running",            pure_quantify_is_running,            METH_VARARGS},
    {"quantify_help",                  pure_quantify_help,                  METH_VARARGS},
    {"quantify_print_recording_state", pure_quantify_print_recording_state, METH_VARARGS},
    {"quantify_start_recording_data",  pure_quantify_start_recording_data,  METH_VARARGS},
    {"quantify_stop_recording_data",   pure_quantify_stop_recording_data,   METH_VARARGS},
    {"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 925 926 927 928
     pure_quantify_disable_recording_data, METH_VARARGS},
    {"quantify_clear_data",        pure_quantify_clear_data,        METH_VARARGS},
    {"quantify_save_data",         pure_quantify_save_data,         METH_VARARGS},
    {"quantify_save_data_to_file", pure_quantify_save_data_to_file, METH_VARARGS},
    {"quantify_add_annotation",    pure_quantify_add_annotation,    METH_VARARGS},
929
#endif /* QUANTIFY_H */
930
    {NULL,  NULL}                            /* sentinel */
931 932 933
};


934

935 936
static void
ins(d, name, val)
937 938 939
    PyObject *d;
    char* name;
    long val;
940
{
941 942 943 944 945
    PyObject *v = PyInt_FromLong(val);
    if (v) {
        (void)PyDict_SetItemString(d, name, v);
        Py_DECREF(v);
    }
946 947 948 949 950 951
}


void
initpure()
{
952
    PyObject *m, *d;
953

954 955 956
    if (PyErr_WarnPy3k("the pure module has been removed in "
                       "Python 3.0", 2) < 0)
        return;
957

958 959 960 961
    m = Py_InitModule("pure", pure_methods);
    if (m == NULL)
        return;
    d = PyModule_GetDict(m);
962

963 964 965 966
    /* this is bogus because we should be able to find this information
     * out from the header files.  Pure's current versions don't
     * include this information!
     */
967
#ifdef PURE_PURIFY_VERSION
968
    ins(d, "PURIFY_VERSION", PURE_PURIFY_VERSION);
969
#else
970
    PyDict_SetItemString(d, "PURIFY_VERSION", Py_None);
971 972
#endif

973 974 975
    /* these aren't terribly useful because purify_exit() isn't
     * exported correctly.  See the note at the top of the file.
     */
976
#ifdef PURIFY_EXIT_ERRORS
977
    ins(d, "PURIFY_EXIT_ERRORS", PURIFY_EXIT_ERRORS);
978 979
#endif
#ifdef PURIFY_EXIT_LEAKS
980
    ins(d, "PURIFY_EXIT_LEAKS",  PURIFY_EXIT_LEAKS);
981 982
#endif
#ifdef PURIFY_EXIT_PLEAKS
983
    ins(d, "PURIFY_EXIT_PLEAKS", PURIFY_EXIT_PLEAKS);
984 985 986 987
#endif


#ifdef PURE_QUANTIFY_VERSION
988
    ins(d, "QUANTIFY_VERSION", PURE_QUANTIFY_VERSION);
989
#else
990
    PyDict_SetItemString(d, "QUANTIFY_VERSION", Py_None);
991 992
#endif
}