| @@ -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*); | |||