From bf72e45180e1dd80d9efea8d2acebcac15ea12a4 Mon Sep 17 00:00:00 2001 From: Evan Martin Date: Wed, 7 Dec 2011 12:08:00 -0800 Subject: use re2c to parse depfiles --- configure.py | 10 +++- src/depfile_parser.cc | 150 +++++++++++++++++++++++++++++++++++++++++++++++ src/depfile_parser.h | 26 ++++++++ src/depfile_parser.in.cc | 55 +++++++++++++++++ src/graph.cc | 23 ++++---- src/string_piece.h | 2 + 6 files changed, 254 insertions(+), 12 deletions(-) create mode 100644 src/depfile_parser.cc create mode 100644 src/depfile_parser.h create mode 100644 src/depfile_parser.in.cc diff --git a/configure.py b/configure.py index 2121f47..0267290 100755 --- a/configure.py +++ b/configure.py @@ -141,9 +141,17 @@ if platform != 'mingw': objs += cxx('browse', order_only=built('browse_py.h')) n.newline() +n.comment('the depfile parser is generated using re2c.') +n.rule('re2c', + command='re2c -b --no-generation-date -o $out $in', + description='RE2C $out') +# Generate the .cc file in the source directory so we can check it in. +n.build(src('depfile_parser.cc'), 're2c', src('depfile_parser.in.cc')) +n.newline() + n.comment('Core source files all build into ninja library.') for name in ['build', 'build_log', 'clean', 'edit_distance', 'eval_env', - 'graph', 'graphviz', 'parsers', 'util', + 'graph', 'graphviz', 'parsers', 'util', 'depfile_parser', 'disk_interface', 'state']: objs += cxx(name) if platform == 'mingw': diff --git a/src/depfile_parser.cc b/src/depfile_parser.cc new file mode 100644 index 0000000..7be4a60 --- /dev/null +++ b/src/depfile_parser.cc @@ -0,0 +1,150 @@ +/* Generated by re2c 0.13.5 */ +#line 1 "src/depfile_parser.in.cc" +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "depfile_parser.h" + +bool DepfileParser::Parse(const string& content, string* err) { + const char* p = content.data(); + const char* end = content.data() + content.size(); + for (;;) { + const char* start = p; + char yych; + +#line 27 "src/depfile_parser.cc" + { + static const unsigned char yybm[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 128, 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, + 0, 0, 0, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 0, 0, 0, 0, 0, + 0, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 0, 0, 0, 0, 64, + 0, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 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, 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, 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, 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, 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, + 0, 0, 0, 0, 0, 0, 0, 0, + }; + + if ((end - p) < 2) break; + yych = *p; + if (yych <= '@') { + if (yych <= 0x1F) { + if (yych == '\n') goto yy5; + goto yy8; + } else { + if (yych <= ' ') goto yy5; + if (yych <= '*') goto yy8; + if (yych <= ':') goto yy6; + goto yy8; + } + } else { + if (yych <= '^') { + if (yych <= 'Z') goto yy6; + if (yych == '\\') goto yy3; + goto yy8; + } else { + if (yych == '`') goto yy8; + if (yych <= 'z') goto yy6; + goto yy8; + } + } +yy2: +#line 38 "src/depfile_parser.in.cc" + { continue; } +#line 90 "src/depfile_parser.cc" +yy3: + ++p; + if ((yych = *p) == '\n') goto yy13; +yy4: +#line 48 "src/depfile_parser.in.cc" + { + *err = "BUG: depfile lexer encountered unknown state"; + return false; + } +#line 100 "src/depfile_parser.cc" +yy5: + yych = *++p; + goto yy12; +yy6: + ++p; + yych = *p; + goto yy10; +yy7: +#line 39 "src/depfile_parser.in.cc" + { + // Got a filename. + if (p[-1] == ':') { + out_ = StringPiece(start, p - start - 1); + } else { + ins_.push_back(StringPiece(start, p - start)); + } + continue; + } +#line 119 "src/depfile_parser.cc" +yy8: + yych = *++p; + goto yy4; +yy9: + ++p; + if (end <= p) break; + yych = *p; +yy10: + if (yybm[0+yych] & 64) { + goto yy9; + } + goto yy7; +yy11: + ++p; + if (end <= p) break; + yych = *p; +yy12: + if (yybm[0+yych] & 128) { + goto yy11; + } + goto yy2; +yy13: + ++p; +#line 37 "src/depfile_parser.in.cc" + { continue; } +#line 145 "src/depfile_parser.cc" + } +#line 52 "src/depfile_parser.in.cc" + + } + return true; +} diff --git a/src/depfile_parser.h b/src/depfile_parser.h new file mode 100644 index 0000000..fd94be9 --- /dev/null +++ b/src/depfile_parser.h @@ -0,0 +1,26 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +using namespace std; + +#include "string_piece.h" + +struct DepfileParser { + bool Parse(const string& content, string* err); + + StringPiece out_; + vector ins_; +}; diff --git a/src/depfile_parser.in.cc b/src/depfile_parser.in.cc new file mode 100644 index 0000000..1e22ca9 --- /dev/null +++ b/src/depfile_parser.in.cc @@ -0,0 +1,55 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "depfile_parser.h" + +bool DepfileParser::Parse(const string& content, string* err) { + const char* p = content.data(); + const char* end = content.data() + content.size(); + for (;;) { + const char* start = p; + char yych; + /*!re2c + re2c:define:YYCTYPE = "const char"; + re2c:define:YYCURSOR = p; + re2c:define:YYMARKER = q; + re2c:define:YYLIMIT = end; + + re2c:yyfill:parameter = 0; + re2c:define:YYFILL = break; + + re2c:indent:top = 2; + re2c:indent:string = " "; + + re2c:yych:emit = 0; + + '\\\n' { continue; } + [ \n]* { continue; } + [a-zA-Z0-9+,/_:.-]+ { + // Got a filename. + if (p[-1] == ':') { + out_ = StringPiece(start, p - start - 1); + } else { + ins_.push_back(StringPiece(start, p - start)); + } + continue; + } + [^] { + *err = "BUG: depfile lexer encountered unknown state"; + return false; + } + */ + } + return true; +} diff --git a/src/graph.cc b/src/graph.cc index 9733e3d..be0c529 100644 --- a/src/graph.cc +++ b/src/graph.cc @@ -18,6 +18,7 @@ #include #include "build_log.h" +#include "depfile_parser.h" #include "disk_interface.h" #include "parsers.h" #include "state.h" @@ -217,29 +218,29 @@ bool Edge::LoadDepFile(State* state, DiskInterface* disk_interface, if (content.empty()) return true; - MakefileParser makefile; - string makefile_err; - if (!makefile.Parse(content, &makefile_err)) { - *err = path + ": " + makefile_err; + DepfileParser depfile; + string depfile_err; + if (!depfile.Parse(content, &depfile_err)) { + *err = path + ": " + depfile_err; return false; } // Check that this depfile matches our output. StringPiece opath = StringPiece(outputs_[0]->path()); - if (opath != makefile.out_) { + if (opath != depfile.out_) { *err = "expected depfile '" + path + "' to mention '" + - outputs_[0]->path() + "', got '" + makefile.out_.AsString() + "'"; + outputs_[0]->path() + "', got '" + depfile.out_.AsString() + "'"; return false; } - inputs_.insert(inputs_.end() - order_only_deps_, makefile.ins_.size(), 0); - implicit_deps_ += makefile.ins_.size(); + inputs_.insert(inputs_.end() - order_only_deps_, depfile.ins_.size(), 0); + implicit_deps_ += depfile.ins_.size(); vector::iterator implicit_dep = - inputs_.end() - order_only_deps_ - makefile.ins_.size(); + inputs_.end() - order_only_deps_ - depfile.ins_.size(); // Add all its in-edges. - for (vector::iterator i = makefile.ins_.begin(); - i != makefile.ins_.end(); ++i, ++implicit_dep) { + for (vector::iterator i = depfile.ins_.begin(); + i != depfile.ins_.end(); ++i, ++implicit_dep) { string path(i->str_, i->len_); if (!CanonicalizePath(&path, err)) return false; diff --git a/src/string_piece.h b/src/string_piece.h index 3b94ce3..2f881a2 100644 --- a/src/string_piece.h +++ b/src/string_piece.h @@ -31,6 +31,8 @@ struct StringPiece { StringPiece(const string& str) : str_(str.data()), len_(str.size()) {} StringPiece(const char* str) : str_(str), len_(strlen(str)) {} + StringPiece(const char* str, int len) : str_(str), len_(len) {} + bool operator==(const StringPiece& other) const { return len_ == other.len_ && memcmp(str_, other.str_, len_) == 0; } -- cgit v0.12