Trailing-Edge - PDP-10 Archives - mit_emacs_170_teco_1220 - emacs/tdebug.emacs
There are no other files named tdebug.emacs in the archive.

!~FILENAME~:! !Teco debugging functions!
!& File TDEBUG Loaded:! !S This is just used to detect if TDEBUG is loaded.!
!& Setup TDEBUG Library:! !S Setup variables for debugging
Setup variables and buffers for debugging break points
No argument will split the screen in half, positive argument
splits the screen at that line. Also will call TDEBUG Setup Hook
after standard initialize. It also puts Stepped Minibuffer on C-M-Altmode
Clobbers backtrace to be a breakpoint!
!* Set up the window variables!
				    !* Calculate the break line for window!
   FF"N ' "# Q0-1/2' M.V Tdebug_Window_1_Size
   Q0-QTdebug_Window_1_Size M.V Tdebug_Window_2_Size
				    !* Calculate the window sizes!
   @:I*| W 0 F[ STEP MACRO .M| U.M
				    !* Make sure M.M is not stepped!
   @:I*| W 0 F[ STEP MACRO .V| U.V
				    !* Make sure M.V is not stepped!
   @:I*| W 0 F[ STEP MACRO ..P| U..P
				    !* Make sure error handler is not stepped!
   @:I*| W M | UM		    !* Make sure MM is not stepped! 

   0 M.V Tdebug_Proceed_Count	    !* Create some variables!
   0 M.V Tdebug_Break_PC
   0 M.V Tdebug_Backtrace_Level
   0 M.V Tdebug_Arg
   0 M.V Tdebugged_Buffer
   0 M.V Tdebug_Ref_Count	    !* Signals we are inside the debugger!
   0 M.V Tdebug_Saved_FS_LINES
   0 M.V Tdebug_Silent		    !* Says we shouldn't redisplay user buffer!
   0 M.V Tdebug_Function_Base	    !* The function level we entered debugger at!
   0 M.V Tdebug_Q_Base		    !* Same for Q registers!
   0 M.V Tdebug_Q_Top		    !* The top of the Q register pdl!
				    !* when we entered a break point!
   0 M.V Tdebug_Whole_Stack	    !* Set when we view the whole stack!
   0 M.V Tdebug_Function_Frame	    !* Set if function frame available!
   1 M.V Tdebug_Verbose	    !* Verbose Q register printer!
   0 M.V Tdebug_Info_Line	    !* The saved info line!
   :I* M.V Tdebug_Prev_Command    !* The previous stepped expr!
   m.m Backtrace m.v Old_Backtrace	    !* for killing library!
   M.M &_Tdebug_Error_Break M.V MM_Backtrace
				    !* Define this for debugging backtrace!

   Q0 M.V Tdebug_Break_Table	    !* The breakpoint table!
   3 U:0(0)			    !* Set the length of an entry to 3!

   FS BCONS M.V Tdebugger_Previous_Display
   FS BCONS M.V Tdebugger_Function_Display

   M(M.M &_Tdebug_Qprint_Setup)    !* Setup printer!
   M.M &_Tdebug_Minibuffer U... !* Setup stepper function!

   M(0 FO..Q TDEBUG_Setup_Hook F"E W @:I*// ')
!& Kill TDEBUG Library:! !S Undo & Setup TDEBUG Library.!
!Debug Mode:! !C Calls the debugger using the minibuffer
Reads and executes teco commands.
Uses the Minibuffer to read the commands. Pushes the command string
onto a ring buffer in Q.N.  An explicit argument initializes
the minibuffer with the command from the top of that ring buffer.
Once inside the minibuffer, C-M-Y pops to previous saved
minibuffer commands, going around the ring.!

   F:M(M.M &_Tdebug_Minibuffer)
!Break:! !C Put breakpoint at front of specified function.
String argument is the name of the function to breakpoint.
We add a call to & Tdebug break point onto the front of the function
Numeric arg inhibits Tdebug Break Hook from being run.!

   :I* [0			    !* Get the string argument!
   M.M 0 [1		    !* Get pointer to the function!
   Q1 M(M.M &_Macro_Name) U0	    !* Get the full name of the function!
   QTdebug_Break_Table[3	    !* Get pointer to the breakpoint table!
   :FO3 0 [2		    !* Is negative if not found, or index!
   Q2 "L Q3 [..Q		    !* Fake out M.V with new symbol table!
         M.V 0		    !* Create the variable!
	 ]..Q			    !* Back to main variables!
	 :FO3 0 U2'	    !* Put index in 2!
      "# Q1 - Q:3(Q2+2) "E ''	    !* If same as breakpointed form, return!
   Q1 M.V MM_ 0		    !* Cons up MM variable!
   Q1 U:3(Q2+1)'		    !* Put the old string in slot 1!
   :@I*/ MM &_Tdebug_Breakpoint
1/  F( UMM_0 ) U:3(Q2+2)  !* Put newly consed function in variable and slot 2!
    "E M(0 FO..Q Tdebug_Break_Hook F"E W @:I*// ')'
   				    !* Return!
!Unbreak:! !C Remove breakpoint from front of specified function.
String argument is the name of the function to unbreakpoint.
If the function has been changed for any reason, it will print
out a message, and refuse to change it.  Numeric arg inhibits
Tdebug Break Hook from being run.!

   :I* [0			    !* Get the string argument!
   FQ 0 "E :M(M.M &_Tdebug_Remove_Breakpoints) ' !* Remove all berak points!
   M.M 0 [1		    !* Get pointer to the function!
   Q1 M(M.M &_Macro_Name) U0	    !* Get the full name of the function!
   QTdebug_Break_Table[3	    !* Get pointer to the breakpoint table!
   :FO3 0 [2		    !* Is negative if not found, or index!
   Q2 "L :I*MNB	Function_Not_Breakpointed FS ERR'
   QMM_ 0  - Q:3(Q2+2)"N	    !* If the break point function is not the same!
      :I*MHC	Function_Has_Changed FS ERR'
   Q:3(Q2+1) UMM_ 0 	    !* Put back original function!
   Q3[..O			    !* Select the q vector!
   Q2*5J 15D ]..O		    !* Kill the entries for this function name!
    "E M(0 FO..Q Tdebug_Break_Hook F"E W @:I*// ')'
!Insert Breakpoint:! !C Insert a breakpoint command before current line.
Use this while editing the source code for a function.
TCompile the function, and it will contain a breakpoint.!

    0l 13i 10i -2c
!Kill Breakpoints:! !C Removes breakpoints in function being edited.
Use this while editing the source code for a function.
TCompile the function, and then all breakpoints inserted with
Insert Breakpoint will be gone.!

    .[1 [2
    M(M.M ^R_Mark_Page)
    .[3 Q3[4

    < @:S|M(M.M_&_Tdebug_Breakpoint)|;
      0L FU2 1K
      Q1-."G Q1-Q2,.FU1'
!& Tdebug Remove Breakpoints:! !S Remove all breakpoints
Numeric arg inhibits Tdebug Break Hook from being run!
   QTdebug_Break_Table[0	    !* Get pointer to the break point table!
   1 [1				    !* Pointer into symbol table!
   [2				    !* Used as name pointer!
   (FQ 0)/15<			    !* 15 characters / entry!
   Q:0(Q1) U2			    !* Get name from table!
   QMM_ 2 - Q:0(Q1+2) "E
      Q:0(Q1+1) UMM_ 2 '	    !* Reset the variable to point to original function!
   Q1+3 U1>			    !* Step to next place!
   Q0 [..O 5J ZK 		    !* Kill whole table but length!
    "E M(0 FO..Q Tdebug_Break_Hook F"E W @:I*// ')'
!List Breakpoints:! !C List all currently breakpointed functions!

   :FT ---Breakpoints---

   QTdebug_Break_Table[0	    !* pointer to the breakpoint table!
   1 [1
   (FQ 0)/15<
   Q:0(Q1) U2			    !* Get name pointer!
   FT 2 
				    !* Type the names!
   Q1+3 U1 >			    !* Next function!
!& Tdebug Breakpoint:! !S The Breakpoint Function
Enters a breakpoint from the users function.
To use, insert a MM& Tdebug Breakpoint into the code!

   M(M.M &_Tdebug_Enter)
				    !* Enter the break point handler!
!& Tdebug Error Break:! !S This is entered when an error happens
Enters a breakpoint from the error handler!

   M(M.M &_Tdebug_Enter)
   D FS REREAD		    !* Error was one level down!
				    !* Enter the break point handler!
!& Tdebug Step:! !S TDEBUG single-step handler and command loop.
Negative argument means break unconditionally.
In command loop, ? lists help info.!

   W 0 F[ STEP MACRO		    !* Turn off stepping temporarily!

   FQ(-FS BACK STRING)"L '	    !* Exit if teco internal code!

!* Decide to break or not!
   "L'			    !* If the argument is negative break!
     "# FS STEP DEPTH "L	    !* If we are not checking PC!
           %Tdebug_Proceed_Count"L ''    !* Then exit if count is < 0!
				    !* If we have gone up a level, break anyway!
				    !* Otherwise check the PC and count!
	     -FS BACK PC-QTdebug_Break_PC-1"L '
				    !* If we haven't passed the point, return!
	     %Tdebug_Proceed_Count"L ' '''
				    !* If the count hasn't expired, return!
!* Now actually break!
   Q..O UTdebugged_Buffer	    !* This is the debugged buffer!
   QTdebugger_Function_Display[..O   !* Go to the debugging buffer!
   FS QP PTR-2 UTdebug_Q_Top	    !* This was the QPDL point when we entered!

   F[S STRING F[ INSLEN	    !* Bind some things the debugged function uses.!
   QTdebug_Silent "E
      QTdebugged_Buffer [..O @V ]..O'
				    !* Maybe redisplay the top buffer!
   @FN | 1M(M.M &_Tdebug_Select_Window) |   !* On exit, select function window!
   2M(M.M &_Tdebug_Select_Window)  !* Change back to debugger buffer!
   FS BACK DEPTH-1 UTdebug_Backtrace_Level	    !* The caller is one level down!

!Newframe!			    !* Return here for a new function frame!
   M(M.M&_Tdebug_New_Frame)	    !* Get a new frame!
   M(M.M&_Tdebug_Display_Frame)    !* Redisplay if needed!

!Iread!				    !* Here to init arg before reading!


!Read!				    !* Get and dispatch on cmd char!
   M.M &_Tdebug_Help F[ HELP MAC  !* So that he gets doc on help key!
   < . @V			    !* Display the function buffer!
     :FI :FC U0			    !* Read char & cvt to upper case!
     @FI @FS ^RCMAC-(33.FS ^R INIT)"E XU0'
				    !* Make ctl-alt look like X!

!* If the char is a digit, update q$Tdebug Arg$ !
     Q0-0+1"G Q0-9-1"L 10*QTdebug_Arg+Q0-0 UTdebug_Arg 0U0''
     Q0-40."E :I*Space U0 0;'	    !* Change spaces to Space!
     Q0"N Q0-40."L Q0#100.U0	    !* represent ctl-A as ^A,!
		   :I0^ 0'
		"# Q0-177."E :I0 ^?'	    !* rubout as ^?,!
			  "# Q0:I0''	    !* other chars as themselves.!
	  0;' >
     F] HELP MAC		    !* Pop off help for now!

!* Execute the code for the char.!
   1,M.M #_TDebug_0 U0	    !* Find the code, return 0 if nonex!
   Q0"E ]0 FG OREAD'		    !* Barf if nonexistent!
   QTdebug_ArgF"E+1' M(Q0(]0))[0   !* call code in Q0, put val in Q0,!
				    !* but don-t have Q0 bound during call.!
!* Dispatch on the return code!
   O Disp_ 0
      !Disp_Newframe! ]0 O Newframe
      !Disp_Iread!    ]0 O Iread

   				    !* Just proceed!

   0,-7 FS QPSLOT		    !* Turn off stepping!

   0,-7 FS QP SLOT		    !* Zero the saved FS STEP MACRO!
   				    !* And exit!
!& Tdebug New Frame:! !S Display a new frame at level Tdebug Backtrace Level
Sets Tdebug Function Frame to 1 if succeeds.!

   0 UTdebug_Function_Frame
   HK [3
   QTdebug_Whole_Stack "N	    !* If we should view the whole stack!
       -1 [0			    !* the level must be greater than this!
       FS BACK DEPTH [1'	    !* the level must be less than this!
     "# QTdebug_Function_Base[0
        FS BACK DEPTH-1 [1'
   < QTdebug_Backtrace_LevelU3
	   0fo..q Tdebug_New_Frame_Hooku0
	   q0"n m0'
	   1 UTdebug_Function_Frame'
       "# :FT Already_at_top_of_stack
	  Q1-1 UTdebug_Backtrace_Level''
     "# :FT Already_at_bottom_of_stack
	Q0+1 UTdebug_Backtrace_Level'
!& Tdebug Display Frame:! !S Display frame level and frame, if required!
	0,0A-15."E 0,1A-12."E C''   !* dont split CR/LF!
	M(M.M &_Tdebug_New_Mode_Line) U0   !* Get the new mode line!
	F= Tdebug_Info_Line 0 "N	    !* If the new mode line is different!
	   Q0 UTdebug_Info_Line
	   M(M.M &_Tdebug_Display_Mode_Line)'
	H F= 0 "E		    !* If this frame is still on the screen,!
		       .@V'	    !* display it! 
		    "# @V	    !* and do new display,!
		       H(Q0[..O HK)G(-FS QP SLOT)]..O'	    !* and remember it!
!& Tdebug New Mode Line:! !S Cons up new mode line for debugger!
        QTdebug_Backtrace_Level U1
	Q1 FS BACK STRING U4	    !* Get the function!
	Q4 M(M.M &_Macro_Name) F"N U4'    !* Either insert name or!
		"# W :I4 **STRING** '	    !* **STRING** for name!
	   QTdebug_Function_Base U3
	   Q1-Q3 U1
	   Q2-Q3 U2'
	Q1 :\ U1
	Q2 :\ U2
	:I3--Function_Level_1 / 2'
     "# :I3'
   QTdebug_Ref_Count:\ U1
   :I* 1 _Tdebug_Breakpoint 3
!& Tdebug Display Mode Line:! !S Displays Tdebugs mode line!

   QTdebug_Info_Line [0		    !* This is the mode line!
   QTDEBUG_Window_1_Size+1 F[ TOP LINE  !* Set the top line!
   2 F[ LINES			    !* two lines for mode line!

   :FT 0  		    !* type mode line and return!
!& Tdebug Select Window:! !S Select windows by numeric arg
1->Window 1; 2->Window 2; 0->Bind to full screen; -1->Unbind full screen!
	0 +  [N   3-[O	    !* New, old!
	FS WINDOW U TDEBUG_Window_o_Window  !* Swap windows!
	QTDEBUG_Window_n_Window FS WINDOW
	-1 F"N W QTDEBUG_Window_1_Size+4' FS TOPLINE
     "# 0 FS TOP LINE QTDEBUG_Window_1_Size FS LINESF+
     F] REFRESH F] LINES F] TOP LINE  !* restore the windows!
     M(FS REFRESH)'		    !* refresh the whole thing!
!& Tdebug Enter:! !S Enter Debugger subroutine.
Sets up the two window mode, and prepares to be in
Debug Break points.!

   @FN | WFW |	    !* On exit, redisplay!

   FS WINDOW M.V TDEBUG_Window_1_Window  !* Make up the windows!
   -1 M.V TDEBUG_Window_2_Window

   F[LINES F[Top Line		    !* Save portion of screen in use.!

   M.M&_Tdebug_Refresh F[REFRESH  !* Two window Refresh!

 UTdebug_Info_Line		    !* New info line is null string two lines long!
   0 UTdebug_Silent		    !* Start out displaying buffer!

   Q..O UTdebugged_Buffer	    !* This is the debugged buffer!
   M.M &_Tdebug_Select_Window [W   !* Get pointer to window selection!
   QTdebugger_Function_Display [..O HK ]..O	    !* Clear the Function buffer!
   1MW				    !* Now, back to window 1!
   M(FS REFRESH)		    !* Refresh the bottom buffer!

   -1 UTdebug_Proceed_Count	    !* Set up variables for Debugging!
   0 UTdebug_Break_PC
   -1 FS STEP DEPTH		    !* Stop as soon as possible!
   0 UTdebug_Function_Base	    !* Unless otherwise specified, whole stack!
   0 UTdebug_Q_Base
   0 UTdebug_Whole_Stack	    !* normally only view part of the stack!

!* Must not use  to exit -- don't pop what we pushed.!
!& Tdebug Minibuffer:! !S Usual Minibuffer, except it is stepped.
Reads and executes teco commands.
Uses the Minibuffer to read the commands. Pushes the command string
onto a ring buffer in Q.N.  An explicit argument initializes
the minibuffer with the command last debugged.
Once inside the minibuffer, C-M-Y pops to previous saved
minibuffer commands, going around the ring.!

   M.M ^R_Pop_Minibuffer_Ring[...Y
				    !* Install C-M-Y!
   Q..O,( F[B BIND		    !* Make new buffer!
        FF"N G(QTdebug_Prev_Command)' !*  and fill with previous command!
				    !* string if appropriate!
	) M(M.M &_Minibuffer)Step_Minibuffer	    !* Read stuff in minibuffer!
   H"E 0 '
   F=(Q:.N(0)F"E W :I*')..O"N   !* If this command not same as previous minibuffer,!
      Q.N[..O ZJ-5D		    !* push this command onto ring buffer of!
      J 5,0I ]..O		    !* minibuffer commands.!
   F]B BIND ]...Y		    !* Restore normal environment!
   M(M.M &_Tdebug_Enter)	    !* Enter the debugger!
   FS QP PTR+1 UTdebug_Q_Base    !* Assume FS STEP MACRO will be pushed!
   FS BACK DEPTH UTdebug_Function_Base   !* This is the function base level!
   Q:.N(0) UTdebug_Prev_Command   !* Save this command for later!

   M.M&_Tdebug_Step F[ STEP MACRO M:.N(0) 
				    !* Step the minibuffer!
!& Tdebug Refresh:! !S Debug refresh subroutine.
Redisplays the users buffer in the top window, and the
debugging buffer in the lower window.!

    0 F[ REFRESH 
    FS TOP LINE"N		    !* here we are in window 2!
       QTDEBUG_Window_1_SizeF[ LINES 0F[ TOP LINE
       QTDEBUG_Window_1_WindowF[ WINDOW
       QTdebug_Silent"E 0U..H @V''
       QTDEBUG_Window_2_SizeF[ LINES QTDEBUG_Window_1_Size+1F[ TOP LINE
       QTDEBUG_Window_2_WindowF[ WINDOW
       0U..H @V'
    FS LISTEN"N -1FS PJATY'	    !* if we stopped redisplay because of typeout, !
				    !* try later!
    4 FS LINES			    !* Now the stars!
    QTDEBUG_Window_1_SizeFS TOP LINE
    :FT FS WIDTH/10<FT---------->
    QTdebug_Info_Line [0		    !* Get mode line!

    FS WIDTH/10,4 F U0 <FT----------> 0U..H 
!# Tdebug A:! !C Print the arguments for the current stack frame!
        10000 [Tdebug_Qprint_Lines
	40 [Tdebug_Qprint_Length
	"# QTdebug_Backtrace_Level FS BACK ARGS F([2 [1) F [3
			!* 1 has the first arg, 2 the second, 3 the flags!
	   Q3"E INo_Arguments

	        :FT HT :I*Iread '	    !* No arguments, just return!
	   M.M &_Tdebug_Insert_Object_Info [0
				    !* Print ^X arg!
	   Q3&2"N Q1 M0' "# I<None>'
				    !* Print ^Y arg!
	   Q3&1"N Q2 M0 ' "# I<None>'
!# Tdebug D:! !# Tdebug ^J:! !C Go Down the stack, to earlier invocations!
	QTdebug_Backtrace_Level- UTdebug_Backtrace_Level
!# Tdebug U:! !# Tdebug ^:! !C Go Up the stack to more recent invocations!
	QTdebug_Backtrace_Level+ UTdebug_Backtrace_Level
!# Tdebug ^R:! !C Call ^R on current function frame!
	0[..F .
!# Tdebug B:! !C Call ^R on buffer!
	1M(M.M &_Tdebug_Select_Window)
	0F[ ^R ENTER :I*[Buffer] [..J
	. ]..J F] ^R ENTER  ]..O
	2M(M.M &_Tdebug_Select_Window)
!# Tdebug ^[:! !C Altmode - Run Minibuffer on The Buffer!
	1M(M.M &_Tdebug_Select_Window)	    !* Select top window!
	QTdebugged_Buffer [..O	    !* and use debugged Buffer!
	M(M.M ^R_Execute_Mini)
	]..O 2M(M.M &_Tdebug_Select_Window) !* Reselect lower window!
!# Tdebug M:! !C Run Minibuffer on the function frame!
	M(M.M ^R_Execute_Mini)
	@V :I*Iread 
!# Tdebug ^L:! !C Clear screen!
!# Tdebug ^N:! !# Tdebug Space:! !C Single proceed to next line!
	- U Tdebug_Proceed_Count
	-FS STEP DEPTH		    !* Break at any level!
!# Tdebug N:! !C Proceed to next line at this level!
	. UTdebug_Break_PC
	- UTdebug_Proceed_Count
	QTdebug_Backtrace_Level FS STEP DEPTH    !* Break at spec level!
!# Tdebug L:! !C Exit <arg> levels (Actually, like <arg>D N)!
	QTdebug_Backtrace_Level -  [0
	Q0"L :I*Exit '	    !* Exiting past bottom!
	Q0 FS STEP DEPTH	    !* Break at spec level!
	Q0 FS BACK PC UTdebug_Break_PC
	-1 UTdebug_Proceed_Count   !* else set break params and exit!
!# Tdebug ^?:! !C Rubout flushes arg!
!# Tdebug \:! !C Select empty buffer/window for editing/patching
Q0,Q1,Q2 are bound to nargs, first, and second arg respectively!
	0[1 0[2			    !* Bind q1,q2 to frame args!
	QTdebug_Backtrace_Level FS BACK ARGS F( F[0
	)F( Q0-1"E )F( U2'
	)F( Q0-2"E )F(0U2 U1'
	)F( Q0-3"E )U2 U1 '"# )W'
	1M(M.M &_Tdebug_Select_Window)	    !* Window 1!
	F[ B BIND		    !* Get empty buffer and edit!
	0F[ ^R ENTER :I*[Hackery_Buffer][..J
	  ]..J F] ^R ENTER F] B BIND
	QTdebug_Silent"E QTdebugged_Buffer[..O @V ]..O'
				    !* Redisplay buffer!
	2M(M.M &_Tdebug_Select_Window)	    !* Reselect window 2!
!# Tdebug X:! !C Exit - like DDTs $P!
!# Tdebug Q:! !C Quit - Abort all functions currently in progress!
!# Tdebug .:! !C Move cursor to other window!
	< 1M(M.M &_Tdebug_Select_Window)
	  QTdebugged_Buffer[..O @V ]..O   !* Display top window!
	  @FI U1		    !* Wait for typed char!
	  2M(M.M &_Tdebug_Select_Window)
	  @V			    !* Display bottom window!
	  Q1-. "N  Q1 FS REREADW 
		     :I*Iread '  !* If the typed ch wasnt . then exit!
	  :FI-. "N :I*Iread '  !* Another . goes back to top window!
	  FI W >
!# Tdebug =:! !C Print numeric arg!
	@FT_   @:=
!# Tdebug S:! !C Print home for QP slot <arg>!
        QTdebug_Q_Top-QTdebug_Q_Base [0
				    !* Argument must be less than this!
	QTdebug_Q_Base+-1 [1'   !* This is the slot number!
        FS QP PTR[0

	I Of_ G0 I_slots:_
	-Q0"G I QP_Slot_ G() I _is_out_of_range.
'	     "# ISlot_ G() I_home_is_
		G(Q1 FS QP HOME)	    !* Insert a string naming the home!
	            Q1 M(M.M &_Tdebug_Insert_QP_Slot_Info)'
		 "# I
		    40 [Tdebug_Qprint_Length
	            Q1 FS QP SLOT M(M.M &_Tdebug_Insert_Object_Info)''
!# Tdebug H:! !C Print homes for all qp slots, from last down.
Arg is number of slots to display, defaulting to all!
   QTdebug_Whole_Stack"E	    !* check stack mode!
        QTdebug_Q_Top-1 [1	    !* QP slot of the first Q reg!
	QTdebug_Q_Top-QTdebug_Q_Base [2'
				    !* This is the name of this slot!
     "# FS QP PTR [1
        Q1 [2'
	-1"G  '"# Q2'[0	    !* Get number of slots to display!
	Q2-Q0"L Q2U0'		    !* Don-t go past end of slots!
	M.M &_Tdebug_Insert_QP_Slot_Info  !* Abbreviate!
	M.M &_Tdebug_Select_Window 0MW    !* Abbrev & bind to full screen!
	Q0< ISlot_ G(Q2) I_home_is_
            G(Q1 FS QP HOME)	    !* Insert a string naming the home!
	    Q1MS  Q1-1 U1
	    Q2-1 U2>		    !* Insert stuff for all slots!
	HV :FI-40."E FI'	    !* Display results!
	F] B BIND -MW		    !* Flush buffer & unbind window!
!& Tdebug Insert QP Slot Info:! !S Insert ... for slot <arg>
Argument is the slot number!
	[1 [2 [3 0[4
	I_			    !* Line up for pretty display (sp,tab)!
	Q1 FS QP SLOTU3 Q3FP U2    !* Slot into q3, typep into q2!
	Q2+4"E Inumber= G3'
	Q2+3"E I[pure_string_space_number]=
	       8[..E G3 ]..E
	Q2+2"E I[impure_string_space_number]=
	       8[..E G3 ]..E
	Q2+1"E I[dead_buffer]'
	Q2"E   I[buffer],_length=
	       G(FQ3)  1U4'	    !* Set string insert flag!
	Q2-1"E I[Q-vector],_length=
	Q2-100"E I[purstr],_length=
	       G(FQ3)  1U4'	    !* Set string insert flag!
	Q2-101"E I[string],_length=
		 G(FQ3)  1U4'	    !* Set string insert flag!

	Q4"N			    !* Insert string contents!
	     .F[VB Z-.F[VZ	    !* Bind bounds to empty at . !
	     FQ3-20"G		    !* If more than 20 chs in string,!
		      0,20G3 J	    !* get 1st 20 and back up!
		      :L .,ZK	    !* Move to end of 1st line and kill rest!
		      I_...'	    !* Insert deletion marker!
		   "# G3 J :L	    !* Else get string, move to eol!
		      Z-.F"G D I_...'W'    !* If more than 1 line, delete rest!
	     F]VZ F]VB'	    !* Restore bounds!
				    !* Finally terminal cr!
!# Tdebug ?:! !C Print Help message and documentation!
	 M(M.M Describe)&_Tdebug_Step
	 FT Another_?_will_enter_documentation_mode,_which_<sp>_will_exit.
	 :FI-? "E FIW M(M.M &_Tdebug_Describe)'
!& Tdebug Describe:! !S Debug mode command documentation!
       [0 F+
       < :FTType_a_debug_command_to_describe_(or_"*"_for_list):
	 FI :FC U0
	 Q0-*"E 0M(M.M &_Tdebug_Select_Window)    !* Bind window to full screen!
		  M(M.M &_Get_Library_Pointer)TDEBUG U0   !* Pointer in 0 to lib!
		  Q0 M(M.M &_List_One_File)#_Tdebug_C
		  :FV FI W
		  -M(M.M &_Tdebug_Select_Window)
	 Q0-40."E F+ '
	 Q0-40."L Q0#100.U0 :I0 ^ 0'   !* Represent ctl-A as ^A, !
	       "# Q0-177."E :I0 ^?'	    !* rubout as ^?,!
			 "# Q0:I0''	    !* Other chars as themselves.!
	 1,M.M ~DOC~_#_TDebug_0 U0
	 Q0"E :FV is_not_defined.'
	   "# :FV 0'
!# Tdebug ^S:! !# Tdebug ^W:! !C Causes the users buffer to not be redisplayed!
   1 UTdebug_Silent		    !* Turn on the silent flag!
!# Tdebug ^V:! !C Causes the users buffer to be redisplayed!
   0 UTdebug_Silent
!# Tdebug F:! !C Toggles full display of Q vectors!
   QTdebug_Verbose F"E W 2' -1 UTdebug_Verbose
!# Tdebug W:! !C Toggles display the whole stack mode!
   QTdebug_Whole_Stack F"E W 2' -1 UTdebug_Whole_Stack
   M(M.M &_Tdebug_New_Mode_Line)
!# Tdebug V:! !C Displays a Q register's contents!
   :I* [.9
   :I*View_Q_Register: [..0	    !* The title!
   1:< M(M.M &_Read_Q-Reg) U.9	    !* Get name of q register into 0!
       F[ B BIND		    !* Get a buffer!
       I Q .9 _Contains:

       40 [Tdebug_Qprint_Length
       Q .9 M(M.M &_Tdebug_Insert_Object_Info)
				    !* Insert objects info!
   >"N FQ.9 "E F[ B BIND' "# HK'
       I Q_Register_ .9 _does_not_exist.
'				    !* On error, print something enlightening!
   :FT HT
   :I*Iread 			    !* And return!
!& Tdebug Help:! !S Gives help key documentation!
   M(M.M &_Tdebug_Describe)	    !* Run describe!
   @V				    !* And redisplay!
!& Tdebug Insert Object Info:! !S Inserts object's description into the buffer
Given an object as the argument, it inserts a description of the object
into the buffer. It uses one variable, Tdebug Qprint length, to determine the
maximum length to insert. Tdebug Qprint depth is used to determine how deep to
print Q vectors for. Tdebug Qprint lines is used to determine how many lines of
a Q vector to print. First Argument is level of indention.!

   0 [3				    !* String pointer to insert!
   Q2 FP [1			    !* Get type into 1!
   Q1+4"E I[Number]= G2'	    !* Insert number!
   Q1+3"E I[Pure_String_Number]=
          8[..E G2 ]..E I.'	    !* This is sort of random type!
   Q1+2"E I[Impure_String_Number]=
          8[..E G2 ]..E I.'	    !* This is sort of random type!
   Q1+1"E I[Dead_Buffer]'
   Q1"E I[Buffer]_Length=
        G(FQ2) Q2 U3'		    !* Print string below!
   Q1-1"E I[Qvector]_Length=
        G(FQ2 / 5)
        +1,Q2 M(M.M &_Tdebug_Qvector_Print)'    !* Print Qvector!
   Q1-100"E I[Pure_String]_Name:	   !* Print name of the pure string!
        G( Q2 M(M.M &_Macro_Name) )'
				    !* Insert the name of the pure string!
   Q1-101"E I[String]_Length=
        G(FQ2) Q2 U3'		    !* Print the string!
        I:_			    !* Here insert string!
	.F[ VB Z-.F[ VZ	    !* Make virtual buffer around .!
	FQ2 - QTdebug_Qprint_Length"G    !* If more than 20 chars!
	           0,QTdebug_Qprint_Length G2 J  !* Insert first 20 chars and go to top!
		   :L .,Z K	    !* Kill all but first line!
		   I_...'	    !* and insert ...!
		"# G3 J :L	    !* Insert and go to end of line!
		   Z-. F"G D I_...' W'	    !* Kill it if more than 1 line!
	F] VZ F] VB'
				    !* Insert CR at end!
!& Tdebug Qprint Setup:! !S Setups variables used by Qprint!
   M.M &_Tdebug_Qprint_Var_Setup [S	    !* Setup function for Qprint!
   20 MS Tdebug_Qprint_Length		    !* Setup up defaults if they aren't set!
   5  MS Tdebug_Qprint_Depth
   5  MS Tdebug_Qprint_Lines
   @:I*/___/ MS Tdebug_Qprint_Indention   !* What to indent with!
!& Tdebug Qprint Var Setup:! !S Initializes a variable
If the string argument is already defined, do nothing. Otherwise initialize
that variable to the numeric argument!
   :I* [0			    !* Get the name of the variable!
   0FO..Q 0 "E  M.V 0'	    !* If it isn't defined, define it!
!& Tdebug Qvector Print:! !S Prints a Qvector
If the depth is 0 just print ... else print the Q vector recursively,
printing Tdebug Qprint Lines number of lines. First argument is current indention
level, second is the q vector!

	IMore.... '		    !* Too deep, just print ...!
				    !* Otherwise insert CR!
   0[0				    !* This is the index into the Q vector!
   FQ()/5 [1			    !* The length of this Q vector!
   QTdebug_Qprint_Depth-1 [Tdebug_Qprint_Depth
				    !* Decrement the depth!
   Q1-QTdebug_Qprint_Lines"G QTdebug_Qprint_Lines' "# Q1' <
     <G Tdebug_Qprint_Indention>	    !* Indent!
     ISlot_ G0 I_		    !* Print the slot number!
				    !* Repeat the Min(length of qvec, qprint lines)!
     +1,Q:()(Q0) M(M.M &_Tdebug_Insert_Object_Info)
				    !* Call print object with indention!
     %0>			    !* Increment slot pointer!
     "# -2D'