// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "tools/gn/c_tool.h"
#include "tools/gn/c_substitution_type.h"
#include "tools/gn/target.h"

const char* CTool::kCToolCc = "cc";
const char* CTool::kCToolCxx = "cxx";
const char* CTool::kCToolObjC = "objc";
const char* CTool::kCToolObjCxx = "objcxx";
const char* CTool::kCToolRc = "rc";
const char* CTool::kCToolAsm = "asm";
const char* CTool::kCToolAlink = "alink";
const char* CTool::kCToolSolink = "solink";
const char* CTool::kCToolSolinkModule = "solink_module";
const char* CTool::kCToolLink = "link";

CTool::CTool(const char* n)
    : Tool(n), depsformat_(DEPS_GCC), precompiled_header_type_(PCH_NONE) {
  CHECK(ValidateName(n));
  set_framework_switch("-framework ");
  set_lib_dir_switch("-L");
  set_lib_switch("-l");
  set_linker_arg("");
}

CTool::~CTool() = default;

CTool* CTool::AsC() {
  return this;
}
const CTool* CTool::AsC() const {
  return this;
}

bool CTool::ValidateName(const char* name) const {
  return name == kCToolCc || name == kCToolCxx || name == kCToolObjC ||
         name == kCToolObjCxx || name == kCToolRc || name == kCToolAsm ||
         name == kCToolAlink || name == kCToolSolink ||
         name == kCToolSolinkModule || name == kCToolLink;
}

void CTool::SetComplete() {
  SetToolComplete();
  link_output_.FillRequiredTypes(&substitution_bits_);
  depend_output_.FillRequiredTypes(&substitution_bits_);
}

bool CTool::ValidateRuntimeOutputs(Err* err) {
  if (runtime_outputs().list().empty())
    return true;  // Empty is always OK.

  if (name_ != kCToolSolink && name_ != kCToolSolinkModule &&
      name_ != kCToolLink) {
    *err = Err(defined_from(), "This tool specifies runtime_outputs.",
               "This is only valid for linker tools (alink doesn't count).");
    return false;
  }

  for (const SubstitutionPattern& pattern : runtime_outputs().list()) {
    if (!IsPatternInOutputList(outputs(), pattern)) {
      *err = Err(defined_from(), "This tool's runtime_outputs is bad.",
                 "It must be a subset of the outputs. The bad one is:\n  " +
                     pattern.AsString());
      return false;
    }
  }
  return true;
}

// Validates either link_output or depend_output. To generalize to either, pass
// the associated pattern, and the variable name that should appear in error
// messages.
bool CTool::ValidateLinkAndDependOutput(const SubstitutionPattern& pattern,
                                        const char* variable_name,
                                        Err* err) {
  if (pattern.empty())
    return true;  // Empty is always OK.

  // It should only be specified for certain tool types.
  if (name_ != kCToolSolink && name_ != kCToolSolinkModule) {
    *err = Err(defined_from(),
               "This tool specifies a " + std::string(variable_name) + ".",
               "This is only valid for solink and solink_module tools.");
    return false;
  }

  if (!IsPatternInOutputList(outputs(), pattern)) {
    *err = Err(defined_from(), "This tool's link_output is bad.",
               "It must match one of the outputs.");
    return false;
  }

  return true;
}

bool CTool::ReadPrecompiledHeaderType(Scope* scope, Err* err) {
  const Value* value = scope->GetValue("precompiled_header_type", true);
  if (!value)
    return true;  // Not present is fine.
  if (!value->VerifyTypeIs(Value::STRING, err))
    return false;

  if (value->string_value().empty())
    return true;  // Accept empty string, do nothing (default is "no PCH").

  if (value->string_value() == "gcc") {
    set_precompiled_header_type(PCH_GCC);
    return true;
  } else if (value->string_value() == "msvc") {
    set_precompiled_header_type(PCH_MSVC);
    return true;
  }
  *err = Err(*value, "Invalid precompiled_header_type",
             "Must either be empty, \"gcc\", or \"msvc\".");
  return false;
}

