X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcommon%2Fsearchpath.c;h=21750229903439d01a03ecca29fc181e5938288b;hb=0d8e8a95338560a1e0d96258d6def311cf2ad368;hp=e8883f63c5e00e8d676033dee27cf81b197b14f0;hpb=3629c9ac7ce203c46b5228906cc93d5c94bb5636;p=cc65 diff --git a/src/common/searchpath.c b/src/common/searchpath.c index e8883f63c..217502299 100644 --- a/src/common/searchpath.c +++ b/src/common/searchpath.c @@ -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 */ @@ -33,7 +33,6 @@ -#include #include #include #if defined(_MSC_VER) @@ -45,157 +44,196 @@ #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; + /* Add a clean copy of the path to the collection */ + CollAppend (P, CleanupPath (New)); +} - /* Get the length of the original string */ - OrigLen = Orig? strlen (Orig) : 0; - /* 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; - } +SearchPath* NewSearchPath (void) +/* Create a new, empty search path list */ +{ + return NewCollection (); +} - /* Allocate memory for the new string */ - NewPath = (char*) xmalloc (OrigLen + NewLen + 2); - /* 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); +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); + } +} - /* Return the new path */ - return NewPath; + + +void AddSearchPathFromEnv (SearchPath* P, const char* EnvVar) +/* Add a search path from an environment variable to the end of an existing + * list. + */ +{ + AddSearchPath (P, getenv (EnvVar)); } -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 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. */ { - const char* P; - int Max; - char PathName [FILENAME_MAX]; - - /* Initialize variables */ - Max = sizeof (PathName) - strlen (File) - 2; - if (Max < 0) { - return 0; - } - P = Path; + StrBuf Dir = AUTO_STRBUF_INITIALIZER; - /* Handle a NULL pointer as replacement for an empty string */ - if (P == 0) { - P = ""; + const char* EnvVal = getenv (EnvVar); + if (EnvVal == 0) { + /* Not found */ + return; } - /* Start the search */ - while (*P) { - /* Copy the next path element into the buffer */ - int Count = 0; - while (*P != '\0' && *P != ';' && Count < Max) { - PathName [Count++] = *P++; - } + /* Copy the environment variable to the buffer */ + SB_CopyStr (&Dir, EnvVal); - /* Add a path separator and the filename */ - if (Count) { - PathName [Count++] = '/'; + /* Add a path separator if necessary */ + if (SB_NotEmpty (&Dir)) { + if (SB_LookAtLast (&Dir) != '\\' && SB_LookAtLast (&Dir) != '/') { + SB_AppendChar (&Dir, '/'); } - strcpy (PathName + Count, File); + } - /* Check if this file exists */ - if (access (PathName, 0) == 0) { - /* The file exists */ - return xstrdup (PathName); - } + /* Add the subdirectory and terminate the string */ + SB_AppendStr (&Dir, SubDir); + SB_Terminate (&Dir); - /* Skip a list separator if we have one */ - if (*P == ';') { - ++P; - } + /* Add the search path */ + AddSearchPath (P, SB_GetConstBuf (&Dir)); + + /* Free the temp buffer */ + SB_Done (&Dir); +} + + + +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; } - /* Not found */ - return 0; + /* Insert a clean copy of the path at position 0, return success */ + CollInsert (P, Path, 0); + return 1; } -void AddSearchPath (const char* NewPath, unsigned Where) -/* Add a new search path to the existing one */ +void PopSearchPath (SearchPath* P) +/* Remove a search path from the head of an existing search path list */ { - /* 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); - } - } - } + /* Remove the path at position 0 */ + xfree (CollAt (P, 0)); + CollDelete (P, 0); } -void AddSearchPathFromEnv (const char* EnvVar, unsigned Where) -/* Add a search from an environment variable */ +void ForgetSearchPath (SearchPath* P) +/* Forget all search paths in the given list */ { - AddSearchPath (getenv (EnvVar), Where); + unsigned I; + 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; }