[C++] Fix comment_in_command.mk
diff --git a/func.cc b/func.cc
index 41d3471..9cb86c1 100644
--- a/func.cc
+++ b/func.cc
@@ -40,6 +40,60 @@
namespace {
+// TODO: This code is very similar to
+// NinjaGenerator::TranslateCommand. Factor them out.
+shared_ptr<string> StripShellComment(shared_ptr<string> cmd) {
+ if (cmd->find('#') == string::npos)
+ return cmd;
+
+ shared_ptr<string> res = make_shared<string>();
+ bool prev_backslash = false;
+ // Set space as an initial value so the leading comment will be
+ // stripped out.
+ char prev_char = ' ';
+ char quote = 0;
+ bool done = false;
+ const char* in = cmd->c_str();
+ for (; *in && !done; in++) {
+ switch (*in) {
+ case '#':
+ if (quote == 0 && isspace(prev_char)) {
+ while (*in && *in != '\n')
+ in++;
+ break;
+ }
+
+ case '\'':
+ case '"':
+ case '`':
+ if (quote) {
+ if (quote == *in)
+ quote = 0;
+ } else if (!prev_backslash) {
+ quote = *in;
+ }
+ *res += *in;
+ break;
+
+ case '\\':
+ *res += '\\';
+ break;
+
+ default:
+ *res += *in;
+ }
+
+ if (*in == '\\') {
+ prev_backslash = !prev_backslash;
+ } else {
+ prev_backslash = false;
+ }
+
+ prev_char = *in;
+ }
+ return res;
+}
+
void PatsubstFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
shared_ptr<string> pat_str = args[0]->Eval(ev);
shared_ptr<string> repl = args[1]->Eval(ev);
@@ -437,7 +491,7 @@
shared_ptr<string> cmd = args[0]->Eval(ev);
if (ev->avoid_io() && !HasNoIoInShellScript(*cmd)) {
*s += "$(";
- *s += *cmd;
+ *s += *StripShellComment(cmd);
*s += ")";
return;
}
diff --git a/ninja.cc b/ninja.cc
index 3598beb..a562b12 100644
--- a/ninja.cc
+++ b/ninja.cc
@@ -207,12 +207,12 @@
// stripped out.
char prev_char = ' ';
char quote = 0;
- bool done = false;
- for (; *in && !done; in++) {
+ for (; *in; in++) {
switch (*in) {
case '#':
if (quote == 0 && isspace(prev_char)) {
- done = true;
+ while (in[1] && *in != '\n')
+ in++;
} else {
*cmd_buf += *in;
}
diff --git a/testcase/comment_in_command.mk b/testcase/comment_in_command.mk
index 41fad51..881a241 100644
--- a/testcase/comment_in_command.mk
+++ b/testcase/comment_in_command.mk
@@ -1,5 +1,3 @@
-# TODO(c-ninja): Fix
-
MAKEVER:=$(shell make --version | ruby -n0e 'puts $$_[/Make (\d)/,1]')
test1:
@@ -19,7 +17,11 @@
test3: $(shell echo foo #)
test4:
- echo $(shell echo OK #)
+ echo $(shell echo OK # FAIL \
+ FAIL2)
+
+test5:
+ echo $(shell echo $$(echo PASS))
foo:
echo OK
diff --git a/testcase/escape_for_shell_in_recipe.mk b/testcase/escape_for_shell_in_recipe.mk
new file mode 100644
index 0000000..29b5fcf
--- /dev/null
+++ b/testcase/escape_for_shell_in_recipe.mk
@@ -0,0 +1,7 @@
+# TODO(ninja): The first testcase fails due to an extra escape. We
+# should be careful not to break the second case when we fix the first
+# case.
+
+test:
+ echo $(shell echo \"" # "\")
+ echo $$(echo \"" # "\")