for the record, and for all those interested,
---------- Forwarded message ---------- From: Luis Rivera jlrn77@gmail.com Date: 22 May 2010 14:56 Subject: Re: findfiles syntax To: Maurice Lombardi
On 22 May 2010 03:19, Maurice Lombardi Maurice.Lombardi@ujf-grenoble.fr wrote:
Luis Rivera a écrit :
program FindFilesTest;
uses GPC, FileUtils;
type alphafile=text; var nameoffile: string; filename: alphafile; const mydir='/usr/local/';
function aopenin(var a:alphafile):boolean; begin if ioresult=0 then assign(a,trim(nameoffile)); findfiles(mydir,a,false,reset,nil); aopenin:=ioresult=0; end;
begin WriteLn ('Enter file name to type: '); ReadLn (nameoffile); if aopenin(alphafile) then
[...] Declaring the text file as filename is very confusing: this is certainly the source of your errors: you confuse a file and its name.
- a is a file, not a string (Mask)
mydir is a string (the name of the directory to search in)
- reset has for parameter a file, not a string.
So it expects the string containing the filename...
Changing the naming conventions, trying to avoid confusing the FileName (string) with the FileContents (text), I may do the following:
program AtBat;
uses GPC, FileUtils;
type alphafile=text; var filename: string; filecontents: alphafile; const mydir='/usr/local/';
function aopenin(var a:alphafile):boolean; var f:string; begin if ioresult=0 then f:=trim(filename); assign(a,f); findfiles(mydir,f,false,reset,nil); aopenin:=ioresult=0; end;
begin WriteLn ('Enter file name to type: '); ReadLn (filename); if aopenin(filecontents) then WriteLn(filename, ' found!') else Writeln('Sorry: search failed!'); end.
However, I still get the same error message...
BTW: a simple, sensible way to state "DoNothing" as DirAction?
You might want to declare a FileAction procedure with a string parameter (nameoffile): probably you would include in it the assign which is before findfiles in your program and the reset
That's what I just tried to do! :-)
Notice that if there are multiple files found, you will have an error because you then try to reopen a file (a) which has not been closed: findfiles apply FileAction on all files which match Mask.
Maybe I can get around that problem defining the FileAction procedure in such a way that wildcards are forbidden...
You can close the file inside FileAction, but beware not to confuse nameoffile as a parameter of FileAction and as a global variable: if you give two different names and assign the global name to the parameter inside FileAction you can recover at the end the last nameoffile found.
PS:
A := B = C; is correct in Pascal, weird but correct.
Cool. Thanks for pointing that out.
Cheers!
-- Luis Rivera O< http://www.asciiribbon.org/ campaign
Luis Rivera wrote:
On 22 May 2010 03:19, Maurice Lombardi Maurice.Lombardi@ujf-grenoble.fr wrote:
Luis Rivera a écrit :
program FindFilesTest;
uses GPC, FileUtils;
type  alphafile=text; var  nameoffile: string;  filename: alphafile; const  mydir='/usr/local/';
function aopenin(var a:alphafile):boolean; begin if ioresult=0 then assign(a,trim(nameoffile)); findfiles(mydir,a,false,reset,nil); aopenin:=ioresult=0; end;
begin WriteLn ('Enter file name to type: '); ReadLn (nameoffile); if aopenin(alphafile) then
[...] Declaring the text file as filename is very confusing: this is certainly the source of your errors: you confuse a file and its name.
- a is a file, not a string (Mask)
mydir is a string (the name of the directory to search in)
He talked about "a", not "mydir".
- reset has for parameter a file, not a string.
So it expects the string containing the filename...
... and the file, so it does not match TStringProc (even if Reset was a regular procedure, which it isn't for several reasons, so it can't be used as a procedural parameter anyway).
Changing the naming conventions, trying to avoid confusing the FileName (string) with the FileContents (text), I may do the following:
program AtBat;
uses GPC, FileUtils;
 type  alphafile=text;  var  filename: string;  filecontents: alphafile;  const  mydir='/usr/local/';
 function aopenin(var a:alphafile):boolean;  var f:string;  begin if ioresult=0 then  f:=trim(filename);  assign(a,f);  findfiles(mydir,f,false,reset,nil);  aopenin:=ioresult=0;  end;
 begin  WriteLn ('Enter file name to type: ');  ReadLn (filename);  if aopenin(filecontents) then  WriteLn(filename, ' found!') else  Writeln('Sorry: search failed!'); end.
