• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // +build ignore
16 
17 #include "rule.h"
18 
19 #include "expr.h"
20 #include "log.h"
21 #include "parser.h"
22 #include "stringprintf.h"
23 #include "strutil.h"
24 #include "symtab.h"
25 
Rule()26 Rule::Rule() : is_double_colon(false), is_suffix_rule(false), cmd_lineno(0) {}
27 
ParseInputs(const StringPiece & inputs_str)28 void Rule::ParseInputs(const StringPiece& inputs_str) {
29   bool is_order_only = false;
30   for (auto const& input : WordScanner(inputs_str)) {
31     if (input == "|") {
32       is_order_only = true;
33       continue;
34     }
35     Symbol input_sym = Intern(TrimLeadingCurdir(input));
36     (is_order_only ? order_only_inputs : inputs).push_back(input_sym);
37   }
38 }
39 
ParsePrerequisites(const StringPiece & line,size_t separator_pos,const RuleStmt * rule_stmt)40 void Rule::ParsePrerequisites(const StringPiece& line,
41                               size_t separator_pos,
42                               const RuleStmt* rule_stmt) {
43   // line is either
44   //    prerequisites [ ; command ]
45   // or
46   //    target-prerequisites : prereq-patterns [ ; command ]
47   // First, separate command. At this point separator_pos should point to ';'
48   // unless null.
49   StringPiece prereq_string = line;
50   if (separator_pos != string::npos &&
51       rule_stmt->sep != RuleStmt::SEP_SEMICOLON) {
52     CHECK(line[separator_pos] == ';');
53     // TODO: Maybe better to avoid Intern here?
54     cmds.push_back(Value::NewLiteral(
55         Intern(TrimLeftSpace(line.substr(separator_pos + 1))).str()));
56     prereq_string = line.substr(0, separator_pos);
57   }
58 
59   if ((separator_pos = prereq_string.find(':')) == string::npos) {
60     // Simple prerequisites
61     ParseInputs(prereq_string);
62     return;
63   }
64 
65   // Static pattern rule.
66   if (!output_patterns.empty()) {
67     ERROR_LOC(loc, "*** mixed implicit and normal rules: deprecated syntax");
68   }
69 
70   // Empty static patterns should not produce rules, but need to eat the
71   // commands So return a rule with no outputs nor output_patterns
72   if (outputs.empty()) {
73     return;
74   }
75 
76   StringPiece target_prereq = prereq_string.substr(0, separator_pos);
77   StringPiece prereq_patterns = prereq_string.substr(separator_pos + 1);
78 
79   for (StringPiece target_pattern : WordScanner(target_prereq)) {
80     target_pattern = TrimLeadingCurdir(target_pattern);
81     for (Symbol target : outputs) {
82       if (!Pattern(target_pattern).Match(target.str())) {
83         WARN_LOC(loc, "target `%s' doesn't match the target pattern",
84                  target.c_str());
85       }
86     }
87     output_patterns.push_back(Intern(target_pattern));
88   }
89 
90   if (output_patterns.empty()) {
91     ERROR_LOC(loc, "*** missing target pattern.");
92   }
93   if (output_patterns.size() > 1) {
94     ERROR_LOC(loc, "*** multiple target patterns.");
95   }
96   if (!IsPatternRule(output_patterns[0].str())) {
97     ERROR_LOC(loc, "*** target pattern contains no '%%'.");
98   }
99   ParseInputs(prereq_patterns);
100 }
101 
DebugString() const102 string Rule::DebugString() const {
103   vector<string> v;
104   v.push_back(StringPrintf("outputs=[%s]", JoinSymbols(outputs, ",").c_str()));
105   v.push_back(StringPrintf("inputs=[%s]", JoinSymbols(inputs, ",").c_str()));
106   if (!order_only_inputs.empty()) {
107     v.push_back(StringPrintf("order_only_inputs=[%s]",
108                              JoinSymbols(order_only_inputs, ",").c_str()));
109   }
110   if (!output_patterns.empty()) {
111     v.push_back(StringPrintf("output_patterns=[%s]",
112                              JoinSymbols(output_patterns, ",").c_str()));
113   }
114   if (is_double_colon)
115     v.push_back("is_double_colon");
116   if (is_suffix_rule)
117     v.push_back("is_suffix_rule");
118   if (!cmds.empty()) {
119     v.push_back(StringPrintf("cmds=[%s]", JoinValues(cmds, ",").c_str()));
120   }
121   return JoinStrings(v, " ");
122 }
123