Recent

Author Topic: osutil.inc - GetAppConfigDir() Global and other puzzlements  (Read 904 times)

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 941
  • Former Delphi 1-7, 10.2 User
Background: I'm trying to come up with a patch for macOS so that the "correct" path for GetAppConfigDir is returned (https://bugs.freepascal.org/view.php?id=20706 - ignore the function proposed there as it uses the File Manager API which is deprecated in macOS 10.8 and later).

From osutil.inc:

Code: Pascal  [Select][+][-]
  1. Function DGetAppConfigDir(Global : Boolean) : String;
  2.  
  3. begin
  4.   Result:=ExcludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)));
  5. end;
  6.  

Where does the Global boolean get actioned?

Code: Pascal  [Select][+][-]
  1. { ---------------------------------------------------------------------
  2.     Fallback implementations for AppConfigDir implementation.
  3.   ---------------------------------------------------------------------}
  4. {
  5.  If a particular OS does it different:
  6.  - set the HAVE_OSCONFIG define before including sysutils.inc.
  7.  - implement the functions.
  8.  Default config assumes a DOS-like configuration.
  9. }
  10.  
  11. {$ifndef HAS_OSCONFIG}
  12. Function GetAppConfigDir(Global : Boolean) : String;
  13.  
  14. begin
  15.   Result:=DGetAppConfigDir(Global);
  16. end;
  17.  

1) Is the HAVE_OSCONFIG in the comment wrong as the code uses HAS_OSCONFIG ?

2) How to specify darwin? Obviously {$if define(darwin)} would do it, but in the context of using HAS/HAVE_OSCONFIG how does one do it? I couldn't see any examples in the code. I'm guessing that in sysutils.inc:

Code: Pascal  [Select][+][-]
  1. {$if define(darwin)}
  2. Function GetAppConfigDir(Global : Boolean) : String;
  3. begin
  4.   // fill in body
  5. end;
  6.  
  7. Function GetAppConfigFile(Global : Boolean; SubDir : Boolean) : String;
  8.  
  9. begin
  10.  // fill in body
  11. end;
  12.  
  13. {$define HAS_OSCONFIG}
  14. {$endif darwin}
  15.  
  16. { OS utility code }
  17. {$i osutil.inc}
  18.  

Am I close?

3) What does "Default config assumes a DOS-like configuration." mean?

Still in osutil.inc, should not:

Code: Pascal  [Select][+][-]
  1. Function GetAppConfigFile(Global : Boolean) : String;
  2.  
  3. begin
  4.   Result:=GetAppConfigFile(Global,False);
  5. end;
  6.  

in fact be:

Code: Pascal  [Select][+][-]
  1. Function DGetAppConfigFile(Global : Boolean) : String;
  2.  
  3. begin
  4.   Result:=GetAppConfigFile(Global,False);
  5. end;
  6.  

That is, the D prefix is missing on the function definition?
o Lazarus v2.1.0 r63871, FPC v3.3.1 r46876, macOS 10.14.6 (with sup update), Xcode 11.3.1
o Lazarus v2.1.0 r61574, FPC v3.3.1 r42318, FreeBSD 12.1 amd64 (VMware Fusion VM)
o FPC 3.0.4, FreeBSD 12.2-STABLE r365646 amd64
o Lazarus v2.1.0 r61574, FPC v3.0.4, Ubuntu 18.04 (Parallels VM)

PascalDragon

  • Hero Member
  • *****
  • Posts: 2132
  • Compiler Developer
Re: osutil.inc - GetAppConfigDir() Global and other puzzlements
« Reply #1 on: May 28, 2020, 04:54:36 pm »
Background: I'm trying to come up with a patch for macOS so that the "correct" path for GetAppConfigDir is returned (https://bugs.freepascal.org/view.php?id=20706 - ignore the function proposed there as it uses the File Manager API which is deprecated in macOS 10.8 and later).

Your function will nevertheless work with older versions as well? Minimum supported version currently is 10.4.

From osutil.inc:

