1// Copyright 2015 Google Inc. All Rights Reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15#include "dyndep_parser.h" 16 17#include <vector> 18 19#include "dyndep.h" 20#include "graph.h" 21#include "state.h" 22#include "util.h" 23#include "version.h" 24 25using namespace std; 26 27DyndepParser::DyndepParser(State* state, FileReader* file_reader, 28 DyndepFile* dyndep_file) 29 : Parser(state, file_reader) 30 , dyndep_file_(dyndep_file) { 31} 32 33bool DyndepParser::Parse(const string& filename, const string& input, 34 string* err) { 35 lexer_.Start(filename, input); 36 37 // Require a supported ninja_dyndep_version value immediately so 38 // we can exit before encountering any syntactic surprises. 39 bool haveDyndepVersion = false; 40 41 for (;;) { 42 Lexer::Token token = lexer_.ReadToken(); 43 switch (token) { 44 case Lexer::BUILD: { 45 if (!haveDyndepVersion) 46 return lexer_.Error("expected 'ninja_dyndep_version = ...'", err); 47 if (!ParseEdge(err)) 48 return false; 49 break; 50 } 51 case Lexer::IDENT: { 52 lexer_.UnreadToken(); 53 if (haveDyndepVersion) 54 return lexer_.Error(string("unexpected ") + Lexer::TokenName(token), 55 err); 56 if (!ParseDyndepVersion(err)) 57 return false; 58 haveDyndepVersion = true; 59 break; 60 } 61 case Lexer::ERROR: 62 return lexer_.Error(lexer_.DescribeLastError(), err); 63 case Lexer::TEOF: 64 if (!haveDyndepVersion) 65 return lexer_.Error("expected 'ninja_dyndep_version = ...'", err); 66 return true; 67 case Lexer::NEWLINE: 68 break; 69 default: 70 return lexer_.Error(string("unexpected ") + Lexer::TokenName(token), 71 err); 72 } 73 } 74 return false; // not reached 75} 76 77bool DyndepParser::ParseDyndepVersion(string* err) { 78 string name; 79 EvalString let_value; 80 if (!ParseLet(&name, &let_value, err)) 81 return false; 82 if (name != "ninja_dyndep_version") { 83 return lexer_.Error("expected 'ninja_dyndep_version = ...'", err); 84 } 85 string version = let_value.Evaluate(&env_); 86 int major, minor; 87 ParseVersion(version, &major, &minor); 88 if (major != 1 || minor != 0) { 89 return lexer_.Error( 90 string("unsupported 'ninja_dyndep_version = ") + version + "'", err); 91 return false; 92 } 93 return true; 94} 95 96bool DyndepParser::ParseLet(string* key, EvalString* value, string* err) { 97 if (!lexer_.ReadIdent(key)) 98 return lexer_.Error("expected variable name", err); 99 if (!ExpectToken(Lexer::EQUALS, err)) 100 return false; 101 if (!lexer_.ReadVarValue(value, err)) 102 return false; 103 return true; 104} 105 106bool DyndepParser::ParseEdge(string* err) { 107 // Parse one explicit output. We expect it to already have an edge. 108 // We will record its dynamically-discovered dependency information. 109 Dyndeps* dyndeps = NULL; 110 { 111 EvalString out0; 112 if (!lexer_.ReadPath(&out0, err)) 113 return false; 114 if (out0.empty()) 115 return lexer_.Error("expected path", err); 116 117 string path = out0.Evaluate(&env_); 118 if (path.empty()) 119 return lexer_.Error("empty path", err); 120 uint64_t slash_bits; 121 CanonicalizePath(&path, &slash_bits); 122 Node* node = state_->LookupNode(path); 123 if (!node || !node->in_edge()) 124 return lexer_.Error("no build statement exists for '" + path + "'", err); 125 Edge* edge = node->in_edge(); 126 std::pair<DyndepFile::iterator, bool> res = 127 dyndep_file_->insert(DyndepFile::value_type(edge, Dyndeps())); 128 if (!res.second) 129 return lexer_.Error("multiple statements for '" + path + "'", err); 130 dyndeps = &res.first->second; 131 } 132 133 // Disallow explicit outputs. 134 { 135 EvalString out; 136 if (!lexer_.ReadPath(&out, err)) 137 return false; 138 if (!out.empty()) 139 return lexer_.Error("explicit outputs not supported", err); 140 } 141 142 // Parse implicit outputs, if any. 143 vector<EvalString> outs; 144 if (lexer_.PeekToken(Lexer::PIPE)) { 145 for (;;) { 146 EvalString out; 147 if (!lexer_.ReadPath(&out, err)) 148 return err; 149 if (out.empty()) 150 break; 151 outs.push_back(out); 152 } 153 } 154 155 if (!ExpectToken(Lexer::COLON, err)) 156 return false; 157 158 string rule_name; 159 if (!lexer_.ReadIdent(&rule_name) || rule_name != "dyndep") 160 return lexer_.Error("expected build command name 'dyndep'", err); 161 162 // Disallow explicit inputs. 163 { 164 EvalString in; 165 if (!lexer_.ReadPath(&in, err)) 166 return false; 167 if (!in.empty()) 168 return lexer_.Error("explicit inputs not supported", err); 169 } 170 171 // Parse implicit inputs, if any. 172 vector<EvalString> ins; 173 if (lexer_.PeekToken(Lexer::PIPE)) { 174 for (;;) { 175 EvalString in; 176 if (!lexer_.ReadPath(&in, err)) 177 return err; 178 if (in.empty()) 179 break; 180 ins.push_back(in); 181 } 182 } 183 184 // Disallow order-only inputs. 185 if (lexer_.PeekToken(Lexer::PIPE2)) 186 return lexer_.Error("order-only inputs not supported", err); 187 188 if (!ExpectToken(Lexer::NEWLINE, err)) 189 return false; 190 191 if (lexer_.PeekToken(Lexer::INDENT)) { 192 string key; 193 EvalString val; 194 if (!ParseLet(&key, &val, err)) 195 return false; 196 if (key != "restat") 197 return lexer_.Error("binding is not 'restat'", err); 198 string value = val.Evaluate(&env_); 199 dyndeps->restat_ = !value.empty(); 200 } 201 202 dyndeps->implicit_inputs_.reserve(ins.size()); 203 for (vector<EvalString>::iterator i = ins.begin(); i != ins.end(); ++i) { 204 string path = i->Evaluate(&env_); 205 if (path.empty()) 206 return lexer_.Error("empty path", err); 207 uint64_t slash_bits; 208 CanonicalizePath(&path, &slash_bits); 209 Node* n = state_->GetNode(path, slash_bits); 210 dyndeps->implicit_inputs_.push_back(n); 211 } 212 213 dyndeps->implicit_outputs_.reserve(outs.size()); 214 for (vector<EvalString>::iterator i = outs.begin(); i != outs.end(); ++i) { 215 string path = i->Evaluate(&env_); 216 if (path.empty()) 217 return lexer_.Error("empty path", err); 218 string path_err; 219 uint64_t slash_bits; 220 CanonicalizePath(&path, &slash_bits); 221 Node* n = state_->GetNode(path, slash_bits); 222 dyndeps->implicit_outputs_.push_back(n); 223 } 224 225 return true; 226} 227