+ Last = true;
+ }
+ else {
+ Out = MakeTempFile(TempDir, In.getBasename(), CurTool->OutputSuffix());
+ }
+
+ if (int ret = CurTool->GenerateAction(In, Out, InLangs).Execute())
+ throw error_code(ret);
+
+ if (Last)
+ return;
+
+ CurNode = &getNode(ChooseEdge(CurNode->OutEdges,
+ InLangs,
+ CurNode->Name())->ToolName());
+ In = Out; Out.clear();
+ }
+}
+
+// Find the head of the toolchain corresponding to the given file.
+// Also, insert an input language into InLangs.
+const Node* CompilationGraph::
+FindToolChain(const sys::Path& In, const std::string* forceLanguage,
+ InputLanguagesSet& InLangs) const {
+
+ // Determine the input language.
+ const std::string& InLanguage =
+ forceLanguage ? *forceLanguage : GetLanguage(In);
+
+ // Add the current input language to the input language set.
+ InLangs.insert(InLanguage);
+
+ // Find the toolchain for the input language.
+ const tools_vector_type& TV = getToolsVector(InLanguage);
+ if (TV.empty())
+ throw std::runtime_error("No toolchain corresponding to language "
+ + InLanguage + " found");
+ return &getNode(ChooseEdge(TV, InLangs)->ToolName());
+}
+
+// Helper function used by Build().
+// Traverses initial portions of the toolchains (up to the first Join node).
+// This function is also responsible for handling the -x option.
+void CompilationGraph::BuildInitial (InputLanguagesSet& InLangs,
+ const sys::Path& TempDir) {
+ // This is related to -x option handling.
+ cl::list<std::string>::const_iterator xIter = Languages.begin(),
+ xBegin = xIter, xEnd = Languages.end();
+ bool xEmpty = true;
+ const std::string* xLanguage = 0;
+ unsigned xPos = 0, xPosNext = 0, filePos = 0;
+
+ if (xIter != xEnd) {
+ xEmpty = false;
+ xPos = Languages.getPosition(xIter - xBegin);
+ cl::list<std::string>::const_iterator xNext = llvm::next(xIter);
+ xPosNext = (xNext == xEnd) ? std::numeric_limits<unsigned>::max()
+ : Languages.getPosition(xNext - xBegin);
+ xLanguage = (*xIter == "none") ? 0 : &(*xIter);
+ }
+
+ // For each input file:
+ for (cl::list<std::string>::const_iterator B = InputFilenames.begin(),
+ CB = B, E = InputFilenames.end(); B != E; ++B) {
+ sys::Path In = sys::Path(*B);
+
+ // Code for handling the -x option.
+ // Output: std::string* xLanguage (can be NULL).
+ if (!xEmpty) {
+ filePos = InputFilenames.getPosition(B - CB);
+
+ if (xPos < filePos) {
+ if (filePos < xPosNext) {
+ xLanguage = (*xIter == "none") ? 0 : &(*xIter);
+ }
+ else { // filePos >= xPosNext
+ // Skip xIters while filePos > xPosNext
+ while (filePos > xPosNext) {
+ ++xIter;
+ xPos = xPosNext;
+
+ cl::list<std::string>::const_iterator xNext = llvm::next(xIter);
+ if (xNext == xEnd)
+ xPosNext = std::numeric_limits<unsigned>::max();
+ else
+ xPosNext = Languages.getPosition(xNext - xBegin);
+ xLanguage = (*xIter == "none") ? 0 : &(*xIter);
+ }
+ }
+ }
+ }