Code: Pascal  [Select][+][-]
  1. Function DGetAppConfigDir(Global : Boolean) : String;
  2.  
  3. begin
  4.   Result:=ExcludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)));
  5. end;
  6.  

Where does the Global boolean get actioned?

Nowhere. That's why it is the default/fallback implementation. For *nix systems HAS_OSCONFIG is set as well and implemented in rtl/unix/sysutils.pp.

Code: Pascal  [Select][+][-]
  1. { ---------------------------------------------------------------------
  2.     Fallback implementations for AppConfigDir implementation.
  3.   ---------------------------------------------------------------------}
  4. {
  5.  If a particular OS does it different:
  6.  - set the HAVE_OSCONFIG define before including sysutils.inc.
  7.  - implement the functions.
  8.  Default config assumes a DOS-like configuration.
  9. }
  10.  
  11. {$ifndef HAS_OSCONFIG}
  12. Function GetAppConfigDir(Global : Boolean) : String;
  13.  
  14. begin
  15.   Result:=DGetAppConfigDir(Global);
  16. end;
  17.  

1) Is the HAVE_OSCONFIG in the comment wrong as the code uses HAS_OSCONFIG ?

Correct. I have fixed the comment.

2) How to specify darwin? Obviously {$if define(darwin)} would do it, but in the context of using HAS/HAVE_OSCONFIG how does one do it? I couldn't see any examples in the code. I'm guessing that in sysutils.inc:

Code: Pascal  [Select][+][-]
  1. {$if define(darwin)}
  2. Function GetAppConfigDir(Global : Boolean) : String;
  3. begin
  4.   // fill in body
  5. end;
  6.  
  7. Function GetAppConfigFile(Global : Boolean; SubDir : Boolean) : String;
  8.  
  9. begin
  10.  // fill in body
  11. end;
  12.  
  13. {$define HAS_OSCONFIG}
  14. {$endif darwin}
  15.  
  16. { OS utility code }
  17. {$i osutil.inc}
  18.  

Am I close?

Not quite. You need to implement your check for DARWIN inside rtl/unix/sysutils.pp as that already provides GetAppConfigFile and GetAppConfigDir itself.

3) What does "Default config assumes a DOS-like configuration." mean?

Exactly what you noticed above: there is no difference between global and user configuration. This comment refers to the default implementation of DGetAppConfigDir.

Still in osutil.inc, should not:

Code: Pascal  [Select][+][-]
  1. Function GetAppConfigFile(Global : Boolean) : String;
  2.  
  3. begin
  4.   Result:=GetAppConfigFile(Global,False);
  5. end;
  6.  

in fact be:

Code: Pascal  [Select][+][-]
  1. Function DGetAppConfigFile(Global : Boolean) : String;
  2.  
  3. begin
  4.   Result:=GetAppConfigFile(Global,False);
  5. end;
  6.  

That is, the D prefix is missing on the function definition?

No. The function GetAppConfigFile with one argument is simply a convenience function for GetAppConfigFile with two arguments as such it is not a default implementation (like DGetAppConfigDir and DGetAppConfigFile), but the final implementation.

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 941
  • Former Delphi 1-7, 10.2 User
Re: osutil.inc - GetAppConfigDir() Global and other puzzlements
« Reply #2 on: May 29, 2020, 02:50:08 am »
Thanks, that clears up a few puzzlements.

Back to osutil.inc, I dislocated the D I was talking about... this is what is there:

Code: Pascal  [Select][+][-]
  1. Function GetAppConfigFile(Global : Boolean) : String;
  2.  
  3. begin
  4.   Result:=GetAppConfigFile(Global,False);
  5. end;
  6.  

Should it not be:

Code: Pascal  [Select][+][-]
  1. Function GetAppConfigFile(Global : Boolean) : String;
  2.  
  3. begin
  4.   Result:=DGetAppConfigFile(Global,False);  <--------- with D
  5. end;
  6.  

