diff options
Diffstat (limited to 'lldb/tools/driver/Driver.cpp')
-rw-r--r-- | lldb/tools/driver/Driver.cpp | 2238 |
1 files changed, 1068 insertions, 1170 deletions
diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp index c057d71a830..db950153753 100644 --- a/lldb/tools/driver/Driver.cpp +++ b/lldb/tools/driver/Driver.cpp @@ -9,16 +9,16 @@ #include "Driver.h" +#include <fcntl.h> +#include <limits.h> #include <stdio.h> -#include <string.h> #include <stdlib.h> -#include <limits.h> -#include <fcntl.h> +#include <string.h> // Includes for pipe() #if defined(_WIN32) -#include <io.h> #include <fcntl.h> +#include <io.h> #elif defined(__ANDROID_NDK__) #include <errno.h> #else @@ -50,7 +50,7 @@ using namespace lldb; -static void reset_stdin_termios (); +static void reset_stdin_termios(); static bool g_old_stdin_termios_is_valid = false; static struct termios g_old_stdin_termios; @@ -58,1253 +58,1155 @@ static Driver *g_driver = NULL; // In the Driver::MainLoop, we change the terminal settings. This function is // added as an atexit handler to make sure we clean them up. -static void -reset_stdin_termios () -{ - if (g_old_stdin_termios_is_valid) - { - g_old_stdin_termios_is_valid = false; - ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios); - } +static void reset_stdin_termios() { + if (g_old_stdin_termios_is_valid) { + g_old_stdin_termios_is_valid = false; + ::tcsetattr(STDIN_FILENO, TCSANOW, &g_old_stdin_termios); + } } -typedef struct -{ - uint32_t usage_mask; // Used to mark options that can be used together. If (1 << n & usage_mask) != 0 - // then this option belongs to option set n. - bool required; // This option is required (in the current usage level) - const char * long_option; // Full name for this option. - int short_option; // Single character for this option. - int option_has_arg; // no_argument, required_argument or optional_argument - uint32_t completion_type; // Cookie the option class can use to do define the argument completion. - lldb::CommandArgumentType argument_type; // Type of argument this option takes - const char * usage_text; // Full text explaining what this options does and what (if any) argument to - // pass it. +typedef struct { + uint32_t usage_mask; // Used to mark options that can be used together. If (1 + // << n & usage_mask) != 0 + // then this option belongs to option set n. + bool required; // This option is required (in the current usage level) + const char *long_option; // Full name for this option. + int short_option; // Single character for this option. + int option_has_arg; // no_argument, required_argument or optional_argument + uint32_t completion_type; // Cookie the option class can use to do define the + // argument completion. + lldb::CommandArgumentType argument_type; // Type of argument this option takes + const char *usage_text; // Full text explaining what this options does and + // what (if any) argument to + // pass it. } OptionDefinition; -#define LLDB_3_TO_5 LLDB_OPT_SET_3|LLDB_OPT_SET_4|LLDB_OPT_SET_5 -#define LLDB_4_TO_5 LLDB_OPT_SET_4|LLDB_OPT_SET_5 - -static OptionDefinition g_options[] = -{ - { LLDB_OPT_SET_1, true , "help" , 'h', no_argument , 0, eArgTypeNone, - "Prints out the usage information for the LLDB debugger." }, - { LLDB_OPT_SET_2, true , "version" , 'v', no_argument , 0, eArgTypeNone, - "Prints out the current version number of the LLDB debugger." }, - { LLDB_OPT_SET_3, true , "arch" , 'a', required_argument, 0, eArgTypeArchitecture, - "Tells the debugger to use the specified architecture when starting and running the program. <architecture> must " - "be one of the architectures for which the program was compiled." }, - { LLDB_OPT_SET_3, true , "file" , 'f', required_argument, 0, eArgTypeFilename, - "Tells the debugger to use the file <filename> as the program to be debugged." }, - { LLDB_OPT_SET_3, false, "core" , 'c', required_argument, 0, eArgTypeFilename, - "Tells the debugger to use the fullpath to <path> as the core file." }, - { LLDB_OPT_SET_5, true , "attach-pid" , 'p', required_argument, 0, eArgTypePid, - "Tells the debugger to attach to a process with the given pid." }, - { LLDB_OPT_SET_4, true , "attach-name" , 'n', required_argument, 0, eArgTypeProcessName, - "Tells the debugger to attach to a process with the given name." }, - { LLDB_OPT_SET_4, true , "wait-for" , 'w', no_argument , 0, eArgTypeNone, - "Tells the debugger to wait for a process with the given pid or name to launch before attaching." }, - { LLDB_3_TO_5, false, "source" , 's', required_argument, 0, eArgTypeFilename, - "Tells the debugger to read in and execute the lldb commands in the given file, after any file provided on the command line has been loaded." }, - { LLDB_3_TO_5, false, "one-line" , 'o', required_argument, 0, eArgTypeNone, - "Tells the debugger to execute this one-line lldb command after any file provided on the command line has been loaded." }, - { LLDB_3_TO_5, false, "source-before-file" , 'S', required_argument, 0, eArgTypeFilename, - "Tells the debugger to read in and execute the lldb commands in the given file, before any file provided on the command line has been loaded." }, - { LLDB_3_TO_5, false, "one-line-before-file" , 'O', required_argument, 0, eArgTypeNone, - "Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded." }, - { LLDB_3_TO_5, false, "one-line-on-crash" , 'k', required_argument, 0, eArgTypeNone, - "When in batch mode, tells the debugger to execute this one-line lldb command if the target crashes." }, - { LLDB_3_TO_5, false, "source-on-crash" , 'K', required_argument, 0, eArgTypeFilename, - "When in batch mode, tells the debugger to source this file of lldb commands if the target crashes." }, - { LLDB_3_TO_5, false, "source-quietly" , 'Q', no_argument , 0, eArgTypeNone, - "Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded." }, - { LLDB_3_TO_5, false, "batch" , 'b', no_argument , 0, eArgTypeNone, - "Tells the debugger to running the commands from -s, -S, -o & -O, and then quit. However if any run command stopped due to a signal or crash, " - "the debugger will return to the interactive prompt at the place of the crash." }, - { LLDB_3_TO_5, false, "editor" , 'e', no_argument , 0, eArgTypeNone, - "Tells the debugger to open source files using the host's \"external editor\" mechanism." }, - { LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , 0, eArgTypeNone, - "Do not automatically parse any '.lldbinit' files." }, - { LLDB_3_TO_5, false, "no-use-colors" , 'X', no_argument , 0, eArgTypeNone, - "Do not use colors." }, - { LLDB_OPT_SET_6, true , "python-path" , 'P', no_argument , 0, eArgTypeNone, - "Prints out the path to the lldb.py file for this version of lldb." }, - { LLDB_3_TO_5, false, "script-language", 'l', required_argument, 0, eArgTypeScriptLang, - "Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default. " - "Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl. Currently only the Python " - "extensions have been implemented." }, - { LLDB_3_TO_5, false, "debug" , 'd', no_argument , 0, eArgTypeNone, - "Tells the debugger to print out extra information for debugging itself." }, - { LLDB_OPT_SET_7, true , "repl" , 'r', optional_argument, 0, eArgTypeNone, - "Runs lldb in REPL mode with a stub process." }, - { LLDB_OPT_SET_7, true , "repl-language" , 'R', required_argument, 0, eArgTypeNone, - "Chooses the language for the REPL." }, - { 0, false, NULL , 0 , 0 , 0, eArgTypeNone, NULL } -}; +#define LLDB_3_TO_5 LLDB_OPT_SET_3 | LLDB_OPT_SET_4 | LLDB_OPT_SET_5 +#define LLDB_4_TO_5 LLDB_OPT_SET_4 | LLDB_OPT_SET_5 + +static OptionDefinition g_options[] = { + {LLDB_OPT_SET_1, true, "help", 'h', no_argument, 0, eArgTypeNone, + "Prints out the usage information for the LLDB debugger."}, + {LLDB_OPT_SET_2, true, "version", 'v', no_argument, 0, eArgTypeNone, + "Prints out the current version number of the LLDB debugger."}, + {LLDB_OPT_SET_3, true, "arch", 'a', required_argument, 0, + eArgTypeArchitecture, + "Tells the debugger to use the specified architecture when starting and " + "running the program. <architecture> must " + "be one of the architectures for which the program was compiled."}, + {LLDB_OPT_SET_3, true, "file", 'f', required_argument, 0, eArgTypeFilename, + "Tells the debugger to use the file <filename> as the program to be " + "debugged."}, + {LLDB_OPT_SET_3, false, "core", 'c', required_argument, 0, eArgTypeFilename, + "Tells the debugger to use the fullpath to <path> as the core file."}, + {LLDB_OPT_SET_5, true, "attach-pid", 'p', required_argument, 0, eArgTypePid, + "Tells the debugger to attach to a process with the given pid."}, + {LLDB_OPT_SET_4, true, "attach-name", 'n', required_argument, 0, + eArgTypeProcessName, + "Tells the debugger to attach to a process with the given name."}, + {LLDB_OPT_SET_4, true, "wait-for", 'w', no_argument, 0, eArgTypeNone, + "Tells the debugger to wait for a process with the given pid or name to " + "launch before attaching."}, + {LLDB_3_TO_5, false, "source", 's', required_argument, 0, eArgTypeFilename, + "Tells the debugger to read in and execute the lldb commands in the given " + "file, after any file provided on the command line has been loaded."}, + {LLDB_3_TO_5, false, "one-line", 'o', required_argument, 0, eArgTypeNone, + "Tells the debugger to execute this one-line lldb command after any file " + "provided on the command line has been loaded."}, + {LLDB_3_TO_5, false, "source-before-file", 'S', required_argument, 0, + eArgTypeFilename, "Tells the debugger to read in and execute the lldb " + "commands in the given file, before any file provided " + "on the command line has been loaded."}, + {LLDB_3_TO_5, false, "one-line-before-file", 'O', required_argument, 0, + eArgTypeNone, "Tells the debugger to execute this one-line lldb command " + "before any file provided on the command line has been " + "loaded."}, + {LLDB_3_TO_5, false, "one-line-on-crash", 'k', required_argument, 0, + eArgTypeNone, "When in batch mode, tells the debugger to execute this " + "one-line lldb command if the target crashes."}, + {LLDB_3_TO_5, false, "source-on-crash", 'K', required_argument, 0, + eArgTypeFilename, "When in batch mode, tells the debugger to source this " + "file of lldb commands if the target crashes."}, + {LLDB_3_TO_5, false, "source-quietly", 'Q', no_argument, 0, eArgTypeNone, + "Tells the debugger to execute this one-line lldb command before any file " + "provided on the command line has been loaded."}, + {LLDB_3_TO_5, false, "batch", 'b', no_argument, 0, eArgTypeNone, + "Tells the debugger to running the commands from -s, -S, -o & -O, and " + "then quit. However if any run command stopped due to a signal or crash, " + "the debugger will return to the interactive prompt at the place of the " + "crash."}, + {LLDB_3_TO_5, false, "editor", 'e', no_argument, 0, eArgTypeNone, + "Tells the debugger to open source files using the host's \"external " + "editor\" mechanism."}, + {LLDB_3_TO_5, false, "no-lldbinit", 'x', no_argument, 0, eArgTypeNone, + "Do not automatically parse any '.lldbinit' files."}, + {LLDB_3_TO_5, false, "no-use-colors", 'X', no_argument, 0, eArgTypeNone, + "Do not use colors."}, + {LLDB_OPT_SET_6, true, "python-path", 'P', no_argument, 0, eArgTypeNone, + "Prints out the path to the lldb.py file for this version of lldb."}, + {LLDB_3_TO_5, false, "script-language", 'l', required_argument, 0, + eArgTypeScriptLang, + "Tells the debugger to use the specified scripting language for " + "user-defined scripts, rather than the default. " + "Valid scripting languages that can be specified include Python, Perl, " + "Ruby and Tcl. Currently only the Python " + "extensions have been implemented."}, + {LLDB_3_TO_5, false, "debug", 'd', no_argument, 0, eArgTypeNone, + "Tells the debugger to print out extra information for debugging itself."}, + {LLDB_OPT_SET_7, true, "repl", 'r', optional_argument, 0, eArgTypeNone, + "Runs lldb in REPL mode with a stub process."}, + {LLDB_OPT_SET_7, true, "repl-language", 'R', required_argument, 0, + eArgTypeNone, "Chooses the language for the REPL."}, + {0, false, NULL, 0, 0, 0, eArgTypeNone, NULL}}; static const uint32_t last_option_set_with_args = 2; -Driver::Driver () : - SBBroadcaster ("Driver"), - m_debugger (SBDebugger::Create(false)), - m_option_data () -{ - // We want to be able to handle CTRL+D in the terminal to have it terminate - // certain input - m_debugger.SetCloseInputOnEOF (false); - g_driver = this; -} - -Driver::~Driver () -{ - g_driver = NULL; +Driver::Driver() + : SBBroadcaster("Driver"), m_debugger(SBDebugger::Create(false)), + m_option_data() { + // We want to be able to handle CTRL+D in the terminal to have it terminate + // certain input + m_debugger.SetCloseInputOnEOF(false); + g_driver = this; } +Driver::~Driver() { g_driver = NULL; } -// This function takes INDENT, which tells how many spaces to output at the front -// of each line; TEXT, which is the text that is to be output. It outputs the -// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the -// front of each line. It breaks lines on spaces, tabs or newlines, shortening -// the line if necessary to not break in the middle of a word. It assumes that +// This function takes INDENT, which tells how many spaces to output at the +// front +// of each line; TEXT, which is the text that is to be output. It outputs the +// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the +// front of each line. It breaks lines on spaces, tabs or newlines, shortening +// the line if necessary to not break in the middle of a word. It assumes that // each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters. -void -OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns) -{ - int len = strlen (text); - std::string text_string (text); - - // Force indentation to be reasonable. - if (indent >= output_max_columns) - indent = 0; - - // Will it all fit on one line? - - if (len + indent < output_max_columns) - // Output as a single line - fprintf (out, "%*s%s\n", indent, "", text); - else - { - // We need to break it up into multiple lines. - int text_width = output_max_columns - indent - 1; - int start = 0; - int end = start; - int final_end = len; - int sub_len; - - while (end < final_end) - { - // Dont start the 'text' on a space, since we're already outputting the indentation. - while ((start < final_end) && (text[start] == ' ')) - start++; - - end = start + text_width; - if (end > final_end) - end = final_end; - else - { - // If we're not at the end of the text, make sure we break the line on white space. - while (end > start - && text[end] != ' ' && text[end] != '\t' && text[end] != '\n') - end--; - } - sub_len = end - start; - std::string substring = text_string.substr (start, sub_len); - fprintf (out, "%*s%s\n", indent, "", substring.c_str()); - start = end + 1; - } +void OutputFormattedUsageText(FILE *out, int indent, const char *text, + int output_max_columns) { + int len = strlen(text); + std::string text_string(text); + + // Force indentation to be reasonable. + if (indent >= output_max_columns) + indent = 0; + + // Will it all fit on one line? + + if (len + indent < output_max_columns) + // Output as a single line + fprintf(out, "%*s%s\n", indent, "", text); + else { + // We need to break it up into multiple lines. + int text_width = output_max_columns - indent - 1; + int start = 0; + int end = start; + int final_end = len; + int sub_len; + + while (end < final_end) { + // Dont start the 'text' on a space, since we're already outputting the + // indentation. + while ((start < final_end) && (text[start] == ' ')) + start++; + + end = start + text_width; + if (end > final_end) + end = final_end; + else { + // If we're not at the end of the text, make sure we break the line on + // white space. + while (end > start && text[end] != ' ' && text[end] != '\t' && + text[end] != '\n') + end--; + } + sub_len = end - start; + std::string substring = text_string.substr(start, sub_len); + fprintf(out, "%*s%s\n", indent, "", substring.c_str()); + start = end + 1; } + } } -void -ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data) -{ - uint32_t screen_width = 80; - uint32_t indent_level = 0; - const char *name = "lldb"; - - fprintf (out, "\nUsage:\n\n"); - - indent_level += 2; - - - // First, show each usage level set of options, e.g. <cmd> [options-for-level-0] - // <cmd> [options-for-level-1] - // etc. - - uint32_t num_options; - uint32_t num_option_sets = 0; - - for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options) - { - uint32_t this_usage_mask = option_table[num_options].usage_mask; - if (this_usage_mask == LLDB_OPT_SET_ALL) - { - if (num_option_sets == 0) - num_option_sets = 1; - } - else - { - for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++) - { - if (this_usage_mask & 1 << j) - { - if (num_option_sets <= j) - num_option_sets = j + 1; - } - } +void ShowUsage(FILE *out, OptionDefinition *option_table, + Driver::OptionData data) { + uint32_t screen_width = 80; + uint32_t indent_level = 0; + const char *name = "lldb"; + + fprintf(out, "\nUsage:\n\n"); + + indent_level += 2; + + // First, show each usage level set of options, e.g. <cmd> + // [options-for-level-0] + // <cmd> + // [options-for-level-1] + // etc. + + uint32_t num_options; + uint32_t num_option_sets = 0; + + for (num_options = 0; option_table[num_options].long_option != NULL; + ++num_options) { + uint32_t this_usage_mask = option_table[num_options].usage_mask; + if (this_usage_mask == LLDB_OPT_SET_ALL) { + if (num_option_sets == 0) + num_option_sets = 1; + } else { + for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++) { + if (this_usage_mask & 1 << j) { + if (num_option_sets <= j) + num_option_sets = j + 1; } + } } - - for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++) - { - uint32_t opt_set_mask; - - opt_set_mask = 1 << opt_set; - - if (opt_set > 0) - fprintf (out, "\n"); - fprintf (out, "%*s%s", indent_level, "", name); - bool is_help_line = false; - - for (uint32_t i = 0; i < num_options; ++i) - { - if (option_table[i].usage_mask & opt_set_mask) - { - CommandArgumentType arg_type = option_table[i].argument_type; - const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type); - // This is a bit of a hack, but there's no way to say certain options don't have arguments yet... - // so we do it by hand here. - if (option_table[i].short_option == 'h') - is_help_line = true; - - if (option_table[i].required) - { - if (option_table[i].option_has_arg == required_argument) - fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name); - else if (option_table[i].option_has_arg == optional_argument) - fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name); - else - fprintf (out, " -%c", option_table[i].short_option); - } - else - { - if (option_table[i].option_has_arg == required_argument) - fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name); - else if (option_table[i].option_has_arg == optional_argument) - fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name); - else - fprintf (out, " [-%c]", option_table[i].short_option); - } - } + } + + for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++) { + uint32_t opt_set_mask; + + opt_set_mask = 1 << opt_set; + + if (opt_set > 0) + fprintf(out, "\n"); + fprintf(out, "%*s%s", indent_level, "", name); + bool is_help_line = false; + + for (uint32_t i = 0; i < num_options; ++i) { + if (option_table[i].usage_mask & opt_set_mask) { + CommandArgumentType arg_type = option_table[i].argument_type; + const char *arg_name = + SBCommandInterpreter::GetArgumentTypeAsCString(arg_type); + // This is a bit of a hack, but there's no way to say certain options + // don't have arguments yet... + // so we do it by hand here. + if (option_table[i].short_option == 'h') + is_help_line = true; + + if (option_table[i].required) { + if (option_table[i].option_has_arg == required_argument) + fprintf(out, " -%c <%s>", option_table[i].short_option, arg_name); + else if (option_table[i].option_has_arg == optional_argument) + fprintf(out, " -%c [<%s>]", option_table[i].short_option, arg_name); + else + fprintf(out, " -%c", option_table[i].short_option); + } else { + if (option_table[i].option_has_arg == required_argument) + fprintf(out, " [-%c <%s>]", option_table[i].short_option, arg_name); + else if (option_table[i].option_has_arg == optional_argument) + fprintf(out, " [-%c [<%s>]]", option_table[i].short_option, + arg_name); + else + fprintf(out, " [-%c]", option_table[i].short_option); } - if (!is_help_line && (opt_set <= last_option_set_with_args)) - fprintf (out, " [[--] <PROGRAM-ARG-1> [<PROGRAM_ARG-2> ...]]"); + } } - - fprintf (out, "\n\n"); - - // Now print out all the detailed information about the various options: long form, short form and help text: - // -- long_name <argument> - // - short <argument> - // help text - - // This variable is used to keep track of which options' info we've printed out, because some options can be in - // more than one usage level, but we only want to print the long form of its information once. - - Driver::OptionData::OptionSet options_seen; - Driver::OptionData::OptionSet::iterator pos; - - indent_level += 5; - - for (uint32_t i = 0; i < num_options; ++i) - { - // Only print this option if we haven't already seen it. - pos = options_seen.find (option_table[i].short_option); - if (pos == options_seen.end()) - { - CommandArgumentType arg_type = option_table[i].argument_type; - const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type); - - options_seen.insert (option_table[i].short_option); - fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option); - if (arg_type != eArgTypeNone) - fprintf (out, "<%s>", arg_name); - fprintf (out, "\n"); - fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option); - if (arg_type != eArgTypeNone) - fprintf (out, "<%s>", arg_name); - fprintf (out, "\n"); - indent_level += 5; - OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width); - indent_level -= 5; - fprintf (out, "\n"); - } + if (!is_help_line && (opt_set <= last_option_set_with_args)) + fprintf(out, " [[--] <PROGRAM-ARG-1> [<PROGRAM_ARG-2> ...]]"); + } + + fprintf(out, "\n\n"); + + // Now print out all the detailed information about the various options: long + // form, short form and help text: + // -- long_name <argument> + // - short <argument> + // help text + + // This variable is used to keep track of which options' info we've printed + // out, because some options can be in + // more than one usage level, but we only want to print the long form of its + // information once. + + Driver::OptionData::OptionSet options_seen; + Driver::OptionData::OptionSet::iterator pos; + + indent_level += 5; + + for (uint32_t i = 0; i < num_options; ++i) { + // Only print this option if we haven't already seen it. + pos = options_seen.find(option_table[i].short_option); + if (pos == options_seen.end()) { + CommandArgumentType arg_type = option_table[i].argument_type; + const char *arg_name = + SBCommandInterpreter::GetArgumentTypeAsCString(arg_type); + + options_seen.insert(option_table[i].short_option); + fprintf(out, "%*s-%c ", indent_level, "", option_table[i].short_option); + if (arg_type != eArgTypeNone) + fprintf(out, "<%s>", arg_name); + fprintf(out, "\n"); + fprintf(out, "%*s--%s ", indent_level, "", option_table[i].long_option); + if (arg_type != eArgTypeNone) + fprintf(out, "<%s>", arg_name); + fprintf(out, "\n"); + indent_level += 5; + OutputFormattedUsageText(out, indent_level, option_table[i].usage_text, + screen_width); + indent_level -= 5; + fprintf(out, "\n"); } - - indent_level -= 5; - - fprintf (out, "\n%*sNotes:\n", - indent_level, ""); - indent_level += 5; - - fprintf (out, "\n%*sMultiple \"-s\" and \"-o\" options can be provided. They will be processed" - "\n%*sfrom left to right in order, with the source files and commands" - "\n%*sinterleaved. The same is true of the \"-S\" and \"-O\" options. The before" - "\n%*sfile and after file sets can intermixed freely, the command parser will" - "\n%*ssort them out. The order of the file specifiers (\"-c\", \"-f\", etc.) is" - "\n%*snot significant in this regard.\n\n", - indent_level, "", - indent_level, "", - indent_level, "", - indent_level, "", - indent_level, "", - indent_level, ""); - - fprintf (out, "\n%*sIf you don't provide -f then the first argument will be the file to be" - "\n%*sdebugged which means that '%s -- <filename> [<ARG1> [<ARG2>]]' also" - "\n%*sworks. But remember to end the options with \"--\" if any of your" - "\n%*sarguments have a \"-\" in them.\n\n", - indent_level, "", - indent_level, "", - name, - indent_level, "", - indent_level, ""); + } + + indent_level -= 5; + + fprintf(out, "\n%*sNotes:\n", indent_level, ""); + indent_level += 5; + + fprintf(out, + "\n%*sMultiple \"-s\" and \"-o\" options can be provided. They will " + "be processed" + "\n%*sfrom left to right in order, with the source files and commands" + "\n%*sinterleaved. The same is true of the \"-S\" and \"-O\" " + "options. The before" + "\n%*sfile and after file sets can intermixed freely, the command " + "parser will" + "\n%*ssort them out. The order of the file specifiers (\"-c\", " + "\"-f\", etc.) is" + "\n%*snot significant in this regard.\n\n", + indent_level, "", indent_level, "", indent_level, "", indent_level, + "", indent_level, "", indent_level, ""); + + fprintf( + out, + "\n%*sIf you don't provide -f then the first argument will be the file " + "to be" + "\n%*sdebugged which means that '%s -- <filename> [<ARG1> [<ARG2>]]' also" + "\n%*sworks. But remember to end the options with \"--\" if any of your" + "\n%*sarguments have a \"-\" in them.\n\n", + indent_level, "", indent_level, "", name, indent_level, "", indent_level, + ""); } -void -BuildGetOptTable (OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table, - uint32_t num_options) -{ - if (num_options == 0) - return; - - uint32_t i; - uint32_t j; - std::bitset<256> option_seen; - - getopt_table.resize (num_options + 1); - - for (i = 0, j = 0; i < num_options; ++i) - { - char short_opt = expanded_option_table[i].short_option; - - if (option_seen.test(short_opt) == false) - { - getopt_table[j].name = expanded_option_table[i].long_option; - getopt_table[j].has_arg = expanded_option_table[i].option_has_arg; - getopt_table[j].flag = NULL; - getopt_table[j].val = expanded_option_table[i].short_option; - option_seen.set(short_opt); - ++j; - } - } +void BuildGetOptTable(OptionDefinition *expanded_option_table, + std::vector<struct option> &getopt_table, + uint32_t num_options) { + if (num_options == 0) + return; - getopt_table[j].name = NULL; - getopt_table[j].has_arg = 0; - getopt_table[j].flag = NULL; - getopt_table[j].val = 0; + uint32_t i; + uint32_t j; + std::bitset<256> option_seen; -} + getopt_table.resize(num_options + 1); -Driver::OptionData::OptionData () : - m_args(), - m_script_lang (lldb::eScriptLanguageDefault), - m_core_file (), - m_crash_log (), - m_initial_commands (), - m_after_file_commands (), - m_after_crash_commands(), - m_debug_mode (false), - m_source_quietly(false), - m_print_version (false), - m_print_python_path (false), - m_print_help (false), - m_wait_for(false), - m_repl (false), - m_repl_lang (eLanguageTypeUnknown), - m_repl_options (), - m_process_name(), - m_process_pid(LLDB_INVALID_PROCESS_ID), - m_use_external_editor(false), - m_batch(false), - m_seen_options() -{ -} + for (i = 0, j = 0; i < num_options; ++i) { + char short_opt = expanded_option_table[i].short_option; -Driver::OptionData::~OptionData () -{ -} - -void -Driver::OptionData::Clear () -{ - m_args.clear (); - m_script_lang = lldb::eScriptLanguageDefault; - m_initial_commands.clear (); - m_after_file_commands.clear (); - - // If there is a local .lldbinit, add that to the - // list of things to be sourced, if the settings - // permit it. - SBFileSpec local_lldbinit (".lldbinit", true); - - SBFileSpec homedir_dot_lldb = SBHostOS::GetUserHomeDirectory(); - homedir_dot_lldb.AppendPathComponent (".lldbinit"); - - // Only read .lldbinit in the current working directory - // if it's not the same as the .lldbinit in the home - // directory (which is already being read in). - if (local_lldbinit.Exists() - && strcmp (local_lldbinit.GetDirectory(), homedir_dot_lldb.GetDirectory()) != 0) - { - char path[2048]; - local_lldbinit.GetPath(path, 2047); - InitialCmdEntry entry(path, true, true, true); - m_after_file_commands.push_back (entry); + if (option_seen.test(short_opt) == false) { + getopt_table[j].name = expanded_option_table[i].long_option; + getopt_table[j].has_arg = expanded_option_table[i].option_has_arg; + getopt_table[j].flag = NULL; + getopt_table[j].val = expanded_option_table[i].short_option; + option_seen.set(short_opt); + ++j; } - - m_debug_mode = false; - m_source_quietly = false; - m_print_help = false; - m_print_version = false; - m_print_python_path = false; - m_use_external_editor = false; - m_wait_for = false; - m_process_name.erase(); - m_batch = false; - m_after_crash_commands.clear(); - - m_process_pid = LLDB_INVALID_PROCESS_ID; -} + } -void -Driver::OptionData::AddInitialCommand (const char *command, CommandPlacement placement, bool is_file, SBError &error) -{ - std::vector<InitialCmdEntry> *command_set; - switch (placement) - { - case eCommandPlacementBeforeFile: - command_set = &(m_initial_commands); - break; - case eCommandPlacementAfterFile: - command_set = &(m_after_file_commands); - break; - case eCommandPlacementAfterCrash: - command_set = &(m_after_crash_commands); - break; - } - - if (is_file) - { - SBFileSpec file(command); - if (file.Exists()) - command_set->push_back (InitialCmdEntry(command, is_file, false)); - else if (file.ResolveExecutableLocation()) - { - char final_path[PATH_MAX]; - file.GetPath (final_path, sizeof(final_path)); - command_set->push_back (InitialCmdEntry(final_path, is_file, false)); - } - else - error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg); - } - else - command_set->push_back (InitialCmdEntry(command, is_file, false)); + getopt_table[j].name = NULL; + getopt_table[j].has_arg = 0; + getopt_table[j].flag = NULL; + getopt_table[j].val = 0; } -void -Driver::ResetOptionValues () -{ - m_option_data.Clear (); +Driver::OptionData::OptionData() + : m_args(), m_script_lang(lldb::eScriptLanguageDefault), m_core_file(), + m_crash_log(), m_initial_commands(), m_after_file_commands(), + m_after_crash_commands(), m_debug_mode(false), m_source_quietly(false), + m_print_version(false), m_print_python_path(false), m_print_help(false), + m_wait_for(false), m_repl(false), m_repl_lang(eLanguageTypeUnknown), + m_repl_options(), m_process_name(), + m_process_pid(LLDB_INVALID_PROCESS_ID), m_use_external_editor(false), + m_batch(false), m_seen_options() {} + +Driver::OptionData::~OptionData() {} + +void Driver::OptionData::Clear() { + m_args.clear(); + m_script_lang = lldb::eScriptLanguageDefault; + m_initial_commands.clear(); + m_after_file_commands.clear(); + + // If there is a local .lldbinit, add that to the + // list of things to be sourced, if the settings + // permit it. + SBFileSpec local_lldbinit(".lldbinit", true); + + SBFileSpec homedir_dot_lldb = SBHostOS::GetUserHomeDirectory(); + homedir_dot_lldb.AppendPathComponent(".lldbinit"); + + // Only read .lldbinit in the current working directory + // if it's not the same as the .lldbinit in the home + // directory (which is already being read in). + if (local_lldbinit.Exists() && + strcmp(local_lldbinit.GetDirectory(), homedir_dot_lldb.GetDirectory()) != + 0) { + char path[2048]; + local_lldbinit.GetPath(path, 2047); + InitialCmdEntry entry(path, true, true, true); + m_after_file_commands.push_back(entry); + } + + m_debug_mode = false; + m_source_quietly = false; + m_print_help = false; + m_print_version = false; + m_print_python_path = false; + m_use_external_editor = false; + m_wait_for = false; + m_process_name.erase(); + m_batch = false; + m_after_crash_commands.clear(); + + m_process_pid = LLDB_INVALID_PROCESS_ID; } -const char * -Driver::GetFilename() const -{ - if (m_option_data.m_args.empty()) - return NULL; - return m_option_data.m_args.front().c_str(); +void Driver::OptionData::AddInitialCommand(const char *command, + CommandPlacement placement, + bool is_file, SBError &error) { + std::vector<InitialCmdEntry> *command_set; + switch (placement) { + case eCommandPlacementBeforeFile: + command_set = &(m_initial_commands); + break; + case eCommandPlacementAfterFile: + command_set = &(m_after_file_commands); + break; + case eCommandPlacementAfterCrash: + command_set = &(m_after_crash_commands); + break; + } + + if (is_file) { + SBFileSpec file(command); + if (file.Exists()) + command_set->push_back(InitialCmdEntry(command, is_file, false)); + else if (file.ResolveExecutableLocation()) { + char final_path[PATH_MAX]; + file.GetPath(final_path, sizeof(final_path)); + command_set->push_back(InitialCmdEntry(final_path, is_file, false)); + } else + error.SetErrorStringWithFormat( + "file specified in --source (-s) option doesn't exist: '%s'", optarg); + } else + command_set->push_back(InitialCmdEntry(command, is_file, false)); } -const char * -Driver::GetCrashLogFilename() const -{ - if (m_option_data.m_crash_log.empty()) - return NULL; - return m_option_data.m_crash_log.c_str(); +void Driver::ResetOptionValues() { m_option_data.Clear(); } + +const char *Driver::GetFilename() const { + if (m_option_data.m_args.empty()) + return NULL; + return m_option_data.m_args.front().c_str(); } -lldb::ScriptLanguage -Driver::GetScriptLanguage() const -{ - return m_option_data.m_script_lang; +const char *Driver::GetCrashLogFilename() const { + if (m_option_data.m_crash_log.empty()) + return NULL; + return m_option_data.m_crash_log.c_str(); } -void -Driver::WriteCommandsForSourcing (CommandPlacement placement, SBStream &strm) -{ - std::vector<OptionData::InitialCmdEntry> *command_set; - switch (placement) - { - case eCommandPlacementBeforeFile: - command_set = &m_option_data.m_initial_commands; - break; - case eCommandPlacementAfterFile: - command_set = &m_option_data.m_after_file_commands; - break; - case eCommandPlacementAfterCrash: - command_set = &m_option_data.m_after_crash_commands; - break; - } - - for (const auto &command_entry : *command_set) - { - const char *command = command_entry.contents.c_str(); - if (command_entry.is_file) - { - // If this command_entry is a file to be sourced, and it's the ./.lldbinit file (the .lldbinit - // file in the current working directory), only read it if target.load-cwd-lldbinit is 'true'. - if (command_entry.is_cwd_lldbinit_file_read) - { - SBStringList strlist = m_debugger.GetInternalVariableValue ("target.load-cwd-lldbinit", - m_debugger.GetInstanceName()); - if (strlist.GetSize() == 1 && strcmp (strlist.GetStringAtIndex(0), "warn") == 0) - { - FILE *output = m_debugger.GetOutputFileHandle (); - ::fprintf (output, - "There is a .lldbinit file in the current directory which is not being read.\n" - "To silence this warning without sourcing in the local .lldbinit,\n" - "add the following to the lldbinit file in your home directory:\n" - " settings set target.load-cwd-lldbinit false\n" - "To allow lldb to source .lldbinit files in the current working directory,\n" - "set the value of this variable to true. Only do so if you understand and\n" - "accept the security risk.\n"); - return; - } - if (strlist.GetSize() == 1 && strcmp (strlist.GetStringAtIndex(0), "false") == 0) - { - return; - } - } - bool source_quietly = m_option_data.m_source_quietly || command_entry.source_quietly; - strm.Printf("command source -s %i '%s'\n", source_quietly, command); - } - else - strm.Printf("%s\n", command); - } +lldb::ScriptLanguage Driver::GetScriptLanguage() const { + return m_option_data.m_script_lang; } -bool -Driver::GetDebugMode() const -{ - return m_option_data.m_debug_mode; +void Driver::WriteCommandsForSourcing(CommandPlacement placement, + SBStream &strm) { + std::vector<OptionData::InitialCmdEntry> *command_set; + switch (placement) { + case eCommandPlacementBeforeFile: + command_set = &m_option_data.m_initial_commands; + break; + case eCommandPlacementAfterFile: + command_set = &m_option_data.m_after_file_commands; + break; + case eCommandPlacementAfterCrash: + command_set = &m_option_data.m_after_crash_commands; + break; + } + + for (const auto &command_entry : *command_set) { + const char *command = command_entry.contents.c_str(); + if (command_entry.is_file) { + // If this command_entry is a file to be sourced, and it's the ./.lldbinit + // file (the .lldbinit + // file in the current working directory), only read it if + // target.load-cwd-lldbinit is 'true'. + if (command_entry.is_cwd_lldbinit_file_read) { + SBStringList strlist = m_debugger.GetInternalVariableValue( + "target.load-cwd-lldbinit", m_debugger.GetInstanceName()); + if (strlist.GetSize() == 1 && + strcmp(strlist.GetStringAtIndex(0), "warn") == 0) { + FILE *output = m_debugger.GetOutputFileHandle(); + ::fprintf( + output, + "There is a .lldbinit file in the current directory which is not " + "being read.\n" + "To silence this warning without sourcing in the local " + ".lldbinit,\n" + "add the following to the lldbinit file in your home directory:\n" + " settings set target.load-cwd-lldbinit false\n" + "To allow lldb to source .lldbinit files in the current working " + "directory,\n" + "set the value of this variable to true. Only do so if you " + "understand and\n" + "accept the security risk.\n"); + return; + } + if (strlist.GetSize() == 1 && + strcmp(strlist.GetStringAtIndex(0), "false") == 0) { + return; + } + } + bool source_quietly = + m_option_data.m_source_quietly || command_entry.source_quietly; + strm.Printf("command source -s %i '%s'\n", source_quietly, command); + } else + strm.Printf("%s\n", command); + } } +bool Driver::GetDebugMode() const { return m_option_data.m_debug_mode; } -// Check the arguments that were passed to this program to make sure they are valid and to get their -// argument values (if any). Return a boolean value indicating whether or not to start up the full -// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR +// Check the arguments that were passed to this program to make sure they are +// valid and to get their +// argument values (if any). Return a boolean value indicating whether or not +// to start up the full +// debugger (i.e. the Command Interpreter) or not. Return FALSE if the +// arguments were invalid OR // if the user only wanted help or version information. -SBError -Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) -{ - ResetOptionValues (); - - SBCommandReturnObject result; +SBError Driver::ParseArgs(int argc, const char *argv[], FILE *out_fh, + bool &exiting) { + ResetOptionValues(); - SBError error; - std::string option_string; - struct option *long_options = NULL; - std::vector<struct option> long_options_vector; - uint32_t num_options; + SBCommandReturnObject result; - for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options) - /* Do Nothing. */; + SBError error; + std::string option_string; + struct option *long_options = NULL; + std::vector<struct option> long_options_vector; + uint32_t num_options; - if (num_options == 0) - { - if (argc > 1) - error.SetErrorStringWithFormat ("invalid number of options"); - return error; - } + for (num_options = 0; g_options[num_options].long_option != NULL; + ++num_options) + /* Do Nothing. */; - BuildGetOptTable (g_options, long_options_vector, num_options); + if (num_options == 0) { + if (argc > 1) + error.SetErrorStringWithFormat("invalid number of options"); + return error; + } - if (long_options_vector.empty()) - long_options = NULL; - else - long_options = &long_options_vector.front(); + BuildGetOptTable(g_options, long_options_vector, num_options); - if (long_options == NULL) - { - error.SetErrorStringWithFormat ("invalid long options"); - return error; - } + if (long_options_vector.empty()) + long_options = NULL; + else + long_options = &long_options_vector.front(); - // Build the option_string argument for call to getopt_long_only. - - for (int i = 0; long_options[i].name != NULL; ++i) - { - if (long_options[i].flag == NULL) - { - option_string.push_back ((char) long_options[i].val); - switch (long_options[i].has_arg) - { - default: - case no_argument: - break; - case required_argument: - option_string.push_back (':'); - break; - case optional_argument: - option_string.append ("::"); - break; - } - } - } + if (long_options == NULL) { + error.SetErrorStringWithFormat("invalid long options"); + return error; + } - // This is kind of a pain, but since we make the debugger in the Driver's constructor, we can't - // know at that point whether we should read in init files yet. So we don't read them in in the - // Driver constructor, then set the flags back to "read them in" here, and then if we see the - // "-n" flag, we'll turn it off again. Finally we have to read them in by hand later in the - // main loop. - - m_debugger.SkipLLDBInitFiles (false); - m_debugger.SkipAppInitFiles (false); + // Build the option_string argument for call to getopt_long_only. - // Prepare for & make calls to getopt_long_only. + for (int i = 0; long_options[i].name != NULL; ++i) { + if (long_options[i].flag == NULL) { + option_string.push_back((char)long_options[i].val); + switch (long_options[i].has_arg) { + default: + case no_argument: + break; + case required_argument: + option_string.push_back(':'); + break; + case optional_argument: + option_string.append("::"); + break; + } + } + } + + // This is kind of a pain, but since we make the debugger in the Driver's + // constructor, we can't + // know at that point whether we should read in init files yet. So we don't + // read them in in the + // Driver constructor, then set the flags back to "read them in" here, and + // then if we see the + // "-n" flag, we'll turn it off again. Finally we have to read them in by + // hand later in the + // main loop. + + m_debugger.SkipLLDBInitFiles(false); + m_debugger.SkipAppInitFiles(false); + +// Prepare for & make calls to getopt_long_only. #if __GLIBC__ - optind = 0; + optind = 0; #else - optreset = 1; - optind = 1; + optreset = 1; + optind = 1; #endif - int val; - while (1) - { - int long_options_index = -1; - val = ::getopt_long_only (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index); - - if (val == -1) + int val; + while (1) { + int long_options_index = -1; + val = ::getopt_long_only(argc, const_cast<char **>(argv), + option_string.c_str(), long_options, + &long_options_index); + + if (val == -1) + break; + else if (val == '?') { + m_option_data.m_print_help = true; + error.SetErrorStringWithFormat("unknown or ambiguous option"); + break; + } else if (val == 0) + continue; + else { + m_option_data.m_seen_options.insert((char)val); + if (long_options_index == -1) { + for (int i = 0; long_options[i].name || long_options[i].has_arg || + long_options[i].flag || long_options[i].val; + ++i) { + if (long_options[i].val == val) { + long_options_index = i; break; - else if (val == '?') - { - m_option_data.m_print_help = true; - error.SetErrorStringWithFormat ("unknown or ambiguous option"); - break; - } - else if (val == 0) - continue; - else - { - m_option_data.m_seen_options.insert ((char) val); - if (long_options_index == -1) - { - for (int i = 0; - long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val; - ++i) - { - if (long_options[i].val == val) - { - long_options_index = i; - break; - } - } - } - - if (long_options_index >= 0) - { - const int short_option = g_options[long_options_index].short_option; - - switch (short_option) - { - case 'h': - m_option_data.m_print_help = true; - break; - - case 'v': - m_option_data.m_print_version = true; - break; - - case 'P': - m_option_data.m_print_python_path = true; - break; - - case 'b': - m_option_data.m_batch = true; - break; - - case 'c': - { - SBFileSpec file(optarg); - if (file.Exists()) - { - m_option_data.m_core_file = optarg; - } - else - error.SetErrorStringWithFormat("file specified in --core (-c) option doesn't exist: '%s'", optarg); - } - break; - - case 'e': - m_option_data.m_use_external_editor = true; - break; - - case 'x': - m_debugger.SkipLLDBInitFiles (true); - m_debugger.SkipAppInitFiles (true); - break; - - case 'X': - m_debugger.SetUseColor (false); - break; - - case 'f': - { - SBFileSpec file(optarg); - if (file.Exists()) - { - m_option_data.m_args.push_back (optarg); - } - else if (file.ResolveExecutableLocation()) - { - char path[PATH_MAX]; - file.GetPath (path, sizeof(path)); - m_option_data.m_args.push_back (path); - } - else - error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg); - } - break; - - case 'a': - if (!m_debugger.SetDefaultArchitecture (optarg)) - error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg); - break; - - case 'l': - m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg); - break; - - case 'd': - m_option_data.m_debug_mode = true; - break; - - case 'Q': - m_option_data.m_source_quietly = true; - break; - - case 'K': - m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterCrash, true, error); - break; - case 'k': - m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterCrash, false, error); - break; - - case 'n': - m_option_data.m_process_name = optarg; - break; - - case 'w': - m_option_data.m_wait_for = true; - break; - - case 'p': - { - char *remainder; - m_option_data.m_process_pid = strtol (optarg, &remainder, 0); - if (remainder == optarg || *remainder != '\0') - error.SetErrorStringWithFormat ("Could not convert process PID: \"%s\" into a pid.", - optarg); - } - break; - - case 'r': - m_option_data.m_repl = true; - if (optarg && optarg[0]) - m_option_data.m_repl_options = optarg; - else - m_option_data.m_repl_options.clear(); - break; - - case 'R': - m_option_data.m_repl_lang = SBLanguageRuntime::GetLanguageTypeFromString (optarg); - if (m_option_data.m_repl_lang == eLanguageTypeUnknown) - { - error.SetErrorStringWithFormat ("Unrecognized language name: \"%s\"", optarg); - } - break; - - case 's': - m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterFile, true, error); - break; - case 'o': - m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterFile, false, error); - break; - case 'S': - m_option_data.AddInitialCommand(optarg, eCommandPlacementBeforeFile, true, error); - break; - case 'O': - m_option_data.AddInitialCommand(optarg, eCommandPlacementBeforeFile, false, error); - break; - default: - m_option_data.m_print_help = true; - error.SetErrorStringWithFormat ("unrecognized option %c", short_option); - break; - } - } - else - { - error.SetErrorStringWithFormat ("invalid option with value %i", val); - } - if (error.Fail()) - { - return error; - } + } } - } - - if (error.Fail() || m_option_data.m_print_help) - { - ShowUsage (out_fh, g_options, m_option_data); - exiting = true; - } - else if (m_option_data.m_print_version) - { - ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString()); - exiting = true; - } - else if (m_option_data.m_print_python_path) - { - SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath(); - if (python_file_spec.IsValid()) - { - char python_path[PATH_MAX]; - size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX); - if (num_chars < PATH_MAX) - { - ::fprintf (out_fh, "%s\n", python_path); - } - else - ::fprintf (out_fh, "<PATH TOO LONG>\n"); + } + + if (long_options_index >= 0) { + const int short_option = g_options[long_options_index].short_option; + + switch (short_option) { + case 'h': + m_option_data.m_print_help = true; + break; + + case 'v': + m_option_data.m_print_version = true; + break; + + case 'P': + m_option_data.m_print_python_path = true; + break; + + case 'b': + m_option_data.m_batch = true; + break; + + case 'c': { + SBFileSpec file(optarg); + if (file.Exists()) { + m_option_data.m_core_file = optarg; + } else + error.SetErrorStringWithFormat( + "file specified in --core (-c) option doesn't exist: '%s'", + optarg); + } break; + + case 'e': + m_option_data.m_use_external_editor = true; + break; + + case 'x': + m_debugger.SkipLLDBInitFiles(true); + m_debugger.SkipAppInitFiles(true); + break; + + case 'X': + m_debugger.SetUseColor(false); + break; + + case 'f': { + SBFileSpec file(optarg); + if (file.Exists()) { + m_option_data.m_args.push_back(optarg); + } else if (file.ResolveExecutableLocation()) { + char path[PATH_MAX]; + file.GetPath(path, sizeof(path)); + m_option_data.m_args.push_back(path); + } else + error.SetErrorStringWithFormat( + "file specified in --file (-f) option doesn't exist: '%s'", + optarg); + } break; + + case 'a': + if (!m_debugger.SetDefaultArchitecture(optarg)) + error.SetErrorStringWithFormat( + "invalid architecture in the -a or --arch option: '%s'", + optarg); + break; + + case 'l': + m_option_data.m_script_lang = m_debugger.GetScriptingLanguage(optarg); + break; + + case 'd': + m_option_data.m_debug_mode = true; + break; + + case 'Q': + m_option_data.m_source_quietly = true; + break; + + case 'K': + m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterCrash, + true, error); + break; + case 'k': + m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterCrash, + false, error); + break; + + case 'n': + m_option_data.m_process_name = optarg; + break; + + case 'w': + m_option_data.m_wait_for = true; + break; + + case 'p': { + char *remainder; + m_option_data.m_process_pid = strtol(optarg, &remainder, 0); + if (remainder == optarg || *remainder != '\0') + error.SetErrorStringWithFormat( + "Could not convert process PID: \"%s\" into a pid.", optarg); + } break; + + case 'r': + m_option_data.m_repl = true; + if (optarg && optarg[0]) + m_option_data.m_repl_options = optarg; + else + m_option_data.m_repl_options.clear(); + break; + + case 'R': + m_option_data.m_repl_lang = + SBLanguageRuntime::GetLanguageTypeFromString(optarg); + if (m_option_data.m_repl_lang == eLanguageTypeUnknown) { + error.SetErrorStringWithFormat("Unrecognized language name: \"%s\"", + optarg); + } + break; + + case 's': + m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterFile, + true, error); + break; + case 'o': + m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterFile, + false, error); + break; + case 'S': + m_option_data.AddInitialCommand(optarg, eCommandPlacementBeforeFile, + true, error); + break; + case 'O': + m_option_data.AddInitialCommand(optarg, eCommandPlacementBeforeFile, + false, error); + break; + default: + m_option_data.m_print_help = true; + error.SetErrorStringWithFormat("unrecognized option %c", + short_option); + break; } - else - ::fprintf (out_fh, "<COULD NOT FIND PATH>\n"); - exiting = true; + } else { + error.SetErrorStringWithFormat("invalid option with value %i", val); + } + if (error.Fail()) { + return error; + } } - else if (m_option_data.m_process_name.empty() && m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID) - { - // Any arguments that are left over after option parsing are for - // the program. If a file was specified with -f then the filename - // is already in the m_option_data.m_args array, and any remaining args - // are arguments for the inferior program. If no file was specified with - // -f, then what is left is the program name followed by any arguments. - - // Skip any options we consumed with getopt_long_only - argc -= optind; - argv += optind; - - if (argc > 0) - { - for (int arg_idx=0; arg_idx<argc; ++arg_idx) - { - const char *arg = argv[arg_idx]; - if (arg) - m_option_data.m_args.push_back (arg); - } - } - + } + + if (error.Fail() || m_option_data.m_print_help) { + ShowUsage(out_fh, g_options, m_option_data); + exiting = true; + } else if (m_option_data.m_print_version) { + ::fprintf(out_fh, "%s\n", m_debugger.GetVersionString()); + exiting = true; + } else if (m_option_data.m_print_python_path) { + SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath(); + if (python_file_spec.IsValid()) { + char python_path[PATH_MAX]; + size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX); + if (num_chars < PATH_MAX) { + ::fprintf(out_fh, "%s\n", python_path); + } else + ::fprintf(out_fh, "<PATH TOO LONG>\n"); + } else + ::fprintf(out_fh, "<COULD NOT FIND PATH>\n"); + exiting = true; + } else if (m_option_data.m_process_name.empty() && + m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID) { + // Any arguments that are left over after option parsing are for + // the program. If a file was specified with -f then the filename + // is already in the m_option_data.m_args array, and any remaining args + // are arguments for the inferior program. If no file was specified with + // -f, then what is left is the program name followed by any arguments. + + // Skip any options we consumed with getopt_long_only + argc -= optind; + argv += optind; + + if (argc > 0) { + for (int arg_idx = 0; arg_idx < argc; ++arg_idx) { + const char *arg = argv[arg_idx]; + if (arg) + m_option_data.m_args.push_back(arg); + } } - else - { - // Skip any options we consumed with getopt_long_only - argc -= optind; - //argv += optind; // Commented out to keep static analyzer happy - if (argc > 0) - ::fprintf (out_fh, "Warning: program arguments are ignored when attaching.\n"); - } + } else { + // Skip any options we consumed with getopt_long_only + argc -= optind; + // argv += optind; // Commented out to keep static analyzer happy - return error; + if (argc > 0) + ::fprintf(out_fh, + "Warning: program arguments are ignored when attaching.\n"); + } + + return error; } -static ::FILE * -PrepareCommandsForSourcing (const char *commands_data, size_t commands_size, int fds[2]) -{ - enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE +static ::FILE *PrepareCommandsForSourcing(const char *commands_data, + size_t commands_size, int fds[2]) { + enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE - ::FILE *commands_file = NULL; - fds[0] = -1; - fds[1] = -1; - int err = 0; + ::FILE *commands_file = NULL; + fds[0] = -1; + fds[1] = -1; + int err = 0; #ifdef _WIN32 - err = _pipe(fds, commands_size, O_BINARY); + err = _pipe(fds, commands_size, O_BINARY); #else - err = pipe(fds); + err = pipe(fds); #endif - if (err == 0) - { - ssize_t nrwr = write(fds[WRITE], commands_data, commands_size); - if (nrwr < 0) - { - fprintf(stderr, "error: write(%i, %p, %" PRIu64 ") failed (errno = %i) " - "when trying to open LLDB commands pipe\n", - fds[WRITE], static_cast<const void *>(commands_data), - static_cast<uint64_t>(commands_size), errno); - } - else if (static_cast<size_t>(nrwr) == commands_size) - { - // Close the write end of the pipe so when we give the read end to - // the debugger/command interpreter it will exit when it consumes all - // of the data + if (err == 0) { + ssize_t nrwr = write(fds[WRITE], commands_data, commands_size); + if (nrwr < 0) { + fprintf(stderr, "error: write(%i, %p, %" PRIu64 ") failed (errno = %i) " + "when trying to open LLDB commands pipe\n", + fds[WRITE], static_cast<const void *>(commands_data), + static_cast<uint64_t>(commands_size), errno); + } else if (static_cast<size_t>(nrwr) == commands_size) { +// Close the write end of the pipe so when we give the read end to +// the debugger/command interpreter it will exit when it consumes all +// of the data #ifdef _WIN32 - _close(fds[WRITE]); fds[WRITE] = -1; + _close(fds[WRITE]); + fds[WRITE] = -1; #else - close(fds[WRITE]); fds[WRITE] = -1; + close(fds[WRITE]); + fds[WRITE] = -1; #endif - // Now open the read file descriptor in a FILE * that we can give to - // the debugger as an input handle - commands_file = fdopen(fds[READ], "r"); - if (commands_file) - { - fds[READ] = -1; // The FILE * 'commands_file' now owns the read descriptor - // Hand ownership if the FILE * over to the debugger for "commands_file". - } - else - { - fprintf(stderr, - "error: fdopen(%i, \"r\") failed (errno = %i) when " + // Now open the read file descriptor in a FILE * that we can give to + // the debugger as an input handle + commands_file = fdopen(fds[READ], "r"); + if (commands_file) { + fds[READ] = + -1; // The FILE * 'commands_file' now owns the read descriptor + // Hand ownership if the FILE * over to the debugger for + // "commands_file". + } else { + fprintf(stderr, "error: fdopen(%i, \"r\") failed (errno = %i) when " "trying to open LLDB commands pipe\n", - fds[READ], errno); - } - } - } - else - { - fprintf(stderr, "error: can't create pipe file descriptors for LLDB commands\n"); + fds[READ], errno); + } } + } else { + fprintf(stderr, + "error: can't create pipe file descriptors for LLDB commands\n"); + } - return commands_file; + return commands_file; } -void -CleanupAfterCommandSourcing (int fds[2]) -{ - enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE +void CleanupAfterCommandSourcing(int fds[2]) { + enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE - // Close any pipes that we still have ownership of - if ( fds[WRITE] != -1) - { + // Close any pipes that we still have ownership of + if (fds[WRITE] != -1) { #ifdef _WIN32 - _close(fds[WRITE]); fds[WRITE] = -1; + _close(fds[WRITE]); + fds[WRITE] = -1; #else - close(fds[WRITE]); fds[WRITE] = -1; + close(fds[WRITE]); + fds[WRITE] = -1; #endif - - } + } - if ( fds[READ] != -1) - { + if (fds[READ] != -1) { #ifdef _WIN32 - _close(fds[READ]); fds[READ] = -1; + _close(fds[READ]); + fds[READ] = -1; #else - close(fds[READ]); fds[READ] = -1; + close(fds[READ]); + fds[READ] = -1; #endif - } - + } } -std::string -EscapeString (std::string arg) -{ - std::string::size_type pos = 0; - while ((pos = arg.find_first_of("\"\\", pos)) != std::string::npos) - { - arg.insert (pos, 1, '\\'); - pos += 2; - } - return '"' + arg + '"'; +std::string EscapeString(std::string arg) { + std::string::size_type pos = 0; + while ((pos = arg.find_first_of("\"\\", pos)) != std::string::npos) { + arg.insert(pos, 1, '\\'); + pos += 2; + } + return '"' + arg + '"'; } -void -Driver::MainLoop () -{ - if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0) - { - g_old_stdin_termios_is_valid = true; - atexit (reset_stdin_termios); - } +void Driver::MainLoop() { + if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0) { + g_old_stdin_termios_is_valid = true; + atexit(reset_stdin_termios); + } #ifndef _MSC_VER - // Disabling stdin buffering with MSVC's 2015 CRT exposes a bug in fgets - // which causes it to miss newlines depending on whether there have been an - // odd or even number of characters. Bug has been reported to MS via Connect. - ::setbuf (stdin, NULL); + // Disabling stdin buffering with MSVC's 2015 CRT exposes a bug in fgets + // which causes it to miss newlines depending on whether there have been an + // odd or even number of characters. Bug has been reported to MS via Connect. + ::setbuf(stdin, NULL); #endif - ::setbuf (stdout, NULL); - - m_debugger.SetErrorFileHandle (stderr, false); - m_debugger.SetOutputFileHandle (stdout, false); - m_debugger.SetInputFileHandle (stdin, false); // Don't take ownership of STDIN yet... - - m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor); + ::setbuf(stdout, NULL); + + m_debugger.SetErrorFileHandle(stderr, false); + m_debugger.SetOutputFileHandle(stdout, false); + m_debugger.SetInputFileHandle(stdin, + false); // Don't take ownership of STDIN yet... + + m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor); + + struct winsize window_size; + if (isatty(STDIN_FILENO) && + ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) { + if (window_size.ws_col > 0) + m_debugger.SetTerminalWidth(window_size.ws_col); + } + + SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter(); + + // Before we handle any options from the command line, we parse the + // .lldbinit file in the user's home directory. + SBCommandReturnObject result; + sb_interpreter.SourceInitFileInHomeDirectory(result); + if (GetDebugMode()) { + result.PutError(m_debugger.GetErrorFileHandle()); + result.PutOutput(m_debugger.GetOutputFileHandle()); + } + + // Now we handle options we got from the command line + SBStream commands_stream; + + // First source in the commands specified to be run before the file arguments + // are processed. + WriteCommandsForSourcing(eCommandPlacementBeforeFile, commands_stream); + + const size_t num_args = m_option_data.m_args.size(); + if (num_args > 0) { + char arch_name[64]; + if (m_debugger.GetDefaultArchitecture(arch_name, sizeof(arch_name))) + commands_stream.Printf("target create --arch=%s %s", arch_name, + EscapeString(m_option_data.m_args[0]).c_str()); + else + commands_stream.Printf("target create %s", + EscapeString(m_option_data.m_args[0]).c_str()); - struct winsize window_size; - if (isatty (STDIN_FILENO) - && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) - { - if (window_size.ws_col > 0) - m_debugger.SetTerminalWidth (window_size.ws_col); + if (!m_option_data.m_core_file.empty()) { + commands_stream.Printf(" --core %s", + EscapeString(m_option_data.m_core_file).c_str()); } - - SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter(); - - // Before we handle any options from the command line, we parse the - // .lldbinit file in the user's home directory. - SBCommandReturnObject result; - sb_interpreter.SourceInitFileInHomeDirectory(result); - if (GetDebugMode()) - { - result.PutError (m_debugger.GetErrorFileHandle()); - result.PutOutput (m_debugger.GetOutputFileHandle()); + commands_stream.Printf("\n"); + + if (num_args > 1) { + commands_stream.Printf("settings set -- target.run-args "); + for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx) + commands_stream.Printf( + " %s", EscapeString(m_option_data.m_args[arg_idx]).c_str()); + commands_stream.Printf("\n"); } - - // Now we handle options we got from the command line - SBStream commands_stream; - - // First source in the commands specified to be run before the file arguments are processed. - WriteCommandsForSourcing (eCommandPlacementBeforeFile, commands_stream); - - const size_t num_args = m_option_data.m_args.size(); - if (num_args > 0) - { - char arch_name[64]; - if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name))) - commands_stream.Printf("target create --arch=%s %s", arch_name, EscapeString(m_option_data.m_args[0]).c_str()); - else - commands_stream.Printf("target create %s", EscapeString(m_option_data.m_args[0]).c_str()); - - if (!m_option_data.m_core_file.empty()) - { - commands_stream.Printf(" --core %s", EscapeString(m_option_data.m_core_file).c_str()); - } - commands_stream.Printf("\n"); - - if (num_args > 1) - { - commands_stream.Printf ("settings set -- target.run-args "); - for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx) - commands_stream.Printf(" %s", EscapeString(m_option_data.m_args[arg_idx]).c_str()); - commands_stream.Printf("\n"); - } - } - else if (!m_option_data.m_core_file.empty()) - { - commands_stream.Printf("target create --core %s\n", EscapeString(m_option_data.m_core_file).c_str()); + } else if (!m_option_data.m_core_file.empty()) { + commands_stream.Printf("target create --core %s\n", + EscapeString(m_option_data.m_core_file).c_str()); + } else if (!m_option_data.m_process_name.empty()) { + commands_stream.Printf("process attach --name %s", + EscapeString(m_option_data.m_process_name).c_str()); + + if (m_option_data.m_wait_for) + commands_stream.Printf(" --waitfor"); + + commands_stream.Printf("\n"); + + } else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid) { + commands_stream.Printf("process attach --pid %" PRIu64 "\n", + m_option_data.m_process_pid); + } + + WriteCommandsForSourcing(eCommandPlacementAfterFile, commands_stream); + + if (GetDebugMode()) { + result.PutError(m_debugger.GetErrorFileHandle()); + result.PutOutput(m_debugger.GetOutputFileHandle()); + } + + bool handle_events = true; + bool spawn_thread = false; + + if (m_option_data.m_repl) { + const char *repl_options = NULL; + if (!m_option_data.m_repl_options.empty()) + repl_options = m_option_data.m_repl_options.c_str(); + SBError error(m_debugger.RunREPL(m_option_data.m_repl_lang, repl_options)); + if (error.Fail()) { + const char *error_cstr = error.GetCString(); + if (error_cstr && error_cstr[0]) + fprintf(stderr, "error: %s\n", error_cstr); + else + fprintf(stderr, "error: %u\n", error.GetError()); } - else if (!m_option_data.m_process_name.empty()) - { - commands_stream.Printf ("process attach --name %s", EscapeString(m_option_data.m_process_name).c_str()); - - if (m_option_data.m_wait_for) - commands_stream.Printf(" --waitfor"); + } else { + // Check if we have any data in the commands stream, and if so, save it to a + // temp file + // so we can then run the command interpreter using the file contents. + const char *commands_data = commands_stream.GetData(); + const size_t commands_size = commands_stream.GetSize(); + + // The command file might have requested that we quit, this variable will + // track that. + bool quit_requested = false; + bool stopped_for_crash = false; + if (commands_data && commands_size) { + int initial_commands_fds[2]; + bool success = true; + FILE *commands_file = PrepareCommandsForSourcing( + commands_data, commands_size, initial_commands_fds); + if (commands_file) { + m_debugger.SetInputFileHandle(commands_file, true); + + // Set the debugger into Sync mode when running the command file. + // Otherwise command files + // that run the target won't run in a sensible way. + bool old_async = m_debugger.GetAsync(); + m_debugger.SetAsync(false); + int num_errors; + + SBCommandInterpreterRunOptions options; + options.SetStopOnError(true); + if (m_option_data.m_batch) + options.SetStopOnCrash(true); + + m_debugger.RunCommandInterpreter(handle_events, spawn_thread, options, + num_errors, quit_requested, + stopped_for_crash); + + if (m_option_data.m_batch && stopped_for_crash && + !m_option_data.m_after_crash_commands.empty()) { + int crash_command_fds[2]; + SBStream crash_commands_stream; + WriteCommandsForSourcing(eCommandPlacementAfterCrash, + crash_commands_stream); + const char *crash_commands_data = crash_commands_stream.GetData(); + const size_t crash_commands_size = crash_commands_stream.GetSize(); + commands_file = PrepareCommandsForSourcing( + crash_commands_data, crash_commands_size, crash_command_fds); + if (commands_file) { + bool local_quit_requested; + bool local_stopped_for_crash; + m_debugger.SetInputFileHandle(commands_file, true); + + m_debugger.RunCommandInterpreter( + handle_events, spawn_thread, options, num_errors, + local_quit_requested, local_stopped_for_crash); + if (local_quit_requested) + quit_requested = true; + } + } + m_debugger.SetAsync(old_async); + } else + success = false; - commands_stream.Printf("\n"); + // Close any pipes that we still have ownership of + CleanupAfterCommandSourcing(initial_commands_fds); - } - else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid) - { - commands_stream.Printf ("process attach --pid %" PRIu64 "\n", m_option_data.m_process_pid); + // Something went wrong with command pipe + if (!success) { + exit(1); + } } - WriteCommandsForSourcing(eCommandPlacementAfterFile, commands_stream); - - if (GetDebugMode()) - { - result.PutError(m_debugger.GetErrorFileHandle()); - result.PutOutput(m_debugger.GetOutputFileHandle()); - } - - bool handle_events = true; - bool spawn_thread = false; - - if (m_option_data.m_repl) - { - const char *repl_options = NULL; - if (!m_option_data.m_repl_options.empty()) - repl_options = m_option_data.m_repl_options.c_str(); - SBError error (m_debugger.RunREPL(m_option_data.m_repl_lang, repl_options)); - if (error.Fail()) - { - const char *error_cstr = error.GetCString(); - if (error_cstr && error_cstr[0]) - fprintf (stderr, "error: %s\n", error_cstr); - else - fprintf (stderr, "error: %u\n", error.GetError()); - } - } - else - { - // Check if we have any data in the commands stream, and if so, save it to a temp file - // so we can then run the command interpreter using the file contents. - const char *commands_data = commands_stream.GetData(); - const size_t commands_size = commands_stream.GetSize(); - - // The command file might have requested that we quit, this variable will track that. - bool quit_requested = false; - bool stopped_for_crash = false; - if (commands_data && commands_size) - { - int initial_commands_fds[2]; - bool success = true; - FILE *commands_file = PrepareCommandsForSourcing (commands_data, commands_size, initial_commands_fds); - if (commands_file) - { - m_debugger.SetInputFileHandle (commands_file, true); - - // Set the debugger into Sync mode when running the command file. Otherwise command files - // that run the target won't run in a sensible way. - bool old_async = m_debugger.GetAsync(); - m_debugger.SetAsync(false); - int num_errors; - - SBCommandInterpreterRunOptions options; - options.SetStopOnError (true); - if (m_option_data.m_batch) - options.SetStopOnCrash (true); - - m_debugger.RunCommandInterpreter(handle_events, - spawn_thread, - options, - num_errors, - quit_requested, - stopped_for_crash); - - if (m_option_data.m_batch && stopped_for_crash && !m_option_data.m_after_crash_commands.empty()) - { - int crash_command_fds[2]; - SBStream crash_commands_stream; - WriteCommandsForSourcing (eCommandPlacementAfterCrash, crash_commands_stream); - const char *crash_commands_data = crash_commands_stream.GetData(); - const size_t crash_commands_size = crash_commands_stream.GetSize(); - commands_file = PrepareCommandsForSourcing (crash_commands_data, crash_commands_size, crash_command_fds); - if (commands_file) - { - bool local_quit_requested; - bool local_stopped_for_crash; - m_debugger.SetInputFileHandle (commands_file, true); - - m_debugger.RunCommandInterpreter(handle_events, - spawn_thread, - options, - num_errors, - local_quit_requested, - local_stopped_for_crash); - if (local_quit_requested) - quit_requested = true; - - } - } - m_debugger.SetAsync(old_async); - } - else - success = false; - - // Close any pipes that we still have ownership of - CleanupAfterCommandSourcing(initial_commands_fds); - - // Something went wrong with command pipe - if (!success) - { - exit(1); - } + // Now set the input file handle to STDIN and run the command + // interpreter again in interactive mode and let the debugger + // take ownership of stdin - } + bool go_interactive = true; + if (quit_requested) + go_interactive = false; + else if (m_option_data.m_batch && !stopped_for_crash) + go_interactive = false; - // Now set the input file handle to STDIN and run the command - // interpreter again in interactive mode and let the debugger - // take ownership of stdin + if (go_interactive) { + m_debugger.SetInputFileHandle(stdin, true); + m_debugger.RunCommandInterpreter(handle_events, spawn_thread); + } + } - bool go_interactive = true; - if (quit_requested) - go_interactive = false; - else if (m_option_data.m_batch && !stopped_for_crash) - go_interactive = false; + reset_stdin_termios(); + fclose(stdin); - if (go_interactive) - { - m_debugger.SetInputFileHandle (stdin, true); - m_debugger.RunCommandInterpreter(handle_events, spawn_thread); - } - } - - reset_stdin_termios(); - fclose (stdin); - - SBDebugger::Destroy (m_debugger); + SBDebugger::Destroy(m_debugger); } - -void -Driver::ResizeWindow (unsigned short col) -{ - GetDebugger().SetTerminalWidth (col); +void Driver::ResizeWindow(unsigned short col) { + GetDebugger().SetTerminalWidth(col); } -void -sigwinch_handler (int signo) -{ - struct winsize window_size; - if (isatty (STDIN_FILENO) - && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) - { - if ((window_size.ws_col > 0) && g_driver != NULL) - { - g_driver->ResizeWindow (window_size.ws_col); - } +void sigwinch_handler(int signo) { + struct winsize window_size; + if (isatty(STDIN_FILENO) && + ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) { + if ((window_size.ws_col > 0) && g_driver != NULL) { + g_driver->ResizeWindow(window_size.ws_col); } + } } -void -sigint_handler (int signo) -{ - static bool g_interrupt_sent = false; - if (g_driver) - { - if (!g_interrupt_sent) - { - g_interrupt_sent = true; - g_driver->GetDebugger().DispatchInputInterrupt(); - g_interrupt_sent = false; - return; - } - } - - exit (signo); +void sigint_handler(int signo) { + static bool g_interrupt_sent = false; + if (g_driver) { + if (!g_interrupt_sent) { + g_interrupt_sent = true; + g_driver->GetDebugger().DispatchInputInterrupt(); + g_interrupt_sent = false; + return; + } + } + + exit(signo); } -void -sigtstp_handler (int signo) -{ - if (g_driver) - g_driver->GetDebugger().SaveInputTerminalState(); +void sigtstp_handler(int signo) { + if (g_driver) + g_driver->GetDebugger().SaveInputTerminalState(); - signal (signo, SIG_DFL); - kill (getpid(), signo); - signal (signo, sigtstp_handler); + signal(signo, SIG_DFL); + kill(getpid(), signo); + signal(signo, sigtstp_handler); } -void -sigcont_handler (int signo) -{ - if (g_driver) - g_driver->GetDebugger().RestoreInputTerminalState(); +void sigcont_handler(int signo) { + if (g_driver) + g_driver->GetDebugger().RestoreInputTerminalState(); - signal (signo, SIG_DFL); - kill (getpid(), signo); - signal (signo, sigcont_handler); + signal(signo, SIG_DFL); + kill(getpid(), signo); + signal(signo, sigcont_handler); } int @@ -1315,48 +1217,44 @@ main(int argc, char const *argv[]) #endif { #ifdef _WIN32 - // Convert wide arguments to UTF-8 - std::vector<std::string> argvStrings(argc); - std::vector<const char *> argvPointers(argc); - for (int i = 0; i != argc; ++i) - { - llvm::convertWideToUTF8(wargv[i], argvStrings[i]); - argvPointers[i] = argvStrings[i].c_str(); - } - const char **argv = argvPointers.data(); + // Convert wide arguments to UTF-8 + std::vector<std::string> argvStrings(argc); + std::vector<const char *> argvPointers(argc); + for (int i = 0; i != argc; ++i) { + llvm::convertWideToUTF8(wargv[i], argvStrings[i]); + argvPointers[i] = argvStrings[i].c_str(); + } + const char **argv = argvPointers.data(); #endif - SBDebugger::Initialize(); + SBDebugger::Initialize(); - SBHostOS::ThreadCreated("<lldb.driver.main-thread>"); + SBHostOS::ThreadCreated("<lldb.driver.main-thread>"); - signal(SIGINT, sigint_handler); + signal(SIGINT, sigint_handler); #if !defined(_MSC_VER) - signal(SIGPIPE, SIG_IGN); - signal(SIGWINCH, sigwinch_handler); - signal(SIGTSTP, sigtstp_handler); - signal(SIGCONT, sigcont_handler); + signal(SIGPIPE, SIG_IGN); + signal(SIGWINCH, sigwinch_handler); + signal(SIGTSTP, sigtstp_handler); + signal(SIGCONT, sigcont_handler); #endif - // Create a scope for driver so that the driver object will destroy itself - // before SBDebugger::Terminate() is called. - { - Driver driver; - - bool exiting = false; - SBError error(driver.ParseArgs(argc, argv, stdout, exiting)); - if (error.Fail()) - { - const char *error_cstr = error.GetCString(); - if (error_cstr) - ::fprintf(stderr, "error: %s\n", error_cstr); - } - else if (!exiting) - { - driver.MainLoop(); - } - } + // Create a scope for driver so that the driver object will destroy itself + // before SBDebugger::Terminate() is called. + { + Driver driver; + + bool exiting = false; + SBError error(driver.ParseArgs(argc, argv, stdout, exiting)); + if (error.Fail()) { + const char *error_cstr = error.GetCString(); + if (error_cstr) + ::fprintf(stderr, "error: %s\n", error_cstr); + } else if (!exiting) { + driver.MainLoop(); + } + } - SBDebugger::Terminate(); - return 0; + SBDebugger::Terminate(); + return 0; } |