From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15445 invoked by alias); 3 Jan 2009 23:09:25 -0000 Received: (qmail 15435 invoked by uid 22791); 3 Jan 2009 23:09:22 -0000 X-SWARE-Spam-Status: No, hits=-0.3 required=5.0 tests=AWL,BAYES_50,J_CHICKENPOX_35,J_CHICKENPOX_37,J_CHICKENPOX_51,J_CHICKENPOX_53,SPF_PASS X-Spam-Check-By: sourceware.org Received: from igw3.br.ibm.com (HELO igw3.br.ibm.com) (32.104.18.26) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 03 Jan 2009 23:09:16 +0000 Received: from d24relay01.br.ibm.com (unknown [9.8.31.16]) by igw3.br.ibm.com (Postfix) with ESMTP id A7ED9390009 for ; Sat, 3 Jan 2009 21:04:21 -0200 (BRDT) Received: from d24av02.br.ibm.com (d24av02.br.ibm.com [9.18.232.47]) by d24relay01.br.ibm.com (8.13.8/8.13.8/NCO v9.1) with ESMTP id n0408gwi3915846 for ; Sat, 3 Jan 2009 21:08:42 -0300 Received: from d24av02.br.ibm.com (loopback [127.0.0.1]) by d24av02.br.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id n03N99SP023773 for ; Sat, 3 Jan 2009 21:09:09 -0200 Received: from [9.18.196.120] ([9.18.196.120]) by d24av02.br.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id n03N98DH023764; Sat, 3 Jan 2009 21:09:08 -0200 Subject: Re: [RFC][python] Fixes and improvements to gdb.Value. From: Thiago Jung Bauermann To: Eli Zaretskii Cc: gdb-patches@sourceware.org In-Reply-To: References: <1230949500.8380.140.camel@localhost.localdomain> Content-Type: text/plain; charset=utf-8 Date: Sat, 03 Jan 2009 23:09:00 -0000 Message-Id: <1231024147.8380.166.camel@localhost.localdomain> Mime-Version: 1.0 Content-Transfer-Encoding: 8bit X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2009-01/txt/msg00016.txt.bz2 Hi Eli, El sáb, 03-01-2009 a las 11:41 +0200, Eli Zaretskii escribió: > > * gdb.texinfo (Basic Python): Document gdb.history. > > This part is approved, but I have a few comments: Thanks for the review and the comments. The patch below addresses them, and removes the copyright updates since they were already made. > > +@findex gdb.history > > The text below this does not mention "gdb.history" at all. Should it? > I could imagine a reader who gets here by following the "gdb.history" > index entry, and is then puzzled by not finding that text anywhere. Well, the text is in the section which describes functions in the gdb module, so the reader should be aware that the function is inside it. Also, in Python "gdb.history" wouldn't be the only possible way of referencing the function. If the user imports the gdb module with "from gdb import *", then he would just need to type "history" to use it. "gdb.history" is only special in that from the CLI, the gdb module is automatically imported and would be accessible to the user spelled like that. But (s)he could type "python from gdb import *" and then use the other way to access it. In a nutshell, my answer is "no, I don't think it should". :-) > > +If @var{number} is less than or equal to zero, then @value{GDBN} will > > +take the absolute value of @var{number} and count backward from the > > +last element to find the value to return. > > For clarity, I'd separate the zero case and the negative case. First, > "is less than or equal to zero" is a mouthful that would be eliminated > then; you could simply say "negative". And second, "count zero > elements backward" is an abstraction that is a better avoided. Good point. I reworded it to: If @var{number} is negative, then @value{GDBN} will take its absolute value and count backward from the last element (i.e., the most recent element) to find the value to return. If @var{number} is zero, then @value{GDBN} will return the most recent element. If the element specified by @value{number} doesn't exist in the value history, a @code{RuntimeError} exception will be raised. What do you think? > > If there is no such element > > +in the value history, an exception will be raised. > > Should we say which exception will be raised, and perhaps have a > cross-reference to where exceptions raised in Python code are > described? I changed it to mention that the RuntimeError exception will be raised. Since exceptions are a common occurence in Python (and in GDB's Python API), I think we would have too many references to the exceptions section if we added a link to it from every place which mentions exceptions. > > +The return value is always an instance of @code{gdb.Value} > > +(@pxref{Values From Inferior}). > > +@end defun > > I'd modify this thusly: > > If no exception is raised, the return value is always an instance of > @code{gdb.Value} (@pxref{Values From Inferior}). > > The point is that we should be crystal clear that a value is returned > only if there's no exception (since there are languages where an > exception, too, can return a value), and that "always" does not > include the case with an exception. Right. I wasn't aware that in some languages functions can both return a value and raise an exception. I adopted your wording. > > + string object converted to a named 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) > > +static char * > > +unicode_to_encoded_string (PyObject *unicode_str, const char *charset) > > I think our convention is to up-case references to arguments in > comments that describe the function. So please use "named CHARSET" in > the above comment. Changed. > > +/* Converts a python string (8-bit or unicode) to a target string in > > Is 8-bit and Unicode the only 2 alternatives here? IOW, doesn;t this > support Far Eastern multibyte encodings, such as ISO-2022, Big-5, > etc.? Sorry if I'm talking nonsense out of ignorance about Python's > support of non-ASCII characters. Yes, Python only has those two types of string objects. I'm no expert, but I think multibyte encodings can be represented in 8-bit Python strings. They are ill named, with "8-bit string" they really mean "array of uninterpreted bytes". In Python 3.0, "Unicode string" is now called "str", and "8-bit string" is called "bytes". -- []'s Thiago Jung Bauermann IBM Linux Technology Center gdb/ 2009-01-03 Tom Tromey Thiago Jung Bauermann * python/python-internal.h (gdbpy_get_value_from_history): Rename prototype to gdbpy_history. (gdbpy_is_string): Declare. (python_string_to_host_string): Declare. * python/python-utils.c (gdbpy_is_string): New function. (unicode_to_encoded_string): New function. (unicode_to_target_string): Use it. (python_string_to_host_string): New function. * python/python-value.c (valpy_address): New function. (valpy_getitem): Convert field name to host string. Handle array accesses. (enum valpy_opcode) : New constants. (valpy_binop): Update. (valpy_invert): New function. (valpy_lsh): Likewise. (valpy_rsh): Likewise. (valpy_and): Likewise. (valpy_or): Likewise. (valpy_xor): Likewise. (valpy_richcompare): Call convert_value_from_python instead of doing conversions itself. (is_intlike, valpy_int, valpy_long, valpy_float): New functions. (convert_value_from_python): Use gdbpy_is_string. Clear Python exception and throw GDB exception if python_string_to_target_string fails. (gdbpy_get_value_from_history): Rename function to gdbpy_history. (gdbpy_initialize_values): Don't set tp_new. (value_object_type): Add valpy_new. (value_object_methods): Add `address' entry. (value_object_as_number): Update for new methods. * python/python.c (GdbMethods): Rename entry from `get_value_from_history' to `history'. gdb/doc/ 2009-01-03 Tom Tromey * gdb.texinfo (Basic Python): Document gdb.history. gdb/testsuite/ 2009-01-03 Tom Tromey Thiago Jung Bauermann * gdb.python/python-value.exp: Use `gdb.history' instead of `gdb.value_from_history'. (test_value_numeric_ops): Add test for conversion of enum constant. * gdb.python/python-value.c (enum e): New type. (evalue): New global. (main): Use argv. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 6ef124c..4f7888e 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -1,6 +1,6 @@ \input texinfo @c -*-texinfo-*- @c Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, -@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 @c Free Software Foundation, Inc. @c @c %**start of header @@ -18086,6 +18086,21 @@ If the named parameter does not exist, this function throws a a Python value of the appropriate type, and returned. @end defun +@findex gdb.history +@defun history number +Return a value from @value{GDBN}'s value history (@pxref{Value +History}). @var{number} indicates which history element to return. +If @var{number} is negative, then @value{GDBN} will take its absolute value +and count backward from the last element (i.e., the most recent element) to +find the value to return. If @var{number} is zero, then @value{GDBN} will +return the most recent element. If the element specified by @value{number} +doesn't exist in the value history, a @code{RuntimeError} exception will be +raised. + +If no exception is raised, the return value is always an instance of +@code{gdb.Value} (@pxref{Values From Inferior}). +@end defun + @findex gdb.write @defun write string Print a string to @value{GDBN}'s paginated standard output stream. diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index 24d1b44..bcd37e4 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -60,7 +60,7 @@ struct value; extern PyObject *gdb_module; extern PyTypeObject value_object_type; -PyObject *gdbpy_get_value_from_history (PyObject *self, PyObject *args); +PyObject *gdbpy_history (PyObject *self, PyObject *args); PyObject *value_to_value_object (struct value *v); @@ -87,5 +87,7 @@ 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); +char *python_string_to_host_string (PyObject *obj); +int gdbpy_is_string (PyObject *obj); #endif /* GDB_PYTHON_INTERNAL_H */ diff --git a/gdb/python/python-utils.c b/gdb/python/python-utils.c index 9aae43f..6a95939 100644 --- a/gdb/python/python-utils.c +++ b/gdb/python/python-utils.c @@ -95,26 +95,37 @@ python_string_to_unicode (PyObject *obj) } /* 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. + string object converted to 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) +static char * +unicode_to_encoded_string (PyObject *unicode_str, const char *charset) { - char *target_string; + char *result; PyObject *string; - /* Translate string to target's charset. */ - string = PyUnicode_AsEncodedString (unicode_str, target_charset (), NULL); + /* Translate string to named charset. */ + string = PyUnicode_AsEncodedString (unicode_str, charset, NULL); if (string == NULL) return NULL; - target_string = xstrdup (PyString_AsString (string)); + result = xstrdup (PyString_AsString (string)); Py_DECREF (string); - return target_string; + return result; +} + +/* 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) +{ + return unicode_to_encoded_string (unicode_str, target_charset ()); } /* Converts a python string (8-bit or unicode) to a target string in @@ -132,3 +143,28 @@ python_string_to_target_string (PyObject *obj) return unicode_to_target_string (str); } + +/* Converts a python string (8-bit or unicode) to a target string in + the host's charset. Returns NULL on error, with a python exception set. + + The caller is responsible for xfree'ing the string. */ +char * +python_string_to_host_string (PyObject *obj) +{ + PyObject *str; + + str = python_string_to_unicode (obj); + if (str == NULL) + return NULL; + + return unicode_to_encoded_string (str, host_charset ()); +} + +/* Return true if OBJ is a Python string or unicode object, false + otherwise. */ + +int +gdbpy_is_string (PyObject *obj) +{ + return PyString_Check (obj) || PyUnicode_Check (obj); +} diff --git a/gdb/python/python-value.c b/gdb/python/python-value.c index 92e0431..4d1f864 100644 --- a/gdb/python/python-value.c +++ b/gdb/python/python-value.c @@ -132,6 +132,22 @@ valpy_dereference (PyObject *self, PyObject *args) return value_to_value_object (res_val); } +/* Return "&value". */ +static PyObject * +valpy_address (PyObject *self, PyObject *args) +{ + struct value *res_val = NULL; /* Initialize to appease gcc warning. */ + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + res_val = value_addr (((value_object *) self)->value); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return value_to_value_object (res_val); +} + static Py_ssize_t valpy_length (PyObject *self) { @@ -147,26 +163,37 @@ static PyObject * valpy_getitem (PyObject *self, PyObject *key) { value_object *self_value = (value_object *) self; - char *field; + char *field = NULL; + struct value *idx = NULL; struct value *res_val = NULL; /* Initialize to appease gcc warning. */ - struct cleanup *old; volatile struct gdb_exception except; - field = python_string_to_target_string (key); - if (field == NULL) - return NULL; - - old = make_cleanup (xfree, field); + if (gdbpy_is_string (key)) + { + field = python_string_to_host_string (key); + if (field == NULL) + return NULL; + } TRY_CATCH (except, RETURN_MASK_ALL) { struct value *tmp = self_value->value; - res_val = value_struct_elt (&tmp, NULL, field, 0, NULL); + + if (field) + res_val = value_struct_elt (&tmp, NULL, field, 0, NULL); + else + { + /* Assume we are attempting an array access, and let the + value code throw an exception if the index has an invalid + type. */ + struct value *idx = convert_value_from_python (key); + res_val = value_subscript (tmp, idx); + } } + if (field) + xfree (field); GDB_PY_HANDLE_EXCEPTION (except); - do_cleanups (old); - return value_to_value_object (res_val); } @@ -220,7 +247,12 @@ enum valpy_opcode VALPY_MUL, VALPY_DIV, VALPY_REM, - VALPY_POW + VALPY_POW, + VALPY_LSH, + VALPY_RSH, + VALPY_BITAND, + VALPY_BITOR, + VALPY_BITXOR }; /* If TYPE is a reference, return the target; otherwise return TYPE. */ @@ -302,6 +334,21 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other) case VALPY_POW: res_val = value_binop (arg1, arg2, BINOP_EXP); break; + case VALPY_LSH: + res_val = value_binop (arg1, arg2, BINOP_LSH); + break; + case VALPY_RSH: + res_val = value_binop (arg1, arg2, BINOP_RSH); + break; + case VALPY_BITAND: + res_val = value_binop (arg1, arg2, BINOP_BITWISE_AND); + break; + case VALPY_BITOR: + res_val = value_binop (arg1, arg2, BINOP_BITWISE_IOR); + break; + case VALPY_BITXOR: + res_val = value_binop (arg1, arg2, BINOP_BITWISE_XOR); + break; } } GDB_PY_HANDLE_EXCEPTION (except); @@ -412,45 +459,66 @@ valpy_nonzero (PyObject *self) } } -/* Implements comparison operations for value objects. */ +/* Implements ~ for value objects. */ static PyObject * -valpy_richcompare (PyObject *self, PyObject *other, int op) +valpy_invert (PyObject *self) { - int result = 0; - struct value *value_self, *value_other; + struct value *val = NULL; volatile struct gdb_exception except; - if (PyObject_TypeCheck (other, &value_object_type)) - value_other = ((value_object *) other)->value; - else if (PyInt_Check (other)) + TRY_CATCH (except, RETURN_MASK_ALL) { - LONGEST l; + val = value_complement (((value_object *) self)->value); + } + GDB_PY_HANDLE_EXCEPTION (except); - l = PyInt_AsLong (other); - if (PyErr_Occurred ()) - return NULL; + return value_to_value_object (val); +} - value_other = value_from_longest (builtin_type_pyint, l); - } - else if (PyFloat_Check (other)) - { - DOUBLEST d; +/* Implements left shift for value objects. */ +static PyObject * +valpy_lsh (PyObject *self, PyObject *other) +{ + return valpy_binop (VALPY_LSH, self, other); +} - d = PyFloat_AsDouble (other); - if (PyErr_Occurred ()) - return NULL; +/* Implements right shift for value objects. */ +static PyObject * +valpy_rsh (PyObject *self, PyObject *other) +{ + return valpy_binop (VALPY_RSH, self, other); +} - value_other = value_from_double (builtin_type_pyfloat, d); - } - else if (PyString_Check (other) || PyUnicode_Check (other)) - { - char *str; +/* Implements bitwise and for value objects. */ +static PyObject * +valpy_and (PyObject *self, PyObject *other) +{ + return valpy_binop (VALPY_BITAND, self, other); +} - str = python_string_to_target_string (other); - value_other = value_from_string (str); - xfree (str); - } - else if (other == Py_None) +/* Implements bitwise or for value objects. */ +static PyObject * +valpy_or (PyObject *self, PyObject *other) +{ + return valpy_binop (VALPY_BITOR, self, other); +} + +/* Implements bitwise xor for value objects. */ +static PyObject * +valpy_xor (PyObject *self, PyObject *other) +{ + return valpy_binop (VALPY_BITXOR, self, other); +} + +/* Implements comparison operations for value objects. */ +static PyObject * +valpy_richcompare (PyObject *self, PyObject *other, int op) +{ + int result = 0; + struct value *value_other; + volatile struct gdb_exception except; + + if (other == Py_None) /* Comparing with None is special. From what I can tell, in Python None is smaller than anything else. */ switch (op) { @@ -468,15 +536,11 @@ valpy_richcompare (PyObject *self, PyObject *other, int op) "Invalid operation on gdb.Value."); return NULL; } - else - { - PyErr_SetString (PyExc_NotImplementedError, - "Operation not supported on gdb.Value of this type."); - return NULL; - } TRY_CATCH (except, RETURN_MASK_ALL) { + value_other = convert_value_from_python (other); + switch (op) { case Py_LT: result = value_less (((value_object *) self)->value, value_other); @@ -513,6 +577,92 @@ valpy_richcompare (PyObject *self, PyObject *other, int op) Py_RETURN_FALSE; } +/* Helper function to determine if a type is "int-like". */ +static int +is_intlike (struct type *type, int ptr_ok) +{ + CHECK_TYPEDEF (type); + return (TYPE_CODE (type) == TYPE_CODE_INT + || TYPE_CODE (type) == TYPE_CODE_ENUM + || TYPE_CODE (type) == TYPE_CODE_BOOL + || TYPE_CODE (type) == TYPE_CODE_CHAR + || (ptr_ok && TYPE_CODE (type) == TYPE_CODE_PTR)); +} + +/* Implements conversion to int. */ +static PyObject * +valpy_int (PyObject *self) +{ + struct value *value = ((value_object *) self)->value; + struct type *type = value_type (value); + LONGEST l = 0; + volatile struct gdb_exception except; + + CHECK_TYPEDEF (type); + if (!is_intlike (type, 0)) + { + PyErr_SetString (PyExc_RuntimeError, "cannot convert value to int"); + return NULL; + } + + TRY_CATCH (except, RETURN_MASK_ALL) + { + l = value_as_long (value); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return PyInt_FromLong (l); +} + +/* Implements conversion to long. */ +static PyObject * +valpy_long (PyObject *self) +{ + struct value *value = ((value_object *) self)->value; + struct type *type = value_type (value); + LONGEST l = 0; + volatile struct gdb_exception except; + + if (!is_intlike (type, 1)) + { + PyErr_SetString (PyExc_RuntimeError, "cannot convert value to long"); + return NULL; + } + + TRY_CATCH (except, RETURN_MASK_ALL) + { + l = value_as_long (value); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return PyLong_FromLong (l); +} + +/* Implements conversion to float. */ +static PyObject * +valpy_float (PyObject *self) +{ + struct value *value = ((value_object *) self)->value; + struct type *type = value_type (value); + double d = 0; + volatile struct gdb_exception except; + + CHECK_TYPEDEF (type); + if (TYPE_CODE (type) != TYPE_CODE_FLT) + { + PyErr_SetString (PyExc_RuntimeError, "cannot convert value to float"); + return NULL; + } + + TRY_CATCH (except, RETURN_MASK_ALL) + { + d = value_as_double (value); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return PyFloat_FromDouble (d); +} + /* Returns an object for a value which is released from the all_values chain, so its lifetime is not bound to the execution of a command. */ PyObject * @@ -561,13 +711,16 @@ convert_value_from_python (PyObject *obj) if (! PyErr_Occurred ()) value = value_from_double (builtin_type_pyfloat, d); } - else if (PyString_Check (obj) || PyUnicode_Check (obj)) + else if (gdbpy_is_string (obj)) { char *s; s = python_string_to_target_string (obj); if (s == NULL) - return NULL; + { + PyErr_Clear (); + error (_("Error converting Python value.")); + } old = make_cleanup (xfree, s); value = value_from_string (s); @@ -587,7 +740,7 @@ convert_value_from_python (PyObject *obj) /* Returns value object in the ARGth position in GDB's history. */ PyObject * -gdbpy_get_value_from_history (PyObject *self, PyObject *args) +gdbpy_history (PyObject *self, PyObject *args) { int i; struct value *res_val = NULL; /* Initialize to appease gcc warning. */ @@ -608,7 +761,6 @@ gdbpy_get_value_from_history (PyObject *self, PyObject *args) void gdbpy_initialize_values (void) { - value_object_type.tp_new = valpy_new; if (PyType_Ready (&value_object_type) < 0) return; @@ -619,6 +771,7 @@ gdbpy_initialize_values (void) } static PyMethodDef value_object_methods[] = { + { "address", valpy_address, METH_NOARGS, "Return the address of the value." }, { "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." }, {NULL} /* Sentinel */ }; @@ -634,7 +787,19 @@ static PyNumberMethods value_object_as_number = { valpy_negative, /* nb_negative */ valpy_positive, /* nb_positive */ valpy_absolute, /* nb_absolute */ - valpy_nonzero /* nb_nonzero */ + valpy_nonzero, /* nb_nonzero */ + valpy_invert, /* nb_invert */ + valpy_lsh, /* nb_lshift */ + valpy_rsh, /* nb_rshift */ + valpy_and, /* nb_and */ + valpy_xor, /* nb_xor */ + valpy_or, /* nb_or */ + NULL, /* nb_coerce */ + valpy_int, /* nb_int */ + valpy_long, /* nb_long */ + valpy_float, /* nb_float */ + NULL, /* nb_oct */ + NULL /* nb_hex */ }; static PyMappingMethods value_object_as_mapping = { @@ -672,7 +837,17 @@ PyTypeObject value_object_type = { 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ - value_object_methods /* tp_methods */ + value_object_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + valpy_new /* tp_new */ }; #endif /* HAVE_PYTHON */ diff --git a/gdb/python/python.c b/gdb/python/python.c index e778ac4..991321f 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -52,7 +52,7 @@ static PyObject *gdbpy_flush (PyObject *, PyObject *); static PyMethodDef GdbMethods[] = { - { "get_value_from_history", gdbpy_get_value_from_history, METH_VARARGS, + { "history", gdbpy_history, METH_VARARGS, "Get a value from history" }, { "execute", execute_gdb_command, METH_VARARGS, "Execute a gdb command" }, diff --git a/gdb/testsuite/gdb.python/python-value.c b/gdb/testsuite/gdb.python/python-value.c index 8c10956..17e5c62 100644 --- a/gdb/testsuite/gdb.python/python-value.c +++ b/gdb/testsuite/gdb.python/python-value.c @@ -27,6 +27,14 @@ union u float b; }; +enum e + { + ONE = 1, + TWO = 2 + }; + +enum e evalue = TWO; + int main (int argc, char *argv[]) { @@ -37,5 +45,7 @@ main (int argc, char *argv[]) s.b = 5; u.a = 7; + argv[0][0] = 'a'; /* Just to avoid getting argv optimized out. */ + return 0; /* break to inspect struct and union */ } diff --git a/gdb/testsuite/gdb.python/python-value.exp b/gdb/testsuite/gdb.python/python-value.exp index 2057e61..8f5e0ab 100644 --- a/gdb/testsuite/gdb.python/python-value.exp +++ b/gdb/testsuite/gdb.python/python-value.exp @@ -111,13 +111,18 @@ proc test_value_numeric_ops {} { gdb_test "python print 'result = ' + str(1-i)" " = -4" "subtract python integer from integer value" gdb_test "python print 'result = ' + str(1.5+f)" " = 2.75" "add python float with double value" + # Conversion test. + gdb_test "print evalue" " = TWO" + gdb_test "python evalue = gdb.history (0)" "" + gdb_test "python print int (evalue)" "2" + # Test pointer arithmethic # First, obtain the pointers gdb_test "print (void *) 2" "" "" - gdb_test "python a = gdb.get_value_from_history (0)" "" "" + gdb_test "python a = gdb.history (0)" "" "" gdb_test "print (void *) 5" "" "" - gdb_test "python b = gdb.get_value_from_history (0)" "" "" + gdb_test "python b = gdb.history (0)" "" "" gdb_test "python print 'result = ' + str(a+5)" " = 0x7" "add pointer value with python integer" gdb_test "python print 'result = ' + str(b-2)" " = 0x3" "subtract python integer from pointer value" @@ -205,7 +210,7 @@ proc test_value_in_inferior {} { # Just get inferior variable s in the value history, available to python. gdb_test "print s" " = {a = 3, b = 5}" "" - gdb_py_test_silent_cmd "python s = gdb.get_value_from_history (0)" "get value from history" 1 + gdb_py_test_silent_cmd "python s = gdb.history (0)" "get value from history" 1 gdb_test "python print 'result = ' + str(s\['a'\])" " = 3" "access element inside struct using 8-bit string name" gdb_test "python print 'result = ' + str(s\[u'a'\])" " = 3" "access element inside struct using unicode name" @@ -215,7 +220,7 @@ proc test_value_in_inferior {} { # Just get inferior variable argv the value history, available to python. gdb_test "print argv" " = \\(char \\*\\*\\) 0x.*" "" - gdb_py_test_silent_cmd "python argv = gdb.get_value_from_history (0)" "" 0 + gdb_py_test_silent_cmd "python argv = gdb.history (0)" "" 0 gdb_py_test_silent_cmd "python arg0 = argv.dereference ()" "dereference value" 1 # Check that the dereferenced value is sane