which is the pattern that the other functions follow? Otherwise you have GetAppConfigFile() calling itself infinitely.
o Lazarus v2.1.0 r63871, FPC v3.3.1 r46876, macOS 10.14.6 (with sup update), Xcode 11.3.1
o Lazarus v2.1.0 r61574, FPC v3.3.1 r42318, FreeBSD 12.1 amd64 (VMware Fusion VM)
o FPC 3.0.4, FreeBSD 12.2-STABLE r365646 amd64
o Lazarus v2.1.0 r61574, FPC v3.0.4, Ubuntu 18.04 (Parallels VM)

lucamar

  • Hero Member
  • *****
  • Posts: 3025
Re: osutil.inc - GetAppConfigDir() Global and other puzzlements
« Reply #3 on: May 29, 2020, 04:38:35 am »
Should it not be:
Code: Pascal  [Select][+][-]
  1. Function GetAppConfigFile(Global : Boolean) : String;
  2. begin
  3.   Result:=DGetAppConfigFile(Global,False);  <--------- with D
  4. end;
which is the pattern that the other functions follow? Otherwise you have GetAppConfigFile() calling itself infinitely.

No, it calls other overload, the one that accepts two parameters, which is where all is done. This wouldn't be needed if there was only one function declared as:

Code: Pascal  [Select][+][-]
  1. function GetAppConfigFile(Global: Boolean; SubDir: Boolean = False):string;
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.8/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

PascalDragon

  • Hero Member
  • *****
  • Posts: 2132
  • Compiler Developer
Re: osutil.inc - GetAppConfigDir() Global and other puzzlements
« Reply #4 on: May 29, 2020, 09:12:47 am »
Thanks, that clears up a few puzzlements.

Back to osutil.inc, I dislocated the D I was talking about... this is what is there:

Code: Pascal  [Select][+][-]
  1. Function GetAppConfigFile(Global : Boolean) : String;
  2.  
  3. begin
  4.   Result:=GetAppConfigFile(Global,False);
  5. end;
  6.  

Should it not be:

Code: Pascal  [Select][+][-]
  1. Function GetAppConfigFile(Global : Boolean) : String;
  2.  
  3. begin
  4.   Result:=DGetAppConfigFile(Global,False);  <--------- with D
  5. end;
  6.  

which is the pattern that the other functions follow? Otherwise you have GetAppConfigFile() calling itself infinitely.

I'll simply repeat what I wrote in my previous post:

No. The function GetAppConfigFile with one argument is simply a convenience function for GetAppConfigFile with two arguments as such it is not a default implementation (like DGetAppConfigDir and DGetAppConfigFile), but the final implementation.

And as lucamar said, that function is not calling itself, because it calls the function with two parameters.

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 941
  • Former Delphi 1-7, 10.2 User
Re: osutil.inc - GetAppConfigDir() Global and other puzzlements
« Reply #5 on: May 29, 2020, 09:59:17 am »
Thanks to both of you - I finally got it  :-[
o Lazarus v2.1.0 r63871, FPC v3.3.1 r46876, macOS 10.14.6 (with sup update), Xcode 11.3.1
o Lazarus v2.1.0 r61574, FPC v3.3.1 r42318, FreeBSD 12.1 amd64 (VMware Fusion VM)
o FPC 3.0.4, FreeBSD 12.2-STABLE r365646 amd64
o Lazarus v2.1.0 r61574, FPC v3.0.4, Ubuntu 18.04 (Parallels VM)

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 941
  • Former Delphi 1-7, 10.2 User
Re: osutil.inc - GetAppConfigDir() Global and other puzzlements
« Reply #6 on: May 29, 2020, 02:59:19 pm »
Just noticed:

Your function will nevertheless work with older versions as well? Minimum supported version currently is 10.4.

Yes - NSSearchPathForDirectoriesInDomains() from the Foundation framework applies from macOS 10.0+ so works with every version to date and is not already deprecated. Handy, because I don't see any way to #ifdef a macOS version.
o Lazarus v2.1.0 r63871, FPC v3.3.1 r46876, macOS 10.14.6 (with sup update), Xcode 11.3.1
o Lazarus v2.1.0 r61574, FPC v3.3.1 r42318, FreeBSD 12.1 amd64 (VMware Fusion VM)
o FPC 3.0.4, FreeBSD 12.2-STABLE r365646 amd64
o Lazarus v2.1.0 r61574, FPC v3.0.4, Ubuntu 18.04 (Parallels VM)

lucamar

  • Hero Member
  • *****
  • Posts: 3025
Re: osutil.inc - GetAppConfigDir() Global and other puzzlements
« Reply #7 on: May 29, 2020, 04:55:22 pm »
Handy, because I don't see any way to #ifdef a macOS version.

I would matter little, if anything at all, since $IFDEF only works at compilation time and it would compile into your binary a call to a possibly incorrect function. What would work is getting the version at run-time and selecting (or setting a pointer to) one or other call accordingly :)
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.8/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 941
  • Former Delphi 1-7, 10.2 User
