[RFA][patch 1/9] Initial Python support, patch du jour

Thiago Jung Bauermann bauerman@br.ibm.com
Wed Aug 6 05:35:00 GMT 2008


On Tue, 2008-08-05 at 21:13 +0300, Eli Zaretskii wrote:
> > From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> > The two paragraphs talking about exception handling should go to a new
> > subsubsection, and the paragraph stdout and pagination should go to the
> > "Basic Python" subsubsection.
> > 
> > Then we can whack the "GDB exposes a number of features to Python
> > scripts." sentence.
> > 
> > IMO it is the best option.
> 
> Can you show me the patch along those lines?

Sure. I'm sending everything I have so far, actually. In the end I
preferred to keep the paragraph about stdout and pagination in the
Python API subsection, instead of moving it to Basic Python.

The code part is the same as the last submission and is already
approved. The documentation part reflects everything we've discussed
until now. I hope I didn't miss anything, it was a long thread. :-)
-- 
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center

gdb/
2008-08-06  Vladimir Prus  <vladimir@codesourcery.com>
	    Tom Tromey  <tromey@redhat.com>
	    Thiago Jung Bauermann  <bauerman@br.ibm.com>
	    Doug Evans  <dje@google.com>

	* Makefile.in (SUBDIR_PYTHON_OBS, SUBDIR_PYTHON_SRCS,
	SUBDIR_PYTHON_DEPS, SUBDIR_PYTHON_LDFLAGS, SUBDIR_PYTHON_CFLAGS,
	PYTHON_CFLAGS): New.
	(python_h, python_internal_h): New.
	(cli-script.o): Depend on python.h
	(python.o, python-utils.o): New.
	* cli/cli-script.c (print_command_lines): Handle python_control.
	(execute_control_command): Handle python_control.
	(execute_control_command_untraced): New function.
	(while_command): Call execute_control_command_untraced.
	(if_command): Likewise.
	(get_command_line): Remove static attribute.
	(read_next_line): Handle "python".
	(recurse_read_control_structure): Handle python_control.
	(read_command_lines): Handle python_control.
	Include python.h.
	* cli/cli-script.h (get_command_line): Add prototype.
	(execute_control_command_untraced): Likewise.
	* configure.ac: Add --with-python.
	* defs.h (enum command_control_type) <python_control>: New
	constant.
	* python/python-internal.h: New file.
	* python/python.c: New file.
	* python/python.h: New file.
	* python/python-utils.c: New file.
	* NEWS: Mention Python scripting support and its new commands.

gdb/doc/
2008-08-06  Tom Tromey  <tromey@redhat.com>

	* gdb.texinfo (Extending GDB): New chapter.
	(Sequences): Demoted chapter, now a section under the new
	Extending GDB chapter.
	(Python): New section.

gdb/testsuite/
2008-08-06  Tom Tromey  <tromey@redhat.com>

	* gdb.python/python.exp: New file.

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 3e82b92..615be3f 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -254,6 +254,19 @@ SUBDIR_TUI_LDFLAGS=
 SUBDIR_TUI_CFLAGS= \
 	-DTUI=1
 
+#
+# python sub directory definitons
+#
+SUBDIR_PYTHON_OBS = \
+	python.o \
+	python-utils.o
+SUBDIR_PYTHON_SRCS = \
+	python/python.c \
+	python/python-utils.c
+SUBDIR_PYTHON_DEPS =
+SUBDIR_PYTHON_LDFLAGS=
+SUBDIR_PYTHON_CFLAGS=
+
 
 # Opcodes currently live in one of two places.  Either they are in the
 # opcode library, typically ../opcodes, or they are in a header file
@@ -963,6 +976,13 @@ tui_wingeneral_h = $(srcdir)/tui/tui-wingeneral.h
 tui_win_h = $(srcdir)/tui/tui-win.h $(tui_data_h)
 tui_winsource_h = $(srcdir)/tui/tui-winsource.h $(tui_data_h)
 
+#
+# gdb/python/ headers
+#
+
+python_h = $(srcdir)/python/python.h $(value_h)
+python_internal_h = $(srcdir)/python/python-internal.h
+
 # gdb/features preparsed descriptions
 features_headers = $(defs_h) $(gdbtypes_h) $(target_descriptions_h)
 arm_with_iwmmxt_c = $(srcdir)/features/arm-with-iwmmxt.c $(features_headers)
@@ -3064,7 +3084,8 @@ cli-logging.o: $(srcdir)/cli/cli-logging.c $(defs_h) $(gdbcmd_h) $(ui_out_h) \
 	$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-logging.c
 cli-script.o: $(srcdir)/cli/cli-script.c $(defs_h) $(value_h) $(language_h) \
 	$(ui_out_h) $(gdb_string_h) $(exceptions_h) $(top_h) $(cli_cmds_h) \
-	$(cli_decode_h) $(cli_script_h) $(gdb_assert_h) $(breakpoint_h)
+	$(cli_decode_h) $(cli_script_h) $(gdb_assert_h) $(breakpoint_h) \
+	$(python_h)
 	$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-script.c
 cli-setshow.o: $(srcdir)/cli/cli-setshow.c $(defs_h) $(readline_tilde_h) \
 	$(value_h) $(gdb_string_h) $(ui_out_h) $(cli_decode_h) $(cli_cmds_h) \
@@ -3389,4 +3410,22 @@ tui-winsource.o: $(srcdir)/tui/tui-winsource.c $(defs_h) $(symtab_h) \
 	$(gdb_curses_h) $(gdb_assert_h)
 	$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tui-winsource.c
 
