@@ -26,15 +26,24 @@ struct HashNode { | |||||
This uses the djb2 algorithm: http://www.cse.yorku.ca/~oz/hash.html | 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; | size_t hash = 5381; | ||||
while (*key) | |||||
while ((size < 0 || size-- > 0) && *key) | |||||
hash = ((hash << 5) + hash) + *(key++); | hash = ((hash << 5) + hash) + *(key++); | ||||
return hash % table->buckets; | 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. | Create and return a new HashTable. | ||||
These HashTables are designed to be generic, a sort of poor-man's C++ | 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. | Search for a key in the hash table. | ||||
Return the corresponding node on success and NULL on failure. | 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) { | while (node) { | ||||
if (!strcmp(key, NODE_KEY(table, node))) | |||||
if (keyeq(key, NODE_KEY(table, node), size)) | |||||
return node; | return node; | ||||
node = NEXT_NODE(table, 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) | 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]; | NEXT_NODE(table, node) = table->nodes[index]; | ||||
table->nodes[index] = node; | 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. | (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. | 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; | HashNode *node = table->nodes[index], *prev = NULL, *next; | ||||
while (node) { | while (node) { | ||||
next = NEXT_NODE(table, node); | next = NEXT_NODE(table, node); | ||||
if (!strcmp(key, NODE_KEY(table, node))) { | |||||
if (keyeq(key, NODE_KEY(table, node), size)) { | |||||
if (prev) | if (prev) | ||||
NEXT_NODE(table, prev) = next; | NEXT_NODE(table, prev) = next; | ||||
else | else | ||||
@@ -5,6 +5,7 @@ | |||||
#include <stdbool.h> | #include <stdbool.h> | ||||
#include <stddef.h> | #include <stddef.h> | ||||
#include <unistd.h> | |||||
#define hash_table_NEW(node, key, next, callback) \ | #define hash_table_NEW(node, key, next, callback) \ | ||||
hash_table_new(offsetof(node, key), offsetof(node, next), \ | hash_table_new(offsetof(node, key), offsetof(node, next), \ | ||||
@@ -28,6 +29,6 @@ typedef struct { | |||||
HashTable* hash_table_new(size_t, size_t, HashFreeCallback); | HashTable* hash_table_new(size_t, size_t, HashFreeCallback); | ||||
void hash_table_free(HashTable*); | 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*); | 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) | if (ai.size <= 0) | ||||
return false; | 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; | bool negative = false; | ||||
ssize_t i = 0; | ssize_t i = 0; | ||||
@@ -421,8 +425,7 @@ bool argparse_label(ASMArgLabel *result, ASMArgParseInfo ai) | |||||
if (ai.size <= 0 || ai.size >= MAX_SYMBOL_SIZE) | if (ai.size <= 0 || ai.size >= MAX_SYMBOL_SIZE) | ||||
return false; | return false; | ||||
// TODO: check for deftable | |||||
// Validate the label characters: | |||||
for (const char *i = ai.arg; i < ai.arg + ai.size; i++) { | for (const char *i = ai.arg; i < ai.arg + ai.size; i++) { | ||||
char c = *i; | char c = *i; | ||||
if (!((c >= 'a' && c <= 'z') || c == '_' || c == '.' || | if (!((c >= 'a' && c <= 'z') || c == '_' || c == '.' || | ||||
@@ -430,6 +433,9 @@ bool argparse_label(ASMArgLabel *result, ASMArgParseInfo ai) | |||||
return false; | return false; | ||||
} | } | ||||
if (asm_deftable_find(ai.deftable, ai.arg, ai.size)) | |||||
return false; | |||||
strncpy(result->text, ai.arg, ai.size); | strncpy(result->text, ai.arg, ai.size); | ||||
result->text[ai.size] = '\0'; | result->text[ai.size] = '\0'; | ||||
return true; | return true; | ||||
@@ -151,7 +151,7 @@ void asm_deftable_free(ASMDefineTable *deftable) | |||||
*/ | */ | ||||
const ASMSymbol* asm_symtable_find(const ASMSymbolTable *tab, const char *key) | 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. | 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. | 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 | #ifdef DEBUG_MODE | ||||
@@ -108,9 +108,9 @@ void asm_deftable_free(ASMDefineTable*); | |||||
const ASMSymbol* asm_symtable_find(const ASMSymbolTable*, const char*); | const ASMSymbol* asm_symtable_find(const ASMSymbolTable*, const char*); | ||||
void asm_symtable_insert(ASMSymbolTable*, ASMSymbol*); | 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*); | 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 | #ifdef DEBUG_MODE | ||||
void asm_lines_print(const ASMLine*); | void asm_lines_print(const ASMLine*); | ||||