* gdbarch.sh (struct gdbarch_data): Add field init_p.
(register_gdbarch_data): Initialize init_p. (gdbarch_data): Initialize data pointer using the init function. (init_gdbarch_data): Delete function. (gdbarch_update_p): Update. (initialize_non_multiarch): Update. (struct gdbarch): Add field initialized_p. * gdbarch.h, gdbarch.c: Re-generate.
This commit is contained in:
parent
3010767930
commit
76860b5fb3
4 changed files with 81 additions and 80 deletions
|
@ -1,3 +1,14 @@
|
||||||
|
2002-06-08 Andrew Cagney <ac131313@redhat.com>
|
||||||
|
|
||||||
|
* gdbarch.sh (struct gdbarch_data): Add field init_p.
|
||||||
|
(register_gdbarch_data): Initialize init_p.
|
||||||
|
(gdbarch_data): Initialize data pointer using the init function.
|
||||||
|
(init_gdbarch_data): Delete function.
|
||||||
|
(gdbarch_update_p): Update.
|
||||||
|
(initialize_non_multiarch): Update.
|
||||||
|
(struct gdbarch): Add field initialized_p.
|
||||||
|
* gdbarch.h, gdbarch.c: Re-generate.
|
||||||
|
|
||||||
2002-06-07 Michal Ludvig <mludvig@suse.cz>
|
2002-06-07 Michal Ludvig <mludvig@suse.cz>
|
||||||
|
|
||||||
* x86-64-linux-nat.c (x86_64_fxsave_offset): New.
|
* x86-64-linux-nat.c (x86_64_fxsave_offset): New.
|
||||||
|
|
|
@ -68,7 +68,6 @@
|
||||||
|
|
||||||
static void verify_gdbarch (struct gdbarch *gdbarch);
|
static void verify_gdbarch (struct gdbarch *gdbarch);
|
||||||
static void alloc_gdbarch_data (struct gdbarch *);
|
static void alloc_gdbarch_data (struct gdbarch *);
|
||||||
static void init_gdbarch_data (struct gdbarch *);
|
|
||||||
static void free_gdbarch_data (struct gdbarch *);
|
static void free_gdbarch_data (struct gdbarch *);
|
||||||
static void init_gdbarch_swap (struct gdbarch *);
|
static void init_gdbarch_swap (struct gdbarch *);
|
||||||
static void clear_gdbarch_swap (struct gdbarch *);
|
static void clear_gdbarch_swap (struct gdbarch *);
|
||||||
|
@ -87,6 +86,8 @@ int gdbarch_debug = GDBARCH_DEBUG;
|
||||||
|
|
||||||
struct gdbarch
|
struct gdbarch
|
||||||
{
|
{
|
||||||
|
/* Has this architecture been fully initialized? */
|
||||||
|
int initialized_p;
|
||||||
/* basic architectural information */
|
/* basic architectural information */
|
||||||
const struct bfd_arch_info * bfd_arch_info;
|
const struct bfd_arch_info * bfd_arch_info;
|
||||||
int byte_order;
|
int byte_order;
|
||||||
|
@ -269,6 +270,7 @@ extern const struct bfd_arch_info bfd_default_arch_struct;
|
||||||
|
|
||||||
struct gdbarch startup_gdbarch =
|
struct gdbarch startup_gdbarch =
|
||||||
{
|
{
|
||||||
|
1, /* Always initialized. */
|
||||||
/* basic architecture information */
|
/* basic architecture information */
|
||||||
&bfd_default_arch_struct,
|
&bfd_default_arch_struct,
|
||||||
BFD_ENDIAN_BIG,
|
BFD_ENDIAN_BIG,
|
||||||
|
@ -423,7 +425,6 @@ initialize_non_multiarch ()
|
||||||
they are starting from scratch. */
|
they are starting from scratch. */
|
||||||
clear_gdbarch_swap (&startup_gdbarch);
|
clear_gdbarch_swap (&startup_gdbarch);
|
||||||
init_gdbarch_swap (&startup_gdbarch);
|
init_gdbarch_swap (&startup_gdbarch);
|
||||||
init_gdbarch_data (&startup_gdbarch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4771,6 +4772,7 @@ set_gdbarch_coff_make_msymbol_special (struct gdbarch *gdbarch,
|
||||||
struct gdbarch_data
|
struct gdbarch_data
|
||||||
{
|
{
|
||||||
unsigned index;
|
unsigned index;
|
||||||
|
int init_p;
|
||||||
gdbarch_data_init_ftype *init;
|
gdbarch_data_init_ftype *init;
|
||||||
gdbarch_data_free_ftype *free;
|
gdbarch_data_free_ftype *free;
|
||||||
};
|
};
|
||||||
|
@ -4797,6 +4799,7 @@ register_gdbarch_data (gdbarch_data_init_ftype *init,
|
||||||
gdbarch_data_free_ftype *free)
|
gdbarch_data_free_ftype *free)
|
||||||
{
|
{
|
||||||
struct gdbarch_data_registration **curr;
|
struct gdbarch_data_registration **curr;
|
||||||
|
/* Append the new registraration. */
|
||||||
for (curr = &gdbarch_data_registry.registrations;
|
for (curr = &gdbarch_data_registry.registrations;
|
||||||
(*curr) != NULL;
|
(*curr) != NULL;
|
||||||
curr = &(*curr)->next);
|
curr = &(*curr)->next);
|
||||||
|
@ -4805,31 +4808,12 @@ register_gdbarch_data (gdbarch_data_init_ftype *init,
|
||||||
(*curr)->data = XMALLOC (struct gdbarch_data);
|
(*curr)->data = XMALLOC (struct gdbarch_data);
|
||||||
(*curr)->data->index = gdbarch_data_registry.nr++;
|
(*curr)->data->index = gdbarch_data_registry.nr++;
|
||||||
(*curr)->data->init = init;
|
(*curr)->data->init = init;
|
||||||
|
(*curr)->data->init_p = 1;
|
||||||
(*curr)->data->free = free;
|
(*curr)->data->free = free;
|
||||||
return (*curr)->data;
|
return (*curr)->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Walk through all the registered users initializing each in turn. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
init_gdbarch_data (struct gdbarch *gdbarch)
|
|
||||||
{
|
|
||||||
struct gdbarch_data_registration *rego;
|
|
||||||
for (rego = gdbarch_data_registry.registrations;
|
|
||||||
rego != NULL;
|
|
||||||
rego = rego->next)
|
|
||||||
{
|
|
||||||
struct gdbarch_data *data = rego->data;
|
|
||||||
gdb_assert (data->index < gdbarch->nr_data);
|
|
||||||
if (data->init != NULL)
|
|
||||||
{
|
|
||||||
void *pointer = data->init (gdbarch);
|
|
||||||
set_gdbarch_data (gdbarch, data, pointer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create/delete the gdbarch data vector. */
|
/* Create/delete the gdbarch data vector. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -4862,7 +4846,7 @@ free_gdbarch_data (struct gdbarch *gdbarch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Initialize the current value of thee specified per-architecture
|
/* Initialize the current value of the specified per-architecture
|
||||||
data-pointer. */
|
data-pointer. */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -4871,8 +4855,11 @@ set_gdbarch_data (struct gdbarch *gdbarch,
|
||||||
void *pointer)
|
void *pointer)
|
||||||
{
|
{
|
||||||
gdb_assert (data->index < gdbarch->nr_data);
|
gdb_assert (data->index < gdbarch->nr_data);
|
||||||
if (data->free != NULL && gdbarch->data[data->index] != NULL)
|
if (gdbarch->data[data->index] != NULL)
|
||||||
data->free (gdbarch, gdbarch->data[data->index]);
|
{
|
||||||
|
gdb_assert (data->free != NULL);
|
||||||
|
data->free (gdbarch, gdbarch->data[data->index]);
|
||||||
|
}
|
||||||
gdbarch->data[data->index] = pointer;
|
gdbarch->data[data->index] = pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4883,6 +4870,20 @@ void *
|
||||||
gdbarch_data (struct gdbarch *gdbarch, struct gdbarch_data *data)
|
gdbarch_data (struct gdbarch *gdbarch, struct gdbarch_data *data)
|
||||||
{
|
{
|
||||||
gdb_assert (data->index < gdbarch->nr_data);
|
gdb_assert (data->index < gdbarch->nr_data);
|
||||||
|
/* The data-pointer isn't initialized, call init() to get a value but
|
||||||
|
only if the architecture initializaiton has completed. Otherwise
|
||||||
|
punt - hope that the caller knows what they are doing. */
|
||||||
|
if (gdbarch->data[data->index] == NULL
|
||||||
|
&& gdbarch->initialized_p)
|
||||||
|
{
|
||||||
|
/* Be careful to detect an initialization cycle. */
|
||||||
|
gdb_assert (data->init_p);
|
||||||
|
data->init_p = 0;
|
||||||
|
gdb_assert (data->init != NULL);
|
||||||
|
gdbarch->data[data->index] = data->init (gdbarch);
|
||||||
|
data->init_p = 1;
|
||||||
|
gdb_assert (gdbarch->data[data->index] != NULL);
|
||||||
|
}
|
||||||
return gdbarch->data[data->index];
|
return gdbarch->data[data->index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5276,8 +5277,9 @@ gdbarch_update_p (struct gdbarch_info info)
|
||||||
rego->arches = this;
|
rego->arches = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Switch to this new architecture. Dump it out. */
|
/* Switch to this new architecture marking it initialized. */
|
||||||
current_gdbarch = new_gdbarch;
|
current_gdbarch = new_gdbarch;
|
||||||
|
current_gdbarch->initialized_p = 1;
|
||||||
if (gdbarch_debug)
|
if (gdbarch_debug)
|
||||||
{
|
{
|
||||||
fprintf_unfiltered (gdb_stdlog,
|
fprintf_unfiltered (gdb_stdlog,
|
||||||
|
@ -5296,10 +5298,8 @@ gdbarch_update_p (struct gdbarch_info info)
|
||||||
called. */
|
called. */
|
||||||
init_gdbarch_swap (new_gdbarch);
|
init_gdbarch_swap (new_gdbarch);
|
||||||
|
|
||||||
/* Initialize the per-architecture data-pointer of all parties that
|
/* Initialize the per-architecture data. CURRENT_GDBARCH
|
||||||
registered an interest in this architecture. CURRENT_GDBARCH
|
|
||||||
must be updated before these modules are called. */
|
must be updated before these modules are called. */
|
||||||
init_gdbarch_data (new_gdbarch);
|
|
||||||
architecture_changed_event ();
|
architecture_changed_event ();
|
||||||
|
|
||||||
if (gdbarch_debug)
|
if (gdbarch_debug)
|
||||||
|
|
|
@ -2591,20 +2591,15 @@ extern int gdbarch_update_p (struct gdbarch_info info);
|
||||||
for the reserved data-pointer is returned. That identifer should
|
for the reserved data-pointer is returned. That identifer should
|
||||||
be saved in a local static variable.
|
be saved in a local static variable.
|
||||||
|
|
||||||
The per-architecture data-pointer can be initialized in one of two
|
The per-architecture data-pointer is either initialized explicitly
|
||||||
ways: The value can be set explicitly using a call to
|
(set_gdbarch_data()) or implicitly (by INIT() via a call to
|
||||||
set_gdbarch_data(); the value can be set implicitly using the value
|
gdbarch_data()). FREE() is called to delete either an existing
|
||||||
returned by a non-NULL INIT() callback. INIT(), when non-NULL is
|
data-poitner overridden by set_gdbarch_data() or when the
|
||||||
called after the basic architecture vector has been created.
|
architecture object is being deleted.
|
||||||
|
|
||||||
When a previously created architecture is re-selected, the
|
When a previously created architecture is re-selected, the
|
||||||
per-architecture data-pointer for that previous architecture is
|
per-architecture data-pointer for that previous architecture is
|
||||||
restored. INIT() is not called.
|
restored. INIT() is not re-called.
|
||||||
|
|
||||||
During initialization, multiple assignments of the data-pointer are
|
|
||||||
allowed, non-NULL values are deleted by calling FREE(). If the
|
|
||||||
architecture is deleted using gdbarch_free() all non-NULL data
|
|
||||||
pointers are also deleted using FREE().
|
|
||||||
|
|
||||||
Multiple registrarants for any architecture are allowed (and
|
Multiple registrarants for any architecture are allowed (and
|
||||||
strongly encouraged). */
|
strongly encouraged). */
|
||||||
|
|
|
@ -1082,20 +1082,15 @@ extern int gdbarch_update_p (struct gdbarch_info info);
|
||||||
for the reserved data-pointer is returned. That identifer should
|
for the reserved data-pointer is returned. That identifer should
|
||||||
be saved in a local static variable.
|
be saved in a local static variable.
|
||||||
|
|
||||||
The per-architecture data-pointer can be initialized in one of two
|
The per-architecture data-pointer is either initialized explicitly
|
||||||
ways: The value can be set explicitly using a call to
|
(set_gdbarch_data()) or implicitly (by INIT() via a call to
|
||||||
set_gdbarch_data(); the value can be set implicitly using the value
|
gdbarch_data()). FREE() is called to delete either an existing
|
||||||
returned by a non-NULL INIT() callback. INIT(), when non-NULL is
|
data-poitner overridden by set_gdbarch_data() or when the
|
||||||
called after the basic architecture vector has been created.
|
architecture object is being deleted.
|
||||||
|
|
||||||
When a previously created architecture is re-selected, the
|
When a previously created architecture is re-selected, the
|
||||||
per-architecture data-pointer for that previous architecture is
|
per-architecture data-pointer for that previous architecture is
|
||||||
restored. INIT() is not called.
|
restored. INIT() is not re-called.
|
||||||
|
|
||||||
During initialization, multiple assignments of the data-pointer are
|
|
||||||
allowed, non-NULL values are deleted by calling FREE(). If the
|
|
||||||
architecture is deleted using gdbarch_free() all non-NULL data
|
|
||||||
pointers are also deleted using FREE().
|
|
||||||
|
|
||||||
Multiple registrarants for any architecture are allowed (and
|
Multiple registrarants for any architecture are allowed (and
|
||||||
strongly encouraged). */
|
strongly encouraged). */
|
||||||
|
@ -1249,7 +1244,6 @@ cat <<EOF
|
||||||
|
|
||||||
static void verify_gdbarch (struct gdbarch *gdbarch);
|
static void verify_gdbarch (struct gdbarch *gdbarch);
|
||||||
static void alloc_gdbarch_data (struct gdbarch *);
|
static void alloc_gdbarch_data (struct gdbarch *);
|
||||||
static void init_gdbarch_data (struct gdbarch *);
|
|
||||||
static void free_gdbarch_data (struct gdbarch *);
|
static void free_gdbarch_data (struct gdbarch *);
|
||||||
static void init_gdbarch_swap (struct gdbarch *);
|
static void init_gdbarch_swap (struct gdbarch *);
|
||||||
static void clear_gdbarch_swap (struct gdbarch *);
|
static void clear_gdbarch_swap (struct gdbarch *);
|
||||||
|
@ -1271,6 +1265,8 @@ printf "/* Maintain the struct gdbarch object */\n"
|
||||||
printf "\n"
|
printf "\n"
|
||||||
printf "struct gdbarch\n"
|
printf "struct gdbarch\n"
|
||||||
printf "{\n"
|
printf "{\n"
|
||||||
|
printf " /* Has this architecture been fully initialized? */\n"
|
||||||
|
printf " int initialized_p;\n"
|
||||||
printf " /* basic architectural information */\n"
|
printf " /* basic architectural information */\n"
|
||||||
function_list | while do_read
|
function_list | while do_read
|
||||||
do
|
do
|
||||||
|
@ -1343,6 +1339,7 @@ printf "extern const struct bfd_arch_info bfd_default_arch_struct;\n"
|
||||||
printf "\n"
|
printf "\n"
|
||||||
printf "struct gdbarch startup_gdbarch =\n"
|
printf "struct gdbarch startup_gdbarch =\n"
|
||||||
printf "{\n"
|
printf "{\n"
|
||||||
|
printf " 1, /* Always initialized. */\n"
|
||||||
printf " /* basic architecture information */\n"
|
printf " /* basic architecture information */\n"
|
||||||
function_list | while do_read
|
function_list | while do_read
|
||||||
do
|
do
|
||||||
|
@ -1381,7 +1378,6 @@ initialize_non_multiarch ()
|
||||||
they are starting from scratch. */
|
they are starting from scratch. */
|
||||||
clear_gdbarch_swap (&startup_gdbarch);
|
clear_gdbarch_swap (&startup_gdbarch);
|
||||||
init_gdbarch_swap (&startup_gdbarch);
|
init_gdbarch_swap (&startup_gdbarch);
|
||||||
init_gdbarch_data (&startup_gdbarch);
|
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
@ -1747,6 +1743,7 @@ cat <<EOF
|
||||||
struct gdbarch_data
|
struct gdbarch_data
|
||||||
{
|
{
|
||||||
unsigned index;
|
unsigned index;
|
||||||
|
int init_p;
|
||||||
gdbarch_data_init_ftype *init;
|
gdbarch_data_init_ftype *init;
|
||||||
gdbarch_data_free_ftype *free;
|
gdbarch_data_free_ftype *free;
|
||||||
};
|
};
|
||||||
|
@ -1773,6 +1770,7 @@ register_gdbarch_data (gdbarch_data_init_ftype *init,
|
||||||
gdbarch_data_free_ftype *free)
|
gdbarch_data_free_ftype *free)
|
||||||
{
|
{
|
||||||
struct gdbarch_data_registration **curr;
|
struct gdbarch_data_registration **curr;
|
||||||
|
/* Append the new registraration. */
|
||||||
for (curr = &gdbarch_data_registry.registrations;
|
for (curr = &gdbarch_data_registry.registrations;
|
||||||
(*curr) != NULL;
|
(*curr) != NULL;
|
||||||
curr = &(*curr)->next);
|
curr = &(*curr)->next);
|
||||||
|
@ -1781,31 +1779,12 @@ register_gdbarch_data (gdbarch_data_init_ftype *init,
|
||||||
(*curr)->data = XMALLOC (struct gdbarch_data);
|
(*curr)->data = XMALLOC (struct gdbarch_data);
|
||||||
(*curr)->data->index = gdbarch_data_registry.nr++;
|
(*curr)->data->index = gdbarch_data_registry.nr++;
|
||||||
(*curr)->data->init = init;
|
(*curr)->data->init = init;
|
||||||
|
(*curr)->data->init_p = 1;
|
||||||
(*curr)->data->free = free;
|
(*curr)->data->free = free;
|
||||||
return (*curr)->data;
|
return (*curr)->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Walk through all the registered users initializing each in turn. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
init_gdbarch_data (struct gdbarch *gdbarch)
|
|
||||||
{
|
|
||||||
struct gdbarch_data_registration *rego;
|
|
||||||
for (rego = gdbarch_data_registry.registrations;
|
|
||||||
rego != NULL;
|
|
||||||
rego = rego->next)
|
|
||||||
{
|
|
||||||
struct gdbarch_data *data = rego->data;
|
|
||||||
gdb_assert (data->index < gdbarch->nr_data);
|
|
||||||
if (data->init != NULL)
|
|
||||||
{
|
|
||||||
void *pointer = data->init (gdbarch);
|
|
||||||
set_gdbarch_data (gdbarch, data, pointer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create/delete the gdbarch data vector. */
|
/* Create/delete the gdbarch data vector. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1838,7 +1817,7 @@ free_gdbarch_data (struct gdbarch *gdbarch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Initialize the current value of thee specified per-architecture
|
/* Initialize the current value of the specified per-architecture
|
||||||
data-pointer. */
|
data-pointer. */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1847,8 +1826,11 @@ set_gdbarch_data (struct gdbarch *gdbarch,
|
||||||
void *pointer)
|
void *pointer)
|
||||||
{
|
{
|
||||||
gdb_assert (data->index < gdbarch->nr_data);
|
gdb_assert (data->index < gdbarch->nr_data);
|
||||||
if (data->free != NULL && gdbarch->data[data->index] != NULL)
|
if (gdbarch->data[data->index] != NULL)
|
||||||
data->free (gdbarch, gdbarch->data[data->index]);
|
{
|
||||||
|
gdb_assert (data->free != NULL);
|
||||||
|
data->free (gdbarch, gdbarch->data[data->index]);
|
||||||
|
}
|
||||||
gdbarch->data[data->index] = pointer;
|
gdbarch->data[data->index] = pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1859,6 +1841,20 @@ void *
|
||||||
gdbarch_data (struct gdbarch *gdbarch, struct gdbarch_data *data)
|
gdbarch_data (struct gdbarch *gdbarch, struct gdbarch_data *data)
|
||||||
{
|
{
|
||||||
gdb_assert (data->index < gdbarch->nr_data);
|
gdb_assert (data->index < gdbarch->nr_data);
|
||||||
|
/* The data-pointer isn't initialized, call init() to get a value but
|
||||||
|
only if the architecture initializaiton has completed. Otherwise
|
||||||
|
punt - hope that the caller knows what they are doing. */
|
||||||
|
if (gdbarch->data[data->index] == NULL
|
||||||
|
&& gdbarch->initialized_p)
|
||||||
|
{
|
||||||
|
/* Be careful to detect an initialization cycle. */
|
||||||
|
gdb_assert (data->init_p);
|
||||||
|
data->init_p = 0;
|
||||||
|
gdb_assert (data->init != NULL);
|
||||||
|
gdbarch->data[data->index] = data->init (gdbarch);
|
||||||
|
data->init_p = 1;
|
||||||
|
gdb_assert (gdbarch->data[data->index] != NULL);
|
||||||
|
}
|
||||||
return gdbarch->data[data->index];
|
return gdbarch->data[data->index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2252,8 +2248,9 @@ gdbarch_update_p (struct gdbarch_info info)
|
||||||
rego->arches = this;
|
rego->arches = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Switch to this new architecture. Dump it out. */
|
/* Switch to this new architecture marking it initialized. */
|
||||||
current_gdbarch = new_gdbarch;
|
current_gdbarch = new_gdbarch;
|
||||||
|
current_gdbarch->initialized_p = 1;
|
||||||
if (gdbarch_debug)
|
if (gdbarch_debug)
|
||||||
{
|
{
|
||||||
fprintf_unfiltered (gdb_stdlog,
|
fprintf_unfiltered (gdb_stdlog,
|
||||||
|
@ -2272,10 +2269,8 @@ gdbarch_update_p (struct gdbarch_info info)
|
||||||
called. */
|
called. */
|
||||||
init_gdbarch_swap (new_gdbarch);
|
init_gdbarch_swap (new_gdbarch);
|
||||||
|
|
||||||
/* Initialize the per-architecture data-pointer of all parties that
|
/* Initialize the per-architecture data. CURRENT_GDBARCH
|
||||||
registered an interest in this architecture. CURRENT_GDBARCH
|
|
||||||
must be updated before these modules are called. */
|
must be updated before these modules are called. */
|
||||||
init_gdbarch_data (new_gdbarch);
|
|
||||||
architecture_changed_event ();
|
architecture_changed_event ();
|
||||||
|
|
||||||
if (gdbarch_debug)
|
if (gdbarch_debug)
|
||||||
|
|
Loading…
Reference in a new issue