ns.c (6350B)
1 #include <stdlib.h> 2 3 #include "ns.h" 4 #include "var.h" 5 #include "helper.h" 6 7 /* Initializes namespace context 8 */ 9 ns_ctx* ns_ctx_init(void) 10 { 11 ns_ctx* new = (ns_ctx*)malloc(sizeof(ns_ctx)); 12 M_ASSERT(new); 13 14 new->ptr = 0; 15 return new; 16 } 17 18 void ns_ctx_del(ns_ctx* ctx) 19 { 20 N_ASSERT(ctx, "ns_ctx_del\n"); 21 free(ctx); 22 } 23 24 /* Push namespace to context 25 */ 26 void ns_ctx_push(ns_ctx* ctx, ns_t* ns) 27 { 28 N_ASSERT(ctx, "ns_ctx_push\n"); 29 N_ASSERT(ns, "ns_ctx_push\n"); 30 31 ASSERT((ctx->ptr + 1) < NS_CTX_DEPTH, "ns_ctx overflow"); 32 33 ctx->spaces[ctx->ptr] = ns; 34 ctx->ptr = ctx->ptr + 1; 35 } 36 37 /* Pop namespace to context 38 */ 39 ns_t* ns_ctx_pop(ns_ctx* ctx) 40 { 41 N_ASSERT(ctx, "ns_ctx_pop\n"); 42 43 ASSERT((ctx->ptr - 1) >= 0, "ns_ctx underflow"); 44 45 ns_t* rv; 46 47 ctx->ptr = ctx->ptr - 1; 48 49 rv = ctx->spaces[ctx->ptr]; 50 51 return rv; 52 } 53 54 /* Initialize namespace container of size 55 * ns_addr - name limit 56 * int - Namespace level 57 */ 58 ns_cont* ns_cont_init(ns_addr size, int level) 59 { 60 ns_cont* new = (ns_cont*)malloc(sizeof(ns_cont)); 61 M_ASSERT(new); 62 63 new->names = (var_cont**)malloc(sizeof(var_cont*)*size); 64 M_ASSERT(new->names); 65 66 new->size = size; 67 new->level = level; 68 69 for (int i = 0; i < size; i++) 70 { 71 new->names[i] = NULL; 72 } 73 74 new->next = NULL; 75 76 return new; 77 } 78 79 /* Initializes namespace of size 80 * ns_addr - name limit 81 */ 82 ns_t* ns_init(ns_addr size) 83 { 84 ns_t* ns = (ns_t*)malloc(sizeof(ns_t)); 85 M_ASSERT(ns); 86 87 static unsigned int inc = 0; 88 89 ns->id = inc; 90 91 inc++; 92 93 ns->root = ns_cont_init(size, (ns->id)<<16); 94 ns->last = ns->root; 95 96 return ns; 97 } 98 99 /* Cleans up memory, returns variable with label to_return 100 */ 101 var_cont* ns_cont_del(ns_cont* container, ns_addr to_return) 102 { 103 N_ASSERT(container, "ns_cont_del\n"); 104 N_ASSERT(container->names, "ns_cont_del\n"); 105 106 var_cont* rv = NULL; 107 108 if (container->names[to_return] != NULL) 109 { 110 rv = container->names[to_return]; 111 if (rv->ownership == container->level) 112 { 113 rv->ownership = -1; 114 } 115 } 116 117 for (int i = 0; i < container->size; i++) 118 { 119 if (i != to_return && container->names[i] != NULL) 120 { 121 if (container->names[i]->ownership == container->level && 122 (rv == NULL || container->names[i]->data != rv->data)) 123 { 124 var_del(container->names[i]); 125 } 126 } 127 } 128 129 free(container->names); 130 131 free(container); 132 133 return rv; 134 } 135 136 void ns_cont_free(ns_cont* container) 137 { 138 N_ASSERT(container, "ns_cont_del\n"); 139 140 if (container->next != NULL) 141 { 142 ns_cont_free(container->next); 143 } 144 145 free(container->names); 146 free(container); 147 } 148 149 /* Cleans up memory 150 */ 151 void ns_del(ns_t* ns) 152 { 153 N_ASSERT(ns, "ns_del\n"); 154 155 if (ns->root != NULL) 156 { 157 ns_cont_free(ns->root); 158 } 159 160 free(ns); 161 } 162 163 /* Pushes namespace of size 164 * ns_t* - namespace instance 165 * ns_addr - name limit 166 */ 167 void ns_push(ns_t* ns, ns_addr size) 168 { 169 N_ASSERT(ns, "ns_push\n"); 170 171 ns_cont* new = ns_cont_init(size, ns->last->level + 1); 172 173 new->next = ns->last; 174 ns->last = new; 175 } 176 177 /* Pops last namespace level 178 */ 179 var_cont* ns_pop(ns_t* ns) 180 { 181 N_ASSERT(ns, "ns_pop\n"); 182 183 // Define our return value 184 var_cont* rv = NULL; 185 // Is this the last link on the chain? 186 if (ns->last->next != NULL) { 187 // Get the next to last link on the chain 188 ns_cont* newlast = ns->last->next; 189 // Try to delete that namespace container 190 rv = ns_cont_del(ns->last, 0); 191 // Set the new last to the last link on the chain 192 ns->last = newlast; 193 } 194 195 return rv; 196 } 197 198 /* Declares a variable, at root or last namespace 199 * ns_t* - Namespace instance 200 * b_type - Type of variable 201 * int - Mux value [0] 202 * ns_addr - Variable name 203 * 204 * @param[0] = namespace level 205 * 0 -> current namespace 206 * 1 -> global namespace 207 */ 208 void ns_dec(ns_t* ns, b_type type, int scope, ns_addr address) 209 { 210 N_ASSERT(ns, "ns_dec\n"); 211 212 // Which namespace are we searching in? (scope == 0 -> local) 213 ns_cont* scoped_ns = scope ? ns->root : ns->last; 214 // Declare the name in the correct namespace 215 ns_cont_dec(scoped_ns, type, address); 216 } 217 218 /* Declares a variable, at namespace 219 * ns_t* - Namespace instance 220 * b_type - Type of variable 221 * ns_addr - Variable name 222 */ 223 void ns_cont_dec(ns_cont* container, b_type type, ns_addr address) 224 { 225 N_ASSERT(container, "ns_cont_dec\n"); 226 // Address must be in range 227 SIZE_ASSERT( container->size > address ); 228 // Initalize a variable container 229 var_cont* new_var = var_new(type); 230 container->names[ address ] = new_var; 231 // Set the ownership of this 232 container->names[ address ]->ownership = container->level; 233 } 234 235 /* Sets variable to value, at root or last namespace 236 * ns_t* - namespace instance 237 * int - mux value [0] 238 * ns_addr - Variable name 239 * var_cont* - Variable 240 * 241 * @param[0] = namespace level 242 * * 0 -> current namespace 243 * * 1 -> global namespace 244 */ 245 void ns_set(ns_t* ns, int scope, ns_addr address, var_cont* var) 246 { 247 N_ASSERT(ns, "ns_set\n"); 248 N_ASSERT(var, "ns_set\n"); 249 250 ns_cont* scoped_ns = scope ? ns->root : ns->last; 251 252 ns_cont_set(scoped_ns, var, address); 253 } 254 255 /* Sets variable to value, at root or last namespace 256 * ns_cont* - Namespace instance 257 * var_cont* - Variable 258 * ns_addr - Variable name 259 */ 260 void ns_cont_set(ns_cont* container, var_cont* var, ns_addr address) 261 { 262 N_ASSERT(container, "ns_cont_set\n"); 263 N_ASSERT(var, "ns_cont_set\n"); 264 // Addresss must be in range 265 SIZE_ASSERT( container->size > address ); 266 N_ASSERT(container->names[ address ], 267 "Attempt to set an undeclared variable\n"); 268 269 if (var->ownership < 0) 270 { 271 // This is my variable now 272 var->ownership = container->level; 273 } 274 275 container->names[ address ]->ownership = var->ownership; 276 277 var_set(container->names[ address ], var->data, var->type); 278 } 279 280 /* Gets variable from address 281 282 * ns_t* - namespace instance 283 * int - mux value [0] 284 * ns_addr - Variable name 285 * 286 * @param[0] = namespace level 287 * 0 -> current namespace 288 * 1 -> global namespace 289 */ 290 var_cont* ns_get(ns_t* ns, int scope, ns_addr address) 291 { 292 N_ASSERT(ns, "ns_get\n"); 293 N_ASSERT(ns->root, "ns_get\n"); 294 N_ASSERT(ns->last, "ns_get\n"); 295 296 ns_cont* scoped_ns = scope ? ns->root : ns->last; 297 298 return ns_cont_get(scoped_ns, address); 299 } 300 301 /* Gets variable from address 302 * ns_t* - namespace instance 303 * ns_addr - Variable name 304 */ 305 var_cont* ns_cont_get(ns_cont* container, ns_addr address) 306 { 307 N_ASSERT(container, "ns_cont_get\n"); 308 SIZE_ASSERT( container->size > address ); 309 310 return container->names[ address ]; 311 }