However, I still get the same error message...
BTW: a simple, sensible way to state "DoNothing" as DirAction?
You might want to declare a FileAction procedure with a string parameter (nameoffile): probably you would include in it the assign which is before findfiles in your program and the reset
That's what I just tried to do! :-)
Please read more carefully what he wrote (see above), otherwise people here might not be willing to help you in the future:
You might want to declare a FileAction procedure
(which obviously means a procedure to be used for the FileAction parameter)
You did not do this, you still try to pass "Reset" here.
with a string parameter (nameoffile):
You did not do this either. You did not declare a procedure at all (and the only function you declare does not have a string parameter, but a file parameter, and is not for "FileAction" anyway).
probably you would include in it the assign which is before findfiles in your program and the reset
"In it" means in the FileAction procedure. You try to do the "Assign" before calling FindFiles. How should this work? You cannot assign the filename before you have found it. (What you'd do is to assign the filename as typed by the user, but if the file is in a subdirectory, you don't get the directory, because you haven't searched it yet.)
Notice that if there are multiple files found, you will have an error because you then try to reopen a file (a) which has not been closed: findfiles apply FileAction on all files which match Mask.
Maybe I can get around that problem defining the FileAction procedure in such a way that wildcards are forbidden...
You still could have several files with the same name in different directories.
If you only care for any file found, I'd suggest to write a FileAction procedure that stores the file name in a (global) string variable. (If multiple files are found, the last one will be stored eventually.) Then after FindFiles returns (not in the FileAction procedure), assign the file to the name in thie variable.
If you initialize the variable with an empty string, you can check this way if the file was not found. Checking for IOResult is not a valid check for file not found -- if there is no file, FindFiles will simply not call FileAction, but not set an error code.
I do. However, one thing that bothers me is that the sample code at findfilesdemo.pas mentioned earlier in this thread includes the line
 FindFiles (DirSelf, '*.{pas,p,pp,dpr}', False, DoOutput, nil);
as an example. Now I wonder why it compiles and runs if nil shouldn't match.
In fact, GPC allows "nil" for procedural parameters (if the called routine expects it, which FindFiles explicitly does, as described in its comment).
Frank
On 24 May 2010 18:55, Frank Heckenbach ih8mj@fjf.gnu.de wrote:
Luis Rivera wrote:
- a is a file, not a string (Mask)
mydir is a string (the name of the directory to search in)
He talked about "a", not "mydir".
Oops! Right! Sorry! (I think I mistook the 1) as a reference to the first parameter)
- reset has for parameter a file, not a string.
So it expects the string containing the filename...
... and the file, so it does not match TStringProc (even if Reset was a regular procedure, which it isn't for several reasons, so it can't be used as a procedural parameter anyway).
Well, besides the fact that I was still mistaking the filename with the file itself, I think this "irregularity" of Reset explains a lot already! I guess my whole approach is doomed because of this.
So, correct me if I'm wrong, but valid procedures for this parameter would be deleting, copying, and stuff like that, a bit like DirAction, right?
Please read more carefully what he wrote (see above), otherwise people here might not be willing to help you in the future:
You might want to declare a FileAction procedure
(which obviously means a procedure to be used for the FileAction parameter)
You did not do this, you still try to pass "Reset" here.
with a string parameter (nameoffile):
You did not do this either. You did not declare a procedure at all (and the only function you declare does not have a string parameter, but a file parameter, and is not for "FileAction" anyway).
You're right, I hadn't define this FileAction yet. I was kind of thinking aloud (or in writing, so to speak).
probably you would include in it the assign which is before findfiles in your program and the reset
"In it" means in the FileAction procedure. You try to do the "Assign" before calling FindFiles. How should this work? You cannot assign the filename before you have found it. (What you'd do is to assign the filename as typed by the user, but if the file is in a subdirectory, you don't get the directory, because you haven't searched it yet.)
Right. I already had the uneasy feeling of short-circuiting myself, and indeed I was doing so. Thanks.
Notice that if there are multiple files found, you will have an error because you then try to reopen a file (a) which has not been closed: findfiles apply FileAction on all files which match Mask.
Maybe I can get around that problem defining the FileAction procedure in such a way that wildcards are forbidden...
You still could have several files with the same name in different directories.
If you only care for any file found, I'd suggest to write a FileAction procedure that stores the file name in a (global) string variable. (If multiple files are found, the last one will be stored eventually.) Then after FindFiles returns (not in the FileAction procedure), assign the file to the name in the variable.
Got it! Thanks!
If you initialize the variable with an empty string, you can check this way if the file was not found. Checking for IOResult is not a valid check for file not found -- if there is no file, FindFiles will simply not call FileAction, but not set an error code.
I see. So perhaps it was always a bad idea to try to use it to define a function returning boolean.
In fact, GPC allows "nil" for procedural parameters (if the called routine expects it, which FindFiles explicitly does, as described in its comment).
OK. That explains a lot...
Well, I guess I'll have to cool down, get back to the blackboard, and rethink my whole strategy.
Thanks for all the feedback!
Luis Rivera wrote:
- a is a file, not a string (Mask)
mydir is a string (the name of the directory to search in)
He talked about "a", not "mydir".
Oops! Right! Sorry! (I think I mistook the 1) as a reference to the first parameter)
I see. Perhaps another reason not to call parameters "a". ;-)
- reset has for parameter a file, not a string.
So it expects the string containing the filename...
... and the file, so it does not match TStringProc (even if Reset was a regular procedure, which it isn't for several reasons, so it can't be used as a procedural parameter anyway).
Well, besides the fact that I was still mistaking the filename with the file itself, I think this "irregularity" of Reset explains a lot already!
Not really. Even if it was regular, it wouldn't match as it takes two parameters.
So, correct me if I'm wrong, but valid procedures for this parameter would be deleting, copying, and stuff like that, a bit like DirAction, right?
These would be typical examples (for DirAction it might be things like MkDir or RmDir).
But the point here is not what the procedure does, but what parameters it takes. Procedural parameters must match exactly, and since the unit declares:
type TStringProc = procedure (const s: String);
your procedure header must look exactly like this:
procedure MyFileAction (const s: String);
If you initialize the variable with an empty string, you can check this way if the file was not found. Checking for IOResult is not a valid check for file not found -- if there is no file, FindFiles will simply not call FileAction, but not set an error code.
I see. So perhaps it was always a bad idea to try to use it to define a function returning boolean.
You do this (returning the value of "global-string <> ''" in the approach I described. Or you can just return the string (with empty meaning not found).
Frank