expand $$ as $
authorEvan Martin <martine@danga.com>
Fri, 27 May 2011 03:15:05 +0000 (20:15 -0700)
committerEvan Martin <martine@danga.com>
Fri, 27 May 2011 03:15:05 +0000 (20:15 -0700)
doc/manual.asciidoc
src/eval_env.cc
src/ninja_test.cc
src/parsers_test.cc

index 9ef972eeea710b21c4425f5bf9874e4d429cc63a..744bfccff0ac84eada5f939fca98e04516e5805a 100644 (file)
@@ -375,7 +375,8 @@ A file is a series of declarations.  A declaration can be one of:
 Comments begin with `#` and extend to the end of the line.
 
 Newlines are significant, but they can be escaped by putting a `$`
-before them.
+before them.  To produce a literal `$` in a path or variable value use
+`$$`.
 
 Other whitespace is only significant if it's at the beginning of a
 line.  If a line is intended more than the previous one, it's
index 8633f855d1b53569b326a8ab847d4a9b9b19d3ca..a5127d308299a9f1349323ffb9a8f9abb5b38fa7 100644 (file)
@@ -55,6 +55,9 @@ bool EvalString::Parse(const string& input, string* err, size_t* err_index) {
       }
       parsed_.push_back(make_pair(input.substr(start, end - start), SPECIAL));
       ++end;
+    } else if (start < input.size() && input[start] == '$') {
+      parsed_.push_back(make_pair("$", RAW));
+      end = start + 1;
     } else {
       for (end = start; end < input.size(); ++end) {
         char c = input[end];
index bec038e9cde585eb903479396c5cb9598e9c3c8a..6e3f549f35744fb0aae61de5acbd985c0e43f279 100644 (file)
@@ -106,6 +106,15 @@ TEST(EvalString, Curlies) {
   env.vars["var"] = "barbar";
   EXPECT_EQ("foo barbarbaz", str.Evaluate(&env));
 }
+TEST(EvalString, Dollars) {
+  EvalString str;
+  string err;
+  EXPECT_TRUE(str.Parse("foo$$bar$bar", &err));
+  ASSERT_EQ("", err);
+  TestEnv env;
+  env.vars["bar"] = "baz";
+  EXPECT_EQ("foo$barbaz", str.Evaluate(&env));
+}
 
 struct StatTest : public StateTestWithBuiltinRules,
                   public DiskInterface {
index abbfb2fdba7502ba24a6491d4853eb4d4caa5cae..2c2bdf2e8aea5078b6d03032275cd277b7fc89a8 100644 (file)
@@ -137,6 +137,18 @@ TEST_F(ParserTest, Comment) {
   EXPECT_EQ("not # a comment", state.bindings_.LookupVariable("foo"));
 }
 
+TEST_F(ParserTest, Dollars) {
+  ASSERT_NO_FATAL_FAILURE(AssertParse(
+"rule foo\n"
+"  command = ${out}bar$$baz$$$\n"
+"blah\n"
+"x = $$dollar\n"
+"build $x: foo y\n"
+));
+  EXPECT_EQ("$dollar", state.bindings_.LookupVariable("x"));
+  EXPECT_EQ("$dollarbar$baz$blah", state.edges_[0]->EvaluateCommand());
+}
+
 TEST_F(ParserTest, CanonicalizeFile) {
   ASSERT_NO_FATAL_FAILURE(AssertParse(
 "rule cat\n"