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 | |
25 | using namespace std; |
26 | |
27 | DyndepParser::DyndepParser(State* state, FileReader* file_reader, |
28 | DyndepFile* dyndep_file) |
29 | : Parser(state, file_reader) |
30 | , dyndep_file_(dyndep_file) { |
31 | } |
32 | |
33 | bool 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 | |
77 | bool 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 | |
96 | bool 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 | |
106 | bool 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 | |