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