17757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch/* C-based Tracer for Coverage. */ 27757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 37757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "Python.h" 47757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "compile.h" /* in 2.3, this wasn't part of Python.h */ 57757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "eval.h" /* or this. */ 67757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "structmember.h" 77757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "frameobject.h" 87757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 97757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch/* Compile-time debugging helpers */ 107757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#undef WHAT_LOG /* Define to log the WHAT params in the trace function. */ 117757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#undef TRACE_LOG /* Define to log our bookkeeping. */ 127757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#undef COLLECT_STATS /* Collect counters: stats are printed when tracer is stopped. */ 137757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 147757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#if COLLECT_STATS 157757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define STATS(x) x 167757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#else 177757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define STATS(x) 187757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#endif 197757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 207757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch/* Py 2.x and 3.x compatibility */ 217757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 227757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#ifndef Py_TYPE 237757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define Py_TYPE(o) (((PyObject*)(o))->ob_type) 247757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#endif 257757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 267757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#if PY_MAJOR_VERSION >= 3 277757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 287757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define MyText_Type PyUnicode_Type 297757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define MyText_Check(o) PyUnicode_Check(o) 307757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define MyText_AS_STRING(o) PyBytes_AS_STRING(PyUnicode_AsASCIIString(o)) 317757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define MyInt_FromLong(l) PyLong_FromLong(l) 327757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 337757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define MyType_HEAD_INIT PyVarObject_HEAD_INIT(NULL, 0) 347757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#else 367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 377757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define MyText_Type PyString_Type 387757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define MyText_Check(o) PyString_Check(o) 397757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define MyText_AS_STRING(o) PyString_AS_STRING(o) 407757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define MyInt_FromLong(l) PyInt_FromLong(l) 417757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 427757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define MyType_HEAD_INIT PyObject_HEAD_INIT(NULL) 0, 437757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 447757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#endif /* Py3k */ 457757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 467757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch/* The values returned to indicate ok or error. */ 477757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define RET_OK 0 487757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define RET_ERROR -1 497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 507757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch/* An entry on the data stack. For each call frame, we need to record the 517757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch dictionary to capture data, and the last line number executed in that 527757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch frame. 537757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch*/ 547757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochtypedef struct { 557757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyObject * file_data; /* PyMem_Malloc'ed, a borrowed ref. */ 567757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch int last_line; 577757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch} DataStackEntry; 587757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 597757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch/* The CTracer type. */ 607757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 617757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochtypedef struct { 627757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyObject_HEAD 637757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 647757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* Python objects manipulated directly by the Collector class. */ 657757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyObject * should_trace; 667757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyObject * warn; 677757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyObject * data; 687757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyObject * should_trace_cache; 697757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyObject * arcs; 707757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 717757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* Has the tracer been started? */ 727757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch int started; 737757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* Are we tracing arcs, or just lines? */ 747757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch int tracing_arcs; 757757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 767757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* 777757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch The data stack is a stack of dictionaries. Each dictionary collects 787757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch data for a single source file. The data stack parallels the call stack: 797757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch each call pushes the new frame's file data onto the data stack, and each 807757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return pops file data off. 817757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 827757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch The file data is a dictionary whose form depends on the tracing options. 837757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch If tracing arcs, the keys are line number pairs. If not tracing arcs, 847757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch the keys are line numbers. In both cases, the value is irrelevant 857757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch (None). 867757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch */ 877757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* The index of the last-used entry in data_stack. */ 887757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch int depth; 897757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* The file data at each level, or NULL if not recording. */ 907757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch DataStackEntry * data_stack; 917757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch int data_stack_alloc; /* number of entries allocated at data_stack. */ 927757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 937757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* The current file_data dictionary. Borrowed. */ 947757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyObject * cur_file_data; 957757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 967757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* The line number of the last line recorded, for tracing arcs. 977757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch -1 means there was no previous line, as when entering a code object. 987757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch */ 997757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch int last_line; 1007757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1017757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* The parent frame for the last exception event, to fix missing returns. */ 1027757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyFrameObject * last_exc_back; 1037757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch int last_exc_firstlineno; 1047757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1057757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#if COLLECT_STATS 1067757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch struct { 10707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch unsigned calls; 10807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch unsigned lines; 10907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch unsigned returns; 11007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch unsigned exceptions; 11107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch unsigned others; 11207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch unsigned new_files; 11307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch unsigned missed_returns; 11407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch unsigned stack_reallocs; 11507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch unsigned errors; 1167757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } stats; 1177757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#endif /* COLLECT_STATS */ 1187757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch} CTracer; 1197757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1207757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define STACK_DELTA 100 1217757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1227757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochstatic int 1237757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochCTracer_init(CTracer *self, PyObject *args_unused, PyObject *kwds_unused) 1247757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch{ 1257757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#if COLLECT_STATS 1267757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->stats.calls = 0; 1277757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->stats.lines = 0; 1287757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->stats.returns = 0; 1297757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->stats.exceptions = 0; 1307757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->stats.others = 0; 1317757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->stats.new_files = 0; 1327757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->stats.missed_returns = 0; 1337757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->stats.stack_reallocs = 0; 1347757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->stats.errors = 0; 1357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#endif /* COLLECT_STATS */ 1367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1377757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->should_trace = NULL; 1387757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->warn = NULL; 1397757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->data = NULL; 1407757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->should_trace_cache = NULL; 1417757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->arcs = NULL; 1427757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1437757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->started = 0; 1447757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->tracing_arcs = 0; 1457757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1467757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->depth = -1; 1477757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->data_stack = PyMem_Malloc(STACK_DELTA*sizeof(DataStackEntry)); 1487757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (self->data_stack == NULL) { 1497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch STATS( self->stats.errors++; ) 1507757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyErr_NoMemory(); 1517757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return RET_ERROR; 1527757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 1537757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->data_stack_alloc = STACK_DELTA; 1547757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1557757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->cur_file_data = NULL; 1567757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->last_line = -1; 1577757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1587757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->last_exc_back = NULL; 1597757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1607757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return RET_OK; 1617757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch} 1627757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1637757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochstatic void 1647757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochCTracer_dealloc(CTracer *self) 1657757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch{ 1667757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (self->started) { 1677757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyEval_SetTrace(NULL, NULL); 1687757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 1697757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1707757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch Py_XDECREF(self->should_trace); 1717757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch Py_XDECREF(self->warn); 1727757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch Py_XDECREF(self->data); 1737757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch Py_XDECREF(self->should_trace_cache); 1747757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1757757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyMem_Free(self->data_stack); 1767757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1777757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch Py_TYPE(self)->tp_free((PyObject*)self); 1787757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch} 1797757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1807757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#if TRACE_LOG 1817757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochstatic const char * 1827757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochindent(int n) 1837757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch{ 1847757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch static const char * spaces = 1857757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch " " 1867757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch " " 1877757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch " " 1887757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch " " 1897757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch ; 1907757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return spaces + strlen(spaces) - n*2; 1917757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch} 1927757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1937757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochstatic int logging = 0; 1947757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch/* Set these constants to be a file substring and line number to start logging. */ 1957757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochstatic const char * start_file = "tests/views"; 1967757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochstatic int start_line = 27; 1977757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1987757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochstatic void 1997757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochshowlog(int depth, int lineno, PyObject * filename, const char * msg) 2007757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch{ 2017757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (logging) { 2027757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch printf("%s%3d ", indent(depth), depth); 2037757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (lineno) { 2047757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch printf("%4d", lineno); 2057757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 2067757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch else { 2077757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch printf(" "); 2087757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 2097757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (filename) { 2107757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch printf(" %s", MyText_AS_STRING(filename)); 2117757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 2127757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (msg) { 2137757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch printf(" %s", msg); 2147757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 2157757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch printf("\n"); 2167757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 2177757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch} 2187757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 2197757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define SHOWLOG(a,b,c,d) showlog(a,b,c,d) 2207757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#else 2217757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define SHOWLOG(a,b,c,d) 2227757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#endif /* TRACE_LOG */ 2237757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 2247757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#if WHAT_LOG 2257757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochstatic const char * what_sym[] = {"CALL", "EXC ", "LINE", "RET "}; 2267757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#endif 2277757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 2287757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch/* Record a pair of integers in self->cur_file_data. */ 2297757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochstatic int 2307757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochCTracer_record_pair(CTracer *self, int l1, int l2) 2317757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch{ 2327757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch int ret = RET_OK; 2337757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 2347757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyObject * t = PyTuple_New(2); 2357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (t != NULL) { 2367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyTuple_SET_ITEM(t, 0, MyInt_FromLong(l1)); 2377757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyTuple_SET_ITEM(t, 1, MyInt_FromLong(l2)); 2387757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (PyDict_SetItem(self->cur_file_data, t, Py_None) < 0) { 2397757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch STATS( self->stats.errors++; ) 2407757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch ret = RET_ERROR; 2417757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 2427757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch Py_DECREF(t); 2437757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 2447757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch else { 2457757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch STATS( self->stats.errors++; ) 2467757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch ret = RET_ERROR; 2477757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 2487757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return ret; 2497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch} 2507757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 2517757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch/* 2527757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * The Trace Function 2537757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch */ 2547757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochstatic int 2557757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochCTracer_trace(CTracer *self, PyFrameObject *frame, int what, PyObject *arg_unused) 2567757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch{ 2577757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch int ret = RET_OK; 2587757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyObject * filename = NULL; 2597757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyObject * tracename = NULL; 2607757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 2617757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch #if WHAT_LOG 2627757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (what <= sizeof(what_sym)/sizeof(const char *)) { 2637757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch printf("trace: %s @ %s %d\n", what_sym[what], MyText_AS_STRING(frame->f_code->co_filename), frame->f_lineno); 2647757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 2657757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch #endif 2667757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 2677757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch #if TRACE_LOG 2687757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (strstr(MyText_AS_STRING(frame->f_code->co_filename), start_file) && frame->f_lineno == start_line) { 2697757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch logging = 1; 2707757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 2717757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch #endif 2727757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 2737757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* See below for details on missing-return detection. */ 2747757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (self->last_exc_back) { 2757757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (frame == self->last_exc_back) { 2767757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* Looks like someone forgot to send a return event. We'll clear 2777757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch the exception state and do the RETURN code here. Notice that the 2787757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch frame we have in hand here is not the correct frame for the RETURN, 2797757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch that frame is gone. Our handling for RETURN doesn't need the 2807757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch actual frame, but we do log it, so that will look a little off if 2817757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch you're looking at the detailed log. 2827757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 2837757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch If someday we need to examine the frame when doing RETURN, then 2847757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch we'll need to keep more of the missed frame's state. 2857757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch */ 2867757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch STATS( self->stats.missed_returns++; ) 2877757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (self->depth >= 0) { 2887757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (self->tracing_arcs && self->cur_file_data) { 2897757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (CTracer_record_pair(self, self->last_line, -self->last_exc_firstlineno) < 0) { 2907757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return RET_ERROR; 2917757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 2927757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 2937757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "missedreturn"); 2947757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->cur_file_data = self->data_stack[self->depth].file_data; 2957757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->last_line = self->data_stack[self->depth].last_line; 2967757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->depth--; 2977757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 2987757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 2997757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->last_exc_back = NULL; 3007757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 3017757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 3027757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 3037757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch switch (what) { 3047757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch case PyTrace_CALL: /* 0 */ 3057757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch STATS( self->stats.calls++; ) 3067757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* Grow the stack. */ 3077757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->depth++; 3087757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (self->depth >= self->data_stack_alloc) { 3097757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch STATS( self->stats.stack_reallocs++; ) 3107757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* We've outgrown our data_stack array: make it bigger. */ 3117757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch int bigger = self->data_stack_alloc + STACK_DELTA; 3127757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch DataStackEntry * bigger_data_stack = PyMem_Realloc(self->data_stack, bigger * sizeof(DataStackEntry)); 3137757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (bigger_data_stack == NULL) { 3147757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch STATS( self->stats.errors++; ) 3157757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyErr_NoMemory(); 3167757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->depth--; 3177757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return RET_ERROR; 3187757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 3197757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->data_stack = bigger_data_stack; 3207757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->data_stack_alloc = bigger; 3217757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 3227757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 3237757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* Push the current state on the stack. */ 3247757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->data_stack[self->depth].file_data = self->cur_file_data; 3257757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->data_stack[self->depth].last_line = self->last_line; 3267757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 3277757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* Check if we should trace this line. */ 3287757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch filename = frame->f_code->co_filename; 3297757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch tracename = PyDict_GetItem(self->should_trace_cache, filename); 3307757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (tracename == NULL) { 3317757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch STATS( self->stats.new_files++; ) 3327757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* We've never considered this file before. */ 3337757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* Ask should_trace about it. */ 3347757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyObject * args = Py_BuildValue("(OO)", filename, frame); 3357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch tracename = PyObject_Call(self->should_trace, args, NULL); 3367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch Py_DECREF(args); 3377757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (tracename == NULL) { 3387757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* An error occurred inside should_trace. */ 3397757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch STATS( self->stats.errors++; ) 3407757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return RET_ERROR; 3417757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 3427757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (PyDict_SetItem(self->should_trace_cache, filename, tracename) < 0) { 3437757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch STATS( self->stats.errors++; ) 3447757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return RET_ERROR; 3457757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 3467757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 3477757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch else { 3487757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch Py_INCREF(tracename); 3497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 3507757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 3517757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* If tracename is a string, then we're supposed to trace. */ 3527757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (MyText_Check(tracename)) { 3537757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyObject * file_data = PyDict_GetItem(self->data, tracename); 3547757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (file_data == NULL) { 3557757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch file_data = PyDict_New(); 3567757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (file_data == NULL) { 3577757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch STATS( self->stats.errors++; ) 3587757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return RET_ERROR; 3597757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 3607757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch ret = PyDict_SetItem(self->data, tracename, file_data); 3617757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch Py_DECREF(file_data); 3627757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (ret < 0) { 3637757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch STATS( self->stats.errors++; ) 3647757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return RET_ERROR; 3657757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 3667757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 3677757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->cur_file_data = file_data; 3687757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* Make the frame right in case settrace(gettrace()) happens. */ 3697757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch Py_INCREF(self); 3707757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch frame->f_trace = (PyObject*)self; 3717757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch SHOWLOG(self->depth, frame->f_lineno, filename, "traced"); 3727757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 3737757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch else { 3747757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->cur_file_data = NULL; 3757757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch SHOWLOG(self->depth, frame->f_lineno, filename, "skipped"); 3767757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 3777757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 3787757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch Py_DECREF(tracename); 3797757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 3807757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->last_line = -1; 3817757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch break; 3827757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 3837757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch case PyTrace_RETURN: /* 3 */ 3847757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch STATS( self->stats.returns++; ) 3857757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* A near-copy of this code is above in the missing-return handler. */ 3867757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (self->depth >= 0) { 3877757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (self->tracing_arcs && self->cur_file_data) { 3887757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch int first = frame->f_code->co_firstlineno; 3897757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (CTracer_record_pair(self, self->last_line, -first) < 0) { 3907757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return RET_ERROR; 3917757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 3927757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 3937757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 3947757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "return"); 3957757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->cur_file_data = self->data_stack[self->depth].file_data; 3967757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->last_line = self->data_stack[self->depth].last_line; 3977757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->depth--; 3987757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 3997757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch break; 4007757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 4017757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch case PyTrace_LINE: /* 2 */ 4027757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch STATS( self->stats.lines++; ) 4037757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (self->depth >= 0) { 4047757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "line"); 4057757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (self->cur_file_data) { 4067757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* We're tracing in this frame: record something. */ 4077757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (self->tracing_arcs) { 4087757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* Tracing arcs: key is (last_line,this_line). */ 4097757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (CTracer_record_pair(self, self->last_line, frame->f_lineno) < 0) { 4107757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return RET_ERROR; 4117757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 4127757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 4137757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch else { 4147757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* Tracing lines: key is simply this_line. */ 4157757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyObject * this_line = MyInt_FromLong(frame->f_lineno); 4167757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (this_line == NULL) { 4177757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch STATS( self->stats.errors++; ) 4187757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return RET_ERROR; 4197757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 4207757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch ret = PyDict_SetItem(self->cur_file_data, this_line, Py_None); 4217757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch Py_DECREF(this_line); 4227757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (ret < 0) { 4237757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch STATS( self->stats.errors++; ) 4247757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return RET_ERROR; 4257757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 4267757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 4277757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 4287757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->last_line = frame->f_lineno; 4297757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 4307757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch break; 4317757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 4327757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch case PyTrace_EXCEPTION: 4337757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* Some code (Python 2.3, and pyexpat anywhere) fires an exception event 4347757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch without a return event. To detect that, we'll keep a copy of the 4357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch parent frame for an exception event. If the next event is in that 4367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch frame, then we must have returned without a return event. We can 4377757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch synthesize the missing event then. 4387757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 4397757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch Python itself fixed this problem in 2.4. Pyexpat still has the bug. 4407757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch I've reported the problem with pyexpat as http://bugs.python.org/issue6359 . 4417757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch If it gets fixed, this code should still work properly. Maybe some day 4427757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch the bug will be fixed everywhere coverage.py is supported, and we can 4437757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch remove this missing-return detection. 4447757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 4457757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch More about this fix: http://nedbatchelder.com/blog/200907/a_nasty_little_bug.html 4467757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch */ 4477757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch STATS( self->stats.exceptions++; ) 4487757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->last_exc_back = frame->f_back; 4497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->last_exc_firstlineno = frame->f_code->co_firstlineno; 4507757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch break; 4517757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 4527757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch default: 4537757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch STATS( self->stats.others++; ) 4547757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch break; 4557757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 4567757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 4577757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return RET_OK; 4587757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch} 4597757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 4607757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch/* 4617757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * Python has two ways to set the trace function: sys.settrace(fn), which 4627757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * takes a Python callable, and PyEval_SetTrace(func, obj), which takes 4637757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * a C function and a Python object. The way these work together is that 4647757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * sys.settrace(pyfn) calls PyEval_SetTrace(builtin_func, pyfn), using the 4657757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * Python callable as the object in PyEval_SetTrace. So sys.gettrace() 4667757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * simply returns the Python object used as the second argument to 4677757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * PyEval_SetTrace. So sys.gettrace() will return our self parameter, which 4687757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * means it must be callable to be used in sys.settrace(). 4697757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * 4707757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * So we make our self callable, equivalent to invoking our trace function. 4717757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * 4727757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * To help with the process of replaying stored frames, this function has an 4737757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * optional keyword argument: 4747757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * 4757757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * def CTracer_call(frame, event, arg, lineno=0) 4767757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * 4777757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * If provided, the lineno argument is used as the line number, and the 4787757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * frame's f_lineno member is ignored. 4797757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch */ 4807757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochstatic PyObject * 4817757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochCTracer_call(CTracer *self, PyObject *args, PyObject *kwds) 4827757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch{ 4837757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyFrameObject *frame; 4847757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyObject *what_str; 4857757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyObject *arg; 4867757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch int lineno = 0; 4877757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch int what; 4887757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch int orig_lineno; 4897757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyObject *ret = NULL; 4907757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 4917757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch static char *what_names[] = { 4927757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch "call", "exception", "line", "return", 4937757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch "c_call", "c_exception", "c_return", 4947757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch NULL 4957757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch }; 4967757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 4977757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch #if WHAT_LOG 4987757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch printf("pytrace\n"); 4997757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch #endif 5007757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 5017757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch static char *kwlist[] = {"frame", "event", "arg", "lineno", NULL}; 5027757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 5037757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!O|i:Tracer_call", kwlist, 5047757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch &PyFrame_Type, &frame, &MyText_Type, &what_str, &arg, &lineno)) { 5057757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch goto done; 5067757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 5077757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 5087757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* In Python, the what argument is a string, we need to find an int 5097757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch for the C function. */ 5107757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch for (what = 0; what_names[what]; what++) { 5117757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (!strcmp(MyText_AS_STRING(what_str), what_names[what])) { 5127757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch break; 5137757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 5147757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 5157757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 5167757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* Save off the frame's lineno, and use the forced one, if provided. */ 5177757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch orig_lineno = frame->f_lineno; 5187757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (lineno > 0) { 5197757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch frame->f_lineno = lineno; 5207757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 5217757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 5227757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* Invoke the C function, and return ourselves. */ 5237757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (CTracer_trace(self, frame, what, arg) == RET_OK) { 5247757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch Py_INCREF(self); 5257757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch ret = (PyObject *)self; 5267757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 5277757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 5287757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* Clean up. */ 5297757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch frame->f_lineno = orig_lineno; 5307757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 5317757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochdone: 5327757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return ret; 5337757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch} 5347757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 5357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochstatic PyObject * 5367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochCTracer_start(CTracer *self, PyObject *args_unused) 5377757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch{ 5387757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyEval_SetTrace((Py_tracefunc)CTracer_trace, (PyObject*)self); 5397757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->started = 1; 5407757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->tracing_arcs = self->arcs && PyObject_IsTrue(self->arcs); 5417757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->last_line = -1; 5427757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 5437757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch /* start() returns a trace function usable with sys.settrace() */ 5447757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch Py_INCREF(self); 5457757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return (PyObject *)self; 5467757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch} 5477757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 5487757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochstatic PyObject * 5497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochCTracer_stop(CTracer *self, PyObject *args_unused) 5507757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch{ 5517757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (self->started) { 5527757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyEval_SetTrace(NULL, NULL); 5537757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self->started = 0; 5547757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 5557757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 5567757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return Py_BuildValue(""); 5577757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch} 5587757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 5597757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochstatic PyObject * 5607757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochCTracer_get_stats(CTracer *self) 5617757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch{ 5627757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#if COLLECT_STATS 5637757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return Py_BuildValue( 5647757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch "{sI,sI,sI,sI,sI,sI,sI,sI,si,sI}", 5657757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch "calls", self->stats.calls, 5667757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch "lines", self->stats.lines, 5677757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch "returns", self->stats.returns, 5687757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch "exceptions", self->stats.exceptions, 5697757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch "others", self->stats.others, 5707757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch "new_files", self->stats.new_files, 5717757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch "missed_returns", self->stats.missed_returns, 5727757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch "stack_reallocs", self->stats.stack_reallocs, 5737757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch "stack_alloc", self->data_stack_alloc, 5747757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch "errors", self->stats.errors 5757757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch ); 5767757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#else 5777757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return Py_BuildValue(""); 5787757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#endif /* COLLECT_STATS */ 5797757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch} 5807757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 5817757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochstatic PyMemberDef 5827757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochCTracer_members[] = { 5837757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch { "should_trace", T_OBJECT, offsetof(CTracer, should_trace), 0, 5847757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyDoc_STR("Function indicating whether to trace a file.") }, 5857757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 5867757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch { "warn", T_OBJECT, offsetof(CTracer, warn), 0, 5877757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyDoc_STR("Function for issuing warnings.") }, 5887757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 5897757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch { "data", T_OBJECT, offsetof(CTracer, data), 0, 5907757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyDoc_STR("The raw dictionary of trace data.") }, 5917757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 5927757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch { "should_trace_cache", T_OBJECT, offsetof(CTracer, should_trace_cache), 0, 5937757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyDoc_STR("Dictionary caching should_trace results.") }, 5947757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 5957757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch { "arcs", T_OBJECT, offsetof(CTracer, arcs), 0, 5967757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyDoc_STR("Should we trace arcs, or just lines?") }, 5977757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 5987757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch { NULL } 5997757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch}; 6007757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 6017757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochstatic PyMethodDef 6027757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochCTracer_methods[] = { 6037757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch { "start", (PyCFunction) CTracer_start, METH_VARARGS, 6047757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyDoc_STR("Start the tracer") }, 6057757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 6067757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch { "stop", (PyCFunction) CTracer_stop, METH_VARARGS, 6077757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyDoc_STR("Stop the tracer") }, 6087757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 6097757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch { "get_stats", (PyCFunction) CTracer_get_stats, METH_VARARGS, 6107757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyDoc_STR("Get statistics about the tracing") }, 6117757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 6127757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch { NULL } 6137757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch}; 6147757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 6157757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochstatic PyTypeObject 6167757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochCTracerType = { 6177757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch MyType_HEAD_INIT 6187757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch "coverage.CTracer", /*tp_name*/ 6197757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch sizeof(CTracer), /*tp_basicsize*/ 6207757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /*tp_itemsize*/ 6217757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch (destructor)CTracer_dealloc, /*tp_dealloc*/ 6227757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /*tp_print*/ 6237757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /*tp_getattr*/ 6247757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /*tp_setattr*/ 6257757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /*tp_compare*/ 6267757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /*tp_repr*/ 6277757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /*tp_as_number*/ 6287757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /*tp_as_sequence*/ 6297757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /*tp_as_mapping*/ 6307757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /*tp_hash */ 6317757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch (ternaryfunc)CTracer_call, /*tp_call*/ 6327757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /*tp_str*/ 6337757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /*tp_getattro*/ 6347757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /*tp_setattro*/ 6357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /*tp_as_buffer*/ 6367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 6377757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch "CTracer objects", /* tp_doc */ 6387757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /* tp_traverse */ 6397757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /* tp_clear */ 6407757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /* tp_richcompare */ 6417757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /* tp_weaklistoffset */ 6427757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /* tp_iter */ 6437757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /* tp_iternext */ 6447757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch CTracer_methods, /* tp_methods */ 6457757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch CTracer_members, /* tp_members */ 6467757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /* tp_getset */ 6477757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /* tp_base */ 6487757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /* tp_dict */ 6497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /* tp_descr_get */ 6507757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /* tp_descr_set */ 6517757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /* tp_dictoffset */ 6527757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch (initproc)CTracer_init, /* tp_init */ 6537757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /* tp_alloc */ 6547757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 0, /* tp_new */ 6557757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch}; 6567757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 6577757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch/* Module definition */ 6587757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 6597757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define MODULE_DOC PyDoc_STR("Fast coverage tracer.") 6607757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 6617757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#if PY_MAJOR_VERSION >= 3 6627757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 6637757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochstatic PyModuleDef 6647757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochmoduledef = { 6657757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyModuleDef_HEAD_INIT, 6667757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch "coverage.tracer", 6677757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch MODULE_DOC, 6687757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch -1, 6697757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch NULL, /* methods */ 6707757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch NULL, 6717757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch NULL, /* traverse */ 6727757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch NULL, /* clear */ 6737757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch NULL 6747757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch}; 6757757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 6767757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 6777757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochPyObject * 6787757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochPyInit_tracer(void) 6797757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch{ 6807757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyObject * mod = PyModule_Create(&moduledef); 6817757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (mod == NULL) { 6827757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return NULL; 6837757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 6847757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 6857757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch CTracerType.tp_new = PyType_GenericNew; 6867757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (PyType_Ready(&CTracerType) < 0) { 6877757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch Py_DECREF(mod); 6887757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return NULL; 6897757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 6907757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 6917757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch Py_INCREF(&CTracerType); 6927757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyModule_AddObject(mod, "CTracer", (PyObject *)&CTracerType); 6937757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 6947757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return mod; 6957757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch} 6967757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 6977757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#else 6987757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 6997757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochvoid 7007757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochinittracer(void) 7017757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch{ 7027757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyObject * mod; 7037757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 7047757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch mod = Py_InitModule3("coverage.tracer", NULL, MODULE_DOC); 7057757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (mod == NULL) { 7067757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return; 7077757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 7087757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 7097757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch CTracerType.tp_new = PyType_GenericNew; 7107757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (PyType_Ready(&CTracerType) < 0) { 7117757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return; 7127757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 7137757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 7147757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch Py_INCREF(&CTracerType); 7157757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch PyModule_AddObject(mod, "CTracer", (PyObject *)&CTracerType); 7167757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch} 7177757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 7187757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#endif /* Py3k */ 7197757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 720