Index: lib/Frontend/InitHeaderSearch.cpp =================================================================== --- lib/Frontend/InitHeaderSearch.cpp (revision 117652) +++ lib/Frontend/InitHeaderSearch.cpp (working copy) @@ -67,6 +67,14 @@ void AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base, llvm::StringRef Arch, llvm::StringRef Version); + /// Flexible path base recovery - A step closer to removing hardcoded paths + std::string FindPathBase(const std::string &body,const std::string &part); + /// Returns the base or root folder of MinGW + std::string GetMinGWBase(); + /// Interacts with System using pipes to collect valuable data + std::string EvalSystemCommand(std::string cmd,bool trim); + /// Returns last two bits of info needed to make mingw paths dynamic + std::string GetMinGWVersion(const std::string & base); /// AddDelimitedPaths - Add a list of paths delimited by the system PATH /// separator. The processing follows that of the CPATH variable for gcc. @@ -414,7 +422,116 @@ } return(false); } +/** Finds full path that contains provided substring within a collection of paths. +* You can supply any Env var that holds path collections and extract paths from it +* that match a partial string. The path return is only up to the part substring so even if a path +* is mentioned that is used for BIN folder you get the actual base path. +* Search is case insensitive and should work for Win and Unix paths. If Mac and other +* platforms fail then what we consider path and name separators needs to be generalized. +* Finds the first occurance of provided parial string. +* Path separators used: :;"' +* Name separators used: forward and backward slash +* @param body string with collection of paths +* @param part partial string known to be present in our desired path base +* @return path base from last path separator until the first path separator after part +*/ +std::string InitHeaderSearch::FindPathBase(const std::string &body,const std::string &part){ + // convert to lower case for case insesitive search + std::string lbody=body; + std::transform(lbody.begin(), lbody.end(), lbody.begin(), + (int(*)(int)) std::tolower); + std::string lpart=part; + std::transform(lpart.begin(), lpart.end(), lpart.begin(), + (int(*)(int)) std::tolower); + std::string ret=""; + // locate first occurance + int plen=lpart.length(); + int blen=lbody.length(); + int state=-1; // when it reaches plen we got a match + int index=0; + for(;index0){ + char c=lbody[begin-1]; + // we try to sense a path separator + if((c==':' && lbody[begin]!='\\') || c==';' || c=='"' || c=='\'') break; + begin--; + } + // should have being and end with blen that contains part + ret=body.substr(begin,end-begin); + return ret; +} + +/** Returns the base or root folder of MinGW. + * Uses FindBasePath to recover MinGW root folder. If it fails for some reason + * defaults to c:/MinGW. With this method the only hardcoded part of MinGW header search is in + * the version. + */ +std::string InitHeaderSearch::GetMinGWBase(){ + const char * path=getenv("PATH"); + if(path==NULL) path=getenv("CPATH"); + std::string fallback="c:/mingw"; + if(path==NULL) return fallback; + std::string ret=FindPathBase(path,"/mingw"); + if(ret.empty()) return fallback; + return ret; +} + +/** Tries to execute an external command and collects the result via a pipe. +* +*/ +std::string InitHeaderSearch::EvalSystemCommand(std::string cmd,bool trim){ + const char * exe=cmd.c_str(); + const int N=4096; + char line[N]; + FILE *pipe=popen(exe,"r"); + if(pipe==NULL) return std::string(); // issue with pipe opening + std::string ret=""; + while(fgets(line,N,pipe)!=NULL){ + ret.append(line); + } + fclose(pipe); + if(trim){ + unsigned int len=ret.length(); + for(int i=len-1;i>=0;i--){ + if(ret[i]=='\n') len--; + else if(ret[i]=='\f') len--; + else if(ret[i]=='\r') len--; + else break; + } + if(len