diff --git a/components/codetools/definetemplates.pas b/components/codetools/definetemplates.pas index ffa08770af..26c77694f0 100644 --- a/components/codetools/definetemplates.pas +++ b/components/codetools/definetemplates.pas @@ -546,6 +546,18 @@ const DefineTemplateFlagNames: array[TDefineTemplateFlag] of shortstring = ( 'AutoGenerated' ); + +type + TShortFilenameTreeItem = class + public + ShortFilename: string; // = ExtractFilename(Filename) + Filename: string; + end; + + TShortFilenameTree = class + public + + end; function DefineActionNameToAction(const s: string): TDefineAction; function DefineTemplateFlagsToString(Flags: TDefineTemplateFlags): string; @@ -560,11 +572,13 @@ function GetDefaultCompilerFilename: string; function CreateDefinesInDirectories(const SourcePaths, FlagName: string ): TDefineTemplate; +function GatherFiles(Directory, ExcludeDirMask, IncludeFileMask: string + ): TStringList; + procedure ReadMakefileFPC(const Filename: string; List: TStrings); procedure ParseMakefileFPC(const Filename, SrcOS: string; var Dirs, SubDirs: string); - implementation @@ -580,6 +594,54 @@ type // some useful functions +function GatherFiles(Directory, ExcludeDirMask, IncludeFileMask: string): TStringList; +{ ExcludeDirMask: check FilenameIsMatching vs the short file name of a directory + IncludeFileMask: check FilenameIsMatching vs the short file name of a file +} + + procedure Search(CurDir: string); + var + FileInfo: TSearchRec; + ShortFilename: String; + Filename: String; + begin + DebugLn(['Search CurDir=',CurDir]); + if FindFirstUTF8(CurDir+FileMask,faAnyFile,FileInfo)=0 then begin + repeat + ShortFilename:=FileInfo.Name; + if (ShortFilename='') or (ShortFilename='.') or (ShortFilename='..') then + continue; + debugln(['Search ShortFilename=',ShortFilename,' IsDir=',(FileInfo.Attr and faDirectory)>0]); + Filename:=CurDir+ShortFilename; + if (FileInfo.Attr and faDirectory)>0 then begin + // directory + if (ExcludeDirMask='') + or (FilenameIsMatching(ExcludeDirMask,ShortFilename,true)) + then begin + Search(Filename+PathDelim); + end else begin + DebugLn(['Search DIR MISMATCH ',Filename]); + end; + end else begin + // file + if (IncludeFileMask='') + or FilenameIsMatching(IncludeFileMask,ShortFilename,true) then begin + DebugLn(['Search ADD ',Filename]); + GatherFiles.Add(Filename); + end else begin + DebugLn(['Search MISMATCH ',Filename]); + end; + end; + until FindNextUTF8(FileInfo)<>0; + end; + FindCloseUTF8(FileInfo); + end; + +begin + Result:=TStringList.Create; + Search(CleanAndExpandDirectory(Directory)); +end; + procedure ReadMakefileFPC(const Filename: string; List: TStrings); var MakefileFPC: TStringList; diff --git a/components/codetools/fileprocs.pas b/components/codetools/fileprocs.pas index 3a30db4cc7..adef013d9d 100644 --- a/components/codetools/fileprocs.pas +++ b/components/codetools/fileprocs.pas @@ -129,6 +129,7 @@ function SearchPascalFileInDir(const ShortFilename, BaseDirectory: string; function SearchPascalFileInPath(const ShortFilename, BasePath, SearchPath, Delimiter: string; SearchCase: TCTSearchFileCase): string; +// search paths function CreateAbsoluteSearchPath(const SearchPath, BaseDirectory: string): string; function CreateRelativeSearchPath(const SearchPath, BaseDirectory: string): string; function MinimizeSearchPath(const SearchPath: string): string; @@ -1791,13 +1792,32 @@ var EndPos: LongInt; NextStartPos: LongInt; CmpPos: LongInt; + UseQuickCompare: Boolean; + PathStr: String; + CurFilename: String; begin Result:=nil; if SearchPath=nil then exit; - if APath=nil then exit; + if (APath=nil) or (APathLen=0) then exit; // ignore trailing PathDelim at end while (APathLen>1) and (APath[APathLen-1]=PathDelim) do dec(APathLen); + {$IFDEF CaseInsensitiveFilenames} + UseQuickCompare:=false; + {$ELSE} + {$IFDEF NotLiteralFilenames} + CmpPos:=0; + while (CmpPosStartPos+1) and (SearchPath[EndPos-1]=PathDelim) do dec(EndPos); // compare current path - if EndPos-StartPos=APathLen then begin - CmpPos:=0; - while CmpPosSearchPath[StartPos+CmpPos] then - break; - inc(CmpPos); + if UseQuickCompare then begin + if EndPos-StartPos=APathLen then begin + CmpPos:=0; + while CmpPosSearchPath[StartPos+CmpPos] then + break; + inc(CmpPos); + end; + if CmpPos=APathLen then begin + Result:=@SearchPath[StartPos]; + exit; + end; end; - if CmpPos=APathLen then begin + end else if EndPos>StartPos then begin + // use CompareFilenames + CurFilename:=''; + SetLength(CurFilename,EndPos-StartPos); + System.Move(SearchPath[StartPos],CurFilename[1],EndPos-StartPos); + if CompareFilenames(PathStr,CurFilename)=0 then begin Result:=@SearchPath[StartPos]; exit; end; @@ -2026,8 +2057,33 @@ var DirStartFile, DirEndFile, AsteriskPos, BracketMaskPos, BracketFilePos: integer; + + function TryNextOr: boolean; + begin + Result:=false; + if BracketMaskPos<1 then exit; + repeat + inc(DirStartMask); + if DirStartMask>=DirEndMask then exit; // error, missing } + if Mask[DirStartMask]=SpecialChar then begin + // special char -> next char is normal char + inc(DirStartMask); + end else if Mask[DirStartMask]='}' then begin + // bracket found (= end of Or operator) + // -> filename does not match + exit; + end else if Mask[DirStartMask]=',' then begin + // next Or found + // -> reset filename position and compare + inc(DirStartMask); + DirStartFile:=BracketFilePos; + exit(true); + end; + until false; + end; + begin - //debugln('[FilenameIsMatching] Mask="',Mask,'" Filename="',Filename,'" MatchExactly=',MatchExactly); + //debugln(['[FilenameIsMatching] Mask="',Mask,'" Filename="',Filename,'" MatchExactly=',MatchExactly]); Result:=false; if (Filename='') then exit; if (Mask='') then begin @@ -2043,19 +2099,21 @@ begin // find ends of directories DirEndMask:=FindDirectoryEnd(Mask,DirStartMask); DirEndFile:=FindDirectoryEnd(Filename,DirStartFile); - // debugln(' Compare "',copy(Mask,DirStartMask,DirEndMask-DirStartMask),'"', - // ' "',copy(Filename,DirStartFile,DirEndFile-DirStartFile),'"'); + //debugln(' Compare "',copy(Mask,DirStartMask,DirEndMask-DirStartMask),'"', + //' "',copy(Filename,DirStartFile,DirEndFile-DirStartFile),'"'); // compare directories AsteriskPos:=0; BracketMaskPos:=0; - while (DirStartMask=DirEndMask) then exit; end; // compare char - if CharsEqual(Mask[DirStartMask],Filename[DirStartFile]) then begin + if (DirStartFile0 then begin // try next Or - repeat - inc(DirStartMask); - if DirStartMask>=DirEndMask then exit; // error, missing } - if Mask[DirStartMask]=SpecialChar then begin - // special char -> next char is normal char - inc(DirStartMask); - end else if Mask[DirStartMask]='}' then begin - // bracket found (= end of Or operator) - // -> filename does not match - exit; - end else if Mask[DirStartMask]=',' then begin - // next Or found - // -> reset filename position and compare - inc(DirStartMask); - DirStartFile:=BracketFilePos; - break; - end; - until false; + if not TryNextOr then exit; end else if AsteriskPos>0 then begin // * operator always fits inc(DirStartFile);