Browse Source

+ MacOS support

Tomas Hajny 21 years ago
parent
commit
af1ab052af
1 changed files with 112 additions and 51 deletions
  1. 112 51
      rtl/inc/fexpand.inc

+ 112 - 51
rtl/inc/fexpand.inc

@@ -23,12 +23,32 @@
  {$ENDIF FPC_FEXPAND_DRIVES}
  {$ENDIF FPC_FEXPAND_DRIVES}
 {$ENDIF FPC_FEXPAND_VOLUMES}
 {$ENDIF FPC_FEXPAND_VOLUMES}
 
 
+{$IFDEF FPC_FEXPAND_DIRSEP_IS_CURDIR}
+ {$IFNDEF FPC_FEXPAND_DRIVES}
+  (* If DirectorySeparator at the beginning marks a relative path, *)
+  (* an absolute path must always begin with a drive or volume.    *)
+  {$DEFINE FPC_FEXPAND_DRIVES}
+ {$ENDIF FPC_FEXPAND_DRIVES}
+ {$IFNDEF FPC_FEXPAND_MULTIPLE_UPDIR}
+  (* Traversing multiple levels at once explicitely allowed. *)
+  {$DEFINE FPC_FEXPAND_MULTIPLE_UPDIR}
+ {$ENDIF FPC_FEXPAND_MULTIPLE_UPDIR}
+ (* Helper define used to support common features of FPC_FEXPAND_DIRSEP_IS_* *)
+ {$DEFINE FPC_FEXPAND_UPDIR_HELPER}
+{$ENDIF FPC_FEXPAND_DIRSEP_IS_CURDIR}
+
 {$IFDEF FPC_FEXPAND_DIRSEP_IS_UPDIR}
 {$IFDEF FPC_FEXPAND_DIRSEP_IS_UPDIR}
- {$IFNDEF FPC_FEXPAND_DRIVESEP_IS_ROOT}
-  (* If DriveSeparator is used for upper directory,       *)
-  (* it cannot be used for marking root at the same time. *)
-  {$DEFINE FPC_FEXPAND_DRIVESEP_IS_ROOT}
- {$ENDIF FPC_FEXPAND_DRIVESEP_IS_ROOT}
+ {$IFNDEF FPC_FEXPAND_DRIVES}
+  (* If DirectorySeparator at the beginning marks a relative path, *)
+  (* an absolute path must always begin with a drive or volume.    *)
+  {$DEFINE FPC_FEXPAND_DRIVES}
+ {$ENDIF FPC_FEXPAND_DRIVES}
+ {$IFNDEF FPC_FEXPAND_MULTIPLE_UPDIR}
+  (* Traversing multiple levels at once explicitely allowed. *)
+  {$DEFINE FPC_FEXPAND_MULTIPLE_UPDIR}
+ {$ENDIF FPC_FEXPAND_MULTIPLE_UPDIR}
+ (* Helper define used to support common features of FPC_FEXPAND_DIRSEP_IS_* *)
+ {$DEFINE FPC_FEXPAND_UPDIR_HELPER}
 {$ENDIF FPC_FEXPAND_DIRSEP_IS_UPDIR}
 {$ENDIF FPC_FEXPAND_DIRSEP_IS_UPDIR}
 
 
 procedure GetDirIO (DriveNr: byte; var Dir: OpenString);
 procedure GetDirIO (DriveNr: byte; var Dir: OpenString);
@@ -47,7 +67,7 @@ end;
 
 
 
 
 {$IFDEF FPC_FEXPAND_VOLUMES}
 {$IFDEF FPC_FEXPAND_VOLUMES}
-{$IFNDEF FPC_FEXPAND_NO_DEFAULT_PATHS}
+ {$IFNDEF FPC_FEXPAND_NO_DEFAULT_PATHS}
 procedure GetDirIO (const VolumeName: OpenString; var Dir: OpenString);
 procedure GetDirIO (const VolumeName: OpenString; var Dir: OpenString);
 
 
 var
 var
@@ -58,7 +78,7 @@ begin
   GetDir (VolumeName, Dir);
   GetDir (VolumeName, Dir);
   InOutRes := OldInOutRes;
   InOutRes := OldInOutRes;
 end;
 end;