+#
+# gdb/python/ dependencies
+#
+# Need to explicitly specify the compile rule as make will do nothing
+# or try to compile the object file into the sub-directory.
+
+# Flags needed to compile Python code
+PYTHON_CFLAGS=@PYTHON_CFLAGS@
+
+python.o: $(srcdir)/python/python.c $(defs_h) $(python_h) \
+	$(command_h) $(libiberty_h) $(cli_decode_h) $(charset_h) $(top_h) \
+	$(exceptions_h) $(python_internal_h) $(version_h) $(cli_script_h) \
+	$(ui_out_h) $(target_h) $(gdbthread_h)
+	$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
+python-utils.o: $(srcdir)/python/python-utils.c $(defs_h) $(python_internal_h)
+	$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
+	  $(srcdir)/python/python-utils.c -o python-utils.o
+
 ### end of the gdb Makefile.in.
diff --git a/gdb/NEWS b/gdb/NEWS
index e783259..82dbfe6 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -62,12 +62,24 @@ have also been fixed.
   gdbserver executable to debug both 32-bit and 64-bit programs.
   (This requires gdbserver itself to be built as a 64-bit executable.)
 
+* Python scripting
+
+  GDB now has support for scripting using Python.  Whether this is
+  available is determined at configure time.
+
 * New commands
 
 find [/size-char] [/max-count] start-address, end-address|+search-space-size,
     val1 [, val2, ...]
   Search memory for a sequence of bytes.
 
+maint set python print-stack
+maint show python print-stack
+  Show a stack trace when an error is encountered in a Python script.
+
+python [CODE]
+  Invoke CODE by passing it to the Python interpreter.
+
 set print symbol-loading
 show print symbol-loading
   Control printing of symbol loading messages.
diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index e6fbe3f..5aafc75 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -34,6 +34,8 @@
 #include "cli/cli-script.h"
 #include "gdb_assert.h"
 
+#include "python/python.h"
+
 /* Prototypes for local functions */
 
 static enum command_control_type
@@ -102,7 +104,7 @@ build_command_line (enum command_control_type type, char *args)
 /* Build and return a new command structure for the control commands
    such as "if" and "while".  */
 
-static struct command_line *
+struct command_line *
 get_command_line (enum command_control_type type, char *arg)
 {
   struct command_line *cmd;
@@ -225,6 +227,20 @@ print_command_lines (struct ui_out *uiout, struct command_line *cmd,
 	  continue;
 	}
 
+      if (list->control_type == python_control)
+	{
+	  ui_out_field_string (uiout, NULL, "python");
+	  ui_out_text (uiout, "\n");
+	  /* Don't indent python code at all.  */
+	  print_command_lines (uiout, *list->body_list, 0);
+	  if (depth)
+	    ui_out_spaces (uiout, 2 * depth);
+	  ui_out_field_string (uiout, NULL, "end");
+	  ui_out_text (uiout, "\n");
+	  list = list->next;
+	  continue;
+	}
+
       /* ignore illegal command type and try next */
       list = list->next;
     }				/* while (list) */
@@ -527,6 +543,12 @@ execute_control_command (struct command_line *cmd)
 	ret = commands_from_control_command (new_line, cmd);
 	break;
       }
+    case python_control:
+      {
+	eval_python_from_control_command (cmd);
+	ret = simple_control;
+	break;
+      }
 
     default:
       warning (_("Invalid control type in canned commands structure."));
@@ -538,6 +560,17 @@ execute_control_command (struct command_line *cmd)
   return ret;
 }
 
+/* Like execute_control_command, but first set
+   suppress_next_print_command_trace.   */
+
+enum command_control_type
+execute_control_command_untraced (struct command_line *cmd)
+{
+  suppress_next_print_command_trace = 1;
+  return execute_control_command (cmd);
+}
+
+
 /* "while" command support.  Executes a body of statements while the
    loop condition is nonzero.  */
 
@@ -552,8 +585,7 @@ while_command (char *arg, int from_tty)
   if (command == NULL)
     return;
 
-  suppress_next_print_command_trace = 1;
-  execute_control_command (command);
+  execute_control_command_untraced (command);
   free_command_lines (&command);
 }
 
@@ -571,8 +603,7 @@ if_command (char *arg, int from_tty)
   if (command == NULL)
     return;
 
-  suppress_next_print_command_trace = 1;
-  execute_control_command (command);
+  execute_control_command_untraced (command);
   free_command_lines (&command);
 }
 
@@ -886,6 +917,12 @@ read_next_line (struct command_line **command)
         first_arg++;
       *command = build_command_line (commands_control, first_arg);
     }
