Fixed line wrapping for the "long help" content in LLDB commands. Content is now dynamically wrapped for the column width of the current terminal. Lines that begin with whitespace will be indented identically on subsequent lines to maintain formatting.

Existing commands supplying this type of help content have been reworked to take advantage of the changes.  In addition to formatting changes, content was changes for accuracy and clarity purposes.
    
<rdar://problem/21269977>

llvm-svn: 242122
This commit is contained in:
Kate Stone 2015-07-14 05:48:36 +00:00
parent 2ffb36e829
commit ea671fbdff
13 changed files with 590 additions and 532 deletions

View File

@ -160,6 +160,9 @@ public:
{ {
} }
void
FormatLongHelpText (Stream &output_strm, const char *long_help);
void void
GenerateHelpText (CommandReturnObject &result); GenerateHelpText (CommandReturnObject &result);

View File

@ -23,10 +23,10 @@
</BuildActionEntries> </BuildActionEntries>
</BuildAction> </BuildAction>
<TestAction <TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
shouldUseLaunchSchemeArgsEnv = "YES" shouldUseLaunchSchemeArgsEnv = "YES">
buildConfiguration = "Debug">
<Testables> <Testables>
</Testables> </Testables>
<MacroExpansion> <MacroExpansion>
@ -45,19 +45,23 @@
isEnabled = "YES"> isEnabled = "YES">
</EnvironmentVariable> </EnvironmentVariable>
</EnvironmentVariables> </EnvironmentVariables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
displayScaleIsEnabled = "NO" displayScaleIsEnabled = "NO"
displayScale = "1.00" displayScale = "1.00"
launchStyle = "0" launchStyle = "0"
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES" debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"> allowLocationSimulation = "YES">
<BuildableProductRunnable> <BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "26F5C26910F3D9A4009D5894" BlueprintIdentifier = "26F5C26910F3D9A4009D5894"
@ -79,10 +83,10 @@
<ProfileAction <ProfileAction
displayScaleIsEnabled = "NO" displayScaleIsEnabled = "NO"
displayScale = "1.00" displayScale = "1.00"
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES" shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = "" savedToolIdentifier = ""
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES"> debugDocumentVersioning = "YES">
<EnvironmentVariables> <EnvironmentVariables>
<EnvironmentVariable <EnvironmentVariable

View File

@ -1249,27 +1249,27 @@ public:
CommandObjectBreakpointDisable (CommandInterpreter &interpreter) : CommandObjectBreakpointDisable (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter, CommandObjectParsed (interpreter,
"breakpoint disable", "breakpoint disable",
"Disable the specified breakpoint(s) without removing it/them. If no breakpoints are specified, disable them all.", "Disable the specified breakpoint(s) without removing them. If none are specified, disable all breakpoints.",
NULL) NULL)
{ {
SetHelpLong( SetHelpLong(
"Disable the specified breakpoint(s) without removing it/them. \n\ "Disable the specified breakpoint(s) without removing them. \
If no breakpoints are specified, disable them all.\n\ If none are specified, disable all breakpoints." R"(
\n\
Note: disabling a breakpoint will cause none of its locations to be hit\n\ )" "Note: disabling a breakpoint will cause none of its locations to be hit \
regardless of whether they are enabled or disabled. So the sequence: \n\ regardless of whether they are enabled or disabled. After the sequence:" R"(
\n\
(lldb) break disable 1\n\ (lldb) break disable 1
(lldb) break enable 1.1\n\ (lldb) break enable 1.1
\n\
will NOT cause location 1.1 to get hit. To achieve that, do:\n\ execution will NOT stop at location 1.1. To achieve that, type:
\n\
(lldb) break disable 1.*\n\ (lldb) break disable 1.*
(lldb) break enable 1.1\n\ (lldb) break enable 1.1
\n\
The first command disables all the locations of breakpoint 1, \n\ )" "The first command disables all the locations of breakpoint 1, \
the second re-enables the first location." the second re-enables the first location."
); );
CommandArgumentEntry arg; CommandArgumentEntry arg;
CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange); CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange);

View File

