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 "command.h" 18 19 #include <unordered_map> 20 #include <unordered_set> 21 22 #include "dep.h" 23 #include "eval.h" 24 #include "flags.h" 25 #include "log.h" 26 #include "strutil.h" 27 #include "var.h" 28 29 namespace { 30 31 class AutoVar : public Var { 32 public: 33 virtual const char* Flavor() const override { 34 return "undefined"; 35 } 36 virtual VarOrigin Origin() const override { 37 return VarOrigin::AUTOMATIC; 38 } 39 40 virtual void AppendVar(Evaluator*, Value*) override { CHECK(false); } 41 42 virtual StringPiece String() const override { 43 ERROR("$(value %s) is not implemented yet", sym_); 44 return ""; 45 } 46 47 virtual string DebugString() const override { 48 return string("AutoVar(") + sym_ + ")"; 49 } 50 51 protected: 52 AutoVar(CommandEvaluator* ce, const char* sym) : ce_(ce), sym_(sym) {} 53 virtual ~AutoVar() = default; 54 55 CommandEvaluator* ce_; 56 const char* sym_; 57 }; 58 59 #define DECLARE_AUTO_VAR_CLASS(name) \ 60 class name : public AutoVar { \ 61 public: \ 62 name(CommandEvaluator* ce, const char* sym) \ 63 : AutoVar(ce, sym) {} \ 64 virtual ~name() = default; \ 65 virtual void Eval(Evaluator* ev, string* s) const override; \ 66 } 67 68 DECLARE_AUTO_VAR_CLASS(AutoAtVar); 69 DECLARE_AUTO_VAR_CLASS(AutoLessVar); 70 DECLARE_AUTO_VAR_CLASS(AutoHatVar); 71 DECLARE_AUTO_VAR_CLASS(AutoPlusVar); 72 DECLARE_AUTO_VAR_CLASS(AutoStarVar); 73 DECLARE_AUTO_VAR_CLASS(AutoNotImplementedVar); 74 75 class AutoSuffixDVar : public AutoVar { 76 public: 77 AutoSuffixDVar(CommandEvaluator* ce, const char* sym, Var* wrapped) 78 : AutoVar(ce, sym), wrapped_(wrapped) { 79 } 80 virtual ~AutoSuffixDVar() = default; 81 virtual void Eval(Evaluator* ev, string* s) const override; 82 83 private: 84 Var* wrapped_; 85 }; 86 87 class AutoSuffixFVar : public AutoVar { 88 public: 89 AutoSuffixFVar(CommandEvaluator* ce, const char* sym, Var* wrapped) 90 : AutoVar(ce, sym), wrapped_(wrapped) {} 91 virtual ~AutoSuffixFVar() = default; 92 virtual void Eval(Evaluator* ev, string* s) const override; 93 94 private: 95 Var* wrapped_; 96 }; 97 98 void AutoAtVar::Eval(Evaluator*, string* s) const { 99 *s += ce_->current_dep_node()->output.str(); 100 } 101 102 void AutoLessVar::Eval(Evaluator*, string* s) const { 103 auto& ai = ce_->current_dep_node()->actual_inputs; 104 if (!ai.empty()) 105 *s += ai[0].str(); 106 } 107 108 void AutoHatVar::Eval(Evaluator*, string* s) const { 109 unordered_set<StringPiece> seen; 110 WordWriter ww(s); 111 for (Symbol ai : ce_->current_dep_node()->actual_inputs) { 112 if (seen.insert(ai.str()).second) 113 ww.Write(ai.str()); 114 } 115 } 116 117 void AutoPlusVar::Eval(Evaluator*, string* s) const { 118 WordWriter ww(s); 119 for (Symbol ai : ce_->current_dep_node()->actual_inputs) { 120 ww.Write(ai.str()); 121 } 122 } 123 124 void AutoStarVar::Eval(Evaluator*, string* s) const { 125 const DepNode* n = ce_->current_dep_node(); 126 if (!n->output_pattern.IsValid()) 127 return; 128 Pattern pat(n->output_pattern.str()); 129 pat.Stem(n->output.str()).AppendToString(s); 130 } 131 132 void AutoNotImplementedVar::Eval(Evaluator* ev, string*) const { 133 ev->Error(StringPrintf( 134 "Automatic variable `$%s' isn't supported yet", sym_)); 135 } 136 137 void AutoSuffixDVar::Eval(Evaluator* ev, string* s) const { 138 string buf; 139 wrapped_->Eval(ev, &buf); 140 WordWriter ww(s); 141 for (StringPiece tok : WordScanner(buf)) { 142 ww.Write(Dirname(tok)); 143 } 144 } 145 146 void AutoSuffixFVar::Eval(Evaluator* ev, string* s) const { 147 string buf; 148 wrapped_->Eval(ev, &buf); 149 WordWriter ww(s); 150 for (StringPiece tok : WordScanner(buf)) { 151 ww.Write(Basename(tok)); 152 } 153 } 154 155 void ParseCommandPrefixes(StringPiece* s, bool* echo, bool* ignore_error) { 156 *s = TrimLeftSpace(*s); 157 while (true) { 158 char c = s->get(0); 159 if (c == '@') { 160 *echo = false; 161 } else if (c == '-') { 162 *ignore_error = true; 163 } else if (c == '+') { 164 // ignore recursion marker 165 } else { 166 break; 167 } 168 *s = TrimLeftSpace(s->substr(1)); 169 } 170 } 171 172 } // namespace 173 174 CommandEvaluator::CommandEvaluator(Evaluator* ev) 175 : ev_(ev) { 176 #define INSERT_AUTO_VAR(name, sym) do { \ 177 Var* v = new name(this, sym); \ 178 Intern(sym).SetGlobalVar(v); \ 179 Intern(sym"D").SetGlobalVar(new AutoSuffixDVar(this, sym"D", v)); \ 180 Intern(sym"F").SetGlobalVar(new AutoSuffixFVar(this, sym"F", v)); \ 181 } while (0) 182 INSERT_AUTO_VAR(AutoAtVar, "@"); 183 INSERT_AUTO_VAR(AutoLessVar, "<"); 184 INSERT_AUTO_VAR(AutoHatVar, "^"); 185 INSERT_AUTO_VAR(AutoPlusVar, "+"); 186 INSERT_AUTO_VAR(AutoStarVar, "*"); 187 // TODO: Implement them. 188 INSERT_AUTO_VAR(AutoNotImplementedVar, "%"); 189 INSERT_AUTO_VAR(AutoNotImplementedVar, "?"); 190 INSERT_AUTO_VAR(AutoNotImplementedVar, "|"); 191 } 192 193 void CommandEvaluator::Eval(DepNode* n, vector<Command*>* commands) { 194 ev_->set_loc(n->loc); 195 ev_->set_current_scope(n->rule_vars); 196 current_dep_node_ = n; 197 for (Value* v : n->cmds) { 198 const string&& cmds_buf = v->Eval(ev_); 199 StringPiece cmds = cmds_buf; 200 bool global_echo = !g_flags.is_silent_mode; 201 bool global_ignore_error = false; 202 ParseCommandPrefixes(&cmds, &global_echo, &global_ignore_error); 203 if (cmds == "") 204 continue; 205 while (true) { 206 size_t lf_cnt; 207 size_t index = FindEndOfLine(cmds, 0, &lf_cnt); 208 if (index == cmds.size()) 209 index = string::npos; 210 StringPiece cmd = TrimLeftSpace(cmds.substr(0, index)); 211 cmds = cmds.substr(index + 1); 212 213 bool echo = global_echo; 214 bool ignore_error = global_ignore_error; 215 ParseCommandPrefixes(&cmd, &echo, &ignore_error); 216 217 if (!cmd.empty()) { 218 Command* command = new Command(n->output); 219 command->cmd = cmd.as_string(); 220 command->echo = echo; 221 command->ignore_error = ignore_error; 222 commands->push_back(command); 223 } 224 if (index == string::npos) 225 break; 226 } 227 continue; 228 } 229 230 if (!ev_->delayed_output_commands().empty()) { 231 vector<Command*> output_commands; 232 for (const string& cmd : ev_->delayed_output_commands()) { 233 Command* c = new Command(n->output); 234 c->cmd = cmd; 235 c->echo = false; 236 c->ignore_error = false; 237 output_commands.push_back(c); 238 } 239 // Prepend |output_commands|. 240 commands->swap(output_commands); 241 copy(output_commands.begin(), output_commands.end(), 242 back_inserter(*commands)); 243 ev_->clear_delayed_output_commands(); 244 } 245 246 ev_->set_current_scope(NULL); 247 } 248