@@ -26,15 +26,24 @@ struct HashNode { | |||
This uses the djb2 algorithm: http://www.cse.yorku.ca/~oz/hash.html | |||
*/ | |||
static inline size_t hash_key(const HashTable *table, const char *key) | |||
static inline size_t hash_key( | |||
const HashTable *table, const char *key, ssize_t size) | |||
{ | |||
size_t hash = 5381; | |||
while (*key) | |||
while ((size < 0 || size-- > 0) && *key) | |||
hash = ((hash << 5) + hash) + *(key++); | |||
return hash % table->buckets; | |||
} | |||
/* | |||
Return true if the two key strings are equal, or false if they aren't. | |||
*/ | |||
static inline bool keyeq(const char *s1, const char *s2, ssize_t size) | |||
{ | |||
return !(size >= 0 ? strncmp(s1, s2, size) : strcmp(s1, s2)); | |||
} | |||
/* | |||
Create and return a new HashTable. | |||
These HashTables are designed to be generic, a sort of poor-man's C++ | |||
@@ -89,12 +98,15 @@ void hash_table_free(HashTable *table) | |||
Search for a key in the hash table. | |||
Return the corresponding node on success and NULL on failure. | |||
If the key is null-terminated, pass size as -1. | |||
*/ | |||
const HashNode* hash_table_find(const HashTable *table, const char *key) | |||
const HashNode* hash_table_find( | |||
const HashTable *table, const char *key, ssize_t size) | |||
{ | |||
HashNode *node = table->nodes[hash_key(table, key)]; | |||
HashNode *node = table->nodes[hash_key(table, key, size)]; | |||
while (node) { | |||
if (!strcmp(key, NODE_KEY(table, node))) | |||
if (keyeq(key, NODE_KEY(table, node), size)) | |||
return node; | |||
node = NEXT_NODE(table, node); | |||
} | |||
@@ -111,7 +123,7 @@ const HashNode* hash_table_find(const HashTable *table, const char *key) | |||
*/ | |||
void hash_table_insert(HashTable *table, HashNode *node) | |||
{ | |||
size_t index = hash_key(table, NODE_KEY(table, node)); | |||
size_t index = hash_key(table, NODE_KEY(table, node), -1); | |||
NEXT_NODE(table, node) = table->nodes[index]; | |||
table->nodes[index] = node; | |||
} | |||
@@ -120,15 +132,17 @@ void hash_table_insert(HashTable *table, HashNode *node) | |||
(Try to) remove a node with the given key from the table. | |||
Return true if the node was removed, or false if it was not found. | |||
If the key is null-terminated, pass size as -1. | |||
*/ | |||
bool hash_table_remove(HashTable *table, const char *key) | |||
bool hash_table_remove(HashTable *table, const char *key, ssize_t size) | |||
{ | |||
size_t index = hash_key(table, key); | |||
size_t index = hash_key(table, key, size); | |||
HashNode *node = table->nodes[index], *prev = NULL, *next; | |||
while (node) { | |||
next = NEXT_NODE(table, node); | |||
if (!strcmp(key, NODE_KEY(table, node))) { | |||
if (keyeq(key, NODE_KEY(table, node), size)) { | |||
if (prev) | |||
NEXT_NODE(table, prev) = next; | |||
else | |||
@@ -5,6 +5,7 @@ | |||
#include <stdbool.h> | |||
#include <stddef.h> | |||
#include <unistd.h> | |||
#define hash_table_NEW(node, key, next, callback) \ | |||
hash_table_new(offsetof(node, key), offsetof(node, next), \ | |||
@@ -28,6 +29,6 @@ typedef struct { | |||
HashTable* hash_table_new(size_t, size_t, HashFreeCallback); | |||
void hash_table_free(HashTable*); | |||
const HashNode* hash_table_find(const HashTable*, const char*); | |||
const HashNode* hash_table_find(const HashTable*, const char*, ssize_t); | |||
void hash_table_insert(HashTable*, HashNode*); | |||
bool hash_table_remove(HashTable*, const char*); | |||
bool hash_table_remove(HashTable*, const char*, ssize_t); |
@@ -303,7 +303,11 @@ bool argparse_immediate(ASMArgImmediate *result, ASMArgParseInfo ai) | |||
if (ai.size <= 0) | |||
return false; | |||
// TODO: lookup here for definition table | |||
const ASMDefine *define = asm_deftable_find(ai.deftable, ai.arg, ai.size); | |||
if (define) { | |||
*result = define->value; | |||
return true; | |||
} | |||
bool negative = false; | |||
ssize_t i = 0; | |||
@@ -421,8 +425,7 @@ bool argparse_label(ASMArgLabel *result, ASMArgParseInfo ai) | |||
if (ai.size <= 0 || ai.size >= MAX_SYMBOL_SIZE) | |||
return false; | |||
// TODO: check for deftable | |||
// Validate the label characters: | |||
for (const char *i = ai.arg; i < ai.arg + ai.size; i++) { | |||
char c = *i; | |||
if (!((c >= 'a' && c <= 'z') || c == '_' || c == '.' || | |||
@@ -430,6 +433,9 @@ bool argparse_label(ASMArgLabel *result, ASMArgParseInfo ai) | |||
return false; | |||
} | |||
if (asm_deftable_find(ai.deftable, ai.arg, ai.size)) | |||
return false; | |||
strncpy(result->text, ai.arg, ai.size); | |||
result->text[ai.size] = '\0'; | |||
return true; | |||
@@ -151,7 +151,7 @@ void asm_deftable_free(ASMDefineTable *deftable) | |||
*/ | |||
const ASMSymbol* asm_symtable_find(const ASMSymbolTable *tab, const char *key) | |||
{ | |||
return (ASMSymbol*) hash_table_find(tab, key); | |||
return (ASMSymbol*) hash_table_find(tab, key, -1); | |||
} | |||
/* | |||
@@ -169,9 +169,10 @@ void asm_symtable_insert(ASMSymbolTable *tab, ASMSymbol *symbol) | |||
Return the corresponding ASMDefine on success and NULL on failure. | |||
*/ | |||
const ASMDefine* asm_deftable_find(const ASMDefineTable *tab, const char *key) | |||
const ASMDefine* asm_deftable_find( | |||
const ASMDefineTable *tab, const char *key, size_t size) | |||
{ | |||
return (ASMDefine*) hash_table_find(tab, key); | |||
return (ASMDefine*) hash_table_find(tab, key, size); | |||
} | |||
/* | |||
@@ -189,9 +190,10 @@ void asm_deftable_insert(ASMDefineTable *tab, ASMDefine *define) | |||
Return true if the node was removed, or false if it was not found. | |||
*/ | |||
bool asm_deftable_remove(ASMDefineTable *tab, const char *key) | |||
bool asm_deftable_remove( | |||
ASMDefineTable *tab, const char *key, size_t size) | |||
{ | |||
return hash_table_remove(tab, key); | |||
return hash_table_remove(tab, key, size); | |||
} | |||
#ifdef DEBUG_MODE | |||
@@ -108,9 +108,9 @@ void asm_deftable_free(ASMDefineTable*); | |||
const ASMSymbol* asm_symtable_find(const ASMSymbolTable*, const char*); | |||
void asm_symtable_insert(ASMSymbolTable*, ASMSymbol*); | |||
const ASMDefine* asm_deftable_find(const ASMDefineTable*, const char*); | |||
const ASMDefine* asm_deftable_find(const ASMDefineTable*, const char*, size_t); | |||
void asm_deftable_insert(ASMDefineTable*, ASMDefine*); | |||
bool asm_deftable_remove(ASMDefineTable*, const char*); | |||
bool asm_deftable_remove(ASMDefineTable*, const char*, size_t); | |||
#ifdef DEBUG_MODE | |||
void asm_lines_print(const ASMLine*); | |||