mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-26 10:39:40 +02:00
examples: started repair function for fpdoc fragments
git-svn-id: trunk@28412 -
This commit is contained in:
parent
c2e17f304b
commit
acc881191b
4
.gitattributes
vendored
4
.gitattributes
vendored
@ -3189,6 +3189,10 @@ examples/fontenum/fontenumeration.lpr svneol=native#text/pascal
|
|||||||
examples/fontenum/mainunit.lfm svneol=native#text/plain
|
examples/fontenum/mainunit.lfm svneol=native#text/plain
|
||||||
examples/fontenum/mainunit.lrs svneol=native#text/pascal
|
examples/fontenum/mainunit.lrs svneol=native#text/pascal
|
||||||
examples/fontenum/mainunit.pas svneol=native#text/pascal
|
examples/fontenum/mainunit.pas svneol=native#text/pascal
|
||||||
|
examples/fpdocrepair/RepairFPDoc.lpi svneol=native#text/plain
|
||||||
|
examples/fpdocrepair/RepairFPDoc.lpr svneol=native#text/plain
|
||||||
|
examples/fpdocrepair/mainunit.lfm svneol=native#text/plain
|
||||||
|
examples/fpdocrepair/mainunit.pas svneol=native#text/pascal
|
||||||
examples/gridexamples/grid_semaphor/TSemaphorDBGrid.xpm -text svneol=native#image/x-xpixmap
|
examples/gridexamples/grid_semaphor/TSemaphorDBGrid.xpm -text svneol=native#image/x-xpixmap
|
||||||
examples/gridexamples/grid_semaphor/example/project1.lpi svneol=native#text/plain
|
examples/gridexamples/grid_semaphor/example/project1.lpi svneol=native#text/plain
|
||||||
examples/gridexamples/grid_semaphor/example/project1.lpr svneol=native#text/pascal
|
examples/gridexamples/grid_semaphor/example/project1.lpr svneol=native#text/pascal
|
||||||
|
86
examples/fpdocrepair/RepairFPDoc.lpi
Normal file
86
examples/fpdocrepair/RepairFPDoc.lpi
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<CONFIG>
|
||||||
|
<ProjectOptions>
|
||||||
|
<Version Value="9"/>
|
||||||
|
<General>
|
||||||
|
<SessionStorage Value="InIDEConfig"/>
|
||||||
|
<MainUnit Value="0"/>
|
||||||
|
<ResourceType Value="res"/>
|
||||||
|
</General>
|
||||||
|
<i18n>
|
||||||
|
<EnableI18N LFM="False"/>
|
||||||
|
</i18n>
|
||||||
|
<VersionInfo>
|
||||||
|
<StringTable ProductVersion=""/>
|
||||||
|
</VersionInfo>
|
||||||
|
<BuildModes Count="1">
|
||||||
|
<Item1 Name="Default" Default="True"/>
|
||||||
|
</BuildModes>
|
||||||
|
<PublishOptions>
|
||||||
|
<Version Value="2"/>
|
||||||
|
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
|
||||||
|
<ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
|
||||||
|
</PublishOptions>
|
||||||
|
<RunParams>
|
||||||
|
<local>
|
||||||
|
<FormatVersion Value="1"/>
|
||||||
|
<LaunchingApplication PathPlusParams="/usr/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
|
||||||
|
</local>
|
||||||
|
</RunParams>
|
||||||
|
<RequiredPackages Count="1">
|
||||||
|
<Item1>
|
||||||
|
<PackageName Value="LCL"/>
|
||||||
|
</Item1>
|
||||||
|
</RequiredPackages>
|
||||||
|
<Units Count="2">
|
||||||
|
<Unit0>
|
||||||
|
<Filename Value="RepairFPDoc.lpr"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<UnitName Value="RepairFPDoc"/>
|
||||||
|
</Unit0>
|
||||||
|
<Unit1>
|
||||||
|
<Filename Value="mainunit.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<ComponentName Value="Form1"/>
|
||||||
|
<ResourceBaseClass Value="Form"/>
|
||||||
|
<UnitName Value="MainUnit"/>
|
||||||
|
</Unit1>
|
||||||
|
</Units>
|
||||||
|
</ProjectOptions>
|
||||||
|
<CompilerOptions>
|
||||||
|
<Version Value="9"/>
|
||||||
|
<Target>
|
||||||
|
<Filename Value="RepairFPDoc"/>
|
||||||
|
</Target>
|
||||||
|
<SearchPaths>
|
||||||
|
<IncludeFiles Value="$(ProjOutDir)"/>
|
||||||
|
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
|
||||||
|
</SearchPaths>
|
||||||
|
<Linking>
|
||||||
|
<Options>
|
||||||
|
<Win32>
|
||||||
|
<GraphicApplication Value="True"/>
|
||||||
|
</Win32>
|
||||||
|
</Options>
|
||||||
|
</Linking>
|
||||||
|
<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>
|
18
examples/fpdocrepair/RepairFPDoc.lpr
Normal file
18
examples/fpdocrepair/RepairFPDoc.lpr
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
program RepairFPDoc;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
uses
|
||||||
|
{$IFDEF UNIX}{$IFDEF UseCThreads}
|
||||||
|
cthreads,
|
||||||
|
{$ENDIF}{$ENDIF}
|
||||||
|
Interfaces, // this includes the LCL widgetset
|
||||||
|
Forms, MainUnit
|
||||||
|
{ you can add units after this };
|
||||||
|
|
||||||
|
begin
|
||||||
|
Application.Initialize;
|
||||||
|
Application.CreateForm(TForm1, Form1);
|
||||||
|
Application.Run;
|
||||||
|
end.
|
||||||
|
|
9
examples/fpdocrepair/mainunit.lfm
Normal file
9
examples/fpdocrepair/mainunit.lfm
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
object Form1: TForm1
|
||||||
|
Left = 275
|
||||||
|
Height = 240
|
||||||
|
Top = 250
|
||||||
|
Width = 320
|
||||||
|
Caption = 'Form1'
|
||||||
|
OnCreate = FormCreate
|
||||||
|
LCLVersion = '0.9.29'
|
||||||
|
end
|
388
examples/fpdocrepair/mainunit.pas
Normal file
388
examples/fpdocrepair/mainunit.pas
Normal file
@ -0,0 +1,388 @@
|
|||||||
|
unit MainUnit;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, LCLProc,
|
||||||
|
contnrs;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
{ TForm1 }
|
||||||
|
|
||||||
|
TForm1 = class(TForm)
|
||||||
|
procedure FormCreate(Sender: TObject);
|
||||||
|
private
|
||||||
|
public
|
||||||
|
procedure TestComment;
|
||||||
|
procedure TestInvalidCharacters;
|
||||||
|
function Test(Title, Fragment, FixedFragment: string): boolean;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
Form1: TForm1;
|
||||||
|
|
||||||
|
procedure FixFPDocFragment(var Fragment: string; Fix: boolean;
|
||||||
|
out ErrorList: TObjectList);
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
{$R *.lfm}
|
||||||
|
|
||||||
|
type
|
||||||
|
TFPDocFragmentError = class
|
||||||
|
public
|
||||||
|
ErrorPos: integer;
|
||||||
|
Msg: string;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure FixFPDocFragment(var Fragment: string; Fix: boolean;
|
||||||
|
out ErrorList: TObjectList);
|
||||||
|
{ - Fix all tags to lowercase to reduce svn commits
|
||||||
|
- remove unneeded spaces
|
||||||
|
< b => <b
|
||||||
|
b > => b>
|
||||||
|
a b => a b
|
||||||
|
- auto close comments
|
||||||
|
- remove #0 from comments
|
||||||
|
- auto close unclosed tags
|
||||||
|
- fix & without ;
|
||||||
|
- convert special characters to &x;
|
||||||
|
- fix unclosed attribute values
|
||||||
|
}
|
||||||
|
type
|
||||||
|
TStackItemTyp = (
|
||||||
|
sitTag,
|
||||||
|
sitComment
|
||||||
|
);
|
||||||
|
TStackItem = record
|
||||||
|
Typ: TStackItemTyp;
|
||||||
|
StartPos: integer;
|
||||||
|
NameStartPos: integer;
|
||||||
|
NameEndPos: integer;
|
||||||
|
EndPos: integer;
|
||||||
|
end;
|
||||||
|
PStackItem = ^TStackItem;
|
||||||
|
var
|
||||||
|
Stack: PStackItem;
|
||||||
|
Capacity: integer;
|
||||||
|
Top: integer;
|
||||||
|
TopItem: PStackItem;
|
||||||
|
p: PChar;
|
||||||
|
|
||||||
|
function Rel(pt: PChar): integer;
|
||||||
|
begin
|
||||||
|
Result:=pt-PChar(Fragment)+1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function LineCol(pt: integer): string;
|
||||||
|
var
|
||||||
|
Line: Integer;
|
||||||
|
Col: Integer;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
Line:=1;
|
||||||
|
Col:=1;
|
||||||
|
if pt>length(Fragment) then pt:=length(Fragment)+1;
|
||||||
|
i:=1;
|
||||||
|
while i<pt do begin
|
||||||
|
case Fragment[i] of
|
||||||
|
#10,#13:
|
||||||
|
begin
|
||||||
|
inc(Line);
|
||||||
|
inc(i);
|
||||||
|
if (i<=length(Fragment)) and (Fragment[i] in [#10,#13])
|
||||||
|
and (Fragment[i-1]<>Fragment[i])
|
||||||
|
then
|
||||||
|
inc(i);
|
||||||
|
Col:=1;
|
||||||
|
end;
|
||||||
|
else
|
||||||
|
inc(Col);
|
||||||
|
end;
|
||||||
|
inc(i);
|
||||||
|
end;
|
||||||
|
Result:=IntToStr(Line)+','+IntToStr(Col);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Error(ErrorPos: PChar; ErrorMsg: string);
|
||||||
|
var
|
||||||
|
NewError: TFPDocFragmentError;
|
||||||
|
begin
|
||||||
|
debugln(['Error ',ErrorMsg]);
|
||||||
|
if ErrorList=nil then
|
||||||
|
ErrorList:=TObjectList.Create(true);
|
||||||
|
NewError:=TFPDocFragmentError.Create;
|
||||||
|
NewError.ErrorPos:=Rel(ErrorPos);
|
||||||
|
NewError.Msg:=ErrorMsg;
|
||||||
|
ErrorList.Add(NewError);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Replace(StartPos, Len: integer; const NewTxt: string);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
Item: PStackItem;
|
||||||
|
Diff: Integer;
|
||||||
|
OldP: integer;
|
||||||
|
begin
|
||||||
|
OldP:=Rel(p);
|
||||||
|
Fragment:=copy(Fragment,1,StartPos-1)+NewTxt
|
||||||
|
+copy(Fragment,StartPos+Len,length(Fragment));
|
||||||
|
Diff:=length(NewTxt)-Len;
|
||||||
|
if Diff<>0 then begin
|
||||||
|
// adjust positions
|
||||||
|
if OldP>StartPos then
|
||||||
|
inc(OldP,Diff);
|
||||||
|
for i:=0 to Top do begin
|
||||||
|
Item:=@Stack[i];
|
||||||
|
if Item^.StartPos>StartPos then inc(Item^.StartPos,Diff);
|
||||||
|
if Item^.EndPos>StartPos then inc(Item^.EndPos,Diff);
|
||||||
|
if Item^.NameStartPos>StartPos then inc(Item^.NameStartPos,Diff);
|
||||||
|
if Item^.NameEndPos>StartPos then inc(Item^.NameEndPos,Diff);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
p:=PChar(Fragment)+OldP-1;
|
||||||
|
debugln(['Replace ',dbgstr(copy(Fragment,1,Rel(p)-1)),'|',dbgstr(copy(Fragment,Rel(p),length(Fragment)))]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure HandleSpecialChar;
|
||||||
|
var
|
||||||
|
c: Integer;
|
||||||
|
begin
|
||||||
|
c:=ord(p^);
|
||||||
|
if Fix then begin
|
||||||
|
case p^ of
|
||||||
|
#0..#31,#127:
|
||||||
|
// delete
|
||||||
|
Replace(Rel(p),1,'');
|
||||||
|
'<': Replace(Rel(p),1,'<');
|
||||||
|
'>': Replace(Rel(p),1,'>');
|
||||||
|
'&': Replace(Rel(p),1,'&');
|
||||||
|
'''': Replace(Rel(p),1,''');
|
||||||
|
'"': Replace(Rel(p),1,'"');
|
||||||
|
else
|
||||||
|
// convert
|
||||||
|
Replace(Rel(p),1,'&'+IntToStr(c)+';');
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
// skip
|
||||||
|
Error(p,'invalid character #'+IntToStr(c));
|
||||||
|
inc(p);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Push(Typ: TStackItemTyp);
|
||||||
|
begin
|
||||||
|
inc(Top);
|
||||||
|
if Top=Capacity then begin
|
||||||
|
inc(Capacity);
|
||||||
|
ReAllocMem(Stack,SizeOf(TStackItem)*Capacity);
|
||||||
|
end;
|
||||||
|
TopItem:=@Stack[Top];
|
||||||
|
FillByte(TopItem^,SizeOf(TStackItem),0);
|
||||||
|
TopItem^.Typ:=Typ;
|
||||||
|
TopItem^.StartPos:=p-PChar(Fragment);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Pop;
|
||||||
|
begin
|
||||||
|
if Top<0 then raise Exception.Create('bug');
|
||||||
|
dec(Top);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure ParseComment;
|
||||||
|
begin
|
||||||
|
// comment
|
||||||
|
Push(sitComment);
|
||||||
|
inc(p,4);
|
||||||
|
// parse comment
|
||||||
|
repeat
|
||||||
|
if p^ in [#0..#8,#11,#12,#14..#31,#127] then begin
|
||||||
|
// invalid character in comment => delete
|
||||||
|
if (p^=#0) and (p-PChar(Fragment)=length(Fragment)) then
|
||||||
|
begin
|
||||||
|
// reached end of fragment => close comment
|
||||||
|
if Fix then begin
|
||||||
|
Replace(Rel(p),0,'-->');
|
||||||
|
inc(p,3);
|
||||||
|
end else
|
||||||
|
Error(p,'comment end not found, start at '+LineCol(TopItem^.StartPos));
|
||||||
|
break;
|
||||||
|
end else begin
|
||||||
|
// invalid #0 character in comment => delete
|
||||||
|
if Fix then
|
||||||
|
Replace(Rel(p),1,'')
|
||||||
|
else begin
|
||||||
|
Error(p,'invalid character');
|
||||||
|
inc(p);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end else if (p^='-') and (p[1]='-') and (p[2]='>') then
|
||||||
|
begin
|
||||||
|
// comment end found
|
||||||
|
inc(p,3);
|
||||||
|
break;
|
||||||
|
end else
|
||||||
|
inc(p);
|
||||||
|
until false;
|
||||||
|
Pop;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure ParseAmpersand;
|
||||||
|
var
|
||||||
|
AmpPos: PChar;
|
||||||
|
i: Integer;
|
||||||
|
NeedLowercase: PChar;
|
||||||
|
len: integer;
|
||||||
|
begin
|
||||||
|
AmpPos:=p;
|
||||||
|
// & or &name; or &decimal;
|
||||||
|
case p[1] of
|
||||||
|
'0'..'9':
|
||||||
|
begin
|
||||||
|
// decimal number
|
||||||
|
inc(p);
|
||||||
|
i:=ord(p^)-ord('0');
|
||||||
|
while p^ in ['0'..'9'] do
|
||||||
|
begin
|
||||||
|
i:=i+10+ord(p^)-ord('0');
|
||||||
|
if i>$10FFFF then
|
||||||
|
break;
|
||||||
|
inc(p);
|
||||||
|
end;
|
||||||
|
if p^=';' then
|
||||||
|
begin
|
||||||
|
// ok
|
||||||
|
inc(p);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
'a'..'z','A'..'Z':
|
||||||
|
begin
|
||||||
|
// name
|
||||||
|
inc(p);
|
||||||
|
NeedLowercase:=nil;
|
||||||
|
while p^ in ['a'..'z','A'..'Z'] do begin
|
||||||
|
if (NeedLowercase=nil) and (p^ in ['A'..'Z']) then
|
||||||
|
NeedLowercase:=p;
|
||||||
|
inc(p);
|
||||||
|
end;
|
||||||
|
if p^=';' then begin
|
||||||
|
if NeedLowercase<>nil then begin
|
||||||
|
if Fix then begin
|
||||||
|
len:=(p-AmpPos)-1;
|
||||||
|
Replace(Rel(AmpPos)+1,len,lowercase(copy(Fragment,Rel(AmpPos)+1,len)));
|
||||||
|
end else begin
|
||||||
|
Error(NeedLowercase,'special character name is not lower case');
|
||||||
|
inc(p);
|
||||||
|
end;
|
||||||
|
end else begin
|
||||||
|
// ok
|
||||||
|
inc(p);
|
||||||
|
end;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
p:=AmpPos;
|
||||||
|
// invalid character => convert or skip
|
||||||
|
HandleSpecialChar;
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
ErrorList:=nil;
|
||||||
|
if Fragment='' then exit;
|
||||||
|
Top:=-1;
|
||||||
|
Capacity:=0;
|
||||||
|
Stack:=nil;
|
||||||
|
try
|
||||||
|
p:=PChar(Fragment);
|
||||||
|
repeat
|
||||||
|
case p^ of
|
||||||
|
#0..#8,#11,#12,#14..#31,#127:
|
||||||
|
begin
|
||||||
|
if (p^=#0) and (p-PChar(Fragment)=length(Fragment)) then
|
||||||
|
begin
|
||||||
|
// reached end of fragment
|
||||||
|
break;
|
||||||
|
end else begin
|
||||||
|
// invalid character => convert or skip
|
||||||
|
HandleSpecialChar;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
'<':
|
||||||
|
begin
|
||||||
|
// comment, tag or 'lower than'
|
||||||
|
if (p[1]='!') and (p[2]='-') and (p[3]='-') then
|
||||||
|
// comment
|
||||||
|
ParseComment
|
||||||
|
else begin
|
||||||
|
// invalid character => convert or skip
|
||||||
|
HandleSpecialChar;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
'>':
|
||||||
|
// invalid character => convert or skip
|
||||||
|
HandleSpecialChar;
|
||||||
|
'&':
|
||||||
|
ParseAmpersand;
|
||||||
|
else
|
||||||
|
inc(p);
|
||||||
|
end;
|
||||||
|
until false;
|
||||||
|
if Top>=0 then begin
|
||||||
|
// ToDo: fix unclosed tags
|
||||||
|
debugln(['FixFPDocFragment ToDo: fix unclosed tags']);
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
ReAllocMem(Stack,0);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TForm1 }
|
||||||
|
|
||||||
|
procedure TForm1.FormCreate(Sender: TObject);
|
||||||
|
begin
|
||||||
|
TestComment;
|
||||||
|
TestInvalidCharacters;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TForm1.TestComment;
|
||||||
|
begin
|
||||||
|
Test('close comment','<!--','<!---->');
|
||||||
|
Test('close comment and delete invalid char','<!--null'#0#1#2'comment','<!--nullcomment-->');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TForm1.TestInvalidCharacters;
|
||||||
|
begin
|
||||||
|
Test('delete special characters','A'#0'B'#1#127,'AB');
|
||||||
|
Test('replace tag characters','LT<GT>AMP&','LT<GT>AMP&');
|
||||||
|
Test('lower case special characters','<','<');
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TForm1.Test(Title, Fragment, FixedFragment: string): boolean;
|
||||||
|
var
|
||||||
|
s: String;
|
||||||
|
ErrorList: TObjectList;
|
||||||
|
begin
|
||||||
|
Result:=true;
|
||||||
|
try
|
||||||
|
s:=Fragment;
|
||||||
|
FixFPDocFragment(s,true,ErrorList);
|
||||||
|
if s<>FixedFragment then begin
|
||||||
|
Result:=false;
|
||||||
|
debugln(['failed: ',Title]);
|
||||||
|
debugln([' fragment: '+DbgStr(Fragment)]);
|
||||||
|
debugln([' should: '+DbgStr(FixedFragment)]);
|
||||||
|
debugln([' result: '+DbgStr(s)]);
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
ErrorList.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user