// Copyright 2014 The Bazel Authors. 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.

#include "src/main/cpp/option_processor.h"
#include "src/main/cpp/option_processor-internal.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <cassert>
#include <iterator>
#include <set>
#include <sstream>
#include <utility>

#include "src/main/cpp/blaze_util.h"
#include "src/main/cpp/blaze_util_platform.h"
#include "src/main/cpp/util/file.h"
#include "src/main/cpp/util/logging.h"
#include "src/main/cpp/util/path.h"
#include "src/main/cpp/util/path_platform.h"
#include "src/main/cpp/util/strings.h"
#include "src/main/cpp/workspace_layout.h"

// On OSX, there apparently is no header that defines this.
#ifndef environ
extern char **environ;
#endif

namespace blaze {

using std::map;
using std::set;
using std::string;
using std::vector;

constexpr char WorkspaceLayout::WorkspacePrefix[];
static constexpr const char* kRcBasename = ".bazelrc";
static std::vector<std::string> GetProcessedEnv();

OptionProcessor::OptionProcessor(
    const WorkspaceLayout* workspace_layout,
    std::unique_ptr<StartupOptions> default_startup_options)
    : workspace_layout_(workspace_layout),
      parsed_startup_options_(std::move(default_startup_options)),
      system_bazelrc_path_(BAZEL_SYSTEM_BAZELRC_PATH) {}

OptionProcessor::OptionProcessor(
    const WorkspaceLayout* workspace_layout,
    std::unique_ptr<StartupOptions> default_startup_options,
    const std::string& system_bazelrc_path)
    : workspace_layout_(workspace_layout),
      parsed_startup_options_(std::move(default_startup_options)),
      system_bazelrc_path_(system_bazelrc_path) {}

std::unique_ptr<CommandLine> OptionProcessor::SplitCommandLine(
    vector<string> args, string* error) const {
  const string lowercase_product_name =
      parsed_startup_options_->GetLowercaseProductName();

  if (args.empty()) {
    blaze_util::StringPrintf(error,
                             "Unable to split command line, args is empty");
    return nullptr;
  }

  string& path_to_binary = args[0];

  // Process the startup options.
  vector<string> startup_args;
  vector<string>::size_type i = 1;
  while (i < args.size() && IsArg(args[i])) {
    string& current_arg = args[i];
    // If the current argument is a valid nullary startup option such as
    // --master_bazelrc or --nomaster_bazelrc proceed to examine the next
    // argument.
    if (parsed_startup_options_->IsNullary(current_arg)) {
      startup_args.push_back(current_arg);
      i++;
    } else if (parsed_startup_options_->IsUnary(current_arg)) {
      // If the current argument is a valid unary startup option such as
      // --bazelrc there are two cases to consider.

      // The option is of the form '--bazelrc=value', hence proceed to
      // examine the next argument.
      if (current_arg.find("=") != string::npos) {
        startup_args.push_back(std::move(current_arg));
        i++;
      } else {
        // Otherwise, the option is of the form '--bazelrc value', hence
        // skip the next argument and proceed to examine the argument located
        // two places after.
        if (i + 1 >= args.size()) {
          blaze_util::StringPrintf(
              error,
              "Startup option '%s' expects a value.\n"
              "Usage: '%s=somevalue' or '%s somevalue'.\n"
              "  For more info, run '%s help startup_options'.",
              current_arg.c_str(), current_arg.c_str(), current_arg.c_str(),
              lowercase_product_name.c_str());
          return nullptr;
        }
        // In this case we transform it to the form '--bazelrc=value'.
        startup_args.push_back(std::move(current_arg) + "=" +
                               std::move(args[i + 1]));
        i += 2;
      }
    } else {
      // If the current argument is not a valid unary or nullary startup option
      // then fail.
      blaze_util::StringPrintf(
          error,
          "Unknown startup option: '%s'.\n"
          "  For more info, run '%s help startup_options'.",
          current_arg.c_str(), lowercase_product_name.c_str());
      return nullptr;
    }
  }

  // The command is the arg right after the startup options.
  if (i == args.size()) {
    return std::unique_ptr<CommandLine>(new CommandLine(
        std::move(path_to_binary), std::move(startup_args), "", {}));
  }
  string& command = args[i];

  // The rest are the command arguments.
  vector<string> command_args(std::make_move_iterator(args.begin() + i + 1),
                              std::make_move_iterator(args.end()));

  return std::unique_ptr<CommandLine>(
      new CommandLine(std::move(path_to_binary), std::move(startup_args),
                      std::move(command), std::move(command_args)));
}

namespace internal {

std::string FindLegacyUserBazelrc(const char* cmd_line_rc_file,
                                  const std::string& workspace) {
  if (cmd_line_rc_file != nullptr) {
    string rcFile = blaze::AbsolutePathFromFlag(cmd_line_rc_file);
    if (!blaze_util::CanReadFile(rcFile)) {
      // The actual rc file reading will catch this - we ignore this here in the
      // legacy version since this is just a warning. Exit eagerly though.
      return "";
    }
    return rcFile;
  }

  string workspaceRcFile = blaze_util::JoinPath(workspace, kRcBasename);
  if (blaze_util::CanReadFile(workspaceRcFile)) {
    return workspaceRcFile;
  }

  string home = blaze::GetHomeDir();
  if (!home.empty()) {
    string userRcFile = blaze_util::JoinPath(home, kRcBasename);
    if (blaze_util::CanReadFile(userRcFile)) {
      return userRcFile;
    }
  }
  return "";
}

std::set<std::string> GetOldRcPaths(
    const WorkspaceLayout* workspace_layout, const std::string& workspace,
    const std::string& cwd, const std::string& path_to_binary,
    const std::vector<std::string>& startup_args,
    const std::string& system_bazelrc_path) {
  // Find the old list of rc files that would have been loaded here, so we can
  // provide a useful warning about old rc files that might no longer be read.
  std::vector<std::string> candidate_bazelrc_paths;
  if (SearchNullaryOption(startup_args, "master_bazelrc", true)) {
    const std::string workspace_rc =
        workspace_layout->GetWorkspaceRcPath(workspace, startup_args);
    const std::string binary_rc =
        internal::FindRcAlongsideBinary(cwd, path_to_binary);
    candidate_bazelrc_paths = {workspace_rc, binary_rc, system_bazelrc_path};
  }
  string user_bazelrc_path = internal::FindLegacyUserBazelrc(
      SearchUnaryOption(startup_args, "--bazelrc"), workspace);
  if (!user_bazelrc_path.empty()) {
    candidate_bazelrc_paths.push_back(user_bazelrc_path);
  }
  // DedupeBlazercPaths returns paths whose canonical path could be computed,
  // therefore these paths must exist.
  const std::vector<std::string> deduped_existing_blazerc_paths =
      internal::DedupeBlazercPaths(candidate_bazelrc_paths);
  return std::set<std::string>(deduped_existing_blazerc_paths.begin(),
                               deduped_existing_blazerc_paths.end());
}

// Deduplicates the given paths based on their canonical form.
// Computes the canonical form using blaze_util::MakeCanonical.
// Returns the unique paths in their original form (not the canonical one).
std::vector<std::string> DedupeBlazercPaths(
    const std::vector<std::string>& paths) {
  std::set<std::string> canonical_paths;
  std::vector<std::string> result;
  for (const std::string& path : paths) {
    const std::string canonical_path = blaze_util::MakeCanonical(path.c_str());
    if (canonical_path.empty()) {
      // MakeCanonical returns an empty string when it fails. We ignore this
      // failure since blazerc paths may point to invalid locations.
    } else if (canonical_paths.find(canonical_path) == canonical_paths.end()) {
      result.push_back(path);
      canonical_paths.insert(canonical_path);
    }
  }
  return result;
}

std::string FindSystemWideRc(const std::string& system_bazelrc_path) {
  const std::string path =
      blaze_util::MakeAbsoluteAndResolveEnvvars(system_bazelrc_path);
  if (blaze_util::CanReadFile(path)) {
    return path;
  }
  return "";
}

std::string FindRcAlongsideBinary(const std::string& cwd,
                                  const std::string& path_to_binary) {
  const std::string path = blaze_util::IsAbsolute(path_to_binary)
                               ? path_to_binary
                               : blaze_util::JoinPath(cwd, path_to_binary);
  const std::string base = blaze_util::Basename(path_to_binary);
  const std::string binary_blazerc_path = path + "." + base + "rc";
  if (blaze_util::CanReadFile(binary_blazerc_path)) {
    return binary_blazerc_path;
  }
  return "";
}

blaze_exit_code::ExitCode ParseErrorToExitCode(RcFile::ParseError parse_error) {
  switch (parse_error) {
    case RcFile::ParseError::NONE:
      return blaze_exit_code::SUCCESS;
    case RcFile::ParseError::UNREADABLE_FILE:
      // We check readability before parsing, so this is unexpected for
      // top-level rc files, so is an INTERNAL_ERROR. It can happen for imported
      // files, however, which should be BAD_ARGV, but we don't currently
      // differentiate.
      // TODO(bazel-team): fix RcFile to reclassify unreadable files that were
      // read from a recursive call due to a malformed import.
      return blaze_exit_code::INTERNAL_ERROR;
    case RcFile::ParseError::INVALID_FORMAT:
    case RcFile::ParseError::IMPORT_LOOP:
      return blaze_exit_code::BAD_ARGV;
    default:
      return blaze_exit_code::INTERNAL_ERROR;
  }
}

void WarnAboutDuplicateRcFiles(const std::set<std::string>& read_files,
                               const std::deque<std::string>& loaded_rcs) {
  // The first rc file in the queue is the top-level one, the one that would
  // have imported all the others in the queue. The top-level rc is one of the
  // default locations (system, workspace, home) or the explicit path passed by
  // --bazelrc.
  const std::string& top_level_rc = loaded_rcs.front();

  const std::set<std::string> unique_loaded_rcs(loaded_rcs.begin(),
                                                loaded_rcs.end());
  // First check if each of the newly loaded rc files was already read.
  for (const std::string& loaded_rc : unique_loaded_rcs) {
    if (read_files.count(loaded_rc) > 0) {
      if (loaded_rc == top_level_rc) {
        BAZEL_LOG(WARNING)
            << "Duplicate rc file: " << loaded_rc
            << " is read multiple times, it is a standard rc file location "
               "but must have been unnecessarily imported earlier.";
      } else {
        BAZEL_LOG(WARNING)
            << "Duplicate rc file: " << loaded_rc
            << " is read multiple times, most recently imported from "
            << top_level_rc;
      }
    }
    // Now check if the top-level rc file loads up its own duplicates (it can't
    // be a cycle, since that would be an error and we would have already
    // exited, but it could have a diamond dependency of some sort.)
    if (std::count(loaded_rcs.begin(), loaded_rcs.end(), loaded_rc) > 1) {
      BAZEL_LOG(WARNING) << "Duplicate rc file: " << loaded_rc
                         << " is imported multiple times from " << top_level_rc;
    }
  }
}

std::vector<std::string> GetLostFiles(
    const std::set<std::string>& old_files,
    const std::set<std::string>& read_files_canon) {
  std::vector<std::string> result;
  for (const auto& old : old_files) {
    std::string old_canon = blaze_util::MakeCanonical(old.c_str());
    if (!old_canon.empty() &&
        read_files_canon.find(old_canon) == read_files_canon.end()) {
      result.push_back(old);
    }
  }
  return result;
}

}  // namespace internal

// TODO(#4502) Consider simplifying result_rc_files to a vector of RcFiles, no
// unique_ptrs.
blaze_exit_code::ExitCode OptionProcessor::GetRcFiles(
    const WorkspaceLayout* workspace_layout, const std::string& workspace,
    const std::string& cwd, const CommandLine* cmd_line,
    std::vector<std::unique_ptr<RcFile>>* result_rc_files,
    std::string* error) const {
  assert(cmd_line != nullptr);
  assert(result_rc_files != nullptr);

  std::vector<std::string> rc_files;

  // Get the system rc (unless --nosystem_rc).
  if (SearchNullaryOption(cmd_line->startup_args, "system_rc", true)) {
    // MakeAbsoluteAndResolveEnvvars will standardize the form of the
    // provided path. This also means we accept relative paths, which is
    // is convenient for testing.
    const std::string system_rc =
        blaze_util::MakeAbsoluteAndResolveEnvvars(system_bazelrc_path_);
    rc_files.push_back(system_rc);
  }

  // Get the workspace rc: %workspace%/.bazelrc (unless --noworkspace_rc), but
  // only if we are in a workspace: invoking commands like "help" from outside
  // a workspace should work.
  if (!workspace.empty() &&
      SearchNullaryOption(cmd_line->startup_args, "workspace_rc", true)) {
    const std::string workspaceRcFile =
        blaze_util::JoinPath(workspace, kRcBasename);
    rc_files.push_back(workspaceRcFile);
  }

  // Get the user rc: $HOME/.bazelrc (unless --nohome_rc)
  if (SearchNullaryOption(cmd_line->startup_args, "home_rc", true)) {
    const std::string home = blaze::GetHomeDir();
    if (!home.empty()) {
      rc_files.push_back(blaze_util::JoinPath(home, kRcBasename));
    }
  }

  // Get the command-line provided rc, passed as --bazelrc or nothing if the
  // flag is absent.
  const char* cmd_line_rc_file =
      SearchUnaryOption(cmd_line->startup_args, "--bazelrc");
  if (cmd_line_rc_file != nullptr) {
    string absolute_cmd_line_rc = blaze::AbsolutePathFromFlag(cmd_line_rc_file);
    // Unlike the previous 3 paths, where we ignore it if the file does not
    // exist or is unreadable, since this path is explicitly passed, this is an
    // error. Check this condition here.
    if (!blaze_util::CanReadFile(absolute_cmd_line_rc)) {
      BAZEL_LOG(ERROR) << "Error: Unable to read .bazelrc file '"
                       << absolute_cmd_line_rc << "'.";
      return blaze_exit_code::BAD_ARGV;
    }
    rc_files.push_back(absolute_cmd_line_rc);
  }

  // Log which files we're looking for before removing duplicates and
  // non-existent files, so that this can serve to debug why a certain file is
  // not being read. The final files which are read will be logged as they are
  // parsed, and can be found using --announce_rc.
  std::string joined_rcs;
  blaze_util::JoinStrings(rc_files, ',', &joined_rcs);
  BAZEL_LOG(INFO) << "Looking for the following rc files: " << joined_rcs;

  // It's possible that workspace == home, that files are symlinks for each
  // other, or that the --bazelrc flag is a duplicate. Dedupe them to minimize
  // the likelihood of repeated options. Since bazelrcs can include one another,
  // this isn't sufficient to prevent duplicate options, so we also warn if we
  // discover duplicate loads later. This also has the effect of removing paths
  // that don't point to real files.
  rc_files = internal::DedupeBlazercPaths(rc_files);

  std::set<std::string> read_files_canonical_paths;
  // Parse these potential files, in priority order;
  for (const std::string& top_level_bazelrc_path : rc_files) {
    std::unique_ptr<RcFile> parsed_rc;
    blaze_exit_code::ExitCode parse_rcfile_exit_code = ParseRcFile(
        workspace_layout, workspace, top_level_bazelrc_path, &parsed_rc, error);
    if (parse_rcfile_exit_code != blaze_exit_code::SUCCESS) {
      return parse_rcfile_exit_code;
    }

    // Check that none of the rc files loaded this time are duplicate.
    const std::deque<std::string>& sources =
        parsed_rc->canonical_source_paths();
    internal::WarnAboutDuplicateRcFiles(read_files_canonical_paths, sources);
    read_files_canonical_paths.insert(sources.begin(), sources.end());

    result_rc_files->push_back(std::move(parsed_rc));
  }

  // Provide a warning for any old file that might have been missed with the new
  // expectations. This compares "canonical" paths to one another, so should not
  // require additional transformation.
  // TODO(b/36168162): Remove this warning along with
  // internal::GetOldRcPaths and internal::FindLegacyUserBazelrc after
  // the transition period has passed.
  const std::set<std::string> old_files = internal::GetOldRcPaths(
      workspace_layout, workspace, cwd, cmd_line->path_to_binary,
      cmd_line->startup_args, internal::FindSystemWideRc(system_bazelrc_path_));

  std::vector<std::string> lost_files =
      internal::GetLostFiles(old_files, read_files_canonical_paths);
  if (!lost_files.empty()) {
    std::string joined_lost_rcs;
    blaze_util::JoinStrings(lost_files, '\n', &joined_lost_rcs);
    BAZEL_LOG(WARNING)
        << "The following rc files are no longer being read, please transfer "
           "their contents or import their path into one of the standard rc "
           "files:\n"
        << joined_lost_rcs;
  }

  return blaze_exit_code::SUCCESS;
}

blaze_exit_code::ExitCode ParseRcFile(const WorkspaceLayout* workspace_layout,
                                      const std::string& workspace,
                                      const std::string& rc_file_path,
                                      std::unique_ptr<RcFile>* result_rc_file,
                                      std::string* error) {
  assert(!rc_file_path.empty());
  assert(result_rc_file != nullptr);

  RcFile::ParseError parse_error;
  std::unique_ptr<RcFile> parsed_file = RcFile::Parse(
      rc_file_path, workspace_layout, workspace, &parse_error, error);
  if (parsed_file == nullptr) {
    return internal::ParseErrorToExitCode(parse_error);
  }
  *result_rc_file = std::move(parsed_file);
  return blaze_exit_code::SUCCESS;
}

blaze_exit_code::ExitCode OptionProcessor::ParseOptions(
    const vector<string>& args, const string& workspace, const string& cwd,
    string* error) {
  cmd_line_ = SplitCommandLine(args, error);
  if (cmd_line_ == nullptr) {
    return blaze_exit_code::BAD_ARGV;
  }

  // Read the rc files, unless --ignore_all_rc_files was provided on the command
  // line. This depends on the startup options in argv since these may contain
  // other rc-modifying options. For all other options, the precedence of
  // options will be rc first, then command line options, though, despite this
  // exception.
  std::vector<std::unique_ptr<RcFile>> rc_files;
  if (!SearchNullaryOption(cmd_line_->startup_args, "ignore_all_rc_files",
                           false)) {
    const blaze_exit_code::ExitCode rc_parsing_exit_code = GetRcFiles(
        workspace_layout_, workspace, cwd, cmd_line_.get(), &rc_files, error);
    if (rc_parsing_exit_code != blaze_exit_code::SUCCESS) {
      return rc_parsing_exit_code;
    }
  }

  // Parse the startup options in the correct priority order.
  const blaze_exit_code::ExitCode parse_startup_options_exit_code =
      ParseStartupOptions(rc_files, error);
  if (parse_startup_options_exit_code != blaze_exit_code::SUCCESS) {
    return parse_startup_options_exit_code;
  }

  blazerc_and_env_command_args_ =
      GetBlazercAndEnvCommandArgs(cwd, rc_files, GetProcessedEnv());
  return blaze_exit_code::SUCCESS;
}

static void PrintStartupOptions(const std::string& source,
                                const std::vector<std::string>& options) {
  if (!source.empty()) {
    std::string startup_args;
    blaze_util::JoinStrings(options, ' ', &startup_args);
    fprintf(stderr, "INFO: Reading 'startup' options from %s: %s\n",
            source.c_str(), startup_args.c_str());
  }
}

void OptionProcessor::PrintStartupOptionsProvenanceMessage() const {
  StartupOptions* parsed_startup_options = GetParsedStartupOptions();

  // Print the startup flags in the order they are parsed, to keep the
  // precedence clear. In order to minimize the number of lines of output in
  // the terminal, group sequential flags by origin. Note that an rc file may
  // turn up multiple times in this list, if, for example, it imports another
  // rc file and contains startup options on either side of the import
  // statement. This is done intentionally to make option priority clear.
  std::string command_line_source;
  std::string& most_recent_blazerc = command_line_source;
  std::vector<std::string> accumulated_options;
  for (const auto& flag : parsed_startup_options->original_startup_options_) {
    if (flag.source == most_recent_blazerc) {
      accumulated_options.push_back(flag.value);
    } else {
      PrintStartupOptions(most_recent_blazerc, accumulated_options);
      // Start accumulating again.
      accumulated_options.clear();
      accumulated_options.push_back(flag.value);
      most_recent_blazerc = flag.source;
    }
  }
  // Don't forget to print out the last ones.
  PrintStartupOptions(most_recent_blazerc, accumulated_options);
}

blaze_exit_code::ExitCode OptionProcessor::ParseStartupOptions(
    const std::vector<std::unique_ptr<RcFile>> &rc_files,
    std::string *error) {
  // Rc files can import other files at any point, and these imported rcs are
  // expanded in place. Here, we isolate just the startup options but keep the
  // file they came from attached for the option_sources tracking and for
  // sending to the server.
  std::vector<RcStartupFlag> rcstartup_flags;

  for (const auto& blazerc : rc_files) {
    const auto iter = blazerc->options().find("startup");
    if (iter == blazerc->options().end()) continue;

    for (const RcOption& option : iter->second) {
      rcstartup_flags.push_back({*option.source_path, option.option});
    }
  }

  for (const std::string& arg : cmd_line_->startup_args) {
    if (!IsArg(arg)) {
      break;
    }
    rcstartup_flags.push_back(RcStartupFlag("", arg));
  }

  return parsed_startup_options_->ProcessArgs(rcstartup_flags, error);
}

static bool IsValidEnvName(const char* p) {
#if defined(_WIN32) || defined(__CYGWIN__)
  for (; *p && *p != '='; ++p) {
    if (!((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') ||
          (*p >= '0' && *p <= '9') || *p == '_')) {
      return false;
    }
  }
#endif
  return true;
}

#if defined(_WIN32)
static void PreprocessEnvString(string* env_str) {
  static constexpr const char* vars_to_uppercase[] = {"PATH", "SYSTEMROOT",
                                                      "SYSTEMDRIVE",
                                                      "TEMP", "TEMPDIR", "TMP"};

  int pos = env_str->find_first_of('=');
  if (pos == string::npos) return;

  string name = env_str->substr(0, pos);
  // We do not care about locale. All variable names are ASCII.
  std::transform(name.begin(), name.end(), name.begin(), ::toupper);
  if (std::find(std::begin(vars_to_uppercase), std::end(vars_to_uppercase),
                name) != std::end(vars_to_uppercase)) {
    env_str->assign(name + "=" + env_str->substr(pos + 1));
  }
}

#elif defined(__CYGWIN__)  // not defined(_WIN32)

static void PreprocessEnvString(string* env_str) {
  int pos = env_str->find_first_of('=');
  if (pos == string::npos) return;
  string name = env_str->substr(0, pos);
  if (name == "PATH") {
    env_str->assign("PATH=" + env_str->substr(pos + 1));
  } else if (name == "TMP") {
    // A valid Windows path "c:/foo" is also a valid Unix path list of
    // ["c", "/foo"] so must use ConvertPath here. See GitHub issue #1684.
    env_str->assign("TMP=" + blaze_util::ConvertPath(env_str->substr(pos + 1)));
  }
}

#else  // Non-Windows platforms.

static void PreprocessEnvString(const string* env_str) {
  // do nothing.
}
#endif  // defined(_WIN32)

static std::vector<std::string> GetProcessedEnv() {
  std::vector<std::string> processed_env;
  for (char** env = environ; *env != NULL; env++) {
    string env_str(*env);
    if (IsValidEnvName(*env)) {
      PreprocessEnvString(&env_str);
      processed_env.push_back(std::move(env_str));
    }
  }
  return processed_env;
}

// IMPORTANT: The options added here do not come from the user. In order for
// their source to be correctly tracked, the options must either be passed
// as --default_override=0, 0 being "client", or must be listed in
// BlazeOptionHandler.INTERNAL_COMMAND_OPTIONS!
std::vector<std::string> OptionProcessor::GetBlazercAndEnvCommandArgs(
    const std::string& cwd,
    const std::vector<std::unique_ptr<RcFile>>& blazercs,
    const std::vector<std::string>& env) {
  // Provide terminal options as coming from the least important rc file.
  std::vector<std::string> result = {
      "--rc_source=client",
      "--default_override=0:common=--isatty=" +
          ToString(IsStderrStandardTerminal()),
      "--default_override=0:common=--terminal_columns=" +
          ToString(GetStderrTerminalColumns())};
  if (IsEmacsTerminal()) {
    result.push_back("--default_override=0:common=--emacs");
  }

  EnsurePythonPathOption(&result);

  // Map .blazerc numbers to filenames. The indexes here start at 1 because #0
  // is reserved the "client" options created by this function.
  int cur_index = 1;
  std::map<std::string, int> rcfile_indexes;
  for (const auto& blazerc : blazercs) {
    for (const std::string& source_path : blazerc->canonical_source_paths()) {
      // Deduplicate the rc_source list because the same file might be included
      // from multiple places.
      if (rcfile_indexes.find(source_path) != rcfile_indexes.end()) continue;

      result.push_back("--rc_source=" + blaze_util::ConvertPath(source_path));
      rcfile_indexes[source_path] = cur_index;
      cur_index++;
    }
  }

  // Add RcOptions as default_overrides.
  for (const auto& blazerc : blazercs) {
    for (const auto& command_options : blazerc->options()) {
      const string& command = command_options.first;
      // Skip startup flags, which are already parsed by the client.
      if (command == "startup") continue;

      for (const RcOption& rcoption : command_options.second) {
        std::ostringstream oss;
        oss << "--default_override=" << rcfile_indexes[*rcoption.source_path]
            << ':' << command << '=' << rcoption.option;
        result.push_back(oss.str());
      }
    }
  }

  // Pass the client environment to the server.
  for (const string& env_var : env) {
    result.push_back("--client_env=" + env_var);
  }
  result.push_back("--client_cwd=" + blaze_util::ConvertPath(cwd));
  return result;
}

std::vector<std::string> OptionProcessor::GetCommandArguments() const {
  assert(cmd_line_ != nullptr);
  // When the user didn't specify a command, the server expects the command
  // arguments to be empty in order to display the help message.
  if (cmd_line_->command.empty()) {
    return {};
  }

  std::vector<std::string> command_args = blazerc_and_env_command_args_;
  command_args.insert(command_args.end(),
                      cmd_line_->command_args.begin(),
                      cmd_line_->command_args.end());
  return command_args;
}

std::vector<std::string> OptionProcessor::GetExplicitCommandArguments() const {
  assert(cmd_line_ != nullptr);
  return cmd_line_->command_args;
}

std::string OptionProcessor::GetCommand() const {
  assert(cmd_line_ != nullptr);
  return cmd_line_->command;
}

StartupOptions* OptionProcessor::GetParsedStartupOptions() const {
  assert(parsed_startup_options_ != NULL);
  return parsed_startup_options_.get();
}

}  // namespace blaze
