@@ -36,7 +36,9 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3636#include "traceback.h"
3737
3838#ifndef NDEBUG
39- #define TRACE
39+ /* For debugging the interpreter: */
40+ #define LLTRACE 1 /* Low-level trace feature */
41+ #define CHECKEXC 1 /* Double-check exception checking */
4042#endif
4143
4244/* Forward declarations */
@@ -69,6 +71,7 @@ static int testbool();
6971static int assign_subscript PROTO ((object * , object * , object * ) );
7072static int assign_slice PROTO ((object * , object * , object * , object * ) );
7173static int import_from PROTO ((object * , object * , object * ) );
74+ static object * call_trace PROTO ((object * , frameobject * , char * , object * ) );
7275
7376
7477static frameobject * current_frame ;
@@ -106,12 +109,12 @@ eval_code(co, globals, locals, arg)
106109 register object * u ;
107110 register object * t ;
108111 register frameobject * f ; /* Current frame */
109- int lineno ; /* Current line number */
112+ object * trace ; /* Trace function or NULL */
110113 object * retval ; /* Return value iff why == WHY_RETURN */
111114 char * name ; /* Name used by some instructions */
112115 FILE * fp ; /* Used by print operations */
113- #ifdef TRACE
114- int trace = dictlookup (globals , "__trace__ " ) != NULL ;
116+ #ifdef LLTRACE
117+ int lltrace = dictlookup (globals , "__lltrace__ " ) != NULL ;
115118#endif
116119
117120/* Code access macros */
@@ -134,9 +137,9 @@ eval_code(co, globals, locals, arg)
134137#define BASIC_PUSH (v ) (*stack_pointer++ = (v))
135138#define BASIC_POP () (*--stack_pointer)
136139
137- #ifdef TRACE
138- #define PUSH (v ) (BASIC_PUSH(v), trace && prtrace(TOP(), "push"))
139- #define POP () (trace && prtrace(TOP(), "pop"), BASIC_POP())
140+ #ifdef LLTRACE
141+ #define PUSH (v ) (BASIC_PUSH(v), lltrace && prtrace(TOP(), "push"))
142+ #define POP () (lltrace && prtrace(TOP(), "pop"), BASIC_POP())
140143#else
141144#define PUSH (v ) BASIC_PUSH(v)
142145#define POP () BASIC_POP()
@@ -153,9 +156,37 @@ eval_code(co, globals, locals, arg)
153156 return NULL ;
154157
155158 current_frame = f ;
159+
160+ trace = sysget ("trace" );
161+ if (trace != NULL ) {
162+ /* sys.trace, if defined, is a function that will
163+ be called on *every* entry to a code block.
164+ Its return value, if not None, is a function that
165+ will be called at the start of each executed line
166+ of code. (Actually, the function must return
167+ itself in order to continue tracing.)
168+ The trace functions are called with three arguments:
169+ a pointer to the current frame, a string indicating
170+ why the function is called, and an argument which
171+ depends on the situation. The global trace function
172+ (sys.trace) is also called whenever an exception
173+ is detected. */
174+ trace = call_trace (trace , f , "call" , arg );
175+ if (trace == NULL ) {
176+ /* Trace function raised an error */
177+ sysset ("trace" , (object * )NULL );
178+ current_frame = f -> f_back ;
179+ DECREF (f );
180+ return NULL ;
181+ }
182+ if (trace == None ) {
183+ /* No need to trace this code block */
184+ DECREF (trace );
185+ trace = NULL ;
186+ }
187+ }
156188
157189 next_instr = GETUSTRINGVALUE (f -> f_code -> co_code );
158-
159190 stack_pointer = f -> f_valuestack ;
160191
161192 if (arg != NULL ) {
@@ -166,7 +197,6 @@ eval_code(co, globals, locals, arg)
166197 why = WHY_NOT ;
167198 err = 0 ;
168199 x = None ; /* Not a reference, just anything non-NULL */
169- lineno = -1 ;
170200
171201 for (;;) {
172202 static int ticker ;
@@ -178,7 +208,6 @@ eval_code(co, globals, locals, arg)
178208 if (intrcheck ()) {
179209 err_set (KeyboardInterrupt );
180210 why = WHY_EXCEPTION ;
181- tb_here (f , INSTR_OFFSET (), lineno );
182211 goto on_error ;
183212 }
184213 }
@@ -189,10 +218,10 @@ eval_code(co, globals, locals, arg)
189218 if (HAS_ARG (opcode ))
190219 oparg = NEXTARG ();
191220
192- #ifdef TRACE
221+ #ifdef LLTRACE
193222 /* Instruction tracing */
194223
195- if (trace ) {
224+ if (lltrace ) {
196225 if (HAS_ARG (opcode )) {
197226 printf ("%d: %d, %d\n" ,
198227 (int ) (INSTR_OFFSET () - 3 ),
@@ -273,6 +302,7 @@ eval_code(co, globals, locals, arg)
273302
274303 case UNARY_CALL :
275304 v = POP ();
305+ f -> f_lasti = INSTR_OFFSET () - 1 ; /* For tracing */
276306 x = call_object (v , (object * )NULL );
277307 DECREF (v );
278308 PUSH (x );
@@ -342,6 +372,7 @@ eval_code(co, globals, locals, arg)
342372 case BINARY_CALL :
343373 w = POP ();
344374 v = POP ();
375+ f -> f_lasti = INSTR_OFFSET () - 1 ; /* For tracing */
345376 x = call_object (v , w );
346377 DECREF (v );
347378 DECREF (w );
@@ -921,17 +952,31 @@ eval_code(co, globals, locals, arg)
921952 break ;
922953
923954 case SET_LINENO :
924- #ifdef TRACE
925- if (trace )
955+ #ifdef LLTRACE
956+ if (lltrace )
926957 printf ("--- Line %d ---\n" , oparg );
927958#endif
928- lineno = oparg ;
959+ f -> f_lineno = oparg ;
960+ if (trace != NULL ) {
961+ /* Trace each line of code reached */
962+ f -> f_lasti = INSTR_OFFSET ();
963+ x = call_trace (trace , f , "line" , None );
964+ /* The trace function must return itself
965+ in order to continue tracing */
966+ DECREF (trace );
967+ if (x == None ) {
968+ DECREF (x );
969+ trace = NULL ;
970+ }
971+ else
972+ trace = x ;
973+ }
929974 break ;
930975
931976 default :
932977 fprintf (stderr ,
933978 "XXX lineno: %d, opcode: %d\n" ,
934- lineno , opcode );
979+ f -> f_lineno , opcode );
935980 err_setstr (SystemError , "eval_code: unknown opcode" );
936981 why = WHY_EXCEPTION ;
937982 break ;
@@ -950,7 +995,7 @@ eval_code(co, globals, locals, arg)
950995 err = 0 ;
951996 }
952997
953- #ifndef NDEBUG
998+ #ifndef CHECKEXC
954999 /* Double-check exception status */
9551000
9561001 if (why == WHY_EXCEPTION || why == WHY_RERAISE ) {
@@ -971,10 +1016,49 @@ eval_code(co, globals, locals, arg)
9711016 /* Log traceback info if this is a real exception */
9721017
9731018 if (why == WHY_EXCEPTION ) {
974- int lasti = INSTR_OFFSET () - 1 ;
1019+ f -> f_lasti = INSTR_OFFSET () - 1 ;
9751020 if (HAS_ARG (opcode ))
976- lasti -= 2 ;
977- tb_here (f , lasti , lineno );
1021+ f -> f_lasti -= 2 ;
1022+ tb_here (f );
1023+
1024+ if (trace )
1025+ v = trace ;
1026+ else
1027+ v = sysget ("trace" );
1028+ if (v ) {
1029+ object * type , * value , * traceback , * arg ;
1030+ err_get (& type , & value );
1031+ traceback = tb_fetch ();
1032+ arg = newtupleobject (3 );
1033+ if (arg == NULL )
1034+ err_clear ();
1035+ else {
1036+ settupleitem (arg , 0 , type );
1037+ settupleitem (arg , 1 , value );
1038+ settupleitem (arg , 2 , traceback );
1039+ }
1040+ v = call_trace (v , f , "exception" , arg );
1041+ if (v == NULL ) {
1042+ /* Trace function raised error */
1043+ tb_here (f );
1044+ sysset ("trace" , (object * )NULL );
1045+ XDECREF (trace );
1046+ trace = NULL ;
1047+ }
1048+ else {
1049+ /* Restore original exception */
1050+ err_setval (type , value );
1051+ tb_store (traceback );
1052+ if (v == None )
1053+ DECREF (v );
1054+ else {
1055+ /* Set trace function */
1056+ XDECREF (trace );
1057+ trace = v ;
1058+ }
1059+ }
1060+ XDECREF (arg );
1061+ }
9781062 }
9791063
9801064 /* For the rest, treat WHY_RERAISE as WHY_EXCEPTION */
@@ -1012,9 +1096,7 @@ eval_code(co, globals, locals, arg)
10121096 Python main loop. Don't do
10131097 this for 'finally'. */
10141098 if (b -> b_type == SETUP_EXCEPT ) {
1015- #if 1 /* Oops, this breaks too many things */
10161099 sysset ("exc_traceback" , v );
1017- #endif
10181100 sysset ("exc_value" , val );
10191101 sysset ("exc_type" , exc );
10201102 err_clear ();
@@ -1049,18 +1131,31 @@ eval_code(co, globals, locals, arg)
10491131 XDECREF (v );
10501132 }
10511133
1134+ if (why != WHY_RETURN )
1135+ retval = NULL ;
1136+
1137+ if (trace ) {
1138+ if (why == WHY_RETURN ) {
1139+ x = call_trace (trace , f , "return" , retval );
1140+ if (x == NULL ) {
1141+ XDECREF (retval );
1142+ retval = NULL ;
1143+ }
1144+ else
1145+ DECREF (x );
1146+ }
1147+ DECREF (trace );
1148+ }
1149+
10521150 /* Restore previous frame and release the current one */
10531151
10541152 current_frame = f -> f_back ;
10551153 DECREF (f );
10561154
1057- if (why == WHY_RETURN )
1058- return retval ;
1059- else
1060- return NULL ;
1155+ return retval ;
10611156}
10621157
1063- #ifdef TRACE
1158+ #ifdef LLTRACE
10641159static int
10651160prtrace (v , str )
10661161 object * v ;
@@ -1073,6 +1168,46 @@ prtrace(v, str)
10731168}
10741169#endif
10751170
1171+ static object *
1172+ call_trace (trace , f , msg , arg )
1173+ object * trace ;
1174+ frameobject * f ;
1175+ char * msg ;
1176+ object * arg ;
1177+ {
1178+ object * arglist , * what , * res ;
1179+ static int tracing = 0 ;
1180+
1181+ if (tracing ) {
1182+ /* Don't trace the trace code! */
1183+ INCREF (None );
1184+ return None ;
1185+ }
1186+
1187+ arglist = newtupleobject (3 );
1188+ if (arglist == NULL )
1189+ return NULL ;
1190+ what = newstringobject (msg );
1191+ if (what == NULL ) {
1192+ DECREF (arglist );
1193+ return NULL ;
1194+ }
1195+ INCREF (f );
1196+ if (arg == NULL )
1197+ arg = None ;
1198+ INCREF (arg );
1199+ settupleitem (arglist , 0 , (object * )f );
1200+ settupleitem (arglist , 1 , what );
1201+ settupleitem (arglist , 2 , arg );
1202+ tracing ++ ;
1203+ res = call_object (trace , arglist );
1204+ tracing -- ;
1205+ if (res == NULL )
1206+ tb_here (f );
1207+ DECREF (arglist );
1208+ return res ;
1209+ }
1210+
10761211object *
10771212getlocals ()
10781213{
0 commit comments