Copy lazy string handling fixes from Python.
This patch keeps the Scheme side of lazy string handling in sync with the python size, bringing over fixes for PRs python/17728, python/18439, python/18779. gdb/ChangeLog: * guile/scm-lazy-string.c (lazy_string_smob): Clarify use of LENGTH member. Change type of TYPE member to SCM. All uses updated. (lsscm_make_lazy_string_smob): Add assert. (lsscm_make_lazy_string): Flag bad length values. (lsscm_elt_type): New function. (gdbscm_lazy_string_to_value): Rewrite to use lsscm_safe_lazy_string_to_value. (lsscm_safe_lazy_string_to_value): Fix handling of TYPE_CODE_PTR. * guile/scm-value.c (gdbscm_value_to_lazy_string): Flag bad length values. Fix TYPE_CODE_PTR. Handle TYPE_CODE_ARRAY. Handle typedefs in incoming type. * guile/guile-internal.h (tyscm_scm_to_type): Declare. * guile/scm-type.c (tyscm_scm_to_type): New function. gdb/testsuite/ChangeLog: * gdb.guile/scm-value.c (main) Delete locals sptr, sn. * gdb.guile/scm-lazy-string.c: New file. * gdb.guile/scm-value.exp: Move lazy string tests to ... * gdb.guile/scm-lazy-string.exp: ... here, new file. Add more tests for pointer, array, typedef lazy strings.
This commit is contained in:
parent
34b433203b
commit
a7c0469f99
8 changed files with 278 additions and 74 deletions
|
@ -1,5 +1,21 @@
|
||||||
2017-03-16 Doug Evans <dje@google.com>
|
2017-03-16 Doug Evans <dje@google.com>
|
||||||
|
|
||||||
|
* guile/scm-lazy-string.c (lazy_string_smob): Clarify use of LENGTH
|
||||||
|
member. Change type of TYPE member to SCM. All uses updated.
|
||||||
|
(lsscm_make_lazy_string_smob): Add assert.
|
||||||
|
(lsscm_make_lazy_string): Flag bad length values.
|
||||||
|
(lsscm_elt_type): New function.
|
||||||
|
(gdbscm_lazy_string_to_value): Rewrite to use
|
||||||
|
lsscm_safe_lazy_string_to_value.
|
||||||
|
(lsscm_safe_lazy_string_to_value): Fix handling of TYPE_CODE_PTR.
|
||||||
|
* guile/scm-value.c (gdbscm_value_to_lazy_string): Flag bad length
|
||||||
|
values. Fix TYPE_CODE_PTR. Handle TYPE_CODE_ARRAY. Handle typedefs
|
||||||
|
in incoming type.
|
||||||
|
* guile/guile-internal.h (tyscm_scm_to_type): Declare.
|
||||||
|
* guile/scm-type.c (tyscm_scm_to_type): New function.
|
||||||
|
|
||||||
|
2017-03-15 Doug Evans <dje@google.com>
|
||||||
|
|
||||||
PR python/17728, python/18439, python/18779
|
PR python/17728, python/18439, python/18779
|
||||||
* python/py-lazy-string.c (lazy_string_object): Clarify use of LENGTH
|
* python/py-lazy-string.c (lazy_string_object): Clarify use of LENGTH
|
||||||
member. Change type of TYPE member to PyObject *. All uses updated.
|
member. Change type of TYPE member to PyObject *. All uses updated.
|
||||||
|
|
|
@ -44,14 +44,20 @@ typedef struct
|
||||||
freed. */
|
freed. */
|
||||||
char *encoding;
|
char *encoding;
|
||||||
|
|
||||||
/* Holds the length of the string in characters. If the length is -1,
|
/* If TYPE is an array: If the length is known, then this value is the
|
||||||
then the string will be fetched and encoded up to the first null of
|
array's length, otherwise it is -1.
|
||||||
appropriate width. */
|
If TYPE is not an array: Then this value represents the string's length.
|
||||||
|
In either case, if the value is -1 then the string will be fetched and
|
||||||
|
encoded up to the first null of appropriate width. */
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
/* This attribute holds the type that is represented by the lazy
|
/* The type of the string.
|
||||||
string's type. */
|
For example if the lazy string was created from a C "char*" then TYPE
|
||||||
struct type *type;
|
represents a C "char*". To get the type of the character in the string
|
||||||
|
call lsscm_elt_type which handles the different kinds of values for TYPE.
|
||||||
|
This is recorded as an SCM object so that we take advantage of support for
|
||||||
|
preserving the type should its owning objfile go away. */
|
||||||
|
SCM type;
|
||||||
} lazy_string_smob;
|
} lazy_string_smob;
|
||||||
|
|
||||||
static const char lazy_string_smob_name[] = "gdb:lazy-string";
|
static const char lazy_string_smob_name[] = "gdb:lazy-string";
|
||||||
|
@ -95,7 +101,10 @@ lsscm_print_lazy_string_smob (SCM self, SCM port, scm_print_state *pstate)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Low level routine to create a <gdb:lazy-string> object.
|
/* Low level routine to create a <gdb:lazy-string> object.
|
||||||
The caller must verify !(address == 0 && length != 0). */
|
The caller must verify:
|
||||||
|
- length >= -1
|
||||||
|
- !(address == 0 && length != 0)
|
||||||
|
- type != NULL */
|
||||||
|
|
||||||
static SCM
|
static SCM
|
||||||
lsscm_make_lazy_string_smob (CORE_ADDR address, int length,
|
lsscm_make_lazy_string_smob (CORE_ADDR address, int length,
|
||||||
|
@ -105,18 +114,17 @@ lsscm_make_lazy_string_smob (CORE_ADDR address, int length,
|
||||||
scm_gc_malloc (sizeof (lazy_string_smob), lazy_string_smob_name);
|
scm_gc_malloc (sizeof (lazy_string_smob), lazy_string_smob_name);
|
||||||
SCM ls_scm;
|
SCM ls_scm;
|
||||||
|
|
||||||
/* Caller must verify this. */
|
gdb_assert (length >= -1);
|
||||||
gdb_assert (!(address == 0 && length != 0));
|
gdb_assert (!(address == 0 && length != 0));
|
||||||
gdb_assert (type != NULL);
|
gdb_assert (type != NULL);
|
||||||
|
|
||||||
ls_smob->address = address;
|
ls_smob->address = address;
|
||||||
/* Coerce all values < 0 to -1. */
|
ls_smob->length = length;
|
||||||
ls_smob->length = length < 0 ? -1 : length;
|
|
||||||
if (encoding == NULL || strcmp (encoding, "") == 0)
|
if (encoding == NULL || strcmp (encoding, "") == 0)
|
||||||
ls_smob->encoding = NULL;
|
ls_smob->encoding = NULL;
|
||||||
else
|
else
|
||||||
ls_smob->encoding = xstrdup (encoding);
|
ls_smob->encoding = xstrdup (encoding);
|
||||||
ls_smob->type = type;
|
ls_smob->type = tyscm_scm_from_type (type);
|
||||||
|
|
||||||
ls_scm = scm_new_smob (lazy_string_smob_tag, (scm_t_bits) ls_smob);
|
ls_scm = scm_new_smob (lazy_string_smob_tag, (scm_t_bits) ls_smob);
|
||||||
gdbscm_init_gsmob (&ls_smob->base);
|
gdbscm_init_gsmob (&ls_smob->base);
|
||||||
|
@ -147,11 +155,18 @@ SCM
|
||||||
lsscm_make_lazy_string (CORE_ADDR address, int length,
|
lsscm_make_lazy_string (CORE_ADDR address, int length,
|
||||||
const char *encoding, struct type *type)
|
const char *encoding, struct type *type)
|
||||||
{
|
{
|
||||||
|
if (length < -1)
|
||||||
|
{
|
||||||
|
return gdbscm_make_out_of_range_error (NULL, 0,
|
||||||
|
scm_from_int (length),
|
||||||
|
_("invalid length"));
|
||||||
|
}
|
||||||
|
|
||||||
if (address == 0 && length != 0)
|
if (address == 0 && length != 0)
|
||||||
{
|
{
|
||||||
return gdbscm_make_out_of_range_error
|
return gdbscm_make_out_of_range_error
|
||||||
(NULL, 0, scm_from_int (length),
|
(NULL, 0, scm_from_int (length),
|
||||||
_("cannot create a lazy string with address 0x0"
|
_("cannot create a lazy string with address 0x0,"
|
||||||
" and a non-zero length"));
|
" and a non-zero length"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,6 +190,28 @@ lsscm_get_lazy_string_arg_unsafe (SCM self, int arg_pos, const char *func_name)
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the type of a character in lazy string LS_SMOB. */
|
||||||
|
|
||||||
|
static struct type *
|
||||||
|
lsscm_elt_type (lazy_string_smob *ls_smob)
|
||||||
|
{
|
||||||
|
struct type *type = tyscm_scm_to_type (ls_smob->type);
|
||||||
|
struct type *realtype;
|
||||||
|
|
||||||
|
realtype = check_typedef (type);
|
||||||
|
|
||||||
|
switch (TYPE_CODE (realtype))
|
||||||
|
{
|
||||||
|
case TYPE_CODE_PTR:
|
||||||
|
case TYPE_CODE_ARRAY:
|
||||||
|
return TYPE_TARGET_TYPE (realtype);
|
||||||
|
default:
|
||||||
|
/* This is done to preserve existing behaviour. PR 20769.
|
||||||
|
E.g., gdb.parse_and_eval("my_int_variable").lazy_string().type. */
|
||||||
|
return realtype;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Lazy string methods. */
|
/* Lazy string methods. */
|
||||||
|
|
||||||
|
@ -223,7 +260,7 @@ gdbscm_lazy_string_type (SCM self)
|
||||||
SCM ls_scm = lsscm_get_lazy_string_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
SCM ls_scm = lsscm_get_lazy_string_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||||||
lazy_string_smob *ls_smob = (lazy_string_smob *) SCM_SMOB_DATA (ls_scm);
|
lazy_string_smob *ls_smob = (lazy_string_smob *) SCM_SMOB_DATA (ls_scm);
|
||||||
|
|
||||||
return tyscm_scm_from_type (ls_smob->type);
|
return ls_smob->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (lazy-string->value <gdb:lazy-string>) -> <gdb:value> */
|
/* (lazy-string->value <gdb:lazy-string>) -> <gdb:value> */
|
||||||
|
@ -232,25 +269,13 @@ static SCM
|
||||||
gdbscm_lazy_string_to_value (SCM self)
|
gdbscm_lazy_string_to_value (SCM self)
|
||||||
{
|
{
|
||||||
SCM ls_scm = lsscm_get_lazy_string_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
SCM ls_scm = lsscm_get_lazy_string_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||||||
lazy_string_smob *ls_smob = (lazy_string_smob *) SCM_SMOB_DATA (ls_scm);
|
SCM except_scm;
|
||||||
struct value *value = NULL;
|
struct value *value;
|
||||||
|
|
||||||
if (ls_smob->address == 0)
|
|
||||||
{
|
|
||||||
gdbscm_throw (gdbscm_make_out_of_range_error (FUNC_NAME, SCM_ARG1, self,
|
|
||||||
_("cannot create a value from NULL")));
|
|
||||||
}
|
|
||||||
|
|
||||||
TRY
|
|
||||||
{
|
|
||||||
value = value_at_lazy (ls_smob->type, ls_smob->address);
|
|
||||||
}
|
|
||||||
CATCH (except, RETURN_MASK_ALL)
|
|
||||||
{
|
|
||||||
GDBSCM_HANDLE_GDB_EXCEPTION (except);
|
|
||||||
}
|
|
||||||
END_CATCH
|
|
||||||
|
|
||||||
|
value = lsscm_safe_lazy_string_to_value (ls_scm, SCM_ARG1, FUNC_NAME,
|
||||||
|
&except_scm);
|
||||||
|
if (value == NULL)
|
||||||
|
gdbscm_throw (except_scm);
|
||||||
return vlscm_scm_from_value (value);
|
return vlscm_scm_from_value (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,19 +300,41 @@ lsscm_safe_lazy_string_to_value (SCM string, int arg_pos,
|
||||||
gdb_assert (lsscm_is_lazy_string (string));
|
gdb_assert (lsscm_is_lazy_string (string));
|
||||||
|
|
||||||
ls_smob = (lazy_string_smob *) SCM_SMOB_DATA (string);
|
ls_smob = (lazy_string_smob *) SCM_SMOB_DATA (string);
|
||||||
*except_scmp = SCM_BOOL_F;
|
|
||||||
|
|
||||||
if (ls_smob->address == 0)
|
if (ls_smob->address == 0)
|
||||||
{
|
{
|
||||||
*except_scmp
|
*except_scmp
|
||||||
= gdbscm_make_out_of_range_error (FUNC_NAME, SCM_ARG1, string,
|
= gdbscm_make_out_of_range_error (func_name, arg_pos, string,
|
||||||
_("cannot create a value from NULL"));
|
_("cannot create a value from NULL"));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY
|
TRY
|
||||||
{
|
{
|
||||||
value = value_at_lazy (ls_smob->type, ls_smob->address);
|
struct type *type = tyscm_scm_to_type (ls_smob->type);
|
||||||
|
struct type *realtype = check_typedef (type);
|
||||||
|
|
||||||
|
switch (TYPE_CODE (realtype))
|
||||||
|
{
|
||||||
|
case TYPE_CODE_PTR:
|
||||||
|
/* If a length is specified we need to convert this to an array
|
||||||
|
of the specified size. */
|
||||||
|
if (ls_smob->length != -1)
|
||||||
|
{
|
||||||
|
/* PR 20786: There's no way to specify an array of length zero.
|
||||||
|
Record a length of [0,-1] which is how Ada does it. Anything
|
||||||
|
we do is broken, but this one possible solution. */
|
||||||
|
type = lookup_array_range_type (TYPE_TARGET_TYPE (realtype),
|
||||||
|
0, ls_smob->length - 1);
|
||||||
|
value = value_at_lazy (type, ls_smob->address);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
value = value_from_pointer (type, ls_smob->address);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
value = value_at_lazy (type, ls_smob->address);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CATCH (except, RETURN_MASK_ALL)
|
CATCH (except, RETURN_MASK_ALL)
|
||||||
{
|
{
|
||||||
|
@ -307,12 +354,14 @@ lsscm_val_print_lazy_string (SCM string, struct ui_file *stream,
|
||||||
const struct value_print_options *options)
|
const struct value_print_options *options)
|
||||||
{
|
{
|
||||||
lazy_string_smob *ls_smob;
|
lazy_string_smob *ls_smob;
|
||||||
|
struct type *elt_type;
|
||||||
|
|
||||||
gdb_assert (lsscm_is_lazy_string (string));
|
gdb_assert (lsscm_is_lazy_string (string));
|
||||||
|
|
||||||
ls_smob = (lazy_string_smob *) SCM_SMOB_DATA (string);
|
ls_smob = (lazy_string_smob *) SCM_SMOB_DATA (string);
|
||||||
|
elt_type = lsscm_elt_type (ls_smob);
|
||||||
|
|
||||||
val_print_string (ls_smob->type, ls_smob->encoding,
|
val_print_string (elt_type, ls_smob->encoding,
|
||||||
ls_smob->address, ls_smob->length,
|
ls_smob->address, ls_smob->length,
|
||||||
stream, options);
|
stream, options);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1173,8 +1173,10 @@ gdbscm_value_to_string (SCM self, SCM rest)
|
||||||
Return a Scheme object representing a lazy_string_object type.
|
Return a Scheme object representing a lazy_string_object type.
|
||||||
A lazy string is a pointer to a string with an optional encoding and length.
|
A lazy string is a pointer to a string with an optional encoding and length.
|
||||||
If ENCODING is not given, the target's charset is used.
|
If ENCODING is not given, the target's charset is used.
|
||||||
If LENGTH is provided then the length parameter is set to LENGTH, otherwise
|
If LENGTH is provided then the length parameter is set to LENGTH.
|
||||||
length will be set to -1 (first null of appropriate with).
|
Otherwise if the value is an array of known length then the array's length
|
||||||
|
is used. Otherwise the length will be set to -1 (meaning first null of
|
||||||
|
appropriate with).
|
||||||
LENGTH must be a Scheme integer, it can't be a <gdb:value> integer. */
|
LENGTH must be a Scheme integer, it can't be a <gdb:value> integer. */
|
||||||
|
|
||||||
static SCM
|
static SCM
|
||||||
|
@ -1198,18 +1200,69 @@ gdbscm_value_to_lazy_string (SCM self, SCM rest)
|
||||||
&encoding_arg_pos, &encoding,
|
&encoding_arg_pos, &encoding,
|
||||||
&length_arg_pos, &length);
|
&length_arg_pos, &length);
|
||||||
|
|
||||||
|
if (length < -1)
|
||||||
|
{
|
||||||
|
gdbscm_out_of_range_error (FUNC_NAME, length_arg_pos,
|
||||||
|
scm_from_int (length),
|
||||||
|
_("invalid length"));
|
||||||
|
}
|
||||||
|
|
||||||
cleanups = make_cleanup (xfree, encoding);
|
cleanups = make_cleanup (xfree, encoding);
|
||||||
|
|
||||||
TRY
|
TRY
|
||||||
{
|
{
|
||||||
struct cleanup *inner_cleanup
|
struct cleanup *inner_cleanup
|
||||||
= make_cleanup_value_free_to_mark (value_mark ());
|
= make_cleanup_value_free_to_mark (value_mark ());
|
||||||
|
struct type *type, *realtype;
|
||||||
|
CORE_ADDR addr;
|
||||||
|
|
||||||
if (TYPE_CODE (value_type (value)) == TYPE_CODE_PTR)
|
type = value_type (value);
|
||||||
value = value_ind (value);
|
realtype = check_typedef (type);
|
||||||
|
|
||||||
result = lsscm_make_lazy_string (value_address (value), length,
|
switch (TYPE_CODE (realtype))
|
||||||
encoding, value_type (value));
|
{
|
||||||
|
case TYPE_CODE_ARRAY:
|
||||||
|
{
|
||||||
|
LONGEST array_length = -1;
|
||||||
|
LONGEST low_bound, high_bound;
|
||||||
|
|
||||||
|
/* PR 20786: There's no way to specify an array of length zero.
|
||||||
|
Record a length of [0,-1] which is how Ada does it. Anything
|
||||||
|
we do is broken, but this one possible solution. */
|
||||||
|
if (get_array_bounds (realtype, &low_bound, &high_bound))
|
||||||
|
array_length = high_bound - low_bound + 1;
|
||||||
|
if (length == -1)
|
||||||
|
length = array_length;
|
||||||
|
else if (array_length == -1)
|
||||||
|
{
|
||||||
|
type = lookup_array_range_type (TYPE_TARGET_TYPE (realtype),
|
||||||
|
0, length - 1);
|
||||||
|
}
|
||||||
|
else if (length != array_length)
|
||||||
|
{
|
||||||
|
/* We need to create a new array type with the
|
||||||
|
specified length. */
|
||||||
|
if (length > array_length)
|
||||||
|
error (_("length is larger than array size"));
|
||||||
|
type = lookup_array_range_type (TYPE_TARGET_TYPE (type),
|
||||||
|
low_bound,
|
||||||
|
low_bound + length - 1);
|
||||||
|
}
|
||||||
|
addr = value_address (value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TYPE_CODE_PTR:
|
||||||
|
/* If a length is specified we defer creating an array of the
|
||||||
|
specified width until we need to. */
|
||||||
|
addr = value_as_address (value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Should flag an error here. PR 20769. */
|
||||||
|
addr = value_address (value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = lsscm_make_lazy_string (addr, length, encoding, type);
|
||||||
|
|
||||||
do_cleanups (inner_cleanup);
|
do_cleanups (inner_cleanup);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,14 @@
|
||||||
* gdb.cp/m-static.exp: Fix expectation for prototype of
|
* gdb.cp/m-static.exp: Fix expectation for prototype of
|
||||||
test5.single_constructor and single_constructor::single_constructor.
|
test5.single_constructor and single_constructor::single_constructor.
|
||||||
=======
|
=======
|
||||||
|
2017-03-15 Doug Evans <dje@google.com>
|
||||||
|
|
||||||
|
* gdb.guile/scm-value.c (main) Delete locals sptr, sn.
|
||||||
|
* gdb.guile/scm-lazy-string.c: New file.
|
||||||
|
* gdb.guile/scm-value.exp: Move lazy string tests to ...
|
||||||
|
* gdb.guile/scm-lazy-string.exp: ... here, new file. Add more tests
|
||||||
|
for pointer, array, typedef lazy strings.
|
||||||
|
|
||||||
2017-03-15 Doug Evans <dje@google.com>
|
2017-03-15 Doug Evans <dje@google.com>
|
||||||
|
|
||||||
PR python/17728, python/18439, python/18779
|
PR python/17728, python/18439, python/18779
|
||||||
|
|
29
gdb/testsuite/gdb.guile/scm-lazy-string.c
Normal file
29
gdb/testsuite/gdb.guile/scm-lazy-string.c
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/* This testcase is part of GDB, the GNU debugger.
|
||||||
|
|
||||||
|
Copyright 2015-2016 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/>. */
|
||||||
|
|
||||||
|
typedef const char *pointer;
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
const char *ptr = "pointer";
|
||||||
|
const char array[] = "array";
|
||||||
|
pointer typedef_ptr = "typedef pointer";
|
||||||
|
const char *null = 0;
|
||||||
|
|
||||||
|
return 0; /* break here */
|
||||||
|
}
|
82
gdb/testsuite/gdb.guile/scm-lazy-string.exp
Normal file
82
gdb/testsuite/gdb.guile/scm-lazy-string.exp
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
# Copyright (C) 2008-2016 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 lazy strings to Guile.
|
||||||
|
|
||||||
|
load_lib gdb-guile.exp
|
||||||
|
|
||||||
|
standard_testfile
|
||||||
|
|
||||||
|
if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
# Skip all tests if Guile scripting is not enabled.
|
||||||
|
if { [skip_guile_tests] } { continue }
|
||||||
|
|
||||||
|
#gdb_install_guile_utils
|
||||||
|
#gdb_install_guile_module
|
||||||
|
|
||||||
|
# The following tests require execution.
|
||||||
|
|
||||||
|
if ![gdb_guile_runto_main] {
|
||||||
|
fail "Can't run to main"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_breakpoint [gdb_get_line_number "break here"]
|
||||||
|
gdb_continue_to_breakpoint "break here"
|
||||||
|
|
||||||
|
gdb_scm_test_silent_cmd "gu (define null (parse-and-eval \"null\"))" 1
|
||||||
|
|
||||||
|
gdb_scm_test_silent_cmd "gu (define nullstr (value->lazy-string null #:length 0))" "create a null lazy string" 1
|
||||||
|
gdb_test "gu (print (lazy-string-length nullstr))" "= 0" "null lazy string length"
|
||||||
|
gdb_test "gu (print (lazy-string-address nullstr))" "= 0" "null lazy string address"
|
||||||
|
gdb_test "gu (print (lazy-string-type nullstr))" "const char \\*" "null lazy string type"
|
||||||
|
gdb_test "gu (print (lazy-string->value nullstr))" \
|
||||||
|
"Out of range: cannot create a value from NULL.*Error while executing Scheme code." \
|
||||||
|
"create value from NULL"
|
||||||
|
gdb_test "gu (print (lazy-string->value (value->lazy-string null #:length 3)))" \
|
||||||
|
"Out of range: cannot create a lazy string with address 0x0, and a non-zero length.*Error while executing Scheme code." \
|
||||||
|
"null lazy string with non-zero length"
|
||||||
|
gdb_test "gu (print (value->lazy-string null #:length -2))" \
|
||||||
|
"Out of range: invalid length.*Error while executing Scheme code." \
|
||||||
|
"bad length"
|
||||||
|
|
||||||
|
foreach var_spec { { "ptr" "pointer" "const char \\*" -1 } \
|
||||||
|
{ "array" "array" "const char \\[6\\]" 6 } \
|
||||||
|
{ "typedef_ptr" "typedef pointer" "pointer" -1 } } {
|
||||||
|
set var [lindex $var_spec 0]
|
||||||
|
set value [lindex $var_spec 1]
|
||||||
|
set type [lindex $var_spec 2]
|
||||||
|
set length [lindex $var_spec 3]
|
||||||
|
with_test_prefix $var {
|
||||||
|
gdb_test "print $var" "\"$value\""
|
||||||
|
gdb_scm_test_silent_cmd "gu (define $var (history-ref 0))" "get value from history" 1
|
||||||
|
gdb_scm_test_silent_cmd "gu (define l$var (value->lazy-string $var))" "acquire lazy string" 1
|
||||||
|
gdb_test "gu (print (value-type $var))" "$type" "string type name equality"
|
||||||
|
gdb_test "gu (print (lazy-string-type l$var))" "$type" "lazy-string type name equality"
|
||||||
|
gdb_test "gu (print (lazy-string-length l$var))" "$length" "lazy string length"
|
||||||
|
gdb_test "gu (print (lazy-string->value l$var))" "\"$value\"" "lazy string value"
|
||||||
|
gdb_scm_test_silent_cmd "gu (define l2$var (value->lazy-string $var #:length 2))" "acquire lazy string, length 2" 1
|
||||||
|
gdb_test "gu (print (lazy-string-length l2$var))" "2" "lazy string length 2"
|
||||||
|
gdb_test "gu (print (lazy-string->value l2$var))" "\"[string range $value 0 1]\"" "lazy string length 2 value"
|
||||||
|
# This test will have to wait until gdb can handle it. There's no way,
|
||||||
|
# currently, to internally specify an array of length zero in the C
|
||||||
|
# language support. PR 20786
|
||||||
|
#gdb_test "gu (print (lazy-string->value (value->lazy-string $var #:length 0)))" "\"\"" "empty lazy string value"
|
||||||
|
}
|
||||||
|
}
|
|
@ -81,13 +81,11 @@ main (int argc, char *argv[])
|
||||||
char nullst[17] = "divide\0et\0impera";
|
char nullst[17] = "divide\0et\0impera";
|
||||||
void (*fp1) (void) = &func1;
|
void (*fp1) (void) = &func1;
|
||||||
int (*fp2) (int, int) = &func2;
|
int (*fp2) (int, int) = &func2;
|
||||||
const char *sptr = "pointer";
|
|
||||||
const char *embed = "embedded x\201\202\203\204";
|
const char *embed = "embedded x\201\202\203\204";
|
||||||
int a[3] = {1,2,3};
|
int a[3] = {1,2,3};
|
||||||
int *p = a;
|
int *p = a;
|
||||||
int i = 2;
|
int i = 2;
|
||||||
int *ptr_i = &i;
|
int *ptr_i = &i;
|
||||||
const char *sn = 0;
|
|
||||||
s.a = 3;
|
s.a = 3;
|
||||||
s.b = 5;
|
s.b = 5;
|
||||||
u.a = 7;
|
u.a = 7;
|
||||||
|
|
|
@ -213,36 +213,6 @@ proc test_strings {} {
|
||||||
"restore target-charset"
|
"restore target-charset"
|
||||||
}
|
}
|
||||||
|
|
||||||
proc test_lazy_strings {} {
|
|
||||||
global hex
|
|
||||||
|
|
||||||
gdb_test "print sptr" "\"pointer\""
|
|
||||||
gdb_scm_test_silent_cmd "gu (define sptr (history-ref 0))" \
|
|
||||||
"lazy strings: get sptr value from history"
|
|
||||||
|
|
||||||
gdb_scm_test_silent_cmd "gu (define lstr (value->lazy-string sptr))" \
|
|
||||||
"Aquire lazy string"
|
|
||||||
gdb_test "gu (print (lazy-string-type lstr))" \
|
|
||||||
"= const char \*." "Test lazy-string type name equality"
|
|
||||||
gdb_test "gu (print (value-type sptr))" \
|
|
||||||
"= const char \*." "Test string type name equality"
|
|
||||||
|
|
||||||
# Prevent symbol on address 0x0 being printed.
|
|
||||||
gdb_test_no_output "set print symbol off"
|
|
||||||
gdb_test "print sn" "0x0"
|
|
||||||
|
|
||||||
gdb_scm_test_silent_cmd "gu (define snptr (history-ref 0))" \
|
|
||||||
"lazy strings: get snptr value from history"
|
|
||||||
gdb_test "gu (define snstr (value->lazy-string snptr #:length 5))" \
|
|
||||||
".*cannot create a lazy string with address.*" "Test lazy string"
|
|
||||||
gdb_scm_test_silent_cmd "gu (define snstr (value->lazy-string snptr #:length 0))" \
|
|
||||||
"Successfully create a lazy string"
|
|
||||||
gdb_test "gu (print (lazy-string-length snstr))" \
|
|
||||||
"= 0" "Test lazy string length"
|
|
||||||
gdb_test "gu (print (lazy-string-address snstr))" \
|
|
||||||
"= 0" "Test lazy string address"
|
|
||||||
}
|
|
||||||
|
|
||||||
proc test_inferior_function_call {} {
|
proc test_inferior_function_call {} {
|
||||||
global gdb_prompt hex decimal
|
global gdb_prompt hex decimal
|
||||||
|
|
||||||
|
@ -457,7 +427,6 @@ if ![gdb_guile_runto_main] {
|
||||||
test_value_in_inferior
|
test_value_in_inferior
|
||||||
test_inferior_function_call
|
test_inferior_function_call
|
||||||
test_strings
|
test_strings
|
||||||
test_lazy_strings
|
|
||||||
test_value_after_death
|
test_value_after_death
|
||||||
|
|
||||||
# Test either C or C++ values.
|
# Test either C or C++ values.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue