hammer/src/registry.c

88 lines
2.7 KiB
C
Raw Normal View History

2013-11-19 21:14:39 -06:00
/* Parser combinators for binary formats.
* Copyright (C) 2012 Meredith L. Patterson, Dan "TQ" Hirsch
*
* 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, version 2.
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <search.h>
#include <stdlib.h>
#include "hammer.h"
#include "internal.h"
typedef struct Entry_ {
const char* name;
HTokenType value;
2013-11-19 21:14:39 -06:00
} Entry;
static void *tt_registry = NULL;
static Entry** tt_by_id = NULL;
static unsigned int tt_by_id_sz = 0;
2013-11-19 21:14:39 -06:00
#define TT_START TT_USER
static HTokenType tt_next = TT_START;
2013-11-19 21:14:39 -06:00
/*
// TODO: These are for the extension registry, which does not yet have a good name.
static void *ext_registry = NULL;
static Entry** ext_by_id = NULL;
static int ext_by_id_sz = 0;
static int ext_next = 0;
*/
static int compare_entries(const void* v1, const void* v2) {
const Entry *e1 = (Entry*)v1, *e2 = (Entry*)v2;
return strcmp(e1->name, e2->name);
}
HTokenType h_allocate_token_type(const char* name) {
2013-11-19 21:14:39 -06:00
Entry* new_entry = malloc(sizeof(*new_entry));
new_entry->name = name;
new_entry->value = 0;
2013-11-19 21:14:39 -06:00
Entry* probe = *(Entry**)tsearch(new_entry, &tt_registry, compare_entries);
if (probe->value != 0) {
2013-11-19 21:14:39 -06:00
// Token type already exists...
// TODO: treat this as a bug?
free(new_entry);
return probe->value;
} else {
// new value
probe->name = strdup(probe->name); // drop ownership of name
probe->value = tt_next++;
if ((probe->value - TT_START) >= tt_by_id_sz) {
if (tt_by_id_sz == 0)
tt_by_id = malloc(sizeof(*tt_by_id) * ((tt_by_id_sz = (tt_next - TT_START) * 16)));
else
tt_by_id = realloc(tt_by_id, sizeof(*tt_by_id) * ((tt_by_id_sz *= 2)));
}
assert(probe->value - TT_START < tt_by_id_sz);
tt_by_id[probe->value - TT_START] = probe;
return probe->value;
}
}
HTokenType h_get_token_type_number(const char* name) {
2013-11-19 21:14:39 -06:00
Entry e;
e.name = name;
Entry **ret = (Entry**)tfind(&e, &tt_registry, compare_entries);
if (ret == NULL)
return 0;
2013-11-19 21:14:39 -06:00
else
return (*ret)->value;
}
const char* h_get_token_type_name(HTokenType token_type) {
2013-11-19 21:14:39 -06:00
if (token_type >= tt_next || token_type < TT_START)
return NULL;
else
return tt_by_id[token_type - TT_START]->name;
}