From 197ce39fd3b1f6507847726f01e08b28df1feb44 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Wed, 6 May 2015 02:32:06 -0500 Subject: [PATCH] Do define substitution in argparsers; fix hashtables. --- src/assembler/hash_table.c | 32 +++++++++++++++++++++++--------- src/assembler/hash_table.h | 5 +++-- src/assembler/parse_util.c | 12 +++++++++--- src/assembler/state.c | 12 +++++++----- src/assembler/state.h | 4 ++-- 5 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/assembler/hash_table.c b/src/assembler/hash_table.c index 614f526..566cece 100644 --- a/src/assembler/hash_table.c +++ b/src/assembler/hash_table.c @@ -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 diff --git a/src/assembler/hash_table.h b/src/assembler/hash_table.h index 2b70560..bc12c3e 100644 --- a/src/assembler/hash_table.h +++ b/src/assembler/hash_table.h @@ -5,6 +5,7 @@ #include #include +#include #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); diff --git a/src/assembler/parse_util.c b/src/assembler/parse_util.c index 209a285..db20736 100644 --- a/src/assembler/parse_util.c +++ b/src/assembler/parse_util.c @@ -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; diff --git a/src/assembler/state.c b/src/assembler/state.c index 089a0e9..5852b90 100644 --- a/src/assembler/state.c +++ b/src/assembler/state.c @@ -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 diff --git a/src/assembler/state.h b/src/assembler/state.h index 1a3646b..2fa41c3 100644 --- a/src/assembler/state.h +++ b/src/assembler/state.h @@ -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*);