From aa0fbdd82c86c683f6d2bf39dcc9dedfc9c7a8d0 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Thu, 13 Sep 2012 14:35:16 +0000 Subject: [PATCH] 2012-09-13 Pedro Alves * Makefile.in (COMMON_OBS): Add registry.o. * registry.c: New file. * registry.h (struct registry_container): Declare. (registry_data_callback): New typedef. (struct registry_data, struct registry_data_registration, struct registry_data_registry): New type. (register_data_with_cleanup, registry_alloc_data) (registry_callback_adaptor, registry_clear_data) (registry_container_free_data, registry_set_data, registry_data): Declare. (DEFINE_REGISTRY): Refactor structures and functions as shims over the new common structures and functions. (DECLARE_REGISTRY): Declare struct TAG ## _data. Use the tagged callback typedefs. --- gdb/ChangeLog | 17 ++++++ gdb/Makefile.in | 2 +- gdb/registry.c | 116 ++++++++++++++++++++++++++++++++++++ gdb/registry.h | 182 ++++++++++++++++++++++++++++++++++---------------------- 4 files changed, 246 insertions(+), 71 deletions(-) create mode 100644 gdb/registry.c diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 1e9b76e..8c83178 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,20 @@ +2012-09-13 Pedro Alves + + * Makefile.in (COMMON_OBS): Add registry.o. + * registry.c: New file. + * registry.h (struct registry_container): Declare. + (registry_data_callback): New typedef. + (struct registry_data, struct registry_data_registration, struct + registry_data_registry): New type. + (register_data_with_cleanup, registry_alloc_data) + (registry_callback_adaptor, registry_clear_data) + (registry_container_free_data, registry_set_data, registry_data): + Declare. + (DEFINE_REGISTRY): Refactor structures and functions as shims over + the new common structures and functions. + (DECLARE_REGISTRY): Declare struct TAG ## _data. Use the tagged + callback typedefs. + 2012-09-12 Doug Evans * dwarf2read.c (dwarf2_read_addr_index): Fix handling the case where diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 5d5574e..9e7702d 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -921,7 +921,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ inferior.o osdata.o gdb_usleep.o record.o gcore.o \ gdb_vecs.o jit.o progspace.o skip.o probe.o \ common-utils.o buffer.o ptid.o gdb-dlfcn.o common-agent.o \ - format.o + format.o registry.o TSOBS = inflow.o diff --git a/gdb/registry.c b/gdb/registry.c new file mode 100644 index 0000000..c01929b --- /dev/null +++ b/gdb/registry.c @@ -0,0 +1,116 @@ +/* Support functions for general registry objects. + + Copyright (C) 2011, 2012 + 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 . */ + +#include "defs.h" +#include "registry.h" +#include "gdb_assert.h" +#include "gdb_string.h" + +const struct registry_data * +register_data_with_cleanup (struct registry_data_registry *registry, + registry_data_callback save, + registry_data_callback free) +{ + struct registry_data_registration **curr; + + /* Append new registration. */ + for (curr = ®istry->registrations; + *curr != NULL; + curr = &(*curr)->next) + ; + + *curr = XMALLOC (struct registry_data_registration); + (*curr)->next = NULL; + (*curr)->data = XMALLOC (struct registry_data); + (*curr)->data->index = registry->num_registrations++; + (*curr)->data->save = save; + (*curr)->data->free = free; + + return (*curr)->data; +} + +void +registry_alloc_data (struct registry_data_registry *registry, + struct registry_fields *fields) +{ + gdb_assert (fields->data == NULL); + fields->num_data = registry->num_registrations; + fields->data = XCALLOC (fields->num_data, void *); +} + +void +registry_clear_data (struct registry_data_registry *data_registry, + registry_callback_adaptor adaptor, + struct registry_container *container, + struct registry_fields *fields) +{ + struct registry_data_registration *registration; + int i; + + gdb_assert (fields->data != NULL); + + /* Process all the save handlers. */ + + for (registration = data_registry->registrations, i = 0; + i < fields->num_data; + registration = registration->next, i++) + if (fields->data[i] != NULL && registration->data->save != NULL) + adaptor (registration->data->save, container, fields->data[i]); + + /* Now process all the free handlers. */ + + for (registration = data_registry->registrations, i = 0; + i < fields->num_data; + registration = registration->next, i++) + if (fields->data[i] != NULL && registration->data->free != NULL) + adaptor (registration->data->free, container, fields->data[i]); + + memset (fields->data, 0, fields->num_data * sizeof (void *)); +} + +void +registry_container_free_data (struct registry_data_registry *data_registry, + registry_callback_adaptor adaptor, + struct registry_container *container, + struct registry_fields *fields) +{ + void ***rdata = &fields->data; + gdb_assert (*rdata != NULL); + registry_clear_data (data_registry, adaptor, container, fields); + xfree (*rdata); + *rdata = NULL; +} + +void +registry_set_data (struct registry_fields *fields, + const struct registry_data *data, + void *value) +{ + gdb_assert (data->index < fields->num_data); + fields->data[data->index] = value; +} + +void * +registry_data (struct registry_fields *fields, + const struct registry_data *data) +{ + gdb_assert (data->index < fields->num_data); + return fields->data[data->index]; +} diff --git a/gdb/registry.h b/gdb/registry.h index 423caa6..062a500 100644 --- a/gdb/registry.h +++ b/gdb/registry.h @@ -85,48 +85,85 @@ struct registry_fields #define REGISTRY_ACCESS_FIELD(CONTAINER) \ (CONTAINER) +/* Opaque type representing a container type with a registry. This + type is never defined. This is used to factor out common + functionality of all struct tag names into common code. IOW, + "struct tag name" pointers are cast to and from "struct + registry_container" pointers when calling the common registry + "backend" functions. */ +struct registry_container; + +/* Registry callbacks have this type. */ +typedef void (*registry_data_callback) (struct registry_container *, void *); + +struct registry_data +{ + unsigned index; + registry_data_callback save; + registry_data_callback free; +}; + +struct registry_data_registration +{ + struct registry_data *data; + struct registry_data_registration *next; +}; + +struct registry_data_registry +{ + struct registry_data_registration *registrations; + unsigned num_registrations; +}; + +/* Registry backend functions. Client code uses the frontend + functions defined by DEFINE_REGISTRY below instead. */ + +const struct registry_data *register_data_with_cleanup + (struct registry_data_registry *registry, + registry_data_callback save, + registry_data_callback free); + +void registry_alloc_data (struct registry_data_registry *registry, + struct registry_fields *registry_fields); + +/* Cast FUNC and CONTAINER to the real types, and call FUNC, also + passing DATA. */ +typedef void (*registry_callback_adaptor) (registry_data_callback func, + struct registry_container *container, + void *data); + +void registry_clear_data (struct registry_data_registry *data_registry, + registry_callback_adaptor adaptor, + struct registry_container *container, + struct registry_fields *fields); + +void registry_container_free_data (struct registry_data_registry *data_registry, + registry_callback_adaptor adaptor, + struct registry_container *container, + struct registry_fields *fields); + +void registry_set_data (struct registry_fields *fields, + const struct registry_data *data, + void *value); + +void *registry_data (struct registry_fields *fields, + const struct registry_data *data); + /* Define a new registry implementation. */ #define DEFINE_REGISTRY(TAG, ACCESS) \ -struct TAG ## _data \ -{ \ - unsigned index; \ - void (*save) (struct TAG *, void *); \ - void (*free) (struct TAG *, void *); \ -}; \ - \ -struct TAG ## _data_registration \ -{ \ - struct TAG ## _data *data; \ - struct TAG ## _data_registration *next; \ -}; \ - \ -struct TAG ## _data_registry \ -{ \ - struct TAG ## _data_registration *registrations; \ - unsigned num_registrations; \ -}; \ - \ -struct TAG ## _data_registry TAG ## _data_registry = { NULL, 0 }; \ +struct registry_data_registry TAG ## _data_registry = { NULL, 0 }; \ \ const struct TAG ## _data * \ register_ ## TAG ## _data_with_cleanup (void (*save) (struct TAG *, void *), \ - void (*free) (struct TAG *, void *)) \ + void (*free) (struct TAG *, void *)) \ { \ - struct TAG ## _data_registration **curr; \ - \ - /* Append new registration. */ \ - for (curr = &TAG ## _data_registry.registrations; \ - *curr != NULL; curr = &(*curr)->next); \ - \ - *curr = XMALLOC (struct TAG ## _data_registration); \ - (*curr)->next = NULL; \ - (*curr)->data = XMALLOC (struct TAG ## _data); \ - (*curr)->data->index = TAG ## _data_registry.num_registrations++; \ - (*curr)->data->save = save; \ - (*curr)->data->free = free; \ + struct registry_data_registration **curr; \ \ - return (*curr)->data; \ + return (struct TAG ## _data *) \ + register_data_with_cleanup (&TAG ## _data_registry, \ + (registry_data_callback) save, \ + (registry_data_callback) free); \ } \ \ const struct TAG ## _data * \ @@ -139,76 +176,81 @@ static void \ TAG ## _alloc_data (struct TAG *container) \ { \ struct registry_fields *rdata = &ACCESS (container)->registry_data; \ - gdb_assert (rdata->data == NULL); \ - rdata->num_data = TAG ## _data_registry.num_registrations; \ - rdata->data = XCALLOC (rdata->num_data, void *); \ + \ + registry_alloc_data (&TAG ## _data_registry, rdata); \ } \ \ -void \ -clear_ ## TAG ## _data (struct TAG *container) \ +static void \ +TAG ## registry_callback_adaptor (registry_data_callback func, \ + struct registry_container *container, \ + void *data) \ { \ - struct registry_fields *rdata = &ACCESS (container)->registry_data; \ - struct TAG ## _data_registration *registration; \ - int i; \ + struct TAG *tagged_container = (struct TAG *) container; \ + struct registry_fields *rdata \ + = &ACCESS (tagged_container)->registry_data; \ \ - gdb_assert (rdata->data != NULL); \ + registry_ ## TAG ## _callback tagged_func \ + = (registry_ ## TAG ## _callback) func; \ \ - /* Process all the save handlers. */ \ - \ - for (registration = TAG ## _data_registry.registrations, i = 0; \ - i < rdata->num_data; \ - registration = registration->next, i++) \ - if (rdata->data[i] != NULL && registration->data->save != NULL) \ - registration->data->save (container, rdata->data[i]); \ - \ - /* Now process all the free handlers. */ \ + tagged_func (tagged_container, data); \ +} \ \ - for (registration = TAG ## _data_registry.registrations, i = 0; \ - i < rdata->num_data; \ - registration = registration->next, i++) \ - if (rdata->data[i] != NULL && registration->data->free != NULL) \ - registration->data->free (container, rdata->data[i]); \ +void \ +clear_ ## TAG ## _data (struct TAG *container) \ +{ \ + struct registry_fields *rdata = &ACCESS (container)->registry_data; \ \ - memset (rdata->data, 0, rdata->num_data * sizeof (void *)); \ + registry_clear_data (&TAG ## _data_registry, \ + TAG ## registry_callback_adaptor, \ + (struct registry_container *) container, \ + rdata); \ } \ \ static void \ TAG ## _free_data (struct TAG *container) \ { \ struct registry_fields *rdata = &ACCESS (container)->registry_data; \ - gdb_assert (rdata->data != NULL); \ - clear_ ## TAG ## _data (container); \ - xfree (rdata->data); \ - rdata->data = NULL; \ + \ + registry_container_free_data (&TAG ## _data_registry, \ + TAG ## registry_callback_adaptor, \ + (struct registry_container *) container, \ + rdata); \ } \ \ void \ -set_ ## TAG ## _data (struct TAG *container, const struct TAG ## _data *data, \ - void *value) \ +set_ ## TAG ## _data (struct TAG *container, \ + const struct TAG ## _data *data, \ + void *value) \ { \ struct registry_fields *rdata = &ACCESS (container)->registry_data; \ - gdb_assert (data->index < rdata->num_data); \ - rdata->data[data->index] = value; \ + \ + registry_set_data (rdata, \ + (struct registry_data *) data, \ + value); \ } \ \ void * \ TAG ## _data (struct TAG *container, const struct TAG ## _data *data) \ { \ struct registry_fields *rdata = &ACCESS (container)->registry_data; \ - gdb_assert (data->index < rdata->num_data); \ - return rdata->data[data->index]; \ + \ + return registry_data (rdata, \ + (struct registry_data *) data); \ } /* External declarations for the registry functions. */ #define DECLARE_REGISTRY(TAG) \ +struct TAG ## _data; \ +typedef void (*registry_ ## TAG ## _callback) (struct TAG *, void *); \ extern const struct TAG ## _data *register_ ## TAG ## _data (void); \ extern const struct TAG ## _data *register_ ## TAG ## _data_with_cleanup \ - (void (*save) (struct TAG *, void *), void (*free) (struct TAG *, void *)); \ + (registry_ ## TAG ## _callback save, registry_ ## TAG ## _callback free); \ extern void clear_ ## TAG ## _data (struct TAG *); \ extern void set_ ## TAG ## _data (struct TAG *, \ - const struct TAG ## _data *data, void *value); \ + const struct TAG ## _data *data, \ + void *value); \ extern void *TAG ## _data (struct TAG *, \ const struct TAG ## _data *data); -- 2.7.4