X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcommon%2Fsearchpath.c;h=21750229903439d01a03ecca29fc181e5938288b;hb=0d8e8a95338560a1e0d96258d6def311cf2ad368;hp=2f536388bca3ecd9c66d6c4273b06978aa34d4dd;hpb=a9e46e245aa7b5c914c95b3314c21548ccb77f75;p=cc65 diff --git a/src/common/searchpath.c b/src/common/searchpath.c index 2f536388b..217502299 100644 --- a/src/common/searchpath.c +++ b/src/common/searchpath.c @@ -2,11 +2,11 @@ /* */ /* searchpath.h */ /* */ -/* Search path path handling for ld65 */ +/* Handling of search paths */ /* */ /* */ /* */ -/* (C) 2000-2009, Ullrich von Bassewitz */ +/* (C) 2000-2010, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -44,6 +44,7 @@ #endif /* common */ +#include "coll.h" #include "searchpath.h" #include "strbuf.h" #include "xmalloc.h" @@ -51,136 +52,75 @@ /*****************************************************************************/ -/* Data */ +/* Code */ /*****************************************************************************/ -static char* SearchPaths[MAX_SEARCH_PATHS]; - - - -/*****************************************************************************/ -/* Code */ -/*****************************************************************************/ - - - -static char* Add (char* Orig, const char* New) -/* Create a new path from Orig and New, delete Orig, return the result */ +static char* CleanupPath (const char* Path) +/* Prepare and return a clean copy of Path */ { - unsigned OrigLen, NewLen; - char* NewPath; - - /* Get the length of the original string */ - OrigLen = Orig? strlen (Orig) : 0; + unsigned Len; + char* NewPath; - /* Get the length of the new path */ - NewLen = strlen (New); + /* Get the length of the path */ + Len = strlen (Path); /* Check for a trailing path separator and remove it */ - if (NewLen > 0 && (New [NewLen-1] == '\\' || New [NewLen-1] == '/')) { - --NewLen; + if (Len > 0 && (Path[Len-1] == '\\' || Path[Len-1] == '/')) { + --Len; } /* Allocate memory for the new string */ - NewPath = (char*) xmalloc (OrigLen + NewLen + 2); + NewPath = (char*) xmalloc (Len + 1); - /* 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 */ + /* Copy the path and terminate it, then return the copy */ + memcpy (NewPath, Path, Len); + NewPath [Len] = '\0'; return 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. - */ +static void Add (SearchPath* P, const char* New) +/* Cleanup a new search path and add it to the list */ { - const char* P; - StrBuf PathName = AUTO_STRBUF_INITIALIZER; - - /* 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++); - } - - /* Add a path separator and the filename */ - if (SB_NotEmpty (&PathName)) { - SB_AppendChar (&PathName, '/'); - } - SB_AppendStr (&PathName, File); - SB_Terminate (&PathName); + /* Add a clean copy of the path to the collection */ + CollAppend (P, CleanupPath (New)); +} - /* Check if this file exists */ - if (access (SB_GetBuf (&PathName), 0) == 0) { - /* The file exists, return its name */ - char* Name = xstrdup (SB_GetBuf (&PathName)); - SB_Done (&PathName); - return Name; - } - /* Skip a list separator if we have one */ - if (*P == ';') { - ++P; - } - } - /* Not found */ - SB_Done (&PathName); - return 0; +SearchPath* NewSearchPath (void) +/* Create a new, empty search path list */ +{ + return NewCollection (); } -void AddSearchPath (const char* NewPath, unsigned Where) -/* Add a new search path to the existing one */ +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) { - unsigned I; - for (I = 0; I < MAX_SEARCH_PATHS; ++I) { - unsigned Mask = (0x01U << I); - if (Where & Mask) { - SearchPaths[I] = Add (SearchPaths[I], NewPath); - } - } + Add (P, NewPath); } } -void AddSearchPathFromEnv (const char* EnvVar, unsigned Where) -/* Add a search path from an environment variable */ +void AddSearchPathFromEnv (SearchPath* P, const char* EnvVar) +/* Add a search path from an environment variable to the end of an existing + * list. + */ { - AddSearchPath (getenv (EnvVar), Where); + AddSearchPath (P, getenv (EnvVar)); } -void AddSubSearchPathFromEnv (const char* EnvVar, const char* SubDir, unsigned Where) +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. */ @@ -203,14 +143,12 @@ void AddSubSearchPathFromEnv (const char* EnvVar, const char* SubDir, unsigned W } } - /* Add the subdirectory */ + /* Add the subdirectory and terminate the string */ SB_AppendStr (&Dir, SubDir); - - /* Terminate the string */ SB_Terminate (&Dir); /* Add the search path */ - AddSearchPath (SB_GetConstBuf (&Dir), Where); + AddSearchPath (P, SB_GetConstBuf (&Dir)); /* Free the temp buffer */ SB_Done (&Dir); @@ -218,38 +156,84 @@ void AddSubSearchPathFromEnv (const char* EnvVar, const char* SubDir, unsigned W -void ForgetAllSearchPaths (unsigned Where) -/* Forget all search paths in the given lists. */ +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 PopSearchPath (SearchPath* P) +/* Remove a search path from the head of an existing search path list */ +{ + /* Remove the path at position 0 */ + xfree (CollAt (P, 0)); + CollDelete (P, 0); +} + + + +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; }