| ︙ | | |
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
-
+
|
/*
* Each subcommand has a number of 'types' to which it can apply. Currently
* 'execution', 'command' and 'variable' are the only types supported. These
* three arrays MUST be kept in sync! In the future we may provide an API to
* add to the list of supported trace types.
*/
static const char *traceTypeOptions[] = {
static const char *const traceTypeOptions[] = {
"execution", "command", "variable", NULL
};
static Tcl_TraceTypeObjCmd *const traceSubCmds[] = {
TraceExecutionObjCmd,
TraceCommandObjCmd,
TraceVariableObjCmd,
};
|
| ︙ | | |
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
|
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
|
-
+
|
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
int optionIndex;
char *name, *flagOps, *p;
/* Main sub commands to 'trace' */
static const char *traceOptions[] = {
static const char *const traceOptions[] = {
"add", "info", "remove",
#ifndef TCL_REMOVE_OBSOLETE_TRACES
"variable", "vdelete", "vinfo",
#endif
NULL
};
/* 'OLD' options are pre-Tcl-8.4 style */
|
| ︙ | | |
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
|
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
|
-
+
|
Tcl_WrongNumArgs(interp, 2, objv, "type ?arg ...?");
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[2], traceTypeOptions, "option",
0, &typeIndex) != TCL_OK) {
return TCL_ERROR;
}
return (traceSubCmds[typeIndex])(interp, optionIndex, objc, objv);
return traceSubCmds[typeIndex](interp, optionIndex, objc, objv);
}
case TRACE_INFO: {
/*
* All sub commands of trace info must take exactly two more arguments
* which name the type of thing being traced and the name of the thing
* being traced.
*/
|
| ︙ | | |
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
|
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
|
-
+
|
Tcl_WrongNumArgs(interp, 2, objv, "type name");
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[2], traceTypeOptions, "option",
0, &typeIndex) != TCL_OK) {
return TCL_ERROR;
}
return (traceSubCmds[typeIndex])(interp, optionIndex, objc, objv);
return traceSubCmds[typeIndex](interp, optionIndex, objc, objv);
break;
}
#ifndef TCL_REMOVE_OBSOLETE_TRACES
case TRACE_OLD_VARIABLE:
case TRACE_OLD_VDELETE: {
Tcl_Obj *copyObjv[6];
|
| ︙ | | |
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
|
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
|
-
+
-
+
|
}
Tcl_ListObjAppendElement(NULL, opsList, opObj);
}
copyObjv[0] = NULL;
memcpy(copyObjv+1, objv, objc*sizeof(Tcl_Obj *));
copyObjv[4] = opsList;
if (optionIndex == TRACE_OLD_VARIABLE) {
code = (traceSubCmds[2])(interp, TRACE_ADD, objc+1, copyObjv);
code = traceSubCmds[2](interp, TRACE_ADD, objc+1, copyObjv);
} else {
code = (traceSubCmds[2])(interp, TRACE_REMOVE, objc+1, copyObjv);
code = traceSubCmds[2](interp, TRACE_REMOVE, objc+1, copyObjv);
}
Tcl_DecrRefCount(opsList);
return code;
}
case TRACE_OLD_VINFO: {
ClientData clientData;
char ops[5];
|
| ︙ | | |
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
|
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
|
-
+
|
{
int commandLength, index;
char *name, *command;
size_t length;
enum traceOptions {
TRACE_ADD, TRACE_INFO, TRACE_REMOVE
};
static const char *opStrings[] = {
static const char *const opStrings[] = {
"enter", "leave", "enterstep", "leavestep", NULL
};
enum operations {
TRACE_EXEC_ENTER, TRACE_EXEC_LEAVE,
TRACE_EXEC_ENTER_STEP, TRACE_EXEC_LEAVE_STEP
};
|
| ︙ | | |
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
|
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
|
-
+
|
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
int commandLength, index;
char *name, *command;
size_t length;
enum traceOptions { TRACE_ADD, TRACE_INFO, TRACE_REMOVE };
static const char *opStrings[] = { "delete", "rename", NULL };
static const char *const opStrings[] = { "delete", "rename", NULL };
enum operations { TRACE_CMD_DELETE, TRACE_CMD_RENAME };
switch ((enum traceOptions) optionIndex) {
case TRACE_ADD:
case TRACE_REMOVE: {
int flags = 0;
int i, listLen, result;
|
| ︙ | | |
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
|
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
|
-
+
|
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
int commandLength, index;
char *name, *command;
size_t length;
enum traceOptions { TRACE_ADD, TRACE_INFO, TRACE_REMOVE };
static const char *opStrings[] = {
static const char *const opStrings[] = {
"array", "read", "unset", "write", NULL
};
enum operations {
TRACE_VAR_ARRAY, TRACE_VAR_READ, TRACE_VAR_UNSET, TRACE_VAR_WRITE
};
switch ((enum traceOptions) optionIndex) {
|
| ︙ | | |
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
|
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
|
-
-
-
+
+
+
|
if (tracePtr->flags & traceFlags) {
if (tracePtr->proc == TraceExecutionProc) {
TraceCommandInfo *tcmdPtr = tracePtr->clientData;
tcmdPtr->curFlags = traceFlags;
tcmdPtr->curCode = code;
}
traceCode = (tracePtr->proc)(tracePtr->clientData,
interp, curLevel, command, (Tcl_Command) cmdPtr,
objc, objv);
traceCode = tracePtr->proc(tracePtr->clientData, interp,
curLevel, command, (Tcl_Command) cmdPtr, objc,
objv);
}
} else {
/*
* Old-style trace.
*/
if (traceFlags & TCL_TRACE_ENTER_EXEC) {
|
| ︙ | | |
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
|
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
|
-
+
|
}
/*
* Execute any delete callback.
*/
if (tracePtr->delProc != NULL) {
(tracePtr->delProc)(tracePtr->clientData);
tracePtr->delProc(tracePtr->clientData);
}
/*
* Delete the trace object.
*/
Tcl_EventuallyFree((char *) tracePtr, TCL_DYNAMIC);
|
| ︙ | | |
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
|
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
|
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
+
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
|
* Restore the variable's flags, remove the record of our active traces,
* and then return.
*/
done:
if (code == TCL_ERROR) {
if (leaveErrMsg) {
const char *type = "";
const char *verb = "";
Tcl_Obj *options = Tcl_GetReturnOptions((Tcl_Interp *)iPtr, code);
Tcl_Obj *errorInfoKey, *errorInfo;
const char *type = "";
TclNewLiteralStringObj(errorInfoKey, "-errorinfo");
Tcl_IncrRefCount(errorInfoKey);
Tcl_DictObjGet(NULL, options, errorInfoKey, &errorInfo);
Tcl_IncrRefCount(errorInfo);
Tcl_DictObjRemove(NULL, options, errorInfoKey);
if (Tcl_IsShared(errorInfo)) {
Tcl_DecrRefCount(errorInfo);
errorInfo = Tcl_DuplicateObj(errorInfo);
Tcl_IncrRefCount(errorInfo);
}
Tcl_AppendToObj(errorInfo, "\n (", -1);
switch (flags&(TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_ARRAY)) {
case TCL_TRACE_READS:
type = "read";
Tcl_AppendToObj(errorInfo, type, -1);
verb = "read";
type = verb;
break;
case TCL_TRACE_WRITES:
type = "set";
Tcl_AppendToObj(errorInfo, "write", -1);
verb = "set";
type = "write";
break;
case TCL_TRACE_ARRAY:
type = "trace array";
Tcl_AppendToObj(errorInfo, "array", -1);
verb = "trace array";
type = "array";
break;
}
if (disposeFlags & TCL_TRACE_RESULT_OBJECT) {
Tcl_SetObjResult((Tcl_Interp *)iPtr, (Tcl_Obj *) result);
} else {
Tcl_SetResult((Tcl_Interp *)iPtr, result, TCL_STATIC);
}
Tcl_AddErrorInfo((Tcl_Interp *)iPtr, "");
Tcl_AppendObjToErrorInfo((Tcl_Interp *)iPtr, Tcl_ObjPrintf(
"\n (%s trace on \"%s%s%s%s\")", type, part1,
(part2 ? "(" : ""), (part2 ? part2 : ""),
(part2 ? ")" : "") ));
if (disposeFlags & TCL_TRACE_RESULT_OBJECT) {
TclVarErrMsg((Tcl_Interp *) iPtr, part1, part2, type,
TclVarErrMsg((Tcl_Interp *) iPtr, part1, part2, verb,
Tcl_GetString((Tcl_Obj *) result));
} else {
TclVarErrMsg((Tcl_Interp *) iPtr, part1, part2, type, result);
TclVarErrMsg((Tcl_Interp *) iPtr, part1, part2, verb, result);
}
Tcl_AppendToObj(errorInfo, " trace on \"", -1);
Tcl_AppendToObj(errorInfo, part1, -1);
if (part2 != NULL) {
Tcl_AppendToObj(errorInfo, "(", -1);
Tcl_AppendToObj(errorInfo, part1, -1);
Tcl_AppendToObj(errorInfo, ")", -1);
}
Tcl_AppendToObj(errorInfo, "\")", -1);
Tcl_DictObjPut(NULL, options, errorInfoKey, errorInfo);
Tcl_DecrRefCount(errorInfoKey);
Tcl_DecrRefCount(errorInfo);
code = Tcl_SetReturnOptions((Tcl_Interp *) iPtr, options);
iPtr->flags &= ~(ERR_ALREADY_LOGGED);
Tcl_DiscardInterpState(state);
} else {
Tcl_RestoreInterpState((Tcl_Interp *) iPtr, state);
}
DisposeTraceResult(disposeFlags,result);
} else if (state) {
|
| ︙ | | |