-{$ENDIF FPC_FEXPAND_NO_DEFAULT_PATHS}
+ {$ENDIF FPC_FEXPAND_NO_DEFAULT_PATHS}
 {$ENDIF FPC_FEXPAND_VOLUMES}
 {$ENDIF FPC_FEXPAND_VOLUMES}
 
 
 
 
@@ -69,10 +89,10 @@ function FExpand (const Path: PathStr): PathStr;
    In addition, FPC_FEXPAND_UNC, FPC_FEXPAND_DRIVES, FPC_FEXPAND_GETENV_PCHAR,
    In addition, FPC_FEXPAND_UNC, FPC_FEXPAND_DRIVES, FPC_FEXPAND_GETENV_PCHAR,
    FPC_FEXPAND_TILDE, FPC_FEXPAND_VOLUMES, FPC_FEXPAND_NO_DEFAULT_PATHS,
    FPC_FEXPAND_TILDE, FPC_FEXPAND_VOLUMES, FPC_FEXPAND_NO_DEFAULT_PATHS,
    FPC_FEXPAND_DRIVESEP_IS_ROOT, FPC_FEXPAND_NO_CURDIR,
    FPC_FEXPAND_DRIVESEP_IS_ROOT, FPC_FEXPAND_NO_CURDIR,
-   FPC_FEXPAND_NO_DOTS_UPDIR and FPC_FEXPAND_DIRSEP_IS_UPDIR conditionals might
-   be defined to specify FExpand behaviour - see end of this file for
+   FPC_FEXPAND_NO_DOTS_UPDIR, FPC_FEXPAND_DIRSEP_IS_UPDIR,
+   FPC_FEXPAND_DIRSEP_IS_CURDIR and FPC_FEXPAND_MULTIPLE_UPDIR conditionals
+   might be defined to specify FExpand behaviour - see end of this file for
    individual descriptions.
    individual descriptions.
-
 *)
 *)
 
 
 {$IFDEF FPC_FEXPAND_DRIVES}
 {$IFDEF FPC_FEXPAND_DRIVES}
@@ -108,17 +128,18 @@ begin
 (* by converting all to the native one.           *)
 (* by converting all to the native one.           *)
     if DirectorySeparator = '\' then
     if DirectorySeparator = '\' then
     {Allow slash as backslash}
     {Allow slash as backslash}
-        begin
-            for I := 1 to Length (Pa) do
-                if Pa [I] = '/' then
-                    Pa [I] := DirectorySeparator
-        end
+      begin
+        for I := 1 to Length (Pa) do
+          if Pa [I] = '/' then
+            Pa [I] := DirectorySeparator
+      end
     else
     else
+      if DirectorySeparator = '\' then
     {Allow backslash as slash}
     {Allow backslash as slash}
         begin
         begin
-            for I := 1 to Length (Pa) do
-                if Pa [I] = '\' then
-                    Pa [I] := DirectorySeparator;
+          for I := 1 to Length (Pa) do
+            if Pa [I] = '\' then
+              Pa [I] := DirectorySeparator;
         end;
         end;
 
 
 (* PathStart is amount of characters to strip to get beginning *)
 (* PathStart is amount of characters to strip to get beginning *)
@@ -235,17 +256,18 @@ begin
  {$ENDIF FPC_FEXPAND_DRIVESEP_IS_ROOT}
  {$ENDIF FPC_FEXPAND_DRIVESEP_IS_ROOT}
 {$ENDIF FPC_FEXPAND_VOLUMES}
 {$ENDIF FPC_FEXPAND_VOLUMES}
 
 
-(* Do we have an absolute path? *)
-{$IFDEF FPC_FEXPAND_DRIVES}
+(* Do we have an absolute path without drive or volume? *)
+{$IFNDEF FPC_FEXPAND_DIRSEP_IS_CURDIR}
+ {$IFDEF FPC_FEXPAND_DRIVES}
             if (Length (Pa) > 0)
             if (Length (Pa) > 0)
