TMGIDE6 ;TMG/kst/GT/M debugger Code Coloration ;4/4/09 ;;1.0;TMG-LIB;**1**;4/4/09 ; ;" TMG IDE Code Coloration ;" ;" K. Toppenberg ;" 4/4/09 ;" License: GPL Applies ;" ;"------------------------------------------------------------ ;"PUBLIC API ;"------------------------------------------------------------ ;"ShowLine(line,Options,BkColor) -- Encode and write out a line of code with colors ;"WriteMLine(line,BkColor) -- write out markup line, converting tags into colors ;"MarkupLine(line,Options) -- add markup tags that will allow coloration. ;"------------------------------------------------------------ ;"PRIVATE API ;"------------------------------------------------------------ ;"------------------------------------------------------------ ;"------------------------------------------------------------ temp new tempPos,pos,offset set pos="^PSOORFIN" new Options set Options("XCMD")=1 set Options("LCASE")=1 for offset=50:1:58 do . set tempPos="+"_offset_pos . new line set line=$text(@tempPos) . write offset,": " if $$ShowLine(line,.Options,40) write ! do VTATRIB^TMGTERM(0) ;"Reset colors quit ShowPos(Pos) ;"A temp function to show out code at a given position. new line set line=$text(@Pos) write Pos,": " if $$ShowLine(line) write ! quit ShowLine(line,Options,MaxChar) ;"Purpose: to encode and write out a line of code with colors ;"Input: line -- the code line to show ;" Options -- See MarkupLine for format ;" MaxChar -- OPTIONAL. Max count of characters to be allowed written. ;"Results: returns the actual number of chars written to screen. new temp set temp=$$MarkupLine(line,.Options) ;"write "{",$get(MaxChar),"}" new result set result=$$WriteMLine(temp,.MaxChar) quit result WriteMLine(line,MaxChar) ;"Purpose: to write out markup line, converting tags into colors) ;"Input: line -- the text to show, created by MarkupLine. DON'T pass by reference ;" MaxChar -- OPTIONAL. Max count of characters to be allowed written. ;"result: number of actual characters written to screen (removing tags) new result set result=0 set MaxChar=$get(MaxChar,9999) for quit:($length(line)'>0)!(result>MaxChar) do . new p set p=$find(line,"{C") . if p>0 do ;"start color found . . new partS set partS=$extract(line,1,p-3) . . do SetColors^TMGIDE2("NORM") . . do DoWrite(partS,.result,MaxChar) . . ;"write partS set result=result+$length(partS) . . set line=$extract(line,p-2,999) . . new code set code=$$GetWord^TMGSTUTL(line,1,"{","}") . . set line=$extract(line,$length(code)+3,999) ;"shorten to after color tag onward . . new mode set mode=$piece(code,":",2) . . do SetColors^TMGIDE2(mode) . . set p=$find(line,"{C/}") ;"look for close color directive . . if p>0 do . . . set partS=$extract(line,1,p-5) ;"get text up to closing color . . . do DoWrite(partS,.result,MaxChar) . . . ;"write partS set result=result+$length(partS) . . . do SetColors^TMGIDE2("NORM") . . . set line=$extract(line,p,999) ;"shorten to next segment after closing color onward . . else do . . . do DoWrite(line,.result,MaxChar) . . . ;"write line set result=result+$length(line) . . . set line="" . else do . . do DoWrite(line,.result,MaxChar) . . ;"write line set result=result+$length(line) . . set line="" quit result DoWrite(s,CurLen,MaxLen) ;"Purpose: To do a controlled write to the screen. ;"Input: s -- the text to write ;" CurLen -- PASS BY REFERENCE. Current Num chars that have been written ;" MaxLen -- the limit to chars that can be written to screen. new len set len=$length(s) if CurLen+len>MaxLen do . set s=$extract(s,1,(MaxLen-CurLen)) . set len=$length(s) write s set CurLen=CurLen+len quit MarkupLine(line,Options) ;"Purpose: To take an arbitrary line of code and add markup tags ;" that will allow coloration. ;"Input : line -- the line of code to consider. DON'T pass by reference. ;" Options -- PASS BY REFERENCE. OPTIONAL. Format ;" Options('XCMD')=1 --> turn I --> IF etc. (expand commands) ;" Options('UCASE')=1 --> turn commands into UPPER CASE ;" Options('LCASE')=1 --> turn commands into LOWER CASE ;" Options('Tab')=8 --> e.g. turn $char(9) into 8 spaces (Default is 5) ;"Results : returns line with markup added. Format: ;" {C:Name}...{C/}aaaa bbb ccc{C:Name2}ddddd{C/} ;" 'Name' will be one of the following: ;" LABEL -- for a code label ;" CMD -- for a command, e.g. IF F GOTO ELSE etc. ;" FN -- anything starting with $$ ;" MOD -- e.g. ^MYMODULE ;" IFN -- intrinsic function, i.e. starting with $ ;" STR -- a string ;" PC -- a post-conditional ;" # -- a comment new result set result="" new token,cmd,arg,tabStr,p,ch new tabLen set tabLen=$get(Options("Tab"),5) set $piece(tabStr," ",tabLen)="" set line=$get(line) set line=$translate(line,$char(9),tabStr) ;"turn tabs into spaces if $extract(line,1)'=" " do . set token=$piece(line," ",1) . set line=$piece(line," ",2,999) . set result="{C:LABEL}"_token_"{C/} " for p=1:1 quit:(p>$length(line))!($extract(line,p)'=" ") set result=result_$extract(line,1,p-1) ;"get leading space set line=$extract(line,p,999) new comment set comment="" ;"Extract comments first... set p=1 for set p=$find(line,";",p) quit:(p'>0) do . if $$InQt^TMGSTUTL(line,p-1) quit . set comment=$extract(line,p-1,999) . set comment="{C:#}"_comment_"{C/}" . set line=$extract(line,1,p-2) ;"====== Loop to get COMMAND ARG pairs ====" for quit:($length(line)'>0) do . for set ch=$extract(line,1) quit:(" ."'[ch)!(ch="") do . . set result=result_ch,line=$extract(line,2,999) . quit:(line="") . set token=$$NextBlock(.line) . if token[":" do . . set cmd=$$NextBlock(.token,":") . . set result=result_$$HndlCmd(cmd,.Options)_"{C:PC}:{C/}" . . set result=result_$$HndlArgs(token)_" " . else do . . set result=result_$$HndlCmd(token,.Options)_" " . set arg=$$NextBlock(.line) . set arg=$$HndlArgs(arg) . set result=result_arg_" " ; set result=result_comment ;"add back comment (if any) quit result ; HndlArgs(Args) ;"Purpose: to return a formatted arguments text ;"Input: Args -- the text that supplies arguments to a command, OR ;" the text that is post-conditional code ;"results: returns the Args with markup code. new p set p=1 for set p=$find(Args,"$$",p) quit:(p'>0) do quit:(p'>0) ;"Handle functions . if $$InQt^TMGSTUTL(Args,p-1) set p=$find(Args,"""",p) quit . new fnName set fnName="$$"_$$GetWord^TMGSTUTL(Args,p,"$","():^= ") . new partA,partB . set partA=$extract(Args,1,p-3) . set partB=$extract(Args,p-2+$length(fnName),999) . set Args=partA_"{C:FN}"_fnName_"{C/}"_partB . set p=p+6+$length(fnName) ;"6=length of {C:FN} set p=1 for set p=$find(Args,"$",p) quit:(p'>0) do quit:(p'>0) ;"Handle intrinsic functions . if $$InQt^TMGSTUTL(Args,p-1) set p=$find(Args,"""",p) quit . if $extract(Args,p)="$" set p=p+1 quit ;"avoid $$ matches . new fnName set fnName="$"_$$GetWord^TMGSTUTL(Args,p,"$","():,= ") . new partA,partB . set partA=$extract(Args,1,p-2) . set partB=$extract(Args,p-1+$length(fnName),999) . set Args=partA_"{C:IFN}"_fnName_"{C/}"_partB . set p=p+7+$length(fnName) ;"7=length of {C:IFN} set p=1 for set p=$find(Args,"^",p) quit:(p'>0) do quit:(p'>0);"Handle Modules . if $$InQt^TMGSTUTL(Args,p-1) set p=$find(Args,"""",p) quit . new modName set modName="^"_$$GetWord^TMGSTUTL(Args,p,"^","():,= ") . new partA,partB . set partA=$extract(Args,1,p-2) . set partB=$extract(Args,p-1+$length(modName),999) . set Args=partA_"{C:MOD}"_modName_"{C/}"_partB . set p=p+7+$length(modName) ;"7=length of {C:MOD} set p=1 for set p=$find(Args,"""",p) quit:(p'>0) do ;"Handle Strings . new p2 . if $extract(Args,p)="""" set p2=p . else set p2=$$StrBounds^TMGSTUTL(Args,p) . if p2=0 set p=999 quit . new partA,partB,partC . set partA=$extract(Args,1,p-2) . set partB=$extract(Args,p-1,p2) . set partC=$extract(Args,p2+1,999) . set Args=partA_"{C:STR}"_partB_"{C/}"_partC . set p=p+7+$length(partB) ;"7=length of {C:STR} quit Args HndlCmd(Cmd,Options) ;"Purpose: Return formatted command ;"Input: Cmd -- the mumps command ;" Options -- OPTIONAL. Format: ;" Options('XCMD')=1 --> turn I --> IF etc. (expand commands) ;" Options('SCMD')=1 --> turn IF --> I etc. (shrink commands) ;" Options('UCASE')=1 --> turn commands into UPPER CASE ;" Options('LCASE')=1 --> turn commands into LOWER CASE ;"Results: returns the command with markup code new result set result="" set Cmd=$get(Cmd) new tempCmd set tempCmd=$$UP^XLFSTR(Cmd) if $get(Options("XCMD")) do . if tempCmd="AB" set Cmd="ABLOCK" quit . if tempCmd="A" set Cmd="ASSIGN" quit . if tempCmd="ASTA" set Cmd="ASTART" quit . if tempCmd="ASTO" set Cmd="ASTOP" quit . if tempCmd="AUNB" set Cmd="AUNBLOCK" quit . if tempCmd="B" set Cmd="BREAK" quit . if tempCmd="C" set Cmd="CLOSE" quit . if tempCmd="D" set Cmd="DO" quit . if tempCmd="E" set Cmd="ELSE" quit . if tempCmd="ESTA" set Cmd="ESTART" quit . if tempCmd="ESTO" set Cmd="ESTOP" quit . if tempCmd="ETR" set Cmd="ETRIGGER" quit . if tempCmd="F" set Cmd="FOR" quit . if tempCmd="G" set Cmd="GOTO" quit . ;"if tempCmd="H" set Cmd="HALT" quit . ;"if tempCmd="H" set Cmd="HANG" quit . if tempCmd="I" set Cmd="IF" quit . if tempCmd="J" set Cmd="JOB" quit . if tempCmd="K" set Cmd="KILL" quit . if tempCmd="KS" set Cmd="KSUBSCRIPTS" quit . if tempCmd="KV" set Cmd="KVALUE" quit . if tempCmd="L" set Cmd="LOCK" quit . if tempCmd="M" set Cmd="MERGE" quit . if tempCmd="N" set Cmd="NEW" quit . if tempCmd="O" set Cmd="OPEN" quit . if tempCmd="Q" set Cmd="QUIT" quit . if tempCmd="R" set Cmd="READ" quit . if tempCmd="RL" set Cmd="RLOAD" quit . if tempCmd="RS" set Cmd="RSAVE" quit . if tempCmd="S" set Cmd="SET" quit . if tempCmd="TC" set Cmd="TCOMMIT" quit . if tempCmd="TH" set Cmd="THEN" quit . if tempCmd="TRE" set Cmd="TRESTART" quit . if tempCmd="TRO" set Cmd="TROLLBACK" quit . if tempCmd="TS" set Cmd="TSTART" quit . if tempCmd="U" set Cmd="USE" quit . if tempCmd="V" set Cmd="VIEW" quit . if tempCmd="W" set Cmd="WRITE" quit . if tempCmd="X" set Cmd="XECUTE" quit . if tempCmd="ZWR" set Cmd="ZWRITE" quit if $get(Options("SCMD")) do . if tempCmd="ABLOCK" set Cmd="AB" quit . if tempCmd="ASSIGN" set Cmd="A" quit . if tempCmd="ASTART" set Cmd="ASTA" quit . if tempCmd="ASTOP" set Cmd="ASTO" quit . if tempCmd="AUNBLOCK" set Cmd="AUNB" quit . if tempCmd="BREAK" set Cmd="B" quit . if tempCmd="CLOSE" set Cmd="C" quit . if tempCmd="DO" set Cmd="D" quit . if tempCmd="ELSE" set Cmd="E" quit . if tempCmd="ESTART" set Cmd="ESTA" quit . if tempCmd="ESTOP" set Cmd="ESTO" quit . if tempCmd="ETRIGGER" set Cmd="ETR" quit . if tempCmd="FOR" set Cmd="F" quit . if tempCmd="GOTO" set Cmd="G" quit . if tempCmd="HALT" set Cmd="H" quit . if tempCmd="HANG" set Cmd="H" quit . if tempCmd="IF" set Cmd="I" quit . if tempCmd="JOB" set Cmd="J" quit . if tempCmd="KILL" set Cmd="K" quit . if tempCmd="KSUBSCRIPTS" set Cmd="KS" quit . if tempCmd="KVALUE" set Cmd="KV" quit . if tempCmd="LOCK" set Cmd="L" quit . if tempCmd="MERGE" set Cmd="M" quit . if tempCmd="NEW" set Cmd="N" quit . if tempCmd="OPEN" set Cmd="O" quit . if tempCmd="QUIT" set Cmd="Q" quit . if tempCmd="READ" set Cmd="R" quit . if tempCmd="RLOAD" set Cmd="RL" quit . if tempCmd="RSAVE" set Cmd="RS" quit . if tempCmd="SET" set Cmd="S" quit . if tempCmd="TCOMMIT" set Cmd="TC" quit . if tempCmd="THEN" set Cmd="TH" quit . if tempCmd="TRESTART" set Cmd="TRE" quit . if tempCmd="TROLLBACK" set Cmd="TRO" quit . if tempCmd="TSTART" set Cmd="TS" quit . if tempCmd="USE" set Cmd="U" quit . if tempCmd="VIEW" set Cmd="V" quit . if tempCmd="WRITE" set Cmd="W" quit . if tempCmd="XECUTE" set Cmd="X" quit . if tempCmd="ZWRITE" set Cmd="ZWR" quit if $get(Options("UCASE")) set Cmd=$$UP^XLFSTR(Cmd) if $get(Options("LCASE")) set Cmd=$$LOW^XLFSTR(Cmd) set result="{C:CMD}"_Cmd_"{C/}" quit result NextBlock(line,Div) ;"Purpose: to return from the begining to the next space. Space is ;" discarded. ;" e.g. line='This is a test', then function will return 'This' ;" and line will be changed to be 'is a test' ;" e.g. line='quit:(test) do' will return 'quit:(test)' ;" and line will be changed to ' do' (with 1 space) ;" e.g. line=' do' will return '' ;" and line will be changed to 'do' ;" e.g. line='test' will return 'test' ;" and line will be changed to '' ;" NO e.g. line='..test' will return '...' ;" NO and line will be changed to 'test' ;"Input: line -- PASS BY REFERENCE ;" Div -- the divider of blocks. OPTIONAL. Default=" " ;"Result: the first block, see above. new result set result="" set Div=$get(Div," ") new done set done=0 new p set p=1 for do quit:(done) . set p=$find(line,Div,p) . if p'>0 set result=line,line="",done=1 quit . if $$InQt^TMGSTUTL(line,p-1) quit . set result=$extract(line,1,p-2) . set line=$extract(line,p,999) . set done=1 quit result ; InitColors ;"Purpose: to establish tmgDbgOptions globally-scoped var for colors, new ref set ref=$name(^TMG("TMGIDE",$J,"COLORS")) new refMaster set refMaster=$name(^TMG("TMGIDE","COLORS")) if ($data(@ref)=0)&($data(@refMaster)'=0) do . merge @ref=^TMG("TMGIDE","COLORS") ;"copy master into job's else do . if $data(TMGcBlack)=0 do SetGlobals^TMGTERM . set @ref@("BACKGROUND")=TMGcBlue . set @ref@("HighExecPos")=TMGcGrey . set @ref@("HighBkPos")=TMGcBRed . set @ref@("BkPos")=TMGcRed . set @ref@("Highlight")=TMGcFGBWhite . ;"----------------------------------- . set @ref@("LABEL","fg")=TMGcBYellow . set @ref@("LABEL","bg")=TMGcRed . set @ref@("SPECIAL","fg")=TMGcBYellow . set @ref@("SPECIAL","bg")=TMGcRed . ;"----------------------------------- . set @ref@("NORM","fg")=TMGcFGBWhite . set @ref@("NORM","bg")="@" ;"signal to use current background color . set @ref@("CMD","fg")=TMGcBRed . set @ref@("CMD","bg")="@" . set @ref@("FN","fg")=TMGcBCyan . set @ref@("FN","bg")="@" . set @ref@("MOD","fg")=TMGcBBlue . set @ref@("MOD","bg")="@" . set @ref@("IFN","fg")=TMGcRed . set @ref@("IFN","bg")="@" . set @ref@("STR","fg")=TMGcBMagenta . set @ref@("STR","bg")="@" . set @ref@("PC","fg")=TMGcBRed . set @ref@("PC","bg")="@" . set @ref@("#","fg")=TMGcBYellow . set @ref@("#","bg")="@" . merge @refMaster=@ref quit ; EditColors ;"Purpose: Enable Edit Colors write # new ref set ref=$name(^TMG("TMGIDE",$J,"COLORS")) new Menu,Menu2,UsrSlct,UsrSlct2,UsrRaw,fg,bg,ct set ct=1 set Menu(0)="Pick Color to Edit" set Menu(ct)="Window Background color"_$char(9)_"BACKGROUND",ct=ct+1 set Menu(ct)="Current Execution Position Background Color"_$char(9)_"HighExecPos",ct=ct+1 set Menu(ct)="Highlighted Breakpoint Background Color"_$char(9)_"HighBkPos",ct=ct+1 set Menu(ct)="Breakpoint Background Color"_$char(9)_"BkPos",ct=ct+1 set Menu(ct)="Highlight Background Color"_$char(9)_"Highlight",ct=ct+1 set Menu(ct)="Label Foreground & Background Color"_$char(9)_"LABEL",ct=ct+1 set Menu(ct)="'Special' Foreground & Background Color"_$char(9)_"SPECIAL",ct=ct+1 set Menu(ct)="Normal Text Foreground Color"_$char(9)_"NORM",ct=ct+1 set Menu(ct)="Command Foreground Color"_$char(9)_"CMD",ct=ct+1 set Menu(ct)="Functions Foreground Color"_$char(9)_"FN",ct=ct+1 set Menu(ct)="Module/Global reference Foreground Color"_$char(9)_"MOD",ct=ct+1 set Menu(ct)="Mumps intrinsic functions Foreground Color"_$char(9)_"IFN",ct=ct+1 set Menu(ct)="String Foreground Color"_$char(9)_"STR",ct=ct+1 set Menu(ct)="Post-conditional Foreground Color"_$char(9)_"PC",ct=ct+1 set Menu(ct)="Comments Foreground Color"_$char(9)_"#",ct=ct+1 new i M1 set i=0 for set i=$order(Menu(i)) quit:(i="") do . new bg,fg . new mode set mode=$piece(Menu(i),$char(9),2) . if "BACKGROUND,Highlight,HighBkPos,HighExecPos,BkPos"[mode do . . set bg=$get(@ref@(mode)) . . set fg=$select(bg=0:7,1:10) . else do . . set fg=$get(@ref@(mode,"fg")) . . set bg=$get(@ref@(mode,"bg")) . . if bg="@" set bg=$get(@ref@("BACKGROUND"),0) . set Menu(i,"COLOR","fg")=fg . set Menu(i,"COLOR","bg")=bg ; set UsrSlct=$$Menu^TMGUSRIF(.Menu,"^",.UsrRaw) if UsrSlct="^" goto ECDn if "BACKGROUND,Highlight,HighBkPos,HighExecPos,BkPos"[UsrSlct do goto M1 . set @ref@(UsrSlct)=$$PickBGColor^TMGTERM() if UsrSlct=0 set UsrSlct="" goto M1 if "SPECIAL,LABEL"'[UsrSlct do goto M1 . new bg set bg=$get(@ref@("BACKGROUND"),0) . write "Setting bg=",bg,! . set @ref@(UsrSlct,"fg")=$$PickFGColor^TMGTERM(@ref@(UsrSlct,"fg"),bg) new Label set Label=$get(Menu(UsrRaw)) kill Menu2 set Menu2(0)="For "_$piece(Label,$char(9),1)_"..." set Menu2(1)="Edit Foreground color"_$char(9)_"fg" set Menu2(2)="Edit Background color"_$char(9)_"bg" set Menu2(3)="Edit BOTH colors"_$char(9)_"fg&bg" write ! M2 set fg=+$get(@ref@(UsrSlct,"fg"),1) set bg=+$get(@ref@(UsrSlct,"bg"),0) do VCOLORS^TMGTERM(fg,bg) write "Here are the current colors..." do VTATRIB^TMGTERM(0) ;"Reset colors write ! set UsrSlct2=$$Menu^TMGUSRIF(.Menu2,"^",.UsrRaw) if UsrSlct2="^" goto M1 M3 if UsrSlct2="fg" do goto M2 . set @ref@(UsrSlct,"fg")=$$PickFGColor^TMGTERM(@ref@(UsrSlct,"fg"),@ref@(UsrSlct,"bg")) if UsrSlct2="bg" do goto M2 . set @ref@(UsrSlct,"bg")=$$PickBGColor^TMGTERM(@ref@(UsrSlct,"bg")) if UsrSlct2="fg&bg" do goto M2 . do PickColors^TMGTERM(.fg,.bg) . set @ref@(UsrSlct,"fg")=fg . set @ref@(UsrSlct,"bg")=bg goto M2 ECDn new % set %=2 write "Set current colors as default" do YN^DICN if %=1 do . kill ^TMG("TMGIDE","COLORS") . merge ^TMG("TMGIDE","COLORS")=^TMG("TMGIDE",$J,"COLORS") quit ; ; TestColors do InitColors new mode for mode="Highlight","HighExecPos","BkPos","HighBkPos","SPECIAL","NORM","LABEL","CMD","FN","MOD","IFN","STR","PC","#" do . do SetColors^TMGIDE2(mode) . write "Here is text for ",mode,"...." . do SetColors^TMGIDE2("Reset") . write ! quit ;"============== Code for TRACE functionality ================= ShowTrace ;"Purpose: to show current trace record of execution. ;"if $get(tmgDbgOptions("TRACE"))=1 quit new ref set ref=$name(^TMG("TMGIDE",$J,"TRACE")) if $data(@ref) do . write "SHOW TRACE RECORDS:",! . new NumRecs set NumRecs=$order(@ref@(""),-1) . write NumRecs," trace lines to display",! . new count set count=1 . new % set %=1 . write "Also display code for each line" do YN^DICN write ! . if %=-1 quit . new showCode set showCode=(%=1) . new Colorize set Colorize=0 . if %=1 do quit:(%=-1) . . set %=1 write "Colorize code" do YN^DICN write ! . . set Colorize=(%=1) . new %ZIS . set %ZIS("A")="Enter Output Device: " . set %ZIS("B")="HOME" . do ^%ZIS ;"standard device call . if POP do quit . . do ShowError^TMGDEBUG(.PriorErrorFound,"Error opening output. Aborting.") . use IO . new i set i="" . for set i=$order(@ref@(i)) quit:(i="")!($get(TMGPTCABORT)=1) do . . new s set s=$get(@ref@(i)) . . write s . . if showCode do . . . new pos set pos=$piece(s,".",$length(s,".")) . . . if pos="" write " ??",! quit . . . ;"write "pos=",pos,! . . . new code . . . do . . . . new $etrap set $etrap="set code=""Error -- ""_pos,$etrap="""",$ecode=""""" . . . . set code=$text(@pos) . . . write ?25,":" . . . new x for x=1:1:$length(s,".")-1 write " " . . . if Colorize do . . . . if $$ShowLine(code,.tmgDbgOptions) . . . . do SetColors^TMGIDE2("Reset") . . . else write code . . . write ! . . else write " ",! . . ;"set count=count+1 . . if count>20 do . . . do PressToCont^TMGUSRIF ;" will set TMGPTCABORT=1 if user entered ^ . . . do CUU^TMGTERM(1) . . . write " ",! . . . do CUU^TMGTERM(1) . . . set count=1 else do . write "(No Trace record found)",! do ^%ZISC ;" Close the output device do PressToCont^TMGUSRIF quit RecordTrace(ExecPos) ;"Purpose: To keep trace record of execution as program runs. ;"Input:ExecPos -- Current execution position new ref set ref=$name(^TMG("TMGIDE",$J,"TRACE")) new Stack do GetStackInfo^TMGIDE2(.Stack,ExecPos) new str set str=$$StackStr(.Stack) new i set i=+$get(@ref)+1 set @ref@(i)=str set @ref=i quit StackStr(Stack) ;"Purpose: Turn stack array into a single string ;"Input: Stack -- PASS BY REFERENCE, Numbered array, as created by GetStackInfo^TMGIDE2 ;"Result: returns string with latest position, with ;" a "." leading for each level of indenction. ;" new result set result="" new count set count=+$order(Stack(""),-1) if count>0 do . new x for x=1:1:(count-1) set result=result_"." . new s set s=$get(Stack(count)) . if s[" <--" set s=$piece(s," <--",1) . if s[" " set s=$piece(s," ",2) . set result=result_s quit result ;"============== Code for VAR TRACING functionality ================= ShowVTrace ;"Purpose: Output changes from last step new tmgRefNum set tmgRefNum=+$order(^TMG("TMGIDE",$J,"VARTRACE","DELTA",""),-1) new tmgRefDelta set tmgRefDelta=$name(^TMG("TMGIDE",$J,"VARTRACE","DELTA",tmgRefNum)) new TMG set TMG(1)="ADDED^Additions",TMG(2)="KILLED^Kills",TMG(3)="CHANGED^Changes" new i for i=1,2,3 do . new node set node=$piece(TMG(i),"^",1) . new title set title=$piece(TMG(i),"^",2) . if $data(@tmgRefDelta@(node)) do . . write title,": " . . new varname set varname="" . . for set varname=$order(@tmgRefDelta@(node,varname)) quit:(varname="") do . . . write varname,"=",$get(@tmgRefDelta@(node,varname))," ; " . . write ! quit RecordVTrace ;"Purpose: To keep a trace of changes to the system variable table. new tmgFullRef set tmgFullRef=$name(^TMG("TMGIDE",$J,"VARTRACE","FULL")) new tmgRefNum set tmgRefNum=+$order(@tmgFullRef@(""),-1)+1 if tmgRefNum'>0 goto RVTDn new tmgRefCurF set tmgRefCurF=$name(@tmgFullRef@(tmgRefNum)) new tmgRefPriorF set tmgRefPriorF=$name(@tmgFullRef@(tmgRefNum-1)) new tmgRefDelta set tmgRefDelta=$name(^TMG("TMGIDE",$J,"VARTRACE","DELTA",tmgRefNum)) do StoreVars(tmgRefCurF) if $data(@tmgRefPriorF) do . do DiffVars(tmgRefCurF,tmgRefPriorF,tmgRefDelta) . kill @tmgRefPriorF RVTDn quit StoreVars(tmgRef) ;"Purpose: To copy system variable table to a storage area ;"Input: Ref -- the NAME of the global to store table at ;"Results: none ;"NOTICE: all vars beginning with "tmg" are NOT shown. new tmgArray zshow "V":tmgArray ;"copy system table to local variable new idx set idx=0 for set idx=$order(tmgArray("V",idx)) quit:(idx="") do . new s set s=tmgArray("V",idx) . new varname set varname=$piece(s,"=",1) . quit:(varname="")!($extract(varname,1,3)="tmg") . new value set value=$p(s,"=",2,999) . set @tmgRef@(varname)=value ;"reformat and store in a global var quit DiffVars(tmgRefCurF,tmgRefPriorF,tmgRefDelta) ;"Purpose: To create a record that shows difference between tmgRefCurF and ;" tmgRefPriorF, and stores the difference ;"Note: Possible differences: ;" 1. New record has a new variable, not previously in existence ;" 2. New record has same variable, but changed value ;" 3. New record does NOT have variable that previously existed. ;"Input: tmgRefCurF -- reference of current full variable store ;" tmgRefPriorF -- reference of prior full viariable store ;" tmgRefDelta -- reference to store changes to. Output Format: ;" @tmgRefDelta@('ADDED',varname)=value ;" @tmgRefDelta@('KILLED',varname)="" ;" @tmgRefDelta@('CHANGED',varname)=new value ;"Result: None. But any prior entry in @tmgRefDelta is deleted and changed as above. ; kill @tmgRefDelta new varname ;"First look for additions and changes set varname="" for set varname=$order(@tmgRefCurF@(varname)) quit:(varname="") do . if $data(@tmgRefPriorF@(varname)) do quit . . if $get(@tmgRefPriorF@(varname))'=$get(@tmgRefCurF@(varname)) do . . . set @tmgRefDelta@("CHANGED",varname)=$get(@tmgRefCurF@(varname)) . set @tmgRefDelta@("ADDED",varname)=$get(@tmgRefCurF@(varname)) ; ;"Next, look for deletions set varname="" for set varname=$order(@tmgRefPriorF@(varname)) quit:(varname="") do . if $data(@tmgRefCurF@(varname)) quit . set @tmgRefDelta@("KILLED",varname)=$get(@tmgRefPriorF@(varname)) ; quit ;";"Finally, look for changes ;"set varname="" ;"for set varname=$order(@tmgRefCurF@(varname)) quit:(varname="") do ;". if $data(@tmgRefPriorF@(varname))=0 quit ;". if $get(@tmgRefPriorF@(varname))=$get(@tmgRefCurF@(varname)) quit ;". set @tmgRefDelta@("CHANGED",varname)=$get(@tmgRefCurF@(varname)) ;"quit ;"================================================================