Re: osutil.inc - GetAppConfigDir() Global and other puzzlements
« Reply #8 on: May 30, 2020, 03:06:55 am »
You are so right - my usual context of compiling an application/library/daemon/kernel loadable module is substantially different to that of a compiler. I've only ever done the former, so it's a learning process for an old dog seeking new tricks. Thanks for your insights.
o Lazarus v2.1.0 r63871, FPC v3.3.1 r46876, macOS 10.14.6 (with sup update), Xcode 11.3.1
o Lazarus v2.1.0 r61574, FPC v3.3.1 r42318, FreeBSD 12.1 amd64 (VMware Fusion VM)
o FPC 3.0.4, FreeBSD 12.2-STABLE r365646 amd64
o Lazarus v2.1.0 r61574, FPC v3.0.4, Ubuntu 18.04 (Parallels VM)

PascalDragon

  • Hero Member
  • *****
  • Posts: 2132
  • Compiler Developer
Re: osutil.inc - GetAppConfigDir() Global and other puzzlements
« Reply #9 on: May 30, 2020, 11:18:34 am »
You are so right - my usual context of compiling an application/library/daemon/kernel loadable module is substantially different to that of a compiler. I've only ever done the former, so it's a learning process for an old dog seeking new tricks. Thanks for your insights.

To be fair, you are not working on the compiler, but the RTL (aka Run Time Library). The only difference is that it comes precompiled instead of you compiling it together with your application. Thus the RTL needs to determine more things at runtime. Just like it determines at runtime whether it can use SSE2 for System.Move for example (for i386). After all you could use the code on an older Pentium that doesn't support SSE yet... Or using newer functionality of Windows 10 while still supporting Windows XP.

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 941
  • Former Delphi 1-7, 10.2 User
Re: osutil.inc - GetAppConfigDir() Global and other puzzlements
« Reply #10 on: May 30, 2020, 03:05:40 pm »
I have the GetAppConfigDir and GetAppConfigFile x2 functions working standalone, but to incorporate them into sysutils.pp I need CocoaAll and MacOSAll in the Uses clause... except it cannot find them if I add them there :(

Any hints?
o Lazarus v2.1.0 r63871, FPC v3.3.1 r46876, macOS 10.14.6 (with sup update), Xcode 11.3.1
o Lazarus v2.1.0 r61574, FPC v3.3.1 r42318, FreeBSD 12.1 amd64 (VMware Fusion VM)
o FPC 3.0.4, FreeBSD 12.2-STABLE r365646 amd64
o Lazarus v2.1.0 r61574, FPC v3.0.4, Ubuntu 18.04 (Parallels VM)

PascalDragon

  • Hero Member
  • *****
  • Posts: 2132
  • Compiler Developer
Re: osutil.inc - GetAppConfigDir() Global and other puzzlements
« Reply #11 on: May 30, 2020, 07:08:46 pm »
I have the GetAppConfigDir and GetAppConfigFile x2 functions working standalone, but to incorporate them into sysutils.pp I need CocoaAll and MacOSAll in the Uses clause... except it cannot find them if I add them there :(

Any hints?

You can't use the CocoaAll or MacOSAll units inside the SysUtils unit (or anything that's part of the RTL) as the latter is compiled before the packages are compiled. If you can't provide the necessary types, functions, etc. by hand you'll have to use a callback function approach that can be set up in some unit that can access the units.

 

TinyPortal © 2005-2018