//
// XREF-C.VDM
// Christian Ziemski 10.03.1999
// 25.08.1999 unlimited size (for Clint)
// 15.08.2000 f. 5.20 (HOME->USER_MACRO)
// 18.09.2002 f. 6.x
// 19.09.2002 some fixes with navigation etc,
// Ctrl-F11/12 added
// 20.09.2002 help window
//
//
// Analyses a C program and creates a function cross reference.
//
//
// (Some ideas adapted from CFUNC.VDM and CONDC.VDM.)
//
//----------------------------------------------------------------------
//
// -- Inline documentation -- (could be displayed with Shft-F1)
//
// After the creation of the reference lists you can toggle between
// a line in the cross reference buffer and the appropriate location
// in the source code buffer with the following keys:
//
// Always:
//
// Shift-F1 toggle a little help window on/off
//
// In the cross reference:
//
// F10 switch window to source text (without any special positioning)
// F11 jump to the appropriate function call (=line number in the reference) in the source text
// F12 jump to the appropriate function definition in the source text
//
// Ctrl-F11 jump to the previous occurance of the current function in the cross reference
// Ctrl-F12 jump to the next occurance of the current function in the cross reference
//
// In the source text:
//
// F10 jump to the appropriate line in the cross reference
// Shift-F11 jump to the previous function
// Shift-F12 jump to the next function
//
//
//----------------------------------------------------------------------
//
// Usage: Load the C source code into a buffer and then
// load/execute the macro XREF-C.VDM.
//
// It uses two additional buffers for the reference lists and some
// registers as documented below.
//
//----------------------------------------------------------------------
//
// Requirements: The function definition must begin in column one.
//
// Known problems: - C macros and
// forward declarations with parameter prototypes
// are not evaluated correctly.
// - some C comments with fuction names in it
// can irritate XREF-C
//
// To do: - windows resizing of the cross reference list
// (Awaiting an answer from Ted ...) 20.09.2002: I can't remember what that means. CZ
// - solve known problems
//
//----------------------------------------------------------------------
//
// used resources:
// ---------------
//
// buffer[#93] : original C source program
// buffer[#94] : condensation of functions
// buffer[#95] : cross reference of functions
//
//
// T-Reg 90 : temp. for building the condensed list
// T-Reg 91 : temp. for storing function call ...
//
//
// #90 : line#
// #91 : line#
// #92 : line#
// #93 : buffer number source text
// #94 : buffer number condensed list
// #95 : buffer number cross-reference list
// #98 : temp.
// #99 : temp.
//
//
// Marker 9
//
/////////////////////////////////////////////////////////////////////////
//
Config( U_AUTO_CFG, "Auto-save config", 0 )
Config( PG_E_SYNTAX, "Enable syntax highlighting (*)", 1 )
Syntax_Load("C.SYN")
Config( D_H_CR_LINE, "Highlight cursor line (1=Full, 2=Partial)", 0, ALL )
// Buffer-Switch-Event-Macro:
// Make the cursor line highlighted in the condensed function list only
RS(114,'if(BN==#95){Config(D_H_CR_LINE,"HCL",2)} else {Config(D_H_CR_LINE,"HCL",0)}')
// --------- the key assignments: ---------------------------
Key_Add("Shft-F1", "[VISUAL EXIT] Call(100,'HELP')",NOCONFIRM)
Key_Add("F10", "[VISUAL EXIT] Call(100,'SWITCHXREF')",NOCONFIRM)
Key_Add("F11", "[VISUAL EXIT] Call(100,'GOTOFCALL')",NOCONFIRM)
Key_Add("F12", "[VISUAL EXIT] Call(100,'GOTOFDEF')",NOCONFIRM)
Key_Add("Shft-F11", "[VISUAL EXIT] Call(100,'PREVFUNC')",NOCONFIRM)
Key_Add("Shft-F12", "[VISUAL EXIT] Call(100,'NEXTFUNC')",NOCONFIRM)
Key_Add("Ctrl-F11", "[VISUAL EXIT] Call(100,'PREVOCC')",NOCONFIRM)
Key_Add("Ctrl-F12", "[VISUAL EXIT] Call(100,'NEXTOCC')",NOCONFIRM)
//-------------------------------------------------------------
#93=Buf_Num // current buffer with source text
if(#94==0){ // if not already assigned
#94=Buf_Free // buffer for condensed list
if(#94==-1){
alert()
Statline_Message("No free buffer available!")
return
}
}
BS(#94) BY(OK)
FSA("|(VEDIT_TEMP)\XRC-COND.TMP", NOMSG+OK) // save file for unlimited size
if(#95==0){ // if not already assigned
#95=Buf_Free // buffer for cross reference
if(#95==-1){
alert()
Statline_Message("No free buffer available!")
return
}
}
BS(#95) BY(OK)
FSA("|(VEDIT_TEMP)\XRC-CROS.TMP", NOMSG+OK) // save file for unlimited size
// ---------- Creation of the condensed function list
BS(#93) // back to the source code
BoF
Reg_Empty(90)
repeat(ALL){
//Search(")|[|P,|W|P,|W|M*|M*|?]|L",ADVANCE+ERRBREAK)
Search(")|[|P,|W|P,|W|M*|M*|?]|L",ERRBREAK)
// Search for ){},
// ) {},
// ) {} /* */
// Line(-1) // Backup to beginning of function declaration
BoL // Backup to beginning of function declaration
//
// Skip this occurrence if 1st char is not alphanumeric.
//
if ((Cur_Char < 65 || Cur_Char > 122)) { Line(1,NOERR) Continue }
//Out_Reg(90, APPEND)
//Num_Type(CL,NOCR) // put located line# into T-Reg
//Out_Reg(CLEAR)
//Reg_Set(90," : ", APPEND)
//Reg_Copy(90,1, APPEND) // put located line into T-Reg
// new version for Clint's jillion functions C-program ...
Reg_Copy(90,1) // just this line
#98=CL
BS(#94) // condensed function list
Num_Ins(#98,NOCR) // put located line# into
IT(" : ")
Reg_Ins(90)
BS(#93) // back to the source code
Line(1) // next line
}
BS(#94)
FS(NOMSG) // save it
// Reg_Ins(90) // condensed function list
// ---------- Creation of the cross reference
//BS(#95)
//WS(3,ATTACH)
//BS(#95,ATTACH)
if (Win_Status(#95) == -1){
Win_Split(#95, 40, RIGHT)
}
BS(#95,ATTACH)
//Win_Move(#95,WINX+WINW-FONTW*40,WINY,FONTW*40,WINH)
// Reg_Ins(90) // another copy of the condensed list
Ins_File("|(VEDIT_TEMP)\XRC-COND.TMP")
BOF
while(!At_EoF) {
#90=Num_Eval(ADVANCE) // line# in C program
S("(",ADVANCE)
DoV("\PW\")
BB(CP)
S("|{|W,(}") // end of function name
BE(CP)
RCB(11,BB,BE) // => function name
Line(1)
Set_Marker(9,CP) // remember the actual position
BS(#93) // C program
BoF
// search for all occurences of the function name
repeat(ALL) {
S("|@(11)|[|W](", ERRBREAK)
if(CL == #90){ // check if it's the function itself
S("{") // >> } << just for parentheses-pairing in VDM
Match_Paren() //
Line(1) //
continue // if yes: ignore
}
#98=CP // begin of function name
S("(",ADVANCE) // check if forward declaration
// testweise 20.09.2002
// if(Match("|[|X])")==0) { // (attention: no param. prototypes here!)
// Line(1) //
// continue // if yes: ignore
// }
#91=CL // line#
RCB(91,#98,EoL_Pos) // function call
BS(#95) // search the correct location in cross reference
BoF // where the actual function is,
repeat(ALL){ // using the line numbers
#92=Num_Eval()
if(#92 >= #91){
Break
}
Line(1,NOERR)
}
if(#92 != #91){
Num_Ins(#91, NOCR) // put located line# into T-Reg
IT(" : -- ") //
RI(91) // insert function call
IN(1) // and CR/LF
}
BS(#93) // back to C source
}
BS(#95) // to cross reference and
GP(Marker(9)) // next function here
Update
}
// --------- just a little bit beautifying (some additional line feeds)
BS(#95)
BoF
while(! AT_EoF) {
S(":", ADVANCE)
if(Match("|[|W]--")==0){
Line(1)
Continue
}
BoL
IN(1)
Line(1)
}
BB(CLEAR)
FS(NOMSG)
BS(#93) BoF
BS(#94) BoF
BS(#95) BoF
Config( D_H_CR_LINE, "Highlight cursor line (1=Full, 2=Partial)", 2 )
Visual_Macro(NOMSG)
return
//=============================================================================
:HELPM:
if(Win_Reserved_Bottom_ID != 0) {
Win_Delete('H')
Return
}
#99=Win_Num
Win_Delete('H')
Win_Reserved('H',3,BOTTOM+NOBORDER)
Win_Switch('H')
Win_Color(15)
Win_Clear()
M(" | | CF11 << XREF-entry | CF12 XREF-entry >>
SF1 Help | | SF11 << function | SF12 function >>
| F10 to crossreference | F11 to fnct call | F12 to fnct def ")
Win_Color(112)
WS(#99)
return
//============================================================================
:HELP:
Key_Purge()
#120=Config( PG_E_SYNTAX, "Enable syntax highlighting (*)", 0 )
#121=Config( D_H_CR_LINE, "Highlight cursor line (1=Full, 2=Partial)", 0 )
// Config( S_E_MORE, "Enable -MORE- operation", 0 )
// Config( S_TOP_MARG, "Top margin for cursor", 2 )
#103=Buf_Num
Buf_Switch(Buf_Free, ATTACH)
Reg_Ins(Macro_Num)
BoF
Search("|H3CDOC>", NOERR) // the leading "<" is masked out intentionally!
if(EM){
Message("\n\n No inline help found.")
}else{
Line(1)
Del_Block(0,Cur_Pos)
Search("|H3C/DOC>", NOERR)
if(!EM){
BoL
Del_Block(Cur_Pos, File_Size)
}
Replace("^/+", BEGIN+ALL+REGEXP+NOERR) // remove leading comment characters
BoF
while(! At_EoF){ // shorten lines longer than window width (not perfect, but ...)
Goto_Col(Win_Cols)
Del_Block(Cur_Pos, EoL_Pos)
Line(1, NOERR+ERRBREAK)
}
EoF
//#105=Win_Lines - 1 -2 // number of lines displayable in the window ??? wieso -2 ??? sonst fehlen oben Zeilen ?!?
#105=Screen_Lines - 1 -2// number of lines displayable in the window ??? wieso -2 ??? sonst fehlen oben Zeilen ?!?
#106=Cur_Line - 1 // number of lines to display
// RS(55, "Win_Lines:")
// ItoA(Win_Lines,55, APPEND)
// RS(55, " Screen_Lines:", APPEND)
// ItoA(Screen_Lines,55, APPEND)
//
// Dialog_Input_1(1,"`info`,
// `|@(55)`",
// WORKAREA+TOP+LEFT,20,20)
BoF
repeat(ALL){
Win_Clear
Type(#105, NORESTORE)
if(Cur_Line >= #106){
break
}
Update
#104=Get_Key("\nPress any key to continue or to quit ...", STATLINE+RAW)
if(#104==27){
break
}
}
}
Update
Visual_Macro(NOMSG)
if(#104 != 27){
Get_Key("\nPress any key to close help...", STATLINE+RAW)
}
Buf_Quit(OK+DELETE)
Buf_Switch(#103)
Config( PG_E_SYNTAX, "Enable syntax highlighting (*)", #120 )
Config( D_H_CR_LINE, "Highlight cursor line (1=Full, 2=Partial)", #121 )
return
//---------------------------------------------------------
//
// // *** F10 ***
:SWITCHXREF:
if(BN!=#93) {
if(BN==#95) {
BS(#93,EVENT)
}
Return
}
#98=Cur_Line
BS(#95,EVENT) // search the actual location in cross reference
BoF //
repeat(ALL){ // using the line numbers
#92=Num_Eval()
if(#92 >= #98){
Break
}
Line(1,NOERR)
if(At_EoF){
Break
}
}
return
//---------------------------------------------------------
//
// // *** F11 ***
//
:GOTOFCALL:
if(BN==#93) {
BS(#95,EVENT)
Return
}
BoL
#98=Num_Eval() // line# from the source code
BS(#93,EVENT)
if(#98>0) { // if not have been on empty line
Goto_Line(#98)
SVL(5)
}
return
//
//--------------------------------
//
// // *** F12 ***
//
:GOTOFDEF:
if(BN==#93) {
BS(#95,EVENT)
Return
}
BoL
if(Match('|[|W]|N')==0) { // if on empty line
BS(#93,EVENT)
Return
}
S(':',ADVANCE+NOERR)
if(EM) {
return
} // if on definition line
if(Match(' -- ',ADVANCE)!=0) { // behave like F11
BoL
#98=Num_Eval() // line# of C source
BS(#93,EVENT)
Goto_Line(#98)
SVL(5)
return
}
// if on function call
BB(CP)
S('|{|W,(}') // o.k. ??????
BE(CP)
RCB(91,BB,BE) // the function name
BB(CLEAR)
Save_Pos()
BoF
S(' : |!-|Y |[|Y]|@(91)') // search the definition of that function
BoL
#98=Num_Eval() // line# of C source
Restore_Pos()
BS(#93,EVENT)
Goto_Line(#98)
SVL(5)
return
//--------------------------------
//
// // *** Shift-F11 ***
//
:PREVFUNC:
if(BN==#95){
Return
}
do{
L(-1,NOERR)
S(')|[|H7b,|W|H7b,|W|M*|M*|?]|L',REVERSE+NOERR+ERRBREAK)
BoL
} while(CC<65||CC>122)
return
//--------------------------------
//
// // *** Shift-F12 ***
//
:NEXTFUNC:
if(BN==#95){
Return
}
do{
L(1,NOERR)
S(')|[|H7b,|W|H7b,|W|M*|M*|?]|L',NOERR+ERRBREAK)
BoL
} while(CC<65||CC>122)
return
//--------------------------------
//
// // *** Ctrl-F11 ***
//
:PREVOCC:
if(BN!=#95){
Return
}
BoL
if(Match('|[|W]|N')==0){
return
}
S(':',ADVANCE+NOERR)
if(EM){
return
}
if(Match(' -- ',ADVANCE)!=0){
S('|[|W](')
DOV('\PW\')
}
BB(CP)
S('|[|W](')
BE(CP)
RCB(91,BB,BE)
BB(CLEAR)
BoL
S('|@(91)', REVERSE+NOERR)
if(!EM){
SVL(Win_Lines/2)
}
return
//--------------------------------
//
// // *** Ctrl-F12 ***
//
:NEXTOCC:
if(BN!=#95){
Return
}
BoL
if(Match('|[|W]|N')==0){
return
}
S(':',ADVANCE+NOERR)
if(EM){
return
}
if(Match(' -- ',ADVANCE)!=0){
S('|[|W](')
DOV('\PW\')
}
BB(CP)
S('|[|W](')
BE(CP)
RCB(91,BB,BE)
BB(CLEAR)
Line(1)
S('|@(91)', NOERR)
if(!EM){
SVL(Win_Lines/2)
}else{
Line(-1)
}
return
// --- end ---