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 
DyndepParser(State * state,FileReader * file_reader,DyndepFile * dyndep_file)27 DyndepParser::DyndepParser(State* state, FileReader* file_reader,
28                            DyndepFile* dyndep_file)
29     : Parser(state, file_reader)
30     , dyndep_file_(dyndep_file) {
31 }
32 
Parse(const string & filename,const string & input,string * err)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 
ParseDyndepVersion(string * err)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 
ParseLet(string * key,EvalString * value,string * err)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 
ParseEdge(string * err)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     string path_err;
119     uint64_t slash_bits;
120     if (!CanonicalizePath(&path, &slash_bits, &path_err))
121       return lexer_.Error(path_err, err);
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     string path_err;
206     uint64_t slash_bits;
207     if (!CanonicalizePath(&path, &slash_bits, &path_err))
208       return lexer_.Error(path_err, err);
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     string path_err;
217     uint64_t slash_bits;
218     if (!CanonicalizePath(&path, &slash_bits, &path_err))
219       return lexer_.Error(path_err, err);
220     Node* n = state_->GetNode(path, slash_bits);
221     dyndeps->implicit_outputs_.push_back(n);
222   }
223 
224   return true;
225 }
226