5 * Copyright 1993-1998 Lucent Technologies, Inc.
7 * Permission to use, copy, modify, and distribute this software and
8 * its documentation for any purpose and without fee is hereby
9 * granted, provided that the above copyright notice appear in all
10 * copies and that both that the copyright notice and warranty
11 * disclaimer appear in supporting documentation, and that the names
12 * of Lucent Technologies any of their entities not be used in
13 * advertising or publicity pertaining to distribution of the software
14 * without specific, written prior permission.
16 * Lucent Technologies disclaims all warranties with regard to this
17 * software, including all implied warranties of merchantability and
18 * fitness. In no event shall Lucent Technologies be liable for any
19 * special, indirect or consequential damages or any damages
20 * whatsoever resulting from loss of use, data or profits, whether in
21 * an action of contract, negligence or other tortuous action, arising
22 * out of or in connection with the use or performance of this
30 #ifdef TIME_WITH_SYS_TIME
34 #ifdef HAVE_SYS_TIME_H
38 #endif /* HAVE_SYS_TIME_H */
39 #endif /* TIME_WITH_SYS_TIME */
42 static Blt_Chain watchChain;
44 static Tcl_CmdTraceProc DebugProc;
45 static Tcl_CmdProc DebugCmd;
56 Blt_ChainLink *linkPtr;
61 for (linkPtr = Blt_ChainFirstLink(&watchChain); linkPtr != NULL;
62 linkPtr = Blt_ChainNextLink(linkPtr)) {
63 infoPtr = Blt_ChainGetValue(linkPtr);
64 if ((infoPtr->name[0] == c) && (strcmp(name, infoPtr->name) == 0)) {
68 linkPtr = Blt_ChainAllocLink(sizeof(WatchInfo));
69 infoPtr = Blt_ChainGetValue(linkPtr);
70 infoPtr->name = Blt_Strdup(name);
71 Blt_ChainLinkAfter(&watchChain, linkPtr, (Blt_ChainLink *)NULL);
76 DeleteWatch(watchName)
79 Blt_ChainLink *linkPtr;
84 for (linkPtr = Blt_ChainFirstLink(&watchChain); linkPtr != NULL;
85 linkPtr = Blt_ChainNextLink(linkPtr)) {
86 infoPtr = Blt_ChainGetValue(linkPtr);
87 if ((infoPtr->name[0] == c) &&
88 (strcmp(infoPtr->name, watchName) == 0)) {
89 Blt_Free(infoPtr->name);
90 Blt_ChainDeleteLink(&watchChain, linkPtr);
98 DebugProc(clientData, interp, level, command, proc, cmdClientData,
100 ClientData clientData; /* Not used. */
101 Tcl_Interp *interp; /* Not used. */
102 int level; /* Current level */
103 char *command; /* Command before substitution */
104 Tcl_CmdProc *proc; /* Not used. */
105 ClientData cmdClientData; /* Not used. */
107 char **argv; /* Command after parsing, but before
110 static unsigned char traceStack[200];
113 Tcl_Channel errChannel;
120 /* This is pretty crappy, but there's no way to trigger stack pops */
121 for (i = level + 1; i < 200; i++) {
124 if (Blt_ChainGetLength(&watchChain) > 0) {
127 Blt_ChainLink *linkPtr;
130 for (linkPtr = Blt_ChainFirstLink(&watchChain); linkPtr != NULL;
131 linkPtr = Blt_ChainNextLink(linkPtr)) {
132 infoPtr = Blt_ChainGetValue(linkPtr);
133 if (Tcl_StringMatch(argv[0], infoPtr->name)) {
138 if ((found) && (level < 200)) {
139 traceStack[level] = 1;
140 traceStack[level + 1] = 1;
142 if ((level >= 200) || (!traceStack[level])) {
147 * Use stderr channel, for compatibility with systems that don't have a
148 * tty (like WIN32). In reality, it doesn't make a difference since
149 * Tk's Win32 console can't handle large streams of data anyways.
151 errChannel = Tcl_GetStdChannel(TCL_STDERR);
152 if (errChannel == NULL) {
153 Tcl_AppendResult(interp, "can't get stderr channel", (char *)NULL);
154 Tcl_BackgroundError(interp);
157 Tcl_DStringInit(&dString);
159 sprintf(prompt, "%-2d-> ", level);
161 /* Skip leading spaces in command line. */
162 while(isspace(UCHAR(*p))) {
167 for (/* empty */; *p != '\0'; /* empty */) {
170 Tcl_DStringAppend(&dString, " ", -1);
172 Tcl_DStringAppend(&dString, prompt, -1);
174 Tcl_DStringAppend(&dString, lineStart, p - lineStart);
175 Tcl_DStringAppend(&dString, "\n", -1);
186 while (isspace(UCHAR(*lineStart))) {
191 Tcl_DStringAppend(&dString, " ", -1);
193 Tcl_DStringAppend(&dString, prompt, -1);
195 Tcl_DStringAppend(&dString, lineStart, p - lineStart);
197 Tcl_DStringAppend(&dString, "\n", -1);
201 Tcl_DStringAppend(&dString, " ...\n", -1);
203 string = Tcl_Merge(argc, argv);
205 sprintf(prompt, " <- ");
207 for (p = string; *p != '\0'; /* empty */) {
210 Tcl_DStringAppend(&dString, " ", -1);
212 Tcl_DStringAppend(&dString, prompt, -1);
215 Tcl_DStringAppend(&dString, lineStart, p - lineStart);
216 Tcl_DStringAppend(&dString, "\n", -1);
228 Tcl_DStringAppend(&dString, " ", -1);
230 Tcl_DStringAppend(&dString, prompt, -1);
232 Tcl_DStringAppend(&dString, lineStart, p - lineStart);
234 Tcl_DStringAppend(&dString, "\n", -1);
238 Tcl_DStringAppend(&dString, " ...\n", -1);
240 Tcl_DStringAppend(&dString, "\n", -1);
242 Tcl_Write(errChannel, (char *)Tcl_DStringValue(&dString), -1);
243 Tcl_Flush(errChannel);
244 Tcl_DStringFree(&dString);
249 DebugCmd(clientData, interp, argc, argv)
250 ClientData clientData; /* Not used. */
255 static Tcl_Trace token;
261 Blt_ChainLink *linkPtr;
265 Tcl_SetResult(interp, Blt_Itoa(level), TCL_VOLATILE);
269 length = strlen(argv[1]);
270 if ((c == 'w') && (strncmp(argv[1], "watch", length) == 0)) {
271 /* Add patterns of command names to watch to the chain */
272 for (i = 2; i < argc; i++) {
275 } else if ((c == 'i') && (strncmp(argv[1], "ignore", length) == 0)) {
276 for (i = 2; i < argc; i++) {
277 DeleteWatch(argv[i]);
282 /* Return the current watch patterns */
283 for (linkPtr = Blt_ChainFirstLink(&watchChain); linkPtr != NULL;
284 linkPtr = Blt_ChainNextLink(linkPtr)) {
285 infoPtr = Blt_ChainGetValue(linkPtr);
286 Tcl_AppendElement(interp, infoPtr->name);
291 if (Tcl_GetBoolean(interp, argv[1], &newLevel) == TCL_OK) {
293 newLevel = 10000; /* Max out the level */
295 } else if (Tcl_GetInt(interp, argv[1], &newLevel) == TCL_OK) {
303 Tcl_DeleteTrace(interp, token);
306 token = Tcl_CreateTrace(interp, newLevel, DebugProc, (ClientData)0);
309 Tcl_SetResult(interp, Blt_Itoa(level), TCL_VOLATILE);
314 Blt_DebugInit(interp)
317 static Blt_CmdSpec cmdSpec =
318 {"bltdebug", DebugCmd,};
320 Blt_ChainInit(&watchChain);
321 if (Blt_InitCmd(interp, "blt", &cmdSpec) == NULL) {
327 #endif /* NO_BLTDEBUG */