/* * CENA C++ Utilities * * by Stephane Chatty * * Copyright 1991, 1992 * Laboratoire de Recherche en Informatique (LRI) * Centre d'Etudes de la Navigation Aerienne (CENA) * * management of search paths * * $Id$ * $CurLog$ */ #include "DirPath.h" #include "String.h" #include #include #include #include /*?class CcuDirPath \typ{CcuDirPath}s generalize the idea contained in the \com{PATH} environment variable of UNIX. A \typ{CcuDirPath} is a list of strings, which are thought of as directory names. When looking for a file, each directory in the list is scanned, until the file is found or the end of the list is reached. ?*/ /*? Construct an empty directory path. ?*/ CcuDirPath :: CcuDirPath () : CcuList (), Alloc (DontAllocNames) { } /*? Construct an empty directory path. The default allocation mode is set to \var{alloc} (see function \fun{FindFile}). All other constructors initialize it to 0. ?*/ CcuDirPath :: CcuDirPath (alloc_mode alloc) : CcuList (), Alloc (alloc) { } /*? Construct a \typ{CcuDirPath} which has one element \var{name}. The string \var{name} is copied. ?*/ CcuDirPath :: CcuDirPath (const char* name) : CcuList (NewString (name)), Alloc (DontAllocNames) { } /*? Construct a \typ{CcuDirPath} with two or more elements (\var{first}, \var{second}, and so on). All strings (\var{first} and the following ones) are copied. {\bf The argument list must be null-terminated.} ?*/ CcuDirPath :: CcuDirPath (const char* first, const char*, ...) : CcuList (), Alloc (DontAllocNames) { va_list ap; va_start(ap, first); for (;;) { const char* p = va_arg(ap,char*); if (!p) break; Append (p); } va_end(ap); } /*?nodoc?*/ CcuDirPath :: ~CcuDirPath () { CcuListIter li (*this); while (++li) FreeString ((char*) (*li)); } /*?nextdoc?*/ void CcuDirPath :: Append (const char* dir) { CcuList::Append (NewString (dir)); } /*? Append (resp. prepend) a directory name to a search path. A copy of the string \var{dir} is created. ?*/ void CcuDirPath :: Prepend (const char* dir) { CcuList::Prepend (NewString (dir)); } /*?nodoc?*/ int CcuDirPath :: Remove (const char* d) { int removed = 0; CcuListIter li (*this); CcuListIter lj (*this); while (++li) { int remove = (strcmp (d, (const char*) *li) == 0); if (remove) { ++removed; RemoveAfter (lj); } else ++lj; } return removed; } /*? Search a path for a readable file with name \var{fn}. The absolute path name is returned, or 0 if the search fails. If the search succeeds, \var{alloc} determines whether the returned name should be a dynamically allocated string or not. If \var{alloc} is not null, an allocation is performed. If \var{alloc} is 0, and \var{fn} was already a full pathname, \var{fn} is returned. If \var{alloc} is 0, and \var{fn} was a relative pathname found in the search path, a named stored in a static buffer is returned. A pathname is considered a full pathname (and hence is not looked up in the search path) if it begins with ``\com{/}'', ``\com{./}'' or ``\com{../}''. ?*/ const char* CcuDirPath :: FindFile (const char* fn, alloc_mode alloc) { if (!fn) return 0; static char absfn[128]; char *dir; char* pathend; /* If fn begins with '/', './' or '../' it is considered absolute */ register const char* p = fn; while (*p == '.') ++p; if ((p - fn) <= 2 && (! *p || *p == '/')) return access (fn, R_OK) ? 0 : alloc ? NewString (fn) : fn; /* Else, look through search path */ CcuListIter it (*this) ; while (++it) { dir = (char*) (*it); strcpy (absfn, dir); pathend = absfn + strlen (dir); if (*(pathend-1) != '/') { *pathend++ = '/'; *pathend = '\0'; } strcat (absfn, fn); if (access (absfn, R_OK) == 0) return (alloc != DontAllocNames) ? NewString (absfn) : absfn; } return 0; } #ifdef DOC /*? This function is similar to the previous one. It uses the allocation mode of this \typ{CcuDirPath} to decide whether to allocate the returned string or not. ?*/ const char* CcuDirPath :: FindFile (const char* fn) { } /*? Set the allocation mode of this dir path to \var{alloc}. ?*/ void CcuDirPath :: SetAlloc (alloc_mode alloc) { } #endif /* DOC */ /*? Add the directories contained in a string of the same form as the environment variable ``PATH'', i.e. dir1:dir2:\ldots:dirN. \var{sep} is the character separating the different components. Its default value is ``:''. ?*/ void CcuDirPath :: AppendEnvPath (const char* path, char sep) { const char *dir, *next = path; for (dir = path; next; dir = next+1) { next = strchr (dir, sep); if (next != dir) CcuList::Append (next ? NewString (dir, next-dir) : NewString (dir)); } }