xref: /third_party/ninja/src/dyndep_parser.cc (revision 695b41ee)
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