This is the mail archive of the
archer@sourceware.org
mailing list for the Archer project.
[python][patch] Add options length parameter to value.string(...)
- From: Phil Muldoon <pmuldoon at redhat dot com>
- To: Project Archer <archer at sourceware dot org>
- Date: Mon, 06 Apr 2009 17:54:38 +0100
- Subject: [python][patch] Add options length parameter to value.string(...)
This patch adds an optional length parameter to the value.string()
method. This allows partial string fetches, and string fetches that
ignore embedded null characters in the C/C++ string case. If the length
parameter is omitted, the method will maintain the existing behaviour of
fetching a string until a terminating null in the C/C++ case.
Regards
Phil
ChangeLog
2009-04-06 Phil Muldoon <pmuldoon@redhat.com>
* python/python-value.c (valpy_string): Parse length keyword. Use
length keyword in LA_GET_STRING.
* c-lang.c (c_get_string): If the length parameter is specified,
use that.
testsuite/ChangeLog
2009-04-06 Phil Muldoon <pmuldoon@redhat.com>
* gdb.python/python-value.exp (test_value_in_inferior): Add
variable length string fetch tests.
* gdb.python/python-value.c (main): Add strings for string fetch tests.
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 8b5410f..344c836 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -249,12 +249,17 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length,
int i;
const gdb_byte *contents = value_contents (value);
- /* Look for a null character. */
- for (i = 0; i < fetchlimit; i++)
- if (extract_unsigned_integer (contents + i * width, width) == 0)
- break;
-
- /* I is now either the number of non-null characters, or FETCHLIMIT. */
+ /* If a length is specified, use that. */
+ if ( *length >= 0 )
+ i = *length;
+ else
+ /* Otherwise, look for a null character. */
+ for (i = 0; i < fetchlimit; i++)
+ if (extract_unsigned_integer (contents + i * width, width) == 0)
+ break;
+
+ /* I is now either a user-defined length, the number of non-null
+ characters, or FETCHLIMIT. */
*length = i * width;
*buffer = xmalloc (*length);
memcpy (*buffer, contents, *length);
@@ -262,7 +267,10 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length,
}
else
{
- err = read_string (value_as_address (value), -1, width, fetchlimit,
+ /* Copy length to orig_len, as read_string will write the number
+ of characters 'read' to length. */
+ int orig_len = *length;
+ err = read_string (value_as_address (value), orig_len, width, fetchlimit,
buffer, length);
if (err)
{
diff --git a/gdb/python/python-value.c b/gdb/python/python-value.c
index b55463c..a308a7a 100644
--- a/gdb/python/python-value.c
+++ b/gdb/python/python-value.c
@@ -179,7 +179,7 @@ valpy_type (PyObject *self, PyObject *args)
static PyObject *
valpy_string (PyObject *self, PyObject *args, PyObject *kw)
{
- int length, ret = 0;
+ int length = -1, ret = 0;
gdb_byte *buffer;
struct value *value = ((value_object *) self)->value;
volatile struct gdb_exception except;
@@ -188,10 +188,10 @@ valpy_string (PyObject *self, PyObject *args, PyObject *kw)
const char *errors = NULL;
const char *user_encoding = NULL;
const char *la_encoding = NULL;
- static char *keywords[] = { "encoding", "errors" };
+ static char *keywords[] = { "encoding", "errors", "length" };
- if (!PyArg_ParseTupleAndKeywords (args, kw, "|ss", keywords,
- &user_encoding, &errors))
+ if (!PyArg_ParseTupleAndKeywords (args, kw, "|ssi", keywords,
+ &user_encoding, &errors, &length))
return NULL;
TRY_CATCH (except, RETURN_MASK_ALL)
@@ -957,7 +957,7 @@ static PyMethodDef value_object_methods[] = {
{ "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." },
{ "type", valpy_type, METH_NOARGS, "Return type of the value." },
{ "string", (PyCFunction) valpy_string, METH_VARARGS | METH_KEYWORDS,
- "string ([encoding] [, errors]) -> string\n\
+ "string ([encoding] [, errors] [, length]) -> string\n\
Return Unicode string representation of the value." },
{NULL} /* Sentinel */
};
diff --git a/gdb/testsuite/gdb.python/python-value.c b/gdb/testsuite/gdb.python/python-value.c
index 092c520..f3d6284 100644
--- a/gdb/testsuite/gdb.python/python-value.c
+++ b/gdb/testsuite/gdb.python/python-value.c
@@ -44,6 +44,8 @@ main (int argc, char *argv[])
struct s s;
union u u;
PTR x = &s;
+ char st[17] = "divide et impera";
+ char nullst[17] = "divide\0et\0impera";
s.a = 3;
s.b = 5;
diff --git a/gdb/testsuite/gdb.python/python-value.exp b/gdb/testsuite/gdb.python/python-value.exp
index cbcf91f..9169fc7 100644
--- a/gdb/testsuite/gdb.python/python-value.exp
+++ b/gdb/testsuite/gdb.python/python-value.exp
@@ -234,6 +234,23 @@ proc test_value_in_inferior {} {
# Test address attribute
gdb_test "python print 'result =', arg0.address" "= 0x\[\[:xdigit:\]\]+" "Test address attribute"
+
+ # Test string fetches, both partial and whole.
+ gdb_test "print st" "\"divide et impera\""
+ gdb_py_test_silent_cmd "python st = gdb.history (0)" "get value from history" 1
+ gdb_test "python print st.string ()" "divide et impera" "Test string with no length"
+ gdb_test "python print st.string (length = -1)" "divide et impera" "Test string (length = -1) is all of the string"
+ gdb_test "python print st.string (length = 6)" "divide"
+ gdb_test "python print st.string (length = 0)" "" "Test string (length = 0) is empty"
+
+ # Fetch a string that has embedded nulls.
+ gdb_test "print nullst" "\"divide\\\\000et\\\\000impera\".*"
+ gdb_py_test_silent_cmd "python nullst = gdb.history (0)" "get value from history" 1
+ gdb_test "python print nullst.string ()" "divide" "Test string to first null"
+ # Python cannot print strings that contain the null (\0) character.
+ # For the purposes of this test, use repr()
+ gdb_py_test_silent_cmd "python nullst = nullst.string (length = 9)" "get string beyond null" 1
+ gdb_test "python print repr(nullst)" "u'divide\\\\x00et'"
}
proc test_value_after_death {} {