@ -49,143 +49,120 @@ public:
m_options (interpreter) m_options (interpreter)
{ {
SetHelpLong ( SetHelpLong (
"\nGeneral information about entering breakpoint commands\n\ R"(
------------------------------------------------------\n\ General information about entering breakpoint commands
\n\ ------------------------------------------------------
This command will cause you to be prompted to enter the command or set of\n\
commands you wish to be executed when the specified breakpoint is hit. You\n\ )" "This command will prompt for commands to be executed when the specified \
will be told to enter your command(s), and will see a '> 'prompt. Because\n\ breakpoint is hit. Each command is typed on its own line following the '> ' \
you can enter one or many commands to be executed when a breakpoint is hit,\n\ prompt until 'DONE' is entered." R"(
you will continue to be prompted after each new-line that you enter, until you\n\
enter the word 'DONE', which will cause the commands you have entered to be\n\ )" "Syntactic errors may not be detected when initially entered, and many \
stored with the breakpoint and executed when the breakpoint is hit.\n\ malformed commands can silently fail when executed. If your breakpoint commands \
\n\ do not appear to be executing, double-check the command syntax." R"(
Syntax checking is not necessarily done when breakpoint commands are entered.\n\
An improperly written breakpoint command will attempt to get executed when the\n\ )" "Note: You may enter any debugger command exactly as you would at the debugger \
breakpoint gets hit, and usually silently fail. If your breakpoint command does\n\ prompt. There is no limit to the number of commands supplied, but do NOT enter \
not appear to be getting executed, go back and check your syntax.\n\ more than one command per line." R"(
\n\
Special information about PYTHON breakpoint commands\n\ Special information about PYTHON breakpoint commands
----------------------------------------------------\n\ ----------------------------------------------------
\n\
You may enter either one line of Python, multiple lines of Python (including\n\ )" "You may enter either one or more lines of Python, including function \
function definitions), or specify a Python function in a module that has already,\n\ definitions or calls to functions that will have been imported by the time \
or will be imported. If you enter a single line of Python, that will be passed\n\ the code executes. Single line breakpoint commands will be interpreted 'as is' \
to the Python interpreter 'as is' when the breakpoint gets hit. If you enter\n\ when the breakpoint is hit. Multiple lines of Python will be wrapped in a \
function definitions, they will be passed to the Python interpreter as soon as\n\ generated function, and a call to the function will be attached to the breakpoint." R"(
you finish entering the breakpoint command, and they can be called later (don't\n\
forget to add calls to them, if you want them called when the breakpoint is\n\ This auto-generated function is passed in three arguments:
hit). If you enter multiple lines of Python that are not function definitions,\n\
they will be collected into a new, automatically generated Python function, and\n\ frame: an lldb.SBFrame object for the frame which hit breakpoint.
a call to the newly generated function will be attached to the breakpoint.\n\
\n\ bp_loc: an lldb.SBBreakpointLocation object that represents the breakpoint location that was hit.
\n\
This auto-generated function is passed in three arguments:\n\ dict: the python session dictionary hit.
\n\
frame: a lldb.SBFrame object for the frame which hit breakpoint.\n\ )" "When specifying a python function with the --python-function option, you need \
bp_loc: a lldb.SBBreakpointLocation object that represents the breakpoint\n\ to supply the function name prepended by the module name:" R"(
location that was hit.\n\
dict: the python session dictionary hit.\n\ --python-function myutils.breakpoint_callback
\n\
When specifying a python function with the --python-function option, you need\n\ The function itself must have the following prototype:
to supply the function name prepended by the module name. So if you import a\n\
module named 'myutils' that contains a 'breakpoint_callback' function, you would\n\ def breakpoint_callback(frame, bp_loc, dict):
specify the option as:\n\ # Your code goes here
\n\
--python-function myutils.breakpoint_callback\n\ )" "The arguments are the same as the arguments passed to generated functions as \
\n\ described above. Note that the global variable 'lldb.frame' will NOT be updated when \
The function itself must have the following prototype:\n\ this function is called, so be sure to use the 'frame' argument. The 'frame' argument \
\n\ can get you to the thread via frame.GetThread(), the thread can get you to the \
def breakpoint_callback(frame, bp_loc, dict):\n\ process via thread.GetProcess(), and the process can get you back to the target \
# Your code goes here\n\ via process.GetTarget()." R"(
\n\
The arguments are the same as the 3 auto generation function arguments listed\n\ )" "Important Note: As Python code gets collected into functions, access to global \
above. Note that the global variable 'lldb.frame' will NOT be setup when this\n\ variables requires explicit scoping using the 'global' keyword. Be sure to use correct \
function is called, so be sure to use the 'frame' argument. The 'frame' argument\n\ Python syntax, including indentation, when entering Python breakpoint commands." R"(
can get you to the thread (frame.GetThread()), the thread can get you to the\n\
process (thread.GetProcess()), and the process can get you back to the target\n\ Example Python one-line breakpoint command:
(process.GetTarget()).\n\
\n\ (lldb) breakpoint command add -s python 1
Important Note: Because loose Python code gets collected into functions, if you\n\ Enter your Python command(s). Type 'DONE' to end.
want to access global variables in the 'loose' code, you need to specify that\n\ > print "Hit this breakpoint!"
they are global, using the 'global' keyword. Be sure to use correct Python\n\ > DONE
syntax, including indentation, when entering Python breakpoint commands.\n\
\n\ As a convenience, this also works for a short Python one-liner:
As a third option, you can pass the name of an already existing Python function\n\
and that function will be attached to the breakpoint. It will get passed the\n\ (lldb) breakpoint command add -s python 1 -o 'import time; print time.asctime()'
frame and bp_loc arguments mentioned above.\n\ (lldb) run
\n\ Launching '.../a.out' (x86_64)
Example Python one-line breakpoint command:\n\ (lldb) Fri Sep 10 12:17:45 2010
\n\ Process 21778 Stopped
(lldb) breakpoint command add -s python 1\n\ * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread
Enter your Python command(s). Type 'DONE' to end.\n\ 36
> print \"Hit this breakpoint!\"\n\ 37 int c(int val)
> DONE\n\ 38 {
\n\ 39 -> return val + 3;
As a convenience, this also works for a short Python one-liner:\n\ 40 }
(lldb) breakpoint command add -s python 1 -o \"import time; print time.asctime()\"\n\ 41
(lldb) run\n\ 42 int main (int argc, char const *argv[])
Launching '.../a.out' (x86_64)\n\
(lldb) Fri Sep 10 12:17:45 2010\n\ Example multiple line Python breakpoint command:
Process 21778 Stopped\n\
* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread\n\ (lldb) breakpoint command add -s p 1
36 \n\ Enter your Python command(s). Type 'DONE' to end.
37 int c(int val)\n\ > global bp_count
38 {\n\ > bp_count = bp_count + 1
39 -> return val + 3;\n\ > print "Hit this breakpoint " + repr(bp_count) + " times!"
40 }\n\ > DONE
41 \n\
42 int main (int argc, char const *argv[])\n\ Example multiple line Python breakpoint command, using function definition:
(lldb)\n\
\n\ (lldb) breakpoint command add -s python 1
Example multiple line Python breakpoint command, using function definition:\n\ Enter your Python command(s). Type 'DONE' to end.
\n\ > def breakpoint_output (bp_no):
(lldb) breakpoint command add -s python 1\n\ > out_string = "Hit breakpoint number " + repr (bp_no)
Enter your Python command(s). Type 'DONE' to end.\n\ > print out_string
> def breakpoint_output (bp_no):\n\ > return True
> out_string = \"Hit breakpoint number \" + repr (bp_no)\n\ > breakpoint_output (1)
> print out_string\n\ > DONE
> return True\n\
> breakpoint_output (1)\n\ )" "In this case, since there is a reference to a global variable, \
> DONE\n\ 'bp_count', you will also need to make sure 'bp_count' exists and is \
\n\ initialized:" R"(
\n\
Example multiple line Python breakpoint command, using 'loose' Python:\n\ (lldb) script
\n\ >>> bp_count = 0
(lldb) breakpoint command add -s p 1\n\ >>> quit()
Enter your Python command(s). Type 'DONE' to end.\n\
> global bp_count\n\ )" "Your Python code, however organized, can optionally return a value. \
> bp_count = bp_count + 1\n\ If the returned value is False, that tells LLDB not to stop at the breakpoint \
> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\"\n\ to which the code is associated. Returning anything other than False, or even \
> DONE\n\ returning None, or even omitting a return statement entirely, will cause \
\n\ LLDB to stop." R"(
In this case, since there is a reference to a global variable,\n\
'bp_count', you will also need to make sure 'bp_count' exists and is\n\ )" "Final Note: A warning that no breakpoint command was generated when there \
initialized:\n\ are no syntax errors may indicate that a function was declared but never called."
\n\ );
(lldb) script\n\
>>> bp_count = 0\n\
>>> quit()\n\
\n\
(lldb)\n\
\n\
\n\
Your Python code, however organized, can optionally return a value.\n\
If the returned value is False, that tells LLDB not to stop at the breakpoint\n\
to which the code is associated. Returning anything other than False, or even\n\
returning None, or even omitting a return statement entirely, will cause\n\
LLDB to stop.\n\
\n\
Final Note: If you get a warning that no breakpoint command was generated, but\n\
you did not get any syntax errors, you probably forgot to add a call to your\n\
functions.\n\
\n\
Special information about debugger command breakpoint commands\n\
--------------------------------------------------------------\n\
\n\
You may enter any debugger command, exactly as you would at the debugger prompt.\n\
You may enter as many debugger commands as you like, but do NOT enter more than\n\
one command per line.\n" );
CommandArgumentEntry arg; CommandArgumentEntry arg;
CommandArgumentData bp_id_arg; CommandArgumentData bp_id_arg;

View File

@ -450,60 +450,74 @@ public:
NULL) NULL)
{ {
SetHelpLong( SetHelpLong(
"'alias' allows the user to create a short-cut or abbreviation for long \n\ "'alias' allows the user to create a short-cut or abbreviation for long \
commands, multi-word commands, and commands that take particular options. \n\ commands, multi-word commands, and commands that take particular options. \
Below are some simple examples of how one might use the 'alias' command: \n\ Below are some simple examples of how one might use the 'alias' command:" R"(
\n 'command alias sc script' // Creates the abbreviation 'sc' for the 'script' \n\
// command. \n\ (lldb) command alias sc script
'command alias bp breakpoint' // Creates the abbreviation 'bp' for the 'breakpoint' \n\
// command. Since breakpoint commands are two-word \n\ Creates the abbreviation 'sc' for the 'script' command.
// commands, the user will still need to enter the \n\
// second word after 'bp', e.g. 'bp enable' or \n\ (lldb) command alias bp breakpoint
// 'bp delete'. \n\
'command alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\ )" " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \
// two-word command 'breakpoint list'. \n\ breakpoint commands are two-word commands, the user would still need to \
\nAn alias can include some options for the command, with the values either \n\ enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'." R"(
filled in at the time the alias is created, or specified as positional \n\
arguments, to be filled in when the alias is invoked. The following example \n\ (lldb) command alias bpl breakpoint list
shows how to create aliases with options: \n\
\n\ Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
'command alias bfl breakpoint set -f %1 -l %2' \n\
\nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\ )" "An alias can include some options for the command, with the values either \
options already part of the alias. So if the user wants to set a breakpoint \n\ filled in at the time the alias is created, or specified as positional \
by file and line without explicitly having to use the -f and -l options, the \n\ arguments, to be filled in when the alias is invoked. The following example \
user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \n\ shows how to create aliases with options:" R"(
for the actual arguments that will be passed when the alias command is used. \n\
The number in the placeholder refers to the position/order the actual value \n\ (lldb) command alias bfl breakpoint set -f %1 -l %2
occupies when the alias is used. All the occurrences of '%1' in the alias \n\
will be replaced with the first argument, all the occurrences of '%2' in the \n\ )" " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
alias will be replaced with the second argument, and so on. This also allows \n\ options already part of the alias. So if the user wants to set a breakpoint \
actual arguments to be used multiple times within an alias (see 'process \n\ by file and line without explicitly having to use the -f and -l options, the \
launch' example below). \n\ user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \
Note: the positional arguments must substitute as whole words in the resultant\n\ for the actual arguments that will be passed when the alias command is used. \
command, so you can't at present do something like:\n\ The number in the placeholder refers to the position/order the actual value \
\n\ occupies when the alias is used. All the occurrences of '%1' in the alias \
command alias bcppfl breakpoint set -f %1.cpp -l %2\n\ will be replaced with the first argument, all the occurrences of '%2' in the \
\n\ alias will be replaced with the second argument, and so on. This also allows \
to get the file extension \".cpp\" automatically appended. For more complex\n\ actual arguments to be used multiple times within an alias (see 'process \
aliasing, use the \"command regex\" command instead.\n\ launch' example below)." R"(
\nSo in the 'bfl' case, the actual file value will be \n\
filled in with the first argument following 'bfl' and the actual line number \n\ )" "Note: the positional arguments must substitute as whole words in the resultant \
value will be filled in with the second argument. The user would use this \n\ command, so you can't at present do something like this to append the file extension \
alias as follows: \n\ \".cpp\":" R"(
\n (lldb) command alias bfl breakpoint set -f %1 -l %2 \n\
<... some time later ...> \n\ (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
(lldb) bfl my-file.c 137 \n\
\nThis would be the same as if the user had entered \n\ )" "For more complex aliasing, use the \"command regex\" command instead. In the \
'breakpoint set -f my-file.c -l 137'. \n\ 'bfl' case above, the actual file value will be filled in with the first argument \
\nAnother example: \n\ following 'bfl' and the actual line number value will be filled in with the second \
\n (lldb) command alias pltty process launch -s -o %1 -e %1 \n\ argument. The user would use this alias as follows:" R"(
(lldb) pltty /dev/tty0 \n\
// becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\ (lldb) command alias bfl breakpoint set -f %1 -l %2
\nIf the user always wanted to pass the same value to a particular option, the \n\ (lldb) bfl my-file.c 137
alias could be defined with that value directly in the alias as a constant, \n\
rather than using a positional placeholder: \n\ This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
\n command alias bl3 breakpoint set -f %1 -l 3 // Always sets a breakpoint on line \n\
// 3 of whatever file is indicated. \n"); Another example:
(lldb) command alias pltty process launch -s -o %1 -e %1
(lldb) pltty /dev/tty0
Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
)" "If the user always wanted to pass the same value to a particular option, the \
alias could be defined with that value directly in the alias as a constant, \
rather than using a positional placeholder:" R"(
(lldb) command alias bl3 breakpoint set -f %1 -l 3
Always sets a breakpoint on line 3 of whatever file is indicated.)"
);
CommandArgumentEntry arg1; CommandArgumentEntry arg1;
CommandArgumentEntry arg2; CommandArgumentEntry arg2;
@ -960,31 +974,30 @@ public:
IOHandlerDelegateMultiline ("", IOHandlerDelegate::Completion::LLDBCommand), IOHandlerDelegateMultiline ("", IOHandlerDelegate::Completion::LLDBCommand),
m_options (interpreter) m_options (interpreter)
{ {
SetHelpLong( SetHelpLong(R"(
"This command allows the user to create powerful regular expression commands\n" )" "This command allows the user to create powerful regular expression commands \
"with substitutions. The regular expressions and substitutions are specified\n" with substitutions. The regular expressions and substitutions are specified \
"using the regular expression substitution format of:\n" using the regular expression substitution format of:" R"(
"\n"
" s/<regex>/<subst>/\n" s/<regex>/<subst>/
"\n"
"<regex> is a regular expression that can use parenthesis to capture regular\n" )" "<regex> is a regular expression that can use parenthesis to capture regular \
"expression input and substitute the captured matches in the output using %1\n" expression input and substitute the captured matches in the output using %1 \
"for the first match, %2 for the second, and so on.\n" for the first match, %2 for the second, and so on." R"(
"\n"
"The regular expressions can all be specified on the command line if more than\n" )" "The regular expressions can all be specified on the command line if more than \
"one argument is provided. If just the command name is provided on the command\n" one argument is provided. If just the command name is provided on the command \
"line, then the regular expressions and substitutions can be entered on separate\n" line, then the regular expressions and substitutions can be entered on separate \
" lines, followed by an empty line to terminate the command definition.\n" lines, followed by an empty line to terminate the command definition." R"(
"\n"
"EXAMPLES\n" EXAMPLES
"\n"
"The following example will define a regular expression command named 'f' that\n" )" "The following example will define a regular expression command named 'f' that \
"will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if\n" will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
"a number follows 'f':\n" a number follows 'f':" R"(
"\n"
" (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/'\n" (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')"
"\n" );
);
} }
~CommandObjectCommandsAddRegex() ~CommandObjectCommandsAddRegex()

View File

@ -202,35 +202,39 @@ CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interprete
m_expr_line_count (0), m_expr_line_count (0),
m_expr_lines () m_expr_lines ()
{ {
SetHelpLong( SetHelpLong(
"Timeouts:\n\ R"(
If the expression can be evaluated statically (without running code) then it will be.\n\ Timeouts:
Otherwise, by default the expression will run on the current thread with a short timeout:\n\
currently .25 seconds. If it doesn't return in that time, the evaluation will be interrupted\n\ )" " If the expression can be evaluated statically (without running code) then it will be. \
and resumed with all threads running. You can use the -a option to disable retrying on all\n\ Otherwise, by default the expression will run on the current thread with a short timeout: \
threads. You can use the -t option to set a shorter timeout.\n\ currently .25 seconds. If it doesn't return in that time, the evaluation will be interrupted \
\n\ and resumed with all threads running. You can use the -a option to disable retrying on all \
User defined variables:\n\ threads. You can use the -t option to set a shorter timeout." R"(
You can define your own variables for convenience or to be used in subsequent expressions.\n\
You define them the same way you would define variables in C. If the first character of \n\ User defined variables:
your user defined variable is a $, then the variable's value will be available in future\n\
expressions, otherwise it will just be available in the current expression.\n\ )" " You can define your own variables for convenience or to be used in subsequent expressions. \
\n\ You define them the same way you would define variables in C. If the first character of \
\n\ your user defined variable is a $, then the variable's value will be available in future \
Continuing evaluation after a breakpoint:\n\ expressions, otherwise it will just be available in the current expression." R"(
If the \"-i false\" option is used, and execution is interrupted by a breakpoint hit, once\n\
you are done with your investigation, you can either remove the expression execution frames\n\ Continuing evaluation after a breakpoint:
from the stack with \"thread return -x\" or if you are still interested in the expression result\n\
you can issue the \"continue\" command and the expression evaluation will complete and the\n\ )" " If the \"-i false\" option is used, and execution is interrupted by a breakpoint hit, once \
expression result will be available using the \"thread.completed-expression\" key in the thread\n\ you are done with your investigation, you can either remove the expression execution frames \
format.\n\ from the stack with \"thread return -x\" or if you are still interested in the expression result \
\n\ you can issue the \"continue\" command and the expression evaluation will complete and the \
Examples: \n\ expression result will be available using the \"thread.completed-expression\" key in the thread \
\n\ format." R"(
expr my_struct->a = my_array[3] \n\
expr -f bin -- (index * 8) + 5 \n\ Examples:
expr unsigned int $foo = 5\n\
expr char c[] = \"foo\"; c[0]\n"); expr my_struct->a = my_array[3]
expr -f bin -- (index * 8) + 5
expr unsigned int $foo = 5
expr char c[] = \"foo\"; c[0])"
);
CommandArgumentEntry arg; CommandArgumentEntry arg;
CommandArgumentData expression_arg; CommandArgumentData expression_arg;

View File

@ -1067,10 +1067,12 @@ public:
0) 0)
{ {
SetHelpLong( SetHelpLong(
"Examples: \n\ R"(Examples:
\n\
platform get-file /the/remote/file/path /the/local/file/path\n\ (lldb) platform get-file /the/remote/file/path /the/local/file/path
# Transfer a file from the remote end with file path /the/remote/file/path to the local host.\n");
Transfer a file from the remote end with file path /the/remote/file/path to the local host.)"
);
CommandArgumentEntry arg1, arg2; CommandArgumentEntry arg1, arg2;
CommandArgumentData file_arg_remote, file_arg_host; CommandArgumentData file_arg_remote, file_arg_host;
@ -1150,10 +1152,12 @@ public:
0) 0)
{ {
SetHelpLong( SetHelpLong(
"Examples: \n\ R"(Examples:
\n\
platform get-size /the/remote/file/path\n\ (lldb) platform get-size /the/remote/file/path
# Get the file size from the remote end with path /the/remote/file/path.\n");
Get the file size from the remote end with path /the/remote/file/path.)"
);
CommandArgumentEntry arg1; CommandArgumentEntry arg1;
CommandArgumentData file_arg_remote; CommandArgumentData file_arg_remote;

View File

@ -1681,7 +1681,8 @@ public:
NULL), NULL),
m_options (interpreter) m_options (interpreter)
{ {
SetHelpLong ("If no signals are specified, update them all. If no update option is specified, list the current values.\n"); SetHelpLong ("\nIf no signals are specified, update them all. If no update "
"option is specified, list the current values.");
CommandArgumentEntry arg; CommandArgumentEntry arg;
CommandArgumentData signal_arg; CommandArgumentData signal_arg;

View File

@ -60,24 +60,25 @@ public:
m_arguments.push_back (arg2); m_arguments.push_back (arg2);
SetHelpLong ( SetHelpLong (
"When setting a dictionary or array variable, you can set multiple entries \n\ "\nWhen setting a dictionary or array variable, you can set multiple entries \
at once by giving the values to the set command. For example: \n\ at once by giving the values to the set command. For example:" R"(
\n\
(lldb) settings set target.run-args value1 value2 value3 \n\ (lldb) settings set target.run-args value1 value2 value3
(lldb) settings set target.env-vars MYPATH=~/.:/usr/bin SOME_ENV_VAR=12345 \n\ (lldb) settings set target.env-vars MYPATH=~/.:/usr/bin SOME_ENV_VAR=12345
\n\
(lldb) settings show target.run-args \n\ (lldb) settings show target.run-args
[0]: 'value1' \n\ [0]: 'value1'
[1]: 'value2' \n\ [1]: 'value2'
[3]: 'value3' \n\ [3]: 'value3'
(lldb) settings show target.env-vars \n\ (lldb) settings show target.env-vars
'MYPATH=~/.:/usr/bin'\n\ 'MYPATH=~/.:/usr/bin'
'SOME_ENV_VAR=12345' \n\ 'SOME_ENV_VAR=12345'
\n\
Warning: The 'set' command re-sets the entire array or dictionary. If you \n\ )" "Warning: The 'set' command re-sets the entire array or dictionary. If you \
just want to add, remove or update individual values (or add something to \n\ just want to add, remove or update individual values (or add something to \
the end), use one of the other settings sub-commands: append, replace, \n\ the end), use one of the other settings sub-commands: append, replace, \
insert-before or insert-after.\n"); insert-before or insert-after."
);
} }

View File

@ -764,31 +764,39 @@ public:
m_arguments.push_back (type_arg); m_arguments.push_back (type_arg);
SetHelpLong( SetHelpLong(
"Some examples of using this command.\n" R"(
"We use as reference the following snippet of code:\n" The following examples of 'type format add' refer to this code snippet for context:
"\n"
"typedef int Aint;\n" typedef int Aint;
"typedef float Afloat;\n" typedef float Afloat;
"typedef Aint Bint;\n" typedef Aint Bint;
"typedef Afloat Bfloat;\n" typedef Afloat Bfloat;
"\n"
"Aint ix = 5;\n" Aint ix = 5;
"Bint iy = 5;\n" Bint iy = 5;
"\n"
"Afloat fx = 3.14;\n" Afloat fx = 3.14;
"BFloat fy = 3.14;\n" BFloat fy = 3.14;
"\n"
"Typing:\n" Adding default formatting:
"type format add -f hex AInt\n"
"frame variable iy\n" (lldb) type format add -f hex AInt
"will produce an hex display of iy, because no formatter is available for Bint and the one for Aint is used instead\n" (lldb) frame variable iy
"To prevent this type\n"
"type format add -f hex -C no AInt\n" )" " Produces hexidecimal display of iy, because no formatter is available for Bint and \
"\n" the one for Aint is used instead." R"(
"A similar reasoning applies to\n"
"type format add -f hex -C no float -p\n" To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains:
"which now prints all floats and float&s as hexadecimal, but does not format float*s\n"
"and does not change the default display for Afloat and Bfloat objects.\n"
(lldb) type format add -f hex -C no AInt
Similar reasoning applies to this:
(lldb) type format add -f hex -C no float -p
)" " All float values and float references are now formatted as hexadecimal, but not \
pointers to floats. Nor will it change the default display for Afloat and Bfloat objects."
); );
// Add the "--format" to all options groups // Add the "--format" to all options groups
@ -1736,69 +1744,86 @@ CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd (CommandInterpreter &in
m_arguments.push_back (type_arg); m_arguments.push_back (type_arg);
SetHelpLong( SetHelpLong(
"Some examples of using this command.\n" R"(
"We use as reference the following snippet of code:\n" The following examples of 'type summary add' refer to this code snippet for context:
"struct JustADemo\n"
"{\n" struct JustADemo
"int* ptr;\n" {
"float value;\n" int* ptr;
"JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}\n" float value;
"};\n" JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
"JustADemo object(42,3.14);\n" };
"struct AnotherDemo : public JustADemo\n" JustADemo demo_instance(42, 3.14);
"{\n"
"uint8_t byte;\n" typedef JustADemo NewDemo;
"AnotherDemo(uint8_t b = 'E', int p = 1, float v = 0.1) : JustADemo(p,v), byte(b) {}\n" NewDemo new_demo_instance(42, 3.14);
"};\n"
"AnotherDemo *another_object = new AnotherDemo('E',42,3.14);\n" (lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo
"\n"
"type summary add --summary-string \"the answer is ${*var.ptr}\" JustADemo\n" Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42"
"when typing frame variable object you will get \"the answer is 42\"\n"
"type summary add --summary-string \"the answer is ${*var.ptr}, and the question is ${var.value}\" JustADemo\n" (lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo
"when typing frame variable object you will get \"the answer is 42 and the question is 3.14\"\n"
"\n" Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14"
"Alternatively, you could also say\n"
"type summary add --summary-string \"${var%V} -> ${*var}\" \"int *\"\n" )" "Alternatively, you could define formatting for all pointers to integers and \
"and replace the above summary string with\n" rely on that when formatting JustADemo to obtain the same result:" R"(
"type summary add --summary-string \"the answer is ${var.ptr}, and the question is ${var.value}\" JustADemo\n"
"to obtain a similar result\n" (lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *"
"\n" (lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo
"To add a summary valid for both JustADemo and AnotherDemo you can use the scoping operator, as in:\n"
"type summary add --summary-string \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes\n" )" "Type summaries are automatically applied to derived typedefs, so the examples \
"\n" above apply to both JustADemo and NewDemo. The cascade option can be used to \
"This will be used for both variables of type JustADemo and AnotherDemo. To prevent this, change the -C to read -C no\n" suppress this behavior:" R"(
"If you do not want pointers to be shown using that summary, you can use the -p option, as in:\n"
"type summary add --summary-string \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes -p\n" (lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no
"A similar option -r exists for references.\n"
"\n" The summary will now be used for values of JustADemo but not NewDemo.
"If you simply want a one-line summary of the content of your variable, without typing an explicit string to that effect\n"
"you can use the -c option, without giving any summary string:\n" )" "By default summaries are shown for pointers and references to values of the \
"type summary add -c JustADemo\n" specified type. To suppress formatting for pointers use the -p option, or apply \
"frame variable object\n" the corresponding -r option to suppress formatting for references:" R"(
"the output being similar to (ptr=0xsomeaddress, value=3.14)\n"
"\n" (lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo
"If you want to display some summary text, but also expand the structure of your object, you can add the -e option, as in:\n"
"type summary add -e --summary-string \"*ptr = ${*var.ptr}\" JustADemo\n" )" "One-line summaries including all fields in a type can be inferred without supplying an \
"Here the value of the int* is displayed, followed by the standard LLDB sequence of children objects, one per line.\n" explicit summary string by passing the -c option:" R"(
"to get an output like:\n"
"\n" (lldb) type summary add -c JustADemo
"*ptr = 42 {\n" (lldb) frame variable demo_instance
" ptr = 0xsomeaddress\n" (ptr=<address>, value=3.14)
" value = 3.14\n"
"}\n" )" "Type summaries normally suppress the nested display of individual fields. To \
"\n" supply a summary to supplement the default structure add the -e option:" R"(
"You can also add Python summaries, in which case you will use lldb public API to gather information from your variables"
"and elaborate them to a meaningful summary inside a script written in Python. The variable object will be passed to your" (lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo
"script as an SBValue object. The following example might help you when starting to use the Python summaries feature:\n"
"type summary add JustADemo -o \"value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();\"\n" )" "Now when displaying JustADemo values the int* is displayed, followed by the \
"If you prefer to type your scripts on multiple lines, you will use the -P option and then type your script, ending it with " standard LLDB sequence of children, one per line:" R"(
"the word DONE on a line by itself to mark you're finished editing your code:\n"
"(lldb)type summary add JustADemo -P\n" *ptr = 42 {
" value = valobj.GetChildMemberWithName('value');\n" ptr = <address>
" return 'My value is ' + value.GetValue();\n" value = 3.14
"DONE\n" }
"(lldb) <-- type further LLDB commands here\n"
); )" "You can also add summaries written in Python. These scripts use lldb public API to \
gather information from your variables and produce a meaningful summary. To start a \
multi-line script use the -P option. The function declaration will be displayed along with \
a comment describing the two arguments. End your script with the word 'DONE' on a line by \
itself:" R"(
(lldb) type summary add JustADemo -P
def function (valobj,internal_dict):
"""valobj: an SBValue which you want to provide a summary for
internal_dict: an LLDB support object not to be used"""
value = valobj.GetChildMemberWithName('value');
return 'My value is ' + value.GetValue();
DONE
Alternatively, the -o option can be used when providing a simple one-line Python script:
(lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")"
);
} }
bool bool
@ -4117,31 +4142,37 @@ public:
m_arguments.push_back (type_arg); m_arguments.push_back (type_arg);
SetHelpLong( SetHelpLong(
"Some examples of using this command.\n" R"(
"We use as reference the following snippet of code:\n" The following examples of 'type filter add' refer to this code snippet for context:
"\n"
"class Foo {;\n" class Foo {
" int a;\n" int a;
" int b;\n" int b;
" int c;\n" int c;
" int d;\n" int d;
" int e;\n" int e;
" int f;\n" int f;
" int g;\n" int g;
" int h;\n" int h;
" int i;\n" int i;
"} \n" }
"Typing:\n" Foo my_foo;
"type filter add --child a --child g Foo\n"
"frame variable a_foo\n" Adding a simple filter:
"will produce an output where only a and g are displayed\n"
"Other children of a_foo (b,c,d,e,f,h and i) are available by asking for them, as in:\n" (lldb) type filter add --child a --child g Foo
"frame variable a_foo.b a_foo.c ... a_foo.i\n" (lldb) frame variable my_foo
"\n"
"Use option --raw to frame variable prevails on the filter\n" )" "Produces output where only a and g are displayed. Other children of my_foo \
"frame variable a_foo --raw\n" (b, c, d, e, f, h and i) are available by asking for them explicitly:" R"(
"shows all the children of a_foo (a thru i) as if no filter was defined\n"
); (lldb) frame variable my_foo.b my_foo.c my_foo.i
)" "The formatting option --raw on frame variable bypasses the filter, showing \
all children of my_foo as if no filter was defined:" R"(
(lldb) frame variable my_foo --raw)"
);
} }
~CommandObjectTypeFilterAdd () ~CommandObjectTypeFilterAdd ()

View File

@ -931,10 +931,14 @@ public:
m_option_watchpoint () m_option_watchpoint ()
{ {
SetHelpLong( SetHelpLong(
"Examples: \n\ R"(
\n\ Examples:
watchpoint set variable -w read_write my_global_var \n\
# Watch my_global_var for read/write access, with the region to watch corresponding to the byte size of the data type.\n"); (lldb) watchpoint set variable -w read_write my_global_var
)" " Watches my_global_var for read/write access, with the region to watch \
corresponding to the byte size of the data type."
);
CommandArgumentEntry arg; CommandArgumentEntry arg;
CommandArgumentData var_name_arg; CommandArgumentData var_name_arg;
@ -1138,10 +1142,13 @@ public:
m_option_watchpoint () m_option_watchpoint ()
{ {
SetHelpLong( SetHelpLong(
"Examples: \n\ R"(
\n\ Examples:
watchpoint set expression -w write -x 1 -- foo + 32\n\
# Watch write access for the 1-byte region pointed to by the address 'foo + 32'.\n"); (lldb) watchpoint set expression -w write -x 1 -- foo + 32
Watches write access for the 1-byte region pointed to by the address 'foo + 32')"
);
CommandArgumentEntry arg; CommandArgumentEntry arg;
CommandArgumentData expression_arg; CommandArgumentData expression_arg;

View File

@ -48,121 +48,112 @@ public:
m_options (interpreter) m_options (interpreter)
{ {
SetHelpLong ( SetHelpLong (
"\nGeneral information about entering watchpoint commands \n\ R"(
------------------------------------------------------ \n\ General information about entering watchpoint commands
\n\ ------------------------------------------------------
This command will cause you to be prompted to enter the command or set \n\
of commands you wish to be executed when the specified watchpoint is \n\ )" "This command will prompt for commands to be executed when the specified \
hit. You will be told to enter your command(s), and will see a '> ' \n\ watchpoint is hit. Each command is typed on its own line following the '> ' \
prompt. Because you can enter one or many commands to be executed when \n\ prompt until 'DONE' is entered." R"(
a watchpoint is hit, you will continue to be prompted after each \n\
new-line that you enter, until you enter the word 'DONE', which will \n\ )" "Syntactic errors may not be detected when initially entered, and many \
cause the commands you have entered to be stored with the watchpoint \n\ malformed commands can silently fail when executed. If your watchpoint commands \
and executed when the watchpoint is hit. \n\ do not appear to be executing, double-check the command syntax." R"(
\n\
Syntax checking is not necessarily done when watchpoint commands are \n\ )" "Note: You may enter any debugger command exactly as you would at the debugger \
entered. An improperly written watchpoint command will attempt to get \n\ prompt. There is no limit to the number of commands supplied, but do NOT enter \
executed when the watchpoint gets hit, and usually silently fail. If \n\ more than one command per line." R"(
your watchpoint command does not appear to be getting executed, go \n\
back and check your syntax. \n\ Special information about PYTHON watchpoint commands
\n\ ----------------------------------------------------
\n\
Special information about PYTHON watchpoint commands \n\ )" "You may enter either one or more lines of Python, including function \
---------------------------------------------------- \n\ definitions or calls to functions that will have been imported by the time \
\n\ the code executes. Single line watchpoint commands will be interpreted 'as is' \
You may enter either one line of Python or multiple lines of Python \n\ when the watchpoint is hit. Multiple lines of Python will be wrapped in a \
(including defining whole functions, if desired). If you enter a \n\ generated function, and a call to the function will be attached to the watchpoint." R"(
single line of Python, that will be passed to the Python interpreter \n\
'as is' when the watchpoint gets hit. If you enter function \n\ This auto-generated function is passed in three arguments:
definitions, they will be passed to the Python interpreter as soon as \n\
you finish entering the watchpoint command, and they can be called \n\ frame: an lldb.SBFrame object for the frame which hit the watchpoint.
later (don't forget to add calls to them, if you want them called when \n\
the watchpoint is hit). If you enter multiple lines of Python that \n\ wp: the watchpoint that was hit.
are not function definitions, they will be collected into a new, \n\
automatically generated Python function, and a call to the newly \n\ )" "When specifying a python function with the --python-function option, you need \
generated function will be attached to the watchpoint. \n\ to supply the function name prepended by the module name:" R"(
\n\
This auto-generated function is passed in two arguments: \n\ --python-function myutils.watchpoint_callback
\n\
frame: an SBFrame object representing the frame which hit the watchpoint. \n\ The function itself must have the following prototype:
From the frame you can get back to the thread and process. \n\
wp: the watchpoint that was hit. \n\ def watchpoint_callback(frame, wp):
\n\ # Your code goes here
Important Note: Because loose Python code gets collected into functions, \n\
if you want to access global variables in the 'loose' code, you need to \n\ )" "The arguments are the same as the arguments passed to generated functions as \
specify that they are global, using the 'global' keyword. Be sure to \n\ described above. Note that the global variable 'lldb.frame' will NOT be updated when \
use correct Python syntax, including indentation, when entering Python \n\ this function is called, so be sure to use the 'frame' argument. The 'frame' argument \
watchpoint commands. \n\ can get you to the thread via frame.GetThread(), the thread can get you to the \
\n\ process via thread.GetProcess(), and the process can get you back to the target \
As a third option, you can pass the name of an already existing Python function \n\ via process.GetTarget()." R"(
and that function will be attached to the watchpoint. It will get passed the \n\
frame and wp_loc arguments mentioned above. \n\ )" "Important Note: As Python code gets collected into functions, access to global \
\n\ variables requires explicit scoping using the 'global' keyword. Be sure to use correct \
Example Python one-line watchpoint command: \n\ Python syntax, including indentation, when entering Python watchpoint commands." R"(
\n\
(lldb) watchpoint command add -s python 1 \n\ Example Python one-line watchpoint command:
Enter your Python command(s). Type 'DONE' to end. \n\
> print \"Hit this watchpoint!\" \n\ (lldb) watchpoint command add -s python 1
> DONE \n\ Enter your Python command(s). Type 'DONE' to end.
\n\ > print "Hit this watchpoint!"
As a convenience, this also works for a short Python one-liner: \n\ > DONE
(lldb) watchpoint command add -s python 1 -o \"import time; print time.asctime()\" \n\
(lldb) run \n\ As a convenience, this also works for a short Python one-liner:
Launching '.../a.out' (x86_64) \n\
(lldb) Fri Sep 10 12:17:45 2010 \n\ (lldb) watchpoint command add -s python 1 -o 'import time; print time.asctime()'
Process 21778 Stopped \n\ (lldb) run
* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = watchpoint 1.1, queue = com.apple.main-thread \n\ Launching '.../a.out' (x86_64)
36 \n\ (lldb) Fri Sep 10 12:17:45 2010
37 int c(int val)\n\ Process 21778 Stopped
38 {\n\ * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = watchpoint 1.1, queue = com.apple.main-thread
39 -> return val + 3;\n\ 36
40 }\n\ 37 int c(int val)
41 \n\ 38 {
42 int main (int argc, char const *argv[])\n\ 39 -> return val + 3;
(lldb) \n\ 40 }
\n\ 41
Example multiple line Python watchpoint command, using function definition: \n\ 42 int main (int argc, char const *argv[])
\n\
(lldb) watchpoint command add -s python 1 \n\ Example multiple line Python watchpoint command, using function definition:
Enter your Python command(s). Type 'DONE' to end. \n\
> def watchpoint_output (wp_no): \n\ (lldb) watchpoint command add -s python 1
> out_string = \"Hit watchpoint number \" + repr (wp_no) \n\ Enter your Python command(s). Type 'DONE' to end.
> print out_string \n\ > def watchpoint_output (wp_no):
> return True \n\ > out_string = "Hit watchpoint number " + repr (wp_no)
> watchpoint_output (1) \n\ > print out_string
> DONE \n\ > return True
\n\ > watchpoint_output (1)
\n\ > DONE
Example multiple line Python watchpoint command, using 'loose' Python: \n\
\n\ Example multiple line Python watchpoint command, using 'loose' Python:
(lldb) watchpoint command add -s p 1 \n\
Enter your Python command(s). Type 'DONE' to end. \n\ (lldb) watchpoint command add -s p 1
> global wp_count \n\ Enter your Python command(s). Type 'DONE' to end.
> wp_count = wp_count + 1 \n\ > global wp_count
> print \"Hit this watchpoint \" + repr(wp_count) + \" times!\" \n\ > wp_count = wp_count + 1
> DONE \n\ > print "Hit this watchpoint " + repr(wp_count) + " times!"
\n\ > DONE
In this case, since there is a reference to a global variable, \n\
'wp_count', you will also need to make sure 'wp_count' exists and is \n\ )" "In this case, since there is a reference to a global variable, \
initialized: \n\ 'wp_count', you will also need to make sure 'wp_count' exists and is \
\n\ initialized:" R"(
(lldb) script \n\
>>> wp_count = 0 \n\ (lldb) script
>>> quit() \n\ >>> wp_count = 0
\n\ >>> quit()
(lldb) \n\
\n\ )" "Final Note: A warning that no watchpoint command was generated when there \
\n\ are no syntax errors may indicate that a function was declared but never called."
Final Note: If you get a warning that no watchpoint command was generated, \n\ );
but you did not get any syntax errors, you probably forgot to add a call \n\
to your functions. \n\
\n\
Special information about debugger command watchpoint commands \n\
-------------------------------------------------------------- \n\
\n\
You may enter any debugger command, exactly as you would at the \n\
debugger prompt. You may enter as many debugger commands as you like, \n\
but do NOT enter more than one command per line. \n" );
CommandArgumentEntry arg; CommandArgumentEntry arg;
CommandArgumentData wp_id_arg; CommandArgumentData wp_id_arg;

View File

@ -10,6 +10,7 @@
#include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/CommandObject.h"
#include <string> #include <string>
#include <sstream>
#include <map> #include <map>
#include <stdlib.h> #include <stdlib.h>
@ -920,6 +921,27 @@ ExprPathHelpTextCallback()
" meaning of array slicing (taking elements n thru m inside the array or pointed-to memory)."; " meaning of array slicing (taking elements n thru m inside the array or pointed-to memory).";
} }
void
CommandObject::FormatLongHelpText (Stream &output_strm, const char *long_help)
{
CommandInterpreter& interpreter = GetCommandInterpreter();
std::stringstream lineStream (long_help);
std::string line;
while (std::getline (lineStream, line)) {
if (line.empty()) {
output_strm << "\n";
continue;
}
size_t result = line.find_first_not_of (" \t");
if (result == std::string::npos) {
result = 0;
}
std::string whitespace_prefix = line.substr (0, result);
std::string remainder = line.substr (result);
interpreter.OutputFormattedHelpText(output_strm, whitespace_prefix.c_str(), remainder.c_str());
}
}
void void
CommandObject::GenerateHelpText (CommandReturnObject &result) CommandObject::GenerateHelpText (CommandReturnObject &result)
{ {
@ -947,7 +969,7 @@ CommandObject::GenerateHelpText (Stream &output_strm)
const char *long_help = GetHelpLong(); const char *long_help = GetHelpLong();
if ((long_help != nullptr) if ((long_help != nullptr)
&& (strlen (long_help) > 0)) && (strlen (long_help) > 0))
output_strm.Printf ("\n%s", long_help); FormatLongHelpText (output_strm, long_help);
if (WantsRawCommandString() && !WantsCompletion()) if (WantsRawCommandString() && !WantsCompletion())
{ {
// Emit the message about using ' -- ' between the end of the command options and the raw input // Emit the message about using ' -- ' between the end of the command options and the raw input
@ -984,7 +1006,7 @@ CommandObject::GenerateHelpText (Stream &output_strm)
const char *long_help = GetHelpLong(); const char *long_help = GetHelpLong();
if ((long_help != nullptr) if ((long_help != nullptr)
&& (strlen (long_help) > 0)) && (strlen (long_help) > 0))
output_strm.Printf ("%s", long_help); FormatLongHelpText (output_strm, long_help);
else if (WantsRawCommandString()) else if (WantsRawCommandString())
{ {
std::string help_text (GetHelp()); std::string help_text (GetHelp());