diff options
Diffstat (limited to 'src/depfile_parser.cc')
-rw-r--r-- | src/depfile_parser.cc | 222 |
1 files changed, 125 insertions, 97 deletions
diff --git a/src/depfile_parser.cc b/src/depfile_parser.cc index 7cee892..405289f 100644 --- a/src/depfile_parser.cc +++ b/src/depfile_parser.cc @@ -1,4 +1,4 @@ -/* Generated by re2c 0.13.5 */ +/* Generated by re2c 1.1.1 */ // Copyright 2011 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,6 +14,12 @@ // limitations under the License. #include "depfile_parser.h" +#include "util.h" + +DepfileParser::DepfileParser(DepfileParserOptions options) + : options_(options) +{ +} // A note on backslashes in Makefiles, from reading the docs: // Backslash-newline is the line continuation character. @@ -35,8 +41,13 @@ bool DepfileParser::Parse(string* content, string* err) { // parsing_targets: whether we are parsing targets or dependencies. char* in = &(*content)[0]; char* end = in + content->size(); + bool have_target = false; + bool have_secondary_target_on_this_rule = false; + bool have_newline_since_primary_target = false; + bool warned_distinct_target_lines = false; bool parsing_targets = true; while (in < end) { + bool have_newline = false; // out: current output point (typically same as in, but can fall behind // as we de-escape backslashes). char* out = in; @@ -45,6 +56,7 @@ bool DepfileParser::Parse(string* content, string* err) { for (;;) { // start: beginning of the current parsed span. const char* start = in; + char* yymarker = NULL; { unsigned char yych; @@ -53,7 +65,7 @@ bool DepfileParser::Parse(string* content, string* err) { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 128, 0, 0, 0, 0, 0, 0, + 0, 128, 0, 0, 0, 128, 0, 0, 128, 128, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 0, 128, 0, 0, @@ -82,88 +94,55 @@ bool DepfileParser::Parse(string* content, string* err) { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, }; - yych = *in; - if (yych <= '=') { - if (yych <= '$') { - if (yych <= ' ') { - if (yych <= 0x00) goto yy7; - goto yy9; - } else { - if (yych <= '!') goto yy5; - if (yych <= '#') goto yy9; - goto yy4; - } + if (yybm[0+yych] & 128) { + goto yy9; + } + if (yych <= '\r') { + if (yych <= '\t') { + if (yych >= 0x01) goto yy4; } else { - if (yych <= '*') { - if (yych <= '\'') goto yy9; - if (yych <= ')') goto yy5; - goto yy9; - } else { - if (yych <= ':') goto yy5; - if (yych <= '<') goto yy9; - goto yy5; - } + if (yych <= '\n') goto yy6; + if (yych <= '\f') goto yy4; + goto yy8; } } else { - if (yych <= '_') { - if (yych <= '[') { - if (yych <= '?') goto yy9; - if (yych <= 'Z') goto yy5; - goto yy9; - } else { - if (yych <= '\\') goto yy2; - if (yych <= '^') goto yy9; - goto yy5; - } + if (yych <= '$') { + if (yych <= '#') goto yy4; + goto yy12; } else { - if (yych <= '|') { - if (yych <= '`') goto yy9; - if (yych <= '{') goto yy5; - goto yy9; - } else { - if (yych == 0x7F) goto yy9; - goto yy5; - } + if (yych == '\\') goto yy13; + goto yy4; } } -yy2: ++in; - if ((yych = *in) <= '"') { - if (yych <= '\f') { - if (yych <= 0x00) goto yy3; - if (yych != '\n') goto yy14; - } else { - if (yych <= '\r') goto yy3; - if (yych == ' ') goto yy16; - goto yy14; - } - } else { - if (yych <= 'Z') { - if (yych <= '#') goto yy16; - if (yych == '*') goto yy16; - goto yy14; - } else { - if (yych <= '\\') goto yy16; - if (yych == '|') goto yy16; - goto yy14; - } + { + break; } -yy3: +yy4: + ++in; +yy5: { // For any other character (e.g. whitespace), swallow it here, // allowing the outer logic to loop around again. break; } -yy4: - yych = *++in; - if (yych == '$') goto yy12; - goto yy3; -yy5: - ++in; - yych = *in; - goto yy11; yy6: + ++in; + { + // A newline ends the current file name and the current rule. + have_newline = true; + break; + } +yy8: + yych = *++in; + if (yych == '\n') goto yy6; + goto yy5; +yy9: + yych = *++in; + if (yybm[0+yych] & 128) { + goto yy9; + } { // Got a span of plain text. int len = (int)(in - start); @@ -173,30 +152,41 @@ yy6: out += len; continue; } -yy7: - ++in; - { - break; - } -yy9: +yy12: yych = *++in; - goto yy3; -yy10: - ++in; - yych = *in; -yy11: - if (yybm[0+yych] & 128) { - goto yy10; + if (yych == '$') goto yy14; + goto yy5; +yy13: + yych = *(yymarker = ++in); + if (yych <= '"') { + if (yych <= '\f') { + if (yych <= 0x00) goto yy5; + if (yych == '\n') goto yy18; + goto yy16; + } else { + if (yych <= '\r') goto yy20; + if (yych == ' ') goto yy22; + goto yy16; + } + } else { + if (yych <= 'Z') { + if (yych <= '#') goto yy22; + if (yych == '*') goto yy22; + goto yy16; + } else { + if (yych <= ']') goto yy22; + if (yych == '|') goto yy22; + goto yy16; + } } - goto yy6; -yy12: +yy14: ++in; { // De-escape dollar character. *out++ = '$'; continue; } -yy14: +yy16: ++in; { // Let backslash before other characters through verbatim. @@ -204,7 +194,18 @@ yy14: *out++ = yych; continue; } -yy16: +yy18: + ++in; + { + // A line continuation ends the current file name. + break; + } +yy20: + yych = *++in; + if (yych == '\n') goto yy18; + in = yymarker; + goto yy5; +yy22: ++in; { // De-escape backslashed character. @@ -216,25 +217,52 @@ yy16: } int len = (int)(out - filename); - const bool is_target = parsing_targets; + const bool is_dependency = !parsing_targets; if (len > 0 && filename[len - 1] == ':') { len--; // Strip off trailing colon, if any. parsing_targets = false; + have_target = true; } - if (len == 0) - continue; + if (len > 0) { + if (is_dependency) { + if (have_secondary_target_on_this_rule) { + if (!have_newline_since_primary_target) { + *err = "depfile has multiple output paths"; + return false; + } else if (options_.depfile_distinct_target_lines_action_ == + kDepfileDistinctTargetLinesActionError) { + *err = + "depfile has multiple output paths (on separate lines)" + " [-w depfilemulti=err]"; + return false; + } else { + if (!warned_distinct_target_lines) { + warned_distinct_target_lines = true; + Warning("depfile has multiple output paths (on separate lines); " + "continuing anyway [-w depfilemulti=warn]"); + } + continue; + } + } + ins_.push_back(StringPiece(filename, len)); + } else if (!out_.str_) { + out_ = StringPiece(filename, len); + } else if (out_ != StringPiece(filename, len)) { + have_secondary_target_on_this_rule = true; + } + } - if (!is_target) { - ins_.push_back(StringPiece(filename, len)); - } else if (!out_.str_) { - out_ = StringPiece(filename, len); - } else if (out_ != StringPiece(filename, len)) { - *err = "depfile has multiple output paths"; - return false; + if (have_newline) { + // A newline ends a rule so the next filename will be a new target. + parsing_targets = true; + have_secondary_target_on_this_rule = false; + if (have_target) { + have_newline_since_primary_target = true; + } } } - if (parsing_targets) { + if (!have_target) { *err = "expected ':' in depfile"; return false; } |