#include #include #include #include "SearchPath.h" const char SearchPath::dirSep = '/'; const char SearchPath::pathSep = ':'; SearchPath::SearchPath( const char *envar, const string &fallbacks ) { if (envar) { const char * const envalue = getenv( envar ); if (envalue) addPaths( envalue ); } if (empty()) addPaths( fallbacks ); } void SearchPath::addPaths( const string &paths ) { typedef string::size_type pos; pos begin = 0; for (;;) { const pos end = paths.find( pathSep, begin ); if (end == string::npos) { addPath( paths.substr( begin ) ); break; } else { addPath( paths.substr( begin, end - begin ) ); begin = end + 1; } } } void SearchPath::addPath( const string &path ) { if (!path.empty()) push_back( path + dirSep ); } DIR *SearchPath::opendir( string &target ) const { for (const_iterator candidate = begin(); candidate != end(); candidate++) { const string fullname = *candidate + target; DIR * const directory = ::opendir( fullname.c_str() ); if (directory) { target = fullname; return directory; } } return 0; } FILE *SearchPath::openSource( string &target ) const { for (const_iterator candidate = begin(); candidate != end(); candidate++) { FILE *file; if ((file = tryOpen( *candidate, target, "ti" ))) return file; if ((file = tryOpen( *candidate, target, "java" ))) return file; } return 0; } FILE *SearchPath::tryOpen( const string &directory, string &target, const char suffix[] ) const { const string fullname = directory + target + '.' + suffix; FILE * const file = ti_fopen( fullname.c_str(), "r" ); if (file) { target = fullname; return file; } else return 0; } /* special versions of fopen/fclose that maintain filename info */ static map fname_map; FILE *ti_fopen(const char *path, const char *mode) { FILE *fp = ::fopen(path, mode); if (fp) { char fullpath[PATH_MAX]; /* make path canonical */ if (!realpath(path,fullpath)) strcpy(fullpath, path); fname_map[fp] = new string(fullpath); } return fp; } int ti_fclose(FILE *stream) { int retval = ::fclose(stream); if (!retval) { map::iterator it = fname_map.find(stream); delete (*it).second; fname_map.erase(it); } return retval; } string *ti_fname(FILE *stream) { return fname_map[stream]; }