TMGTPSTP.m: Difference between revisions

From VistApedia
Jump to navigationJump to search
No edit summary
NeilArmstrong (talk | contribs)
Added a glossary link to Action~
 
(6 intermediate revisions by 2 users not shown)
Line 1: Line 1:
        ;"------------------------------------------------------------
;"------------------------------------------------------------
        ;"------------------------------------------------------------
;"------------------------------------------------------------
        ;"
;"
        ;" GT.M STEP TRAP
;" GT.M STEP TRAP
        ;"
;"
        ;" K. Toppenberg
;" K. Toppenberg
        ;" 4-13-2005
;" 4-13-2005
        ;" License: GPL Applies
;" License: GPL Applies
        ;"  
;"  
        ;" This code module will allow tracing through code.
;" This code module will allow tracing through code.
        ;" It is used as follows:
;" It is used as follows:
        ;"
;"
        ;" set $ZSTEP="do STEPTRAP^TMGTRSTP($ZPOS) zstep into zcontinue"
;" set $ZSTEP="do STEPTRAP^TMGTRSTP($ZPOS) zstep into zcontinue"
        ;" zstep into
;" zstep into
        ;" do ^MyFunction  ;"<--- put the function you want to trace here
;" do ^MyFunction  ;"<--- put the function you want to trace here
        ;"
;"
        ;" set $ZSTEP=""  ;"<---turn off step capture
;" set $ZSTEP=""  ;"<---turn off step capture
        ;" quit
;" quit
        ;"
;"
        ;"
;"
        ;" Dependencies:
;" Dependencies:
        ;"  Uses TMGTERM
;"  Uses TMGTERM
        ;"
;"
        ;"Notes:
;"Notes:
        ;"  This function will be called inbetween lines of the main  
;"  This function will be called inbetween lines of the main  
        ;"  program that is being traced.  Thus is function can't do
;"  program that is being traced.  Thus is function can't do
        ;"  anything that might change the environment of the main
;"  anything that might change the environment of the main
        ;"  program. This includes accessing global variables --
;"  program.  
        ;" because it will mess up the "naked reference".
  ;"------------------------------------------------------------
        ;"------------------------------------------------------------
;"------------------------------------------------------------
        ;"------------------------------------------------------------
          
          
    STEPTRAP(Pos)
STEPTRAP(idePos,Msg)
                ;"Purpose: This is the line that is called by GT.M for each zstep event.
;"Purpose: This is the line that is called by GT.M for each zstep event.
                ;" It will be used to display the current code execution point, and  
;" It will be used to display the current code execution point, and  
                ;" query user as to plans for future execution: run/step/ etc.
