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