@@ -278,6 +278,53 @@ CTracer_set_pdata_stack(CTracer *self)
278
278
* Parts of the trace function.
279
279
*/
280
280
281
+ static void
282
+ CTracer_line_number_range (CTracer * self , PyFrameObject * frame , int lineno , int * lineno_from , int * lineno_to )
283
+ {
284
+ if (self -> pcur_entry -> file_tracer == Py_None ) {
285
+ * lineno_from = * lineno_to = lineno ;
286
+ return ;
287
+ }
288
+
289
+ PyObject * from_to = NULL ;
290
+ PyObject * pyint = NULL ;
291
+
292
+ int f_lineno = PyFrame_GetLineNumber (frame );
293
+ if (lineno != f_lineno ) {
294
+ /* Tracers look at f_lineno, so that's where we store the line number we want them to see. */
295
+ frame -> f_lineno = lineno ;
296
+ }
297
+
298
+ STATS ( self -> stats .pycalls ++ ; )
299
+ from_to = PyObject_CallMethodObjArgs (self -> pcur_entry -> file_tracer , str_line_number_range , frame , NULL );
300
+ frame -> f_lineno = f_lineno ;
301
+ if (from_to == NULL ) {
302
+ goto error ;
303
+ }
304
+ if (!PyTuple_Check (from_to ) || PyTuple_Size (from_to ) != 2 ) {
305
+ PyErr_SetString (
306
+ PyExc_TypeError ,
307
+ "line_number_range must return 2-tuple"
308
+ );
309
+ goto error ;
310
+ }
311
+ pyint = PyTuple_GetItem (from_to , 0 );
312
+ if (pyint == NULL || pyint_as_int (pyint , lineno_from ) < 0 ) {
313
+ goto error ;
314
+ }
315
+ pyint = PyTuple_GetItem (from_to , 1 );
316
+ if (pyint == NULL || pyint_as_int (pyint , lineno_to ) < 0 ) {
317
+ goto error ;
318
+ }
319
+ goto cleanup ;
320
+
321
+ error :
322
+ CTracer_disable_plugin (self , self -> pcur_entry -> disposition );
323
+
324
+ cleanup :
325
+ Py_XDECREF (from_to );
326
+ }
327
+
281
328
static int
282
329
CTracer_check_missing_return (CTracer * self , PyFrameObject * frame )
283
330
{
@@ -301,8 +348,12 @@ CTracer_check_missing_return(CTracer *self, PyFrameObject *frame)
301
348
}
302
349
if (self -> pdata_stack -> depth >= 0 ) {
303
350
if (self -> tracing_arcs && self -> pcur_entry -> file_data ) {
304
- if (CTracer_record_pair (self , self -> pcur_entry -> last_line , - self -> last_exc_firstlineno ) < 0 ) {
305
- goto error ;
351
+ int lineno_from = 0 , lineno_to = 0 ;
352
+ CTracer_line_number_range (self , frame , self -> last_exc_firstlineno , & lineno_from , & lineno_to );
353
+ if (lineno_from > 0 ) {
354
+ if (CTracer_record_pair (self , self -> pcur_entry -> last_line , - lineno_from ) < 0 ) {
355
+ goto error ;
356
+ }
306
357
}
307
358
}
308
359
SHOWLOG (self -> pdata_stack -> depth , PyFrame_GetLineNumber (frame ), frame -> f_code -> co_filename , "missedreturn" );
@@ -548,11 +599,16 @@ CTracer_handle_call(CTracer *self, PyFrameObject *frame)
548
599
* re-entering a generator also. f_lasti is -1 for a true call, and a
549
600
* real byte offset for a generator re-entry.
550
601
*/
551
- if (frame -> f_lasti < 0 ) {
552
- self -> pcur_entry -> last_line = - frame -> f_code -> co_firstlineno ;
553
- }
554
- else {
555
- self -> pcur_entry -> last_line = PyFrame_GetLineNumber (frame );
602
+ if (self -> tracing_arcs && self -> pcur_entry -> file_data ) {
603
+ int lineno_from = 0 , lineno_to = 0 ;
604
+ if (frame -> f_lasti < 0 ) {
605
+ CTracer_line_number_range (self , frame , frame -> f_code -> co_firstlineno , & lineno_from , & lineno_to );
606
+ } else {
607
+ CTracer_line_number_range (self , frame , PyFrame_GetLineNumber (frame ), & lineno_from , & lineno_to );
608
+ }
609
+ if (lineno_from > 0 ) {
610
+ self -> pcur_entry -> last_line = frame -> f_lasti < 0 ? - lineno_from : lineno_from ;
611
+ }
556
612
}
557
613
558
614
ok :
@@ -574,6 +630,9 @@ CTracer_disable_plugin(CTracer *self, PyObject * disposition)
574
630
PyObject * ret ;
575
631
PyErr_Print ();
576
632
633
+ self -> pcur_entry -> file_data = NULL ;
634
+ self -> pcur_entry -> file_tracer = Py_None ;
635
+
577
636
STATS ( self -> stats .pycalls ++ ; )
578
637
ret = PyObject_CallFunctionObjArgs (self -> disable_plugin , disposition , NULL );
579
638
if (ret == NULL ) {
@@ -591,40 +650,6 @@ CTracer_disable_plugin(CTracer *self, PyObject * disposition)
591
650
PyErr_Print ();
592
651
}
593
652
594
-
595
- static int
596
- CTracer_unpack_pair (CTracer * self , PyObject * pair , int * p_one , int * p_two )
597
- {
598
- int ret = RET_ERROR ;
599
- int the_int ;
600
- PyObject * pyint = NULL ;
601
- int index ;
602
-
603
- if (!PyTuple_Check (pair ) || PyTuple_Size (pair ) != 2 ) {
604
- PyErr_SetString (
605
- PyExc_TypeError ,
606
- "line_number_range must return 2-tuple"
607
- );
608
- goto error ;
609
- }
610
-
611
- for (index = 0 ; index < 2 ; index ++ ) {
612
- pyint = PyTuple_GetItem (pair , index );
613
- if (pyint == NULL ) {
614
- goto error ;
615
- }
616
- if (pyint_as_int (pyint , & the_int ) < 0 ) {
617
- goto error ;
618
- }
619
- * (index == 0 ? p_one : p_two ) = the_int ;
620
- }
621
-
622
- ret = RET_OK ;
623
-
624
- error :
625
- return ret ;
626
- }
627
-
628
653
static int
629
654
CTracer_handle_line (CTracer * self , PyFrameObject * frame )
630
655
{
@@ -635,36 +660,17 @@ CTracer_handle_line(CTracer *self, PyFrameObject *frame)
635
660
if (self -> pdata_stack -> depth >= 0 ) {
636
661
SHOWLOG (self -> pdata_stack -> depth , PyFrame_GetLineNumber (frame ), frame -> f_code -> co_filename , "line" );
637
662
if (self -> pcur_entry -> file_data ) {
638
- int lineno_from = -1 ;
639
- int lineno_to = -1 ;
640
-
641
- /* We're tracing in this frame: record something. */
642
- if (self -> pcur_entry -> file_tracer != Py_None ) {
643
- PyObject * from_to = NULL ;
644
- STATS ( self -> stats .pycalls ++ ; )
645
- from_to = PyObject_CallMethodObjArgs (self -> pcur_entry -> file_tracer , str_line_number_range , frame , NULL );
646
- if (from_to == NULL ) {
647
- CTracer_disable_plugin (self , self -> pcur_entry -> disposition );
648
- goto ok ;
649
- }
650
- ret2 = CTracer_unpack_pair (self , from_to , & lineno_from , & lineno_to );
651
- Py_DECREF (from_to );
652
- if (ret2 < 0 ) {
653
- CTracer_disable_plugin (self , self -> pcur_entry -> disposition );
654
- goto ok ;
655
- }
656
- }
657
- else {
658
- lineno_from = lineno_to = PyFrame_GetLineNumber (frame );
659
- }
660
-
661
- if (lineno_from != -1 ) {
663
+ /* We're tracing in this frame: try to record something. */
664
+ int lineno_from = 0 , lineno_to = 0 ;
665
+ CTracer_line_number_range (self , frame , PyFrame_GetLineNumber (frame ), & lineno_from , & lineno_to );
666
+ if (lineno_from > 0 ) {
662
667
for (; lineno_from <= lineno_to ; lineno_from ++ ) {
663
668
if (self -> tracing_arcs ) {
664
669
/* Tracing arcs: key is (last_line,this_line). */
665
670
if (CTracer_record_pair (self , self -> pcur_entry -> last_line , lineno_from ) < 0 ) {
666
671
goto error ;
667
672
}
673
+ self -> pcur_entry -> last_line = lineno_from ;
668
674
}
669
675
else {
670
676
/* Tracing lines: key is simply this_line. */
@@ -679,14 +685,11 @@ CTracer_handle_line(CTracer *self, PyFrameObject *frame)
679
685
goto error ;
680
686
}
681
687
}
682
-
683
- self -> pcur_entry -> last_line = lineno_from ;
684
688
}
685
689
}
686
690
}
687
691
}
688
692
689
- ok :
690
693
ret = RET_OK ;
691
694
692
695
error :
@@ -721,9 +724,12 @@ CTracer_handle_return(CTracer *self, PyFrameObject *frame)
721
724
bytecode = MyBytes_AS_STRING (pCode )[lasti ];
722
725
}
723
726
if (bytecode != YIELD_VALUE ) {
724
- int first = frame -> f_code -> co_firstlineno ;
725
- if (CTracer_record_pair (self , self -> pcur_entry -> last_line , - first ) < 0 ) {
726
- goto error ;
727
+ int lineno_from = 0 , lineno_to = 0 ;
728
+ CTracer_line_number_range (self , frame , frame -> f_code -> co_firstlineno , & lineno_from , & lineno_to );
729
+ if (lineno_from > 0 ) {
730
+ if (CTracer_record_pair (self , self -> pcur_entry -> last_line , - lineno_from ) < 0 ) {
731
+ goto error ;
732
+ }
727
733
}
728
734
}
729
735
}
@@ -936,7 +942,7 @@ CTracer_call(CTracer *self, PyObject *args, PyObject *kwds)
936
942
#endif
937
943
938
944
/* Save off the frame's lineno, and use the forced one, if provided. */
939
- orig_lineno = frame -> f_lineno ;
945
+ orig_lineno = PyFrame_GetLineNumber ( frame ) ;
940
946
if (lineno > 0 ) {
941
947
frame -> f_lineno = lineno ;
942
948
}
0 commit comments