hack: don't eat @ within arguments
authorEvan Martin <martine@danga.com>
Fri, 17 Dec 2010 23:36:16 +0000 (15:36 -0800)
committerEvan Martin <martine@danga.com>
Fri, 17 Dec 2010 23:36:31 +0000 (15:36 -0800)
src/parsers.cc
src/parsers_test.cc

index 4041bf6..cee22b7 100644 (file)
@@ -343,8 +343,14 @@ bool ManifestParser::ParseLet(string* name, string* value, string* err) {
     return false;
 
   // Do @ -> builddir substitution.
-  size_t ofs;
-  while ((ofs = value->find('@')) != string::npos) {
+  // XXX hack: we don't want to eat @ in arguments, so only do the
+  // substitution after a space.
+  size_t ofs = 0;
+  while ((ofs = value->find('@', ofs)) != string::npos) {
+    if (ofs > 0 && (*value)[ofs - 1] != ' ') {
+      ++ofs;
+      continue;
+    }
     value->replace(ofs, 1, builddir_);
     ofs += builddir_.size();
   }
index 6bd8e4b..7590a7a 100644 (file)
@@ -227,12 +227,14 @@ TEST_F(ParserTest, BuildDir) {
 "rule cat\n"
 "  command = cat @otherfile $in > $out\n"
 "build @bin: cat @a.o\n"
-"build @a.o: cat a.cc\n"));
+"build @a.o: cat a.cc\n"
+"multiple_ats = @foo bar@@baz\n"));
   EXPECT_EQ("foo", state.bindings_.LookupVariable("default_test"));
   ASSERT_TRUE(state.LookupNode("out/a.o"));
   const Rule* rule = state.LookupRule("cat");
   ASSERT_TRUE(rule);
   EXPECT_EQ("cat out/otherfile $in > $out", rule->command_.unparsed());
+  EXPECT_EQ("out/foo bar@@baz", state.bindings_.LookupVariable("multiple_ats"));
 }
 
 TEST_F(ParserTest, BuildDirRoot) {