Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: thiagoju@linux.ibm.com
To: Daniel Jacobowitz <drow@false.org>
Cc: Thiago Jung Bauermann <bauerman@br.ibm.com>, gdb-patches@sourceware.org
Subject: Re: [RFC][patch 1/9] initial Python support
Date: Sun, 15 Jun 2008 22:35:00 -0000	[thread overview]
Message-ID: <20080615181833.uxmo25mg0kko40kw@imap.linux.ibm.com> (raw)
In-Reply-To: <20080528205921.GA2969@caradoc.them.org>

[-- Attachment #1: Type: text/plain, Size: 4989 bytes --]

Zitat von Daniel Jacobowitz <drow@false.org>:
> Looks generally good.

Good, I'm generally happy then. :-)

> For the general syntax: Should we allow $() to always mean Python, or
> are there other useful potential scripting interfaces or environment
> variable access or anything, in which case we want $(python ) or $(P )
> or $python( )?  There are only so many nice grouping specifiers.  $<>
> is not so good but we still have $[] and ${}, plus $env().  I don't
> remember if we discussed this before, but we may have.

This discussion is still being carried out. In the interest of having
at least the very basic committed soon, I removed support for Python
evalution inside expressions for this patch. This is now in a separate
patch in the python-patches branch. There, you will also find another
patch which Tromey is developing implementing his other proposal
(i.e., registering functions and then using $(func args) syntax).

The downside is that this patch adds near zero value to the user.
But all other patches build on this one.

> We've discussed already the configure options - I'd prefer to avoid
> this issue and only have --with-python and maybe
> --with-python-lib/--with-python-include.  Parallel to the top level
> gmp/mpfr handling, for instance.

This patch now sports the shiny new --with-python code brought to you
by Doug Evans.

> I didn't know about python-config.  Is that new?  Could we specify a
> path to python-config instead of messing with cflags/ldflags directly?

Yes we could, but I didn't experiment with the idea...

> And we sorted this out on IRC.

Hooray for IRC. :-)

> The special_processing argument to read_next_line / read_command_lines
> is not commented and the name doesn't say much of anything about what
> it's for.  It looks like this changes the behavior of document versus
> define, probably deliberately if it does what I think it does.  So
> this would be a good patch to split out separately.  In general, any
> bits that can go in separately should; it makes the whole pile easier
> to manage :-)

You are right, I didn't know why these changes were there as well but at
the time I kept them in the patch anyway. They seem to be useful only to
varobj/MI Python bindings by Vladimir, and I separated them in another
patch (found in the python-patches branch).

> There are too many #ifdef's in the rest of GDB in this patch, IMO.
> Can python/python.h be included unconditionally, not include
> python-internal.h, and have the exposed interfaces error() when Python
> support is not compiled in?  That's the approach I took for
> xml-support.h.
>
> Similarly we should recognize python_control regardless of
> HAVE_PYTHON.  That way we can parse a .gdbinit which defines Python
> commands and give a sensible error only if they are invoked.

Done, courtesy of Tom Tromey.

> In general I would prefer we not commit any FIXMEs.  We can decide now
> what the right thing to do is and if there is room for future
> enhancement, that's not a FIXME any more :-)

All FIXMEs in this patch are now gone (also by Tromey).

> > +
> > +void
> > +eval_python_from_control_command (struct command_line *cmd)
> > +{
> > +  char *script;
> > +
> > +  if (cmd->body_count != 1)
> > +    error (_("Invalid \"python\" block structure."));
> > +
> > +  demand_python ();
> > +
> > +  script = compute_python_string (cmd->body_list[0]);
> > +  PyRun_SimpleString (script);
> > +  xfree (script);
> > +  if (PyErr_Occurred ())
> > +    {
> > +      PyErr_Print ();
> > +      error ("error while executing Python code");
> > +    }
> > +}
>
> _() around arguments to error.  Also, in general PyErr_Print is
> probably dumping to stderr?  Output should go through GDB's error
> mechanisms, and in this case probably be part of the argument to
> error.  Can you get it to return an error string instead?

This is stillpending, I think.

