summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/manual.asciidoc3
-rw-r--r--src/eval_env.cc3
-rw-r--r--src/ninja_test.cc9
-rw-r--r--src/parsers_test.cc12
4 files changed, 26 insertions, 1 deletions
diff --git a/doc/manual.asciidoc b/doc/manual.asciidoc
index 9ef972e..744bfcc 100644
--- a/doc/manual.asciidoc
+++ b/doc/manual.asciidoc
@@ -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
diff --git a/src/eval_env.cc b/src/eval_env.cc
index 8633f85..a5127d3 100644
--- a/src/eval_env.cc
+++ b/src/eval_env.cc
@@ -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];
diff --git a/src/ninja_test.cc b/src/ninja_test.cc
index bec038e..6e3f549 100644
--- a/src/ninja_test.cc
+++ b/src/ninja_test.cc
@@ -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 {
diff --git a/src/parsers_test.cc b/src/parsers_test.cc
index abbfb2f..2c2bdf2 100644
--- a/src/parsers_test.cc
+++ b/src/parsers_test.cc
@@ -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"