blob: 0a81c69adb97ae4e658c03e403d8f118616ac80b [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"
Shinichiro Hamajie7992752015-06-29 18:38:35 +090023#include "symtab.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090024#include "value.h"
25
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +090026namespace {
27
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090028static void ParseInputs(Rule* r, StringPiece s) {
29 bool is_order_only = false;
30 for (StringPiece input : WordScanner(s)) {
31 if (input == "|") {
32 is_order_only = true;
33 continue;
34 }
Shinichiro Hamajie7992752015-06-29 18:38:35 +090035 Symbol input_sym = Intern(TrimLeadingCurdir(input));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090036 if (is_order_only) {
Shinichiro Hamajie7992752015-06-29 18:38:35 +090037 r->order_only_inputs.push_back(input_sym);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090038 } else {
Shinichiro Hamajie7992752015-06-29 18:38:35 +090039 r->inputs.push_back(input_sym);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090040 }
41 }
42}
43
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +090044bool IsPatternRule(StringPiece s) {
45 return s.find('%') != string::npos;
46}
47
48} // namespace
49
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090050Rule::Rule()
51 : is_double_colon(false),
52 is_suffix_rule(false),
Shinichiro Hamaji0562c302015-06-19 15:30:49 +090053 cmd_lineno(0) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090054}
55
Shinichiro Hamaji2928f462015-06-23 20:24:53 +090056void ParseRule(Loc& loc, StringPiece line, char term,
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +090057 Rule** out_rule, RuleVarAssignment* rule_var) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090058 size_t index = line.find(':');
59 if (index == string::npos) {
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +090060 ERROR("%s:%d: *** missing separator.", LOCF(loc));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090061 }
62
63 StringPiece first = line.substr(0, index);
Shinichiro Hamajie7992752015-06-29 18:38:35 +090064 vector<Symbol> outputs;
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +090065 for (StringPiece tok : WordScanner(first)) {
66 outputs.push_back(Intern(TrimLeadingCurdir(tok)));
67 }
68
Shinichiro Hamajie7992752015-06-29 18:38:35 +090069 const bool is_first_pattern = (
70 !outputs.empty() && IsPatternRule(outputs[0].str()));
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +090071 if (is_first_pattern) {
72 if (outputs.size() > 1) {
73 // TODO: Multiple output patterns are not supported yet.
74 ERROR("%s:%d: *** mixed implicit and normal rules: deprecated syntax",
75 LOCF(loc));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090076 }
77 }
78
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +090079 bool is_double_colon = false;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090080 index++;
81 if (line.get(index) == ':') {
82 is_double_colon = true;
83 index++;
84 }
85
86 StringPiece rest = line.substr(index);
Shinichiro Hamaji2928f462015-06-23 20:24:53 +090087 size_t term_index = rest.find_first_of("=;");
88 if ((term_index != string::npos && rest[term_index] == '=') ||
89 (term_index == string::npos && term == '=')) {
90 if (term_index == string::npos)
91 term_index = rest.size();
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +090092 rule_var->outputs.swap(outputs);
Shinichiro Hamaji2928f462015-06-23 20:24:53 +090093 ParseAssignStatement(rest, term_index,
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +090094 &rule_var->lhs, &rule_var->rhs, &rule_var->op);
95 *out_rule = NULL;
96 return;
97 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090098
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +090099 Rule* rule = new Rule();
100 *out_rule = rule;
101 rule->loc = loc;
102 rule->is_double_colon = is_double_colon;
103 if (is_first_pattern) {
104 rule->output_patterns.swap(outputs);
105 } else {
106 rule->outputs.swap(outputs);
107 }
Shinichiro Hamaji2928f462015-06-23 20:24:53 +0900108 if (term_index != string::npos && term != ';') {
109 CHECK(rest[term_index] == ';');
110 // TODO: Maybe better to avoid Intern here?
111 rule->cmds.push_back(
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900112 NewLiteral(Intern(TrimLeftSpace(rest.substr(term_index + 1))).str()));
Shinichiro Hamaji2928f462015-06-23 20:24:53 +0900113 rest = rest.substr(0, term_index);
114 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900115
116 index = rest.find(':');
117 if (index == string::npos) {
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900118 ParseInputs(rule, rest);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900119 return;
120 }
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900121
122 if (is_first_pattern) {
123 ERROR("%s:%d: *** mixed implicit and normal rules: deprecated syntax",
124 LOCF(loc));
125 }
126
127 StringPiece second = rest.substr(0, index);
128 StringPiece third = rest.substr(index+1);
129
130 for (StringPiece tok : WordScanner(second)) {
Shinichiro Hamaji2e23e4a2015-06-26 07:33:16 +0900131 rule->output_patterns.push_back(Intern(tok));
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900132 }
133
134 if (rule->output_patterns.empty()) {
135 ERROR("%s:%d: *** missing target pattern.", LOCF(loc));
136 }
137 if (rule->output_patterns.size() > 1) {
138 ERROR("%s:%d: *** multiple target patterns.", LOCF(loc));
139 }
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900140 if (!IsPatternRule(rule->output_patterns[0].str())) {
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900141 ERROR("%s:%d: *** target pattern contains no '%%'.", LOCF(loc));
142 }
143 ParseInputs(rule, third);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900144}
145
146string Rule::DebugString() const {
147 vector<string> v;
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900148 v.push_back(StringPrintf("outputs=[%s]", JoinSymbols(outputs, ",").c_str()));
149 v.push_back(StringPrintf("inputs=[%s]", JoinSymbols(inputs, ",").c_str()));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900150 if (!order_only_inputs.empty()) {
151 v.push_back(StringPrintf("order_only_inputs=[%s]",
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900152 JoinSymbols(order_only_inputs, ",").c_str()));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900153 }
Shinichiro Hamaji2e23e4a2015-06-26 07:33:16 +0900154 if (!output_patterns.empty()) {
155 v.push_back(StringPrintf("output_patterns=[%s]",
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900156 JoinSymbols(output_patterns, ",").c_str()));
Shinichiro Hamaji2e23e4a2015-06-26 07:33:16 +0900157 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900158 if (is_double_colon)
159 v.push_back("is_double_colon");
160 if (is_suffix_rule)
161 v.push_back("is_suffix_rule");
162 if (!cmds.empty()) {
163 v.push_back(StringPrintf("cmds=[%s]", JoinValues(cmds, ",").c_str()));
164 }
165 return JoinStrings(v, " ");
166}