Mercurial > repos > rhope
annotate dict.c @ 75:0083b2f7b3c7
Partially working implementation of List. Modified build scripts to allow use of other compilers. Fixed some bugs involving method implementations on different types returning different numbers of outputs. Added Fold to the 'builtins' in the comipler.
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 06 Jul 2010 07:52:59 -0400 |
parents | 94c885692eb5 |
children |
rev | line source |
---|---|
0 | 1 #include "datum.h" |
2 #include "structs.h" | |
3 #include "debugmacros.h" | |
4 #include <string.h> | |
5 #include <stdlib.h> | |
6 //Index, Swap, Remove, Set, Length, New | |
7 | |
8 ternary_node * find_node(datum * dict, datum * key, BOOL novalue) | |
9 { | |
10 int i = 0; | |
11 ternary_node * nodes; | |
12 ternary_node * current = ((dict_data *)dict->c.generic.data)->nodes; | |
13 nodes = current; | |
14 if(((dict_data *)dict->c.generic.data)->num_nodes <= 0 || key->c.generic.len <= 1) | |
15 return NULL; | |
16 while(current >= nodes) | |
17 { | |
18 DEBUGPRINTF("current->letter: %c, key[%d]: %c\n", current->letter, i, ((char*)key->c.generic.data)[i]); | |
19 if(((char*)key->c.generic.data)[i] == current->letter) | |
20 if(i == (key->c.generic.len-2)) | |
21 if(current->payload || novalue) | |
22 return current; | |
23 else | |
24 return NULL; | |
25 else | |
26 { | |
27 current = nodes + current->next; | |
28 ++i; | |
29 } | |
30 else if(((char *)key->c.generic.data)[i] > current->letter) | |
31 current = nodes + current->right; | |
32 else | |
33 current = nodes + current->left; | |
34 } | |
35 return NULL; | |
36 } | |
37 | |
38 int vis_dict_index(datum ** inputlist, queue_entry * worker_entry) | |
39 { | |
40 datum * output; | |
41 int i = 0; | |
42 ternary_node * found = find_node(inputlist[0], inputlist[1], FALSE); | |
43 release_ref(inputlist[1]); | |
44 if(found) | |
45 { | |
46 DEBUGPRINTF("Found payload: %X\n", found->payload); | |
47 /*if(found->payload->type == BUILTIN_TYPE_STRING) | |
48 { | |
49 DEBUGPRINTF("Payload: %s\n", found->payload->c.generic.data); | |
50 }*/ | |
51 | |
52 output = add_ref(found->payload); | |
53 inputlist[1] = NULL; | |
54 } | |
55 else | |
56 { | |
57 inputlist[1] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program); | |
58 inputlist[1]->c.integers.num_a = 0; | |
59 output = NULL; | |
60 } | |
61 release_ref(inputlist[0]); | |
62 inputlist[0] = output; | |
63 return 0; | |
64 } | |
65 | |
66 int vis_dict_swap(datum ** inputlist, queue_entry * worker_entry) | |
67 { | |
68 ternary_node *first, *second; | |
69 datum * temp; | |
70 inputlist[0] = copy_datum(inputlist[0],0); | |
71 first = find_node(inputlist[0], inputlist[1], FALSE); | |
72 if(first) | |
73 { | |
74 second = find_node(inputlist[0], inputlist[2], FALSE); | |
75 if(second) | |
76 { | |
77 temp = first->payload; | |
78 first->payload = second->payload; | |
79 second->payload = temp; | |
80 } | |
81 } | |
82 release_ref(inputlist[1]); | |
83 release_ref(inputlist[2]); | |
84 return 0; | |
85 } | |
86 | |
87 int vis_dict_remove(datum ** inputlist, queue_entry * worker_entry) | |
88 { | |
89 //NOTE: Currently optimized for speed not for memory usage | |
90 //Doesn't remove ternary_nodes that are no longer needed | |
91 ternary_node * found; | |
92 dict_data * dict; | |
93 inputlist[0] = copy_datum(inputlist[0],0); | |
94 found = find_node(inputlist[0], inputlist[1], FALSE); | |
95 release_ref(inputlist[1]); | |
96 dict = (dict_data *)inputlist[0]->c.generic.data; | |
97 if(found) | |
98 { | |
99 release_ref(found->payload); | |
100 found->payload = NULL; | |
101 --(dict->num_entries); | |
102 } | |
103 return 0; | |
104 } | |
105 | |
106 int vis_dict_set(datum ** inputlist, queue_entry * worker_entry) | |
107 { | |
108 ternary_node * found, *current, *last; | |
109 dict_data * dict, *new_dict; | |
110 int new_node_storage,i,dir; | |
111 int newlen; | |
112 //DEBUGPRINTF("Payload: %s\n", inputlist[2]->c.generic.data); | |
113 inputlist[0] = copy_datum(inputlist[0],0); | |
114 found = find_node(inputlist[0], inputlist[1], TRUE); | |
115 dict = (dict_data *)inputlist[0]->c.generic.data; | |
116 DEBUGPRINTF("key: %s\n", inputlist[1]->c.generic.data); | |
117 DEBUGPRINTF("Num nodes: %d, num entries: %d\n", dict->num_nodes, dict->num_entries); | |
118 if(found) | |
119 { | |
120 if(found->payload) | |
121 release_ref(found->payload); | |
122 else | |
123 ++(dict->num_entries); | |
124 found->payload = inputlist[2]; | |
125 } | |
126 else if(inputlist[1]->c.generic.len > 1) //FIXME: silently fail on zero-length keys for now | |
127 { | |
128 if(dict->num_nodes) | |
129 { | |
130 current = dict->nodes; | |
131 i = 0; | |
132 while(current >= dict->nodes) | |
133 { | |
134 DEBUGPRINTF("Current node: %X\n", current); | |
135 last = current; | |
136 DEBUGPRINTF("Current letter: %c, key letter: %c\n", current->letter,((char *)inputlist[1]->c.generic.data)[i]); | |
137 if(((char *)inputlist[1]->c.generic.data)[i] == current->letter) | |
138 { | |
139 DEBUGPUTS("Went straight\n"); | |
140 ++i; | |
141 current = dict->nodes + current->next; | |
142 dir = 0; | |
143 } | |
144 else if(((char *)inputlist[1]->c.generic.data)[i] > current->letter) | |
145 { | |
146 DEBUGPUTS("Went right\n"); | |
147 current = dict->nodes + current->right; | |
148 dir = 1; | |
149 } | |
150 else | |
151 { | |
152 DEBUGPUTS("Went left\n"); | |
153 current = dict->nodes + current->left; | |
154 dir = 2; | |
155 } | |
156 } | |
157 DEBUGPRINTF("Matched %d out of %d characters\n", i, (inputlist[1]->c.generic.len-1)); | |
158 DEBUGPRINTF("node_storage: %d, num_nodes: %d\n", dict->node_storage, dict->num_nodes); | |
159 if((dict->node_storage-dict->num_nodes) < ((inputlist[1]->c.generic.len-1) - i)) | |
160 { | |
161 DEBUGPUTS("Allocating more storage\n"); | |
162 new_node_storage = inputlist[1]->c.generic.len - 1 - i + dict->num_nodes; | |
163 new_node_storage += new_node_storage >> 1; //1.5 times required storage | |
164 newlen = sizeof(dict_data) + sizeof(ternary_node) * (new_node_storage-1); | |
165 new_dict = malloc(newlen); | |
166 DEBUGPRINTF("After malloc: new_dict = %X, size: %d, new_node_storage: %d\n", new_dict, newlen, new_node_storage); | |
167 memcpy(new_dict, dict, sizeof(dict_data) + sizeof(ternary_node) * (dict->num_nodes-1)); | |
168 DEBUGPUTS("After memcpyy\n"); | |
169 new_dict->node_storage = new_node_storage; | |
170 //new_dict->num_entries = dict->num_entries + 1; | |
171 new_dict->num_nodes = dict->num_nodes; | |
172 DEBUGPRINTF("last was: %X, dict->nodes was: %X, ", last, dict->nodes); | |
173 last = new_dict->nodes + (last - dict->nodes); | |
174 DEBUGPRINTF("last is now: %X, dict->nodes is now : %X, ", last, new_dict->nodes); | |
175 VIS_FREE(dict, "dictionary object"); | |
176 DEBUGPUTS("After free\n"); | |
177 dict = new_dict; | |
178 inputlist[0]->c.generic.data = dict; | |
179 inputlist[0]->c.generic.len = newlen; | |
180 } | |
181 ++(dict->num_entries); | |
182 DEBUGPRINTF("Setting current to: %X\n", dict->nodes + dict->num_nodes); | |
183 current =dict->nodes + dict->num_nodes; | |
184 DEBUGPUTS("Setting left, right and next pointer to null\n"); | |
185 current->left = current->right = current->next = -1; | |
186 current->payload = NULL; | |
187 current->letter = ((char *)inputlist[1]->c.generic.data)[i]; | |
188 DEBUGPRINTF("Setting pointer in last node (%X) to current node\n", last); | |
189 if(dir == 1) | |
190 last->right = dict->num_nodes; | |
191 else if(dir == 2) | |
192 last->left = dict->num_nodes; | |
193 else | |
194 last->next = dict->num_nodes; | |
195 ++i; | |
196 ++(dict->num_nodes); | |
197 last = current; | |
198 DEBUGPUTS("Entering node add loop\n"); | |
199 for(;i < (inputlist[1]->c.generic.len-1); ++i) | |
200 { | |
201 DEBUGPRINTF("Adding node at index %d\n", dict->num_nodes); | |
202 current = dict->nodes + dict->num_nodes; | |
203 last->next = dict->num_nodes; | |
204 current->left = current->right = current->next = -1; | |
205 current->payload = NULL; | |
206 current->letter = ((char *)inputlist[1]->c.generic.data)[i]; | |
207 ++(dict->num_nodes); | |
208 last = current; | |
209 } | |
210 DEBUGPUTS("Loop complete\n"); | |
211 last->payload = inputlist[2]; | |
212 } | |
213 else | |
214 { | |
215 if(dict->node_storage < (inputlist[1]->c.generic.len-1)) | |
216 { | |
217 VIS_FREE(dict, "dictionary object"); | |
218 newlen = sizeof(dict_data) + sizeof(ternary_node) * ((inputlist[1]->c.generic.len-1)<<2); | |
219 dict = malloc(newlen); | |
220 dict->node_storage = ((inputlist[1]->c.generic.len-1)<<2) + 1; | |
221 inputlist[0]->c.generic.data = dict; | |
222 inputlist[0]->c.generic.len = newlen; | |
223 | |
224 } | |
225 dict->num_entries = 1; | |
226 dict->num_nodes = (inputlist[1]->c.generic.len-1); | |
227 for(i = 0; i < dict->num_nodes; ++i) | |
228 { | |
229 dict->nodes[i].left = dict->nodes[i].right = -1; | |
230 dict->nodes[i].letter = ((char *)inputlist[1]->c.generic.data)[i]; | |
231 if(i == (dict->num_nodes - 1)) | |
232 { | |
233 dict->nodes[i].next = -1; | |
234 dict->nodes[i].payload = inputlist[2]; | |
235 } | |
236 else | |
237 { | |
238 dict->nodes[i].next = i + 1; | |
239 dict->nodes[i].payload = NULL; | |
240 } | |
241 } | |
242 } | |
243 } | |
244 release_ref(inputlist[1]); | |
245 DEBUGPRINTF("Num nodes after set: %d\n", dict->num_nodes); | |
246 //DEBUGPRINTF("Payload: %s\n", inputlist[2]->c.generic.data); | |
247 return 0; | |
248 } | |
249 | |
250 int vis_dict_length(datum ** inputlist, queue_entry * worker_entry) | |
251 { | |
252 datum * output; | |
253 dict_data * dict = ((dict_data *)inputlist[0]->c.generic.data); | |
254 output = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); | |
255 output->c.integers.num_a = dict->num_entries; | |
256 release_ref(inputlist[0]); | |
257 inputlist[0] = output; | |
258 return 0; | |
259 } | |
260 | |
261 datum * create_dict(program * prog) | |
262 { | |
263 dict_data * dict; | |
264 datum * dat = new_datum(BUILTIN_TYPE_DICT, 1, sizeof(dict_data) + sizeof(ternary_node)*23, prog); | |
265 dict = (dict_data *)dat->c.generic.data; | |
266 dict->num_entries = 0; | |
267 dict->num_nodes = 0; | |
268 dict->node_storage = 24; | |
269 return dat; | |
270 } | |
271 | |
272 int vis_dict_new(datum ** inputlist, queue_entry * worker_entry) | |
273 { | |
274 inputlist[0] = create_dict(worker_entry->instance->def->program); | |
275 return 0; | |
276 } | |
277 | |
278 #define APPEND_KEY_STORE(key, key_store, key_size, val) if(key_size == key_store) { key_store = key_store + (key_store>>1); key = realloc(key, key_store); } key[key_size++] = val | |
279 | |
280 int vis_dict_first(datum ** inputlist, queue_entry * worker_entry) | |
281 { | |
282 dict_data * dict = inputlist[0]->c.generic.data; | |
283 char * key; | |
284 int key_store = 128; | |
285 int key_size = 0; | |
286 | |
287 int i = 0; | |
288 ternary_node * nodes; | |
289 ternary_node * current = dict->nodes; | |
290 nodes = current; | |
291 if(dict->num_nodes <= 0) | |
292 { | |
293 inputlist[1] = inputlist[0]; | |
294 inputlist[0] = NULL; | |
295 } | |
296 else | |
297 { | |
298 key = malloc(128); | |
299 while(1) | |
300 { | |
301 if(current->left >= 0) | |
302 { | |
303 current = nodes + current->left; | |
304 } else if(current->payload) { | |
305 APPEND_KEY_STORE(key, key_store, key_size, current->letter); | |
306 APPEND_KEY_STORE(key, key_store, key_size, '\0'); | |
307 release_ref(inputlist[0]); | |
308 inputlist[0] = new_datum(BUILTIN_TYPE_STRING, 2, 0, worker_entry->instance->def->program); | |
309 inputlist[0]->union_type = 1; | |
310 inputlist[0]->c.generic.data = key; | |
311 inputlist[0]->c.generic.len = key_size; | |
312 inputlist[1] = NULL; | |
313 break; | |
314 } else if(current->next >= 0) { | |
315 APPEND_KEY_STORE(key, key_store, key_size, current->letter); | |
316 current = nodes + current->next; | |
317 } else if(current->right >= 0) { | |
318 current = nodes + current->right; | |
319 } else { | |
320 inputlist[1] = inputlist[0]; | |
321 inputlist[0] = NULL; | |
322 VIS_FREE(key, "dictionary key store"); | |
323 break; | |
324 } | |
325 } | |
326 } | |
327 return 0; | |
328 } | |
329 | |
330 int vis_dict_next(datum ** inputlist, queue_entry * worker_entry) | |
331 { | |
332 dict_data * dict = inputlist[0]->c.generic.data; | |
333 char * key; | |
334 char * old_key = inputlist[1]->c.generic.data; | |
335 int old_key_len = inputlist[1]->c.generic.len-2; | |
336 int key_store = inputlist[1]->c.generic.len; | |
337 int key_size = 0; | |
338 | |
339 int i = 0; | |
340 ternary_node * nodes; | |
341 ternary_node * current = dict->nodes; | |
342 ternary_node * decision = NULL; | |
343 int decision_key_size; | |
344 BOOL next_flag = FALSE; | |
3
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
345 BOOL this_flag = FALSE; |
0 | 346 nodes = current; |
347 | |
348 if(dict->num_nodes <= 0) | |
349 { | |
350 release_ref(inputlist[1]); | |
351 inputlist[1] = inputlist[0]; | |
352 inputlist[0] = NULL; | |
353 return 0; | |
354 } | |
355 else | |
356 { | |
357 key = malloc(key_store); | |
358 while(current >= nodes) | |
359 { | |
360 if(old_key[i] == current->letter) | |
361 if(i == (old_key_len)) | |
362 { | |
3
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
363 /*if(current->left >= 0) |
0 | 364 { |
365 current = nodes + current->left; | |
366 break; | |
367 } | |
3
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
368 else */if(current->next >= 0) |
0 | 369 { |
370 APPEND_KEY_STORE(key, key_store, key_size, current->letter); | |
371 current = nodes + current->next; | |
372 break; | |
373 } | |
374 else if(current->right >= 0) | |
375 { | |
376 current = nodes + current->right; | |
377 break; | |
378 } | |
379 else | |
380 { | |
381 if(decision) | |
382 { | |
383 key_size = decision_key_size; | |
384 current = decision; | |
385 if(next_flag) | |
386 { | |
387 APPEND_KEY_STORE(key, key_store, key_size, current->letter); | |
388 current = nodes + current->next; | |
389 } | |
3
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
390 else if(this_flag) |
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
391 { |
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
392 APPEND_KEY_STORE(key, key_store, key_size, current->letter); |
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
393 APPEND_KEY_STORE(key, key_store, key_size, '\0'); |
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
394 release_ref(inputlist[0]); |
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
395 release_ref(inputlist[1]); |
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
396 inputlist[1] = NULL; |
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
397 inputlist[0] = new_datum(BUILTIN_TYPE_STRING, 2, 0, worker_entry->instance->def->program); |
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
398 inputlist[0]->union_type = 1; |
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
399 inputlist[0]->c.generic.data = key; |
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
400 inputlist[0]->c.generic.len = key_size; |
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
401 return 0; |
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
402 } |
0 | 403 break; |
404 } | |
405 else | |
406 { | |
407 VIS_FREE(key, "dictionary key store"); | |
408 release_ref(inputlist[1]); | |
409 inputlist[1] = inputlist[0]; | |
410 inputlist[0] = NULL; | |
411 return 0; | |
412 } | |
413 } | |
414 } | |
415 else | |
416 { | |
417 if(current->right >= 0) | |
418 { | |
419 decision = nodes + current->right; | |
420 decision_key_size = key_size; | |
421 next_flag = FALSE; | |
3
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
422 this_flag = FALSE; |
0 | 423 } |
424 APPEND_KEY_STORE(key, key_store, key_size, current->letter); | |
425 ++i; | |
426 current = nodes + current->next; | |
427 } | |
428 else if(old_key[i] > current->letter) | |
429 current = nodes + current->right; | |
430 else | |
431 { | |
3
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
432 //Hmm, what do I do here if there's a payload at this location? |
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
433 if(current->next >= 0 || current->payload) |
0 | 434 { |
435 //APPEND_KEY_STORE(key, key_store, key_size, current->letter); | |
436 decision = current;//nodes + current->next; | |
437 decision_key_size = key_size; | |
3
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
438 if(current->payload) |
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
439 { |
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
440 next_flag = FALSE; |
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
441 this_flag = TRUE; |
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
442 } else { |
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
443 next_flag = TRUE; |
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
444 this_flag = FALSE; |
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
445 } |
0 | 446 } |
447 else if(current->right >= 0) | |
448 { | |
449 decision = nodes + current->right; | |
450 decision_key_size = key_size; | |
451 next_flag = FALSE; | |
3
94c885692eb5
Partial set of fixes and enhancements from Linux box
Mike Pavone <pavone@retrodev.com>
parents:
0
diff
changeset
|
452 this_flag = FALSE; |
0 | 453 } |
454 current = nodes + current->left; | |
455 } | |
456 } | |
457 if(current < nodes) | |
458 { | |
459 VIS_FREE(key, "dictionary key store"); | |
460 release_ref(inputlist[1]); | |
461 inputlist[1] = inputlist[0]; | |
462 inputlist[0] = NULL; | |
463 return 0; | |
464 } | |
465 while(1) | |
466 { | |
467 if(current->left >= 0) | |
468 { | |
469 current = nodes + current->left; | |
470 } else if(current->payload) { | |
471 APPEND_KEY_STORE(key, key_store, key_size, current->letter); | |
472 APPEND_KEY_STORE(key, key_store, key_size, '\0'); | |
473 release_ref(inputlist[0]); | |
474 release_ref(inputlist[1]); | |
475 inputlist[1] = NULL; | |
476 inputlist[0] = new_datum(BUILTIN_TYPE_STRING, 2, 0, worker_entry->instance->def->program); | |
477 inputlist[0]->union_type = 1; | |
478 inputlist[0]->c.generic.data = key; | |
479 inputlist[0]->c.generic.len = key_size; | |
480 break; | |
481 } else if(current->next >= 0) { | |
482 APPEND_KEY_STORE(key, key_store, key_size, current->letter); | |
483 current = nodes + current->next; | |
484 } else if(current->right >= 0) { | |
485 current = nodes + current->right; | |
486 } else { | |
487 release_ref(inputlist[1]); | |
488 inputlist[1] = inputlist[0]; | |
489 inputlist[0] = NULL; | |
490 VIS_FREE(key, "dictionary key store"); | |
491 break; | |
492 } | |
493 } | |
494 } | |
495 return 0; | |
496 } | |
497 | |
498 | |
499 |