> > +static PyObject *
> > +execute_gdb_command (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;
> > +
> > +  TRY_CATCH (except, RETURN_MASK_ALL)
> > +    {
> > +      execute_command (arg, 0);
> > +    }
> > +  GDB_PY_HANDLE_EXCEPTION (except);
> > +
> > +  /* gdbtk does bpstat_do_actions here... */
>
> Please figure out if we need to or not.  It looks like we do; running
> the command "continue" to a breakpoint with actions will test it.

I don't know much about bpstat_do_actions, and didn't do the experiment
you mention (not sure I understood it), so I made a crude try at adding
a call to bpstat_do_actions just to get this patch out.

> Speaking of which... a testsuite? :-)

Next in my list!
-- 
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center





[-- Attachment #2: python-basic.diff --]
[-- Type: text/x-patch, Size: 25600 bytes --]

2008-06-15  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.
	(COMMON_OBS): Add python.o.
	(INIT_FILES): Add python/python.c.
	(cli-script.o): Depend on python.h
	(python.o): New.
	* cli/cli-script.c (print_command_lines): Handle python_control.
	(execute_control_command): Handle python_control.
	(execute_control_command_suppressed): New function.
	(while_command): Call execute_control_command_suppressed.
	(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_suppressed): 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.

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 9304bc2..09fdc34 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -254,6 +254,16 @@ SUBDIR_TUI_LDFLAGS=
 SUBDIR_TUI_CFLAGS= \
 	-DTUI=1
 
+#
+# python sub directory definitons
+#
+SUBDIR_PYTHON_OBS =
+SUBDIR_PYTHON_SRCS = \
+	python/python.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 +973,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)
@@ -1081,7 +1098,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	tramp-frame.o \
 	solib.o solib-null.o \
 	prologue-value.o memory-map.o xml-support.o \
-	target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o
+	target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \
+	python.o
 
 TSOBS = inflow.o
 
@@ -1275,7 +1293,11 @@ test-cp-name-parser$(EXEEXT): test-cp-name-parser.o $(LIBIBERTY)
 # duplicates.  Files in the gdb/ directory can end up appearing in
 # COMMON_OBS (as a .o file) and CONFIG_SRCS (as a .c file).
 
-INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS)
+# NOTE: bauermann/2008-06-15: python.c needs to be explicitly included
+# because the generation of init.c does not work for .c files which
+# result in differently named objects (i.e., python/python -> python.o).
+
+INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS) python/python.c
 init.c: $(INIT_FILES)
 	@echo Making init.c
 	@rm -f init.c-tmp init.l-tmp
@@ -3051,7 +3073,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) \
@@ -3375,4 +3398,19 @@ 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 (taken from python-config --cflags)
+PYTHON_CFLAGS=-fno-strict-aliasing -DNDEBUG -fwrapv
+
+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)
+	$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
+
 ### end of the gdb Makefile.in.
diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index e6fbe3f..69fd3c7 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,18 @@ 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");
+	  print_command_lines (uiout, *list->body_list, depth + 1);
+	  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 +541,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 +558,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_suppressed (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 +583,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_suppressed (command);
   free_command_lines (&command);
 }
 
@@ -571,8 +601,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_suppressed (command);
   free_command_lines (&command);
 }
 
@@ -886,6 +915,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 +997,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 +1049,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 +1123,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..7416e1c 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_suppressed (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 101dedf..0adc9fd 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -485,6 +485,99 @@ 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)"
+  CONFIG_INITS="$CONFIG_INITS \$(SUBDIR_PYTHON_INITS)"
+  ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)"
+fi
+
 # ------------------------- #
 # Checks for header files.  #
 # ------------------------- #
diff --git a/gdb/defs.h b/gdb/defs.h
index 2af40ab..98d3f7c 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -642,6 +642,7 @@ enum command_control_type
     while_control,
     if_control,
     commands_control,
