//===-- CommandObjectArgs.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/lldb-python.h"

#include "CommandObjectArgs.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Interpreter/Args.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Value.h"
#include "lldb/Expression/ClangExpression.h"
#include "lldb/Expression/ClangExpressionVariable.h"
#include "lldb/Expression/ClangFunction.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/StackFrame.h"

using namespace lldb;
using namespace lldb_private;

// This command is a toy.  I'm just using it to have a way to construct the arguments to
// calling functions.
//

CommandObjectArgs::CommandOptions::CommandOptions (CommandInterpreter &interpreter) :
    Options(interpreter)
{
    // Keep only one place to reset the values to their defaults
    OptionParsingStarting();
}


CommandObjectArgs::CommandOptions::~CommandOptions ()
{
}

Error
CommandObjectArgs::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg)
{
    Error error;
    
    const int short_option = m_getopt_table[option_idx].val;
    error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
    
    return error;
}

void
CommandObjectArgs::CommandOptions::OptionParsingStarting ()
{
}

const OptionDefinition*
CommandObjectArgs::CommandOptions::GetDefinitions ()
{
    return g_option_table;
}

CommandObjectArgs::CommandObjectArgs (CommandInterpreter &interpreter) :
    CommandObjectParsed (interpreter,
                         "args",
                         "When stopped at the start of a function, reads function arguments of type (u?)int(8|16|32|64)_t, (void|char)*",
                         "args"),
    m_options (interpreter)
{
}

CommandObjectArgs::~CommandObjectArgs ()
{
}

Options *
CommandObjectArgs::GetOptions ()
{
    return &m_options;
}

bool
CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result)
{
    ConstString target_triple;
    
    
    Process *process = m_exe_ctx.GetProcessPtr();
    if (!process)
    {
        result.AppendError ("Args found no process.");
        result.SetStatus (eReturnStatusFailed);
        return false;
    }
    
    const ABI *abi = process->GetABI().get();
    if (!abi)
    {
        result.AppendError ("The current process has no ABI.");
        result.SetStatus (eReturnStatusFailed);
        return false;
    }
    
    const size_t num_args = args.GetArgumentCount ();
    size_t arg_index;
    
    if (!num_args)
    {
        result.AppendError ("args requires at least one argument");
        result.SetStatus (eReturnStatusFailed);
        return false;
    }
    
    Thread *thread = m_exe_ctx.GetThreadPtr();
    
    if (!thread)
    {
        result.AppendError ("args found no thread.");
        result.SetStatus (eReturnStatusFailed);
        return false;
    }
        
    lldb::StackFrameSP thread_cur_frame = thread->GetSelectedFrame ();
    if (!thread_cur_frame)
    {
        result.AppendError ("The current thread has no current frame.");
        result.SetStatus (eReturnStatusFailed);
        return false;
    }
    
    ModuleSP thread_module_sp (thread_cur_frame->GetFrameCodeAddress ().GetModule());
    if (!thread_module_sp)
    {
        result.AppendError ("The PC has no associated module.");
        result.SetStatus (eReturnStatusFailed);
        return false;
    }
    
    ClangASTContext &ast_context = thread_module_sp->GetClangASTContext();
    
    ValueList value_list;
    
    for (arg_index = 0; arg_index < num_args; ++arg_index)
    {
        const char *arg_type_cstr = args.GetArgumentAtIndex(arg_index);
        Value value;
        value.SetValueType(Value::eValueTypeScalar);
        ClangASTType clang_type;
        
        char *int_pos;
        if ((int_pos = strstr (const_cast<char*>(arg_type_cstr), "int")))
        {
            Encoding encoding = eEncodingSint;
            
            int width = 0;
            
            if (int_pos > arg_type_cstr + 1)
            {
                result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
                result.SetStatus (eReturnStatusFailed);
                return false;
            }
            if (int_pos == arg_type_cstr + 1 && arg_type_cstr[0] != 'u')
            {
                result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
                result.SetStatus (eReturnStatusFailed);
                return false;
            }
            if (arg_type_cstr[0] == 'u')
            {
                encoding = eEncodingUint;
            }
            
            char *width_pos = int_pos + 3;
            
            if (!strcmp (width_pos, "8_t"))
                width = 8;
            else if (!strcmp (width_pos, "16_t"))
                width = 16;
            else if (!strcmp (width_pos, "32_t"))
                width = 32;
            else if (!strcmp (width_pos, "64_t"))
                width = 64;
            else
            {
                result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
                result.SetStatus (eReturnStatusFailed);
                return false;
            }
            
            clang_type = ast_context.GetBuiltinTypeForEncodingAndBitSize(encoding, width);
            
            if (!clang_type.IsValid())
            {
                result.AppendErrorWithFormat ("Couldn't get Clang type for format %s (%s integer, width %d).\n",
                                             arg_type_cstr,
                                             (encoding == eEncodingSint ? "signed" : "unsigned"),
                                             width);
                
                result.SetStatus (eReturnStatusFailed);
                return false;
            }
        }
        else if (strchr (arg_type_cstr, '*'))
        {
            if (!strcmp (arg_type_cstr, "void*"))
                clang_type = ast_context.GetBasicType(eBasicTypeVoid).GetPointerType();
            else if (!strcmp (arg_type_cstr, "char*"))
                clang_type = ast_context.GetCStringType (false);
            else
            {
                result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
                result.SetStatus (eReturnStatusFailed);
                return false;
            }
        }
        else 
        {
            result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
            result.SetStatus (eReturnStatusFailed);
            return false;
        }
                     
        value.SetClangType (clang_type);
        value_list.PushValue(value);
    }
    
    if (!abi->GetArgumentValues (*thread, value_list))
    {
        result.AppendError ("Couldn't get argument values");
        result.SetStatus (eReturnStatusFailed);
        return false;
    }
    
    result.GetOutputStream ().Printf("Arguments : \n");

    for (arg_index = 0; arg_index < num_args; ++arg_index)
    {
        result.GetOutputStream ().Printf ("%" PRIu64 " (%s): ", (uint64_t)arg_index, args.GetArgumentAtIndex (arg_index));
        value_list.GetValueAtIndex (arg_index)->Dump (&result.GetOutputStream ());
        result.GetOutputStream ().Printf("\n");
    }
    
    return result.Succeeded();
}

OptionDefinition
CommandObjectArgs::CommandOptions::g_option_table[] =
{
    { LLDB_OPT_SET_1, false, "debug", 'g', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Enable verbose debug logging of the expression parsing and evaluation."},
    { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};

