Recursive filesearch

From Freepascal Amiga wiki
Revision as of 12:29, 18 August 2014 by Molly (talk | contribs) (corrected link to original c-code (in source))
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Another small code example i wanted to 'resque' from aros-exec 'haystack'.

Original code was pasted in this post.

The code does a recursive filesearch using amigados specific calls to do so.

Should be able to work with replacing unit use aros_exec with exec and aros_dos with amigados.

Program RecurseFilematch; 

{$MODE OBJFPC}{$H+} 

uses 
  aros_exec, 
  aros_dos, 
  SysUtils; 



Procedure FileSearchAROS(const pathname, FileMask: string; const DoRecursive: boolean); 
{ 
  Routine based on thomas-rapps post ->  
   http://eab.abime.net/showpost.php?p=660659&postcount=5 
  FileSearch routine that can search directories recursive (no restrictions) and match 
  a given file pattern. The pattern is not applied to the directory, only to the file. 
  This routine is not foolproof and definatly needs a bit more TLC. 
  Sorry for the ugly code. 
} 

var  
  ap          : PAnchorPath; 
  error,  
  level,  
  i           : longint; 

  s,                        // We need a temp string because fpc does not have a ? operator 
  filename    : String;     // String to hold the filename (and only filename part) 
  filemaskTOK : pChar;      // C-String to hold the tokenized mask needed for AROS API Routine 
  isMatch     : Longbool;   // Temp boolean placeholder to hold the match result 
begin 
  ap := AllocVec(sizeof(TAnchorPath) + 1024, MEMF_CLEAR); 
  if (ap <> nil) then 
  begin 
    ap^.ap_BreakBits := SIGBREAKF_CTRL_C; 
    ap^.ap_StrLen    := 1024;   
  end; 

  level := 0; 

  error := MatchFirst(pathname, ap); 

  if (error = 0) and (ap^.ap_Info.fib_DirEntryType >= 0) 
    then ap^.ap_Flags := ap^.ap_Flags or APF_DODIR; 

  while (error = 0) do 
  begin 
    if ((ap^.ap_Flags and APF_DIDDIR) <> 0) then 
    begin 
      { Leaving a directory entered below (APF_DODIR) } 
      dec(level); 
      ap^.ap_Flags := ap^.ap_Flags and not(APF_DIDDIR);     
    end 
    else 
    begin 
      { 
        Soft linked objects are returned by the scanner 
        but they need special treatments; we are merely 
        ignoring them here in order to keep this example 
        simple 
      } 
      if (ap^.ap_Info.fib_DirEntryType <> ST_SOFTLINK) then 
      begin 
        {  
          provide for some indentation  
        } 
        for i := 0 to pred(level) do write(' '); 

        if (ap^.ap_Info.fib_DirEntryType < 0) then 
        begin 
          s := '';  { no ? operator: results in dumb code to mimic the behaviour } 

          { 
            According to AutoDocs/FileInfoBlock struct, we can now 
            be certain that we do not deal with a directory, but are 
            dealing with an actual file. 
            So if we can find a way to determine the name of the 
            file then we could do nice things with it, such as  
            emitting the name. 
          } 
          { get the name } 
          Filename := ap^.ap_Info.fib_FileName; 
          { do something nice, and emit the filename } 
          writeln('filename = ',filename); 

          { 
            Now we have a real filename (only) to work with. But  
            what should we do with it ? Is it even useful ? 
            We know we need the filename to match the given  
            filemask. 
            Is there perhaps a way to do this ? Lets try:                   
          } 
          { allocate heapmem for pchar: fpc business. Size taken from AutoDocs } 
          FileMaskTOK := stralloc((Length(FileMask) * 2) + 2); 
          { create a tokenized filemask with a trickery cast. Size taken from AutoDocs } 
          ParsePatternNoCase(pchar(FileMask), FileMaskTOK, (Length(FileMask) * 2) + 2); 
          { match a pattern } 
          IsMatch := MatchPatternNoCase(FileMaskTOK, FileName); 
          { check the result, if we match we emit the name, or you can do whatever with it } 
          if IsMatch then writeln('It seems that the above printed filename matches the filemask o/');           
          { return allocated heapmem for pchar: fpc business }           
          strdispose(FileMaskTOK); 
        end   
        else s := ' (Dir)'; { no ? operator: results in dumb code to mimic the behaviour } 

        writeln(format('%s%s',[ap^.ap_Buf, s])); 

        { If this is a directory, enter it } 
        if ((ap^.ap_Info.fib_DirEntryType >= 0) and DoRecursive) then 
        begin 
          ap^.ap_Flags := (ap^.ap_Flags or APF_DODIR); 
          inc(level); 
        end; 

      end; 
    end; 
    error := MatchNext(ap); 

  end; 
  MatchEnd(ap); 
  FreeVec(ap); 
end; 



Begin 
  WriteLn('start'); 

  FileSearchAROS('Ram:','#?.info', true); 

  Writeln('end'); 
End.