{ Copyright (C) 2006 Mattias Gaertner This source is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. A copy of the GNU General Public License is available on the World Wide Web at . You can also obtain it by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. } unit H2PasConvert; {$mode objfpc}{$H+} interface uses Classes, SysUtils, LCLProc, LResources, LazConfigStorage, XMLPropStorage, Forms, Controls, Dialogs, FileUtil, FileProcs, AvgLvlTree, // CodeTools BasicCodeTools, // IDEIntf TextTools, IDEExternToolIntf, IDEDialogs, LazIDEIntf, SrcEditorIntf, IDEMsgIntf, IDETextConverter; type { TRemoveCPlusPlusExternCTool } TRemoveCPlusPlusExternCTool = class(TCustomTextConverterTool) public class function ClassDescription: string; override; function Execute(aText: TIDETextConverter): TModalResult; override; end; { TRemoveEmptyCMacrosTool } TRemoveEmptyCMacrosTool = class(TCustomTextConverterTool) public class function ClassDescription: string; override; function Execute(aText: TIDETextConverter): TModalResult; override; end; { TReplaceEdgedBracketPairWithStar } TReplaceEdgedBracketPairWithStar = class(TCustomTextReplaceTool) public class function ClassDescription: string; override; constructor Create(TheOwner: TComponent); override; end; { TReplace0PointerWithNULL } TReplaceMacro0PointerWithNULL = class(TCustomTextConverterTool) public class function ClassDescription: string; override; function Execute(aText: TIDETextConverter): TModalResult; override; end; { TReplaceUnitFilenameWithUnitName } TReplaceUnitFilenameWithUnitName = class(TCustomTextReplaceTool) public class function ClassDescription: string; override; constructor Create(TheOwner: TComponent); override; end; { TRemoveSystemTypes } TRemoveSystemTypes = class(TCustomTextConverterTool) public class function ClassDescription: string; override; function Execute(aText: TIDETextConverter): TModalResult; override; end; { TRemoveRedefinedPointerTypes } TRemoveRedefinedPointerTypes = class(TCustomTextConverterTool) public class function ClassDescription: string; override; function Execute(aText: TIDETextConverter): TModalResult; override; end; { TRemoveEmptyTypeVarConstSections } TRemoveEmptyTypeVarConstSections = class(TCustomTextConverterTool) public class function ClassDescription: string; override; function Execute(aText: TIDETextConverter): TModalResult; override; end; TH2PasProject = class; TH2PasConverter = class; { TH2PasFile } TH2PasFile = class(TPersistent) private FEnabled: boolean; FFilename: string; FModified: boolean; FProject: TH2PasProject; procedure SetEnabled(const AValue: boolean); procedure SetFilename(const AValue: string); procedure SetModified(const AValue: boolean); procedure SetProject(const AValue: TH2PasProject); public constructor Create; destructor Destroy; override; procedure Clear; procedure Assign(Source: TPersistent); override; function IsEqual(AFile: TH2PasFile): boolean; procedure Load(Config: TConfigStorage); procedure Save(Config: TConfigStorage); function GetOutputFilename: string; function GetOutputDirectory: string; function GetOutputExtension: string; function GetH2PasParameters(const InputFilename: string = ''): string; public property Project: TH2PasProject read FProject write SetProject; property Filename: string read FFilename write SetFilename; property Enabled: boolean read FEnabled write SetEnabled; property Modified: boolean read FModified write SetModified; end; { TH2PasProject } TH2PasProject = class(TPersistent) private FBaseDir: string; FCHeaderFiles: TFPList;// list of TH2PasFile FCompactOutputmode: boolean; FConstantsInsteadOfEnums: boolean; FConverter: TH2PasConverter; FCreateIncludeFile: boolean; FFilename: string; FIsVirtual: boolean; FLibname: string; FModified: boolean; FOutputDirectory: string; FOutputExt: string; FPackAllRecords: boolean; FPalmOSSYSTrap: boolean; FPforPointers: boolean; FPostH2PasTools: TComponent; FPreH2PasTools: TComponent; FStripComments: boolean; FStripCommentsAndInfo: boolean; FTforTypedefs: boolean; FTforTypedefsRemoveUnderscore: boolean; FUseExternal: boolean; FUseExternalLibname: boolean; FUseProcVarsForImport: boolean; FVarParams: boolean; FWin32Header: boolean; FUseCTypes : boolean; function GetCHeaderFileCount: integer; function GetCHeaderFiles(Index: integer): TH2PasFile; procedure InternalAddCHeaderFile(AFile: TH2PasFile); procedure InternalRemoveCHeaderFile(AFile: TH2PasFile); procedure SetCompactOutputmode(const AValue: boolean); procedure SetConstantsInsteadOfEnums(const AValue: boolean); procedure SetCreateIncludeFile(const AValue: boolean); procedure SetFilename(const AValue: string); procedure SetLibname(const AValue: string); procedure SetModified(const AValue: boolean); procedure FilenameChanged; procedure SetOutputDirectory(const AValue: string); procedure SetOutputExt(const AValue: string); procedure SetPackAllRecords(const AValue: boolean); procedure SetPalmOSSYSTrap(const AValue: boolean); procedure SetPforPointers(const AValue: boolean); procedure SetStripComments(const AValue: boolean); procedure SetStripCommentsAndInfo(const AValue: boolean); procedure SetTforTypedefs(const AValue: boolean); procedure SetTforTypedefsRemoveUnderscore(const AValue: boolean); procedure SetUseExternal(const AValue: boolean); procedure SetUseExternalLibname(const AValue: boolean); procedure SetUseProcVarsForImport(const AValue: boolean); procedure SetVarParams(const AValue: boolean); procedure SetWin32Header(const AValue: boolean); procedure SetUseCTypes(const AValue: boolean); public constructor Create; destructor Destroy; override; procedure Clear(AddDefaults: boolean); procedure Assign(Source: TPersistent); override; function IsEqual(AProject: TH2PasProject): boolean; procedure Load(Config: TConfigStorage); procedure Save(Config: TConfigStorage); procedure LoadFromFile(const AFilename: string); procedure SaveToFile(const AFilename: string); procedure AddFiles(List: TStrings); procedure DeleteFiles(List: TStrings); function CHeaderFileWithFilename(const AFilename: string): TH2PasFile; function CHeaderFileIndexWithFilename(const AFilename: string): integer; function ShortenFilename(const AFilename: string): string; function LongenFilename(const AFilename: string): string; function NormalizeFilename(const AFilename: string): string; function HasEnabledFiles: boolean; procedure AddDefaultPreH2PasTools; procedure AddDefaultPostH2PasTools; public property CHeaderFileCount: integer read GetCHeaderFileCount; property CHeaderFiles[Index: integer]: TH2PasFile read GetCHeaderFiles; property Modified: boolean read FModified write SetModified; property Filename: string read FFilename write SetFilename; property BaseDir: string read FBaseDir; property IsVirtual: boolean read FIsVirtual; property Converter: TH2PasConverter read FConverter; property PreH2PasTools: TComponent read FPreH2PasTools; property PostH2PasTools: TComponent read FPostH2PasTools; // h2pas options property ConstantsInsteadOfEnums: boolean read FConstantsInsteadOfEnums write SetConstantsInsteadOfEnums; property CompactOutputmode: boolean read FCompactOutputmode write SetCompactOutputmode; property CreateIncludeFile: boolean read FCreateIncludeFile write SetCreateIncludeFile; property Libname: string read FLibname write SetLibname; property OutputExt: string read FOutputExt write SetOutputExt; property PalmOSSYSTrap: boolean read FPalmOSSYSTrap write SetPalmOSSYSTrap; property PforPointers: boolean read FPforPointers write SetPforPointers; property PackAllRecords: boolean read FPackAllRecords write SetPackAllRecords; property StripComments: boolean read FStripComments write SetStripComments; property StripCommentsAndInfo: boolean read FStripCommentsAndInfo write SetStripCommentsAndInfo; property TforTypedefs: boolean read FTforTypedefs write SetTforTypedefs; property TforTypedefsRemoveUnderscore: boolean read FTforTypedefsRemoveUnderscore write SetTforTypedefsRemoveUnderscore; property UseExternal: boolean read FUseExternal write SetUseExternal; property UseExternalLibname: boolean read FUseExternalLibname write SetUseExternalLibname; property UseProcVarsForImport: boolean read FUseProcVarsForImport write SetUseProcVarsForImport; property VarParams: boolean read FVarParams write SetVarParams; property Win32Header: boolean read FWin32Header write SetWin32Header; property UseCTypes: boolean read FUseCTypes write SetUseCTypes; property OutputDirectory: string read FOutputDirectory write SetOutputDirectory; end; { TH2PasTool } TH2PasTool = class(TIDEExternalToolOptions) private FH2PasFile: TH2PasFile; FTargetFilename: string; public property H2PasFile: TH2PasFile read FH2PasFile write FH2PasFile; property TargetFilename: string read FTargetFilename write FTargetFilename; end; { TH2PasConverter } TH2PasConverter = class(TPersistent) private FAutoOpenLastProject: boolean; FExecuting: boolean; Fh2pasFilename: string; FLastUsedFilename: string; FModified: boolean; FProject: TH2PasProject; FProjectHistory: TStrings; FWindowBounds: TRect; function GetCurrentProjectFilename: string; procedure SetAutoOpenLastProject(const AValue: boolean); procedure SetCurrentProjectFilename(const AValue: string); procedure SetProject(const AValue: TH2PasProject); procedure SetProjectHistory(const AValue: TStrings); procedure SetWindowBounds(const AValue: TRect); procedure Seth2pasFilename(const AValue: string); procedure OnParseH2PasLine(Sender: TObject; Line: TIDEScanMessageLine); public constructor Create; destructor Destroy; override; procedure Clear; procedure Assign(Source: TPersistent); override; function IsEqual(AConverter: TH2PasConverter): boolean; procedure Load(Config: TConfigStorage); procedure Save(Config: TConfigStorage); procedure LoadFromFile(const AFilename: string); procedure SaveToFile(const AFilename: string); procedure LoadProject(const Filename: string); procedure SaveProject(const Filename: string); function Execute: TModalResult; function ConvertFile(AFile: TH2PasFile): TModalResult; function GetH2PasFilename: string; function FindH2PasErrorMessage: integer; function GetH2PasErrorPostion(const Line: string; out aFilename: string; out LineNumber, Column: integer): boolean; function FileIsRelated(const aFilename: string): Boolean; public property Project: TH2PasProject read FProject write SetProject; property ProjectHistory: TStrings read FProjectHistory write SetProjectHistory; property CurrentProjectFilename: string read GetCurrentProjectFilename write SetCurrentProjectFilename; property WindowBounds: TRect read FWindowBounds write SetWindowBounds; property AutoOpenLastProject: boolean read FAutoOpenLastProject write SetAutoOpenLastProject; property h2pasFilename: string read Fh2pasFilename write Seth2pasFilename; property Modified: boolean read FModified write FModified; property Executing: boolean read FExecuting; property LastUsedFilename: string read FLastUsedFilename; end; implementation { TH2PasFile } procedure TH2PasFile.SetFilename(const AValue: string); var NewValue: String; begin NewValue:=TrimFilename(AValue); if FFilename=NewValue then exit; FFilename:=NewValue; Modified:=true; end; procedure TH2PasFile.SetEnabled(const AValue: boolean); begin if FEnabled=AValue then exit; FEnabled:=AValue; Modified:=true; end; procedure TH2PasFile.SetModified(const AValue: boolean); begin if FModified=AValue then exit; FModified:=AValue; if FModified and (Project<>nil) then Project.Modified:=true; end; procedure TH2PasFile.SetProject(const AValue: TH2PasProject); begin if FProject=AValue then exit; if FProject<>nil then begin FProject.InternalRemoveCHeaderFile(Self); end; FProject:=AValue; if FProject<>nil then begin FProject.InternalAddCHeaderFile(Self); end; Modified:=true; end; constructor TH2PasFile.Create; begin Clear; end; destructor TH2PasFile.Destroy; begin if FProject<>nil then begin Project:=nil; end; Clear; inherited Destroy; end; procedure TH2PasFile.Clear; begin FEnabled:=true; FFilename:=''; FModified:=false; end; procedure TH2PasFile.Assign(Source: TPersistent); var Src: TH2PasFile; begin if Source is TH2PasFile then begin Src:=TH2PasFile(Source); if not IsEqual(Src) then begin FEnabled:=Src.FEnabled; FFilename:=Src.FFilename; Modified:=true; end; end else begin inherited Assign(Source); end; end; function TH2PasFile.IsEqual(AFile: TH2PasFile): boolean; begin Result:=(CompareFilenames(Filename,AFile.Filename)=0) and (Enabled=AFile.Enabled); end; procedure TH2PasFile.Load(Config: TConfigStorage); begin FEnabled:=Config.GetValue('Enabled/Value',true); FFilename:=Config.GetValue('Filename/Value',''); if Project<>nil then FFilename:=Project.NormalizeFilename(FFilename); FModified:=false; end; procedure TH2PasFile.Save(Config: TConfigStorage); var AFilename: String; begin Config.SetDeleteValue('Enabled/Value',Enabled,true); AFilename:=FFilename; if Project<>nil then AFilename:=Project.ShortenFilename(AFilename); Config.SetDeleteValue('Filename/Value',AFilename,''); FModified:=false; end; function TH2PasFile.GetOutputFilename: string; begin Result:=GetOutputDirectory+ExtractFileNameOnly(Filename)+GetOutputExtension; end; function TH2PasFile.GetOutputDirectory: string; begin Result:=Project.OutputDirectory; if Result='' then Result:=Project.BaseDir; end; function TH2PasFile.GetOutputExtension: string; begin Result:=Project.OutputExt; end; function TH2PasFile.GetH2PasParameters(const InputFilename: string): string; procedure Add(const AnOption: string); begin if Result<>'' then Result:=Result+' '; Result:=Result+AnOption; end; begin Result:=''; if Project.ConstantsInsteadOfEnums then Add('-e'); if Project.CompactOutputmode then Add('-c'); if Project.CreateIncludeFile then Add('-i'); if Project.PalmOSSYSTrap then Add('-x'); if Project.PforPointers then Add('-p'); if Project.PackAllRecords then Add('-pr'); if Project.StripComments then Add('-s'); if Project.StripCommentsAndInfo then Add('-S'); if Project.TforTypedefs then Add('-t'); if Project.TforTypedefsRemoveUnderscore then Add('-T'); if Project.UseExternal then Add('-d'); if Project.UseExternalLibname then Add('-D'); if Project.UseProcVarsForImport then Add('-P'); if Project.VarParams then Add('-v'); if Project.Win32Header then Add('-w'); if Project.UseCTypes then Add('-C'); if Project.Libname<>'' then Add('-l '+Project.Libname); Add('-o '+GetOutputFilename); if InputFilename<>'' then Add(InputFilename) else Add(Filename); end; { TH2PasProject } function TH2PasProject.GetCHeaderFileCount: integer; begin Result:=FCHeaderFiles.Count; end; function TH2PasProject.GetCHeaderFiles(Index: integer): TH2PasFile; begin Result:=TH2PasFile(FCHeaderFiles[Index]); end; procedure TH2PasProject.InternalAddCHeaderFile(AFile: TH2PasFile); begin FCHeaderFiles.Add(AFile); end; procedure TH2PasProject.InternalRemoveCHeaderFile(AFile: TH2PasFile); begin FCHeaderFiles.Remove(AFile); end; procedure TH2PasProject.SetCompactOutputmode(const AValue: boolean); begin if FCompactOutputmode=AValue then exit; FCompactOutputmode:=AValue; Modified:=true; end; procedure TH2PasProject.SetConstantsInsteadOfEnums(const AValue: boolean); begin if FConstantsInsteadOfEnums=AValue then exit; FConstantsInsteadOfEnums:=AValue; Modified:=true; end; procedure TH2PasProject.SetCreateIncludeFile(const AValue: boolean); begin if FCreateIncludeFile=AValue then exit; FCreateIncludeFile:=AValue; Modified:=true; end; procedure TH2PasProject.SetFilename(const AValue: string); var NewValue: String; begin NewValue:=TrimFilename(AValue); if FFilename=NewValue then exit; FFilename:=NewValue; FilenameChanged; Modified:=true; end; procedure TH2PasProject.SetLibname(const AValue: string); begin if FLibname=AValue then exit; FLibname:=AValue; Modified:=true; end; procedure TH2PasProject.SetModified(const AValue: boolean); begin if FModified=AValue then exit; FModified:=AValue; end; procedure TH2PasProject.FilenameChanged; begin FIsVirtual:=(FFilename='') or (not FilenameIsAbsolute(FFilename)); FBaseDir:=ExtractFilePath(FFilename); end; procedure TH2PasProject.SetOutputDirectory(const AValue: string); begin if FOutputDirectory=AValue then exit; FOutputDirectory:=AValue; Modified:=true; end; procedure TH2PasProject.SetOutputExt(const AValue: string); begin if FOutputExt=AValue then exit; FOutputExt:=AValue; Modified:=true; end; procedure TH2PasProject.SetPackAllRecords(const AValue: boolean); begin if FPackAllRecords=AValue then exit; FPackAllRecords:=AValue; Modified:=true; end; procedure TH2PasProject.SetPalmOSSYSTrap(const AValue: boolean); begin if FPalmOSSYSTrap=AValue then exit; FPalmOSSYSTrap:=AValue; Modified:=true; end; procedure TH2PasProject.SetPforPointers(const AValue: boolean); begin if FPforPointers=AValue then exit; FPforPointers:=AValue; Modified:=true; end; procedure TH2PasProject.SetStripComments(const AValue: boolean); begin if FStripComments=AValue then exit; FStripComments:=AValue; Modified:=true; end; procedure TH2PasProject.SetStripCommentsAndInfo(const AValue: boolean); begin if FStripCommentsAndInfo=AValue then exit; FStripCommentsAndInfo:=AValue; Modified:=true; end; procedure TH2PasProject.SetTforTypedefs(const AValue: boolean); begin if FTforTypedefs=AValue then exit; FTforTypedefs:=AValue; Modified:=true; end; procedure TH2PasProject.SetTforTypedefsRemoveUnderscore(const AValue: boolean); begin if FTforTypedefsRemoveUnderscore=AValue then exit; FTforTypedefsRemoveUnderscore:=AValue; Modified:=true; end; procedure TH2PasProject.SetUseExternal(const AValue: boolean); begin if FUseExternal=AValue then exit; FUseExternal:=AValue; Modified:=true; end; procedure TH2PasProject.SetUseExternalLibname(const AValue: boolean); begin if FUseExternalLibname=AValue then exit; FUseExternalLibname:=AValue; Modified:=true; end; procedure TH2PasProject.SetUseProcVarsForImport(const AValue: boolean); begin if FUseProcVarsForImport=AValue then exit; FUseProcVarsForImport:=AValue; Modified:=true; end; procedure TH2PasProject.SetVarParams(const AValue: boolean); begin if FVarParams=AValue then exit; FVarParams:=AValue; Modified:=true; end; procedure TH2PasProject.SetWin32Header(const AValue: boolean); begin if FWin32Header=AValue then exit; FWin32Header:=AValue; Modified:=true; end; procedure TH2PasProject.SetUseCTypes(const AValue: boolean); begin if FUseCTypes=AValue then exit; FUseCTypes:=AValue; Modified:=true; end; constructor TH2PasProject.Create; begin FCHeaderFiles:=TFPList.Create; Clear(true); end; destructor TH2PasProject.Destroy; begin Clear(false); if (Converter<>nil) and (Converter.Project=Self) then Converter.Project:=nil; FreeAndNil(FCHeaderFiles); inherited Destroy; end; procedure TH2PasProject.Clear(AddDefaults: boolean); begin // FFilename is kept FConstantsInsteadOfEnums:=true; FCompactOutputmode:=false; FCreateIncludeFile:=true; FLibname:=''; FOutputExt:='.inc'; FPackAllRecords:=false; FPalmOSSYSTrap:=false; FPforPointers:=true; FStripComments:=false; FStripCommentsAndInfo:=false; FTforTypedefs:=false; FTforTypedefsRemoveUnderscore:=false; FUseExternal:=false; FUseExternalLibname:=true; FUseProcVarsForImport:=false; FVarParams:=false; FWin32Header:=true; FUseCTypes:=false; FOutputDirectory:=''; while CHeaderFileCount>0 do CHeaderFiles[CHeaderFileCount-1].Free; FPreH2PasTools.Free; FPreH2PasTools:=TComponent.Create(nil); FPostH2PasTools.Free; FPostH2PasTools:=TComponent.Create(nil); if AddDefaults then begin AddDefaultPreH2PasTools; AddDefaultPostH2PasTools; end; FModified:=false; end; procedure TH2PasProject.Assign(Source: TPersistent); procedure CopyTools(SrcList: TComponent; var DestList: TComponent); var SrcComponent: TComponent; NewComponent: TObject; i: Integer; begin DestList.Free; DestList:=TComponent.Create(nil); for i:=0 to SrcList.ComponentCount-1 do begin SrcComponent:=SrcList.Components[i]; if SrcComponent is TCustomTextConverterTool then begin NewComponent:= TComponentClass(SrcComponent.ClassType).Create(DestList); TCustomTextConverterTool(NewComponent).Assign(SrcComponent); end; end; end; var Src: TH2PasProject; i: Integer; NewCHeaderFile: TH2PasFile; begin if Source is TH2PasProject then begin Src:=TH2PasProject(Source); if not IsEqual(Src) then begin // FFilename is kept FConstantsInsteadOfEnums:=Src.FConstantsInsteadOfEnums; FCompactOutputmode:=Src.FCompactOutputmode; FCreateIncludeFile:=Src.FCreateIncludeFile; FLibname:=Src.FLibname; FOutputExt:=Src.FOutputExt; FPackAllRecords:=Src.FPackAllRecords; FPalmOSSYSTrap:=Src.FPalmOSSYSTrap; FPforPointers:=Src.FPforPointers; FStripComments:=Src.FStripComments; FStripCommentsAndInfo:=Src.FStripCommentsAndInfo; FTforTypedefs:=Src.FTforTypedefs; FTforTypedefsRemoveUnderscore:=Src.FTforTypedefsRemoveUnderscore; FUseExternal:=Src.FUseExternal; FUseExternalLibname:=Src.FUseExternalLibname; FUseProcVarsForImport:=Src.FUseProcVarsForImport; FVarParams:=Src.FVarParams; FWin32Header:=Src.FWin32Header; FUseCTypes:=Src.FUseCTypes; FOutputDirectory:=Src.FOutputDirectory; Clear(false); for i:=0 to Src.CHeaderFileCount-1 do begin NewCHeaderFile:=TH2PasFile.Create; NewCHeaderFile.Project:=Self; NewCHeaderFile.Assign(Src.CHeaderFiles[i]); end; CopyTools(Src.FPreH2PasTools,FPreH2PasTools); CopyTools(Src.FPostH2PasTools,FPostH2PasTools); Modified:=true; end; end else begin inherited Assign(Source); end; end; function TH2PasProject.IsEqual(AProject: TH2PasProject): boolean; var i: Integer; begin Result:=(AProject.CHeaderFileCount=CHeaderFileCount) and (FConstantsInsteadOfEnums=AProject.FConstantsInsteadOfEnums) and (FCompactOutputmode=AProject.FCompactOutputmode) and (FCreateIncludeFile=AProject.FCreateIncludeFile) and (FLibname=AProject.FLibname) and (FOutputExt=AProject.FOutputExt) and (FPackAllRecords=AProject.FPackAllRecords) and (FPalmOSSYSTrap=AProject.FPalmOSSYSTrap) and (FPforPointers=AProject.FPforPointers) and (FStripComments=AProject.FStripComments) and (FStripCommentsAndInfo=AProject.FStripCommentsAndInfo) and (FTforTypedefs=AProject.FTforTypedefs) and (FTforTypedefsRemoveUnderscore=AProject.FTforTypedefsRemoveUnderscore) and (FUseExternal=AProject.FUseExternal) and (FUseExternalLibname=AProject.FUseExternalLibname) and (FUseProcVarsForImport=AProject.FUseProcVarsForImport) and (FVarParams=AProject.FVarParams) and (FWin32Header=AProject.FWin32Header) and (FUseCTypes=AProject.FUseCTypes) and (FOutputDirectory=AProject.FOutputDirectory); if not Result then exit; for i:=0 to CHeaderFileCount-1 do if not CHeaderFiles[i].IsEqual(AProject.CHeaderFiles[i]) then exit(false); if (not CompareComponents(FPreH2PasTools,AProject.FPreH2PasTools)) or (not CompareComponents(FPostH2PasTools,AProject.FPostH2PasTools)) then exit(false); end; procedure TH2PasProject.Load(Config: TConfigStorage); procedure LoadTools(const SubPath: string; List: TComponent); var NewComponent: TComponent; NewCount: LongInt; i: Integer; begin // load PreH2PasTools Config.AppendBasePath(SubPath); try NewCount:=Config.GetValue('Count',0); for i:=0 to NewCount-1 do begin Config.AppendBasePath('Tool'+IntToStr(i+1)); try NewComponent:=nil; LoadComponentFromConfig(Config,'Value',NewComponent, @TextConverterToolClasses.FindClass,List); finally Config.UndoAppendBasePath; end; end; finally Config.UndoAppendBasePath; end; end; var NewCount: LongInt; i: Integer; NewCHeaderFile: TH2PasFile; begin Clear(false); // FFilename is not saved FConstantsInsteadOfEnums:=Config.GetValue('ConstantsInsteadOfEnums/Value',true); FCompactOutputmode:=Config.GetValue('CompactOutputmode/Value',false); FCreateIncludeFile:=Config.GetValue('CreateIncludeFile/Value',true); FLibname:=Config.GetValue('Libname/Value',''); FOutputExt:=Config.GetValue('OutputExt/Value','.inc'); FPackAllRecords:=Config.GetValue('PackAllRecords/Value',false); FPalmOSSYSTrap:=Config.GetValue('PalmOSSYSTrap/Value',false); FPforPointers:=Config.GetValue('PforPointers/Value',true); FStripComments:=Config.GetValue('StripComments/Value',false); FStripCommentsAndInfo:=Config.GetValue('StripCommentsAndInfo/Value',false); FTforTypedefs:=Config.GetValue('TforTypedefs/Value',false); FTforTypedefsRemoveUnderscore:=Config.GetValue('TforTypedefsRemoveUnderscore/Value',false); FUseExternal:=Config.GetValue('UseExternal/Value',false); FUseExternalLibname:=Config.GetValue('UseExternalLibname/Value',true); FUseProcVarsForImport:=Config.GetValue('UseProcVarsForImport/Value',false); FVarParams:=Config.GetValue('VarParams/Value',false); FWin32Header:=Config.GetValue('Win32Header/Value',true); FUseCTypes:=Config.GetValue('UseCTypes/Value',false); FOutputDirectory:=NormalizeFilename(Config.GetValue('OutputDirectory/Value','')); // load CHeaderFiles Config.AppendBasePath('CHeaderFiles'); try NewCount:=Config.GetValue('Count',0); for i:=0 to NewCount-1 do begin Config.AppendBasePath('File'+IntToStr(i+1)); try NewCHeaderFile:=TH2PasFile.Create; NewCHeaderFile.Project:=Self; NewCHeaderFile.Load(Config); finally Config.UndoAppendBasePath; end; end; finally Config.UndoAppendBasePath; end; LoadTools('PreH2PasTools',FPreH2PasTools); LoadTools('PostH2PasTools',FPostH2PasTools); FModified:=false; end; procedure TH2PasProject.Save(Config: TConfigStorage); procedure SaveTools(const SubPath: string; List: TComponent); var i: Integer; begin Config.AppendBasePath(SubPath); try Config.SetDeleteValue('Count',List.ComponentCount,0); for i:=0 to List.ComponentCount-1 do begin Config.AppendBasePath('Tool'+IntToStr(i+1)); try SaveComponentToConfig(Config,'Value',List.Components[i]); finally Config.UndoAppendBasePath; end; end; finally Config.UndoAppendBasePath; end; end; var i: Integer; begin // FFilename is kept Config.SetDeleteValue('ConstantsInsteadOfEnums/Value',FConstantsInsteadOfEnums,true); Config.SetDeleteValue('CompactOutputmode/Value',FCompactOutputmode,false); Config.SetDeleteValue('CreateIncludeFile/Value',FCreateIncludeFile,true); Config.SetDeleteValue('Libname/Value',FLibname,''); Config.SetDeleteValue('OutputExt/Value',FOutputExt,'.inc'); Config.SetDeleteValue('PackAllRecords/Value',FPackAllRecords,false); Config.SetDeleteValue('PalmOSSYSTrap/Value',FPalmOSSYSTrap,false); Config.SetDeleteValue('PforPointers/Value',FPforPointers,true); Config.SetDeleteValue('StripComments/Value',FStripComments,false); Config.SetDeleteValue('StripCommentsAndInfo/Value',FStripCommentsAndInfo,false); Config.SetDeleteValue('TforTypedefs/Value',FTforTypedefs,false); Config.SetDeleteValue('TforTypedefsRemoveUnderscore/Value',FTforTypedefsRemoveUnderscore,false); Config.SetDeleteValue('UseExternal/Value',FUseExternal,false); Config.SetDeleteValue('UseExternalLibname/Value',FUseExternalLibname,true); Config.SetDeleteValue('UseProcVarsForImport/Value',FUseProcVarsForImport,false); Config.SetDeleteValue('VarParams/Value',FVarParams,false); Config.SetDeleteValue('Win32Header/Value',FWin32Header,true); Config.SetDeleteValue('UseCTypes/Value',FUseCTypes,false); Config.SetDeleteValue('OutputDirectory/Value',ShortenFilename(FOutputDirectory),''); // save CHeaderFiles Config.AppendBasePath('CHeaderFiles'); try Config.SetDeleteValue('Count',CHeaderFileCount,0); for i:=0 to CHeaderFileCount-1 do begin Config.AppendBasePath('File'+IntToStr(i+1)); try CHeaderFiles[i].Save(Config); finally Config.UndoAppendBasePath; end; end; finally Config.UndoAppendBasePath; end; SaveTools('PreH2PasTools',FPreH2PasTools); SaveTools('PostH2PasTools',FPostH2PasTools); FModified:=false; end; procedure TH2PasProject.LoadFromFile(const AFilename: string); var Config: TXMLConfigStorage; begin Config:=TXMLConfigStorage.Create(AFilename,true); try Load(Config); finally Config.Free; end; end; procedure TH2PasProject.SaveToFile(const AFilename: string); var Config: TXMLConfigStorage; begin Config:=TXMLConfigStorage.Create(AFilename,false); try Save(Config); DebugLn(['TH2PasProject.SaveToFile ',AFilename]); Config.WriteToDisk; finally Config.Free; end; end; procedure TH2PasProject.AddFiles(List: TStrings); var i: Integer; NewFilename: string; NewFile: TH2PasFile; begin if List=nil then exit; for i:=0 to List.Count-1 do begin NewFilename:=CleanAndExpandFilename(List[i]); if (NewFilename='') or (not FileExists(NewFilename)) then exit; if CHeaderFileWithFilename(NewFilename)<>nil then exit; NewFile:=TH2PasFile.Create; NewFile.Project:=Self; NewFile.Filename:=NewFilename; end; end; procedure TH2PasProject.DeleteFiles(List: TStrings); var i: Integer; NewFilename: String; CurFile: TH2PasFile; begin if List=nil then exit; for i:=0 to List.Count-1 do begin NewFilename:=CleanAndExpandFilename(List[i]); if (NewFilename='') then exit; CurFile:=CHeaderFileWithFilename(NewFilename); if CurFile<>nil then begin CurFile.Free; end; end; end; function TH2PasProject.CHeaderFileWithFilename(const AFilename: string ): TH2PasFile; var i: LongInt; begin i:=CHeaderFileIndexWithFilename(AFilename); if i>=0 then Result:=CHeaderFiles[i] else Result:=nil; end; function TH2PasProject.CHeaderFileIndexWithFilename(const AFilename: string ): integer; begin Result:=CHeaderFileCount-1; while (Result>=0) and (CompareFilenames(AFilename,CHeaderFiles[Result].Filename)<>0) do dec(Result); end; function TH2PasProject.ShortenFilename(const AFilename: string): string; begin if IsVirtual then Result:=AFilename else Result:=CreateRelativePath(AFilename,fBaseDir); end; function TH2PasProject.LongenFilename(const AFilename: string): string; begin if IsVirtual then Result:=AFilename else if not FilenameIsAbsolute(AFilename) then Result:=TrimFilename(BaseDir+AFilename); end; function TH2PasProject.NormalizeFilename(const AFilename: string): string; begin Result:=LongenFilename(SetDirSeparators(AFilename)); end; function TH2PasProject.HasEnabledFiles: boolean; var i: Integer; begin for i:=0 to CHeaderFileCount-1 do if CHeaderFiles[i].Enabled then exit(true); Result:=false; end; procedure TH2PasProject.AddDefaultPreH2PasTools; begin AddNewTextConverterTool(FPreH2PasTools,TRemoveCPlusPlusExternCTool); AddNewTextConverterTool(FPreH2PasTools,TRemoveEmptyCMacrosTool); AddNewTextConverterTool(FPreH2PasTools,TReplaceEdgedBracketPairWithStar); AddNewTextConverterTool(FPreH2PasTools,TReplaceMacro0PointerWithNULL); end; procedure TH2PasProject.AddDefaultPostH2PasTools; begin AddNewTextConverterTool(FPostH2PasTools,TReplaceUnitFilenameWithUnitName); AddNewTextConverterTool(FPostH2PasTools,TRemoveSystemTypes); AddNewTextConverterTool(FPostH2PasTools,TRemoveRedefinedPointerTypes); AddNewTextConverterTool(FPostH2PasTools,TRemoveEmptyTypeVarConstSections); end; { TH2PasConverter } procedure TH2PasConverter.OnParseH2PasLine(Sender: TObject; Line: TIDEScanMessageLine); var Tool: TH2PasTool; LineNumber: String; MsgType: String; Msg: String; begin if Line.Tool is TH2PasTool then begin Tool:=TH2PasTool(Line.Tool); if REMatches(Line.Line,'^at line ([0-9]+) (error) : (.*)$') then begin LineNumber:=REVar(1); MsgType:=REVar(2); Msg:=REVar(3); Line.Line:=Tool.TargetFilename+'('+LineNumber+') '+MsgType+': '+Msg; end; //DebugLn(['TH2PasConverter.OnParseH2PasLine ',Line.Line]); end; end; function TH2PasConverter.GetCurrentProjectFilename: string; begin if FProjectHistory.Count>0 then Result:=FProjectHistory[FProjectHistory.Count-1] else Result:=''; end; procedure TH2PasConverter.SetAutoOpenLastProject(const AValue: boolean); begin if FAutoOpenLastProject=AValue then exit; FAutoOpenLastProject:=AValue; Modified:=true; end; procedure TH2PasConverter.SetCurrentProjectFilename(const AValue: string); const ProjectHistoryMax=30; var NewValue: String; begin NewValue:=TrimFilename(AValue); if NewValue='' then exit; if CompareFilenames(GetCurrentProjectFilename,NewValue)=0 then exit; FProjectHistory.Add(NewValue); while FProjectHistory.Count>ProjectHistoryMax do FProjectHistory.Delete(0); Modified:=true; end; procedure TH2PasConverter.SetProject(const AValue: TH2PasProject); begin if FProject=AValue then exit; if FProject<>nil then begin FProject.fConverter:=nil; end; FProject:=AValue; if FProject<>nil then begin FProject.fConverter:=Self; if FProject.Filename<>'' then CurrentProjectFilename:=FProject.Filename; end; end; procedure TH2PasConverter.SetProjectHistory(const AValue: TStrings); begin if FProjectHistory=AValue then exit; FProjectHistory.Assign(AValue); end; procedure TH2PasConverter.SetWindowBounds(const AValue: TRect); begin if CompareRect(@FWindowBounds,@AValue) then exit; FWindowBounds:=AValue; Modified:=true; end; procedure TH2PasConverter.Seth2pasFilename(const AValue: string); begin if Fh2pasFilename=AValue then exit; Fh2pasFilename:=AValue; Modified:=true; end; constructor TH2PasConverter.Create; begin FProjectHistory:=TStringList.Create; Clear; end; destructor TH2PasConverter.Destroy; begin FreeAndNil(FProject); Clear; inherited Destroy; end; procedure TH2PasConverter.Clear; begin FAutoOpenLastProject:=true; if FProject<>nil then FreeAndNil(FProject); FProjectHistory.Clear; FWindowBounds:=Rect(0,0,0,0); Fh2pasFilename:='h2pas'; FModified:=false; end; procedure TH2PasConverter.Assign(Source: TPersistent); var Src: TH2PasConverter; begin if Source is TH2PasConverter then begin Src:=TH2PasConverter(Source); if not IsEqual(Src) then begin Clear; // Note: project is kept unchanged FProjectHistory.Assign(Src.FProjectHistory); FWindowBounds:=Src.FWindowBounds; Fh2pasFilename:=Src.Fh2pasFilename; Modified:=true; end; end else begin inherited Assign(Source); end; end; function TH2PasConverter.IsEqual(AConverter: TH2PasConverter): boolean; begin if (FAutoOpenLastProject<>AConverter.FAutoOpenLastProject) or (not CompareRect(@FWindowBounds,@AConverter.FWindowBounds)) or (Fh2pasFilename<>AConverter.h2pasFilename) or (not FProjectHistory.Equals(AConverter.FProjectHistory)) then exit(false); Result:=true; end; procedure TH2PasConverter.Load(Config: TConfigStorage); var i: Integer; begin FAutoOpenLastProject:=Config.GetValue('AutoOpenLastProject/Value',true); Fh2pasFilename:=Config.GetValue('h2pas/Filename','h2pas'); Config.GetValue('WindowBounds/',FWindowBounds,Rect(0,0,0,0)); Config.GetValue('ProjectHistory/',FProjectHistory); for i:=FProjectHistory.Count-1 downto 0 do if FProjectHistory[i]='' then FProjectHistory.Delete(i); // Note: project is saved in its own file end; procedure TH2PasConverter.Save(Config: TConfigStorage); begin Config.SetDeleteValue('AutoOpenLastProject/Value',FAutoOpenLastProject,true); Config.SetDeleteValue('h2pas/Filename',Fh2pasFilename,'h2pas'); Config.SetDeleteValue('WindowBounds/',FWindowBounds,Rect(0,0,0,0)); Config.SetValue('ProjectHistory/',FProjectHistory); end; procedure TH2PasConverter.LoadFromFile(const AFilename: string); var Config: TXMLConfigStorage; begin Config:=TXMLConfigStorage.Create(AFilename,true); try Load(Config); finally Config.Free; end; end; procedure TH2PasConverter.SaveToFile(const AFilename: string); var Config: TXMLConfigStorage; begin Config:=TXMLConfigStorage.Create(AFilename,false); try Save(Config); Config.WriteToDisk; finally Config.Free; end; end; procedure TH2PasConverter.LoadProject(const Filename: string); begin DebugLn(['TH2PasConverter.LoadProject ',Filename]); if FProject=nil then FProject:=TH2PasProject.Create; FProject.Filename:=Filename; FProject.LoadFromFile(Filename); CurrentProjectFilename:=Filename; end; procedure TH2PasConverter.SaveProject(const Filename: string); begin DebugLn(['TH2PasConverter.SaveProject ',Filename]); FProject.Filename:=Filename; FProject.SaveToFile(Filename); CurrentProjectFilename:=Filename; end; function TH2PasConverter.Execute: TModalResult; var i: Integer; AFile: TH2PasFile; CurResult: TModalResult; begin if FExecuting then begin DebugLn(['TH2PasConverter.Execute FAILED: Already executing']); exit(mrCancel); end; Result:=mrOK; FExecuting:=true; try FLastUsedFilename:=''; // convert every c header file for i:=0 to Project.CHeaderFileCount-1 do begin AFile:=Project.CHeaderFiles[i]; if not AFile.Enabled then continue; CurResult:=ConvertFile(AFile); if CurResult=mrAbort then begin DebugLn(['TH2PasConverter.Execute aborted on file ',AFile.Filename]); exit(mrAbort); end; if CurResult<>mrOK then Result:=mrCancel; end; finally FExecuting:=false; end; end; function TH2PasConverter.ConvertFile(AFile: TH2PasFile): TModalResult; var OutputFilename: String; TempCHeaderFilename: String; InputFilename: String; Tool: TH2PasTool; TextConverter: TIDETextConverter; begin Result:=mrCancel; FLastUsedFilename:=''; // check if file exists InputFilename:=AFile.Filename; if not FileExistsCached(InputFilename) then begin Result:=IDEMessageDialog('File not found', 'C header file "'+InputFilename+'" not found', mtError,[mbCancel,mbAbort],''); exit; end; OutputFilename:=AFile.GetOutputFilename; TempCHeaderFilename:=ChangeFileExt(OutputFilename,'.tmp.h'); TextConverter:=TIDETextConverter.Create(nil); try if not CopyFile(InputFilename,TempCHeaderFilename) then begin Result:=IDEMessageDialog('Copying file failed', 'Unable to copy file "'+InputFilename+'"'#13 +'to "'+TempCHeaderFilename+'"', mtError,[mbCancel,mbAbort],''); exit; end; TextConverter.Filename:=TempCHeaderFilename; FLastUsedFilename:=TextConverter.Filename; DebugLn(['TH2PasConverter.ConvertFile TempCHeaderFilename="',TempCHeaderFilename,'" CurrentType=',ord(TextConverter.CurrentType),' FileSize=',FileSize(TempCHeaderFilename)]); // run converters for .h file to make it compatible for h2pas TextConverter.LoadFromFile(InputFilename); Result:=TextConverter.Execute(Project.PreH2PasTools); if Result<>mrOk then begin DebugLn(['TH2PasConverter.ConvertFile Failed running Project.PreH2PasTools on ',TempCHeaderFilename]); exit; end; // run h2pas Tool:=TH2PasTool.Create; try Tool.Title:='h2pas'; Tool.H2PasFile:=AFile; //DebugLn(['TH2PasConverter.ConvertFile AAA TempCHeaderFilename="',TempCHeaderFilename,'" CurrentType=',ord(TextConverter.CurrentType),' FileSize=',FileSize(TempCHeaderFilename)]); Tool.TargetFilename:=TextConverter.Filename; //DebugLn(['TH2PasConverter.ConvertFile BBB TempCHeaderFilename="',TempCHeaderFilename,'" CurrentType=',ord(TextConverter.CurrentType),' FileSize=',FileSize(TempCHeaderFilename)]); Tool.Filename:=GetH2PasFilename; Tool.CmdLineParams:=AFile.GetH2PasParameters(Tool.TargetFilename); Tool.ScanOutput:=true; Tool.ShowAllOutput:=true; Tool.WorkingDirectory:=Project.BaseDir; Tool.OnParseLine:=@OnParseH2PasLine; DebugLn(['TH2PasConverter.ConvertFile Tool.Filename="',Tool.Filename,'" Tool.CmdLineParams="',Tool.CmdLineParams,'"']); Result:=RunExternalTool(Tool); if Result<>mrOk then exit(mrAbort); if FindH2PasErrorMessage>=0 then exit(mrAbort); finally Tool.Free; end; // run beautification tools for new pascal code TextConverter.InitWithFilename(OutputFilename); DebugLn(['TH2PasConverter.ConvertFile OutputFilename: ',copy(TextConverter.Source,1,300)]); Result:=TextConverter.Execute(Project.PostH2PasTools); if Result<>mrOk then begin DebugLn(['TH2PasConverter.ConvertFile Failed running Project.PostH2PasTools on ',TempCHeaderFilename]); exit; end; TextConverter.Filename:=OutputFilename;// save finally TextConverter.Free; if (LazarusIDE<>nil) then begin // reload changed files, so that IDE does not report changed files LazarusIDE.DoRevertEditorFile(TempCHeaderFilename); LazarusIDE.DoRevertEditorFile(OutputFilename); end; end; Result:=mrOk; end; function TH2PasConverter.GetH2PasFilename: string; begin Result:=FindDefaultExecutablePath(h2pasFilename); end; function TH2PasConverter.FindH2PasErrorMessage: integer; var i: Integer; Line: TIDEMessageLine; begin for i:=0 to IDEMessagesWindow.LinesCount-1 do begin Line:=IDEMessagesWindow.Lines[i]; if REMatches(Line.Msg,'^(.*)\([0-9]+\)') then begin Result:=i; exit; end; end; Result:=-1; end; function TH2PasConverter.GetH2PasErrorPostion(const Line: string; out aFilename: string; out LineNumber, Column: integer): boolean; begin Result:=REMatches(Line,'^(.*)\(([0-9]+)\)'); if Result then begin aFilename:=REVar(1); LineNumber:=StrToIntDef(REVar(2),-1); Column:=1; end else begin aFilename:=''; LineNumber:=-1; Column:=-1; end; end; function TH2PasConverter.FileIsRelated(const aFilename: string): Boolean; begin Result:=(CompareFilenames(AFilename,LastUsedFilename)=0) or ((Project<>nil) and (Project.CHeaderFileWithFilename(aFilename)<>nil)); end; { TRemoveCPlusPlusExternCTool } class function TRemoveCPlusPlusExternCTool.ClassDescription: string; begin Result:='Remove C++ ''extern "C"'' lines'; end; function TRemoveCPlusPlusExternCTool.Execute(aText: TIDETextConverter ): TModalResult; var i: Integer; Lines: TStrings; Line: string; begin Result:=mrCancel; if aText=nil then exit; Lines:=aText.Strings; i:=0; while i<=Lines.Count-1 do begin Line:=Trim(Lines[i]); if Line='extern "C" {' then begin Lines[i]:=''; end else if (i>0) and (Line='}') and (Lines[i-1]='#if defined(__cplusplus)') then begin Lines[i]:=''; end; inc(i); end; Result:=mrOk; end; { TRemoveEmptyCMacrosTool } class function TRemoveEmptyCMacrosTool.ClassDescription: string; begin Result:='Remove empty C macros'; end; function TRemoveEmptyCMacrosTool.Execute(aText: TIDETextConverter ): TModalResult; var EmptyMacros: TAvgLvlTree;// tree of PChar procedure AddEmptyMacro(const MacroName: string); var TempStr: String; Identifier: PChar; begin //DebugLn(['AddEmptyMacro MacroName="',MacroName,'"']); if EmptyMacros=nil then EmptyMacros:=TAvgLvlTree.Create(TListSortCompare(@CompareIdentifiers)); Identifier:=@MacroName[1]; if EmptyMacros.Find(Identifier)<>nil then exit; TempStr:=MacroName; // increase refcount if TempStr<>'' then Pointer(TempStr):=nil; EmptyMacros.Add(Identifier); end; procedure DeleteEmptyMacro(const MacroName: string); var OldMacroName: String; Identifier: PChar; Node: TAvgLvlTreeNode; begin //DebugLn(['DeleteEmptyMacro MacroName="',MacroName,'"']); if EmptyMacros=nil then exit; Identifier:=@MacroName[1]; Node:=EmptyMacros.Find(Identifier); if Node=nil then exit; OldMacroName:=''; Pointer(OldMacroName):=Node.Data; if OldMacroName<>'' then OldMacroName:=''; // decrease refcount EmptyMacros.Delete(Node); end; procedure FreeMacros; var CurMacroName: String; Node: TAvgLvlTreeNode; begin if EmptyMacros=nil then exit; CurMacroName:=''; Node:=EmptyMacros.FindLowest; while Node<>nil do begin Pointer(CurMacroName):=Node.Data; if CurMacroName<>'' then CurMacroName:=''; // decrease refcount Node:=EmptyMacros.FindSuccessor(Node); end; EmptyMacros.Free; end; procedure RemoveEmptyMacrosFromString(var s: string); var IdentEnd: Integer; IdentStart: LongInt; Identifier: PChar; IdentLen: LongInt; begin if EmptyMacros=nil then exit; IdentEnd:=1; repeat IdentStart:=FindNextIdentifier(s,IdentEnd,length(s)); if IdentStart>length(s) then exit; Identifier:=@s[IdentStart]; IdentLen:=GetIdentLen(Identifier); if EmptyMacros.Find(Identifier)<>nil then begin // empty macro found -> remove System.Delete(s,IdentStart,IdentLen); IdentEnd:=IdentStart; end else begin IdentEnd:=IdentStart+IdentLen; end; until false; end; var MacroStart, MacroLen: integer; Lines: TStrings; i: Integer; Line: string; MacroName: String; begin Result:=mrCancel; if aText=nil then exit; Lines:=aText.Strings; EmptyMacros:=nil; try i:=0; while i<=Lines.Count-1 do begin Line:=Lines[i]; if REMatches(Line,'^#define\s+([a-zA-Z0-9_]+)\b(.*)$') then begin REVarPos(1,MacroStart,MacroLen); MacroName:=copy(Line,MacroStart,MacroLen); if Trim(copy(Line,MacroStart+MacroLen,length(Line)))='' then AddEmptyMacro(MacroName) else DeleteEmptyMacro(MacroName); end; if (Line<>'') and (Line[1]<>'#') then RemoveEmptyMacrosFromString(Line); Lines[i]:=Line; inc(i); end; finally FreeMacros; end; Result:=mrOk; end; { TReplaceMacro0PointerWithNULL } class function TReplaceMacro0PointerWithNULL.ClassDescription: string; begin Result:='Replace macro values 0 pointer like (char *)0 with NULL'; end; function TReplaceMacro0PointerWithNULL.Execute(aText: TIDETextConverter ): TModalResult; var Lines: TStrings; i: Integer; Line: string; MacroStart, MacroLen: integer; begin Result:=mrCancel; if aText=nil then exit; Lines:=aText.Strings; i:=0; while i<=Lines.Count-1 do begin Line:=Lines[i]; if REMatches(Line,'^#define\s+([a-zA-Z0-9_]+)\s+(\(.*\*\)0)\s*($|//|/\*)') then begin REVarPos(2,MacroStart,MacroLen); Line:=copy(Line,1,MacroStart-1)+'NULL' +copy(Line,MacroStart+MacroLen,length(Line)); Lines[i]:=Line; end; inc(i); end; Result:=mrOk; end; { TReplaceEdgedBracketPairWithStar } class function TReplaceEdgedBracketPairWithStar.ClassDescription: string; begin Result:='Replace [] with *'; end; constructor TReplaceEdgedBracketPairWithStar.Create(TheOwner: TComponent); begin inherited Create(TheOwner); SearchFor:='[]'; ReplaceWith:='*'; end; { TReplaceUnitFilenameWithUnitName } class function TReplaceUnitFilenameWithUnitName.ClassDescription: string; begin Result:='Replace "unit filename;" with "unit name;"'; end; constructor TReplaceUnitFilenameWithUnitName.Create(TheOwner: TComponent); begin inherited Create(TheOwner); SearchFor:='^(unit\s).*(/|\\)([a-z_0-9]+;)'; ReplaceWith:='$1$3'; Options:=Options+[trtRegExpr]; end; { TRemoveSystemTypes } class function TRemoveSystemTypes.ClassDescription: string; begin Result:='Remove type redefinitons like PLongint'; end; function TRemoveSystemTypes.Execute(aText: TIDETextConverter): TModalResult; var Source: String; Flags: TSrcEditSearchOptions; Prompt: Boolean; SearchFor: string; begin Result:=mrCancel; if aText=nil then exit; Source:=aText.Source; Flags:=[sesoReplace,sesoReplaceAll,sesoRegExpr]; Prompt:=false; SearchFor:='^\s*(' +'PLongint\s*=\s*\^Longint' +'|PSmallInt\s*=\s*\^SmallInt' +'|PByte\s*=\s*\^Byte' +'|PWord\s*=\s*\^Word' +'|PDWord\s*=\s*\^DWord' +'|PDouble\s*=\s*\^Double' +'|PChar\s*=\s*\^Char' +');\s*$'; Result:=IDESearchInText('',Source,SearchFor,'',Flags,Prompt,nil); if Result<>mrOk then exit; aText.Source:=Source; end; { TRemoveRedefinedPointerTypes } class function TRemoveRedefinedPointerTypes.ClassDescription: string; begin Result:='Remove redefined pointer types'; end; function TRemoveRedefinedPointerTypes.Execute(aText: TIDETextConverter ): TModalResult; { search for Pname = ^name; if PName has a redefinition, delete the first one } var Lines: TStrings; i: Integer; Line: string; PointerName: String; TypeName: String; j: Integer; Pattern: String; begin Result:=mrCancel; if aText=nil then exit; Lines:=aText.Strings; i:=0; while i<=Lines.Count-1 do begin Line:=Lines[i]; if REMatches(Line,'^\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*\^\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*;\s*($|//|/\*)') then begin PointerName:=REVar(1); TypeName:=REVar(2); Pattern:='^\s*'+PointerName+'\s*=\s*\^\s*'+TypeName+'\s*;'; j:=i+1; while (jlength(Src) then break; CurAtom:=@Src[AtomStart]; if (CompareIdentifiers(CurAtom,'type')=0) or (CompareIdentifiers(CurAtom,'var')=0) or (CompareIdentifiers(CurAtom,'const')=0) or (CompareIdentifiers(CurAtom,'threadvar')=0) or (CompareIdentifiers(CurAtom,'resourcestring')=0) then begin // start of a section found // read next atoms to check if they are identifier plus definition operator // 'name =' or 'name:' or 'name,' KeyWordStart:=AtomStart; KeyWordEnd:=p; ReadRawNextPascalAtom(Src,p,AtomStart); if p0 then begin ReadRawNextPascalAtom(Src,p,AtomStart); if (p<=length(Src)) and (p-AtomStart=1) and (Src[AtomStart] in ['=',':',',']) then DeleteSection:=false; end; if DeleteSection then begin // this section is empty -> delete it Src:=copy(Src,1,KeyWordStart-1)+copy(Src,KeyWordEnd,length(Src)); Modified:=true; // adjust position p:=KeyWordStart; end; end; end; until false; if Modified then aText.Source:=Src; Result:=mrOk; end; end.