Added token type registry. Closes #45
This commit is contained in:
parent
b6098075c7
commit
4811f58374
4 changed files with 118 additions and 0 deletions
|
|
@ -49,6 +49,7 @@ misc_hammer_parts = [
|
||||||
'glue.c',
|
'glue.c',
|
||||||
'hammer.c',
|
'hammer.c',
|
||||||
'pprint.c',
|
'pprint.c',
|
||||||
|
'registry.c',
|
||||||
'system_allocator.c']
|
'system_allocator.c']
|
||||||
|
|
||||||
tests = ['t_benchmark.c',
|
tests = ['t_benchmark.c',
|
||||||
|
|
|
||||||
11
src/hammer.h
11
src/hammer.h
|
|
@ -633,4 +633,15 @@ void h_benchmark_report(FILE* stream, HBenchmarkResults* results);
|
||||||
void h_benchmark_dump_optimized_code(FILE* stream, HBenchmarkResults* results);
|
void h_benchmark_dump_optimized_code(FILE* stream, HBenchmarkResults* results);
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
|
// {{{ Token type registry
|
||||||
|
/// Allocate a new, unused (as far as this function knows) token type.
|
||||||
|
int h_allocate_token_type(const char* name);
|
||||||
|
|
||||||
|
/// Get the token type associated with name. Returns -1 if name is unkown
|
||||||
|
int h_get_token_type_number(const char* name);
|
||||||
|
|
||||||
|
/// Get the name associated with token_type. Returns NULL if the token type is unkown
|
||||||
|
const char* h_get_token_type_name(int token_type);
|
||||||
|
// }}}
|
||||||
|
|
||||||
#endif // #ifndef HAMMER_HAMMER__H
|
#endif // #ifndef HAMMER_HAMMER__H
|
||||||
|
|
|
||||||
87
src/registry.c
Normal file
87
src/registry.c
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
/* 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;
|
||||||
|
int value;
|
||||||
|
} Entry;
|
||||||
|
|
||||||
|
static void *tt_registry = NULL;
|
||||||
|
static Entry** tt_by_id = NULL;
|
||||||
|
static int tt_by_id_sz = 0;
|
||||||
|
#define TT_START TT_USER
|
||||||
|
static int tt_next = TT_START;
|
||||||
|
|
||||||
|
/*
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
int h_allocate_token_type(const char* name) {
|
||||||
|
Entry* new_entry = malloc(sizeof(*new_entry));
|
||||||
|
new_entry->name = name;
|
||||||
|
new_entry->value = -1;
|
||||||
|
Entry* probe = *(Entry**)tsearch(new_entry, &tt_registry, compare_entries);
|
||||||
|
if (probe->value != -1) {
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int h_get_token_type_number(const char* name) {
|
||||||
|
Entry e;
|
||||||
|
e.name = name;
|
||||||
|
Entry **ret = (Entry**)tfind(&e, &tt_registry, compare_entries);
|
||||||
|
if (ret == NULL)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return (*ret)->value;
|
||||||
|
}
|
||||||
|
const char* h_get_token_type_name(int token_type) {
|
||||||
|
if (token_type >= tt_next || token_type < TT_START)
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
return tt_by_id[token_type - TT_START]->name;
|
||||||
|
}
|
||||||
19
src/t_misc.c
19
src/t_misc.c
|
|
@ -1,4 +1,5 @@
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
#include <string.h>
|
||||||
#include "test_suite.h"
|
#include "test_suite.h"
|
||||||
#include "hammer.h"
|
#include "hammer.h"
|
||||||
|
|
||||||
|
|
@ -11,6 +12,24 @@ static void test_tt_user(void) {
|
||||||
g_check_cmp_int32(TT_USER, >, TT_ERR);
|
g_check_cmp_int32(TT_USER, >, TT_ERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_tt_registry(void) {
|
||||||
|
int id = h_allocate_token_type("com.upstandinghackers.test.token_type");
|
||||||
|
g_check_cmp_int32(id, >=, TT_USER);
|
||||||
|
int id2 = h_allocate_token_type("com.upstandinghackers.test.token_type_2");
|
||||||
|
g_check_cmp_int32(id2, !=, id);
|
||||||
|
g_check_cmp_int32(id2, >=, TT_USER);
|
||||||
|
g_check_cmp_int32(id, ==, h_get_token_type_number("com.upstandinghackers.test.token_type"));
|
||||||
|
g_check_cmp_int32(id2, ==, h_get_token_type_number("com.upstandinghackers.test.token_type_2"));
|
||||||
|
g_check_string("com.upstandinghackers.test.token_type", ==, h_get_token_type_name(id));
|
||||||
|
g_check_string("com.upstandinghackers.test.token_type_2", ==, h_get_token_type_name(id2));
|
||||||
|
if (h_get_token_type_name(0) != NULL) {
|
||||||
|
g_test_message("Unknown token type should not return a name");
|
||||||
|
g_test_fail();
|
||||||
|
}
|
||||||
|
g_check_cmp_int32(h_get_token_type_number("com.upstandinghackers.test.unkown_token_type"), ==, -1);
|
||||||
|
}
|
||||||
|
|
||||||
void register_misc_tests(void) {
|
void register_misc_tests(void) {
|
||||||
g_test_add_func("/core/misc/tt_user", test_tt_user);
|
g_test_add_func("/core/misc/tt_user", test_tt_user);
|
||||||
|
g_test_add_func("/core/misc/tt_registry", test_tt_registry);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue