+ return Pos;
+}
+
+/// SubstituteEnv - Given '$ENV(VAR_NAME)', output 'getenv("VAR_NAME")'. Helper
+/// function used by SubstituteSpecialCommands().
+StrVector::const_iterator
+SubstituteEnv (StrVector::const_iterator Pos,
+ StrVector::const_iterator End, raw_ostream& O)
+{
+ const char* errorMessage = "Syntax error in $ENV invocation!";
+ CheckedIncrement(Pos, End, errorMessage);
+ const std::string& EnvName = *Pos;
+
+ if (EnvName == ")")
+ throw "$ENV invocation: empty argument list!";
+
+ O << "checkCString(std::getenv(\"";
+ O << EnvName;
+ O << "\"))";
+
+ CheckedIncrement(Pos, End, errorMessage);
+
+ return Pos;
+}
+
+/// SubstituteSpecialCommands - Given an invocation of $CALL or $ENV, output
+/// handler code. Helper function used by EmitCmdLineVecFill().
+StrVector::const_iterator
+SubstituteSpecialCommands (StrVector::const_iterator Pos,
+ StrVector::const_iterator End,
+ bool IsJoin, raw_ostream& O)
+{
+
+ const std::string& cmd = *Pos;
+
+ // Perform substitution.
+ if (cmd == "$CALL") {
+ Pos = SubstituteCall(Pos, End, IsJoin, O);
+ }
+ else if (cmd == "$ENV") {
+ Pos = SubstituteEnv(Pos, End, O);
+ }
+ else {
+ throw "Unknown special command: " + cmd;
+ }
+
+ // Handle '$CMD(ARG)/additional/text'.
+ const std::string& Leftover = *Pos;
+ assert(Leftover.at(0) == ')');
+ if (Leftover.size() != 1)
+ O << " + std::string(\"" << (Leftover.c_str() + 1) << "\")";
+
+ return Pos;
+}
+
+/// EmitCmdLineVecFill - Emit code that fills in the command line
+/// vector. Helper function used by EmitGenerateActionMethod().
+void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName,
+ bool IsJoin, unsigned IndentLevel,
+ raw_ostream& O) {
+ StrVector StrVec;
+ TokenizeCmdLine(InitPtrToString(CmdLine), StrVec);
+
+ if (StrVec.empty())
+ throw "Tool '" + ToolName + "' has empty command line!";
+
+ StrVector::const_iterator B = StrVec.begin(), E = StrVec.end();
+
+ // Emit the command itself.
+ assert(!StrVec[0].empty());
+ O.indent(IndentLevel) << "cmd = ";
+ if (StrVec[0][0] == '$') {
+ B = SubstituteSpecialCommands(B, E, IsJoin, O);
+ ++B;
+ }
+ else {
+ O << '"' << StrVec[0] << '"';
+ ++B;
+ }
+ O << ";\n";
+
+ // Go through the command arguments.
+ assert(B <= E);
+ for (; B != E; ++B) {
+ const std::string& cmd = *B;
+
+ assert(!cmd.empty());
+ O.indent(IndentLevel);
+
+ if (cmd.at(0) == '$') {
+ O << "vec.push_back(std::make_pair(0, ";
+ B = SubstituteSpecialCommands(B, E, IsJoin, O);
+ O << "));\n";