blob: 7c882a3a2dc09f62e26b9446184054af59fb9e14 [file] [log] [blame]
Shinichiro Hamaji1d545aa2015-06-23 15:29:13 +09001// 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
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +090015// +build ignore
16
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090017#include "rule.h"
18
19#include "log.h"
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +090020#include "parser.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090021#include "stringprintf.h"
22#include "strutil.h"
23#include "value.h"
24
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +090025namespace {
26
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090027static void ParseInputs(Rule* r, StringPiece s) {
28 bool is_order_only = false;
29 for (StringPiece input : WordScanner(s)) {
30 if (input == "|") {
31 is_order_only = true;
32 continue;
33 }
34 input = Intern(TrimLeadingCurdir(input));
35 if (is_order_only) {
36 r->order_only_inputs.push_back(input);
37 } else {
38 r->inputs.push_back(input);
39 }
40 }
41}
42
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +090043bool IsPatternRule(StringPiece s) {
44 return s.find('%') != string::npos;
45}
46
47} // namespace
48
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090049Rule::Rule()
50 : is_double_colon(false),
51 is_suffix_rule(false),
Shinichiro Hamaji0562c302015-06-19 15:30:49 +090052 cmd_lineno(0) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090053}
54
Shinichiro Hamaji2928f462015-06-23 20:24:53 +090055void ParseRule(Loc& loc, StringPiece line, char term,
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +090056 Rule** out_rule, RuleVarAssignment* rule_var) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090057 size_t index = line.find(':');
58 if (index == string::npos) {
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +090059 ERROR("%s:%d: *** missing separator.", LOCF(loc));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090060 }
61
62 StringPiece first = line.substr(0, index);
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +090063 vector<StringPiece> outputs;
64 for (StringPiece tok : WordScanner(first)) {
65 outputs.push_back(Intern(TrimLeadingCurdir(tok)));
66 }
67
Shinichiro Hamajie6469842015-06-24 14:46:28 +090068 const bool is_first_pattern = !outputs.empty() && IsPatternRule(outputs[0]);
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +090069 if (is_first_pattern) {
70 if (outputs.size() > 1) {
71 // TODO: Multiple output patterns are not supported yet.
72 ERROR("%s:%d: *** mixed implicit and normal rules: deprecated syntax",
73 LOCF(loc));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090074 }
75 }
76
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +090077 bool is_double_colon = false;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090078 index++;
79 if (line.get(index) == ':') {
80 is_double_colon = true;
81 index++;
82 }
83
84 StringPiece rest = line.substr(index);
Shinichiro Hamaji2928f462015-06-23 20:24:53 +090085 size_t term_index = rest.find_first_of("=;");
86 if ((term_index != string::npos && rest[term_index] == '=') ||
87 (term_index == string::npos && term == '=')) {
88 if (term_index == string::npos)
89 term_index = rest.size();
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +090090 rule_var->outputs.swap(outputs);
Shinichiro Hamaji2928f462015-06-23 20:24:53 +090091 ParseAssignStatement(rest, term_index,
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +090092 &rule_var->lhs, &rule_var->rhs, &rule_var->op);
93 *out_rule = NULL;
94 return;
95 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090096
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +090097 Rule* rule = new Rule();
98 *out_rule = rule;
99 rule->loc = loc;
100 rule->is_double_colon = is_double_colon;
101 if (is_first_pattern) {
102 rule->output_patterns.swap(outputs);
103 } else {
104 rule->outputs.swap(outputs);
105 }
Shinichiro Hamaji2928f462015-06-23 20:24:53 +0900106 if (term_index != string::npos && term != ';') {
107 CHECK(rest[term_index] == ';');
108 // TODO: Maybe better to avoid Intern here?
109 rule->cmds.push_back(
110 NewLiteral(Intern(TrimLeftSpace(rest.substr(term_index + 1)))));
111 rest = rest.substr(0, term_index);
112 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900113
114 index = rest.find(':');
115 if (index == string::npos) {
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900116 ParseInputs(rule, rest);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900117 return;
118 }
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900119
120 if (is_first_pattern) {
121 ERROR("%s:%d: *** mixed implicit and normal rules: deprecated syntax",
122 LOCF(loc));
123 }
124
125 StringPiece second = rest.substr(0, index);
126 StringPiece third = rest.substr(index+1);
127
128 for (StringPiece tok : WordScanner(second)) {
Shinichiro Hamaji2e23e4a2015-06-26 07:33:16 +0900129 rule->output_patterns.push_back(Intern(tok));
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900130 }
131
132 if (rule->output_patterns.empty()) {
133 ERROR("%s:%d: *** missing target pattern.", LOCF(loc));
134 }
135 if (rule->output_patterns.size() > 1) {
136 ERROR("%s:%d: *** multiple target patterns.", LOCF(loc));
137 }
138 if (!IsPatternRule(rule->output_patterns[0])) {
139 ERROR("%s:%d: *** target pattern contains no '%%'.", LOCF(loc));
140 }
141 ParseInputs(rule, third);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900142}
143
144string Rule::DebugString() const {
145 vector<string> v;
146 v.push_back(StringPrintf("outputs=[%s]", JoinStrings(outputs, ",").c_str()));
147 v.push_back(StringPrintf("inputs=[%s]", JoinStrings(inputs, ",").c_str()));
148 if (!order_only_inputs.empty()) {
149 v.push_back(StringPrintf("order_only_inputs=[%s]",
150 JoinStrings(order_only_inputs, ",").c_str()));
151 }
Shinichiro Hamaji2e23e4a2015-06-26 07:33:16 +0900152 if (!output_patterns.empty()) {
153 v.push_back(StringPrintf("output_patterns=[%s]",
154 JoinStrings(output_patterns, ",").c_str()));
155 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900156 if (is_double_colon)
157 v.push_back("is_double_colon");
158 if (is_suffix_rule)
159 v.push_back("is_suffix_rule");
160 if (!cmds.empty()) {
161 v.push_back(StringPrintf("cmds=[%s]", JoinValues(cmds, ",").c_str()));
162 }
163 return JoinStrings(v, " ");
164}