-
Notifications
You must be signed in to change notification settings - Fork 2
/
TRACER.4TH
319 lines (268 loc) · 10 KB
/
TRACER.4TH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
// Simple program tracing tool Version 1.75
// !!!! NOTE !!!!
// There is one thing you must remember that if you define code words
// with CPU80486, you must turn off tracer ( TRACER OFF ) before you
// start 'CODE:'ing otherwise this might turn out to crash your system.
// !!!! NOTE !!!!
// Also notice that words that influence return stack cannot be traced.
// So if your program use >R , R> ... etc. This tracer might not work.
//
// Written by : Luke Lee on 1/2/'95 for SEE.4TH
// updates : for including in HI.4TH, only EXIT modified.
// update : modify DOES>. after DOES> there can be no
// PUT<trace_out> on ';' .
// update : implement PUT<tracein_does> for tracing codes
// between 'DOES>' and ';' 08/31,09/01
// update : Modify #.S to ensure that 0..1024 cells displayed.
// Also some UnderFlow? added . 02/27/'96
// update : Fix a bug while SHOWTRACE is OFF, modify ShowTracingInto
// and ShowTracingOutof. 02/28/'96
// update : Modify for multitasking, prevent task switching while
// 'ShowTracingInto' and 'ShowTracingOutOf' . 03/12/'96
// update : Remove BKSPC, this will looks better in LOG files
// generated by LOG.4TH . 01/22/'97
// update : Add TRACE{ .. }TRACE and TRACING{ ... }TRACING blocks
// 01/27/'97 v1.75
// Last update : Add SHOWTRACE{ ... }SHOWTRACE blocks. 01/31/'97 v1.75
// Available control flags :
//
// TRACER : If it is ON, extra checking words ( which means <trace_in>
// and <trace_out> ) will be insert into code definitions .
// Only when this flag is ON, the tracer would work.
//
// TRACING : If it is ON, all the following actions could be possible
// since <trace_in> and <trace_out> works only when it is ON.
//
// DEPTHCHK : Check the number of input/output parameter and see if
// it is consistent with the specified #PARMS.
//
// SHOWTRACE : Display the execution sequence of each call in/out.
// Any keyin will pause the displaying; press CTRL-C again
// will terminate tracing.
//
// SHOWFRAME : If it is ON, it will display the stack frame specified
// by #PARMS instead of .S which display DEPTH elements on
// stack . But it works only when SHOWTRACE is ON.
//
// UNSIGNED : If this flag is ON, all the stack items will be displayed
// as unsigned integer. Default value is OFF.
//
// * If some execution abortion cause tracer's improper operation, use
// TRACER/RESET to reset it.
//
// * Use TRACER/STATUS to display current flags setting.
//
// * During tracing, press any key will suspend tracing, press again
// will resume execution; press CTRL-Q will break tracing.
//
ONLY FORTH ALSO DEFINITIONS
VARIABLE TRACER
VARIABLE TRACING
VARIABLE DEPTHCHK // stack depth checker
VARIABLE SHOWTRACE // TRUE : show calling sequence.
VARIABLE SHOWFRAME // TRUE : show current IN/OUT only otherwise .S
VARIABLE UNSIGNED // TRUE : show current stack with unsigned value.
// Default settings :
TRACER OFF
TRACING OFF
DEPTHCHK ON
SHOWTRACE ON
SHOWFRAME ON
UNSIGNED OFF
: OPTIMIZE? OPTIMIZE @ ; 0 1 #PARMS
: .ON/OFF (( T/F -- ))
IF ." ON" ELSE ." OFF" ENDIF ; 1 0 #PARMS
: TRACER/STATUS (( -- ))
CR ." TRACER " TRACER @ .ON/OFF TAB
." TRACING " TRACING @ .ON/OFF TAB
." DEPTHCHK " DEPTHCHK @ .ON/OFF TAB
CR ." SHOWTRACE " SHOWTRACE @ .ON/OFF TAB
." SHOWFRAME " SHOWFRAME @ .ON/OFF TAB
." UNSIGNED " UNSIGNED @ .ON/OFF CR ; 0 0 #PARMS
: #.S (( idepth -- ))
DEPTH 1- // ignore the input parameter 'idepth' 05/05/'95
MIN 0 MAX 1024 MIN
FOR AFT
R@ PICK
UNSIGNED @ IF U.H ELSE .H ENDIF
THEN NEXT ; 1 0 #PARMS
HIDDEN ALSO DEFINITIONS
VARIABLE nesting // nesting level while tracing
FORTH DEFINITIONS
: TRACER/RESET
TRACER OFF TRACING OFF DEPTHCHK ON SHOWTRACE ON SHOWFRAME ON
UNSIGNED OFF nesting OFF ; 0 0 #PARMS
HIDDEN DEFINITIONS
: UnderFlow? (( -- ))
DEPTH 0< IF
MULTI? >R SINGLE
nesting OFF CR ." * Stack underflow while tracing ." CR
R> IF MULTI ENDIF ABORT
ENDIF ; 0 0 #PARMS
: CTRLQ? (( ha -- )) // Break tracing for CTRL-Q, suspend for any other key.
?KEY IF
DROP KEY [ CTRL Q ] LITERAL = IF
MULTI? >R SINGLE
nesting OFF CR ." * User break while tracing " .ID ." . ok" CR
R> IF MULTI ENDIF ABORT
ENDIF
ENDIF DROP ; 1 0 #PARMS
: tabs nesting @ FOR AFT SPACE SPACE THEN NEXT ; 0 0 #PARMS
: SHOWSTACK (( depth -- ))
DEPTH
SHOWFRAME @ IF MIN ELSE NIP ENDIF
#.S ; 1 0 #PARMS
: ShowTracingInto (( ha -- ))
MULTI? >R SINGLE
>R SHOWTRACE @ IF
tabs ." <Enter " R@ .ID SPACE
R@ |IN-PARMS C@ SHOWSTACK
[ CHAR > ] LITERAL EMIT CR
1 nesting +!
R@ CTRLQ?
ENDIF RDROP
R> IF MULTI ENDIF ; 1 0 #PARMS
: <trace_in> (( -- )) // TRACING OFF
(( -- )R: ret -- ha ret ) // DEPTHCHK OFF
(( -- )R: ret -- depthI ha ret ) // DEPTHCHK ON
TRACING @ IF
R@ BODY> >HEAD >R // R: ret ha
R@ ShowTracingInto
DEPTHCHK @ IF (( R: ret ha ))
UnderFlow?
DEPTH // while <trace_in>'s data stack frame is empty !
R> R> (( depthI ha ret ))
ROT >R SWAP >R >R (( R: depthI ha ret ))
ELSE
R> R> SWAP >R >R (( R: ha ret ))
ENDIF
ENDIF ; 0 0 #PARMS
: <tracein_does> (( PFA -- PFA ))
(( PFA -- PFA )R: -- ha ret )
(( PFA -- PFA )R: -- dpethI ha ret )
TRACING @ IF
>R R@ BODY> >HEAD >R // R: ret PFA ha
R@ ShowTracingInto
DEPTHCHK @ IF (( R: ret PFA ha ))
UnderFlow?
DEPTH // while <trace_in>'s data stack frame is empty !
R> R> -ROT R> (( PFA depthI ha ret ))
ROT >R (( PFA ha ret )R: depthI )
ELSE
R> R> SWAP (( PFA ha )R: ret )
R> (( PFA ha ret ))
ENDIF
SWAP >R >R // PFA R: (depthI) ha ret
ENDIF ; 1 1 #PARMS
: DepthCheck (( depth_I depth_O ha -- ))
>R - // in-out ;R: ha
R@ |IN-PARMS C@ R@ |OUT-PARMS C@ // in-out .in .out ;R: ha
OVER $FF <> OVER $FF <> AND IF
- - ?DUP
IF // (in-out)-(.in-.out) = (.out-.in)-(out-in)
R> MULTI? >R >R
CR ." * Stack depth checking failure after calling " R@ .ID ." :"
CR ." " DUP 0> IF . ." less" ELSE NEGATE . ." more" ENDIF
." elements left on stack." CR
nesting OFF RDROP R> IF MULTI ENDIF
ABORT
ENDIF
ELSE
3DROP
ENDIF
RDROP ; 3 0 #PARMS
: ShowTracingOutof (( ha -- ))
MULTI? >R SINGLE
>R SHOWTRACE @ IF
-1 nesting +!
tabs ." <Leave " R@ .ID SPACE
R@ |OUT-PARMS C@ SHOWSTACK
[ CHAR > ] LITERAL EMIT CR
R@ CTRLQ?
ENDIF RDROP
R> IF MULTI ENDIF ; 1 0 #PARMS
: <trace_out> (( -- ))
(( -- )R: ha ret -- )
(( -- )R: depthI ha ret -- )
TRACING @ IF
R> R> SWAP >R >R // R: (depthI) ret ha
R@ ShowTracingOutof
DEPTHCHK @ IF (( )R: depthI ret ha )
UnderFlow?
DEPTH // while <trace_out>'s data stack frame is empty !
R> R> R> (( depthO ha ret depthI ))
SWAP >R (( depthO ha depthI )R: ret )
-ROT DepthCheck
ELSE (( )R: ret ha )
RDROP
ENDIF
ENDIF ; 0 0 #PARMS
VARIABLE OLD-OPTIMIZE
2VARIABLE TRACER-RESETTER
: TRACER/LEAVE (( -- )) // accenditally abort during compiliation
OLD-OPTIMIZE @ OPTIMIZE !
TRACER-RESETTER POP-RESETTER ; 0 0 #PARMS
: PUT<trace_in> (( -- ))
TRACER @ IF
OPTIMIZE? OLD-OPTIMIZE ! OPTIMIZE OFF
['] TRACER/LEAVE TRACER-RESETTER PUSH-RESETTER
COMPILE <trace_in>
ENDIF ; 0 0 #PARMS
: PUT<trace_out> (( -- ))
TRACER @ IF COMPILE <trace_out> ENDIF ; 0 0 #PARMS
: PUT<tracein_does> (( -- ))
TRACER @ IF COMPILE <tracein_does> ENDIF ; 0 0 #PARMS
FORTH DEFINITIONS
DEFER }TRACE IMMEDIATE 0 0 #PARMS
: }TRACING \ ENDIF ; IMMEDIATE COMPILEONLY
: }SHOWTRACE \ ENDIF ; IMMEDIATE COMPILEONLY
HIDDEN DEFINITIONS
VARIABLE TRACE$EVAL
2VARIABLE TRACE{_RESETTER
: TRACE{_RESET ( -- )
TRACE$EVAL @ DUP IF 'EVAL ! ELSE DROP ENDIF
TRACE$EVAL OFF
TRACE{_RESETTER POP-RESETTER ; 0 0 #PARMS
: NO}TRACE CR ." * Cannot use }TRACE without TRACE{ " CR ABORT ; NOPARM
: END}TRACE ['] NO}TRACE IS }TRACE TRACE{_RESET ; NOPARM
: ?CAN'T_NESTING_TRACE{ ( T/F -- )
IF CR ." * Cannot define nesting TRACE{ block." CR ABORT
ENDIF ; 1 0 #PARMS
: WAIT"}TRACE" ( $a -- )
$" TRACE{" OVER $= IF TRACE{_RESET TRUE ?CAN'T_NESTING_TRACE{ ENDIF
['] }TRACE >NAME $= IF TRACE{_RESET ENDIF ; 1 0 #PARMS
: TRACING@ ( -- T/F ) TRACING @ ; 0 1 #PARMS
: SHOWTRACE@ ( -- T/F ) SHOWTRACE @ ; 0 1 #PARMS
FORTH DEFINITIONS
: TRACING{ ( -- )
COMPILE TRACING@ \ IF ; COMPILEONLY IMMEDIATE
: SHOWTRACE{ ( -- ) // 01/31/'97
COMPILE SHOWTRACE@ \ IF ; COMPILEONLY IMMEDIATE
: TRACE{ ( -- ) // NO NESTING TRACE{ .. TRACE{ is allowed // 01/27/'97
['] END}TRACE DEFERRED }TRACE = ?CAN'T_NESTING_TRACE{
['] END}TRACE IS }TRACE
TRACER @ NOT IF
TRACE$EVAL @ ?CAN'T_NESTING_TRACE{
'EVAL @ TRACE$EVAL !
['] WAIT"}TRACE" 'EVAL !
['] TRACE{_RESET TRACE{_RESETTER PUSH-RESETTER
ENDIF ; COMPILEONLY IMMEDIATE 0 0 #PARMS
: : (( <name> -- ))
: PUT<trace_in> ['] NO}TRACE IS }TRACE
; 0 0 #PARMS
: BACKGROUND: (( <name> -- ))
BACKGROUND: PUT<trace_in> ; 0 0 #PARMS
: DOES> (( -- ))
PUT<trace_out>
\ DOES>
PUT<tracein_does> ; IMMEDIATE COMPILEONLY 0 0 #PARMS
: EXIT (( -- ))
PUT<trace_out>
\ EXIT ; IMMEDIATE 0 0 #PARMS
: ; (( -- ))
PUT<trace_out> \ ;
TRACER @ IF TRACER/LEAVE ENDIF ; IMMEDIATE COMPILEONLY 0 0 #PARMS
: MACRO (( -- )) // NO MACRO while tracing
TRACER @ NOT IF MACRO ENDIF ; 0 0 #PARMS
ONLY FORTH ALSO DEFINITIONS