@@ -296,6 +296,53 @@ CTracer_set_pdata_stack(CTracer *self)
296
296
* Parts of the trace function.
297
297
*/
298
298
299
+ static void
300
+ CTracer_line_number_range (CTracer * self , PyFrameObject * frame , int lineno , int * lineno_from , int * lineno_to )
301
+ {
302
+ if (self -> pcur_entry -> file_tracer == Py_None ) {
303
+ * lineno_from = * lineno_to = lineno ;
304
+ return ;
305
+ }
306
+
307
+ PyObject * from_to = NULL ;
308
+ PyObject * pyint = NULL ;
309
+
310
+ int f_lineno = PyFrame_GetLineNumber (frame );
311
+ if (lineno != f_lineno ) {
312
+ /* Tracers look at f_lineno, so that's where we store the line number we want them to see. */
313
+ frame -> f_lineno = lineno ;
314
+ }
315
+
316
+ STATS ( self -> stats .pycalls ++ ; )
317
+ from_to = PyObject_CallMethodObjArgs (self -> pcur_entry -> file_tracer , str_line_number_range , frame , NULL );
318
+ frame -> f_lineno = f_lineno ;
319
+ if (from_to == NULL ) {
320
+ goto error ;
321
+ }
322
+ if (!PyTuple_Check (from_to ) || PyTuple_Size (from_to ) != 2 ) {
323
+ PyErr_SetString (
324
+ PyExc_TypeError ,
325
+ "line_number_range must return 2-tuple"
326
+ );
327
+ goto error ;
328
+ }
329
+ pyint = PyTuple_GetItem (from_to , 0 );
330
+ if (pyint == NULL || pyint_as_int (pyint , lineno_from ) < 0 ) {
331
+ goto error ;
332
+ }
333
+ pyint = PyTuple_GetItem (from_to , 1 );
334
+ if (pyint == NULL || pyint_as_int (pyint , lineno_to ) < 0 ) {
335
+ goto error ;
336
+ }
337
+ goto cleanup ;
338
+
339
+ error :
340
+ CTracer_disable_plugin (self , self -> pcur_entry -> disposition );
341
+
342
+ cleanup :
343
+ Py_XDECREF (from_to );
344
+ }
345
+
299
346
static int
300
347
CTracer_handle_call (CTracer * self , PyFrameObject * frame )
301
348
{
@@ -542,11 +589,16 @@ CTracer_handle_call(CTracer *self, PyFrameObject *frame)
542
589
real_call = (MyFrame_GetLasti (frame ) < 0 );
543
590
#endif
544
591
545
- if (real_call ) {
546
- self -> pcur_entry -> last_line = - MyFrame_GetCode (frame )-> co_firstlineno ;
547
- }
548
- else {
549
- self -> pcur_entry -> last_line = PyFrame_GetLineNumber (frame );
592
+ if (self -> tracing_arcs && self -> pcur_entry -> file_data ) {
593
+ int lineno_from = 0 , lineno_to = 0 ;
594
+ if (real_call ) {
595
+ CTracer_line_number_range (self , frame , MyFrame_GetCode (frame )-> co_firstlineno , & lineno_from , & lineno_to );
596
+ } else {
597
+ CTracer_line_number_range (self , frame , PyFrame_GetLineNumber (frame ), & lineno_from , & lineno_to );
598
+ }
599
+ if (lineno_from > 0 ) {
600
+ self -> pcur_entry -> last_line = real_call ? - lineno_from : lineno_from ;
601
+ }
550
602
}
551
603
552
604
ok :
@@ -571,6 +623,9 @@ CTracer_disable_plugin(CTracer *self, PyObject * disposition)
571
623
PyObject * ret ;
572
624
PyErr_Print ();
573
625
626
+ self -> pcur_entry -> file_data = NULL ;
627
+ self -> pcur_entry -> file_tracer = Py_None ;
628
+
574
629
STATS ( self -> stats .pycalls ++ ; )
575
630
ret = PyObject_CallFunctionObjArgs (self -> disable_plugin , disposition , NULL );
576
631
if (ret == NULL ) {
@@ -588,40 +643,6 @@ CTracer_disable_plugin(CTracer *self, PyObject * disposition)
588
643
PyErr_Print ();
589
644
}
590
645
591
-
592
- static int
593
- CTracer_unpack_pair (CTracer * self , PyObject * pair , int * p_one , int * p_two )
594
- {
595
- int ret = RET_ERROR ;
596
- int the_int ;
597
- PyObject * pyint = NULL ;
598
- int index ;
599
-
600
- if (!PyTuple_Check (pair ) || PyTuple_Size (pair ) != 2 ) {
601
- PyErr_SetString (
602
- PyExc_TypeError ,
603
- "line_number_range must return 2-tuple"
604
- );
605
- goto error ;
606
- }
607
-
608
- for (index = 0 ; index < 2 ; index ++ ) {
609
- pyint = PyTuple_GetItem (pair , index );
610
- if (pyint == NULL ) {
611
- goto error ;
612
- }
613
- if (pyint_as_int (pyint , & the_int ) < 0 ) {
614
- goto error ;
615
- }
616
- * (index == 0 ? p_one : p_two ) = the_int ;
617
- }
618
-
619
- ret = RET_OK ;
620
-
621
- error :
622
- return ret ;
623
- }
624
-
625
646
static int
626
647
CTracer_handle_line (CTracer * self , PyFrameObject * frame )
627
648
{
@@ -632,36 +653,17 @@ CTracer_handle_line(CTracer *self, PyFrameObject *frame)
632
653
if (self -> pdata_stack -> depth >= 0 ) {
633
654
SHOWLOG (PyFrame_GetLineNumber (frame ), MyFrame_GetCode (frame )-> co_filename , "line" );
634
655
if (self -> pcur_entry -> file_data ) {
635
- int lineno_from = -1 ;
636
- int lineno_to = -1 ;
637
-
638
- /* We're tracing in this frame: record something. */
639
- if (self -> pcur_entry -> file_tracer != Py_None ) {
640
- PyObject * from_to = NULL ;
641
- STATS ( self -> stats .pycalls ++ ; )
642
- from_to = PyObject_CallMethodObjArgs (self -> pcur_entry -> file_tracer , str_line_number_range , frame , NULL );
643
- if (from_to == NULL ) {
644
- CTracer_disable_plugin (self , self -> pcur_entry -> disposition );
645
- goto ok ;
646
- }
647
- ret2 = CTracer_unpack_pair (self , from_to , & lineno_from , & lineno_to );
648
- Py_DECREF (from_to );
649
- if (ret2 < 0 ) {
650
- CTracer_disable_plugin (self , self -> pcur_entry -> disposition );
651
- goto ok ;
652
- }
653
- }
654
- else {
655
- lineno_from = lineno_to = PyFrame_GetLineNumber (frame );
656
- }
657
-
658
- if (lineno_from != -1 ) {
656
+ /* We're tracing in this frame: try to record something. */
657
+ int lineno_from = 0 , lineno_to = 0 ;
658
+ CTracer_line_number_range (self , frame , PyFrame_GetLineNumber (frame ), & lineno_from , & lineno_to );
659
+ if (lineno_from > 0 ) {
659
660
for (; lineno_from <= lineno_to ; lineno_from ++ ) {
660
661
if (self -> tracing_arcs ) {
661
662
/* Tracing arcs: key is (last_line,this_line). */
662
663
if (CTracer_record_pair (self , self -> pcur_entry -> last_line , lineno_from ) < 0 ) {
663
664
goto error ;
664
665
}
666
+ self -> pcur_entry -> last_line = lineno_from ;
665
667
}
666
668
else {
667
669
/* Tracing lines: key is simply this_line. */
@@ -676,14 +678,11 @@ CTracer_handle_line(CTracer *self, PyFrameObject *frame)
676
678
goto error ;
677
679
}
678
680
}
679
-
680
- self -> pcur_entry -> last_line = lineno_from ;
681
681
}
682
682
}
683
683
}
684
684
}
685
685
686
- ok :
687
686
ret = RET_OK ;
688
687
689
688
error :
@@ -737,9 +736,12 @@ CTracer_handle_return(CTracer *self, PyFrameObject *frame)
737
736
real_return = !(is_yield || is_yield_from );
738
737
#endif
739
738
if (real_return ) {
740
- int first = MyFrame_GetCode (frame )-> co_firstlineno ;
741
- if (CTracer_record_pair (self , self -> pcur_entry -> last_line , - first ) < 0 ) {
742
- goto error ;
739
+ int lineno_from = 0 , lineno_to = 0 ;
740
+ CTracer_line_number_range (self , frame , MyFrame_GetCode (frame )-> co_firstlineno , & lineno_from , & lineno_to );
741
+ if (lineno_from > 0 ) {
742
+ if (CTracer_record_pair (self , self -> pcur_entry -> last_line , - lineno_from ) < 0 ) {
743
+ goto error ;
744
+ }
743
745
}
744
746
}
745
747
}
@@ -920,7 +922,7 @@ CTracer_call(CTracer *self, PyObject *args, PyObject *kwds)
920
922
#endif
921
923
922
924
/* Save off the frame's lineno, and use the forced one, if provided. */
923
- orig_lineno = frame -> f_lineno ;
925
+ orig_lineno = PyFrame_GetLineNumber ( frame ) ;
924
926
if (lineno > 0 ) {
925
927
frame -> f_lineno = lineno ;
926
928
}
0 commit comments