- {$IFDEF FPC_FEXPAND_DRIVESEP_IS_ROOT}
+  {$IFDEF FPC_FEXPAND_DRIVESEP_IS_ROOT}
                                  and (Pa [1] = DriveSeparator)
                                  and (Pa [1] = DriveSeparator)
- {$ELSE FPC_FEXPAND_DRIVESEP_IS_ROOT}
+  {$ELSE FPC_FEXPAND_DRIVESEP_IS_ROOT}
                                  and (Pa [1] = DirectorySeparator)
                                  and (Pa [1] = DirectorySeparator)
- {$ENDIF FPC_FEXPAND_DRIVESEP_IS_ROOT}
+  {$ENDIF FPC_FEXPAND_DRIVESEP_IS_ROOT}
                                                                    then
                                                                    then
                 begin
                 begin
- {$IFDEF FPC_FEXPAND_UNC}
+  {$IFDEF FPC_FEXPAND_UNC}
                     {Do not touch network drive names}
                     {Do not touch network drive names}
                     if (Length (Pa) > 1) and (Pa [2] = DirectorySeparator)
                     if (Length (Pa) > 1) and (Pa [2] = DirectorySeparator)
                                                             and LFNSupport then
                                                             and LFNSupport then
@@ -274,32 +296,38 @@ begin
                                     end;
                                     end;
                         end
                         end
                     else
                     else
- {$ENDIF FPC_FEXPAND_UNC}
- {$IFDEF FPC_FEXPAND_VOLUMES}
+  {$ENDIF FPC_FEXPAND_UNC}
+  {$IFDEF FPC_FEXPAND_VOLUMES}
                         begin
                         begin
                             I := Pos (DriveSeparator, S);
                             I := Pos (DriveSeparator, S);
-  {$IFDEF FPC_FEXPAND_DIRSEP_IS_UPDIR}
-   {$IFDEF FPC_FEXPAND_DRIVESEP_IS_ROOT}
+   {$IFDEF FPC_FEXPAND_DIRSEP_IS_UPDIR}
+    {$IFDEF FPC_FEXPAND_DRIVESEP_IS_ROOT}
                             if (Pa [1] = DriveSeparator) then
                             if (Pa [1] = DriveSeparator) then
                                 Delete (Pa, 1, 1);
                                 Delete (Pa, 1, 1);
-   {$ENDIF FPC_FEXPAND_DRIVESEP_IS_ROOT}
+    {$ENDIF FPC_FEXPAND_DRIVESEP_IS_ROOT}
                             Pa := Copy (S, 1, I) + Pa;
                             Pa := Copy (S, 1, I) + Pa;
                             PathStart := I;
                             PathStart := I;
-  {$ELSE FPC_FEXPAND_DIRSEP_IS_UPDIR}
+   {$ELSE FPC_FEXPAND_DIRSEP_IS_UPDIR}
                             Pa := Copy (S, 1, Pred (I)) + DriveSeparator + Pa;
                             Pa := Copy (S, 1, Pred (I)) + DriveSeparator + Pa;
                             PathStart := Succ (I);
                             PathStart := Succ (I);
-  {$ENDIF FPC_FEXPAND_DIRSEP_IS_UPDIR}
+   {$ENDIF FPC_FEXPAND_DIRSEP_IS_UPDIR}
                         end;
                         end;
- {$ELSE FPC_FEXPAND_VOLUMES}
+  {$ELSE FPC_FEXPAND_VOLUMES}
                         Pa := S [1] + DriveSeparator + Pa;
                         Pa := S [1] + DriveSeparator + Pa;
- {$ENDIF FPC_FEXPAND_VOLUMES}
+  {$ENDIF FPC_FEXPAND_VOLUMES}
                 end
                 end
             else
             else
-{$ENDIF FPC_FEXPAND_DRIVES}
+ {$ENDIF FPC_FEXPAND_DRIVES}
 
 
                 (* We already have a slash if root is the curent directory. *)
                 (* We already have a slash if root is the curent directory. *)
                 if Length (S) = PathStart then
                 if Length (S) = PathStart then
                     Pa := S + Pa
                     Pa := S + Pa
