// Copyright 2015 Google Inc. All rights reserved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +build ignore

#include "rule.h"

#include "expr.h"
#include "log.h"
#include "parser.h"
#include "stringprintf.h"
#include "strutil.h"
#include "symtab.h"

Rule::Rule() : is_double_colon(false), is_suffix_rule(false), cmd_lineno(0) {}


void Rule::ParseInputs(const StringPiece &inputs_str) {
  bool is_order_only = false;
  for (auto const& input : WordScanner(inputs_str)) {
    if (input == "|") {
      is_order_only = true;
      continue;
    }
    Symbol input_sym = Intern(TrimLeadingCurdir(input));
    (is_order_only ? order_only_inputs : inputs).push_back(input_sym);
  }
}

void Rule::ParsePrerequisites(const StringPiece& line,
                              size_t separator_pos,
                              const RuleStmt *rule_stmt) {
  // line is either
  //    prerequisites [ ; command ]
  // or
  //    target-prerequisites : prereq-patterns [ ; command ]
  // First, separate command. At this point separator_pos should point to ';'
  // unless null.
  StringPiece prereq_string = line;
  if (separator_pos != string::npos && rule_stmt->sep != RuleStmt::SEP_SEMICOLON) {
    CHECK(line[separator_pos] == ';');
    // TODO: Maybe better to avoid Intern here?
    cmds.push_back(Value::NewLiteral(
        Intern(TrimLeftSpace(line.substr(separator_pos + 1))).str()));
    prereq_string = line.substr(0, separator_pos);
  }

  if ((separator_pos = prereq_string.find(':')) == string::npos) {
    // Simple prerequisites
    ParseInputs(prereq_string);
    return;
  }

  // Static pattern rule.
  if (!output_patterns.empty()) {
    ERROR_LOC(loc, "*** mixed implicit and normal rules: deprecated syntax");
  }

  // Empty static patterns should not produce rules, but need to eat the
  // commands So return a rule with no outputs nor output_patterns
  if (outputs.empty()) {
    return;
  }

  StringPiece target_prereq = prereq_string.substr(0, separator_pos);
  StringPiece prereq_patterns = prereq_string.substr(separator_pos + 1);

  for (StringPiece target_pattern : WordScanner(target_prereq)) {
    target_pattern = TrimLeadingCurdir(target_pattern);
    for (Symbol target : outputs) {
      if (!Pattern(target_pattern).Match(target.str())) {
        WARN_LOC(loc, "target `%s' doesn't match the target pattern",
                 target.c_str());
      }
    }
    output_patterns.push_back(Intern(target_pattern));
  }

  if (output_patterns.empty()) {
    ERROR_LOC(loc, "*** missing target pattern.");
  }
  if (output_patterns.size() > 1) {
    ERROR_LOC(loc, "*** multiple target patterns.");
  }
  if (!IsPatternRule(output_patterns[0].str())) {
    ERROR_LOC(loc, "*** target pattern contains no '%%'.");
  }
  ParseInputs(prereq_patterns);
}

string Rule::DebugString() const {
  vector<string> v;
  v.push_back(StringPrintf("outputs=[%s]", JoinSymbols(outputs, ",").c_str()));
  v.push_back(StringPrintf("inputs=[%s]", JoinSymbols(inputs, ",").c_str()));
  if (!order_only_inputs.empty()) {
    v.push_back(StringPrintf("order_only_inputs=[%s]",
                             JoinSymbols(order_only_inputs, ",").c_str()));
  }
  if (!output_patterns.empty()) {
    v.push_back(StringPrintf("output_patterns=[%s]",
                             JoinSymbols(output_patterns, ",").c_str()));
  }
  if (is_double_colon)
    v.push_back("is_double_colon");
  if (is_suffix_rule)
    v.push_back("is_suffix_rule");
  if (!cmds.empty()) {
    v.push_back(StringPrintf("cmds=[%s]", JoinValues(cmds, ",").c_str()));
  }
  return JoinStrings(v, " ");
}
