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
DyndepParser(State * state,FileReader * file_reader,DyndepFile * dyndep_file)25 DyndepParser::DyndepParser(State* state, FileReader* file_reader,
26 DyndepFile* dyndep_file)
27 : Parser(state, file_reader)
28 , dyndep_file_(dyndep_file) {
29 }
30
Parse(const string & filename,const string & input,string * err)31 bool DyndepParser::Parse(const string& filename, const string& input,
32 string* err) {
33 lexer_.Start(filename, input);
34
35 // Require a supported ninja_dyndep_version value immediately so
36 // we can exit before encountering any syntactic surprises.
37 bool haveDyndepVersion = false;
38
39 for (;;) {
40 Lexer::Token token = lexer_.ReadToken();
41 switch (token) {
42 case Lexer::BUILD: {
43 if (!haveDyndepVersion)
44 return lexer_.Error("expected 'ninja_dyndep_version = ...'", err);
45 if (!ParseEdge(err))
46 return false;
47 break;
48 }
49 case Lexer::IDENT: {
50 lexer_.UnreadToken();
51 if (haveDyndepVersion)
52 return lexer_.Error(string("unexpected ") + Lexer::TokenName(token),
53 err);
54 if (!ParseDyndepVersion(err))
55 return false;
56 haveDyndepVersion = true;
57 break;
58 }
59 case Lexer::ERROR:
60 return lexer_.Error(lexer_.DescribeLastError(), err);
61 case Lexer::TEOF:
62 if (!haveDyndepVersion)
63 return lexer_.Error("expected 'ninja_dyndep_version = ...'", err);
64 return true;
65 case Lexer::NEWLINE:
66 break;
67 default:
68 return lexer_.Error(string("unexpected ") + Lexer::TokenName(token),
69 err);
70 }
71 }
72 return false; // not reached
73 }
74
ParseDyndepVersion(string * err)75 bool DyndepParser::ParseDyndepVersion(string* err) {
76 string name;
77 EvalString let_value;
78 if (!ParseLet(&name, &let_value, err))
79 return false;
80 if (name != "ninja_dyndep_version") {
81 return lexer_.Error("expected 'ninja_dyndep_version = ...'", err);
82 }
83 string version = let_value.Evaluate(&env_);
84 int major, minor;
85 ParseVersion(version, &major, &minor);
86 if (major != 1 || minor != 0) {
87 return lexer_.Error(
88 string("unsupported 'ninja_dyndep_version = ") + version + "'", err);
89 return false;
90 }
91 return true;
92 }
93
ParseLet(string * key,EvalString * value,string * err)94 bool DyndepParser::ParseLet(string* key, EvalString* value, string* err) {
95 if (!lexer_.ReadIdent(key))
96 return lexer_.Error("expected variable name", err);
97 if (!ExpectToken(Lexer::EQUALS, err))
98 return false;
99 if (!lexer_.ReadVarValue(value, err))
100 return false;
101 return true;
102 }
103
ParseEdge(string * err)104 bool DyndepParser::ParseEdge(string* err) {
105 // Parse one explicit output. We expect it to already have an edge.
106 // We will record its dynamically-discovered dependency information.
107 Dyndeps* dyndeps = NULL;
108 {
109 EvalString out0;
110 if (!lexer_.ReadPath(&out0, err))
111 return false;
112 if (out0.empty())
113 return lexer_.Error("expected path", err);
114
115 string path = out0.Evaluate(&env_);
116 string path_err;
117 uint64_t slash_bits;
118 if (!CanonicalizePath(&path, &slash_bits, &path_err))
119 return lexer_.Error(path_err, err);
120 Node* node = state_->LookupNode(path);
121 if (!node || !node->in_edge())
122 return lexer_.Error("no build statement exists for '" + path + "'", err);
123 Edge* edge = node->in_edge();
124 std::pair<DyndepFile::iterator, bool> res =
125 dyndep_file_->insert(DyndepFile::value_type(edge, Dyndeps()));
126 if (!res.second)
127 return lexer_.Error("multiple statements for '" + path + "'", err);
128 dyndeps = &res.first->second;
129 }
130
131 // Disallow explicit outputs.
132 {
133 EvalString out;
134 if (!lexer_.ReadPath(&out, err))
135 return false;
136 if (!out.empty())
137 return lexer_.Error("explicit outputs not supported", err);
138 }
139
140 // Parse implicit outputs, if any.
141 vector<EvalString> outs;
142 if (lexer_.PeekToken(Lexer::PIPE)) {
143 for (;;) {
144 EvalString out;
145 if (!lexer_.ReadPath(&out, err))
146 return err;
147 if (out.empty())
148 break;
149 outs.push_back(out);
150 }
151 }
152
153 if (!ExpectToken(Lexer::COLON, err))
154 return false;
155
156 string rule_name;
157 if (!lexer_.ReadIdent(&rule_name) || rule_name != "dyndep")
158 return lexer_.Error("expected build command name 'dyndep'", err);
159
160 // Disallow explicit inputs.
161 {
162 EvalString in;
163 if (!lexer_.ReadPath(&in, err))
164 return false;
165 if (!in.empty())
166 return lexer_.Error("explicit inputs not supported", err);
167 }
168
169 // Parse implicit inputs, if any.
170 vector<EvalString> ins;
171 if (lexer_.PeekToken(Lexer::PIPE)) {
172 for (;;) {
173 EvalString in;
174 if (!lexer_.ReadPath(&in, err))
175 return err;
176 if (in.empty())
177 break;
178 ins.push_back(in);
179 }
180 }
181
182 // Disallow order-only inputs.
183 if (lexer_.PeekToken(Lexer::PIPE2))
184 return lexer_.Error("order-only inputs not supported", err);
185
186 if (!ExpectToken(Lexer::NEWLINE, err))
187 return false;
188
189 if (lexer_.PeekToken(Lexer::INDENT)) {
190 string key;
191 EvalString val;
192 if (!ParseLet(&key, &val, err))
193 return false;
194 if (key != "restat")
195 return lexer_.Error("binding is not 'restat'", err);
196 string value = val.Evaluate(&env_);
197 dyndeps->restat_ = !value.empty();
198 }
199
200 dyndeps->implicit_inputs_.reserve(ins.size());
201 for (vector<EvalString>::iterator i = ins.begin(); i != ins.end(); ++i) {
202 string path = i->Evaluate(&env_);
203 string path_err;
204 uint64_t slash_bits;
205 if (!CanonicalizePath(&path, &slash_bits, &path_err))
206 return lexer_.Error(path_err, err);
207 Node* n = state_->GetNode(path, slash_bits);
208 dyndeps->implicit_inputs_.push_back(n);
209 }
210
211 dyndeps->implicit_outputs_.reserve(outs.size());
212 for (vector<EvalString>::iterator i = outs.begin(); i != outs.end(); ++i) {
213 string path = i->Evaluate(&env_);
214 string path_err;
215 uint64_t slash_bits;
216 if (!CanonicalizePath(&path, &slash_bits, &path_err))
217 return lexer_.Error(path_err, err);
218 Node* n = state_->GetNode(path, slash_bits);
219 dyndeps->implicit_outputs_.push_back(n);
220 }
221
222 return true;
223 }
224