<commit_before>//===- lib/Driver/UniversalDriver.cpp -------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
///
/// Driver for "universal" lld tool which can mimic any linker command line
/// parsing once it figures out which command line flavor to use.
///
//===----------------------------------------------------------------------===//

#include "lld/Driver/Driver.h"

#include "lld/Core/LLVM.h"

#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"

using namespace lld;

namespace {
enum class Flavor {
  invalid,
  gnu_ld,       // -flavor gnu
  win_link,     // -flavor link
  darwin_ld,    // -flavor darwin
  core          // -flavor core OR -core
};

Flavor strToFlavor(StringRef str) {
  return llvm::StringSwitch<Flavor>(str)
           .Case("gnu", Flavor::gnu_ld)
           .Case("link", Flavor::win_link)
           .Case("darwin", Flavor::darwin_ld)
           .Case("core", Flavor::core)
           .Case("ld", Flavor::gnu_ld) // deprecated
           .Default(Flavor::invalid);
}

struct ProgramNameParts {
  StringRef _target;
  StringRef _flavor;
};

ProgramNameParts parseProgramName(StringRef programName) {
  SmallVector<StringRef, 3> components;
  llvm::SplitString(programName, components, "-");
  ProgramNameParts ret;

  using std::begin;
  using std::end;

  // Erase any lld components.
  components.erase(std::remove(components.begin(), components.end(), "lld"),
                   components.end());

  // Find the flavor component.
  auto flIter = std::find_if(components.begin(), components.end(),
                             [](StringRef str)->bool {
    return strToFlavor(str) != Flavor::invalid;
  });

  if (flIter != components.end()) {
    ret._flavor = *flIter;
    components.erase(flIter);
  }

  // Any remaining component must be the target.
  if (components.size() == 1)
    ret._target = components[0];

  return ret;
}

Flavor selectFlavor(std::vector<const char *> &args, raw_ostream &diag) {
  // -core as first arg is shorthand for -flavor core.
  if (args.size() > 1 && StringRef(args[1]) == "-core") {
    args.erase(args.begin() + 1);
    return Flavor::core;
  }
  // Handle -flavor as first arg.
  if (args.size() > 2 && StringRef(args[1]) == "-flavor") {
    Flavor flavor = strToFlavor(args[2]);
    args.erase(args.begin() + 1);
    args.erase(args.begin() + 1);
    if (flavor == Flavor::invalid)
      diag << "error: '" << args[2] << "' invalid value for -flavor.\n";
    return flavor;
  }

  Flavor flavor =
      strToFlavor(parseProgramName(llvm::sys::path::stem(args[0]))._flavor);

  // If flavor still undetermined, then error out.
  if (flavor == Flavor::invalid)
    diag << "error: failed to determine driver flavor from program name"
            " '" << args[0] << "'.\n";
  return flavor;
}
}

namespace lld {
bool UniversalDriver::link(int argc, const char *argv[],
                           raw_ostream &diagnostics) {
  // Convert argv[] C-array to vector.
  std::vector<const char *> args(argv, argv + argc);

  // Determine flavor of link based on command name or -flavor argument.
  // Note: 'args' is modified to remove -flavor option.
  Flavor flavor = selectFlavor(args, diagnostics);

  // Switch to appropriate driver.
  switch (flavor) {
  case Flavor::gnu_ld:
    return GnuLdDriver::linkELF(args.size(), args.data(), diagnostics);
  case Flavor::darwin_ld:
    return DarwinLdDriver::linkMachO(args.size(), args.data(), diagnostics);
  case Flavor::core:<commit_msg>[lld] Add help text for -flavor option.<commit_after>//===- lib/Driver/UniversalDriver.cpp -------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
///
/// Driver for "universal" lld tool which can mimic any linker command line
/// parsing once it figures out which command line flavor to use.
///
//===----------------------------------------------------------------------===//

#include "lld/Driver/Driver.h"

#include "lld/Core/LLVM.h"

#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"

using namespace lld;

namespace {
enum class Flavor {
  invalid,
  gnu_ld,       // -flavor gnu
  win_link,     // -flavor link
  darwin_ld,    // -flavor darwin
  core          // -flavor core OR -core
};

Flavor strToFlavor(StringRef str) {
  return llvm::StringSwitch<Flavor>(str)
           .Case("gnu", Flavor::gnu_ld)
           .Case("link", Flavor::win_link)
           .Case("darwin", Flavor::darwin_ld)
           .Case("core", Flavor::core)
           .Case("ld", Flavor::gnu_ld) // deprecated
           .Default(Flavor::invalid);
}

struct ProgramNameParts {
  StringRef _target;
  StringRef _flavor;
};

ProgramNameParts parseProgramName(StringRef programName) {
  SmallVector<StringRef, 3> components;
  llvm::SplitString(programName, components, "-");
  ProgramNameParts ret;

  using std::begin;
  using std::end;

  // Erase any lld components.
  components.erase(std::remove(components.begin(), components.end(), "lld"),
                   components.end());

  // Find the flavor component.
  auto flIter = std::find_if(components.begin(), components.end(),
                             [](StringRef str)->bool {
    return strToFlavor(str) != Flavor::invalid;
  });

  if (flIter != components.end()) {
    ret._flavor = *flIter;
    components.erase(flIter);
  }

  // Any remaining component must be the target.
  if (components.size() == 1)
    ret._target = components[0];

  return ret;
}

Flavor selectFlavor(std::vector<const char *> &args, raw_ostream &diag) {
  // -core as first arg is shorthand for -flavor core.
  if (args.size() > 1 && StringRef(args[1]) == "-core") {
    args.erase(args.begin() + 1);
    return Flavor::core;
  }
  // Handle -flavor as first arg.
  if (args.size() > 2 && StringRef(args[1]) == "-flavor") {
    Flavor flavor = strToFlavor(args[2]);
    args.erase(args.begin() + 1);
    args.erase(args.begin() + 1);
    if (flavor == Flavor::invalid)
      diag << "error: '" << args[2] << "' invalid value for -flavor.\n";
    return flavor;
  }

  Flavor flavor =
      strToFlavor(parseProgramName(llvm::sys::path::stem(args[0]))._flavor);

  // If flavor still undetermined, then error out.
  if (flavor == Flavor::invalid)
    diag << "error: failed to determine driver flavor from program name"
         << " '" << args[0] << "'.\n"
         << "select a flavor with -flavor [gnu|darwin|core].\n";
  return flavor;
}
}

namespace lld {
bool UniversalDriver::link(int argc, const char *argv[],
                           raw_ostream &diagnostics) {
  // Convert argv[] C-array to vector.
  std::vector<const char *> args(argv, argv + argc);

  // Determine flavor of link based on command name or -flavor argument.
  // Note: 'args' is modified to remove -flavor option.
  Flavor flavor = selectFlavor(args, diagnostics);

  // Switch to appropriate driver.
  switch (flavor) {
  case Flavor::gnu_ld:
    return GnuLdDriver::linkELF(args.size(), args.data(), diagnostics);
  case Flavor::darwin_ld:
    return DarwinLdDriver::linkMachO(args.size(), args.data(), diagnostics);
  case Flavor::core:
{'fraction_non_alphanumeric': 0.19460227272727273, 'fraction_numerical': 0.003615702479338843, 'mean_word_length': 2.466875559534467, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3603210', 'n_tokens_mistral': 2431, 'n_tokens_neox': 2370, 'n_words': 615}