bool CTool::ReadDepsFormat(Scope* scope, Err* err) {
  const Value* value = scope->GetValue("depsformat", true);
  if (!value)
    return true;  // Not present is fine.
  if (!value->VerifyTypeIs(Value::STRING, err))
    return false;

  if (value->string_value() == "gcc") {
    set_depsformat(DEPS_GCC);
  } else if (value->string_value() == "msvc") {
    set_depsformat(DEPS_MSVC);
  } else {
    *err = Err(*value, "Deps format must be \"gcc\" or \"msvc\".");
    return false;
  }
  return true;
}

bool CTool::ReadOutputsPatternList(Scope* scope,
                                   const char* var,
                                   SubstitutionList* field,
                                   Err* err) {
  DCHECK(!complete_);
  const Value* value = scope->GetValue(var, true);
  if (!value)
    return true;  // Not present is fine.
  if (!value->VerifyTypeIs(Value::LIST, err))
    return false;

  SubstitutionList list;
  if (!list.Parse(*value, err))
    return false;

  // Validate the right kinds of patterns are used.
  if (list.list().empty()) {
    *err = Err(defined_from(), "\"outputs\" must be specified for this tool.");
    return false;
  }

  for (const auto& cur_type : list.required_types()) {
    if (!ValidateOutputSubstitution(cur_type)) {
      *err = Err(*value, "Pattern not valid here.",
                 "You used the pattern " + std::string(cur_type->name) +
                     " which is not valid\nfor this variable.");
      return false;
    }
  }

  *field = std::move(list);
  return true;
}

bool CTool::InitTool(Scope* scope, Toolchain* toolchain, Err* err) {
  // Initialize default vars.
  if (!Tool::InitTool(scope, toolchain, err)) {
    return false;
  }

  // All C tools should have outputs.
  if (!ReadOutputsPatternList(scope, "outputs", &outputs_, err)) {
    return false;
  }

  if (!ReadDepsFormat(scope, err) || !ReadPrecompiledHeaderType(scope, err) ||
      !ReadString(scope, "lib_switch", &lib_switch_, err) ||
      !ReadString(scope, "lib_dir_switch", &lib_dir_switch_, err) ||
      !ReadPattern(scope, "link_output", &link_output_, err) ||
      !ReadPattern(scope, "depend_output", &depend_output_, err)) {
    return false;
  }

  // Validate link_output and depend_output.
  if (!ValidateLinkAndDependOutput(link_output(), "link_output", err)) {
    return false;
  }
  if (!ValidateLinkAndDependOutput(depend_output(), "depend_output", err)) {
    return false;
  }
  if ((!link_output().empty() && depend_output().empty()) ||
      (link_output().empty() && !depend_output().empty())) {
    *err = Err(defined_from(),
               "Both link_output and depend_output should either "
               "be specified or they should both be empty.");
    return false;
  }

  if (!ValidateRuntimeOutputs(err)) {
    return false;
  }
  return true;
}

bool CTool::ValidateSubstitution(const Substitution* sub_type) const {
  if (name_ == kCToolCc || name_ == kCToolCxx || name_ == kCToolObjC ||
      name_ == kCToolObjCxx || name_ == kCToolRc || name_ == kCToolAsm)
    return IsValidCompilerSubstitution(sub_type);
  else if (name_ == kCToolAlink)
    return IsValidALinkSubstitution(sub_type);
  else if (name_ == kCToolSolink || name_ == kCToolSolinkModule ||
           name_ == kCToolLink)
    return IsValidLinkerSubstitution(sub_type);
  NOTREACHED();
  return false;
}

bool CTool::ValidateOutputSubstitution(const Substitution* sub_type) const {
  if (name_ == kCToolCc || name_ == kCToolCxx || name_ == kCToolObjC ||
      name_ == kCToolObjCxx || name_ == kCToolRc || name_ == kCToolAsm)
    return IsValidCompilerOutputsSubstitution(sub_type);
  // ALink uses the standard output file patterns as other linker tools.
  else if (name_ == kCToolAlink || name_ == kCToolSolink ||
           name_ == kCToolSolinkModule || name_ == kCToolLink)
    return IsValidLinkerOutputsSubstitution(sub_type);
  NOTREACHED();
  return false;
}
