Module doku
/*
<doku>
<created>23/02/2004 14:07:48</created>
<changed>23/02/04 sk</changed>
<author>Thomas Friebel</author>
<about>
Dieses Modul ist weniger für die direkte Wiederverwendung in anderen
Modulen gedacht, als vielmehr als Entwicklungswerkzeug, um Module mit
Hilfe ihrer Quellcode-Kommentare zu dokumentieren.
Alle Kommentare, die sich zwischen den Tags <DOKU> und
</DOKU> befinden werden in ein HTML-Dokument geschrieben,
welches den Dateinamen des Moduls (inkl. der Endung ".mod") und der
Erweiterung ".htm" bekommt.
Der Aufruf auf Kommandozeilenebene sieht exemplarisch wie folgt aus:
<code>
/tdbengine/tdbengine doku.prg -cwin -smeinmodul.mod -ddoku
</code>
Wurde kein "-d Paramter" als Zielverzeichnis übergeben, so wird ein
Unterverzeichnis ./doku/ angelegt und als Zielpfad verwendet.
Das Ergebnis ist eine Datei namens meinmodul.mod.htm
Das Doku-Modul unterscheidet bisher 2 Vorkommensarten der <Doku>-Tags, nämlich
a.) Innerhalb eines PROCEDURe-Rumpfes und
b.) ausserhalb irgendwelcher Prozeduren.
Im 1. Fall werden alle Doku-Abschnitte erkannt und der Procedure zugeordnet ausgegeben.
</about>
<todo>
Um grössere Dokumentationsblöcke nicht mitten im Quellcode platzieren zu müssen ist noch eine Art Doku-Verweis einzubauen.
An der Stelle, an der im HTML-Dokument ein Text erscheinen soll ist im
Quellcode nur noch ein "Link" auf einen am Modul-Ende stehenden Block
einzufügen. Das soll die Übersichtlichkeit im Source wahren.
</todo>
</doku>
*/
Var cVerStr : String = "0.2"
Var STDOUT : Integer = 0
var false : Byte = NEIN
var true : Byte = JA
var cEOL_Win : String = ^M+^J
var cEOL_NIX : String = ^J
var cEOL : String = cEOL_NIX
Procedure trim(c : String) : String
return rtrim(ltrim(c))
endproc
Procedure ConOut(cText : String)
Write(STDOUT, cText)
EndProc
Procedure ConOutLn(cText : String)
WriteLn(STDOUT, cText)
EndProc
Procedure displayHelp
/*<doku>
<created>30/04/02 11:19:56</created><changed>30/04/02 11:19:56</changed><author>TF</author>
<about>Gibt die Kommandozeilen-Hilfe zum Modul aus</about>
<todo>Für HTML-Ausgabe einrichten</todo>
</doku>*/
ConOutLn("")
ConOutLn("Hilfe")
ConOutLn("----------------------------------------------- ")
ConOutLn("Aufruf: {/bin/tdbengine} doku.prg
[-?|--help] [-c{eol}] [-s|--source]{matchpattern}
[-d|--destination]{destination}")
ConOutLn("")
ConOutLn("eol :
Art des Zeilenumbruchs im Modul (eol = 'win' - Chr(13)+Chr(10), eol =
'unix' - Chr(13))")
ConOutLn("matchpattern : Dateifilter (z.B. *.mod oder doku.mod, etc.)")
ConOutLn("destination : Name des
Zielverzeichnis (wenn leer, dann './doku/'). Wird ggfs. angelegt")
ConOutLn("")
ConOutLn("Beispiele:")
ConOutLn("tdbengine doku.prg -cwin -sadressen.mod -ddoku")
ConOutLn("tdbengine doku.prg --source*.mod")
ConOutLn("tdbengine doku.prg -s*.mod")
ConOutLn("")
ConOutLn("Bei Fragen, Kritik oder Wünschen: http://www.tdbengine.org")
ConOutLn("Dieses Modul kann sowohl gewerblich als
auch privat nach Belieben eingesetzt, modifiziert und weitergegeben
werden.")
ConOutLn("Die Firma tdb Software Service GmbH
gewährt keinerlei Garantie auf die Funktionalität des Programms.")
ConOutLn("")
EndProc
Procedure getUses(fDoc : Integer; cFileTarget : String)
/*<doku>
<created>30/04/02 11:20:50</created><changed>03/05/02
11:20:50 / TF</changed><author>TF</author>
<parameters><li>fDoc : File-Handle des zu erzeugenden HTML-Files </li></parameters>
<about>
Ermittelt alle mit Uses/Include eingebundenen Module
und listet diese im Kopfbereich der Doku als Links zu deren Dokus auf.
Es wird dabei nicht auf die Existenz entsprechender Dokus geprüft.
</about>
<keywords>eingebundene Module, ermitteln, verlinken</keywords>
</doku>*/
Var nLastPos : Integer = 0;
Var nNewPos : Integer = 0;
Var cModul : String
If
RAMText_Find("ramtext:modul","us"+"es",nLastPos,1) > 0 or
RAMText_Find("ramtext:modul","incl"+"ude",nLastPos,1) > 0
WriteLn(fDoc, OEMToANSI("benötigte Module:<br>"))
End
While nLastPos := RAMText_Find("ramtext:modul","us"+"es ",nLastPos,1) > 0
nNewPos := RAMText_Find("ramtext:modul",cEOL, nLastPos)
cModul := RAMText_Part("ramtext:modul",nLastPos, nNewPos - nLastPos)
cModul := Lower(cModul)
cModul := Exchange(cModul,"us"+"es ","")
cModul := Exchange(cModul," ","")
cModul := Exchange(cModul,";","")
If IsFile(cModul) > 0
cModul :=
"<a href='"+cFileTarget+cModul+".htm'>"+cModul+"</a>"
End
WriteLn(fDoc, cModul +"<br>")
nLastPos := nNewPos
End
nLastPos := 1
While nLastPos := RAMText_Find("ramtext:modul","incl"+"ude ",nLastPos,1) > 0
nNewPos := RAMText_Find("ramtext:modul",cEOL, nLastPos)
cModul := RAMText_Part("ramtext:modul",nLastPos, nNewPos - nLastPos)
cModul := Lower(cModul)
cModul := Exchange(cModul,"incl"+"ude ","")
cModul := Exchange(cModul," ","")
cModul := Exchange(cModul,";","")
If IsFile(cModul) > 0
cModul :=
"<a href='"+cFileTarget+cModul+".htm'>"+cModul+"</a>"
End
WriteLn(fDoc, cModul +"<br>")
nLastPos := nNewPos
End
EndProc
Procedure DokuInProc(nBegin, nEnd : Integer; Var aProcPos : Integer[,]; iCount : Integer ) : Integer
Var i : Integer = 0
Var nResult : Integer = 0
While i++ <= iCount do
If nBegin > aProcPos[i,1] and nEnd < aProcPos[i,2]
If aProcPos[i,0] = 0
nResult := i
aProcPos[i,0] := i
i := iCount +1
Else
nResult := -i
End
End
End
Return nResult
EndProc
Procedure ParseBlock
/*<doku>
<todo></todo>
<created>30/04/02 11:22:36</created><changed>30/04/02 11:22:36</changed><author>TF</author>
<about>Ersetzt alle Doku-Tags im Doku-Block durch entsprechende HTML-Konstrukte.
</doku>*/
Var nPosBegin, nPosEnd, nPosCur : Integer
Var nDelBeg, nDelEnd : Integer
Var cNode
: String
Var aNodes
: String[]
Var aPlaceholder
: String[]
Var i
: Integer
Var fBase,fBlock, fClip
: Integer
Var fHeader
: Integer
Var cLine
: String
InitArray(aNodes[10]);
InitArray(aPlaceholder[10]);
aNodes[0] := "created"; aPlaceholder[0] :=
OEMToANSI("<span class='created'><b>Angelegt:</b>
#created#</span>");
aNodes[1] := "changed"; aPlaceholder[1] :=
OEMToANSI("<span class='changed'><b>Geändert:</b>
#changed#</span>");
aNodes[2] := "name"; aPlaceholder[2] :=
OEMToANSI("<br><div class='name'>Name: #name#</div>");
aNodes[3] := "parameters"; aPlaceholder[3] :=
OEMToANSI("<br><span class='parameters'>Parameter:
<ul>#parameters#</ul></span>");
aNodes[4] := "return"; aPlaceholder[4] :=
OEMToANSI("<br><span
class='return'>Rückgabewert:<br>#return#</span>"); //sk
aNodes[5] := "about";
aPlaceholder[5] := OEMToANSI("<br><span
class='about'><b>Beschreibung:</b><br><br>#about#</span>");
aNodes[6] := "todo";
aPlaceholder[6] := OEMToANSI("<br><div
class='todo'><b>TODO:</b><br> #todo#</div>");
aNodes[7] := "attention";
aPlaceholder[7] := OEMToANSI("<br><div
class='attention'><b>ACHTUNG:</b><br>#attention#</div>");
aNodes[8] := "author";
aPlaceholder[8] := OEMToANSI("<br><div
class='author'><b>Autor:</b> #author#</div>");
aNodes[9] := "keywords";
aPlaceholder[9] := OEMToANSI("<br><div
class='keywords'><b>Keywords:</b>
#keywords#</div>");
ramtext("ramtext:blockheader",8192)
fBase := Rewrite("ramtext:blockheader")
writeln(fBase, '<div class="blockheader">')
writeln(fBase, '#created##changed#')
writeln(fBase, '#author#')
writeln(fBase, '#attention#')
writeln(fBase, '#about#')
writeln(fBase, '#todo#')
writeln(fBase, '#parameters#')
writeln(fBase, '#return#')
writeln(fBase, '#keywords#')
writeln(fBase, '#plain#')
writeln(fBase, '</div>')
close(fBase)
i:=0
nPosCur := 0
While cNode := aNodes[i] # "" do
nDelBeg := 0
nDelEnd := 0
If nPosBegin := RAMText_Find("ramtext:block","<"+cNode+">",1,1) > 0
nDelBeg := nPosBegin
nPosBegin := nPosBegin + Length(cNode) +2
If nPosEnd :=
RAMText_Find("ramtext:block","</"+cNode+">",nPosBegin,1) > 0
If nPosEnd > nPosBegin
RAMText_Copy("ramtext:block",nPosBegin,
nPosEnd - nPosBegin)
RAMText_Subst("ramtext:blockheader","#"+cNode+"#",aPlaceholder[i])
fClip := Reset("ramtext:~clip")
While not EOT(fClip)
RAMText_Subst("ramtext:blockheader","#"+cNode+"#",ReadLn(fClip)+"<br>#"+cNode+"#")
End
Close(fClip)
End
RAMText_Subst("ramtext:blockheader","#"+cNode+"#","")
End
nPosCur
:= nPosEnd + Length(cNode) +3
nDelEnd := nPosCur
If nDelBeg > 0 and (nDelBeg < nDelEnd)
RAMText_Delete("ramtext:block",nDelBeg, nDelEnd - nDelBeg)
End
End
i++
RAMText_Subst("ramtext:blockheader","#"+cNode+"#","")
End
RAMText_Subst("ramtext:blockheader","#plain#","<br><div class='plain'>#plain#</div>")
fBlock := Reset("ramtext:block")
While not EOT(fBlock)
If cLine := ReadLn(fBlock) # ""
RAMText_Subst("ramtext:blockheader","#plain#",cLine+"<br>#plain#")
End
End
Close(fBlock)
RAMText_Subst("ramtext:blockheader","#plain#","")
CopyFile( "ramtext:blockheader","ramtext:block")
EndProc
Procedure isParam(c : String) : String
var i : byte
var cP : String
i:=1
while cP := ParamStr(i++) do
if cP[1,Length(c)] = c then
return cP
end
end
return ""
endproc
Procedure Main
/*<doku>
<created>30/04/02 11:25:02</created><changed>30/04/02 11:25:02</changed><author>TF</author>
<about>Die Hauptprozedur des Doku-Moduls. Hier werden die
einzelnen Sourcen nach den <DOKU>-Tags gescannt und die
HTML-Dokumente erstellt</about>
</doku>*/
Var cFile,cDir : String
Var nPos,nPosEnde : Integer
Var f
: Integer
Var fDoc : Integer
Var cFileMatch : String
Var cFileTarget : String
Var bBlockOpen : Byte
Var nPosProc : Integer
Var nPosEndProc : Integer
Var cProcedure : String
Var bWithinProc : Byte
Var aProcedures : String[]
Var aProcPos : Integer[,]
Var iProcedures : Byte
Var i
: Byte
Var nProc : Integer
Var cLine
: String
CGICloseBuffer
ConOutLn("tdbengine doku.mod Version " + cVerStr)
If isParam("-?") or isParam("--help") then
displayHelp
Return
ElsIf cFileMatch := isParam("-s")[3,255] = "" and cFileMatch := isParam("--source")[9,255] = "" then
ConOutLn("Keine Quell-Module angegeben!")
Return
End
if isParam("-c")[3] like "w" or isParam("--charset")[10] like "w" then cEOL := cEOL_Win end
If cFileTarget := isParam("-d")[3,255] = "" and cFileTarget := isParam("--destination")[14,255] = "" then
cFileTarget := "./doku/"
ElsIf cFileTarget[Length(cFileTarget),1] # "/"
cFileTarget := cFileTarget +"/"
End
MakeDir(cFileTarget)
ConOutLn("Such-Pattern : "+cFileMatch)
ConOutLn("Zielverzeichnis : "+cFileTarget)
ConOutLn("Starte Scan-Vorgang")
cFile := trim(FirstDir(cFileMatch,""))
//CGIWriteLn('Main.cFile='+cFile) //sk
While cFile do
ramtext("ramtext:modul",64000)
cDir := trim(DirInfo(cFileMatch)[128,127])
cFile := trim(cFile[1,63])
fDoc := Rewrite("ramtext:docu")
WriteLn(fDoc,"<html>")
WriteLn(fDoc,"<head>")
WriteLn(fDoc,"<title>")
WriteLn(fDoc,cFile+" -
Automatische Quellcode-Dokumentation (Stand: " + DateStr(Today) + " / "
+ TimeStr(Now)+")") //sk
WriteLn(fDoc,"</title>")
WriteLn(fDoc,'<link rel="stylesheet" type="text/css" href="dokustyle.css">')
WriteLn(fDoc,"</head>")
WriteLn(fDoc,"<body>")
WriteLn(fDoc,"<style>")
WriteLn(fDoc,".headline
{margin:10px; color:#123456; font-family:verdana; font-size:16pt;
font-weight:bolder;}")
WriteLn(fDoc,".plain
{position:relative; color:#123456; font-family:verdana;
font-size:8pt;;}")
WriteLn(fDoc,".author {color:#000000; font-family:verdana; font-size:8pt;;}")
WriteLn(fDoc,".created {color:#000000; font-family:verdana; font-size:8pt;;}")
WriteLn(fDoc,".about {color:#123456; font-family:verdana; font-size:9pt;}")
WriteLn(fDoc,".parameters {color:#123456; font-family:verdana; font-size:9pt;}")
WriteLn(fDoc,".return {color:#123456; font-family:verdana; font-size:9pt;}")
WriteLn(fDoc,".todo {color:#123456; font-family:verdana; font-size:8pt;}")
WriteLn(fDoc,".changed {color:#000000; font-family:verdana; font-size:8pt;;}")
WriteLn(fDoc,".keywords
{color:#999999; font-family:verdana; font-size:8pt; font-weight:bold;}")
WriteLn(fDoc,".attention
{border-style:solid; border-width:1; color:#ff0000;
font-family:verdana; font-size:11pt; font-weight:bold;}")
WriteLn(fDoc,".procedure
{color:#123456; font-family:verdana; font-size:10pt;
font-weight:bold;}")
WriteLn(fDoc,"</style>")
WriteLn(fDoc, "<small><a href='.'>Index</a></small>")
WriteLn(fDoc, "<div class='headline'>Modul: "+ cFile +"</div>")
CopyFile(trim(cDir+cFile),"ramtext:modul")
getUses(fDoc,"")
WriteLn(fDoc, "<hr>")
WriteLn(fDoc,"Dokumentierte Prozeduren im Modul:<br>")
WriteLn(fDoc,'<ul><code>#Procedures#</code></ul>') //sk
ConOut(cDir+cFile+NTimes(" ",20 - Length(cFile)) + " : ")
InitArray(aProcedures[99])
iProcedures := 0
i := 0
nPos := 0
nPosProc := 0
bBlockOpen := false
nPosEndProc := 0
nPosEnde := 0
bBlockOpen := false
InitArray(aProcPos[99,2])
While nPosProc := RAMText_Find("ramtext:modul","PROCEDURE ",nPosEndProc,1) > 0 do
cProcedure :=
RAMText_Part("ramtext:modul",nPosProc,RAMText_Find("ramtext:modul",cEOL,
nPosProc) - nPosProc)
nPosEndProc := RAMText_Find("ramtext:modul","ENDPROC",nPosProc,1)
aProcedures[iProcedures++] := cProcedure[11,250]
aProcPos[iProcedures,0] := 0
aProcPos[iProcedures,1] := nPosProc
aProcPos[iProcedures,2] := nPosEndProc
End
While nPos := RAMText_Find("ramtext:modul","<DO"+"KU>",nPosEnde,1) > 0
nPos := nPos + Length("<DO"+"KU>")
nPosEnde :=
RAMText_Find("ramtext:modul","</DO"+"KU>",nPos,1)
If nProc := DokuInProc(nPos, nPosEnde, aProcPos,iProcedures) >
0
bWithinProc := true
WriteLn(fDoc, "<a
name='proc"+Str(nProc)+"'><br><div
style='background-Color:#eeeeee;' class='procedure'><code>"+
aProcedures[nProc] +"</code></div><br>") //sk
ElsIf nProc < 0
bWithinProc := true
ElsIf nProc = 0
bWithinProc := false
WriteLn(fDoc, "<br><div
style='position:relative;background-Color:#eeeeee;
left:20px;'><b><small>HINWEIS</small></b>")
End
If bBlockOpen = true
bBlockOpen := false
Else
bBlockOpen := true
End
If bBlockOpen &&
RAMText_Copy("ramtext:modul",nPos,nPosEnde - nPos) > 0
ConOut(".")
bBlockOpen := false
CopyFile("ramtext:~clip","ramtext:block")
ParseBlock
f := Reset("ramtext:block",1)
While not EOT(f)
Write(fDoc,Read(f))
End
If bWithinProc
Else
WriteLn(fDoc,
"</div>")
End
Close(f)
End
nPosEnde := nPosEnde + Length("</do"+"ku>")
End
WriteLn(fDoc,"</body>")
WriteLn(fDoc,"</html>")
Close(fDoc)
i:= 1
While i <= iProcedures do
If aProcPos[i,0] > 0
RAMText_Subst("ramtext:docu","#Procedures#","<li><a
href='#proc"+Str(i)+"'>"+aProcedures[i]+"</a></li>#Procedures#")
End
i++
End
RAMText_Subst("ramtext:docu","#Procedures#","")
CopyFile("ramtext:docu", cFileTarget+cFile +".htm")
ConOutLn(" OK")
Close(fDoc)
cFile := trim(NextDir[1,63])
End
EndProc