* Added support for project file

git-svn-id: trunk@16711 -
This commit is contained in:
michael 2011-01-05 22:19:53 +00:00
parent 749075a851
commit 853a1eb31c
7 changed files with 807 additions and 158 deletions

3
.gitattributes vendored
View File

@ -11967,6 +11967,8 @@ utils/fpdoc/fpde/xpms.pp svneol=native#text/plain
utils/fpdoc/fpdoc.css -text
utils/fpdoc/fpdoc.lpi svneol=native#text/plain
utils/fpdoc/fpdoc.pp svneol=native#text/plain
utils/fpdoc/fpdocproj.pas svneol=native#text/plain
utils/fpdoc/fpdocxmlopts.pas svneol=native#text/plain
utils/fpdoc/intl/Makefile svneol=native#text/plain
utils/fpdoc/intl/dglobals.de.po svneol=native#text/plain
utils/fpdoc/intl/dglobals.sk.po svneol=native#text/plain
@ -11977,6 +11979,7 @@ utils/fpdoc/intl/fpdocstr.de.po svneol=native#text/plain
utils/fpdoc/intl/makeskel.de.po svneol=native#text/plain
utils/fpdoc/makeskel.lpi svneol=native#text/plain
utils/fpdoc/makeskel.pp svneol=native#text/plain
utils/fpdoc/sample-project.xml svneol=native#text/plain
utils/fpdoc/sh_pas.pp svneol=native#text/plain
utils/fpdoc/testunit.pp svneol=native#text/plain
utils/fpdoc/testunit.xml svneol=native#text/plain

View File