+{$ELSE FPC_FEXPAND_DIRSEP_IS_CURDIR}
+                (* More complex with DirectorySeparator as current directory *)
+                if (S [Length (S)] = DriveSeparator)
+                                         and (Pa [1] = DirectorySeparator) then
+                    Pa := S + Copy (Pa, 2, Pred (Length (Pa)))
+{$ENDIF FPC_FEXPAND_DIRSEP_IS_CURDIR}
                 else
                 else
 
 
                     (* We need an ending slash if FExpand was called  *)
                     (* We need an ending slash if FExpand was called  *)
@@ -312,11 +340,11 @@ begin
                         Pa := S + DirectorySeparator
                         Pa := S + DirectorySeparator
 {$ENDIF FPC_FEXPAND_DIRSEP_IS_UPDIR}
 {$ENDIF FPC_FEXPAND_DIRSEP_IS_UPDIR}
                     else
                     else
- {$IFDEF FPC_FEXPAND_DIRSEP_IS_UPDIR}
+{$IFDEF FPC_FEXPAND_UPDIR_HELPER}
                         if Pa [1] = DirectorySeparator then
                         if Pa [1] = DirectorySeparator then
                             Pa := S + Pa
                             Pa := S + Pa
                         else
                         else
- {$ENDIF FPC_FEXPAND_DIRSEP_IS_UPDIR}
+{$ENDIF FPC_FEXPAND_UPDIR_HELPER}
                         Pa := S + DirectorySeparator + Pa;
                         Pa := S + DirectorySeparator + Pa;
         end;
         end;
 
 
@@ -324,6 +352,7 @@ begin
     Dirs := Copy (Pa, Succ (PathStart), Length (Pa) - PathStart);
     Dirs := Copy (Pa, Succ (PathStart), Length (Pa) - PathStart);
 
 
 {$IFNDEF FPC_FEXPAND_NO_CURDIR}
 {$IFNDEF FPC_FEXPAND_NO_CURDIR}
