| /* This file is part of the program psim. | |
| Copyright (C) 1994-1995,1997, Andrew Cagney <cagney@highland.com.au> | |
| 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/>. | |
| */ | |
| #ifndef _CAP_C_ | |
| #define _CAP_C_ | |
| #include "cap.h" | |
| typedef struct _cap_mapping cap_mapping; | |
| struct _cap_mapping { | |
| unsigned_cell external; | |
| void *internal; | |
| cap_mapping *next; | |
| }; | |
| struct _cap { | |
| int nr_mappings; | |
| cap_mapping *mappings; | |
| }; | |
| INLINE_CAP\ | |
| (cap *) | |
| cap_create(const char *key) | |
| { | |
| return ZALLOC(cap); | |
| } | |
| INLINE_CAP\ | |
| (void) | |
| cap_init(cap *db) | |
| { | |
| cap_mapping *current_map = db->mappings; | |
| if (current_map != NULL) { | |
| db->nr_mappings = db->mappings->external; | |
| /* verify that the mappings that were not removed are in sequence | |
| down to nr 1 */ | |
| while (current_map->next != NULL) { | |
| if (current_map->external != current_map->next->external + 1) | |
| error("cap: cap database possibly corrupt"); | |
| current_map = current_map->next; | |
| } | |
| ASSERT(current_map->next == NULL); | |
| if (current_map->external != 1) | |
| error("cap: cap database possibly currupt"); | |
| } | |
| else { | |
| db->nr_mappings = 0; | |
| } | |
| } | |
| INLINE_CAP\ | |
| (void *) | |
| cap_internal(cap *db, | |
| signed_cell external) | |
| { | |
| cap_mapping *current_map = db->mappings; | |
| while (current_map != NULL) { | |
| if (current_map->external == external) | |
| return current_map->internal; | |
| current_map = current_map->next; | |
| } | |
| return (void*)0; | |
| } | |
| INLINE_CAP\ | |
| (signed_cell) | |
| cap_external(cap *db, | |
| void *internal) | |
| { | |
| cap_mapping *current_map = db->mappings; | |
| while (current_map != NULL) { | |
| if (current_map->internal == internal) | |
| return current_map->external; | |
| current_map = current_map->next; | |
| } | |
| return 0; | |
| } | |
| INLINE_CAP\ | |
| (void) | |
| cap_add(cap *db, | |
| void *internal) | |
| { | |
| if (cap_external(db, internal) != 0) { | |
| error("cap: attempting to add an object already in the data base"); | |
| } | |
| else { | |
| /* insert at the front making things in decending order */ | |
| cap_mapping *new_map = ZALLOC(cap_mapping); | |
| new_map->next = db->mappings; | |
| new_map->internal = internal; | |
| db->nr_mappings += 1; | |
| new_map->external = db->nr_mappings; | |
| db->mappings = new_map; | |
| } | |
| } | |
| INLINE_CAP\ | |
| (void) | |
| cap_remove(cap *db, | |
| void *internal) | |
| { | |
| cap_mapping **current_map = &db->mappings; | |
| while (*current_map != NULL) { | |
| if ((*current_map)->internal == internal) { | |
| cap_mapping *delete = *current_map; | |
| *current_map = delete->next; | |
| free(delete); | |
| return; | |
| } | |
| current_map = &(*current_map)->next; | |
| } | |
| error("cap: attempt to remove nonexistant internal object"); | |
| } | |
| #endif |