]> git.sur5r.net Git - cc65/blobdiff - src/common/searchpath.c
Added cc65_symbol_byscope.
[cc65] / src / common / searchpath.c
index e4c4f7223cb9c6414bdcb1a57563ace2edec5354..21750229903439d01a03ecca29fc181e5938288b 100644 (file)
@@ -2,14 +2,14 @@
 /*                                                                           */
 /*                               searchpath.h                                */
 /*                                                                           */
-/*                    Search path path handling for ld65                     */
+/*                         Handling of search paths                          */
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2003 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2000-2010, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -44,6 +44,7 @@
 #endif
 
 /* common */
+#include "coll.h"
 #include "searchpath.h"
 #include "strbuf.h"
 #include "xmalloc.h"
 
 
 /*****************************************************************************/
-/*                                  Data                                    */
+/*                                  Code                                    */
 /*****************************************************************************/
 
 
 
-static char* SearchPaths[MAX_SEARCH_PATHS];
+static char* CleanupPath (const char* Path)
+/* Prepare and return a clean copy of Path */
+{
+    unsigned Len;
+    char*    NewPath;
 
+    /* Get the length of the path */
+    Len = strlen (Path);
 
+    /* Check for a trailing path separator and remove it */
+    if (Len > 0 && (Path[Len-1] == '\\' || Path[Len-1] == '/')) {
+       --Len;
+    }
 
-/*****************************************************************************/
-/*                                  Code                                    */
-/*****************************************************************************/
+    /* Allocate memory for the new string */
+    NewPath = (char*) xmalloc (Len + 1);
+
+    /* Copy the path and terminate it, then return the copy */
+    memcpy (NewPath, Path, Len);
+    NewPath [Len] = '\0';
+    return NewPath;
+}
 
 
 
-static char* Add (char* Orig, const char* New)
-/* Create a new path from Orig and New, delete Orig, return the result */
+static void Add (SearchPath* P, const char* New)
+/* Cleanup a new search path and add it to the list */
 {
-    unsigned OrigLen, NewLen;
-    char* NewPath;
-
-    /* Get the length of the original string */
-    OrigLen = Orig? strlen (Orig) : 0;
+    /* Add a clean copy of the path to the collection */
+    CollAppend (P, CleanupPath (New));
+}
 
-    /* Get the length of the new path */
-    NewLen = strlen (New);
 
-    /* Check for a trailing path separator and remove it */
-    if (NewLen > 0 && (New [NewLen-1] == '\\' || New [NewLen-1] == '/')) {
-       --NewLen;
-    }
 
-    /* Allocate memory for the new string */
-    NewPath = (char*) xmalloc (OrigLen + NewLen + 2);
+SearchPath* NewSearchPath (void)
+/* Create a new, empty search path list */
+{
+    return NewCollection ();
+}
 
-    /* Copy the strings */
-    memcpy (NewPath, Orig, OrigLen);
-    memcpy (NewPath+OrigLen, New, NewLen);
-    NewPath [OrigLen+NewLen+0] = ';';
-    NewPath [OrigLen+NewLen+1] = '\0';
 
-    /* Delete the original path */
-    xfree (Orig);
 
-    /* Return the new path */
-    return NewPath;
+void AddSearchPath (SearchPath* P, const char* NewPath)
+/* Add a new search path to the end of an existing list */
+{
+    /* Allow a NULL path */
+    if (NewPath) {
+        Add (P, NewPath);
+    }
 }
 
 
 
-static char* Find (const char* Path, const char* File)
-/* Search for a file in a list of directories. If found, return the complete
- * name including the path in a malloced data area, if not found, return 0.
+void AddSearchPathFromEnv (SearchPath* P, const char* EnvVar)
+/* Add a search path from an environment variable to the end of an existing
+ * list.
  */
 {
-    const char* P;
-    StrBuf PathName = AUTO_STRBUF_INITIALIZER;
+    AddSearchPath (P, getenv (EnvVar));
+}
 
-    /* Initialize variables */
-    P = Path;
 
-    /* Handle a NULL pointer as replacement for an empty string */
-    if (P == 0) {
-       P = "";
-    }
 