+ {$IFNDEF FPC_FEXPAND_DIRSEP_IS_CURDIR}
     {First remove all references to '\.\'}
     {First remove all references to '\.\'}
     I := Pos (DirectorySeparator + '.' + DirectorySeparator, Dirs);
     I := Pos (DirectorySeparator + '.' + DirectorySeparator, Dirs);
     while I <> 0 do
     while I <> 0 do
@@ -331,9 +360,20 @@ begin
             Delete (Dirs, I, 2);
             Delete (Dirs, I, 2);
             I := Pos (DirectorySeparator + '.' + DirectorySeparator, Dirs);
             I := Pos (DirectorySeparator + '.' + DirectorySeparator, Dirs);
         end;
         end;
+ {$ENDIF FPC_FEXPAND_DIRSEP_IS_CURDIR}
 {$ENDIF FPC_FEXPAND_NO_CURDIR}
 {$ENDIF FPC_FEXPAND_NO_CURDIR}
 
 
 {$IFNDEF FPC_FEXPAND_NO_DOTS_UPDIR}
 {$IFNDEF FPC_FEXPAND_NO_DOTS_UPDIR}
+ {$IFDEF FPC_FEXPAND_MULTIPLE_UPDIR}
+    {Now replace all references to '\...' with '\..\..'}
+    I := Pos (DirectorySeparator + '...', Dirs);
+    while I <> 0 do
+        begin
+            Insert (DirectorySeparator + '.', Dirs, I + 3);
+            I := Pos (DirectorySeparator + '...', Dirs);
+        end;
+ {$ENDIF FPC_FEXPAND_MULTIPLE_UPDIR}
+
     {Now remove also all references to '\..\' + of course previous dirs..}
     {Now remove also all references to '\..\' + of course previous dirs..}
     I := Pos (DirectorySeparator + '..' + DirectorySeparator, Dirs);
     I := Pos (DirectorySeparator + '..' + DirectorySeparator, Dirs);
     while I <> 0 do
     while I <> 0 do
@@ -346,7 +386,7 @@ begin
         end;
         end;
 {$ENDIF FPC_FEXPAND_NO_DOTS_UPDIR}
 {$ENDIF FPC_FEXPAND_NO_DOTS_UPDIR}
 
 
-{$IFDEF FPC_FEXPAND_DIRSEP_IS_UPDIR}
+{$IFDEF FPC_FEXPAND_UPDIR_HELPER}
     (* Now remove all references to '//' plus previous directories... *)
     (* Now remove all references to '//' plus previous directories... *)
     I := Pos (DirectorySeparator + DirectorySeparator, Dirs);
     I := Pos (DirectorySeparator + DirectorySeparator, Dirs);
     while I <> 0 do
     while I <> 0 do
@@ -357,7 +397,7 @@ begin
             Delete (Dirs, Succ (J), Succ (I - J));
             Delete (Dirs, Succ (J), Succ (I - J));
             I := Pos (DirectorySeparator + DirectorySeparator, Dirs);
             I := Pos (DirectorySeparator + DirectorySeparator, Dirs);
         end;
         end;
-{$ENDIF FPC_FEXPAND_DIRSEP_IS_UPDIR}
+{$ENDIF FPC_FEXPAND_UPDIR_HELPER}
 
 
 {$IFNDEF FPC_FEXPAND_NO_DOTS_UPDIR}
 {$IFNDEF FPC_FEXPAND_NO_DOTS_UPDIR}
     {Then remove also a reference to '\..' at the end of line
     {Then remove also a reference to '\..' at the end of line
@@ -392,6 +432,7 @@ begin
 {$ENDIF FPC_FEXPAND_DIRSEP_IS_UPDIR}
 {$ENDIF FPC_FEXPAND_DIRSEP_IS_UPDIR}
 
 
 {$IFNDEF FPC_FEXPAND_NO_CURDIR}
 {$IFNDEF FPC_FEXPAND_NO_CURDIR}
+ {$IFNDEF FPC_FEXPAND_DIRSEP_IS_CURDIR}
     {...and also a possible reference to '\.'}
     {...and also a possible reference to '\.'}
     if (Length (Dirs) = 1) then
     if (Length (Dirs) = 1) then
         begin
         begin
@@ -408,6 +449,7 @@ begin
     while (Length (Dirs) >= 2) and (Dirs [1] = '.')
     while (Length (Dirs) >= 2) and (Dirs [1] = '.')
                                          and (Dirs [2] = DirectorySeparator) do
                                          and (Dirs [2] = DirectorySeparator) do
         Delete (Dirs, 1, 2);
         Delete (Dirs, 1, 2);
+ {$ENDIF FPC_FEXPAND_DIRSEP_IS_CURDIR}
 {$ENDIF FPC_FEXPAND_NO_CURDIR}
 {$ENDIF FPC_FEXPAND_NO_CURDIR}
 
 
 {$IFDEF FPC_FEXPAND_DIRSEP_IS_UPDIR}
 {$IFDEF FPC_FEXPAND_DIRSEP_IS_UPDIR}
@@ -425,8 +467,10 @@ begin
 
 
     {Two special cases - '.' and '..' alone}
     {Two special cases - '.' and '..' alone}
 {$IFNDEF FPC_FEXPAND_NO_CURDIR}
 {$IFNDEF FPC_FEXPAND_NO_CURDIR}
+ {$IFNDEF FPC_FEXPAND_DIRSEP_IS_CURDIR}
     if (Length (Dirs) = 1) and (Dirs [1] = '.') then
     if (Length (Dirs) = 1) and (Dirs [1] = '.') then
         Dirs := '';
         Dirs := '';
+ {$ENDIF FPC_FEXPAND_DIRSEP_IS_CURDIR}
 {$ENDIF FPC_FEXPAND_NO_CURDIR}
 {$ENDIF FPC_FEXPAND_NO_CURDIR}
 {$IFNDEF FPC_FEXPAND_NO_DOTS_UPDIR}
 {$IFNDEF FPC_FEXPAND_NO_DOTS_UPDIR}
     if (Length (Dirs) = 2) and (Dirs [1] = '.') and (Dirs [2] = '.') then
     if (Length (Dirs) = 2) and (Dirs [1] = '.') and (Dirs [2] = '.') then
@@ -451,9 +495,11 @@ begin
     if (Pa [Length (Pa)] = DirectorySeparator)
     if (Pa [Length (Pa)] = DirectorySeparator)
          and ((Length (Pa) > PathStart) or
          and ((Length (Pa) > PathStart) or
 {A special case with UNC paths}
 {A special case with UNC paths}
-            (RootNotNeeded and (Length (Pa) = PathStart))) and
-                     (Length (Path) <> 0)
-                          and (Path [Length (Path)] <> DirectorySeparator) then
+            (RootNotNeeded and (Length (Pa) = PathStart)))
+    {Reference to current directory at the end should be removed}
+                    and (Length (Path) <> 0)
+                          and (Path [Length (Path)] <> DirectorySeparator)
+                                                                           then
         Dec (Pa [0]);
         Dec (Pa [0]);
 {$ENDIF FPC_FEXPAND_DIRSEP_IS_UPDIR}
 {$ENDIF FPC_FEXPAND_DIRSEP_IS_UPDIR}
 
 
@@ -499,9 +545,9 @@ end;
    should be used as beginning of the "real" path for a particular
    should be used as beginning of the "real" path for a particular
    drive or volume instead of the DirectorySeparator. This would be
    drive or volume instead of the DirectorySeparator. This would be
    used in case that there is only one character (DriveSeparator)
    used in case that there is only one character (DriveSeparator)
-   delimiting the drive letter or volume name from the remaining
-   path _and_ the DriveSeparator marks the root of an absolute path.
-   Example - 'Volume:This/Is/Absolute/Path'.
+   delimitting the drive letter or volume name from the remaining
+   path _and_ the DriveSeparator marks the root of an absolute path
+   in that case. Example - 'Volume:This/Is/Absolute/Path'.
 
 
    FPC_FEXPAND_NO_CURDIR - there is no support to refer to current
    FPC_FEXPAND_NO_CURDIR - there is no support to refer to current
    directory explicitely (like '.' used under both Unix and DOS-like
    directory explicitely (like '.' used under both Unix and DOS-like
@@ -510,17 +556,32 @@ end;
    FPC_FEXPAND_NO_DOTS_UPDIR - '..' cannot be used to refer to the
    FPC_FEXPAND_NO_DOTS_UPDIR - '..' cannot be used to refer to the
    upper directory.
    upper directory.
 
 
-   FPC_FEXPAND_DIRSEP_IS_UPDIR - DirectorySeparator at the beginning of a
-   path (or doubled DirectorySeparator inside the path) refer to the
-   upper directory. Please, note that you can decide to support both '..'
-   and DirectorySeparator as references to the parent directory at the
-   same time for compatibility reasons (although that means that you'd
-   make it impossible to use an otherwise valid name of '..').
+   FPC_FEXPAND_DIRSEP_IS_UPDIR - DirectorySeparator at the beginning of
+   a path (or doubled DirectorySeparator inside the path) refer to the
+   parent directory, one more DirectorySeparator to parent directory of
+   parent directory and so on (Amiga). Please, note that you can decide
+   to support both '..' and DirectorySeparator as references to the parent
+   directory at the same time for compatibility reasons - however this
+   support makes it impossible to use an otherwise possibly valid name
+   of '..'.
+
+   FPC_FEXPAND_DIRSEP_IS_CURDIR - DirectorySeparator at the beginning of
+   a path refers to the current directory (i.e. path beginning with
+   DirectorySeparator is always a relative path). Two DirectorySeparator
+   characters refer to the parent directory, three refer to parent
+   directory of the parent directory and so on (MacOS).
+
+   FPC_FEXPAND_MULTIPLE_UPDIR - grouping of more characters specifying
+   upper directory references higher directory levels. Example: '...'
+   (Netware).
 *)
 *)
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.16  2004-05-29 18:25:21  hajny
+  Revision 1.17  2004-11-21 14:45:17  hajny
+    + MacOS support
+
+  Revision 1.16  2004/05/29 18:25:21  hajny
     * description of individual conditional defines added
     * description of individual conditional defines added
 
 
   Revision 1.15  2002/12/07 16:26:39  hajny
   Revision 1.15  2002/12/07 16:26:39  hajny