@ -89,8 +89,8 @@ Type
procedure StartChapter(ChapterName : String); override;
procedure StartOverview(WithAccess : Boolean); override;
procedure EndOverview; override;
procedure WriteOverviewMember(ALabel,AName,Access,ADescr : String); override;
procedure WriteOverviewMember(ALabel,AName,ADescr : String); override;
procedure WriteOverviewMember(const ALabel,AName,Access,ADescr : String); override;
procedure WriteOverviewMember(const ALabel,AName,ADescr : String); override;
Class Function FileNameExtension : String; override;
// Description node conversion. Overrides for TFPDocWriter.
procedure DescrBeginBold; override;
@ -374,7 +374,7 @@ begin
end;
function TTemplateWriter.FileNameExtension: String;
class function TTemplateWriter.FileNameExtension: String;
begin
Result:=TTemplateExtension;
end;
@ -520,7 +520,7 @@ begin
{ End of overview }
end;
procedure TTemplateWriter.WriteOverviewMember(ALabel,AName,Access,ADescr : String);
procedure TTemplateWriter.WriteOverviewMember(Const ALabel,AName,Access,ADescr : String);
begin
{ Write one entry in property overview:
@ -531,7 +531,7 @@ begin
}
end;
procedure TTemplateWriter.WriteOverviewMember(ALabel,AName,ADescr : String);
procedure TTemplateWriter.WriteOverviewMember(Const ALabel,AName,ADescr : String);
begin
{ Write one entry in method overview:

View File

@ -4,94 +4,143 @@
<Version Value="9"/>
<General>
<Flags>
<SaveClosedFiles Value="False"/>
<SaveOnlyProjectUnits Value="True"/>
<MainUnitHasUsesSectionForAllUnits Value="False"/>
<MainUnitHasCreateFormStatements Value="False"/>
<MainUnitHasTitleStatement Value="False"/>
<LRSInOutputDirectory Value="False"/>
</Flags>
<SessionStorage Value="InProjectDir"/>
<MainUnit Value="0"/>
<Title Value="FPDoc Documentation generator"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
<Icon Value="0"/>
</General>
<i18n>
<EnableI18N LFM="False"/>
</i18n>
<VersionInfo>
<StringTable ProductVersion=""/>
</VersionInfo>
<BuildModes Count="1">
<Item1 Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<IgnoreBinaries Value="False"/>
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
<ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
<CommandLineParams Value="--project=fpdoc.xml"/>
<LaunchingApplication PathPlusParams="/usr/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
</local>
</RunParams>
<Units Count="11">
<RequiredPackages Count="1">
<Item1>
<PackageName Value="FCL"/>
</Item1>
</RequiredPackages>
<Units Count="14">
<Unit0>
<Filename Value="fpdoc.pp"/>
<IsPartOfProject Value="True"/>
<UnitName Value="FPDoc"/>
</Unit0>
<Unit1>
<Filename Value="dwriter.pp"/>
<Filename Value="dglobals.pp"/>
<IsPartOfProject Value="True"/>
<UnitName Value="dWriter"/>
<UnitName Value="dGlobals"/>
</Unit1>
<Unit2>
<Filename Value="dw_dxml.pp"/>
<IsPartOfProject Value="True"/>
<UnitName Value="dw_dxml"/>
</Unit2>
<Unit3>
<Filename Value="dw_html.pp"/>
<IsPartOfProject Value="True"/>
<UnitName Value="dw_html"/>
</Unit3>
<Unit4>
<Filename Value="dw_ipflin.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="dw_ipflin"/>
</Unit4>
<Unit5>
<Filename Value="dw_latex.pp"/>
<IsPartOfProject Value="True"/>
<UnitName Value="dw_latex"/>
</Unit5>
<Unit6>
<Filename Value="dwlinear.pp"/>
<IsPartOfProject Value="True"/>
<UnitName Value="dwlinear"/>
</Unit2>
<Unit3>
<Filename Value="dw_latex.pp"/>
<IsPartOfProject Value="True"/>
<UnitName Value="dw_LaTeX"/>
</Unit3>
<Unit4>
<Filename Value="dw_xml.pp"/>
<IsPartOfProject Value="True"/>
<UnitName Value="dw_XML"/>
</Unit4>
<Unit5>
<Filename Value="dw_html.pp"/>
<IsPartOfProject Value="True"/>
<UnitName Value="dw_HTML"/>
</Unit5>
<Unit6>
<Filename Value="dw_man.pp"/>
<IsPartOfProject Value="True"/>
<UnitName Value="dw_man"/>
</Unit6>
<Unit7>
<Filename Value="dw_linrtf.pp"/>
<IsPartOfProject Value="True"/>
<UnitName Value="dw_LinRTF"/>
<UnitName Value="dw_linrtf"/>
</Unit7>
<Unit8>
<Filename Value="dw_man.pp"/>
<IsPartOfProject Value="True"/>
<UnitName Value="dw_man"/>
</Unit8>
<Unit9>
<Filename Value="dwriter.pp"/>
<IsPartOfProject Value="True"/>
<UnitName Value="dwriter"/>
</Unit9>
<Unit10>
<Filename Value="dw_txt.pp"/>
<IsPartOfProject Value="True"/>
<UnitName Value="dw_txt"/>
</Unit8>
<Unit9>
<Filename Value="dglobals.pp"/>
<IsPartOfProject Value="True"/>
<UnitName Value="dGlobals"/>
</Unit9>
<Unit10>
<Filename Value="dw_ipflin.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="dw_ipflin"/>
</Unit10>
<Unit11>
<Filename Value="dw_xml.pp"/>
<IsPartOfProject Value="True"/>
<UnitName Value="dw_xml"/>
</Unit11>
<Unit12>
<Filename Value="fpdocproj.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="fpdocproj"/>
</Unit12>
<Unit13>
<Filename Value="fpdocxmlopts.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="fpdocxmlopts"/>
</Unit13>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="9"/>
</Parsing>
<Target>
<Filename Value="fpdoc"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Other>
<CompilerMessages>
<UseMsgFile Value="True"/>
</CompilerMessages>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@ -16,7 +16,7 @@
program FPDoc;
uses
SysUtils, Classes, Gettext, DOM, XMLWrite, PasTree, PParser,
SysUtils, Classes, Gettext, DOM, XMLWrite, PasTree, PParser, custapp,
dGlobals, // GLobal definitions, constants.
dwriter, // TFPDocWriter definition.
dwlinear, // Linear (abstract) writer
@ -27,29 +27,44 @@ uses
dw_ipflin, // IPF writer (new linear output)
dw_man, // Man page writer
dw_linrtf, // linear RTF writer
dw_txt; // TXT writer
dw_txt, fpdocproj, fpdocxmlopts; // TXT writer
const
OSTarget: String = {$I %FPCTARGETOS%};
CPUTarget: String = {$I %FPCTARGETCPU%};
FPCVersion: String = {$I %FPCVERSION%};
FPCDate: String = {$I %FPCDATE%};
DefOSTarget = {$I %FPCTARGETOS%};
DefCPUTarget = {$I %FPCTARGETCPU%};
DefFPCVersion = {$I %FPCVERSION%};
DefFPCDate = {$I %FPCDATE%};
var
Backend : String;
BackendOptions : TStrings;
InputFiles, DescrFiles: TStringList;
PackageName, DocLang, ContentFile : String;
Engine: TFPDocEngine;
StopOnParserError : Boolean;
Type
Procedure Usage(AnExitCode : Byte);
{ TFPDocAplication }
TFPDocAplication = Class(TCustomApplication)
private
FProject : TFPDocProject;
FProjectFile : Boolean;
FPackage : TFPDocPackage;
Protected
procedure ParseCommandLine;
procedure Parseoption(const S: String);
Procedure Usage(AnExitCode : Byte);
procedure CreateDocumentation(APackage : TFPDocPackage; Options : TEngineOptions);
Procedure DoRun; override;
Public
Constructor Create(AOwner : TComponent); override;
Destructor Destroy; override;
Function SelectedPackage : TFPDocPackage;
end;
Procedure TFPDocAplication.Usage(AnExitCode : Byte);
Var
I,P : Integer;
S : String;
L : TStringList;
C : TFPDocWriterClass;
Backend : String;
begin
Writeln(Format(SCmdLineHelp,[ExtractFileName(Paramstr(0))]));
@ -74,6 +89,7 @@ begin
Writeln(SUsageOption190);
L:=TStringList.Create;
Try
Backend:=FProject.OPtions.Backend;
If (Backend='') then
begin
Writeln;
@ -90,8 +106,8 @@ begin
else
begin
Writeln;
Writeln(Format(SUsageFormatSpecific,[Lowercase(Backend)]));
C:=GetWriterClass(backend);
Writeln(Format(SUsageFormatSpecific,[Lowercase(backend)]));
C:=GetWriterClass(Backend);
C.Usage(L);
If L.Count>0 then
For I:=0 to (L.Count-1) div 2 do
@ -106,42 +122,88 @@ begin
Halt(AnExitCode);
end;
procedure InitOptions;
destructor TFPDocAplication.Destroy;
begin
InputFiles := TStringList.Create;
DescrFiles := TStringList.Create;
BackendOptions := TStringList.Create;
Engine := TFPDocEngine.Create;
StopOnParserError:=False;
FreeAndNil(FProject);
Inherited;
end;
procedure FreeOptions;
function TFPDocAplication.SelectedPackage: TFPDocPackage;
begin
Engine.Free;
BackendOptions.Free;
DescrFiles.Free;
InputFiles.Free;
Result:=FPackage;
if (FPackage=Nil) or (FPackage.Name='') then
begin
Writeln(SNeedPackageName);
Usage(1);
end;
end;
procedure ReadContentFile(const AParams: String);
procedure TFPDocAplication.ParseCommandLine;
Function ProjectOpt(Const s : string) : boolean;
begin
Result:=(Copy(s,1,3)='-p=') or (Copy(s,1,10)='--project=');
end;
Function PackageOpt(Const s : string) : boolean;
begin
Result:=((Copy(s,1,3)='-a=') or (Copy(s,1,10)='--package='));
end;
var
i: Integer;
i : Integer;
s : string;
begin
i := Pos(',', AParams);
Engine.ReadContentFile(Copy(AParams, 1, i - 1),
Copy(AParams, i + 1, Length(AParams)));
// Check project
for i := 1 to ParamCount do
begin
s:=ParamStr(I);
If ProjectOpt(S) then
ParseOption(s);
If (FProject.Packages.Count=1) then
FPackage:=FProject.Packages[0]
else if (FProject.Options.DefaultPackageName<>'') then
Fpackage:=FProject.Packages.FindPackage(FProject.Options.DefaultPackageName);
end;
If FProject.Packages.Count=0 then
begin
FPackage:=FProject.Packages.Add as TFPDocPackage;
end;
// Check package
for i := 1 to ParamCount do
begin
s:=ParamStr(I);
If PackageOpt(S) then
ParseOption(s);
end;
for i := 1 to ParamCount do
begin
s:=ParamStr(I);
If Not (ProjectOpt(s) or PackageOpt(S)) then
ParseOption(s);
end;
if (FPackage=Nil) or (FPackage.Name='') then
begin
Writeln(SNeedPackageName);
Usage(1);
end;
end;
procedure ParseOption(const s: String);
procedure TFPDocAplication.Parseoption(Const S : String);
procedure AddToFileList(List: TStringList; const FileName: String);
procedure AddToFileList(List: TStrings; const FileName: String);
var
f: Text;
s: String;
begin
if Copy(FileName, 1, 1) = '@' then
begin
Assign(f, Copy(FileName, 2, Length(FileName)));
AssignFile(f, Copy(FileName, 2, Length(FileName)));
Reset(f);
while not EOF(f) do
begin
@ -161,13 +223,13 @@ begin
if (s = '-h') or (s = '--help') then
Usage(0)
else if s = '--hide-protected' then
Engine.HideProtected := True
FProject.Options.HideProtected := True
else if s = '--warn-no-node' then
Engine.WarnNoNode := True
FProject.Options.WarnNoNode := True
else if s = '--show-private' then
Engine.HidePrivate := False
FProject.Options.ShowPrivate := False
else if s = '--stop-on-parser-error' then
StopOnParserError := True
FProject.Options.StopOnParseError := True
else
begin
i := Pos('=', s);
@ -181,102 +243,122 @@ begin
Cmd := s;
SetLength(Arg, 0);
end;
if Cmd = '--descr' then
AddToFileList(DescrFiles, Arg)
if (Cmd = '--project') or (Cmd='-p') then
begin
FProjectFile:=True;
With TXMLFPDocOptions.Create(self) do
try
LoadOptionsFromFile(FProject,Arg);
finally
Free;
end;
end
else if (Cmd = '--descr') then
AddToFileList(SelectedPackage.Descriptions, Arg)
else if (Cmd = '-f') or (Cmd = '--format') then
begin
Arg:=UpperCase(Arg);
If FindWriterClass(Arg)=-1 then
WriteLn(StdErr, Format(SCmdLineInvalidFormat, [Arg]))
else
BackEnd:=Arg;
FProject.Options.BackEnd:=Arg;
end
else if (Cmd = '-l') or (Cmd = '--lang') then
DocLang := Arg
FProject.Options.Language := Arg
else if (Cmd = '-i') or (Cmd = '--input') then
AddToFileList(InputFiles, Arg)
AddToFileList(SelectedPackage.Inputs, Arg)
else if (Cmd = '-o') or (Cmd = '--output') then
Engine.Output := Arg
SelectedPackage.Output := Arg
else if Cmd = '--content' then
ContentFile := Arg
SelectedPackage.ContentFile := Arg
else if Cmd = '--import' then
ReadContentFile(Arg)
SelectedPackage.Imports.Add(Arg)
else if Cmd = '--package' then
PackageName := Arg
begin
If FProjectFile then
FPackage:=FProject.Packages.FindPackage(Arg)
else
FPackage.Name:=Arg;
end
else if Cmd = '--ostarget' then
OSTarget := Arg
FProject.Options.OSTarget := Arg
else if Cmd = '--cputarget' then
CPUTarget := Arg
FProject.Options.CPUTarget := Arg
else if Cmd = '--mo-dir' then
modir := Arg
FProject.Options.modir := Arg
else if Cmd = '--parse-impl' then
Engine.InterfaceOnly:=false
FProject.Options.InterfaceOnly:=false
else
begin
BackendOptions.Add(Cmd);
BackendOptions.Add(Arg);
FProject.Options.BackendOptions.Add(Cmd);
FProject.Options.BackendOptions.Add(Arg);
end;
end;
end;
procedure ParseCommandLine;
procedure TFPDocAplication.CreateDocumentation(APackage : TFPDocPackage; Options : TEngineOptions);
var
i: Integer;
begin
for i := 1 to ParamCount do
ParseOption(ParamStr(i));
If (BackEnd='') then
BackEnd:='html';
if (PackageName='') then
begin
Writeln(SNeedPackageName);
Usage(1);
end;
end;
procedure CreateDocumentation;
var
i: Integer;
i,j: Integer;
WriterClass : TFPDocWriterClass;
Writer : TFPDocWriter;
Engine : TFPDocEngine;
Cmd,Arg : String;
begin
for i := 0 to DescrFiles.Count - 1 do
Engine.AddDocFile(DescrFiles[i]);
Engine.SetPackageName(PackageName);
if Length(DocLang) > 0 then
TranslateDocStrings(DocLang);
for i := 0 to InputFiles.Count - 1 do
try
ParseSource(Engine, InputFiles[i], OSTarget, CPUTarget);
except
on e: EParserError do
If StopOnParserError then
Raise
else
WriteLn(StdErr, Format('%s(%d,%d): %s',
[e.Filename, e.Row, e.Column, e.Message]));
end;
WriterClass:=GetWriterClass(Backend);
Writer:=WriterClass.Create(Engine.Package,Engine);
With Writer do
Try
If BackendOptions.Count>0 then
for I:=0 to ((BackendOptions.Count-1) div 2) do
If not InterPretOption(BackendOptions[I*2],BackendOptions[I*2+1]) then
WriteLn(StdErr, Format(SCmdLineInvalidOption,[BackendOptions[I*2]+' '+BackendOptions[I*2+1]]));
WriteDoc;
Finally
Free;
end;
if Length(ContentFile) > 0 then
Engine.WriteContentFile(ContentFile);
Engine:=TFPDocEngine.Create;
try
For J:=0 to Apackage.Imports.Count-1 do
begin
Arg:=Apackage.Imports[j];
i := Pos(',', Arg);
Engine.ReadContentFile(Copy(Arg,1,i-1),Copy(Arg,i+1,Length(Arg)));
end;
for i := 0 to APackage.Descriptions.Count - 1 do
Engine.AddDocFile(APackage.Descriptions[i]);
Engine.SetPackageName(APackage.Name);
Engine.Output:=APackage.Output;
Engine.HideProtected:=Options.HideProtected;
Engine.HidePrivate:=Not Options.ShowPrivate;
if Length(Options.Language) > 0 then
TranslateDocStrings(Options.Language);
for i := 0 to Fpackage.Inputs.Count - 1 do
try
ParseSource(Engine, APackage.Inputs[i], Options.OSTarget, Options.CPUTarget);
except
on e: EParserError do
If Options.StopOnParseError then
Raise
else
WriteLn(StdErr, Format('%s(%d,%d): %s',
[e.Filename, e.Row, e.Column, e.Message]));
end;
WriterClass:=GetWriterClass(Options.Backend);
Writer:=WriterClass.Create(Engine.Package,Engine);
With Writer do
Try
If Options.BackendOptions.Count>0 then
for I:=0 to ((Options.BackendOptions.Count-1) div 2) do
begin
Cmd:=Options.BackendOptions[I*2];
Arg:=Options.BackendOptions[I*2+1];
If not InterPretOption(Cmd,Arg) then
WriteLn(StdErr, Format(SCmdLineInvalidOption,[Cmd+'='+Arg]));
end;
WriteDoc;
Finally
Free;
end;
if Length(FPackage.ContentFile) > 0 then
Engine.WriteContentFile(FPackage.ContentFile);
finally
FreeAndNil(Engine);
end;
end;
Procedure TFPDocAplication.DoRun;
begin
{$IFDEF Unix}
@ -285,15 +367,30 @@ begin
gettext.TranslateResourceStrings('intl/fpdoc.%s.mo');
{$ENDIF}
WriteLn(STitle);
WriteLn(Format(SVersion, [FPCVersion, FPCDate]));
WriteLn(Format(SVersion, [DefFPCVersion, DefFPCDate]));
WriteLn(SCopyright);
WriteLn;
InitOptions;
Try
ParseCommandLine;
CreateDocumentation;
WriteLn(SDone);
Finally
FreeOptions;
end;
ParseCommandLine;
CreateDocumentation(FPackage,FProject.Options);
WriteLn(SDone);
Terminate;
end;
constructor TFPDocAplication.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
StopOnException:=true;
FProject:=TFPDOCproject.Create(Nil);
FProject.Options.StopOnParseError:=False;
FProject.Options.CPUTarget:=DefCPUTarget;
FProject.Options.OSTarget:=DefOSTarget;
end;
begin
With TFPDocAplication.Create(Nil) do
try
Run;
finally
Free;
end;
end.

236
utils/fpdoc/fpdocproj.pas Normal file
View File

@ -0,0 +1,236 @@
unit fpdocproj;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils;
Type
{ TFPDocPackage }
TFPDocPackage = Class(TCollectionItem)
private
FContent: String;
FDescriptions: TStrings;
FIMports: TStrings;
FinPuts: TStrings;
FName: String;
FOutput: String;
Public
constructor Create(ACollection: TCollection); override;
destructor destroy; override;
procedure Assign(Source : TPersistent); override;
Property Name : String Read FName Write FName;
Property Inputs : TStrings Read FinPuts;
Property Descriptions : TStrings Read FDescriptions;
Property Imports : TStrings read FIMports;
Property ContentFile : String Read FContent Write FContent;
Property Output : String Read FOutput Write FOutput;
end;
{ TFPDocPackages }
TFPDocPackages = Class(TCollection)
private
function GetP(AIndex : Integer): TFPDocPackage;
procedure SetP(AIndex : Integer; const AValue: TFPDocPackage);
Public
Function IndexOfPackage(Const AName : String) : Integer;
Function FindPackage(Const AName : String) : TFPDOcPackage;
Property Packages[AIndex : Integer] : TFPDocPackage Read GetP Write SetP; Default;
end;
{ TEngineOptions }
TEngineOptions = Class(TPersistent)
private
FBackEndoptions: TStrings;
FCPUTarget: String;
FDefaultPackageName: String;
FFormat: String;
FHidePrivate: Boolean;
FHideProtected: Boolean;
FIO: Boolean;
FLanguage: String;
FMoDir: String;
FOSTarget: String;
FSOPE: Boolean;
FWarnNoNode: Boolean;
procedure SetBackendOptions(const AValue: TStrings);
Public
Constructor Create;
Destructor Destroy; override;
procedure Assign(Source : TPersistent); override;
Published
Property OSTarget : String Read FOSTarget Write FOStarget;
Property CPUTarget : String Read FCPUTarget Write FCPUTarget;
Property Language : String Read FLanguage Write fLanguage;
Property Backend : String Read FFormat Write FFormat;
Property BackendOptions : TStrings Read FBackEndoptions Write SetBackendOptions;
Property StopOnParseError : Boolean Read FSOPE Write FSOPE;
Property HideProtected : Boolean Read FHideProtected Write FHideProtected;
Property WarnNoNode : Boolean Read FWarnNoNode Write FWarnNoNode;
Property ShowPrivate : Boolean Read FHidePrivate Write FHidePrivate;
Property InterfaceOnly : Boolean Read FIO Write FIO;
Property MoDir : String Read FMoDir Write FMODir;
Property DefaultPackageName : String Read FDefaultPackageName Write FDefaultPackageName;
end;
{ TFPDocProject }
TFPDocProject = Class(TComponent)
private
FOptions: TEngineOptions;
FPackages: TFPDocPackages;
procedure setOptions(const AValue: TEngineOptions);
Public
Constructor Create(AOwner : TComponent); override;
Destructor Destroy; override;
Published
Property Packages : TFPDocPackages Read FPackages Write FPackages;
Property Options : TEngineOptions Read FOptions Write setOptions;
end;
implementation
{ TEngineOptions }
procedure TEngineOptions.SetBackendOptions(const AValue: TStrings);
begin
if FBackEndoptions=AValue then exit;
FBackEndoptions.Assign(AValue);
end;
constructor TEngineOptions.Create;
begin
FBackendOptions:=TStringList.Create;
end;
destructor TEngineOptions.Destroy;
begin
FreeAndNil(FBackendOptions);
inherited Destroy;
end;
procedure TEngineOptions.Assign(Source: TPersistent);
var
O : TEngineOptions;
begin
if (Source is TEngineOptions) then
begin
O:=Source as TEngineOptions;
FBackEndoptions.Assign(O.BackendOptions);
FCPUTarget:=O.CPUTarget;
FFormat:=O.Backend;
FLanguage:=O.Language;
FOSTarget:=O.OSTarget;
FSOPE:=O.StopOnParseError;
HideProtected:=O.HideProtected;
WarnNoNode:=O.WarnNoNode;
ShowPrivate:=O.ShowPrivate;
InterfaceOnly:=O.InterfaceOnly;
MoDir:=O.MoDir;
end
else
inherited Assign(Source);
end;
{ TFPDocProject }
procedure TFPDocProject.setOptions(const AValue: TEngineOptions);
begin
if FOptions=AValue then exit;
FOptions.Assign(AValue);
end;
constructor TFPDocProject.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FPackages:=TFPDocPackages.Create(TFPDocPackage);
FOptions:=TEngineOptions.Create;
end;
destructor TFPDocProject.Destroy;
begin
FreeAndNil(Foptions);
FreeAndNil(FPackages);
inherited Destroy;
end;
{ TFPDocPackages }
function TFPDocPackages.GetP(AIndex : Integer): TFPDocPackage;
begin
Result:=TFPDocPackage(Items[AIndex]);
end;
procedure TFPDocPackages.SetP(AIndex : Integer; const AValue: TFPDocPackage);
begin
Items[AIndex]:=AValue;
end;
function TFPDocPackages.IndexOfPackage(const AName: String): Integer;
begin
Result:=Count-1;
While (Result>=0) and (CompareText(GetP(Result).Name,AName)<>0) do
Dec(Result)
end;
function TFPDocPackages.FindPackage(const AName: String): TFPDOcPackage;
Var
I : Integer;
begin
I:=IndexOfPackage(AName);
If (I=-1) then
Result:=Nil
else
Result:=GetP(I);
end;
{ TFPDocPackage }
constructor TFPDocPackage.Create(ACollection: TCollection);
begin
inherited Create(ACollection);
FImports:=TStringList.Create;
FDescriptions:=TStringList.Create;
FInputs:=TStringList.Create;
end;
destructor TFPDocPackage.destroy;
begin
FreeAndNil(FDescriptions);
FreeAndNil(FIMports);
FreeAndNil(FinPuts);
inherited destroy;
end;
procedure TFPDocPackage.Assign(Source: TPersistent);
Var
P : TFPDocPackage;
begin
If Source is TFPDocPackage then
begin
P:=Source as TFPDocPackage;
Fname:=P.Name;
FContent:=P.ContentFile;
FImports.Assign(P.Imports);
FInputs.Assign(P.Inputs);
FDescriptions.Assign(P.Descriptions);
end
else
inherited Assign(Source);
end;
end.

View File

@ -0,0 +1,235 @@
unit fpdocxmlopts;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, fpdocproj, dom;
Type
{ TXMLFPocOptions }
{ TXMLFPDocOptions }
TXMLFPDocOptions = Class(TComponent)
Protected
Procedure Error(Const Msg : String);
Procedure Error(Const Fmt : String; Args : Array of Const);
Procedure LoadPackage(APackage : TFPDocPackage; E : TDOMElement); virtual;
Procedure LoadPackages(Packages : TFPDocPackages; E : TDOMElement);
Procedure LoadEngineOptions(Options : TEngineOptions; E : TDOMElement); virtual;
Public
Procedure LoadOptionsFromFile(AProject : TFPDocProject; Const AFileName : String);
Procedure LoadFromXML(AProject : TFPDocProject; XML : TXMLDocument); virtual;
end;
EXMLFPdoc = Class(Exception);
implementation
Uses XMLRead;
Resourcestring
SErrInvalidRootNode = 'Invalid options root node: Got "%s", expected "docproject"';
SErrNoPackagesNode = 'No "packages" node found in docproject';
SErrNoInputFile = 'unit tag without file attribute found';
SErrNoDescrFile = 'description tag without file attribute';
{ TXMLFPDocOptions }
Function IndexOfString(S : String; List : Array of string) : Integer;
begin
S:=UpperCase(S);
Result:=High(List);
While (Result>=0) and (S<>UpperCase(List[Result])) do
Dec(Result);
end;
procedure TXMLFPDocOptions.Error(Const Msg: String);
begin
Raise EXMLFPDoc.Create(Msg);
end;
procedure TXMLFPDocOptions.Error(const Fmt: String; Args: array of const);
begin
Raise EXMLFPDoc.CreateFmt(Fmt,Args);
end;
procedure TXMLFPDocOptions.LoadPackage(APackage: TFPDocPackage; E: TDOMElement);
Function LoadInput(I : TDOMElement) : String;
Var
S : String;
begin
Result:=I['file'];
If (Result='') then
Error(SErrNoInputFile);
S:=I['options'];
if (S<>'') then
Result:=S+' '+Result;
end;
Function LoadDescription(I : TDOMElement) : String;
Var
S : String;
begin
Result:=I['file'];
If (Result='') then
Error(SErrNoDescrFile);
end;
Const
OpCount = 0;
OpNames : Array[0..OpCount] of string
= ('');
Var
N,S : TDOMNode;
O : TDomElement;
begin
APackage.Name:=E['name'];
APackage.output:=E['output'];
APackage.ContentFile:=E['contentfile'];
N:=E.FirstChild;
While (N<>Nil) do
begin
If (N.NodeType=ELEMENT_NODE) then
begin
O:=N as TDOMElement;
If (O.NodeName='units') then
begin
S:=O.FirstChild;
While (S<>Nil) do
begin
If (S.NodeType=Element_Node) and (S.NodeName='unit') then
APackage.Inputs.add(LoadInput(S as TDomElement));
S:=S.NextSibling;
end;
end
else If (O.NodeName='descriptions') then
begin
S:=O.FirstChild;
While (S<>Nil) do
begin
If (S.NodeType=Element_Node) and (S.NodeName='description') then
APackage.Descriptions.add(LoadDescription(S as TDomElement));
S:=S.NextSibling;
end;
end
end;
N:=N.NextSibling;
end;
end;
procedure TXMLFPDocOptions.LoadPackages(Packages: TFPDocPackages; E: TDOMElement
);
Var
N : TDOMNode;
begin
N:=E.FirstChild;
While (N<>Nil) do
begin
If (N.NodeName='package') and (N.NodeType=ELEMENT_NODE) then
LoadPackage(Packages.Add as TFPDocPackage, N as TDOMElement);
N:=N.NextSibling;
end;
end;
procedure TXMLFPDocOptions.LoadEngineOptions(Options: TEngineOptions;
E: TDOMElement);
Function TrueValue(V : String) : Boolean;
begin
V:=LowerCase(V);
Result:=(v='true') or (v='1') or (v='yes');
end;
Const
NCount = 10;
ONames : Array[0..NCount] of string
= ('hide-protected','warn-no-node','show-private',
'stop-on-parser-error', 'ostarget','cputarget',
'mo-dir','parse-impl','format', 'language',
'package');
Var
O : TDOMnode;
N,V : String;
begin
O:=E.FirstChild;
While (O<>Nil) do
begin
If (O.NodeType=Element_NODE) and (O.NodeName='option') then
begin
N:=LowerCase(TDOMElement(o)['name']);
V:=TDOMElement(o)['value'];
Case IndexOfString(N,ONames) of
0 : Options.HideProtected:=TrueValue(v);
1 : Options.WarnNoNode:=TrueValue(v);
2 : Options.ShowPrivate:=TrueValue(v);
3 : Options.StopOnParseError:=TrueValue(v);
4 : Options.ostarget:=v;
5 : Options.cputarget:=v;
6 : Options.MoDir:=V;
7 : Options.InterfaceOnly:=Not TrueValue(V);
8 : Options.Backend:=V;
9 : Options.Language:=v;
10 : Options.DefaultPackageName:=V;
else
Options.BackendOptions.add('--'+n);
Options.BackendOptions.add(v);
end;
end;
O:=O.NextSibling
end;
end;
procedure TXMLFPDocOptions.LoadOptionsFromFile(AProject: TFPDocProject;
const AFileName: String);
Var
XML : TXMLDocument;
begin
XMLRead.ReadXMLFile(XML,AFileName);
try
LoadFromXML(AProject,XML);
finally
FreeAndNil(XML);
end;
end;
procedure TXMLFPDocOptions.LoadFromXML(AProject: TFPDocProject;
XML: TXMLDocument);
Var
E : TDOMElement;
N : TDomNode;
begin
E:=XML.DocumentElement;
if (E.NodeName<>'docproject') then
Error(SErrInvalidRootNode,[E.NodeName]);
N:=E.FindNode('packages');
If (N=Nil) or (N.NodeType<>ELEMENT_NODE) then
Error(SErrNoPackagesNode);
LoadPackages(AProject.Packages,N as TDomElement);
N:=E.FindNode('options');
If (N<>Nil) and (N.NodeType=ELEMENT_NODE) then
LoadEngineOptions(AProject.Options,N as TDOMElement);
end;
end.

View File

@ -0,0 +1,29 @@
<docproject>
<packages>
<!-- Multiple packages can be entered.
If only one is specified, it is selected.
"name" is a mandatory attribute
a "units" tag is required, and a "descriptions" tag as well
-->
<package name="fpdoc" output="docdir" contentfile="fpdoc.cnt">
<!-- All input files, one "unit" tag per unit -->
<units>
<!-- "file" is a mandatory attribute, "options" is not mandatory -->
<unit file="dglobals.pp" options="-S2"/>
</units>
<descriptions>
<!-- Description files here. One "description" tag per file.
"file" is the only mandatory attribute -->
<description file="dglobals.xml"/>
</descriptions>
</package>
</packages>
<options>
<!-- All command-line options can be specified here with the same name
and value as on the actual command-line. Boolean options must have
a value of 'true', '1' or 'yes' -->
<option name="format" value="html"/>
<option name="hide-protected" value="true"/>
<option name="footer-date" value="yyyy-mm-dd"/>
</options>
</docproject>