-    /* Start the search */
-    while (*P) {
-       /* Clear the string buffer */
-       SB_Clear (&PathName);
-
-        /* Copy the next path element into the buffer */
-       while (*P != '\0' && *P != ';') {
-           SB_AppendChar (&PathName, *P++);
-       }
+void AddSubSearchPathFromEnv (SearchPath* P, const char* EnvVar, const char* SubDir)
+/* Add a search path from an environment variable, adding a subdirectory to
+ * the environment variable value.
+ */
+{
+    StrBuf Dir = AUTO_STRBUF_INITIALIZER;
 
-       /* Add a path separator and the filename */
-               if (SB_NotEmpty (&PathName)) {
-           SB_AppendChar (&PathName, '/');
-       }
-       SB_AppendStr (&PathName, File);
-       SB_Terminate (&PathName);
+    const char* EnvVal = getenv (EnvVar);
+    if (EnvVal == 0) {
+       /* Not found */
+       return;
+    }
 
-       /* Check if this file exists */
-               if (access (SB_GetBuf (&PathName), 0) == 0) {
-           /* The file exists, return its name */
-           char* Name = xstrdup (SB_GetBuf (&PathName));
-           DoneStrBuf (&PathName);
-           return Name;
-       }
+    /* Copy the environment variable to the buffer */
+    SB_CopyStr (&Dir, EnvVal);
 
-       /* Skip a list separator if we have one */
-       if (*P == ';') {
-           ++P;
+    /* Add a path separator if necessary */
+    if (SB_NotEmpty (&Dir)) {
+       if (SB_LookAtLast (&Dir) != '\\' && SB_LookAtLast (&Dir) != '/') {
+           SB_AppendChar (&Dir, '/');
        }
     }
 
-    /* Not found */
-    DoneStrBuf (&PathName);
-    return 0;
+    /* Add the subdirectory and terminate the string */
+    SB_AppendStr (&Dir, SubDir);
+    SB_Terminate (&Dir);
+
+    /* Add the search path */
+    AddSearchPath (P, SB_GetConstBuf (&Dir));
+
+    /* Free the temp buffer */
+    SB_Done (&Dir);
 }
 
 
 
-void AddSearchPath (const char* NewPath, unsigned Where)
-/* Add a new search path to the existing one */
-{
-    /* Allow a NULL path */
-    if (NewPath) {
-        unsigned I;
-        for (I = 0; I < MAX_SEARCH_PATHS; ++I) {
-            unsigned Mask = (0x01U << I);
-            if (Where & Mask) {
-                SearchPaths[I] = Add (SearchPaths[I], NewPath);
-            }
-        }
+int PushSearchPath (SearchPath* P, const char* NewPath)
+/* Add a new search path to the head of an existing search path list, provided
+ * that it's not already there. If the path is already at the first position,
+ * return zero, otherwise return a non zero value.
+ */
+{                                      
+    /* Generate a clean copy of NewPath */
+    char* Path = CleanupPath (NewPath);   
+
+    /* If we have paths, check if Path is already at position zero */
+    if (CollCount (P) > 0 && strcmp (CollConstAt (P, 0), Path) == 0) {
+        /* Match. Delete the copy and return to the caller */
+        xfree (Path);
+        return 0;
     }
+
+    /* Insert a clean copy of the path at position 0, return success */
+    CollInsert (P, Path, 0);
+    return 1;
 }
 
 
 
-void AddSearchPathFromEnv (const char* EnvVar, unsigned Where)
-/* Add a search from an environment variable */
+void PopSearchPath (SearchPath* P)
+/* Remove a search path from the head of an existing search path list */
 {
-    AddSearchPath (getenv (EnvVar), Where);
+    /* Remove the path at position 0 */
+    xfree (CollAt (P, 0));
+    CollDelete (P, 0);
 }
 
 
 
-void ForgetAllSearchPaths (unsigned Where)
-/* Forget all search paths in the given lists. */
+void ForgetSearchPath (SearchPath* P)
+/* Forget all search paths in the given list */
 {
     unsigned I;
-    for (I = 0; I < MAX_SEARCH_PATHS; ++I) {
-        unsigned Mask = (0x01U << I);
-        if (Where & Mask) {
-            xfree (SearchPaths[I]);
-            SearchPaths[I] = 0;
-        }
+    for (I = 0; I < CollCount (P); ++I) {
+        xfree (CollAt (P, I));
     }
+    CollDeleteAll (P);
 }
 
 
 
-char* SearchFile (const char* Name, unsigned Where)
+char* SearchFile (const SearchPath* P, const char* File)
 /* Search for a file in a list of directories. Return a pointer to a malloced
  * area that contains the complete path, if found, return 0 otherwise.
  */
 {
+    char* Name = 0;
+    StrBuf PathName = AUTO_STRBUF_INITIALIZER;
+
+    /* Start the search */
     unsigned I;
-    for (I = 0; I < MAX_SEARCH_PATHS; ++I) {
-        unsigned Mask = (0x01U << I);
-        if (Where & Mask) {
-            char* Path = Find (SearchPaths[I], Name);
-            if (Path) {
-                /* Found the file */
-                return Path;
-            }
-        }
+    for (I = 0; I < CollCount (P); ++I) {
+
+        /* Copy the next path element into the buffer */
+        SB_CopyStr (&PathName, CollConstAt (P, I));
+
+       /* Add a path separator and the filename */
+               if (SB_NotEmpty (&PathName)) {
+           SB_AppendChar (&PathName, '/');
+       }
+       SB_AppendStr (&PathName, File);
+       SB_Terminate (&PathName);
+
+       /* Check if this file exists */
+               if (access (SB_GetBuf (&PathName), 0) == 0) {
+           /* The file exists, we're done */
+           Name = xstrdup (SB_GetBuf (&PathName));
+            break;
+       }
     }
-    return 0;
+
+    /* Cleanup and return the result of the search */
+    SB_Done (&PathName);
+    return Name;
 }