<commit_before>//===-- CommandObjectPlatform.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 "CommandObjectPlatform.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandOptionValidators.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionGroupFile.h"
#include "lldb/Interpreter/OptionGroupPlatform.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/Utils.h"

using namespace lldb;
using namespace lldb_private;

static mode_t
ParsePermissionString(const char* permissions)
{
    if (strlen(permissions) != 9)
        return (mode_t)(-1);
    bool user_r,user_w,user_x,
    group_r,group_w,group_x,
    world_r,world_w,world_x;
    
    user_r = (permissions[0] == 'r');
    user_w = (permissions[1] == 'w');
    user_x = (permissions[2] == 'x');
    
    group_r = (permissions[3] == 'r');
    group_w = (permissions[4] == 'w');
    group_x = (permissions[5] == 'x');
    
    world_r = (permissions[6] == 'r');
    world_w = (permissions[7] == 'w');
    world_x = (permissions[8] == 'x');
    
    mode_t user,group,world;
    user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0);
    group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0);
    world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0);
    
    return user | group | world;
}

static OptionDefinition
g_permissions_options[] =
{
    {   LLDB_OPT_SET_ALL, false, "permissions-value",   'v', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePermissionsNumber         , "Give out the numeric value for permissions (e.g. 757)" },
    {   LLDB_OPT_SET_ALL, false, "permissions-string",  's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePermissionsString  , "Give out the string value for permissions (e.g. rwxr-xr--)." },
    {   LLDB_OPT_SET_ALL, false, "user-read",           'r', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow user to read." },
    {   LLDB_OPT_SET_ALL, false, "user-write",          'w', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow user to write." },
    {   LLDB_OPT_SET_ALL, false, "user-exec",           'x', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow user to execute." },

    {   LLDB_OPT_SET_ALL, false, "group-read",          'R', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow group to read." },
    {   LLDB_OPT_SET_ALL, false, "group-write",         'W', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow group to write." },
    {   LLDB_OPT_SET_ALL, false, "group-exec",          'X', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow group to execute." },

    {   LLDB_OPT_SET_ALL, false, "world-read",          'd', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow world to read." },
    {   LLDB_OPT_SET_ALL, false, "world-write",         't', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow world to write." },
    {   LLDB_OPT_SET_ALL, false, "world-exec",          'e', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow world to execute." },
};

class OptionPermissions : public lldb_private::OptionGroup
{
public:
    OptionPermissions ()
    {
    }
    
    virtual
    ~OptionPermissions ()
    {
    }
    
    virtual lldb_private::Error
    SetOptionValue (CommandInterpreter &interpreter,
                    uint32_t option_idx,
                    const char *option_arg)
    {
        Error error;
        char short_option = (char) GetDefinitions()[option_idx].short_option;
        switch (short_option)
        {
            case 'v':
            {
                bool ok;
                uint32_t perms = StringConvert::ToUInt32(option_arg, 777, 8, &ok);
                if (!ok)
                    error.SetErrorStringWithFormat("invalid value for permissions: %s", option_arg);
                else
                    m_permissions = perms;
            }
                break;
            case 's':
            {
                mode_t perms = ParsePermissionString(option_arg);
                if (perms == (mode_t)-1)
                    error.SetErrorStringWithFormat("invalid value for permissions: %s", option_arg);
                else
                    m_permissions = perms;
            }
            case 'r':
                m_permissions |= lldb::eFilePermissionsUserRead;
                break;
            case 'w':
                m_permissions |= lldb::eFilePermissionsUserWrite;
                break;
            case 'x':
                m_permissions |= lldb::eFilePermissionsUserExecute;
                break;
            case 'R':
                m_permissions |= lldb::eFilePermissionsGroupRead;
                break;
            case 'W':
                m_permissions |= lldb::eFilePermissionsGroupWrite;
                break;
            case 'X':
                m_permissions |= lldb::eFilePermissionsGroupExecute;
                break;
            case 'd':
                m_permissions |= lldb::eFilePermissionsWorldRead;
                break;
            case 't':
                m_permissions |= lldb::eFilePermissionsWorldWrite;
                break;
            case 'e':
                m_permissions |= lldb::eFilePermissionsWorldExecute;
                break;

            default:
                error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
                break;
        }
        
        return error;
    }
    
    void
    OptionParsingStarting (CommandInterpreter &interpreter)
    {
        m_permissions = 0;
    }
    
    virtual uint32_t
    GetNumDefinitions ()
    {
        return llvm::array_lengthof(g_permissions_options);
    }
    
    const lldb_private::OptionDefinition*
    GetDefinitions ()
    {
        return g_permissions_options;
    }
        
    // Instance variables to hold the values for command options.
    
    uint32_t m_permissions;
private:
    DISALLOW_COPY_AND_ASSIGN(OptionPermissions);
};

//----------------------------------------------------------------------
// "platform select <platform-name>"
//----------------------------------------------------------------------
class CommandObjectPlatformSelect : public CommandObjectParsed
{
public:
    CommandObjectPlatformSelect (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter, 
                             "platform select",
                             "Create a platform if needed and select it as the current platform.",
                             "platform select <platform-name>",
                             0),
        m_option_group (interpreter),
        m_platform_options (false) // Don't include the "--platform" option by passing false
    {
        m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, 1);
        m_option_group.Finalize();
    }

    virtual
    ~CommandObjectPlatformSelect ()
    {
    }

    virtual int
    HandleCompletion (Args &input,
                      int &cursor_index,
                      int &cursor_char_position,
                      int match_start_point,
                      int max_return_elements,
                      bool &word_complete,
                      StringList &matches)
    {
        std::string completion_str (input.GetArgumentAtIndex(cursor_index));
        completion_str.erase (cursor_char_position);
        
        CommandCompletions::PlatformPluginNames (m_interpreter, 
                                                 completion_str.c_str(),
                                                 match_start_point,
                                                 max_return_elements,
                                                 NULL,
                                                 word_complete,
                                                 matches);
        return matches.GetSize();
    }

    virtual Options *
    GetOptions ()
    {
        return &m_option_group;
    }

protected:
    virtual bool
    DoExecute (Args& args, CommandReturnObject &result)
    {
        if (args.GetArgumentCount() == 1)
        {
            const char *platform_name = args.GetArgumentAtIndex (0);
            if (platform_name && platform_name[0])
            {
                const bool select = true;
                m_platform_options.SetPlatformName (platform_name);
                Error error;
                ArchSpec platform_arch;
                PlatformSP platform_sp (m_platform_options.CreatePlatformWithOptions (m_interpreter, ArchSpec(), select, error, platform_arch));
                if (platform_sp)
                {
                    m_interpreter.GetDebugger().GetPlatformList().SetSelectedPlatform(platform_sp);

                    platform_sp->GetStatus (result.GetOutputStream());
                    result.SetStatus (eReturnStatusSuccessFinishResult);
                }
                else
                {
                    result.AppendError(error.AsCString());
                    result.SetStatus (eReturnStatusFailed);
                }
            }
            else
            {
                result.AppendError ("invalid platform name");
                result.SetStatus (eReturnStatusFailed);
            }
        }
        else
        {
            result.AppendError ("platform create takes a platform name as an argument\n");
            result.SetStatus (eReturnStatusFailed);
        }
        return result.Succeeded();
    }

    OptionGroupOptions m_option_group;
    OptionGroupPlatform m_platform_options;
};

//----------------------------------------------------------------------
// "platform list"
//----------------------------------------------------------------------
class CommandObjectPlatformList : public CommandObjectParsed
{
public:
    CommandObjectPlatformList (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "platform list",
                             "List all platforms that are available.",
                             NULL,
                             0)
    {
    }

    virtual
    ~CommandObjectPlatformList ()
    {
    }

protected:
    virtual bool
    DoExecute (Args& args, CommandReturnObject &result)
    {
        Stream &ostrm = result.GetOutputStream();
        ostrm.Printf("Available platforms:\n");
        
        PlatformSP host_platform_sp (Platform::GetHostPlatform());
        ostrm.Printf ("%s: %s\n", 
                      host_platform_sp->GetPluginName().GetCString(),
                      host_platform_sp->GetDescription());

        uint32_t idx;
        for (idx = 0; 1; ++idx)
        {
            const char *plugin_name = PluginManager::GetPlatformPluginNameAtIndex (idx);
            if (plugin_name == NULL)
                break;
            const char *plugin_desc = PluginManager::GetPlatformPluginDescriptionAtIndex (idx);
            if (plugin_desc == NULL)
                break;
            ostrm.Printf("%s: %s\n", plugin_name, plugin_desc);
        }
        
        if (idx == 0)
        {
            result.AppendError ("no platforms are available\n");
            result.SetStatus (eReturnStatusFailed);
        }
        else
            result.SetStatus (eReturnStatusSuccessFinishResult);
        return result.Succeeded();
    }
};

//----------------------------------------------------------------------
// "platform status"
//----------------------------------------------------------------------
class CommandObjectPlatformStatus : public CommandObjectParsed
{
public:
    CommandObjectPlatformStatus (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "platform status",
                             "Display status for the currently selected platform.",
                             NULL,
                             0)
    {
    }

    virtual
    ~CommandObjectPlatformStatus ()
    {
    }

protected:
    virtual bool
    DoExecute (Args& args, CommandReturnObject &result)
    {
        Stream &ostrm = result.GetOutputStream();      
        
        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
        PlatformSP platform_sp;
        if (target)
        {
            platform_sp = target->GetPlatform();
        }
        if (!platform_sp)
        {
            platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
        }
        if (platform_sp)
        {
            platform_sp->GetStatus (ostrm);
            result.SetStatus (eReturnStatusSuccessFinishResult);            
        }
        else
        {
            result.AppendError ("no platform us currently selected\n");
            result.SetStatus (eReturnStatusFailed);            
        }
        return result.Succeeded();
    }
};

//----------------------------------------------------------------------
// "platform connect <connect-url>"
//----------------------------------------------------------------------
class CommandObjectPlatformConnect : public CommandObjectParsed
{
public:
    CommandObjectPlatformConnect (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter, 
                             "platform connect",
                             "Connect a platform by name to be the currently selected platform.",
                             "platform connect <connect-url>",
                             0)
    {
    }

    virtual
    ~CommandObjectPlatformConnect ()
    {
    }

protected:
    virtual bool
    DoExecute (Args& args, CommandReturnObject &result)
    {
        Stream &ostrm = result.GetOutputStream();      
        
        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
        if (platform_sp)
        {
            Error error (platform_sp->ConnectRemote (args));
            if (error.Success())
            {
                platform_sp->GetStatus (ostrm);
                result.SetStatus (eReturnStatusSuccessFinishResult);            
            }
            else
            {
                result.AppendErrorWithFormat ("%s\n", error.AsCString());
                result.SetStatus (eReturnStatusFailed);            
            }
        }
        else
        {
            result.AppendError ("no platform is currently selected\n");
            result.SetStatus (eReturnStatusFailed);            
        }
        return result.Succeeded();
    }
    
    virtual Options *
    GetOptions ()
    {
        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
        OptionGroupOptions* m_platform_options = NULL;
        if (platform_sp)
        {
            m_platform_options = platform_sp->GetConnectionOptions(m_interpreter);
            if (m_platform_options != NULL && !m_platform_options->m_did_finalize)
                m_platform_options->Finalize();
        }
        return m_platform_options;
    }

};

//----------------------------------------------------------------------
// "platform disconnect"
//----------------------------------------------------------------------
class CommandObjectPlatformDisconnect : public CommandObjectParsed
{
public:
    CommandObjectPlatformDisconnect (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter, 
                             "platform disconnect",
                             "Disconnect a platform by name to be the currently selected platform.",
                             "platform disconnect",
                             0)
    {
    }

    virtual
    ~CommandObjectPlatformDisconnect ()
    {
    }

protected:
    virtual bool
    DoExecute (Args& args, CommandReturnObject &result)
    {
        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
        if (platform_sp)
        {
            if (args.GetArgumentCount() == 0)
            {
                Error error;
                
                if (platform_sp->IsConnected())
                {
                    // Cache the instance name if there is one since we are 
                    // about to disconnect and the name might go with it.
                    const char *hostname_cstr = platform_sp->GetHostname();
                    std::string hostname;
                    if (hostname_cstr)
                        hostname.assign (hostname_cstr);

                    error = platform_sp->DisconnectRemote ();
                    if (error.Success())
                    {
                        Stream &ostrm = result.GetOutputStream();      
                        if (hostname.empty())
                            ostrm.Printf ("Disconnected from \"%s\"\n", platform_sp->GetPluginName().GetCString());
                        else
                            ostrm.Printf ("Disconnected from \"%s\"\n", hostname.c_str());
                        result.SetStatus (eReturnStatusSuccessFinishResult);            
                    }
                    else
                    {
                        result.AppendErrorWithFormat ("%s", error.AsCString());
                        result.SetStatus (eReturnStatusFailed);            
                    }
                }
                else
                {
                    // Not connected...
                    result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetPluginName().GetCString());
                    result.SetStatus (eReturnStatusFailed);            
                }
            }
            else
            {
                // Bad args
                result.AppendError ("\"platform disconnect\" doesn't take any arguments");
                result.SetStatus (eReturnStatusFailed);            
            }
        }
        else
        {
            result.AppendError ("no platform is currently selected");
            result.SetStatus (eReturnStatusFailed);            
        }
        return result.Succeeded();
    }
};

//----------------------------------------------------------------------
// "platform settings"
//----------------------------------------------------------------------
class CommandObjectPlatformSettings : public CommandObjectParsed
{
public:
    CommandObjectPlatformSettings (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "platform settings",
                             "Set settings for the current target's platform, or for a platform by name.",
                             "platform settings",
                             0),
        m_options (interpreter),
        m_option_working_dir (LLDB_OPT_SET_1, false, "working-dir", 'w', 0, eArgTypePath, "The working directory for the platform.")
    {
        m_options.Append (&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    }
    
    virtual
    ~CommandObjectPlatformSettings ()
    {
    }
    
protected:
    virtual bool
    DoExecute (Args& args, CommandReturnObject &result)
    {
        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
        if (platform_sp)
        {
            if (m_option_working_dir.GetOptionValue().OptionWasSet())
                platform_sp->SetWorkingDirectory (ConstString(m_option_working_dir.GetOptionValue().GetCurrentValue().GetPath().c_str()));
        }
        else
        {
            result.AppendError ("no platform is currently selected");
            result.SetStatus (eReturnStatusFailed);
        }
        return result.Succeeded();
    }
    
    virtual Options *
    GetOptions ()
    {
        if (m_options.DidFinalize() == false)
        {
            m_options.Append(new OptionPermissions());
            m_options.Finalize();
        }
        return &m_options;
    }
protected:
    
    OptionGroupOptions m_options;
    OptionGroupFile m_option_working_dir;

};


//----------------------------------------------------------------------
// "platform mkdir"
//----------------------------------------------------------------------
class CommandObjectPlatformMkDir : public CommandObjectParsed
{
public:
    CommandObjectPlatformMkDir (CommandInterpreter &interpreter) :
    CommandObjectParsed (interpreter,
                         "platform mkdir",
                         "Make a new directory on the remote end.",
                         NULL,
                         0),
    m_options(interpreter)
    {
    }
    
    virtual
    ~CommandObjectPlatformMkDir ()
    {
    }
    
    virtual bool
    DoExecute (Args& args, CommandReturnObject &result)
    {
        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
        if (platform_sp)
        {
            std::string cmd_line;
            args.GetCommandString(cmd_line);
            uint32_t mode;
            const OptionPermissions* options_permissions = (OptionPermissions*)m_options.GetGroupWithOption('r');
            if (options_permissions)
                mode = options_permissions->m_permissions;
            else
                mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX | lldb::eFilePermissionsWorldRX;
            Error error = platform_sp->MakeDirectory(cmd_line.c_str(), mode);
            if (error.Success())
            {
                result.SetStatus (eReturnStatusSuccessFinishResult);
            }
            else
            {
                result.AppendError(error.AsCString());
                result.SetStatus (eReturnStatusFailed);
            }
        }
        else
        {
            result.AppendError ("no platform currently selected\n");
            result.SetStatus (eReturnStatusFailed);
        }
        return result.Succeeded();
    }
    
    virtual Options *
    GetOptions ()
    {
        if (m_options.DidFinalize() == false)
        {
            m_options.Append(new OptionPermissions());
            m_options.Finalize();
        }
        return &m_options;
    }
    OptionGroupOptions m_options;
    
};

//----------------------------------------------------------------------
// "platform fopen"
//----------------------------------------------------------------------
class CommandObjectPlatformFOpen : public CommandObjectParsed
{
public:
    CommandObjectPlatformFOpen (CommandInterpreter &interpreter) :
    CommandObjectParsed (interpreter,
                         "platform file open",
                         "Open a file on the remote end.",
                         NULL,
                         0),
    m_options(interpreter)
    {
    }
    
    virtual
    ~CommandObjectPlatformFOpen ()
    {
    }
    
    virtual bool
    DoExecute (Args& args, CommandReturnObject &result)
    {
        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
        if (platform_sp)
        {
            Error error;
            std::string cmd_line;
            args.GetCommandString(cmd_line);
            mode_t perms;
            const OptionPermissions* options_permissions = (OptionPermissions*)m_options.GetGroupWithOption('r');
            if (options_permissions)
                perms = options_permissions->m_permissions;
            else
                perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW | lldb::eFilePermissionsWorldRead;
            lldb::user_id_t fd = platform_sp->OpenFile(FileSpec(cmd_line.c_str(),false),
                                                       File::eOpenOptionRead | File::eOpenOptionWrite |
                                                       File::eOpenOptionAppend | File::eOpenOptionCanCreate,
                                                       perms,
                                                       error);<commit_msg>Cast to (const OptionPermissions*) to avoid warning.<commit_after>//===-- CommandObjectPlatform.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 "CommandObjectPlatform.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandOptionValidators.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionGroupFile.h"
#include "lldb/Interpreter/OptionGroupPlatform.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/Utils.h"

using namespace lldb;
using namespace lldb_private;

static mode_t
ParsePermissionString(const char* permissions)
{
    if (strlen(permissions) != 9)
        return (mode_t)(-1);
    bool user_r,user_w,user_x,
    group_r,group_w,group_x,
    world_r,world_w,world_x;
    
    user_r = (permissions[0] == 'r');
    user_w = (permissions[1] == 'w');
    user_x = (permissions[2] == 'x');
    
    group_r = (permissions[3] == 'r');
    group_w = (permissions[4] == 'w');
    group_x = (permissions[5] == 'x');
    
    world_r = (permissions[6] == 'r');
    world_w = (permissions[7] == 'w');
    world_x = (permissions[8] == 'x');
    
    mode_t user,group,world;
    user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0);
    group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0);
    world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0);
    
    return user | group | world;
}

static OptionDefinition
g_permissions_options[] =
{
    {   LLDB_OPT_SET_ALL, false, "permissions-value",   'v', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePermissionsNumber         , "Give out the numeric value for permissions (e.g. 757)" },
    {   LLDB_OPT_SET_ALL, false, "permissions-string",  's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePermissionsString  , "Give out the string value for permissions (e.g. rwxr-xr--)." },
    {   LLDB_OPT_SET_ALL, false, "user-read",           'r', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow user to read." },
    {   LLDB_OPT_SET_ALL, false, "user-write",          'w', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow user to write." },
    {   LLDB_OPT_SET_ALL, false, "user-exec",           'x', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow user to execute." },

    {   LLDB_OPT_SET_ALL, false, "group-read",          'R', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow group to read." },
    {   LLDB_OPT_SET_ALL, false, "group-write",         'W', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow group to write." },
    {   LLDB_OPT_SET_ALL, false, "group-exec",          'X', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow group to execute." },

    {   LLDB_OPT_SET_ALL, false, "world-read",          'd', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow world to read." },
    {   LLDB_OPT_SET_ALL, false, "world-write",         't', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow world to write." },
    {   LLDB_OPT_SET_ALL, false, "world-exec",          'e', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow world to execute." },
};

class OptionPermissions : public lldb_private::OptionGroup
{
public:
    OptionPermissions ()
    {
    }
    
    virtual
    ~OptionPermissions ()
    {
    }
    
    virtual lldb_private::Error
    SetOptionValue (CommandInterpreter &interpreter,
                    uint32_t option_idx,
                    const char *option_arg)
    {
        Error error;
        char short_option = (char) GetDefinitions()[option_idx].short_option;
        switch (short_option)
        {
            case 'v':
            {
                bool ok;
                uint32_t perms = StringConvert::ToUInt32(option_arg, 777, 8, &ok);
                if (!ok)
                    error.SetErrorStringWithFormat("invalid value for permissions: %s", option_arg);
                else
                    m_permissions = perms;
            }
                break;
            case 's':
            {
                mode_t perms = ParsePermissionString(option_arg);
                if (perms == (mode_t)-1)
                    error.SetErrorStringWithFormat("invalid value for permissions: %s", option_arg);
                else
                    m_permissions = perms;
            }
            case 'r':
                m_permissions |= lldb::eFilePermissionsUserRead;
                break;
            case 'w':
                m_permissions |= lldb::eFilePermissionsUserWrite;
                break;
            case 'x':
                m_permissions |= lldb::eFilePermissionsUserExecute;
                break;
            case 'R':
                m_permissions |= lldb::eFilePermissionsGroupRead;
                break;
            case 'W':
                m_permissions |= lldb::eFilePermissionsGroupWrite;
                break;
            case 'X':
                m_permissions |= lldb::eFilePermissionsGroupExecute;
                break;
            case 'd':
                m_permissions |= lldb::eFilePermissionsWorldRead;
                break;
            case 't':
                m_permissions |= lldb::eFilePermissionsWorldWrite;
                break;
            case 'e':
                m_permissions |= lldb::eFilePermissionsWorldExecute;
                break;

            default:
                error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
                break;
        }
        
        return error;
    }
    
    void
    OptionParsingStarting (CommandInterpreter &interpreter)
    {
        m_permissions = 0;
    }
    
    virtual uint32_t
    GetNumDefinitions ()
    {
        return llvm::array_lengthof(g_permissions_options);
    }
    
    const lldb_private::OptionDefinition*
    GetDefinitions ()
    {
        return g_permissions_options;
    }
        
    // Instance variables to hold the values for command options.
    
    uint32_t m_permissions;
private:
    DISALLOW_COPY_AND_ASSIGN(OptionPermissions);
};

//----------------------------------------------------------------------
// "platform select <platform-name>"
//----------------------------------------------------------------------
class CommandObjectPlatformSelect : public CommandObjectParsed
{
public:
    CommandObjectPlatformSelect (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter, 
                             "platform select",
                             "Create a platform if needed and select it as the current platform.",
                             "platform select <platform-name>",
                             0),
        m_option_group (interpreter),
        m_platform_options (false) // Don't include the "--platform" option by passing false
    {
        m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, 1);
        m_option_group.Finalize();
    }

    virtual
    ~CommandObjectPlatformSelect ()
    {
    }

    virtual int
    HandleCompletion (Args &input,
                      int &cursor_index,
                      int &cursor_char_position,
                      int match_start_point,
                      int max_return_elements,
                      bool &word_complete,
                      StringList &matches)
    {
        std::string completion_str (input.GetArgumentAtIndex(cursor_index));
        completion_str.erase (cursor_char_position);
        
        CommandCompletions::PlatformPluginNames (m_interpreter, 
                                                 completion_str.c_str(),
                                                 match_start_point,
                                                 max_return_elements,
                                                 NULL,
                                                 word_complete,
                                                 matches);
        return matches.GetSize();
    }

    virtual Options *
    GetOptions ()
    {
        return &m_option_group;
    }

protected:
    virtual bool
    DoExecute (Args& args, CommandReturnObject &result)
    {
        if (args.GetArgumentCount() == 1)
        {
            const char *platform_name = args.GetArgumentAtIndex (0);
            if (platform_name && platform_name[0])
            {
                const bool select = true;
                m_platform_options.SetPlatformName (platform_name);
                Error error;
                ArchSpec platform_arch;
                PlatformSP platform_sp (m_platform_options.CreatePlatformWithOptions (m_interpreter, ArchSpec(), select, error, platform_arch));
                if (platform_sp)
                {
                    m_interpreter.GetDebugger().GetPlatformList().SetSelectedPlatform(platform_sp);

                    platform_sp->GetStatus (result.GetOutputStream());
                    result.SetStatus (eReturnStatusSuccessFinishResult);
                }
                else
                {
                    result.AppendError(error.AsCString());
                    result.SetStatus (eReturnStatusFailed);
                }
            }
            else
            {
                result.AppendError ("invalid platform name");
                result.SetStatus (eReturnStatusFailed);
            }
        }
        else
        {
            result.AppendError ("platform create takes a platform name as an argument\n");
            result.SetStatus (eReturnStatusFailed);
        }
        return result.Succeeded();
    }

    OptionGroupOptions m_option_group;
    OptionGroupPlatform m_platform_options;
};

//----------------------------------------------------------------------
// "platform list"
//----------------------------------------------------------------------
class CommandObjectPlatformList : public CommandObjectParsed
{
public:
    CommandObjectPlatformList (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "platform list",
                             "List all platforms that are available.",
                             NULL,
                             0)
    {
    }

    virtual
    ~CommandObjectPlatformList ()
    {
    }

protected:
    virtual bool
    DoExecute (Args& args, CommandReturnObject &result)
    {
        Stream &ostrm = result.GetOutputStream();
        ostrm.Printf("Available platforms:\n");
        
        PlatformSP host_platform_sp (Platform::GetHostPlatform());
        ostrm.Printf ("%s: %s\n", 
                      host_platform_sp->GetPluginName().GetCString(),
                      host_platform_sp->GetDescription());

        uint32_t idx;
        for (idx = 0; 1; ++idx)
        {
            const char *plugin_name = PluginManager::GetPlatformPluginNameAtIndex (idx);
            if (plugin_name == NULL)
                break;
            const char *plugin_desc = PluginManager::GetPlatformPluginDescriptionAtIndex (idx);
            if (plugin_desc == NULL)
                break;
            ostrm.Printf("%s: %s\n", plugin_name, plugin_desc);
        }
        
        if (idx == 0)
        {
            result.AppendError ("no platforms are available\n");
            result.SetStatus (eReturnStatusFailed);
        }
        else
            result.SetStatus (eReturnStatusSuccessFinishResult);
        return result.Succeeded();
    }
};

//----------------------------------------------------------------------
// "platform status"
//----------------------------------------------------------------------
class CommandObjectPlatformStatus : public CommandObjectParsed
{
public:
    CommandObjectPlatformStatus (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "platform status",
                             "Display status for the currently selected platform.",
                             NULL,
                             0)
    {
    }

    virtual
    ~CommandObjectPlatformStatus ()
    {
    }

protected:
    virtual bool
    DoExecute (Args& args, CommandReturnObject &result)
    {
        Stream &ostrm = result.GetOutputStream();      
        
        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
        PlatformSP platform_sp;
        if (target)
        {
            platform_sp = target->GetPlatform();
        }
        if (!platform_sp)
        {
            platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
        }
        if (platform_sp)
        {
            platform_sp->GetStatus (ostrm);
            result.SetStatus (eReturnStatusSuccessFinishResult);            
        }
        else
        {
            result.AppendError ("no platform us currently selected\n");
            result.SetStatus (eReturnStatusFailed);            
        }
        return result.Succeeded();
    }
};

//----------------------------------------------------------------------
// "platform connect <connect-url>"
//----------------------------------------------------------------------
class CommandObjectPlatformConnect : public CommandObjectParsed
{
public:
    CommandObjectPlatformConnect (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter, 
                             "platform connect",
                             "Connect a platform by name to be the currently selected platform.",
                             "platform connect <connect-url>",
                             0)
    {
    }

    virtual
    ~CommandObjectPlatformConnect ()
    {
    }

protected:
    virtual bool
    DoExecute (Args& args, CommandReturnObject &result)
    {
        Stream &ostrm = result.GetOutputStream();      
        
        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
        if (platform_sp)
        {
            Error error (platform_sp->ConnectRemote (args));
            if (error.Success())
            {
                platform_sp->GetStatus (ostrm);
                result.SetStatus (eReturnStatusSuccessFinishResult);            
            }
            else
            {
                result.AppendErrorWithFormat ("%s\n", error.AsCString());
                result.SetStatus (eReturnStatusFailed);            
            }
        }
        else
        {
            result.AppendError ("no platform is currently selected\n");
            result.SetStatus (eReturnStatusFailed);            
        }
        return result.Succeeded();
    }
    
    virtual Options *
    GetOptions ()
    {
        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
        OptionGroupOptions* m_platform_options = NULL;
        if (platform_sp)
        {
            m_platform_options = platform_sp->GetConnectionOptions(m_interpreter);
            if (m_platform_options != NULL && !m_platform_options->m_did_finalize)
                m_platform_options->Finalize();
        }
        return m_platform_options;
    }

};

//----------------------------------------------------------------------
// "platform disconnect"
//----------------------------------------------------------------------
class CommandObjectPlatformDisconnect : public CommandObjectParsed
{
public:
    CommandObjectPlatformDisconnect (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter, 
                             "platform disconnect",
                             "Disconnect a platform by name to be the currently selected platform.",
                             "platform disconnect",
                             0)
    {
    }

    virtual
    ~CommandObjectPlatformDisconnect ()
    {
    }

protected:
    virtual bool
    DoExecute (Args& args, CommandReturnObject &result)
    {
        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
        if (platform_sp)
        {
            if (args.GetArgumentCount() == 0)
            {
                Error error;
                
                if (platform_sp->IsConnected())
                {
                    // Cache the instance name if there is one since we are 
                    // about to disconnect and the name might go with it.
                    const char *hostname_cstr = platform_sp->GetHostname();
                    std::string hostname;
                    if (hostname_cstr)
                        hostname.assign (hostname_cstr);

                    error = platform_sp->DisconnectRemote ();
                    if (error.Success())
                    {
                        Stream &ostrm = result.GetOutputStream();      
                        if (hostname.empty())
                            ostrm.Printf ("Disconnected from \"%s\"\n", platform_sp->GetPluginName().GetCString());
                        else
                            ostrm.Printf ("Disconnected from \"%s\"\n", hostname.c_str());
                        result.SetStatus (eReturnStatusSuccessFinishResult);            
                    }
                    else
                    {
                        result.AppendErrorWithFormat ("%s", error.AsCString());
                        result.SetStatus (eReturnStatusFailed);            
                    }
                }
                else
                {
                    // Not connected...
                    result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetPluginName().GetCString());
                    result.SetStatus (eReturnStatusFailed);            
                }
            }
            else
            {
                // Bad args
                result.AppendError ("\"platform disconnect\" doesn't take any arguments");
                result.SetStatus (eReturnStatusFailed);            
            }
        }
        else
        {
            result.AppendError ("no platform is currently selected");
            result.SetStatus (eReturnStatusFailed);            
        }
        return result.Succeeded();
    }
};

//----------------------------------------------------------------------
// "platform settings"
//----------------------------------------------------------------------
class CommandObjectPlatformSettings : public CommandObjectParsed
{
public:
    CommandObjectPlatformSettings (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "platform settings",
                             "Set settings for the current target's platform, or for a platform by name.",
                             "platform settings",
                             0),
        m_options (interpreter),
        m_option_working_dir (LLDB_OPT_SET_1, false, "working-dir", 'w', 0, eArgTypePath, "The working directory for the platform.")
    {
        m_options.Append (&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    }
    
    virtual
    ~CommandObjectPlatformSettings ()
    {
    }
    
protected:
    virtual bool
    DoExecute (Args& args, CommandReturnObject &result)
    {
        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
        if (platform_sp)
        {
            if (m_option_working_dir.GetOptionValue().OptionWasSet())
                platform_sp->SetWorkingDirectory (ConstString(m_option_working_dir.GetOptionValue().GetCurrentValue().GetPath().c_str()));
        }
        else
        {
            result.AppendError ("no platform is currently selected");
            result.SetStatus (eReturnStatusFailed);
        }
        return result.Succeeded();
    }
    
    virtual Options *
    GetOptions ()
    {
        if (m_options.DidFinalize() == false)
        {
            m_options.Append(new OptionPermissions());
            m_options.Finalize();
        }
        return &m_options;
    }
protected:
    
    OptionGroupOptions m_options;
    OptionGroupFile m_option_working_dir;

};


//----------------------------------------------------------------------
// "platform mkdir"
//----------------------------------------------------------------------
class CommandObjectPlatformMkDir : public CommandObjectParsed
{
public:
    CommandObjectPlatformMkDir (CommandInterpreter &interpreter) :
    CommandObjectParsed (interpreter,
                         "platform mkdir",
                         "Make a new directory on the remote end.",
                         NULL,
                         0),
    m_options(interpreter)
    {
    }
    
    virtual
    ~CommandObjectPlatformMkDir ()
    {
    }
    
    virtual bool
    DoExecute (Args& args, CommandReturnObject &result)
    {
        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
        if (platform_sp)
        {
            std::string cmd_line;
            args.GetCommandString(cmd_line);
            uint32_t mode;
            const OptionPermissions* options_permissions = (const OptionPermissions*)m_options.GetGroupWithOption('r');
            if (options_permissions)
                mode = options_permissions->m_permissions;
            else
                mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX | lldb::eFilePermissionsWorldRX;
            Error error = platform_sp->MakeDirectory(cmd_line.c_str(), mode);
            if (error.Success())
            {
                result.SetStatus (eReturnStatusSuccessFinishResult);
            }
            else
            {
                result.AppendError(error.AsCString());
                result.SetStatus (eReturnStatusFailed);
            }
        }
        else
        {
            result.AppendError ("no platform currently selected\n");
            result.SetStatus (eReturnStatusFailed);
        }
        return result.Succeeded();
    }
    
    virtual Options *
    GetOptions ()
    {
        if (m_options.DidFinalize() == false)
        {
            m_options.Append(new OptionPermissions());
            m_options.Finalize();
        }
        return &m_options;
    }
    OptionGroupOptions m_options;
    
};

//----------------------------------------------------------------------
// "platform fopen"
//----------------------------------------------------------------------
class CommandObjectPlatformFOpen : public CommandObjectParsed
{
public:
    CommandObjectPlatformFOpen (CommandInterpreter &interpreter) :
    CommandObjectParsed (interpreter,
                         "platform file open",
                         "Open a file on the remote end.",
                         NULL,
                         0),
    m_options(interpreter)
    {
    }
    
    virtual
    ~CommandObjectPlatformFOpen ()
    {
    }
    
    virtual bool
    DoExecute (Args& args, CommandReturnObject &result)
    {
        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
        if (platform_sp)
        {
            Error error;
            std::string cmd_line;
            args.GetCommandString(cmd_line);
            mode_t perms;
            const OptionPermissions* options_permissions = (const OptionPermissions*)m_options.GetGroupWithOption('r');
            if (options_permissions)
                perms = options_permissions->m_permissions;
            else
                perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW | lldb::eFilePermissionsWorldRead;
            lldb::user_id_t fd = platform_sp->OpenFile(FileSpec(cmd_line.c_str(),false),
                                                       File::eOpenOptionRead | File::eOpenOptionWrite |
                                                       File::eOpenOptionAppend | File::eOpenOptionCanCreate,
                                                       perms,
                                                       error);
{'fraction_non_alphanumeric': 0.13915443788183238, 'fraction_numerical': 0.0033286650835210783, 'mean_word_length': 1.4881325118674882, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 40, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3735973', 'n_tokens_mistral': 12466, 'n_tokens_neox': 12206, 'n_words': 2535}