//===-- OptionArgParser.cpp -------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"

using namespace lldb_private;
using namespace lldb;

bool OptionArgParser::ToBoolean(llvm::StringRef ref, bool fail_value,
                                bool *success_ptr) {
  if (success_ptr)
    *success_ptr = true;
  ref = ref.trim();
  if (ref.equals_lower("false") || ref.equals_lower("off") ||
      ref.equals_lower("no") || ref.equals_lower("0")) {
    return false;
  } else if (ref.equals_lower("true") || ref.equals_lower("on") ||
             ref.equals_lower("yes") || ref.equals_lower("1")) {
    return true;
  }
  if (success_ptr)
    *success_ptr = false;
  return fail_value;
}

char OptionArgParser::ToChar(llvm::StringRef s, char fail_value,
                             bool *success_ptr) {
  if (success_ptr)
    *success_ptr = false;
  if (s.size() != 1)
    return fail_value;

  if (success_ptr)
    *success_ptr = true;
  return s[0];
}

int64_t OptionArgParser::ToOptionEnum(llvm::StringRef s,
                                      OptionEnumValueElement *enum_values,
                                      int32_t fail_value, Status &error) {
  error.Clear();
  if (!enum_values) {
    error.SetErrorString("invalid enumeration argument");
    return fail_value;
  }

  if (s.empty()) {
    error.SetErrorString("empty enumeration string");
    return fail_value;
  }

  for (int i = 0; enum_values[i].string_value != nullptr; i++) {
    llvm::StringRef this_enum(enum_values[i].string_value);
    if (this_enum.startswith(s))
      return enum_values[i].value;
  }

  StreamString strm;
  strm.PutCString("invalid enumeration value, valid values are: ");
  for (int i = 0; enum_values[i].string_value != nullptr; i++) {
    strm.Printf("%s\"%s\"", i > 0 ? ", " : "", enum_values[i].string_value);
  }
  error.SetErrorString(strm.GetString());
  return fail_value;
}

Status OptionArgParser::ToFormat(const char *s, lldb::Format &format,
                                 size_t *byte_size_ptr) {
  format = eFormatInvalid;
  Status error;

  if (s && s[0]) {
    if (byte_size_ptr) {
      if (isdigit(s[0])) {
        char *format_char = nullptr;
        unsigned long byte_size = ::strtoul(s, &format_char, 0);
        if (byte_size != ULONG_MAX)
          *byte_size_ptr = byte_size;
        s = format_char;
      } else
        *byte_size_ptr = 0;
    }

    const bool partial_match_ok = true;
    if (!FormatManager::GetFormatFromCString(s, partial_match_ok, format)) {
      StreamString error_strm;
      error_strm.Printf(
          "Invalid format character or name '%s'. Valid values are:\n", s);
      for (Format f = eFormatDefault; f < kNumFormats; f = Format(f + 1)) {
        char format_char = FormatManager::GetFormatAsFormatChar(f);
        if (format_char)
          error_strm.Printf("'%c' or ", format_char);

        error_strm.Printf("\"%s\"", FormatManager::GetFormatAsCString(f));
        error_strm.EOL();
      }

      if (byte_size_ptr)
        error_strm.PutCString(
            "An optional byte size can precede the format character.\n");
      error.SetErrorString(error_strm.GetString());
    }

    if (error.Fail())
      return error;
  } else {
    error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid");
  }
  return error;
}

lldb::ScriptLanguage OptionArgParser::ToScriptLanguage(
    llvm::StringRef s, lldb::ScriptLanguage fail_value, bool *success_ptr) {
  if (success_ptr)
    *success_ptr = true;

  if (s.equals_lower("python"))
    return eScriptLanguagePython;
  if (s.equals_lower("default"))
    return eScriptLanguageDefault;
  if (s.equals_lower("none"))
    return eScriptLanguageNone;

  if (success_ptr)
    *success_ptr = false;
  return fail_value;
}

lldb::addr_t OptionArgParser::ToAddress(const ExecutionContext *exe_ctx,
                                        llvm::StringRef s,
                                        lldb::addr_t fail_value,
                                        Status *error_ptr) {
  bool error_set = false;
  if (s.empty()) {
    if (error_ptr)
      error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
                                          s.str().c_str());
    return fail_value;
  }

  llvm::StringRef sref = s;

  lldb::addr_t addr = LLDB_INVALID_ADDRESS;
  if (!s.getAsInteger(0, addr)) {
    if (error_ptr)
      error_ptr->Clear();
    return addr;
  }

  // Try base 16 with no prefix...
  if (!s.getAsInteger(16, addr)) {
    if (error_ptr)
      error_ptr->Clear();
    return addr;
  }

  Target *target = nullptr;
  if (!exe_ctx || !(target = exe_ctx->GetTargetPtr())) {
    if (error_ptr)
      error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
                                          s.str().c_str());
    return fail_value;
  }

  lldb::ValueObjectSP valobj_sp;
  EvaluateExpressionOptions options;
  options.SetCoerceToId(false);
  options.SetUnwindOnError(true);
  options.SetKeepInMemory(false);
  options.SetTryAllThreads(true);

  ExpressionResults expr_result =
      target->EvaluateExpression(s, exe_ctx->GetFramePtr(), valobj_sp, options);

  bool success = false;
  if (expr_result == eExpressionCompleted) {
    if (valobj_sp)
      valobj_sp = valobj_sp->GetQualifiedRepresentationIfAvailable(
          valobj_sp->GetDynamicValueType(), true);
    // Get the address to watch.
    if (valobj_sp)
      addr = valobj_sp->GetValueAsUnsigned(fail_value, &success);
    if (success) {
      if (error_ptr)
        error_ptr->Clear();
      return addr;
    } else {
      if (error_ptr) {
        error_set = true;
        error_ptr->SetErrorStringWithFormat(
            "address expression \"%s\" resulted in a value whose type "
            "can't be converted to an address: %s",
            s.str().c_str(), valobj_sp->GetTypeName().GetCString());
      }
    }

  } else {
    // Since the compiler can't handle things like "main + 12" we should try to
    // do this for now. The compiler doesn't like adding offsets to function
    // pointer types.
    static RegularExpression g_symbol_plus_offset_regex(
        "^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$");
    RegularExpression::Match regex_match(3);
    if (g_symbol_plus_offset_regex.Execute(sref, &regex_match)) {
      uint64_t offset = 0;
      bool add = true;
      std::string name;
      std::string str;
      if (regex_match.GetMatchAtIndex(s, 1, name)) {
        if (regex_match.GetMatchAtIndex(s, 2, str)) {
          add = str[0] == '+';

          if (regex_match.GetMatchAtIndex(s, 3, str)) {
            if (!llvm::StringRef(str).getAsInteger(0, offset)) {
              Status error;
              addr = ToAddress(exe_ctx, name.c_str(), LLDB_INVALID_ADDRESS,
                               &error);
              if (addr != LLDB_INVALID_ADDRESS) {
                if (add)
                  return addr + offset;
                else
                  return addr - offset;
              }
            }
          }
        }
      }
    }

    if (error_ptr) {
      error_set = true;
      error_ptr->SetErrorStringWithFormat(
          "address expression \"%s\" evaluation failed", s.str().c_str());
    }
  }

  if (error_ptr) {
    if (!error_set)
      error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
                                          s.str().c_str());
  }
  return fail_value;
}
