My Project
|
Defines the interface to symbol.c functions (do not modify) More...
Go to the source code of this file.
Data Structures | |
struct | symbol |
Macros | |
#define | SYM_TAB_SIZE 997 |
Typedefs | |
typedef struct sym_table | sym_table_t |
typedef struct symbol | symbol_t |
typedef void(* | iterate_fnc_t) (symbol_t *sym, void *data) |
Functions | |
int | symbol_add (sym_table_t *symTab, const char *name, int addr) |
char * | symbol_find_by_addr (sym_table_t *symTab, int addr) |
symbol_t * | symbol_find_by_name (sym_table_t *symTab, const char *name) |
sym_table_t * | symbol_init (int table_size) |
void | symbol_reset (sym_table_t *symTab) |
struct node * | symbol_search (sym_table_t *symTab, const char *name, int *hash, int *index) |
void | symbol_term (sym_table_t *symTab) |
void | symbol_iterate (sym_table_t *symTab, iterate_fnc_t fnc, void *data) |
void | symbol_remove_by_addr (sym_table_t *symTab, int addr1, int addr2) |
This file defines the interface to a C file symbol.c that you will complete. The underlying data structure(s) used will be defined by the actual assignment. The assignment will define whether symbols are case sensitive or case in-sensitive.
In this implementation, you will learn about dynamic memory management using malloc/free. You will also learn about function pointers (callback functions).
#define SYM_TAB_SIZE 997 |
Suggested size, 997 is a prime (primes reduce hashing collisions)
typedef void(* iterate_fnc_t) (symbol_t *sym, void *data) |
Defines the signature of a callback function (also known as a function pointer). This is how languages such as Java and C++ do dynamic binding (i.e. figure out which function to call). Recall that in Java the code obj.equals(object)
will call one of possibly many different methods depending on the actual type of obj
. This is because the method .equals() may be overridden.
In the LC3, dynamic binding is based on the JSRR opcode. With this opcode, the address of the routine to call is stored in a register and can be changed at runtime. Compare this to a JSR nameOfRoutine opcode which specifies what routine to call from the label that follows it. Thus, the address is fixed at assembly time.
This is used in the symbol_iterate() function. An interesting variation would be to have the callback function return an integer which determines whether the iteration should contibue or terminate.
symTab | - pointer to the symbol table |
data | - any additional information to be passed on to fnc. The called function will cast this to whatever type was actually passed. |
typedef struct sym_table sym_table_t |
This defines an opaque type. The actual contents of the structure are hidden in the implementation and only a pointer to this structure is used externally to this file. A pointer to an opaque structure is sometimes referred to as a handle.
The symbol_find methods return a pointer to this data structure. It is up to the implementor to decide how to use this stucture in the implementation.
int symbol_add | ( | sym_table_t * | symTab, |
const char * | name, | ||
int | addr | ||
) |
Add a symbol to the symbol table.
symTab | - pointer to the symbol table |
name | - the name of the symbol |
addr | - the address of the symbol |
char* symbol_find_by_addr | ( | sym_table_t * | symTab, |
int | addr | ||
) |
Find a name by its LC3 address
symTab | - pointer to the symbol table |
addr | - an LC3 address |
symbol_t* symbol_find_by_name | ( | sym_table_t * | symTab, |
const char * | name | ||
) |
Find a symbol by its name
symTab | - pointer to the symbol table |
name | - the symbols name |
symbol_search()
. That routine returns a node_t*
, but this routine returns a symbol_t*
. Study this posting to understand how you might solve this.sym_table_t* symbol_init | ( | int | table_size | ) |
Create a new symbol table and return a pointer to it. This function is a constructor for a symbol table. It allocates and initializes both the hash_table
and the addr_table
. The latter is an array of char*
that is indexed by an LC3 address to find the label (if any) associated with that address.
table_size | - the size of the hash table. |
void symbol_iterate | ( | sym_table_t * | symTab, |
iterate_fnc_t | fnc, | ||
void * | data | ||
) |
This function calls the function for every entry in the symbol table. The assigment will define the order in which the entries should be visited.
symTab | - pointer to the symbol table |
fnc | - the function to be called on every element |
data | - any additional information to be passed on to fnc. The called function will cast this to whatever type was actually passed. |
void symbol_remove_by_addr | ( | sym_table_t * | symTab, |
int | addr1, | ||
int | addr2 | ||
) |
Remove all entries from symbol table that have addresses in the given range.
symTab | - pointer to the symbol table |
addr1 | - lowest address of range |
addr2 | - highest address of range |
void symbol_reset | ( | sym_table_t * | symTab | ) |
Remove all the symbols from the symbol table. After this call the opaque symbol table pointer is still valid and new symbols may be added to it. If needed, clear the addr_table
.
symTab | - pointer to the symbol table |
struct node* symbol_search | ( | sym_table_t * | symTab, |
const char * | name, | ||
int * | hash, | ||
int * | index | ||
) |
This function is only used internally and should be declared static. It is a useful support function for the add()/find()
functions. It is declared here for documentation purposes.
symTab | - pointer to the symbol table |
name | - the name of the symbol |
hash | - pointer to location where hash value will be stored |
index | - pointer to location where index will be stored |
void symbol_term | ( | sym_table_t * | symTab | ) |
Remove all symbols from the symbol table, and free all allocated memory. This function is a destructor for a symbol table. There must not be any memory leaks. After executing this function, the opaque pointer to the symbol table is no longer valid.