Skip to content

Commit 19eb924

Browse files
committed
Check for ninja_required_version when $^ escape is used
1 parent 90f226b commit 19eb924

File tree

7 files changed

+47
-4
lines changed

7 files changed

+47
-4
lines changed

src/lexer.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222

2323
using namespace std;
2424

25+
// $^ supported starting this version
26+
const int minNewlineEscapeVersionMajor = 1;
27+
const int minNewlineEscapeVersionMinor = 14;
28+
2529
bool Lexer::Error(const string& message, string* err) {
2630
// Compute line/column.
2731
int line = 1;
@@ -753,6 +757,16 @@ bool Lexer::ReadEvalString(EvalString* eval, bool path, string* err) {
753757
yy81:
754758
++p;
755759
{
760+
if (!newline_version_checked_)
761+
{
762+
if ((manifest_version_major < minNewlineEscapeVersionMajor) ||
763+
(manifest_version_major = minNewlineEscapeVersionMajor &&
764+
manifest_version_minor < minNewlineEscapeVersionMinor))
765+
{
766+
return Error("using $^ escape requires specifying 'ninja_required_version' with version greater or equal 1.14", err);
767+
}
768+
newline_version_checked_ = true;
769+
}
756770
eval->AddText(StringPiece("\n", 1));
757771
continue;
758772
}

src/lexer.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ struct Lexer {
9090
/// Construct an error message with context.
9191
bool Error(const std::string& message, std::string* err);
9292

93+
/// Parsed 'ninja_required_version' from the manifest.
94+
int manifest_version_major = 0;
95+
int manifest_version_minor = 0;
96+
9397
private:
9498
/// Skip past whitespace (called after each read token/ident/etc.).
9599
void EatWhitespace();
@@ -101,6 +105,9 @@ struct Lexer {
101105
StringPiece input_;
102106
const char* ofs_;
103107
const char* last_token_;
108+
109+
/// Holds true if ninja_required_version checked for $^ (newline) escape.
110+
bool newline_version_checked_ = false;
104111
};
105112

106113
#endif // NINJA_LEXER_H_

src/lexer.in.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121

2222
using namespace std;
2323

24+
// $^ supported starting this version
25+
const int minNewlineEscapeVersionMajor = 1;
26+
const int minNewlineEscapeVersionMinor = 14;
27+
2428
bool Lexer::Error(const string& message, string* err) {
2529
// Compute line/column.
2630
int line = 1;
@@ -260,6 +264,16 @@ bool Lexer::ReadEvalString(EvalString* eval, bool path, string* err) {
260264
continue;
261265
}
262266
"$^" {
267+
if (!newline_version_checked_)
268+
{
269+
if ((manifest_version_major < minNewlineEscapeVersionMajor) ||
270+
(manifest_version_major = minNewlineEscapeVersionMajor &&
271+
manifest_version_minor < minNewlineEscapeVersionMinor))
272+
{
273+
return Error("using $^ escape requires specifying 'ninja_required_version' with version greater or equal 1.14", err);
274+
}
275+
newline_version_checked_ = true;
276+
}
263277
eval->AddText(StringPiece("\n", 1));
264278
continue;
265279
}

src/lexer_test.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,14 @@ TEST(Lexer, EscapedNewlines) {
101101
Lexer lexer("foo$\nbar$^newline foo\n");
102102
EvalString eval;
103103
string err;
104+
EXPECT_FALSE(lexer.ReadVarValue(&eval, &err));
105+
EXPECT_EQ("input:1: using $^ escape requires specifying 'ninja_required_version' with version greater or equal 1.14\n", err);
106+
107+
lexer.manifest_version_major = 1;
108+
lexer.manifest_version_minor = 14;
109+
110+
eval.Clear();
111+
err = "";
104112
EXPECT_TRUE(lexer.ReadVarValue(&eval, &err));
105113
EXPECT_EQ("", err);
106114
EXPECT_EQ("[foobar\nnewline foo]", eval.Serialize());

src/manifest_parser.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ bool ManifestParser::Parse(const string& filename, const string& input,
6868
// Check ninja_required_version immediately so we can exit
6969
// before encountering any syntactic surprises.
7070
if (name == "ninja_required_version")
71-
CheckNinjaVersion(value);
71+
CheckNinjaVersion(value, lexer_.manifest_version_major, lexer_.manifest_version_minor);
7272
env_->AddBinding(name, value);
7373
break;
7474
}

src/version.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,9 @@ void ParseVersion(const string& version, int* major, int* minor) {
3333
}
3434
}
3535

36-
void CheckNinjaVersion(const string& version) {
36+
void CheckNinjaVersion(const string& version, int &file_major, int &file_minor) {
3737
int bin_major, bin_minor;
3838
ParseVersion(kNinjaVersion, &bin_major, &bin_minor);
39-
int file_major, file_minor;
4039
ParseVersion(version, &file_major, &file_minor);
4140

4241
if (bin_major > file_major) {

src/version.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ void ParseVersion(const std::string& version, int* major, int* minor);
2626

2727
/// Check whether \a version is compatible with the current Ninja version,
2828
/// aborting if not.
29-
void CheckNinjaVersion(const std::string& required_version);
29+
void CheckNinjaVersion(const std::string& required_version, int &file_major,
30+
int &file_minor);
3031

3132
#endif // NINJA_VERSION_H_

0 commit comments

Comments
 (0)