-
Notifications
You must be signed in to change notification settings - Fork 1
/
symbol.c
164 lines (139 loc) · 4.5 KB
/
symbol.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "symbol.h"
/** @file symbol.c
* @brief You will modify this file and implement nine functions
* @details Your implementation of the functions defined in symbol.h.
* You may add other functions if you find it helpful. Added functions
* should be declared <b>static</b> to indicate they are only used
* within this file. The reference implementation added approximately
* 90 lines of code to this file. This count includes lines containing
* only a single closing bracket (}).
* <p>
* @author <b>Your name</b> goes here
*/
/** size of LC3 memory */
#define LC3_MEMORY_SIZE 65536
/** Provide prototype for strdup() */
char *strdup(const char *s);
/** defines data structure used to store nodes in hash table */
typedef struct node {
symbol_t symbol; /**< the data the user is interested in */
int hash; /**< hash value - makes searching faster */
struct node* next; /**< linked list of symbols at same index */
} node_t;
/** defines the data structure for the hash table */
struct sym_table {
node_t* hash_table[SYMBOL_SIZE]; /**< head of linked list for this index */
char** addr_table; /**< look up symbols by addr */
};
/** djb hash - found at http://www.cse.yorku.ca/~oz/hash.html
* tolower() call to make case insensitive.
*/
static int symbol_hash (const char* name) {
unsigned char* str = (unsigned char*) name;
unsigned long hash = 5381;
int c;
while ((c = *str++))
hash = ((hash << 5) + hash) + tolower(c); /* hash * 33 + c */
c = hash & 0x7FFFFFFF; /* keep 31 bits - avoid negative values */
return c;
}
/** @todo implement this function */
sym_table_t* symbol_init (int lookup_by_addr) {
sym_table_t* tab = calloc (1,sizeof(sym_table_t));
if(lookup_by_addr > 0){
tab -> addr_table = (char**) calloc(LC3_MEMORY_SIZE,sizeof(char*));
}
return tab;
}
/** @todo implement this function */
void symbol_term (sym_table_t* symTab) {
symbol_reset(symTab);
free(symTab);
}
/** @todo implement this function */
void symbol_reset(sym_table_t* symTab) {
for(int i = 0; i < SYMBOL_SIZE;i++){
for(node_t* nodepointer = symTab -> hash_table[i]; nodepointer != NULL; nodepointer = nodepointer -> next){
if(nodepointer != NULL){
free(nodepointer -> symbol.name);
free(nodepointer);
}
}
symTab -> hash_table[i] = NULL;
}
if(symTab -> addr_table !=NULL){
for(int i = 0; i < SYMBOL_SIZE;i++){
symTab -> addr_table[i] = NULL;
}
}
}
/** @todo implement this function */
int symbol_add (sym_table_t* symTab, const char* name, int addr) {
int hash;
int index;
node_t* node = symbol_search(symTab, name, &hash, &index);
struct node* node1 = calloc (1,sizeof(node));
if(node == NULL){
//struct node* pointer = (struct node*) calloc (1,sizeof(struct node));
node_t* hello = malloc(sizeof(node_t));
hello->symbol.name = strdup(name);
hello->symbol.addr = addr;
hello->hash = hash;
hello->next = symTab -> hash_table[index];
symTab->hash_table[index] = hello;
return 1;
}
if(symTab -> addr_table !=NULL){
symTab -> addr_table[addr] = node1 -> symbol.name;
}
return 0;
}
/** @todo implement this function */
struct node* symbol_search (sym_table_t* symTab, const char* name, int* hash, int* index) {
*hash = symbol_hash(name);
*index = (*hash % SYMBOL_SIZE);
// node_t* nodepointer = symTab -> hash_table[*index];
if(symTab -> hash_table[*index] == NULL){
return NULL;
}
else{
for(node_t* nodepointer = symTab -> hash_table[*index]; nodepointer != NULL; nodepointer = nodepointer -> next){
int compare = strcmp(name,nodepointer -> symbol.name);
if(compare == 0){
return nodepointer;
}
}
}
return NULL;
}
/** @todo implement this function */
symbol_t* symbol_find_by_name (sym_table_t* symTab, const char* name) {
int hash;
int index;
node_t* node = symbol_search(symTab, name, &hash, &index);
if(node != NULL){
return &node -> symbol;
}
return NULL;
}
/** @todo implement this function */
char* symbol_find_by_addr (sym_table_t* symTab, int addr) {
return symTab -> addr_table[addr];
}
/** @todo implement this function */
void symbol_iterate (sym_table_t* symTab, iterate_fnc_t fnc, void* data) {
int track = 0;
for(int i = 0; i < SYMBOL_SIZE;i++){
for(node_t* nodepointer = symTab -> hash_table[i]; nodepointer != NULL; nodepointer = nodepointer -> next){
if(nodepointer != NULL){
track++;
(*fnc)(&nodepointer -> symbol, data);
}
}
}
}