;" query user as to plans for future execution: run/step/ etc.
      ;"Input: idePos -- a text line containing position, as returned bye $ZPOS
      ;"     Msg -- OPTIONAL -- can be used by programs to pass in info.
      ;" If Msg=1, then this function was called without the
      ;" $ZSTEP value set, so this function should set it.
        new NakedRef set NakedRef=$$LGR^%ZOSV ;"save naked reference
             
      new tpBlankLine
      new tp[[Action~|Action]]
      new tpKeyIn
      new tpRunMode,tpStepMode
      new tpI
      new tpDone
      new result set result=1  ;1=step into, 2=step over
      new ViewOffset set ViewOffset=0
     
      ;"Run modes: 0=running mode 
      ;"          1=stepping mode
      ;"          2=Don't show code
      ;"     3=running SLOW mode
      ;"          -1=quit
     
      set tpRunMode=$get(TMGRunMode,1)
      set tpStepMode=$get(TMGStepMode,"into")
     
      new ScrHeight,ScrWidth
      set ScrHeight=$get(TMGScrHeight,10)
      set ScrWidth=$get(TMGScrWidth,80)
     
      set tpBlankLine=" "
      for tpI=1:1:ScrWidth-1 set tpBlankLine=tpBlankLine_" "
     
      new ArrayName set ArrayName="^TMP(""TMGIDE"",$J,""MODULES"")"
      set idePos=$$ConvertPos(idePos,ArrayName)
     
      do VCUSAV2^TMGTERM
      if tpRunMode'=2 do
      . do ShowCodePos(idePos,ScrWidth,ScrHeight)
      else  do
      . do CUP^TMGTERM(1,2)
      write tpBlankLine,!
      write tpBlankLine,!
      do CUU^TMGTERM(2)
      if (tpRunMode=0)!(tpRunMode=3)!(tpRunMode=2) do
      . write tpBlankLine,!
      . do CUU^TMGTERM(1)
      . write "(Press any key to pause)",!
      . read *tpKeyIn:0
      . if (tpKeyIn>0) set tpRunMode=1
      . else  if tpRunMode=3 hang 1
     
      if tpRunMode=2 goto SPDone ;"Don't showmode --> goto SPDone
     
      set tpDone=0
      if tpRunMode=1 for  do  quit:tpDone=1
      . new Def[[Action~|Action]] set Def[[Action~|Action]]="O"
      . do ShowCodePos(idePos,ScrWidth,ScrHeight,,ViewOffset)
      . do CUP^TMGTERM(1,ScrHeight+4) ;"Cursor to line (x,y)
      . write tpBlankLine,!
      . do CUU^TMGTERM(2)
      . if tpWatchLine'="" do     
      . . new $etrap set $etrap="write ""(Invalid M Code!.  Error Trapped.)"" set $etrap="""",$ecode="""""
      . . xecute tpWatchLine
      . . write !
      . write tpBlankLine,!
      . do VTATRIB^TMGTERM(7)  ;"reverse text
      . for i=1:1:ScrWidth write "~"
      . do VTATRIB^TMGTERM(0)  ;"reset text
      . write !
      . do CUU^TMGTERM(2)
      . write "[[Action~|Action]] (? for help): "
      . if tpStepMode="into" write "step INTO// " set Def[[Action~|Action]]="I"
      . else  write "step OVER// " set Def[[Action~|Action]]="O"
      . new loop
      . for loop=1:1:20 write " "
      . for loop=1:1:20 write $char(8) ;"backspace
      . set tp[[Action~|Action]]=$$READ^XGF(1) write !
      . ;"read tp[[Action~|Action]],!
      . if tp[[Actio~|Action]]n="" set tpAction=DefAction
      . if "rR"[tpAction do  quit
      . . set tpRunMode=0
      . . set tpDone=1
      . if "lL"[tp[[Action~|Action]] do  quit
      . . set tpRunMode=3
      . . set tpDone=1
      . if "mM"[tp[[Action~|Action]] do  quit
      . . new temp
      . . do CUU^TMGTERM(1)
      . . do CHA^TMGTERM(1) ;"move to x=1 on this line
      . . write tpBlankLine,!
      . . do CUU^TMGTERM(1)
      . . read " enter M code (^ to cancel): ",tpLine,!
      . . if (tpLine'="^") do
      . . . new $etrap set $etrap="write ""(Invalid M Code!.  Error Trapped.)"",! set $etrap="""",$ecode="""""
      . . . write !  ;"get below bottom line for output.
      . . . xecute tpLine
      . if "iI"[tp[[Action~|Action]] do  quit
      . . set tpStepMode="into"
      . . ;"set $ZSTEP="do STEPTRAP^TMGTPSTP($ZPOS) zstep into zcontinue"
      . . set tpDone=1
      . if "Oo"[tp[[Action~|Action]] do  quit
      . . set tpStepMode="over"
      . . ;"set $ZSTEP="do STEPTRAP^TMGTPSTP($ZPOS) zstep over zcontinue"
      . . set tpDone=1
      . if "Bb"[tp[[Action~|Action]] do  quit
      . . new idePos
      . . read "Enter breakpoint (e.g. Label+8^MyFunct): ",idePos,!
      . . set idePos=Pos_":""n tmg s tmg=$$STEPTRAP^TMGTPSTP($ZPOS,1)"""
      . . ZBREAK @idePos
      . if "Hh"[tp[[Action~|Action]] do  quit
      . . set tpRunMode=2
      . . set tpDone=1
      . if "Ww"[tp[[Action~|Action]] do  quit
      . . new temp
      . . do CUU^TMGTERM(1)
      . . do CHA^TMGTERM(1) ;"move to x=1 on this line
      . . write tpBlankLine,!
      . . do CUU^TMGTERM(1)
      . . read "Enter M code (^ to cancel): ",temp,!
      . . if temp'="^" set tpWatchLine=temp
      . if "Aa"[tp[[Action~|Action]] do  quit
      . . set ViewOffset=ViewOffset-1
      . if "Zz"[tp[[Action~|Action]] do  quit
      . . set ViewOffset=ViewOffset+1
      . else  do  quit
      . . write !
      . . new tpNLines
      . . for tpNLines=1:1:5 write tpBlankLine,!
      . . do CUU^TMGTERM(5)
      . . write " L  -- run in sLow mode    M  -- enter any line of M code",!
      . . write " O  -- step OVER line      I  -- step INTO line",!
      . . write " R  -- run                  H  -- Hide debug code",!
      . . write " B  -- set Breakpoint      W - enter variable watch code ",!
      . . write " A -- scroll upward        Z -- scroll downward",!
     
SPDone
      do VCULOAD2^TMGTERM
      set TMGRunMode=tpRunMode
      if tpStepMode="into" set result=1
      else  set result=2
      set TMGStepMode=tpStepMode
     
      if $get(Msg)=1 do
      . set $ZSTEP="N TMGTrap S TMGTrap=$$STEPTRAP^TMGTPSTP($ZPOS) zstep:(TMGTrap=1) into zstep:(TMGTrap=2) over zcontinue"
      . zstep:(result=1) into zstep:(result=2) over
     
        new discard set discard=$get(@NakedRef) ;"reset naked reference.
     
      quit result
     
     
BlankLine
        write tpBlankLine
        do CHA^TMGTERM(1) ;"move to x=1 on this line
        quit
     
ErrTrap(idePos)
;"Purpose: This is the line that is called by GT.M for each ztrap event.
;" It will be used to display the current code execution point
     
      new ScrHeight,ScrWidth
      set ScrHeight=$get(TMGScrHeight,10)
      set ScrWidth=$get(TMGScrWidth,70)
     
      do VCUSAV2^TMGTERM
      do ShowCodePos(idePos,ScrWidth,ScrHeight)
     
ETDone
      do VCULOAD2^TMGTERM
      quit
     
     
     
          
          
        new tpBlankLine
ShowCode(idePos,ScrWidth,ScrHeight,Wipe,ViewOffset)
        new tpAction
      ;"Purpose: This will display code at the top of the screen
        new tpKeyIn
      ;"Input: idePos -- string like this: X+2^ROUTINE[$DMOD]
        new tpRunMode,tpStepMode
      ;"      ScrWidth -- width of code display (Num of columns)
        new tpI
      ;"      ScrHeight -- height of code display (number of rows)
         new tpDone
      ;"      Wipe -- OPTIONAL.  if 1, then code area is wiped blank
         new result set result=1  ;1=step into, 2=step over
      ;"      ViewOffset -- OPTIONAL.  If a value is supplied, then
      ;"              the display will be shifted up or down (i.e. to view
      ;"              code other than at the point of execution)
      ;"              Positive numbers will scroll page downward.
      new i
      new Routine,Label,Offest,s
      new LastRou,LastLabel,LastOffset
      new dbFGColor,bBGColor,nlFGColor,nlBGColor
      new BlankLine       
      new StartOffset
     
      set ScrWidth=$get(ScrWidth,80)
      set ScrHeight=$get(ScrHeight,10)
     
      set BlankLine=" "
      for i=1:1:ScrWidth-1 set BlankLine=BlankLine_" "
     
         do VTATRIB^TMGTERM(7)  ;"reverse text
     
      do CUP^TMGTERM(1,1) ;"Cursor to line (1,1)
      write BlankLine,!  ;"This is needed for some reason...
      do CUU^TMGTERM(2)
     
      if $get(Wipe)=1 do  goto SCDone
         . do VTATRIB^TMGTERM(0)  ;"reset colors
      . for i=0:1:ScrHeight+1 write BlankLine
     
      set s=$piece(idePos,"$",1)  ;"e.g. X+2^ROUTINE$DMOD-->X+2^ROUTINE
      set Routine=$piece(s,"^",2)
      set Label=$piece(s,"^",1)
      set Offset=+$piece(Label,"+",2)
      set Label=$piece(Label,"+",1)
     
      set s="=== Routine: ^"_Routine_" " write s
      for i=1:1:ScrWidth-$length(s) write "="
      write !
     
      if Offset>(ScrHeight) do
        set StartOffset=(Offset-ScrHeight)+2
      else  set StartOffset=0
      set StartOffset=StartOffset+$get(ViewOffset)
     
      for i=StartOffset:1:(ScrHeight+StartOffset) do
      . new line,Bl,ref,LoopOffset
      . set ref=Label_"+"_i_"^"_Routine
      . set line=$text(@ref)
      . set line=$$Substitute^TMGSTUTL(line,$Char(9),"        ")
      . if (i=Offset) do
      . . do VTATRIB^TMGTERM(0)  ;"reset colors
      . . write ">"
      . else  write " "
      . if $length(line)>(ScrWidth-1) do
      . . write $extract(line,1,ScrWidth-4),"...",!
      . else  do
      . . write $extract(line,1,ScrWidth-1)
      . . write $extract(BlankLine,1,ScrWidth-$length(line)-1),!
      . if (i=Offset) do VTATRIB^TMGTERM(7) ;"reverse colors
     
      for i=1:1:ScrWidth write "~"
      write !
     
SCDone
        do VTATRIB^TMGTERM(0)  ;"reset colors
     
      quit
ScanMod(Module,pArray)
        ;"Purpose: To scan a module and find all the labels/entry points/Entry points
        ;"Input: Module -- The name of the module, like "XGF" (not "XGF.m" or "^XGF")             
        ;"        pArray -- pointer to (name of) array Will be filled like this
        ;"              pArray(1,"TAG")="Label1"
        ;"              pArray(1,"OFFSET")=1
        ;"              pArray(2,"TAG")="Label2"
        ;"              pArray(2,"OFFSET")=9
        ;"              pArray(3,"TAG")="Label3"  etc.
        ;"              pArray(3,"OFFSET")=15
        ;"              pArray("Label1")=1
        ;"              pArray("Label2")=2
        ;"              pArray("Label3")=3
        ;"Output: Results are put into array
        ;"Result: none
        new i set i=1
        new LabelNum set LabelNum=0
        new line set line=""
        if $get(Module)="" goto SMDone
          
          
         ;"Run modes: 0=running mode 
         for  do  quit:(line="")
         ;"           1=stepping mode
        . new ch
         ;"           2=Don't show code
        . set line=$text(+i^@Module)
         ;"     3=running SLOW mode
        . if line="" quit
         ;"          -1=quit
        . set line=$$Substitute^TMGSTUTL(line,$Char(9),"  ") ;"replace tabs for spaces
        . set ch=$extract(line,1)
         . if (ch'=" ")&(ch'=";") do
        . . new label
        . . set label=$piece(line," ",1)
        . . set LabelNum=LabelNum+1
         . . set @pArray@(LabelNum,"TAG")=label
         . . set @pArray@(LabelNum,"OFFSET")=i
        . . set @pArray@(label)=LabelNum
         . set i=i+1
          
          
        set tpRunMode=$get(TMGRunMode,1)
SMDone       
         set tpStepMode=$get(TMGStepMode,"into")
         quit
          
          
        new ScrHeight,ScrWidth
        set ScrHeight=$get(TMGScrHeight,10)
        set ScrWidth=$get(TMGScrWidth,80)
          
          
         set tpBlankLine=" "
ConvertPos(Pos,pArray)
         for tpI=1:1:ScrWidth-1 set tpBlankLine=tpBlankLine_" "
         ;"Purpose: to convert a text positioning line from one that is relative to the last tag/label, into
          
         ;"             one that is relative to the start of the file
        do VCUSAV2^TMGTERM
         ;"              e.g. START+8^MYFUNCT --> +32^MYFUNCT       
         if tpRunMode'=2 do
         ;"Input: Pos -- a position, as returned from $ZPOS
         . do ShowCodePos(Pos,ScrWidth,ScrHeight)
         ;"        pArray -- pointer to (name of).  Array holding  holding tag offsets
         else  do
         ;"              pArray will be in this format:
         . do CUP^TMGTERM(1,2)
         ;"              pArray("ModuleA",1,"TAG")="ALabel1"
         write tpBlankLine,!
         ;"              pArray("ModuleA",1,"OFFSET")=1
        write tpBlankLine,!
         ;"              pArray("ModuleA",2,"TAG")="ALabel2"
         do CUU^TMGTERM(2)
         ;"              pArray("ModuleA",2,"OFFSET")=9
          
         ;"              pArray("ModuleA","Label1")=1
        if (tpRunMode=0)!(tpRunMode=3)!(tpRunMode=2) do
         ;"              pArray("ModuleA","Label2")=2
         . write tpBlankLine,!
         ;"             pArray("ModuleA","Label3")=3
         . do CUU^TMGTERM(1)
         ;"             pArray("ModuleB",1,"TAG")="BLabel1"
         . write "(Press any key to pause)",!
         ;"              pArray("ModuleB",1,"OFFSET")=4
        . read *tpKeyIn:0
         ;"              pArray("ModuleB",2,"TAG")="BLabel2"
        . if (tpKeyIn>0) set tpRunMode=1
         ;"              pArray("ModuleB",2,"OFFSET")=23
        . else  if tpRunMode=3 hang 1
         ;"             pArray("ModuleB","Label1")=1
          
         ;"             pArray("ModuleB","Label2")=2
        if tpRunMode=2 goto SPDone ;"Don't showmode --> goto SPDone
         ;"              pArray("ModuleB","Label3")=3
       
         ;"            NOTE: -- if array passed is empty, then this function will call ScanModule to fill it
        set tpDone=0
         ;"Result: returns the new position line, relative to the start of the file/module
         if tpRunMode=1 for  do  quit:tpDone=1
         ;"
         . new DefAction set DefAction="O"
   
         . do ShowCodePos(Pos,ScrWidth,ScrHeight)
         new s       
         . do CUP^TMGTERM(1,ScrHeight+4) ;"Cursor to line (x,y)  
         new result set result=""
        . write tpBlankLine,!
         new Routine,Label,Offset
        . do CUU^TMGTERM(1)
                       
         . write "Action (? for help): "
      set s=$piece(Pos,"$",1) ;"e.g. X+2^ROUTINE$DMOD-->X+2^ROUTINE
        . if tpStepMode="into" write "step INTO// " set DefAction="I"
      if s="" goto CPDone
         . else  write "step OVER// " set DefAction="O"
     
         . read tpAction,!
      set Routine=$piece(s,"^",2)
         . if tpAction="" set tpAction=DefAction
      if Routine="" goto CPDone
         . if "rR"[tpAction do quit
     
         . . set tpRunMode=0
      set s=$piece(s,"^",1)
         . . set tpDone=1
      set Offset=$piece(s,"+",2)
        . if "lL"[tpAction do  quit
      if Offset="" set Offset=1
         . . set tpRunMode=3
      else set Offset=+Offset
        . . set tpDone=1
      set Label=$piece(s,"+",1)
        . if "mM"[tpAction do  quit
     
        . . write tpBlankLine,!
      if $data(@pArray@(Routine))=0 do
        . . do CUU^TMGTERM(1)
      . new p2Array set p2Array=$name(@pArray@(Routine))
        . . new tpLine
      . do ScanMod(Routine,p2Array)
        . . read " enter M code: ",tpLine,!
     
        . . xecute tpLine
      new i set i=+$get(@pArray@(Routine,Label))
        . if "iI"[tpAction do  quit
      if i=0 goto CPDone
        . . set tpStepMode="into"
      new GOffset set GOffset=@pArray@(Routine,i,"OFFSET")
        . . ;"set $ZSTEP="do STEPTRAP^TMGTPSTP($ZPOS) zstep into zcontinue"
      set result="+"_+(GOffset+Offset)_"^"_Routine
        . . set tpDone=1
     
        . if "Oo"[tpAction do  quit
  CPDone
        . . set tpStepMode="over"
        . . ;"set $ZSTEP="do STEPTRAP^TMGTPSTP($ZPOS) zstep over zcontinue"
        . . set tpDone=1
        . if "Hh"[tpAction do quit
        . . set tpRunMode=2
        . . set tpDone=1
        . else  do quit
        . . new tpNLines
        . . for tpNLines=1:1:5 write tpBlankLine,!
        . . do CUU^TMGTERM(5)
        . . write " L  -- run in sLow mode",!
        . . write " M  -- enter any line of M code",!
        . . write " O  -- step OVER line",!
        . . write " I  -- step INTO line",!
        . . write " R  -- run",!
        . . write " H  -- Hide debug code",!
       
    SPDone
        do VCULOAD2^TMGTERM
        set TMGRunMode=tpRunMode
        if tpStepMode="into" set result=1
        else set result=2
        set TMGStepMode=tpStepMode
         quit result
         quit result
       
       
    ErrTrap(Pos)
                ;"Purpose: This is the line that is called by GT.M for each ztrap event.
                ;" It will be used to display the current code execution point
       
        new ScrHeight,ScrWidth
        set ScrHeight=$get(TMGScrHeight,10)
        set ScrWidth=$get(TMGScrWidth,70)
       
        do VCUSAV2^TMGTERM
        do ShowCodePos(Pos,ScrWidth,ScrHeight)
       
        ETDone
        do VCULOAD2^TMGTERM
        quit
       
       
       
       
    ShowCode(Pos,ScrWidth,ScrHeight,Wipe)
        ;"Purpose: This will display code at the top of the screen
        ;"Input: Pos -- string like this: X+2^ROUTINE[$DMOD]
        ;"      ScrWidth -- width of code display (Num of columns)
        ;
        ;"      Wipe -- OPTIONAL.  if 1, then code area is wiped blank
       
        new i
        new Routine,Label,Offest,s
        new LastRou,LastLabel,LastOffset
        new dbFGColor,bBGColor,nlFGColor,nlBGColor
        new BlankLine       
        new StartOffset
       
        set ScrWidth=$get(ScrWidth,80)
        set ScrHeight=$get(ScrHeight,10)
       
        set nlFGColor=$get(TMGNlFGColor,3)
        set nlBGColor=$get(TMGNlBGColor,0)
        set dbFGColor=$get(TMGDbFGColor,0)
        set dbBGColor=$get(TMGDbBGColor,3)
       
        set BlankLine=" "
        for i=1:1:ScrWidth-1 set BlankLine=BlankLine_" "
       
        do VCOLORS^TMGTERM(dbFGColor,dbBGColor)
       
        do CUP^TMGTERM(1,1) ;"Cursor to line (1,1)
        write BlankLine,!  ;"This is needed for some reason...
        do CUU^TMGTERM(2)
       
        if $get(Wipe)=1 do  goto SCDone
        . do VCOLORS^TMGTERM(nlFGColor,nlBGColor)
        . for i=0:1:ScrHeight+1 write BlankLine
       
        set s=$piece(Pos,"$",1)  ;"e.g. X+2^ROUTINE$DMOD-->X+2^ROUTINE
        set Routine=$piece(s,"^",2)
        set Label=$piece(s,"^",1)
        set Offset=+$piece(Label,"+",2)
        set Label=$piece(Label,"+",1)
       
        set s="=== Routine: ^"_Routine_" " write s
        for i=1:1:ScrWidth-$length(s) write "="
        write !
       
        if Offset>(ScrHeight) do
                set StartOffset=(Offset-ScrHeight)
        else  set StartOffset=0
       
        for i=StartOffset:1:(ScrHeight+StartOffset) do
        . new line,Bl,ref,LoopOffset
        . set ref=Label_"+"_i_"^"_Routine
        . set line=$text(@ref)
        . if (i=Offset) do
        . . do VCOLORS^TMGTERM(nlFGColor,nlBGColor)
        . . write ">"
        . else  write " "
        . if $length(line)>(ScrWidth-1) do
        . . write $extract(line,1,ScrWidth-4),"...",!
        . else  do
        . . write $extract(line,1,ScrWidth-1)
        . . write $extract(BlankLine,1,ScrWidth-$length(line)-1),!
        . if (i=Offset) do VCOLORS^TMGTERM(dbFGColor,dbBGColor)
       
        for i=1:1:ScrWidth write "~"
        write !
       
    SCDone
        ;"do VCULOAD^TMGTERM
        do VCOLORS^TMGTERM(nlFGColor,nlBGColor)
       
        ;"do CUD^TMGTERM(2)
       
        quit

Latest revision as of 08:56, 10 July 2012

;"------------------------------------------------------------
;"------------------------------------------------------------
;"
;" GT.M STEP TRAP
;"
;" K. Toppenberg
;" 4-13-2005
;" License: GPL Applies
;" 
;" This code module will allow tracing through code.
;" It is used as follows:
;"
;" set $ZSTEP="do STEPTRAP^TMGTRSTP($ZPOS) zstep into zcontinue"
;" zstep into
;" do ^MyFunction   ;"<--- put the function you want to trace here
;"
;" set $ZSTEP=""  ;"<---turn off step capture
;" quit
;"
;"
;" Dependencies:
;"   Uses TMGTERM
;"
;"Notes:
;"  This function will be called inbetween lines of the main 
;"  program that is being traced.  Thus is function can't do
;"  anything that might change the environment of the main
;"  program. 
;"------------------------------------------------------------
;"------------------------------------------------------------
       
STEPTRAP(idePos,Msg)
	;"Purpose: This is the line that is called by GT.M for each zstep event.
	;"	It will be used to display the current code execution point, and 
	;"	query user as to plans for future execution: run/step/ etc.
     ;"Input: idePos -- a text line containing position, as returned bye $ZPOS
     ;"	    Msg -- OPTIONAL -- can be used by programs to pass in info.
     ;"			If Msg=1, then this function was called without the 
     ;"				$ZSTEP value set, so this function should set it.

       new NakedRef set NakedRef=$$LGR^%ZOSV ;"save naked reference
              
      new tpBlankLine
      new tpAction
      new tpKeyIn
      new tpRunMode,tpStepMode
      new tpI
      new tpDone
      new result set result=1  ;1=step into, 2=step over
      new ViewOffset set ViewOffset=0
      
      ;"Run modes: 0=running mode  
      ;"           1=stepping mode 
      ;"           2=Don't show code 
      ;"	    3=running SLOW mode
      ;"          -1=quit
      
      set tpRunMode=$get(TMGRunMode,1)
      set tpStepMode=$get(TMGStepMode,"into")
      
      new ScrHeight,ScrWidth
      set ScrHeight=$get(TMGScrHeight,10)
      set ScrWidth=$get(TMGScrWidth,80)
      
      set tpBlankLine=" "
      for tpI=1:1:ScrWidth-1 set tpBlankLine=tpBlankLine_" "
      
      new ArrayName set ArrayName="^TMP(""TMGIDE"",$J,""MODULES"")"
      set idePos=$$ConvertPos(idePos,ArrayName)
      
      do VCUSAV2^TMGTERM
      if tpRunMode'=2 do
      . do ShowCodePos(idePos,ScrWidth,ScrHeight)
      else  do
      . do CUP^TMGTERM(1,2)
      write tpBlankLine,!
      write tpBlankLine,!
      do CUU^TMGTERM(2)

      if (tpRunMode=0)!(tpRunMode=3)!(tpRunMode=2) do
      . write tpBlankLine,!
      . do CUU^TMGTERM(1)
      . write "(Press any key to pause)",!
      . read *tpKeyIn:0
      . if (tpKeyIn>0) set tpRunMode=1
      . else  if tpRunMode=3 hang 1
      
      if tpRunMode=2 goto SPDone ;"Don't showmode --> goto SPDone
      
      set tpDone=0
      if tpRunMode=1 for  do  quit:tpDone=1
      . new DefAction set DefAction="O"
      . do ShowCodePos(idePos,ScrWidth,ScrHeight,,ViewOffset)
      . do CUP^TMGTERM(1,ScrHeight+4) ;"Cursor to line (x,y) 
      . write tpBlankLine,!
      . do CUU^TMGTERM(2)
      . if tpWatchLine'="" do       
      . . new $etrap set $etrap="write ""(Invalid M Code!.  Error Trapped.)"" set $etrap="""",$ecode="""""
      . . xecute tpWatchLine
      . . write !
      . write tpBlankLine,!
      . do VTATRIB^TMGTERM(7)  ;"reverse text
      . for i=1:1:ScrWidth write "~"
      . do VTATRIB^TMGTERM(0)  ;"reset text
      . write !
      . do CUU^TMGTERM(2)
      . write "Action (? for help): "
      . if tpStepMode="into" write "step INTO// " set DefAction="I"
      . else  write "step OVER// " set DefAction="O"
      . new loop
      . for loop=1:1:20 write " "
      . for loop=1:1:20 write $char(8) ;"backspace
      . set tpAction=$$READ^XGF(1) write !
      . ;"read tpAction,!
      . if tpActionn="" set tpAction=DefAction
      . if "rR"[tpAction do  quit
      . . set tpRunMode=0
      . . set tpDone=1
      . if "lL"[tpAction do  quit
      . . set tpRunMode=3
      . . set tpDone=1
      . if "mM"[tpAction do  quit
      . . new temp
      . . do CUU^TMGTERM(1)
      . . do CHA^TMGTERM(1) ;"move to x=1 on this line
      . . write tpBlankLine,!
      . . do CUU^TMGTERM(1)
      . . read " enter M code (^ to cancel): ",tpLine,!
      . . if (tpLine'="^") do
      . . . new $etrap set $etrap="write ""(Invalid M Code!.  Error Trapped.)"",! set $etrap="""",$ecode="""""
      . . . write !  ;"get below bottom line for output.
      . . . xecute tpLine
      . if "iI"[tpAction do  quit
      . . set tpStepMode="into"
      . . ;"set $ZSTEP="do STEPTRAP^TMGTPSTP($ZPOS) zstep into zcontinue"
      . . set tpDone=1
      . if "Oo"[tpAction do  quit
      . . set tpStepMode="over"
      . . ;"set $ZSTEP="do STEPTRAP^TMGTPSTP($ZPOS) zstep over zcontinue"
      . . set tpDone=1
      . if "Bb"[tpAction do  quit
      . . new idePos
      . . read "Enter breakpoint (e.g. Label+8^MyFunct): ",idePos,!
      . . set idePos=Pos_":""n tmg s tmg=$$STEPTRAP^TMGTPSTP($ZPOS,1)"""
      . . ZBREAK @idePos
      . if "Hh"[tpAction do  quit
      . . set tpRunMode=2
      . . set tpDone=1
      . if "Ww"[tpAction do  quit
      . . new temp
      . . do CUU^TMGTERM(1)
      . . do CHA^TMGTERM(1) ;"move to x=1 on this line
      . . write tpBlankLine,!
      . . do CUU^TMGTERM(1)
      . . read "Enter M code (^ to cancel): ",temp,!
      . . if temp'="^" set tpWatchLine=temp
      . if "Aa"[tpAction do  quit
      . . set ViewOffset=ViewOffset-1
      . if "Zz"[tpAction do  quit
      . . set ViewOffset=ViewOffset+1
      . else  do  quit
      . . write !
      . . new tpNLines
      . . for tpNLines=1:1:5 write tpBlankLine,!
      . . do CUU^TMGTERM(5)
      . . write " L  -- run in sLow mode     M  -- enter any line of M code",!
      . . write " O  -- step OVER line       I  -- step INTO line",!
      . . write " R  -- run                  H  -- Hide debug code",!
      . . write " B  -- set Breakpoint       W - enter variable watch code ",!
      . . write " A -- scroll upward         Z -- scroll downward",!
      
SPDone
      do VCULOAD2^TMGTERM
      set TMGRunMode=tpRunMode
      if tpStepMode="into" set result=1
      else  set result=2
      set TMGStepMode=tpStepMode
      
      if $get(Msg)=1 do
      . set $ZSTEP="N TMGTrap S TMGTrap=$$STEPTRAP^TMGTPSTP($ZPOS) zstep:(TMGTrap=1) into zstep:(TMGTrap=2) over zcontinue"
      . zstep:(result=1) into zstep:(result=2) over
      
       new discard set discard=$get(@NakedRef) ;"reset naked reference.
      
      quit result
      
      
BlankLine
       write tpBlankLine
       do CHA^TMGTERM(1) ;"move to x=1 on this line
       quit
      
ErrTrap(idePos)
	;"Purpose: This is the line that is called by GT.M for each ztrap event.
	;"	It will be used to display the current code execution point 
      
      new ScrHeight,ScrWidth
      set ScrHeight=$get(TMGScrHeight,10)
      set ScrWidth=$get(TMGScrWidth,70)
      
      do VCUSAV2^TMGTERM
      do ShowCodePos(idePos,ScrWidth,ScrHeight)
     
ETDone
      do VCULOAD2^TMGTERM
      quit 
      
      
      
       
ShowCode(idePos,ScrWidth,ScrHeight,Wipe,ViewOffset)
      ;"Purpose: This will display code at the top of the screen
      ;"Input: idePos -- string like this: X+2^ROUTINE[$DMOD]
      ;"      ScrWidth -- width of code display (Num of columns)
      ;"      ScrHeight -- height of code display (number of rows) 
      ;"      Wipe -- OPTIONAL.  if 1, then code area is wiped blank
      ;"      ViewOffset -- OPTIONAL.  If a value is supplied, then
      ;"               the display will be shifted up or down (i.e. to view
      ;"               code other than at the point of execution)
      ;"               Positive numbers will scroll page downward.

      new i
      new Routine,Label,Offest,s
      new LastRou,LastLabel,LastOffset
      new dbFGColor,bBGColor,nlFGColor,nlBGColor
      new BlankLine        
      new StartOffset
      
      set ScrWidth=$get(ScrWidth,80)
      set ScrHeight=$get(ScrHeight,10)
      
      set BlankLine=" "
      for i=1:1:ScrWidth-1 set BlankLine=BlankLine_" "
      
       do VTATRIB^TMGTERM(7)  ;"reverse text
      
      do CUP^TMGTERM(1,1) ;"Cursor to line (1,1) 
      write BlankLine,!  ;"This is needed for some reason...
      do CUU^TMGTERM(2)
      
      if $get(Wipe)=1 do  goto SCDone
       . do VTATRIB^TMGTERM(0)  ;"reset colors
      . for i=0:1:ScrHeight+1 write BlankLine
      
      set s=$piece(idePos,"$",1)  ;"e.g. X+2^ROUTINE$DMOD-->X+2^ROUTINE
      set Routine=$piece(s,"^",2)
      set Label=$piece(s,"^",1)
      set Offset=+$piece(Label,"+",2)
      set Label=$piece(Label,"+",1)
      
      set s="=== Routine: ^"_Routine_" " write s
      for i=1:1:ScrWidth-$length(s) write "="
      write !
      
      if Offset>(ScrHeight) do
        set StartOffset=(Offset-ScrHeight)+2
      else  set StartOffset=0
      set StartOffset=StartOffset+$get(ViewOffset)
      
      for i=StartOffset:1:(ScrHeight+StartOffset) do
      . new line,Bl,ref,LoopOffset
      . set ref=Label_"+"_i_"^"_Routine
      . set line=$text(@ref)
      . set line=$$Substitute^TMGSTUTL(line,$Char(9),"        ")
      . if (i=Offset) do 
      . . do VTATRIB^TMGTERM(0)  ;"reset colors
      . . write ">"
      . else  write " "
      . if $length(line)>(ScrWidth-1) do
      . . write $extract(line,1,ScrWidth-4),"...",!
      . else  do
      . . write $extract(line,1,ScrWidth-1)
      . . write $extract(BlankLine,1,ScrWidth-$length(line)-1),!
      . if (i=Offset) do VTATRIB^TMGTERM(7)  ;"reverse colors
      
      for i=1:1:ScrWidth write "~"
      write !
      
SCDone
       do VTATRIB^TMGTERM(0)  ;"reset colors
      
      quit


ScanMod(Module,pArray)
       ;"Purpose: To scan a module and find all the labels/entry points/Entry points
       ;"Input: Module -- The name of the module, like "XGF" (not "XGF.m" or "^XGF")               
       ;"         pArray -- pointer to (name of) array Will be filled like this
       ;"              pArray(1,"TAG")="Label1"
       ;"              pArray(1,"OFFSET")=1
       ;"              pArray(2,"TAG")="Label2"
       ;"              pArray(2,"OFFSET")=9
       ;"              pArray(3,"TAG")="Label3"  etc.
       ;"              pArray(3,"OFFSET")=15
       ;"              pArray("Label1")=1
       ;"              pArray("Label2")=2
       ;"              pArray("Label3")=3
       ;"Output: Results are put into array
       ;"Result: none

       new i set i=1
       new LabelNum set LabelNum=0
       new line set line=""
       if $get(Module)="" goto SMDone
       
       for  do  quit:(line="")
       . new ch
       . set line=$text(+i^@Module)
       . if line="" quit
       . set line=$$Substitute^TMGSTUTL(line,$Char(9),"  ") ;"replace tabs for spaces
       . set ch=$extract(line,1)
       . if (ch'=" ")&(ch'=";") do
       . . new label
       . . set label=$piece(line," ",1)
       . . set LabelNum=LabelNum+1
       . . set @pArray@(LabelNum,"TAG")=label
       . . set @pArray@(LabelNum,"OFFSET")=i
       . . set @pArray@(label)=LabelNum
       . set i=i+1
       
SMDone        
       quit
       
       
ConvertPos(Pos,pArray)
       ;"Purpose: to convert a text positioning line from one that is relative to the last tag/label, into
       ;"              one that is relative to the start of the file
       ;"              e.g. START+8^MYFUNCT --> +32^MYFUNCT        
       ;"Input: Pos -- a position, as returned from $ZPOS
       ;"        pArray -- pointer to (name of).  Array holding  holding tag offsets
       ;"              pArray will be in this format:
       ;"              pArray("ModuleA",1,"TAG")="ALabel1"
       ;"              pArray("ModuleA",1,"OFFSET")=1
       ;"              pArray("ModuleA",2,"TAG")="ALabel2"
       ;"              pArray("ModuleA",2,"OFFSET")=9
       ;"              pArray("ModuleA","Label1")=1
       ;"              pArray("ModuleA","Label2")=2
       ;"              pArray("ModuleA","Label3")=3
       ;"              pArray("ModuleB",1,"TAG")="BLabel1"
       ;"              pArray("ModuleB",1,"OFFSET")=4
       ;"              pArray("ModuleB",2,"TAG")="BLabel2"
       ;"              pArray("ModuleB",2,"OFFSET")=23
       ;"              pArray("ModuleB","Label1")=1
       ;"              pArray("ModuleB","Label2")=2
       ;"              pArray("ModuleB","Label3")=3
       ;"            NOTE: -- if array passed is empty, then this function will call ScanModule to fill it
       ;"Result: returns the new position line, relative to the start of the file/module
       ;"

       new s        
       new result set result=""
       new Routine,Label,Offset
                       
      set s=$piece(Pos,"$",1)  ;"e.g. X+2^ROUTINE$DMOD-->X+2^ROUTINE
      if s="" goto CPDone
      
      set Routine=$piece(s,"^",2)
      if Routine="" goto CPDone
      
      set s=$piece(s,"^",1)
      set Offset=$piece(s,"+",2)
      if Offset="" set Offset=1
      else  set Offset=+Offset
      set Label=$piece(s,"+",1)
      
      if $data(@pArray@(Routine))=0 do
      . new p2Array set p2Array=$name(@pArray@(Routine))
      . do ScanMod(Routine,p2Array)
      
      new i set i=+$get(@pArray@(Routine,Label))
      if i=0 goto CPDone
      new GOffset set GOffset=@pArray@(Routine,i,"OFFSET")
      set result="+"_+(GOffset+Offset)_"^"_Routine
      
CPDone
       quit result