+    python_control,
     invalid_control
   };
 
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
new file mode 100644
index 0000000..d39724c
--- /dev/null
+++ b/gdb/python/python-internal.h
@@ -0,0 +1,60 @@
+/* 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.  */
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+/* /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
+
+extern PyObject *gdb_module;
+
+/* 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)
+
+#endif /* GDB_PYTHON_INTERNAL_H */
diff --git a/gdb/python/python.c b/gdb/python/python.c
new file mode 100644
index 0000000..89e136c
--- /dev/null
+++ b/gdb/python/python.c
@@ -0,0 +1,324 @@
+/* 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 <ctype.h>
+
+#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"
+
+
+PyObject *gdb_module;
+
+static PyObject *get_show_variable (PyObject *, PyObject *);
+static PyObject *execute_gdb_command (PyObject *, PyObject *);
+
+static PyMethodDef GdbMethods[] =
+{
+  { "execute", execute_gdb_command, METH_VARARGS,
+    "Execute a gdb command" },
+  { "show", get_show_variable, METH_VARARGS,
+    "Return a gdb setting's value" },
+
+  {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) + 1;
+      strcpy (&script[here], iter->line);
+      here += len;
+      script[here++] = '\n';
+    }
+  script[here] = '\0';
+  return script;
+}
+
+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 ())
+    {
+      PyErr_Print ();
+      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 ())
+	{
+	  PyErr_Print ();
+	  error (_("error while executing Python code"));
+	}
+    }
+  else
+    {
+      char *tmpbuf = xstrprintf ("Type python script");
+      struct cleanup *cleanups = make_cleanup (xfree, tmpbuf);
+      struct command_line *l = get_command_line (python_control, "");
+      cleanups = make_cleanup_free_command_lines (&l);
+      execute_control_command_suppressed (l);
+      do_cleanups (cleanups);
+    }
+}
+
+\f
+
+/* Transform a gdb variable's value into a Python value.  May return
+   NULL (and set a Python exception) on error.  Helper function for
+   get_show_variable.  */
+
+static PyObject *
+variable_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 variable's value as a Python
+   value.  */
+
+static PyObject *
+get_show_variable (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 variable_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 () || !target_executing)
+    {
+      bpstat_do_actions (&stop_bpstat);
+      do_cleanups (old_chain);
+    }
+
+  Py_RETURN_NONE;
+}
+
+\f
+
+/* Initialize the Python code.  */
+
+void
+_initialize_python (void)
+{
+  add_com ("python", class_obscure, python_command, _("\
+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."));
+
+  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");
+}
+
+#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
+    {
+      char *tmpbuf = xstrprintf ("Type python script");
+      struct cleanup *cleanups = make_cleanup (xfree, tmpbuf);
+      struct command_line *l = get_command_line (python_control, "");
+      cleanups = make_cleanup_free_command_lines (&l);
+      execute_control_command_suppressed (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."));
+}
+
+/* Initialize dummy Python code.  */
+
+void
+_initialize_python (void)
+{
+  add_com ("python", class_obscure, python_command, _("\
+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 */
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 */

  parent reply	other threads:[~2008-06-15 22:19 UTC|newest]

Thread overview: 147+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-04-29 15:59 [RFC][patch 0/9] Python support in GDB Thiago Jung Bauermann
2008-04-29 15:59 ` [RFC][patch 8/9] export symtab mechanism to Python Thiago Jung Bauermann
2008-04-29 15:59 ` [RFC][patch 6/9] export frames " Thiago Jung Bauermann
2008-04-29 15:59 ` [RFC][patch 9/9] export threads " Thiago Jung Bauermann
2008-04-29 15:59 ` [RFC][patch 3/9] export hooks mechanism " Thiago Jung Bauermann
2008-04-29 21:29   ` Tom Tromey
2008-04-30 18:27     ` Joel Brobecker
2008-04-30 21:30       ` Tom Tromey
2008-05-27 18:22         ` Tom Tromey
2008-04-30 18:29     ` Daniel Jacobowitz
2008-04-30 23:00       ` Tom Tromey
2008-05-29  7:55   ` Daniel Jacobowitz
2008-05-30 14:59     ` Tom Tromey
2008-06-15 22:53       ` Thiago Jung Bauermann
2008-06-15 22:58         ` Tom Tromey
2008-06-16  3:22           ` Daniel Jacobowitz
2008-06-17 18:13             ` Thiago Jung Bauermann
2008-06-17 22:20               ` Joel Brobecker
2008-06-23 17:58                 ` Tom Tromey
2008-04-29 15:59 ` [RFC][patch 5/9] permit GDB commands implemented in Python Thiago Jung Bauermann
2008-04-29 16:08 ` [RFC][patch 7/9] export block and symbol mechanism to Python Thiago Jung Bauermann
2008-04-29 18:11 ` [RFC][patch 4/9] export breakpoints " Thiago Jung Bauermann
2008-04-29 18:15 ` [RFC][patch 1/9] initial Python support Thiago Jung Bauermann
2008-05-05  8:12   ` Thiago Jung Bauermann
2008-05-05 14:39     ` Daniel Jacobowitz
2008-05-05 14:46       ` Thiago Jung Bauermann
2008-05-05 16:50         ` Daniel Jacobowitz
2008-05-06  2:38           ` Thiago Jung Bauermann
2008-05-11 22:24           ` Thiago Jung Bauermann
2008-05-11 22:26             ` Daniel Jacobowitz
2008-05-12 20:33               ` Thiago Jung Bauermann
2008-05-12 20:39                 ` Daniel Jacobowitz
2008-05-12 21:00                   ` Thiago Jung Bauermann
2008-05-29  0:29   ` Daniel Jacobowitz
2008-05-30 13:07     ` Function syntax (Was: [RFC][patch 1/9] initial Python support) Tom Tromey
2008-06-08 15:24       ` Doug Evans
2008-06-08 15:32         ` Function syntax Tom Tromey
2008-06-08 18:21       ` Function syntax (Was: [RFC][patch 1/9] initial Python support) Daniel Jacobowitz
2008-06-09 13:48         ` Thiago Jung Bauermann
2008-06-09 18:43           ` Daniel Jacobowitz
2008-06-10  0:24             ` Function syntax Tom Tromey
2008-06-10  0:04           ` Tom Tromey
2008-06-11  0:04             ` Thiago Jung Bauermann
2008-06-10  0:00         ` Tom Tromey
2008-05-30 14:47     ` [RFC][patch 1/9] initial Python support Tom Tromey
2008-06-15 22:35     ` thiagoju [this message]
2008-06-23 17:36       ` Tom Tromey
2008-07-06 17:28         ` Tom Tromey
2008-07-08  4:12           ` Thiago Jung Bauermann
2008-07-15  7:38       ` [RFA] " Thiago Jung Bauermann
2008-07-15 17:19         ` Tom Tromey
2008-07-15 18:33           ` Thiago Jung Bauermann
2008-07-15 19:03             ` Tom Tromey
2008-07-16  7:14               ` Thiago Jung Bauermann
2008-07-16 14:39           ` Tom Tromey
2008-07-16 22:02             ` Thiago Jung Bauermann
2008-07-18 19:50               ` Daniel Jacobowitz
2008-07-18 23:24                 ` Tom Tromey
2008-07-19  0:45                   ` Daniel Jacobowitz
2008-07-19 19:50                 ` [RFA] iRe: " Thiago Jung Bauermann
2008-07-19 21:13                   ` Daniel Jacobowitz
2008-07-19 22:13                     ` Thiago Jung Bauermann
2008-07-20 23:47                   ` Thiago Jung Bauermann
2008-07-21  2:03                     ` Daniel Jacobowitz
2008-07-23 17:46                       ` [obvious] Wipe out CONFIG_INITS Thiago Jung Bauermann
2008-07-20 22:43                 ` [RFA] Re: [RFC][patch 1/9] initial Python support Tom Tromey
2008-07-21  1:59                   ` Daniel Jacobowitz
2008-07-21 15:29                 ` [RFA][patch 1/9] Yet another respin of the patch with " Thiago Jung Bauermann
2008-07-21 16:47                   ` Thiago Jung Bauermann
2008-07-26 13:07                   ` Eli Zaretskii
2008-07-26 13:43                     ` Daniel Jacobowitz
2008-07-26 14:02                       ` Eli Zaretskii
2008-07-26 14:42                         ` Daniel Jacobowitz
2008-07-26 17:06                           ` Eli Zaretskii
2008-07-26 17:26                             ` Tom Tromey
2008-07-26 19:21                               ` Eli Zaretskii
2008-07-26 17:40                             ` Daniel Jacobowitz
2008-07-26 17:10                           ` Tom Tromey
2008-07-26 17:40                             ` Eli Zaretskii
2008-07-26 18:00                               ` Tom Tromey
2008-07-26 18:29                                 ` Eli Zaretskii
2008-07-26 18:45                                   ` Tom Tromey
2008-07-26 19:34                                     ` Eli Zaretskii
2008-07-30 14:59                                       ` Thiago Jung Bauermann
2008-07-30 17:57                                         ` Eli Zaretskii
2008-08-04  4:44                                           ` Thiago Jung Bauermann
2008-08-04 19:18                                             ` Eli Zaretskii
2008-08-05  3:42                                               ` Thiago Jung Bauermann
2008-07-26 17:04                     ` Tom Tromey
2008-07-26 17:35                       ` Daniel Jacobowitz
2008-07-26 17:42                         ` Tom Tromey
2008-07-26 19:18                           ` Eli Zaretskii
2008-08-04  2:52                             ` Thiago Jung Bauermann
2008-08-04  3:22                               ` Eli Zaretskii
2008-08-04 12:15                                 ` Daniel Jacobowitz
2008-08-04 19:50                                   ` Eli Zaretskii
2008-08-05  2:08                                     ` Daniel Jacobowitz
2008-08-05  2:41                                       ` Thiago Jung Bauermann
2008-08-05  3:32                                       ` Eli Zaretskii
2008-08-05 12:19                                         ` Daniel Jacobowitz
2008-08-05 18:10                                           ` Eli Zaretskii
2008-08-05 18:23                                             ` Daniel Jacobowitz
2008-08-05 18:50                                               ` Eli Zaretskii
2008-08-05 18:58                                                 ` Daniel Jacobowitz
2008-07-26 19:20                         ` Eli Zaretskii
2008-07-26 18:11                       ` Eli Zaretskii
2008-07-26 18:30                         ` Daniel Jacobowitz
2008-07-26 19:26                           ` Eli Zaretskii
2008-08-01 20:04                           ` Tom Tromey
2008-08-02 17:38                             ` Daniel Jacobowitz
2008-08-02 17:50                               ` Tom Tromey
2008-08-02 19:00                               ` Eli Zaretskii
2008-08-05  4:19                         ` Thiago Jung Bauermann
2008-08-05 18:14                           ` Eli Zaretskii
2008-08-06  5:35                             ` [RFA][patch 1/9] Initial Python support, patch du jour Thiago Jung Bauermann
2008-08-06 18:24                               ` Eli Zaretskii
2008-08-06 19:53                                 ` Thiago Jung Bauermann
2008-08-04  4:44                     ` [RFA][patch 1/9] Yet another respin of the patch with initial Python support Thiago Jung Bauermann
2008-08-04 19:22                       ` Eli Zaretskii
2008-08-05  1:24                         ` Thiago Jung Bauermann
2008-08-02 17:41                   ` Daniel Jacobowitz
2008-08-02 19:02                     ` Eli Zaretskii
2008-08-02 19:07                       ` Daniel Jacobowitz
2008-07-15 18:01         ` [RFA] Re: [RFC][patch 1/9] " Thiago Jung Bauermann
2008-04-29 18:17 ` [RFC][patch 2/9] export values mechanism to Python Thiago Jung Bauermann
2008-05-29  1:23   ` Daniel Jacobowitz
2008-06-03  0:19     ` Tom Tromey
2008-06-03 13:04       ` Daniel Jacobowitz
2008-06-03 14:52         ` Tom Tromey
2008-07-07  6:03       ` Thiago Jung Bauermann
2008-07-07 23:44         ` Tom Tromey
2008-07-26  2:55           ` Daniel Jacobowitz
2008-07-26 17:17             ` Tom Tromey
2008-07-26 17:41               ` Daniel Jacobowitz
2008-07-30  3:01                 ` Tom Tromey
2008-07-30 14:26                   ` Thiago Jung Bauermann
2008-08-13  6:45         ` [python] acessing struct elements Thiago Jung Bauermann
2008-08-13 12:38           ` Daniel Jacobowitz
2008-08-13 20:38             ` Thiago Jung Bauermann
2008-08-17 20:16           ` Tom Tromey
2008-04-29 18:38 ` [RFC][patch 0/9] Python support in GDB Eli Zaretskii
2008-04-29 20:37   ` Thiago Jung Bauermann
2008-04-29 21:22     ` Tom Tromey
2008-04-30  7:54       ` Eli Zaretskii
2008-04-30 19:38         ` Thiago Jung Bauermann
2008-04-30 19:52           ` Eli Zaretskii
2008-05-02 18:30 ` Vladimir Prus

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080615181833.uxmo25mg0kko40kw@imap.linux.ibm.com \
    --to=thiagoju@linux.ibm.com \
    --cc=bauerman@br.ibm.com \
    --cc=drow@false.org \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox