1 /* nl-debug.c --- debugging functions for newLISP
3 Copyright (C) 2008 Lutz Mueller
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #define fgets win32_fgets
28 extern FILE * IOchannel
;
29 extern int evalSilent
;
31 int matchString(char * buffer
, char * string
, int * length
);
32 int stringComp(char * buffer
, char * string
);
33 int printFunction(CELL
* cell
);
34 void getDebuggerInput(char * msg
);
35 void allocateDebugStack(void);
37 extern SYMBOL
* currentFunc
;
38 extern SYMBOL
* timerEvent
;
39 extern SYMBOL
* symHandler
[];
40 extern int currentSignal
;
43 int debugStackIdx
= 0;
47 char postStr
[8] = "#";
48 char headerStr
[16] = "\n-----\n\n";
49 char footerStr
[32] = " s|tep n|ext c|ont q|uit > ";
51 #define pushDebugStack(A) (*(debugStack + debugStackIdx++) = (UINT)(A))
52 #define popDebugStack() (*(debugStack + --debugStackIdx))
54 #define DEBUG_ENTRY "->"
55 #define DEBUG_EXIT "<-"
62 currentFunc
= nilSymbol
;
69 /* printf("closing trace\n"); */
71 if(debugStack
) free(debugStack
);
77 CELL
* p_debug(CELL
* params
)
82 result
= copyCell(evaluateExpression(params
));
89 CELL
* p_trace(CELL
* params
)
99 return((traceFlag
== 0 ? nilCell
: trueCell
));
102 CELL
* p_traceHighlight(CELL
* params
)
104 char * pre
, * post
, * header
, * footer
;
106 params
= getString(params
, &pre
);
107 params
= getString(params
, &post
);
109 strncpy(preStr
, pre
, 7);
110 strncpy(postStr
, post
, 7);
112 if(params
!= nilCell
)
114 params
= getString(params
, &header
);
115 strncpy(headerStr
, header
, 15);
118 if(params
!= nilCell
)
120 getString(params
, &footer
);
121 strncpy(footerStr
, footer
, 31);
129 void traceEntry(CELL
* cell
, CELL
* pCell
, CELL
* args
)
131 int defaultFuncFlag
= FALSE
;
133 if(traceFlag
& (TRACE_IN_ENTRY
| TRACE_IN_EXIT
| TRACE_DEBUG_NEXT
)) return;
134 traceFlag
|= TRACE_IN_ENTRY
;
136 if(traceFlag
& TRACE_SIGNAL
)
138 traceFlag
&= ~TRACE_SIGNAL
;
139 executeSymbol(symHandler
[currentSignal
- 1], stuffInteger(currentSignal
));
140 traceFlag
&= ~TRACE_IN_ENTRY
;
144 if(traceFlag
& TRACE_SIGINT
)
146 traceFlag
&= ~TRACE_SIGINT
;
147 longjmp(errorJump
, ERR_USER_RESET
);
150 if(traceFlag
& TRACE_TIMER
)
152 traceFlag
&= ~TRACE_TIMER
;
153 executeSymbol(timerEvent
, NULL
);
154 traceFlag
&= ~TRACE_IN_ENTRY
;
158 if(debugStackIdx
> 1)
160 if(printFunction(cell
))
161 getDebuggerInput(DEBUG_ENTRY
);
162 if(!traceFlag
) return;
165 if(traceFlag
& TRACE_DEBUG_NEXT
)
167 traceFlag
&= ~TRACE_IN_ENTRY
;
171 if(pCell
->type
== CELL_CONTEXT
)
173 defaultFuncFlag
= TRUE
;
174 currentFunc
= translateCreateSymbol(
175 ((SYMBOL
*)pCell
->contents
)->name
,
177 (SYMBOL
*)pCell
->contents
,
180 pCell
= (CELL
*)currentFunc
->contents
;
183 if((pCell
->type
== CELL_LAMBDA
|| pCell
->type
== CELL_MACRO
)
184 && args
->type
== CELL_SYMBOL
)
186 if(debugStackIdx
== 0) /* startup */
187 traceFlag
&= ~TRACE_DEBUG_NEXT
;
190 currentFunc
= (SYMBOL
*)args
->contents
;
191 pushDebugStack(recursionCount
);
192 pushDebugStack(currentFunc
);
195 traceFlag
&= ~TRACE_IN_ENTRY
;
199 void traceExit(CELL
* result
, CELL
* cell
, CELL
* pCell
, CELL
* args
)
201 if(traceFlag
& (TRACE_IN_ENTRY
| TRACE_IN_EXIT
| TRACE_SIGNAL
| TRACE_SIGINT
| TRACE_TIMER
)) return;
202 traceFlag
|= TRACE_IN_EXIT
;
204 if(traceFlag
& TRACE_DEBUG_NEXT
)
206 if(currentLevel
>= recursionCount
)
207 traceFlag
&= ~TRACE_DEBUG_NEXT
;
210 traceFlag
&= ~TRACE_IN_EXIT
;
215 if( (pCell
->type
== CELL_LAMBDA
|| pCell
->type
== CELL_MACRO
)
216 && args
->type
== CELL_SYMBOL
)
218 if((UINT
)recursionCount
== *(debugStack
+ debugStackIdx
- 2) )
221 if(debugStackIdx
> 0)
222 currentFunc
= (SYMBOL
*)*(debugStack
+ debugStackIdx
- 1);
223 if(debugStackIdx
== 0)
224 traceFlag
&= ~TRACE_DEBUG_NEXT
;
228 if(printFunction(cell
))
230 varPrintf(OUT_CONSOLE
, "\nRESULT: ");
231 printCell(result
, TRUE
, OUT_CONSOLE
);
232 varPrintf(OUT_CONSOLE
, "\n");
234 if(debugStackIdx
> 0)
236 getDebuggerInput(DEBUG_EXIT
);
237 if(!traceFlag
) return;
241 if(traceFlag
& TRACE_DEBUG_NEXT
)
242 currentLevel
= recursionCount
;
244 traceFlag
&= ~TRACE_IN_EXIT
;
248 void getDebuggerInput(char * msg
)
250 char command
[MAX_LINE
];
252 jmp_buf errorJumpSave
;
253 int resultStackIdxSave
;
254 SYMBOL
* contextSave
;
259 if(currentContext
!= mainContext
)
260 context
= currentContext
->name
;
265 varPrintf(OUT_CONSOLE
, "\n[%s %d %s]%s", msg
, recursionCount
, context
, footerStr
);
266 else evalSilent
= FALSE
;
268 fgets(command
, MAX_LINE
- 1, IOchannel
);
270 if( (strcmp(command
, "n\n") == 0) || (strcmp(command
, "n\r\n") == 0))
272 traceFlag
|= TRACE_DEBUG_NEXT
;
273 currentLevel
= recursionCount
;
276 else if( (strcmp(command
, "s\n") == 0) || (strcmp(command
, "s\r\n") == 0))
278 traceFlag
&= ~TRACE_DEBUG_NEXT
;
281 else if( (strcmp(command
, "q\n") == 0) || (strcmp(command
, "q\r\n") == 0))
284 longjmp(errorJump
, ERR_USER_RESET
);
286 else if( (strcmp(command
, "c\n") == 0) || (strcmp(command
, "c\r\n") == 0))
292 resultStackIdxSave
= resultStackIdx
;
293 memcpy(errorJumpSave
, errorJump
, sizeof(jmp_buf));
294 contextSave
= currentContext
;
295 currentContext
= currentFunc
->context
;
296 if(setjmp(errorJump
))
298 cleanupResults(resultStackIdxSave
);
302 executeCommandLine(command
, OUT_CONSOLE
, NULL
);
305 currentContext
= contextSave
;
306 memcpy(errorJump
, errorJumpSave
, sizeof(jmp_buf));
311 int printFunction(CELL
* cell
)
318 if(currentFunc
== nilSymbol
) return FALSE
;
320 openStrStream(&strStream
, MAX_STRING
, 0);
321 printSymbol(currentFunc
, (UINT
)&strStream
);
322 length
= strlen(strStream
.buffer
);
323 funcStr
= allocMemory(length
+ 1);
324 memcpy(funcStr
, strStream
.buffer
, length
+ 1);
325 *(funcStr
+ length
) = 0;
327 openStrStream(&strStream
, MAX_STRING
, 0);
328 printCell((CELL
*)cell
, TRUE
, (UINT
)&strStream
);
329 expStr
= strStream
.buffer
;
330 start
= matchString(funcStr
, expStr
, &length
);
331 closeStrStream(&strStream
);
333 if(start
== -1 || length
== 0)
339 varPrintf(OUT_CONSOLE
, headerStr
);
341 expStr
= allocMemory(length
+ 1);
342 strncpy(expStr
, funcStr
+ start
, length
);
343 *(expStr
+ length
) = 0;
344 *(funcStr
+ start
) = 0;
346 varPrintf(OUT_CONSOLE
, "%s%s%s%s%s",
347 funcStr
, preStr
, expStr
, postStr
, funcStr
+ start
+ length
);
355 void allocateDebugStack(void)
357 debugStack
= (UINT
*)allocMemory(MAX_CPU_STACK
* 2 * sizeof(UINT
));
360 /* search for a string skipping white space
362 int matchString(char * buffer
, char * string
, int * length
)
366 /* strip leading white space */
367 while(*string
<= ' ' && *string
> 0) string
++;
374 if((*length
= stringComp(buffer
, string
)) > 0)
383 if(!flag
) return(-1);
388 /* compare strings skipping white space
390 int stringComp(char * buffer
, char * string
)
395 while(*string
&& *buffer
)
401 if(*string
!= *buffer
) return(0);
411 return(buffer
- start
);