mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-07-10 01:25:30 +08:00
2011-07-21 Phil Muldoon <pmuldoon@redhat.com>
Tom Tromey <tromey@redhat.com> * top.c (set_prompt): Rewrite to free previous prompt, free asynch_new_prompt and set both on new prompts. * event-top.c (display_gdb_prompt): Add prompt substitution logic. * python/python.c (before_prompt_hook): New function. 2011-07-21 Phil Muldoon <pmuldoon@redhat.com> * gdb.python/python.exp: Add prompt substitution tests. 2011-07-21 Phil Muldoon <pmuldoon@redhat.com> * observer.texi (GDB Observers): Add before_prompt observer. * gdb.texinfo (Basic Python): Add documentation for prompt substitution.
This commit is contained in:
gdb
@ -1,3 +1,12 @@
|
|||||||
|
2011-07-21 Phil Muldoon <pmuldoon@redhat.com>
|
||||||
|
Tom Tromey <tromey@redhat.com>
|
||||||
|
|
||||||
|
* top.c (set_prompt): Rewrite to free previous prompt, free
|
||||||
|
asynch_new_prompt and set both on new prompts.
|
||||||
|
* event-top.c (display_gdb_prompt): Add prompt substitution
|
||||||
|
logic.
|
||||||
|
* python/python.c (before_prompt_hook): New function.
|
||||||
|
|
||||||
2011-07-20 Matt Rice <ratmice@gmail.com>
|
2011-07-20 Matt Rice <ratmice@gmail.com>
|
||||||
|
|
||||||
* bfin-tdep.c (bfin_extract_return_value): Fix swapped
|
* bfin-tdep.c (bfin_extract_return_value): Fix swapped
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
2011-07-21 Phil Muldoon <pmuldoon@redhat.com>
|
||||||
|
|
||||||
|
* observer.texi (GDB Observers): Add before_prompt observer.
|
||||||
|
* gdb.texinfo (Basic Python): Add documentation for prompt
|
||||||
|
substitution.
|
||||||
|
|
||||||
2011-07-11 Phil Muldoon <pmuldoon@redhat.com>
|
2011-07-11 Phil Muldoon <pmuldoon@redhat.com>
|
||||||
|
|
||||||
PR python/12438
|
PR python/12438
|
||||||
|
@ -21080,6 +21080,22 @@ provided, it is decoded the way that @value{GDBN}'s inbuilt
|
|||||||
@code{break} or @code{edit} commands do (@pxref{Specify Location}).
|
@code{break} or @code{edit} commands do (@pxref{Specify Location}).
|
||||||
@end defun
|
@end defun
|
||||||
|
|
||||||
|
@defop Operation {@value{GDBN}} prompt_hook current_prompt
|
||||||
|
If @var{prompt_hook} is callable, @value{GDBN} will call the method
|
||||||
|
assigned to this operation before a prompt is displayed by
|
||||||
|
@value{GDBN}.
|
||||||
|
|
||||||
|
The parameter @code{current_prompt} contains the current @value{GDBN}
|
||||||
|
prompt. This method must return a Python string, or @code{None}. If
|
||||||
|
a string is returned, the @value{GDBN} prompt will be set to that
|
||||||
|
string. If @code{None} is returned, @value{GDBN} will continue to use
|
||||||
|
the current prompt.
|
||||||
|
|
||||||
|
Some prompts cannot be substituted in @value{GDBN}. Secondary prompts
|
||||||
|
such as those used by readline for command input, and annotation
|
||||||
|
related prompts are prohibited from being changed.
|
||||||
|
@end defop
|
||||||
|
|
||||||
@node Exception Handling
|
@node Exception Handling
|
||||||
@subsubsection Exception Handling
|
@subsubsection Exception Handling
|
||||||
@cindex python exceptions
|
@cindex python exceptions
|
||||||
|
@ -222,6 +222,11 @@ Bytes from @var{data} to @var{data} + @var{len} have been written
|
|||||||
to the current inferior at @var{addr}.
|
to the current inferior at @var{addr}.
|
||||||
@end deftypefun
|
@end deftypefun
|
||||||
|
|
||||||
|
@deftypefun void before_prompt (const char *@var{current_prompt})
|
||||||
|
Called before a top-level prompt is displayed. @var{current_prompt} is
|
||||||
|
the current top-level prompt.
|
||||||
|
@end deftypefun
|
||||||
|
|
||||||
@deftypefun void test_notification (int @var{somearg})
|
@deftypefun void test_notification (int @var{somearg})
|
||||||
This observer is used for internal testing. Do not use.
|
This observer is used for internal testing. Do not use.
|
||||||
See testsuite/gdb.gdb/observer.exp.
|
See testsuite/gdb.gdb/observer.exp.
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "cli/cli-script.h" /* for reset_command_nest_depth */
|
#include "cli/cli-script.h" /* for reset_command_nest_depth */
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "gdbthread.h"
|
#include "gdbthread.h"
|
||||||
|
#include "observer.h"
|
||||||
#include "continuations.h"
|
#include "continuations.h"
|
||||||
#include "gdbcmd.h" /* for dont_repeat() */
|
#include "gdbcmd.h" /* for dont_repeat() */
|
||||||
|
|
||||||
@ -258,7 +259,7 @@ void
|
|||||||
display_gdb_prompt (char *new_prompt)
|
display_gdb_prompt (char *new_prompt)
|
||||||
{
|
{
|
||||||
int prompt_length = 0;
|
int prompt_length = 0;
|
||||||
char *gdb_prompt = get_prompt ();
|
char *actual_gdb_prompt = NULL;
|
||||||
|
|
||||||
/* Reset the nesting depth used when trace-commands is set. */
|
/* Reset the nesting depth used when trace-commands is set. */
|
||||||
reset_command_nest_depth ();
|
reset_command_nest_depth ();
|
||||||
@ -268,6 +269,25 @@ display_gdb_prompt (char *new_prompt)
|
|||||||
if (!current_interp_display_prompt_p ())
|
if (!current_interp_display_prompt_p ())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Get the prompt before the observers are called as observer hook
|
||||||
|
functions may change the prompt. Do not call observers on an
|
||||||
|
explicit prompt change as passed to this function, as this forms
|
||||||
|
a temporary prompt, IE, displayed but not set. */
|
||||||
|
if (! new_prompt)
|
||||||
|
{
|
||||||
|
char *post_gdb_prompt = NULL;
|
||||||
|
char *pre_gdb_prompt = xstrdup (get_prompt ());
|
||||||
|
|
||||||
|
observer_notify_before_prompt (pre_gdb_prompt);
|
||||||
|
post_gdb_prompt = get_prompt ();
|
||||||
|
|
||||||
|
/* If the observer changed the prompt, use that prompt. */
|
||||||
|
if (strcmp (pre_gdb_prompt, post_gdb_prompt) != 0)
|
||||||
|
actual_gdb_prompt = post_gdb_prompt;
|
||||||
|
|
||||||
|
xfree (pre_gdb_prompt);
|
||||||
|
}
|
||||||
|
|
||||||
if (sync_execution && is_running (inferior_ptid))
|
if (sync_execution && is_running (inferior_ptid))
|
||||||
{
|
{
|
||||||
/* This is to trick readline into not trying to display the
|
/* This is to trick readline into not trying to display the
|
||||||
@ -289,27 +309,35 @@ display_gdb_prompt (char *new_prompt)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!new_prompt)
|
/* If the observer changed the prompt, ACTUAL_GDB_PROMPT will not be
|
||||||
|
NULL. Otherwise, either copy the existing prompt, or set it to
|
||||||
|
NEW_PROMPT. */
|
||||||
|
if (! actual_gdb_prompt)
|
||||||
|
{
|
||||||
|
if (! new_prompt)
|
||||||
{
|
{
|
||||||
/* Just use the top of the prompt stack. */
|
/* Just use the top of the prompt stack. */
|
||||||
prompt_length = strlen (PREFIX (0)) +
|
prompt_length = strlen (PREFIX (0)) +
|
||||||
strlen (SUFFIX (0)) +
|
strlen (SUFFIX (0)) +
|
||||||
strlen (gdb_prompt) + 1;
|
strlen (get_prompt()) + 1;
|
||||||
|
|
||||||
new_prompt = (char *) alloca (prompt_length);
|
actual_gdb_prompt = (char *) alloca (prompt_length);
|
||||||
|
|
||||||
/* Prefix needs to have new line at end. */
|
/* Prefix needs to have new line at end. */
|
||||||
strcpy (new_prompt, PREFIX (0));
|
strcpy (actual_gdb_prompt, PREFIX (0));
|
||||||
strcat (new_prompt, gdb_prompt);
|
strcat (actual_gdb_prompt, get_prompt());
|
||||||
/* Suffix needs to have a new line at end and \032 \032 at
|
/* Suffix needs to have a new line at end and \032 \032 at
|
||||||
beginning. */
|
beginning. */
|
||||||
strcat (new_prompt, SUFFIX (0));
|
strcat (actual_gdb_prompt, SUFFIX (0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
actual_gdb_prompt = new_prompt;;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (async_command_editing_p)
|
if (async_command_editing_p)
|
||||||
{
|
{
|
||||||
rl_callback_handler_remove ();
|
rl_callback_handler_remove ();
|
||||||
rl_callback_handler_install (new_prompt, input_handler);
|
rl_callback_handler_install (actual_gdb_prompt, input_handler);
|
||||||
}
|
}
|
||||||
/* new_prompt at this point can be the top of the stack or the one
|
/* new_prompt at this point can be the top of the stack or the one
|
||||||
passed in. It can't be NULL. */
|
passed in. It can't be NULL. */
|
||||||
@ -318,7 +346,7 @@ display_gdb_prompt (char *new_prompt)
|
|||||||
/* Don't use a _filtered function here. It causes the assumed
|
/* Don't use a _filtered function here. It causes the assumed
|
||||||
character position to be off, since the newline we read from
|
character position to be off, since the newline we read from
|
||||||
the user is not accounted for. */
|
the user is not accounted for. */
|
||||||
fputs_unfiltered (new_prompt, gdb_stdout);
|
fputs_unfiltered (actual_gdb_prompt, gdb_stdout);
|
||||||
gdb_flush (gdb_stdout);
|
gdb_flush (gdb_stdout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,7 @@ static int gdbpy_should_print_stack = 0;
|
|||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
#include "gdbthread.h"
|
#include "gdbthread.h"
|
||||||
|
#include "observer.h"
|
||||||
|
|
||||||
static PyMethodDef GdbMethods[];
|
static PyMethodDef GdbMethods[];
|
||||||
|
|
||||||
@ -682,6 +683,81 @@ gdbpy_initialize_events (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
before_prompt_hook (const char *current_gdb_prompt)
|
||||||
|
{
|
||||||
|
struct cleanup *cleanup;
|
||||||
|
char *prompt = NULL;
|
||||||
|
|
||||||
|
cleanup = ensure_python_env (get_current_arch (), current_language);
|
||||||
|
|
||||||
|
if (PyObject_HasAttrString (gdb_module, "prompt_hook"))
|
||||||
|
{
|
||||||
|
PyObject *hook;
|
||||||
|
|
||||||
|
hook = PyObject_GetAttrString (gdb_module, "prompt_hook");
|
||||||
|
if (hook == NULL)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (PyCallable_Check (hook))
|
||||||
|
{
|
||||||
|
PyObject *result;
|
||||||
|
PyObject *current_prompt;
|
||||||
|
|
||||||
|
current_prompt = PyString_FromString (current_gdb_prompt);
|
||||||
|
if (current_prompt == NULL)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
result = PyObject_CallFunctionObjArgs (hook, current_prompt, NULL);
|
||||||
|
|
||||||
|
Py_DECREF (current_prompt);
|
||||||
|
|
||||||
|
if (result == NULL)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
make_cleanup_py_decref (result);
|
||||||
|
|
||||||
|
/* Return type should be None, or a String. If it is None,
|
||||||
|
fall through, we will not set a prompt. If it is a
|
||||||
|
string, set PROMPT. Anything else, set an exception. */
|
||||||
|
if (result != Py_None && ! PyString_Check (result))
|
||||||
|
{
|
||||||
|
PyErr_Format (PyExc_RuntimeError,
|
||||||
|
_("Return from prompt_hook must " \
|
||||||
|
"be either a Python string, or None"));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != Py_None)
|
||||||
|
{
|
||||||
|
prompt = python_string_to_host_string (result);
|
||||||
|
|
||||||
|
if (prompt == NULL)
|
||||||
|
goto fail;
|
||||||
|
else
|
||||||
|
make_cleanup (xfree, prompt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If a prompt has been set, PROMPT will not be NULL. If it is
|
||||||
|
NULL, do not set the prompt. */
|
||||||
|
if (prompt != NULL)
|
||||||
|
set_prompt (prompt);
|
||||||
|
|
||||||
|
do_cleanups (cleanup);
|
||||||
|
return;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
gdbpy_print_stack ();
|
||||||
|
do_cleanups (cleanup);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Printing. */
|
/* Printing. */
|
||||||
|
|
||||||
/* A python function to write a single string using gdb's filtered
|
/* A python function to write a single string using gdb's filtered
|
||||||
@ -1134,6 +1210,8 @@ Enables or disables printing of Python stack traces."),
|
|||||||
gdbpy_initialize_exited_event ();
|
gdbpy_initialize_exited_event ();
|
||||||
gdbpy_initialize_thread_event ();
|
gdbpy_initialize_thread_event ();
|
||||||
|
|
||||||
|
observer_attach_before_prompt (before_prompt_hook);
|
||||||
|
|
||||||
PyRun_SimpleString ("import gdb");
|
PyRun_SimpleString ("import gdb");
|
||||||
PyRun_SimpleString ("gdb.pretty_printers = []");
|
PyRun_SimpleString ("gdb.pretty_printers = []");
|
||||||
|
|
||||||
@ -1236,6 +1314,8 @@ def GdbSetPythonDirectory (dir):\n\
|
|||||||
\n\
|
\n\
|
||||||
# Install the default gdb.PYTHONDIR.\n\
|
# Install the default gdb.PYTHONDIR.\n\
|
||||||
GdbSetPythonDirectory (gdb.PYTHONDIR)\n\
|
GdbSetPythonDirectory (gdb.PYTHONDIR)\n\
|
||||||
|
# Default prompt hook does nothing.\n\
|
||||||
|
prompt_hook = None\n\
|
||||||
");
|
");
|
||||||
|
|
||||||
do_cleanups (cleanup);
|
do_cleanups (cleanup);
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
2011-07-21 Phil Muldoon <pmuldoon@redhat.com>
|
||||||
|
|
||||||
|
* gdb.python/python.exp: Add prompt substitution tests.
|
||||||
|
|
||||||
2011-07-19 Jan Kratochvil <jan.kratochvil@redhat.com>
|
2011-07-19 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||||
|
|
||||||
Fix crash if referenced CU is aged out.
|
Fix crash if referenced CU is aged out.
|
||||||
|
@ -193,3 +193,85 @@ gdb_py_test_silent_cmd "set python print-stack on" \
|
|||||||
"Test print-backtrace set setting" 1
|
"Test print-backtrace set setting" 1
|
||||||
gdb_test "show python print-stack" \
|
gdb_test "show python print-stack" \
|
||||||
"Whether Python stack will be printed on error is on.*" \
|
"Whether Python stack will be printed on error is on.*" \
|
||||||
|
|
||||||
|
# Test prompt substituion
|
||||||
|
|
||||||
|
gdb_py_test_multiple "prompt substitution" \
|
||||||
|
"python" "" \
|
||||||
|
"someCounter = 0" "" \
|
||||||
|
"def prompt(current):" "" \
|
||||||
|
" global someCounter" "" \
|
||||||
|
" if (current == \"testfake \"):" "" \
|
||||||
|
" return None" "" \
|
||||||
|
" someCounter = someCounter + 1" "" \
|
||||||
|
" return \"py prompt \" + str (someCounter) + \" \"" "" \
|
||||||
|
"end" ""
|
||||||
|
|
||||||
|
gdb_py_test_multiple "prompt substitution readline" \
|
||||||
|
"python" "" \
|
||||||
|
"pCounter = 0" "" \
|
||||||
|
"def program_prompt(current):" "" \
|
||||||
|
" global pCounter" "" \
|
||||||
|
" if (current == \">\"):" "" \
|
||||||
|
" pCounter = pCounter + 1" "" \
|
||||||
|
" return \"python line \" + str (pCounter) + \": \"" "" \
|
||||||
|
" return None" "" \
|
||||||
|
"end" ""
|
||||||
|
|
||||||
|
set newprompt "py prompt 1"
|
||||||
|
set newprompt2 "py prompt 2"
|
||||||
|
set testfake "testfake"
|
||||||
|
|
||||||
|
gdb_test_multiple "python gdb.prompt_hook = prompt" "set the hook" {
|
||||||
|
-re "\[\r\n\]$newprompt $" {
|
||||||
|
pass "set hook"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_test_multiple "set prompt testfake " "set testfake prompt in GDB" {
|
||||||
|
-re "\[\r\n\]$testfake $" {
|
||||||
|
pass "set prompt testfake"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_test_multiple "show prompt" "show testfake prompt" {
|
||||||
|
-re "Gdb's prompt is \"$testfake \"..* $" {
|
||||||
|
pass "show prompt shows guarded prompt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_test_multiple "set prompt blah " "set blah in GDB" {
|
||||||
|
-re "\[\r\n\]$newprompt2 $" {
|
||||||
|
pass "set prompt blah overriden"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_test_multiple "python gdb.prompt_hook = None" "Delete hook" {
|
||||||
|
-re "\[\r\n\]$newprompt2 $" {
|
||||||
|
pass "Delete old hook"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_test_multiple "set prompt $gdb_prompt " "set default prompt" {
|
||||||
|
-re "\[\r\n\]$gdb_prompt $" {
|
||||||
|
pass "set default prompt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_test_multiple "python gdb.prompt_hook = program_prompt" "set the hook" {
|
||||||
|
-re "\[\r\n\]$gdb_prompt $" {
|
||||||
|
pass "set programming hook"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_test_multiple "python" "test we ignore substituion for seconday prompts" {
|
||||||
|
-re "\r\n>$" {
|
||||||
|
pass "readline secondary are not substituted"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_test_multiple "end" "end programming" {
|
||||||
|
-re "\[\r\n\]$gdb_prompt $" {
|
||||||
|
pass "end programming"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
17
gdb/top.c
17
gdb/top.c
@ -1133,14 +1133,17 @@ get_prompt (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
set_prompt (char *s)
|
set_prompt (const char *s)
|
||||||
{
|
{
|
||||||
/* ??rehrauer: I don't know why this fails, since it looks as though
|
char *p = xstrdup (s);
|
||||||
assignments to prompt are wrapped in calls to xstrdup...
|
|
||||||
if (prompt != NULL)
|
xfree (PROMPT (0));
|
||||||
xfree (prompt);
|
PROMPT (0) = p;
|
||||||
*/
|
|
||||||
PROMPT (0) = xstrdup (s);
|
/* Also, free and set new_async_prompt so prompt changes sync up
|
||||||
|
with set/show prompt. */
|
||||||
|
xfree (new_async_prompt);
|
||||||
|
new_async_prompt = xstrdup (PROMPT (0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ extern char *get_prompt (void);
|
|||||||
|
|
||||||
/* This function copies the specified string into the string that
|
/* This function copies the specified string into the string that
|
||||||
is used by gdb for its command prompt. */
|
is used by gdb for its command prompt. */
|
||||||
extern void set_prompt (char *);
|
extern void set_prompt (const char *);
|
||||||
|
|
||||||
/* From random places. */
|
/* From random places. */
|
||||||
extern int readnow_symbol_files;
|
extern int readnow_symbol_files;
|
||||||
|
Reference in New Issue
Block a user