+  else if (p1 - p == 6 && !strncmp (p, "python", 6))
+    {
+      /* Note that we ignore the inline "python command" form
+	 here.  */
+      *command = build_command_line (python_control, "");
+    }
   else if (p1 - p == 10 && !strncmp (p, "loop_break", 10))
     {
       *command = (struct command_line *)
@@ -962,6 +999,7 @@ recurse_read_control_structure (struct command_line *current_cmd)
 	{
 	  if (current_cmd->control_type == while_control
 	      || current_cmd->control_type == if_control
+	      || current_cmd->control_type == python_control
 	      || current_cmd->control_type == commands_control)
 	    {
 	      /* Success reading an entire canned sequence of commands.  */
@@ -1013,6 +1051,7 @@ recurse_read_control_structure (struct command_line *current_cmd)
          on it.  */
       if (next->control_type == while_control
 	  || next->control_type == if_control
+	  || next->control_type == python_control
 	  || next->control_type == commands_control)
 	{
 	  control_level++;
@@ -1086,6 +1125,7 @@ read_command_lines (char *prompt_arg, int from_tty)
 
       if (next->control_type == while_control
 	  || next->control_type == if_control
+	  || next->control_type == python_control
 	  || next->control_type == commands_control)
 	{
 	  control_level++;
diff --git a/gdb/cli/cli-script.h b/gdb/cli/cli-script.h
index 42663dd..50ec1e1 100644
--- a/gdb/cli/cli-script.h
+++ b/gdb/cli/cli-script.h
@@ -40,6 +40,12 @@ extern void show_user_1 (struct cmd_list_element *c, struct ui_file *stream);
 extern enum command_control_type
 	execute_control_command (struct command_line *cmd);
 
+extern enum command_control_type
+	execute_control_command_untraced (struct command_line *cmd);
+
+extern struct command_line *get_command_line (enum command_control_type,
+					      char *);
+
 extern void print_command_lines (struct ui_out *,
 				 struct command_line *, unsigned int);
 
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 0a92812..370c21b 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -497,6 +497,125 @@ else
   fi
 fi
 
+dnl Utility to simplify finding libpython.
+AC_DEFUN([AC_TRY_LIBPYTHON],
+[
+  version=$1
+  define([have_libpython_var],$2)
+  define([VERSION],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+                                  [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+  [HAVE_LIB]VERSION=no
+  AC_MSG_CHECKING([for ${version}])
+  save_LIBS=$LIBS
+  LIBS="$LIBS -l${version}"
+  AC_LINK_IFELSE(AC_LANG_PROGRAM([[#include "${version}/Python.h"]],
+                                 [[Py_Initialize ();]]),
+                 [[HAVE_LIB]VERSION=yes
+                  have_libpython_var=yes],
+                 [LIBS=$save_LIBS])
+  AC_MSG_RESULT([$[HAVE_LIB]VERSION])
+])
+
+AC_ARG_WITH(python,
+  AS_HELP_STRING([--with-python], [include python support (auto/yes/no/<path>)]),
+  [], [with_python=auto])
+AC_MSG_CHECKING([whether to use python])
+AC_MSG_RESULT([$with_python])
+
+if test "${with_python}" = no; then
+  AC_MSG_WARN([python support disabled; some features may be unavailable.])
+  have_libpython=no
+else
+  case "${with_python}" in
+  yes | auto)
+    # Leave as empty, use defaults.
+    python_includes=
+    python_libs=
+    ;;
+  /*)
+    python_includes="-I${with_python}/include"
+    python_libs="-L${with_python}/lib"
+    ;;
+  *)
+    AC_ERROR(invalid value for --with-python)
+    ;;
+  esac
+
+  save_CPPFLAGS=$CPPFLAGS
+  CPPFLAGS="$CPPFLAGS ${python_includes}"
+  save_LIBS=$LIBS
+  LIBS="$LIBS ${python_libs}"
+  have_libpython=no
+  if test "${have_libpython}" = no; then
+    AC_TRY_LIBPYTHON(python2.6, have_libpython)
+    if test "${HAVE_LIBPYTHON2_6}" = yes; then
+      AC_DEFINE(HAVE_LIBPYTHON2_6, 1, [Define if Python 2.6 is being used.])
+    fi
+  fi
+  if test ${have_libpython} = no; then
+    AC_TRY_LIBPYTHON(python2.5, have_libpython)
+    if test "${HAVE_LIBPYTHON2_5}" = yes; then
+      AC_DEFINE(HAVE_LIBPYTHON2_5, 1, [Define if Python 2.5 is being used.])
+    fi
+  fi
+  if test ${have_libpython} = no; then
+    AC_TRY_LIBPYTHON(python2.4, have_libpython)
+    if test "${HAVE_LIBPYTHON2_4}" = yes; then
+      AC_DEFINE(HAVE_LIBPYTHON2_4, 1, [Define if Python 2.4 is being used.])
+    fi
+  fi
+  if test ${have_libpython} = no; then
+    case "${with_python}" in
+    yes)
+      AC_MSG_ERROR([python is missing or unusable])
+      ;;
+    auto)
+      AC_MSG_WARN([python is missing or unusable; some features may be unavailable.])
+      ;;
+    *)
+      AC_MSG_ERROR([no usable python found at ${with_python}])
+      ;;
+    esac
+    CPPFLAGS=$save_CPPFLAGS
+    LIBS=$save_LIBS
+  fi
+fi
+
+if test "${have_libpython}" = yes; then
+  AC_DEFINE(HAVE_PYTHON, 1, [Define if Python interpreter is being linked in.])
+  CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_PYTHON_OBS)"
+  CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_PYTHON_DEPS)"
+  CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_PYTHON_SRCS)"
+  ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)"
+
+  # Flags needed to compile Python code (taken from python-config --cflags).
+  # We cannot call python-config directly because it will output whatever was
+  # used when compiling the Python interpreter itself, including flags which
+  # would make the python-related objects be compiled differently from the
+  # rest of GDB (e.g., -O2 and -fPIC).
+  if test "${GCC}" = yes; then
+    tentative_python_cflags="-fno-strict-aliasing -DNDEBUG -fwrapv"
+  fi
+
+  if test "x${tentative_python_cflags}" != x; then
+    AC_MSG_CHECKING(compiler flags for python code)
+    for flag in ${tentative_python_cflags}; do
+      # Check that the compiler accepts it
+      saved_CFLAGS="$CFLAGS"
+      CFLAGS="$CFLAGS $flag"
+      AC_TRY_COMPILE([],[],PYTHON_CFLAGS="${PYTHON_CFLAGS} $flag",)
+      CFLAGS="$saved_CFLAGS"
+    done
+    AC_MSG_RESULT(${PYTHON_CFLAGS})
+  fi
+else
+  # Even if Python support is not compiled in, we need to have this file
+  # included in order to recognize the GDB command "python".
+  CONFIG_OBS="$CONFIG_OBS python.o"
+  CONFIG_SRCS="$CONFIG_SRCS python/python.c"
+fi
+AC_SUBST(PYTHON_CFLAGS)
+
 # ------------------------- #
 # Checks for header files.  #
 # ------------------------- #
diff --git a/gdb/defs.h b/gdb/defs.h
index 6e6aa80..7fe5934 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -652,6 +652,7 @@ enum command_control_type
     while_control,
     if_control,
     commands_control,
+    python_control,
     invalid_control
   };
 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 2920179..543dea8 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -159,7 +159,7 @@ software in general.  We will miss him.
 * Remote Debugging::            Debugging remote programs
 * Configurations::              Configuration-specific information
 * Controlling GDB::             Controlling @value{GDBN}
-* Sequences::                   Canned sequences of commands
+* Extending GDB::               Extending @value{GDBN}
 * Interpreters::		Command Interpreters
 * TUI::                         @value{GDBN} Text User Interface
 * Emacs::                       Using @value{GDBN} under @sc{gnu} Emacs
@@ -16847,8 +16847,21 @@ Turns on or off debugging messages for built-in XML parsers.
 Displays the current state of XML debugging messages.
 @end table
 
+@node Extending GDB
+@chapter Extending @value{GDBN}
+@cindex extending GDB
+
+@value{GDBN} provides two mechanisms for extension.  The first is based
+on composition of @value{GDBN} commands, and the second is based on the
+Python scripting language.
+
+@menu
+* Sequences::          Canned Sequences of Commands
+* Python::             Scripting @value{GDBN} using Python
+@end menu
+
 @node Sequences
-@chapter Canned Sequences of Commands
+@section Canned Sequences of Commands
 
 Aside from breakpoint commands (@pxref{Break Commands, ,Breakpoint
 Command Lists}), @value{GDBN} provides two ways to store sequences of
@@ -16863,7 +16876,7 @@ files.
 @end menu
 
 @node Define
-@section User-defined Commands
+@subsection User-defined Commands
 
 @cindex user-defined command
 @cindex arguments, to user-defined commands
@@ -16975,7 +16988,7 @@ commands that normally print messages to say what they are doing omit the
 messages when used in a user-defined command.
 
 @node Hooks
-@section User-defined Command Hooks
+@subsection User-defined Command Hooks
 @cindex command hooks
 @cindex hooks, for commands
 @cindex hooks, pre-command
@@ -17056,7 +17069,7 @@ If you try to define a hook which does not match any known command, you
 get a warning from the @code{define} command.
 
 @node Command Files
-@section Command Files
+@subsection Command Files
 
 @cindex command files
 @cindex scripting commands
@@ -17160,7 +17173,7 @@ Terminate the block of commands that are the body of @code{if},
 
 
 @node Output
-@section Commands for Controlled Output
+@subsection Commands for Controlled Output
 
 During the execution of a command file or a user-defined command, normal
 @value{GDBN} output is suppressed; the only output that appears is what is
@@ -17307,6 +17320,159 @@ printf "D32: %Hf - D64: %Df - D128: %DDf\n",1.2345df,1.2E10dd,1.2E1dl
 
 @end table
 
+@node Python
+@section Scripting @value{GDBN} using Python
+@cindex python scripting
+@cindex scripting with python
+
+You can script @value{GDBN} using the @uref{http://www.python.org/,
+Python programming language}.  This feature is available only if
+@value{GDBN} was configured using @option{--with-python}.
+
+@menu
+* Python Commands::             Accessing Python from @value{GDBN}.
+* Python API::                  Accessing @value{GDBN} from Python.
+@end menu
+
+@node Python Commands
+@subsection Python Commands
+@cindex python commands
+@cindex commands to access python
+
+@value{GDBN} provides one command for accessing the Python interpreter,
+and one related setting:
+
+@table @code
+@kindex python
+@item python @r{[}@var{code}@r{]}
+The @code{python} command can be used to evaluate Python code.
+
+If given an argument, the @code{python} command will evaluate the
+argument as a Python command.  For example:
+
+@smallexample
+(@value{GDBP}) python print 23
+23
+@end smallexample
+
+If you do not provide an argument to @code{python}, it will act as a
+multi-line command, like @code{define}.  In this case, the Python
+script is made up of subsequent command lines, given after the
+@code{python} command.  This command list is terminated using a line
+containing @code{end}.  For example:
+
+@smallexample
+(@value{GDBP}) python
+Type python script
+End with a line saying just "end".
+>print 23
+>end
+23
+@end smallexample
+
+@kindex maint set python print-stack
+@item maint set python print-stack
+By default, @value{GDBN} will print a stack trace when an error occurs
+in a Python script.  This can be controlled using @code{maint set
+python print-stack}: if @code{on}, the default, then Python stack
+printing is enabled; if @code{off}, then Python stack printing is
+disabled.
+@end table
+
+@node Python API
+@subsection Python API
+@cindex python api
+@cindex programming in python
+
+@cindex python stdout
+@cindex python pagination
+At startup, @value{GDBN} overrides Python's @code{sys.stdout} and
+@code{sys.stderr} to print using @value{GDBN}'s output-paging streams.
+A Python program which outputs to one of these streams may have its
+output interrupted by the user (@pxref{Screen Size}).  In this
+situation, a Python @code{KeyboardInterrupt} exception is thrown.
+
+@menu
+* Basic Python::                Basic Python Functions.
+* Exception Handling::
+@end menu
+
+@node Basic Python
+@subsubsection Basic Python
+
+@cindex python functions
+@cindex python module
+@cindex gdb module
+@value{GDBN} introduces a new Python module, named @code{gdb}.  All
+methods and classes added by @value{GDBN} are placed in this module.
+@value{GDBN} automatically @code{import}s the @code{gdb} module for
+use in all scripts evaluated by the @code{python} command.
+
+@findex gdb.execute
+@defun execute command
+Evaluate @var{command}, a string, as a @value{GDBN} CLI command.
+If a GDB exception happens while @var{command} runs, it is
+translated as described above.  If no exceptions occur, this
+function returns @code{None}.
+@end defun
+
+@findex gdb.get_parameter
+@defun get_parameter parameter
+Find the value of a @value{GDBN} parameter.  @var{parameter} is a
+string naming the parameter to look up; @var{parameter} may contain
+spaces if the parameter has a multi-part name.  For example,
+@samp{print object} is a valid parameter name.
+
+If the named parameter does not exist, this function throws a
+@code{RuntimeError}.  Otherwise, the parameter's value is converted to
+a Python value of the appropriate type, and returned.
+@end defun
+
+@findex gdb.write
+@defun write string
+Print a string to @value{GDBN}'s paginated standard output stream.
+Writing to @code{sys.stdout} or @code{sys.stderr} will automatically
+call this function.
+@end defun
+
+@findex gdb.flush
+@defun flush
+Flush @value{GDBN}'s paginated standard output stream.  Flushing
+@code{sys.stdout} or @code{sys.stderr} will automatically call this
+function.
+@end defun
+
+@node Exception Handling
+@subsubsection Exception Handling
+@cindex python exceptions
+@cindex exceptions, python
+
+When executing the @code{python} command, Python exceptions
+uncaught within the Python code are translated to calls to
+@value{GDBN} error-reporting mechanism.  If the command that called
+@code{python} does not handle the error, @value{GDBN} will
+terminate it and print an error message containing the Python
+exception name, the associated value, and the Python call stack
+backtrace at the point where the exception was raised.  Example:
+
+@smallexample
+(@value{GDBP}) python print foo
+Traceback (most recent call last):
+  File "<string>", line 1, in <module>
+NameError: name 'foo' is not defined
+@end smallexample
+
+@value{GDBN} errors that happen in @value{GDBN} commands invoked by Python
+code are converted to Python @code{RuntimeError} exceptions.  User
+interrupt (via @kbd{C-c} or by typing @kbd{q} at a pagination
+prompt) is translated to a Python @code{KeyboardInterrupt}
+exception.  If you catch these exceptions in your Python code, your
+exception handler will see @code{RuntimeError} or
+@code{KeyboardInterrupt} as the exception type, the @value{GDBN} error
+message as its value, and the Python call stack backtrace at the
+Python statement closest to where the @value{GDBN} error occured as the
+traceback.
+
 @node Interpreters
 @chapter Command Interpreters
 @cindex command interpreters
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
new file mode 100644
index 0000000..f850448
--- /dev/null
+++ b/gdb/python/python-internal.h
@@ -0,0 +1,71 @@
+/* Gdb/Python header for private use by Python module.
+
+   Copyright (C) 2008 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef GDB_PYTHON_INTERNAL_H
+#define GDB_PYTHON_INTERNAL_H
+
+/* Python 2.4 doesn't include stdint.h soon enough to get {u,}intptr_t
+   needed by pyport.h.  */
+#include <stdint.h>
+
+/* /usr/include/features.h on linux systems will define _POSIX_C_SOURCE
+   if it sees _GNU_SOURCE (which config.h will define).
+   pyconfig.h defines _POSIX_C_SOURCE to a different value than
+   /usr/include/features.h does causing compilation to fail.
+   To work around this, undef _POSIX_C_SOURCE before we include Python.h.  */
+#undef _POSIX_C_SOURCE
+
+#if HAVE_LIBPYTHON2_4
+#include "python2.4/Python.h"
+/* Py_ssize_t is not defined until 2.5.  */
+typedef Py_intptr_t Py_ssize_t;
+#elif HAVE_LIBPYTHON2_5
+#include "python2.5/Python.h"
+#elif HAVE_LIBPYTHON2_6
+#include "python2.6/Python.h"
+#else
+#error "Unable to find usable Python.h"
+#endif
+
+struct block;
+struct symbol;
+struct symtab_and_line;
+
+extern PyObject *gdb_module;
+
+struct cleanup *make_cleanup_py_decref (PyObject *py);
+
+/* Use this after a TRY_EXCEPT to throw the appropriate Python
+   exception.  */
+#define GDB_PY_HANDLE_EXCEPTION(Exception)				\
+    do {								\
+      if (Exception.reason < 0)						\
+	return PyErr_Format (Exception.reason == RETURN_QUIT		\
+			     ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \
+			     "%s", Exception.message);			\
+    } while (0)
+
+
+void gdbpy_print_stack (void);
+
+PyObject *python_string_to_unicode (PyObject *obj);
+char *unicode_to_target_string (PyObject *unicode_str);
+char *python_string_to_target_string (PyObject *obj);
+
+#endif /* GDB_PYTHON_INTERNAL_H */
diff --git a/gdb/python/python-utils.c b/gdb/python/python-utils.c
new file mode 100644
index 0000000..912845f
--- /dev/null
+++ b/gdb/python/python-utils.c
@@ -0,0 +1,117 @@
+/* General utility routines for GDB/Python.
+
+   Copyright (C) 2008 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "charset.h"
+#include "python-internal.h"
+
+
+/* This is a cleanup function which decrements the refcount on a
+   Python object.  */
+
+static void
+py_decref (void *p)
+{
+  PyObject *py = p;
+  /* Note that we need the extra braces in this 'if' to avoid a
+     warning from gcc.  */
+  if (py)
+    {
+      Py_DECREF (py);
+    }
+}
+
+/* Return a new cleanup which will decrement the Python object's
+   refcount when run.  */
+
+struct cleanup *
+make_cleanup_py_decref (PyObject *py)
+{
+  return make_cleanup (py_decref, (void *) py);
+}
+
+/* Converts a Python 8-bit string to a unicode string object.  Assumes the
+   8-bit string is in the host charset.  If an error occurs during conversion,
+   returns NULL with a python exception set.
+
+   As an added bonus, the functions accepts a unicode string and returns it
+   right away, so callers don't need to check which kind of string they've
+   got.
+
+   If the given object is not one of the mentioned string types, NULL is
+   returned, with the TypeError python exception set.  */
+PyObject *
+python_string_to_unicode (PyObject *obj)
+{
+  PyObject *unicode_str;
+
+  /* If obj is already a unicode string, just return it.
+     I wish life was always that simple...  */
+  if (PyUnicode_Check (obj))
+    unicode_str = obj;
+  else if (PyString_Check (obj))
+    unicode_str = PyUnicode_FromEncodedObject (obj, host_charset (), NULL);
+  else
+    {
+      PyErr_SetString (PyExc_TypeError,
+		       _("Expected a string or unicode object."));
+      unicode_str = NULL;
+    }
+
+  return unicode_str;
+}
+
+/* Returns a newly allocated string with the contents of the given unicode
+   string object converted to the target's charset.  If an error occurs during
+   the conversion, NULL will be returned and a python exception will be set.
+
+   The caller is responsible for xfree'ing the string.  */
+char *
+unicode_to_target_string (PyObject *unicode_str)
+{
+  char *target_string;
+  PyObject *string;
+
+  /* Translate string to target's charset.  */
+  string = PyUnicode_AsEncodedString (unicode_str, target_charset (), NULL);
+  if (string == NULL)
+    return NULL;
+
+  target_string = xstrdup (PyString_AsString (string));
+
+  Py_DECREF (string);
+
+  return target_string;
+}
+
+/* Converts a python string (8-bit or unicode) to a target string in
+   the target's charset.  Returns NULL on error, with a python exception set.
+
+   The caller is responsible for xfree'ing the string.  */
+char *
+python_string_to_target_string (PyObject *obj)
+{
+  PyObject *str;
+
+  str = python_string_to_unicode (obj);
+  if (str == NULL)
+    return NULL;
+
+  return unicode_to_target_string (str);
+}
diff --git a/gdb/python/python.c b/gdb/python/python.c
new file mode 100644
index 0000000..a560290
--- /dev/null
+++ b/gdb/python/python.c
@@ -0,0 +1,438 @@
+/* General python/gdb code
+
+   Copyright (C) 2008 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "command.h"
+#include "ui-out.h"
+#include "cli/cli-script.h"
+#include "gdbcmd.h"
+
+#include <ctype.h>
+
+/* True if we should print the stack when catching a Python error,
+   false otherwise.  */
+static int gdbpy_should_print_stack = 1;
+
+#ifdef HAVE_PYTHON
+
+#include "python.h"
+#include "libiberty.h"
+#include "cli/cli-decode.h"
+#include "charset.h"
+#include "top.h"
+#include "exceptions.h"
+#include "python-internal.h"
+#include "version.h"
+#include "target.h"
+#include "gdbthread.h"
+
+
+PyObject *gdb_module;
+
+static PyObject *get_parameter (PyObject *, PyObject *);
+static PyObject *execute_gdb_command (PyObject *, PyObject *);
+static PyObject *gdbpy_write (PyObject *, PyObject *);
+static PyObject *gdbpy_flush (PyObject *, PyObject *);
+
+static PyMethodDef GdbMethods[] =
+{
+  { "execute", execute_gdb_command, METH_VARARGS,
+    "Execute a gdb command" },
+  { "get_parameter", get_parameter, METH_VARARGS,
+    "Return a gdb parameter's value" },
+
+  { "write", gdbpy_write, METH_VARARGS,
+    "Write a string using gdb's filtered stream." },
+  { "flush", gdbpy_flush, METH_NOARGS,
+    "Flush gdb's filtered stdout stream." },
+
+  {NULL, NULL, 0, NULL}
+};
+
+/* Given a command_line, return a command string suitable for passing
+   to Python.  Lines in the string are separated by newlines.  The
+   return value is allocated using xmalloc and the caller is
+   responsible for freeing it.  */
+
+static char *
+compute_python_string (struct command_line *l)
+{
+  struct command_line *iter;
+  char *script = NULL;
+  int size = 0;
+  int here;
+
+  for (iter = l; iter; iter = iter->next)
+    size += strlen (iter->line) + 1;
+
+  script = xmalloc (size + 1);
+  here = 0;
+  for (iter = l; iter; iter = iter->next)
+    {
+      int len = strlen (iter->line);
+      strcpy (&script[here], iter->line);
+      here += len;
+      script[here++] = '\n';
+    }
+  script[here] = '\0';
+  return script;
+}
+
+/* Take a command line structure representing a 'python' command, and
+   evaluate its body using the Python interpreter.  */
+
+void
+eval_python_from_control_command (struct command_line *cmd)
+{
+  char *script;
+
+  if (cmd->body_count != 1)
+    error (_("Invalid \"python\" block structure."));
+
+  script = compute_python_string (cmd->body_list[0]);
+  PyRun_SimpleString (script);
+  xfree (script);
+  if (PyErr_Occurred ())
+    {
+      gdbpy_print_stack ();
+      error (_("error while executing Python code"));
+    }
+}
+
+/* Implementation of the gdb "python" command.  */
+
+static void
+python_command (char *arg, int from_tty)
+{
+  while (arg && *arg && isspace (*arg))
+    ++arg;
+  if (arg && *arg)
+    {
+      PyRun_SimpleString (arg);
+      if (PyErr_Occurred ())
+	{
+	  gdbpy_print_stack ();
+	  error (_("error while executing Python code"));
+	}
+    }
+  else
+    {
+      struct command_line *l = get_command_line (python_control, "");
+      struct cleanup *cleanups = make_cleanup_free_command_lines (&l);
+      execute_control_command_untraced (l);
+      do_cleanups (cleanups);
+    }
+}
+
+
+
+/* Transform a gdb parameters's value into a Python value.  May return
+   NULL (and set a Python exception) on error.  Helper function for
+   get_parameter.  */
+
+static PyObject *
+parameter_to_python (struct cmd_list_element *cmd)
+{
+  switch (cmd->var_type)
+    {
+    case var_string:
+    case var_string_noescape:
+    case var_optional_filename:
+    case var_filename:
+    case var_enum:
+      {
+	char *str = * (char **) cmd->var;
+	if (! str)
+	  str = "";
+	return PyString_Decode (str, strlen (str), host_charset (), NULL);
+      }
+
+    case var_boolean:
+      {
+	if (* (int *) cmd->var)
+	  Py_RETURN_TRUE;
+	else
+	  Py_RETURN_FALSE;
+      }
+
+    case var_auto_boolean:
+      {
+	enum auto_boolean ab = * (enum auto_boolean *) cmd->var;
+	if (ab == AUTO_BOOLEAN_TRUE)
+	  Py_RETURN_TRUE;
+	else if (ab == AUTO_BOOLEAN_FALSE)
+	  Py_RETURN_FALSE;
+	else
+	  Py_RETURN_NONE;
+      }
+
+    case var_integer:
+      if ((* (int *) cmd->var) == INT_MAX)
+	Py_RETURN_NONE;
+      /* Fall through.  */
+    case var_zinteger:
+      return PyLong_FromLong (* (int *) cmd->var);
+
+    case var_uinteger:
+      {
+	unsigned int val = * (unsigned int *) cmd->var;
+	if (val == UINT_MAX)
+	  Py_RETURN_NONE;
+	return PyLong_FromUnsignedLong (val);
+      }
+    }
+
+  return PyErr_Format (PyExc_RuntimeError, "programmer error: unhandled type");
+}
+
+/* A Python function which returns a gdb parameter's value as a Python
+   value.  */
+
+static PyObject *
+get_parameter (PyObject *self, PyObject *args)
+{
+  struct cmd_list_element *alias, *prefix, *cmd;
+  char *arg, *newarg;
+  volatile struct gdb_exception except;
+
+  if (! PyArg_ParseTuple (args, "s", &arg))
+    return NULL;
+
+  newarg = concat ("show ", arg, (char *) NULL);
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      if (! lookup_cmd_composition (newarg, &alias, &prefix, &cmd))
+	{
+	  xfree (newarg);
+	  return PyErr_Format (PyExc_RuntimeError,
+			       "could not find variable `%s'", arg);
+	}
+    }
+  xfree (newarg);
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  if (! cmd->var)
+    return PyErr_Format (PyExc_RuntimeError, "`%s' is not a variable", arg);
+  return parameter_to_python (cmd);
+}
+
+/* A Python function which evaluates a string using the gdb CLI.  */
+
+static PyObject *
+execute_gdb_command (PyObject *self, PyObject *args)
+{
+  struct cmd_list_element *alias, *prefix, *cmd;
+  char *arg, *newarg;
+  volatile struct gdb_exception except;
+  struct cleanup *old_chain;
+
+  if (! PyArg_ParseTuple (args, "s", &arg))
+    return NULL;
+
+  old_chain = make_cleanup (null_cleanup, 0);
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      execute_command (arg, 0);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  /* Do any commands attached to breakpoint we stopped at. Only if we
+     are always running synchronously. Or if we have just executed a
+     command that doesn't start the target. */
+  if (!target_can_async_p () || !is_running (inferior_ptid))
+    {
+      bpstat_do_actions (&stop_bpstat);
+      do_cleanups (old_chain);
+    }
+
+  Py_RETURN_NONE;
+}
+
+
+
+/* Printing.  */
+
+/* A python function to write a single string using gdb's filtered
+   output stream.  */
+static PyObject *
+gdbpy_write (PyObject *self, PyObject *args)
+{
+  char *arg;
+  if (! PyArg_ParseTuple (args, "s", &arg))
+    return NULL;
+  printf_filtered ("%s", arg);
+  Py_RETURN_NONE;
+}
+
+/* A python function to flush gdb's filtered output stream.  */
+static PyObject *
+gdbpy_flush (PyObject *self, PyObject *args)
+{
+  gdb_flush (gdb_stdout);
+  Py_RETURN_NONE;
+}
+
+/* Print a python exception trace, or print nothing and clear the
+   python exception, depending on gdbpy_should_print_stack.  Only call
+   this if a python exception is set.  */
+void
+gdbpy_print_stack (void)
+{
+  if (gdbpy_should_print_stack)
+    PyErr_Print ();
+  else
+    PyErr_Clear ();
+}
+
+#else /* HAVE_PYTHON */
+
+/* Dummy implementation of the gdb "python" command.  */
+
+static void
+python_command (char *arg, int from_tty)
+{
+  while (arg && *arg && isspace (*arg))
+    ++arg;
+  if (arg && *arg)
+    error (_("Python scripting is not supported in this copy of GDB."));
+  else
+    {
+      struct command_line *l = get_command_line (python_control, "");
+      struct cleanup *cleanups = make_cleanup_free_command_lines (&l);
+      execute_control_command_untraced (l);
+      do_cleanups (cleanups);
+    }
+}
+
+void
+eval_python_from_control_command (struct command_line *cmd)
+{
+  error (_("Python scripting is not supported in this copy of GDB."));
+}
+
+#endif /* HAVE_PYTHON */
+
+
+
+/* Lists for 'maint set python' commands.  */
+
+static struct cmd_list_element *set_python_list;
+static struct cmd_list_element *show_python_list;
+
+/* Function for use by 'maint set python' prefix command.  */
+
+static void
+set_python (char *args, int from_tty)
+{
+  help_list (set_python_list, "maintenance set python ", -1, gdb_stdout);
+}
+
+/* Function for use by 'maint show python' prefix command.  */
+
+static void
+show_python (char *args, int from_tty)
+{
+  cmd_show_list (show_python_list, from_tty, "");
+}
+
+/* Initialize the Python code.  */
+
+void
+_initialize_python (void)
+{
+  add_com ("python", class_obscure, python_command,
+#ifdef HAVE_PYTHON
+	   _("\
+Evaluate a Python command.\n\
+\n\
+The command can be given as an argument, for instance:\n\
+\n\
+    python print 23\n\
+\n\
+If no argument is given, the following lines are read and used\n\
+as the Python commands.  Type a line containing \"end\" to indicate\n\
+the end of the command.")
+#else /* HAVE_PYTHON */
+	   _("\
+Evaluate a Python command.\n\
+\n\
+Python scripting is not supported in this copy of GDB.\n\
+This command is only a placeholder.")
+#endif /* HAVE_PYTHON */
+	   );
+
+  add_prefix_cmd ("python", no_class, show_python,
+		  _("Prefix command for python maintenance settings."),
+		  &show_python_list, "maint show python ", 0,
+		  &maintenance_show_cmdlist);
+  add_prefix_cmd ("python", no_class, set_python,
+		  _("Prefix command for python maintenance settings."),
+		  &set_python_list, "maint set python ", 0,
+		  &maintenance_set_cmdlist);
+
+  add_setshow_boolean_cmd ("print-stack", class_maintenance,
+			   &gdbpy_should_print_stack, _("\
+Enable or disable printing of Python stack dump on error."), _("\
+Show whether Python stack will be printed on error."), _("\
+Enables or disables printing of Python stack traces."),
+			   NULL, NULL,
+			   &set_python_list,
+			   &show_python_list);
+
+#ifdef HAVE_PYTHON
+  Py_Initialize ();
+
+  gdb_module = Py_InitModule ("gdb", GdbMethods);
+
+  /* The casts to (char*) are for python 2.4.  */
+  PyModule_AddStringConstant (gdb_module, "VERSION", (char*) version);
+  PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", (char*) host_name);
+  PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", (char*) target_name);
+
+  PyRun_SimpleString ("import gdb");
+
+  /* Create a couple objects which are used for Python's stdout and
+     stderr.  */
+  PyRun_SimpleString ("\
+import sys\n\
+class GdbOutputFile:\n\
+  def close(self):\n\
+    # Do nothing.\n\
+    return None\n\
+\n\
+  def isatty(self):\n\
+    return False\n\
+\n\
+  def write(self, s):\n\
+    gdb.write(s)\n\
+\n\
+  def writelines(self, iterable):\n\
+    for line in iterable:\n\
+      self.write(line)\n\
+\n\
+  def flush(self):\n\
+    gdb.flush()\n\
+\n\
+sys.stderr = GdbOutputFile()\n\
+sys.stdout = GdbOutputFile()\n\
+");
+#endif /* HAVE_PYTHON */
+}
diff --git a/gdb/python/python.h b/gdb/python/python.h
new file mode 100644
index 0000000..00ff159
--- /dev/null
+++ b/gdb/python/python.h
@@ -0,0 +1,27 @@
+/* Python/gdb header for generic use in gdb
+
+   Copyright (C) 2008 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef GDB_PYTHON_H
+#define GDB_PYTHON_H
+
+#include "value.h"
+
+void eval_python_from_control_command (struct command_line *);
+
+#endif /* GDB_PYTHON_H */
diff --git a/gdb/testsuite/gdb.python/python.exp b/gdb/testsuite/gdb.python/python.exp
new file mode 100644
index 0000000..44037f2
--- /dev/null
+++ b/gdb/testsuite/gdb.python/python.exp
@@ -0,0 +1,66 @@
+# Copyright (C) 2008 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite.  It tests the mechanism
+# exposing values to Python.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test_multiple "python print 23" "verify python support" {
+    -re "not supported.*$gdb_prompt $"	{
+      unsupported "python support is disabled"
+      return -1
+    }
+    -re "$gdb_prompt $"	{}
+}
+
+# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}...
+# Run a test named NAME, consisting of multiple lines of input.
+# After each input line INPUT, search for result line RESULT.
+# Succeed if all results are seen; fail otherwise.
+proc gdb_py_test_multiple {name args} {
+    global gdb_prompt
+    foreach {input result} $args {
+	if {[gdb_test_multiple $input "$name - $input" {
+	    -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" {
+		pass "$name - $input"
+	    }
+	}]} {
+	    return 1
+	}
+    }
+    return 0
+}
+
+gdb_py_test_multiple "multi-line python command" \
+  "python" "" \
+  "print 23" "" \
+  "end" "23"
+
+gdb_py_test_multiple "show python command" \
+  "define zzq" "Type commands for definition of .* just \"end\"\\.*" \
+  "python" "" \
+  "print 23" "" \
+  "end" "" \
+  "end" "" \
+  "show user zzq" "User command zzq:.*  python.*print 23.*  end"





More information about the Gdb-patches mailing list