1 /****************************************************************************\
2 Copyright (c) 2002, NVIDIA Corporation.
3
4 NVIDIA Corporation("NVIDIA") supplies this software to you in
5 consideration of your agreement to the following terms, and your use,
6 installation, modification or redistribution of this NVIDIA software
7 constitutes acceptance of these terms. If you do not agree with these
8 terms, please do not use, install, modify or redistribute this NVIDIA
9 software.
10
11 In consideration of your agreement to abide by the following terms, and
12 subject to these terms, NVIDIA grants you a personal, non-exclusive
13 license, under NVIDIA's copyrights in this original NVIDIA software (the
14 "NVIDIA Software"), to use, reproduce, modify and redistribute the
15 NVIDIA Software, with or without modifications, in source and/or binary
16 forms; provided that if you redistribute the NVIDIA Software, you must
17 retain the copyright notice of NVIDIA, this notice and the following
18 text and disclaimers in all such redistributions of the NVIDIA Software.
19 Neither the name, trademarks, service marks nor logos of NVIDIA
20 Corporation may be used to endorse or promote products derived from the
21 NVIDIA Software without specific prior written permission from NVIDIA.
22 Except as expressly stated in this notice, no other rights or licenses
23 express or implied, are granted by NVIDIA herein, including but not
24 limited to any patent rights that may be infringed by your derivative
25 works or by other works in which the NVIDIA Software may be
26 incorporated. No hardware is licensed hereunder.
27
28 THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
29 WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
30 INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
31 NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
32 ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
33 PRODUCTS.
34
35 IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
36 INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
37 TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
38 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
39 OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
40 NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
41 TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
42 NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 \****************************************************************************/
44
45 //
46 // atom.c
47 //
48
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <string.h>
52
53 #include "compiler/debug.h"
54 #include "compiler/preprocessor/slglobals.h"
55
56 #undef malloc
57 #undef realloc
58 #undef free
59
60 ///////////////////////////////////////////////////////////////////////////////////////////////
61 ////////////////////////////////////////// String table: //////////////////////////////////////
62 ///////////////////////////////////////////////////////////////////////////////////////////////
63
64 static const struct {
65 int val;
66 const char *str;
67 } tokens[] = {
68 { CPP_AND_OP, "&&" },
69 { CPP_AND_ASSIGN, "&=" },
70 { CPP_SUB_ASSIGN, "-=" },
71 { CPP_MOD_ASSIGN, "%=" },
72 { CPP_ADD_ASSIGN, "+=" },
73 { CPP_DIV_ASSIGN, "/=" },
74 { CPP_MUL_ASSIGN, "*=" },
75 { CPP_RIGHT_BRACKET, ":>" },
76 { CPP_EQ_OP, "==" },
77 { CPP_XOR_OP, "^^" },
78 { CPP_XOR_ASSIGN, "^=" },
79 { CPP_FLOATCONSTANT, "<float-const>" },
80 { CPP_GE_OP, ">=" },
81 { CPP_RIGHT_OP, ">>" },
82 { CPP_RIGHT_ASSIGN, ">>=" },
83 { CPP_IDENTIFIER, "<ident>" },
84 { CPP_INTCONSTANT, "<int-const>" },
85 { CPP_LE_OP, "<=" },
86 { CPP_LEFT_OP, "<<" },
87 { CPP_LEFT_ASSIGN, "<<=" },
88 { CPP_LEFT_BRACKET, "<:" },
89 { CPP_LEFT_BRACE, "<%" },
90 { CPP_DEC_OP, "--" },
91 { CPP_RIGHT_BRACE, "%>" },
92 { CPP_NE_OP, "!=" },
93 { CPP_OR_OP, "||" },
94 { CPP_OR_ASSIGN, "|=" },
95 { CPP_INC_OP, "++" },
96 { CPP_STRCONSTANT, "<string-const>" },
97 { CPP_TYPEIDENTIFIER, "<type-ident>" },
98 };
99
100 ///////////////////////////////////////////////////////////////////////////////////////////////
101 ////////////////////////////////////////// String table: //////////////////////////////////////
102 ///////////////////////////////////////////////////////////////////////////////////////////////
103
104 #define INIT_STRING_TABLE_SIZE 16384
105
106 typedef struct StringTable_Rec {
107 char *strings;
108 int nextFree;
109 int size;
110 } StringTable;
111
112 /*
113 * InitStringTable() - Initialize the string table.
114 *
115 */
116
InitStringTable(StringTable * stable)117 static int InitStringTable(StringTable *stable)
118 {
119 stable->strings = (char *) malloc(INIT_STRING_TABLE_SIZE);
120 if (!stable->strings)
121 return 0;
122 // Zero-th offset means "empty" so don't use it.
123 stable->nextFree = 1;
124 stable->size = INIT_STRING_TABLE_SIZE;
125 return 1;
126 } // InitStringTable
127
128 /*
129 * FreeStringTable() - Free the string table.
130 *
131 */
132
FreeStringTable(StringTable * stable)133 static void FreeStringTable(StringTable *stable)
134 {
135 if (stable->strings)
136 free(stable->strings);
137 stable->strings = NULL;
138 stable->nextFree = 0;
139 stable->size = 0;
140 } // FreeStringTable
141
142 /*
143 * HashString() - Hash a string with the base hash function.
144 *
145 */
146
HashString(const char * s)147 static int HashString(const char *s)
148 {
149 int hval = 0;
150
151 while (*s) {
152 hval = (hval*13507 + *s*197) ^ (hval >> 2);
153 s++;
154 }
155 return hval & 0x7fffffff;
156 } // HashString
157
158 /*
159 * HashString2() - Hash a string with the incrimenting hash function.
160 *
161 */
162
HashString2(const char * s)163 static int HashString2(const char *s)
164 {
165 int hval = 0;
166
167 while (*s) {
168 hval = (hval*729 + *s*37) ^ (hval >> 1);
169 s++;
170 }
171 return hval;
172 } // HashString2
173
174 /*
175 * AddString() - Add a string to a string table. Return it's offset.
176 *
177 */
178
AddString(StringTable * stable,const char * s)179 static int AddString(StringTable *stable, const char *s)
180 {
181 int len, loc;
182 char *str;
183
184 len = (int) strlen(s);
185 if (stable->nextFree + len + 1 >= stable->size) {
186 assert(stable->size < 1000000);
187 str = (char *) malloc(stable->size*2);
188 memcpy(str, stable->strings, stable->size);
189 free(stable->strings);
190 stable->strings = str;
191 }
192 loc = stable->nextFree;
193 strcpy(&stable->strings[loc], s);
194 stable->nextFree += len + 1;
195 return loc;
196 } // AddString
197
198 ///////////////////////////////////////////////////////////////////////////////////////////////
199 /////////////////////////////////////////// Hash table: ///////////////////////////////////////
200 ///////////////////////////////////////////////////////////////////////////////////////////////
201
202 #define INIT_HASH_TABLE_SIZE 2047
203 #define HASH_TABLE_MAX_COLLISIONS 3
204
205 typedef struct HashEntry_Rec {
206 int index; // String table offset of string representation
207 int value; // Atom (symbol) value
208 } HashEntry;
209
210 typedef struct HashTable_Rec {
211 HashEntry *entry;
212 int size;
213 int entries;
214 int counts[HASH_TABLE_MAX_COLLISIONS + 1];
215 } HashTable;
216
217 /*
218 * InitHashTable() - Initialize the hash table.
219 *
220 */
221
InitHashTable(HashTable * htable,int fsize)222 static int InitHashTable(HashTable *htable, int fsize)
223 {
224 int ii;
225
226 htable->entry = (HashEntry *) malloc(sizeof(HashEntry)*fsize);
227 if (!htable->entry)
228 return 0;
229 htable->size = fsize;
230 for (ii = 0; ii < fsize; ii++) {
231 htable->entry[ii].index = 0;
232 htable->entry[ii].value = 0;
233 }
234 htable->entries = 0;
235 for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++)
236 htable->counts[ii] = 0;
237 return 1;
238 } // InitHashTable
239
240 /*
241 * FreeHashTable() - Free the hash table.
242 *
243 */
244
FreeHashTable(HashTable * htable)245 static void FreeHashTable(HashTable *htable)
246 {
247 if (htable->entry)
248 free(htable->entry);
249 htable->entry = NULL;
250 htable->size = 0;
251 htable->entries = 0;
252 } // FreeHashTable
253
254 /*
255 * Empty() - See if a hash table entry is empty.
256 *
257 */
258
Empty(HashTable * htable,int hashloc)259 static int Empty(HashTable *htable, int hashloc)
260 {
261 assert(hashloc >= 0 && hashloc < htable->size);
262 if (htable->entry[hashloc].index == 0) {
263 return 1;
264 } else {
265 return 0;
266 }
267 } // Empty
268
269 /*
270 * Match() - See if a hash table entry is matches a string.
271 *
272 */
273
Match(HashTable * htable,StringTable * stable,const char * s,int hashloc)274 static int Match(HashTable *htable, StringTable *stable, const char *s, int hashloc)
275 {
276 int strloc;
277
278 strloc = htable->entry[hashloc].index;
279 if (!strcmp(s, &stable->strings[strloc])) {
280 return 1;
281 } else {
282 return 0;
283 }
284 } // Match
285
286 ///////////////////////////////////////////////////////////////////////////////////////////////
287 /////////////////////////////////////////// Atom table: ///////////////////////////////////////
288 ///////////////////////////////////////////////////////////////////////////////////////////////
289
290 #define INIT_ATOM_TABLE_SIZE 1024
291
292
293 struct AtomTable_Rec {
294 StringTable stable; // String table.
295 HashTable htable; // Hashes string to atom number and token value. Multiple strings can
296 // have the same token value but each unique string is a unique atom.
297 int *amap; // Maps atom value to offset in string table. Atoms all map to unique
298 // strings except for some undefined values in the lower, fixed part
299 // of the atom table that map to "<undefined>". The lowest 256 atoms
300 // correspond to single character ASCII values except for alphanumeric
301 // characters and '_', which can be other tokens. Next come the
302 // language tokens with their atom values equal to the token value.
303 // Then come predefined atoms, followed by user specified identifiers.
304 int *arev; // Reversed atom for symbol table use.
305 int nextFree;
306 int size;
307 };
308
309 static AtomTable latable = { { 0 } };
310 AtomTable *atable = &latable;
311
312 static int AddAtomFixed(AtomTable *atable, const char *s, int atom);
313
314 /*
315 * GrowAtomTable() - Grow the atom table to at least "size" if it's smaller.
316 *
317 */
318
GrowAtomTable(AtomTable * atable,int size)319 static int GrowAtomTable(AtomTable *atable, int size)
320 {
321 int *newmap, *newrev;
322
323 if (atable->size < size) {
324 if (atable->amap) {
325 newmap = realloc(atable->amap, sizeof(int)*size);
326 newrev = realloc(atable->arev, sizeof(int)*size);
327 } else {
328 newmap = malloc(sizeof(int)*size);
329 newrev = malloc(sizeof(int)*size);
330 atable->size = 0;
331 }
332 if (!newmap || !newrev) {
333 /* failed to grow -- error */
334 if (newmap)
335 atable->amap = newmap;
336 if (newrev)
337 atable->amap = newrev;
338 return -1;
339 }
340 memset(&newmap[atable->size], 0, (size - atable->size) * sizeof(int));
341 memset(&newrev[atable->size], 0, (size - atable->size) * sizeof(int));
342 atable->amap = newmap;
343 atable->arev = newrev;
344 atable->size = size;
345 }
346 return 0;
347 } // GrowAtomTable
348
349 /*
350 * lReverse() - Reverse the bottom 20 bits of a 32 bit int.
351 *
352 */
353
lReverse(int fval)354 static int lReverse(int fval)
355 {
356 unsigned int in = fval;
357 int result = 0, cnt = 0;
358
359 while(in) {
360 result <<= 1;
361 result |= in&1;
362 in >>= 1;
363 cnt++;
364 }
365
366 // Don't use all 31 bits. One million atoms is plenty and sometimes the
367 // upper bits are used for other things.
368
369 if (cnt < 20)
370 result <<= 20 - cnt;
371 return result;
372 } // lReverse
373
374 /*
375 * AllocateAtom() - Allocate a new atom. Associated with the "undefined" value of -1.
376 *
377 */
378
AllocateAtom(AtomTable * atable)379 static int AllocateAtom(AtomTable *atable)
380 {
381 if (atable->nextFree >= atable->size)
382 GrowAtomTable(atable, atable->nextFree*2);
383 atable->amap[atable->nextFree] = -1;
384 atable->arev[atable->nextFree] = lReverse(atable->nextFree);
385 atable->nextFree++;
386 return atable->nextFree - 1;
387 } // AllocateAtom
388
389 /*
390 * SetAtomValue() - Allocate a new atom associated with "hashindex".
391 *
392 */
393
SetAtomValue(AtomTable * atable,int atomnumber,int hashindex)394 static void SetAtomValue(AtomTable *atable, int atomnumber, int hashindex)
395 {
396 atable->amap[atomnumber] = atable->htable.entry[hashindex].index;
397 atable->htable.entry[hashindex].value = atomnumber;
398 } // SetAtomValue
399
400 /*
401 * FindHashLoc() - Find the hash location for this string. Return -1 it hash table is full.
402 *
403 */
404
FindHashLoc(AtomTable * atable,const char * s)405 static int FindHashLoc(AtomTable *atable, const char *s)
406 {
407 int hashloc, hashdelta, count;
408 int FoundEmptySlot = 0;
409 int collision[HASH_TABLE_MAX_COLLISIONS + 1];
410
411 hashloc = HashString(s) % atable->htable.size;
412 if (!Empty(&atable->htable, hashloc)) {
413 if (Match(&atable->htable, &atable->stable, s, hashloc))
414 return hashloc;
415 collision[0] = hashloc;
416 hashdelta = HashString2(s);
417 count = 0;
418 while (count < HASH_TABLE_MAX_COLLISIONS) {
419 hashloc = ((hashloc + hashdelta) & 0x7fffffff) % atable->htable.size;
420 if (!Empty(&atable->htable, hashloc)) {
421 if (Match(&atable->htable, &atable->stable, s, hashloc)) {
422 return hashloc;
423 }
424 } else {
425 FoundEmptySlot = 1;
426 break;
427 }
428 count++;
429 collision[count] = hashloc;
430 }
431
432 if (!FoundEmptySlot) {
433 if (cpp->options.DumpAtomTable) {
434 int ii;
435 char str[200];
436 sprintf(str, "*** Hash failed with more than %d collisions. Must increase hash table size. ***",
437 HASH_TABLE_MAX_COLLISIONS);
438 CPPShInfoLogMsg(str);
439
440 sprintf(str, "*** New string \"%s\", hash=%04x, delta=%04x", s, collision[0], hashdelta);
441 CPPShInfoLogMsg(str);
442 for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++) {
443 sprintf(str, "*** Collides on try %d at hash entry %04x with \"%s\"",
444 ii + 1, collision[ii], GetAtomString(atable, atable->htable.entry[collision[ii]].value));
445 CPPShInfoLogMsg(str);
446 }
447 }
448 return -1;
449 } else {
450 atable->htable.counts[count]++;
451 }
452 }
453 return hashloc;
454 } // FindHashLoc
455
456 /*
457 * IncreaseHashTableSize()
458 *
459 */
460
IncreaseHashTableSize(AtomTable * atable)461 static int IncreaseHashTableSize(AtomTable *atable)
462 {
463 int ii, strloc, oldhashloc, value, size;
464 AtomTable oldtable;
465 char *s;
466
467 // Save the old atom table and create a new one:
468
469 oldtable = *atable;
470 size = oldtable.htable.size*2 + 1;
471 if (!InitAtomTable(atable, size))
472 return 0;
473
474 // Add all the existing values to the new atom table preserving their atom values:
475
476 for (ii = atable->nextFree; ii < oldtable.nextFree; ii++) {
477 strloc = oldtable.amap[ii];
478 s = &oldtable.stable.strings[strloc];
479 oldhashloc = FindHashLoc(&oldtable, s);
480 assert(oldhashloc >= 0);
481 value = oldtable.htable.entry[oldhashloc].value;
482 AddAtomFixed(atable, s, value);
483 }
484 FreeAtomTable(&oldtable);
485 return 1;
486 } // IncreaseHashTableSize
487
488 /*
489 * LookUpAddStringHash() - Lookup a string in the hash table. If it's not there, add it and
490 * initialize the atom value in the hash table to 0. Return the hash table index.
491 */
492
LookUpAddStringHash(AtomTable * atable,const char * s)493 static int LookUpAddStringHash(AtomTable *atable, const char *s)
494 {
495 int hashloc, strloc;
496
497 while(1) {
498 hashloc = FindHashLoc(atable, s);
499 if (hashloc >= 0)
500 break;
501 IncreaseHashTableSize(atable);
502 }
503
504 if (Empty(&atable->htable, hashloc)) {
505 atable->htable.entries++;
506 strloc = AddString(&atable->stable, s);
507 atable->htable.entry[hashloc].index = strloc;
508 atable->htable.entry[hashloc].value = 0;
509 }
510 return hashloc;
511 } // LookUpAddStringHash
512
513 /*
514 * LookUpAddString() - Lookup a string in the hash table. If it's not there, add it and
515 * initialize the atom value in the hash table to the next atom number.
516 * Return the atom value of string.
517 */
518
LookUpAddString(AtomTable * atable,const char * s)519 int LookUpAddString(AtomTable *atable, const char *s)
520 {
521 int hashindex, atom;
522
523 hashindex = LookUpAddStringHash(atable, s);
524 atom = atable->htable.entry[hashindex].value;
525 if (atom == 0) {
526 atom = AllocateAtom(atable);
527 SetAtomValue(atable, atom, hashindex);
528 }
529 return atom;
530 } // LookUpAddString
531
532 /*
533 * GetAtomString()
534 *
535 */
536
GetAtomString(AtomTable * atable,int atom)537 const char *GetAtomString(AtomTable *atable, int atom)
538 {
539 int soffset;
540
541 if (atom > 0 && atom < atable->nextFree) {
542 soffset = atable->amap[atom];
543 if (soffset > 0 && soffset < atable->stable.nextFree) {
544 return &atable->stable.strings[soffset];
545 } else {
546 return "<internal error: bad soffset>";
547 }
548 } else {
549 if (atom == 0) {
550 return "<null atom>";
551 } else {
552 if (atom == EOF) {
553 return "<EOF>";
554 } else {
555 return "<invalid atom>";
556 }
557 }
558 }
559 } // GetAtomString
560
561 /*
562 * GetReversedAtom()
563 *
564 */
565
GetReversedAtom(AtomTable * atable,int atom)566 int GetReversedAtom(AtomTable *atable, int atom)
567 {
568 if (atom > 0 && atom < atable->nextFree) {
569 return atable->arev[atom];
570 } else {
571 return 0;
572 }
573 } // GetReversedAtom
574
575 /*
576 * AddAtom() - Add a string to the atom, hash and string tables if it isn't already there.
577 * Return it's atom index.
578 */
579
AddAtom(AtomTable * atable,const char * s)580 int AddAtom(AtomTable *atable, const char *s)
581 {
582 int atom;
583
584 atom = LookUpAddString(atable, s);
585 return atom;
586 } // AddAtom
587
588 /*
589 * AddAtomFixed() - Add an atom to the hash and string tables if it isn't already there.
590 * Assign it the atom value of "atom".
591 */
592
AddAtomFixed(AtomTable * atable,const char * s,int atom)593 static int AddAtomFixed(AtomTable *atable, const char *s, int atom)
594 {
595 int hashindex, lsize;
596
597 hashindex = LookUpAddStringHash(atable, s);
598 if (atable->nextFree >= atable->size || atom >= atable->size) {
599 lsize = atable->size*2;
600 if (lsize <= atom)
601 lsize = atom + 1;
602 GrowAtomTable(atable, lsize);
603 }
604 atable->amap[atom] = atable->htable.entry[hashindex].index;
605 atable->htable.entry[hashindex].value = atom;
606 //if (atom >= atable->nextFree)
607 // atable->nextFree = atom + 1;
608 while (atom >= atable->nextFree) {
609 atable->arev[atable->nextFree] = lReverse(atable->nextFree);
610 atable->nextFree++;
611 }
612 return atom;
613 } // AddAtomFixed
614
615 /*
616 * InitAtomTable() - Initialize the atom table.
617 *
618 */
619
InitAtomTable(AtomTable * atable,int htsize)620 int InitAtomTable(AtomTable *atable, int htsize)
621 {
622 unsigned int ii;
623
624 htsize = htsize <= 0 ? INIT_HASH_TABLE_SIZE : htsize;
625 if (!InitStringTable(&atable->stable))
626 return 0;
627 if (!InitHashTable(&atable->htable, htsize))
628 return 0;
629
630 atable->nextFree = 0;
631 atable->amap = NULL;
632 atable->size = 0;
633 GrowAtomTable(atable, INIT_ATOM_TABLE_SIZE);
634 if (!atable->amap)
635 return 0;
636
637 // Initialize lower part of atom table to "<undefined>" atom:
638
639 AddAtomFixed(atable, "<undefined>", 0);
640 for (ii = 0; ii < FIRST_USER_TOKEN_SY; ii++)
641 atable->amap[ii] = atable->amap[0];
642
643 // Add single character tokens to the atom table:
644
645 {
646 const char *s = "~!%^&*()-+=|,.<>/?;:[]{}#";
647 char t[2];
648
649 t[1] = '\0';
650 while (*s) {
651 t[0] = *s;
652 AddAtomFixed(atable, t, s[0]);
653 s++;
654 }
655 }
656
657 // Add multiple character scanner tokens :
658
659 for (ii = 0; ii < sizeof(tokens)/sizeof(tokens[0]); ii++)
660 AddAtomFixed(atable, tokens[ii].str, tokens[ii].val);
661
662 // Add error symbol if running in error mode:
663
664 if (cpp->options.ErrorMode)
665 AddAtomFixed(atable, "error", ERROR_SY);
666
667 AddAtom(atable, "<*** end fixed atoms ***>");
668
669 return 1;
670 } // InitAtomTable
671
672 ///////////////////////////////////////////////////////////////////////////////////////////////
673 ////////////////////////////////// Debug Printing Functions: //////////////////////////////////
674 ///////////////////////////////////////////////////////////////////////////////////////////////
675
676 /*
677 * PrintAtomTable()
678 *
679 */
680
PrintAtomTable(AtomTable * atable)681 void PrintAtomTable(AtomTable *atable)
682 {
683 int ii;
684 char str[200];
685
686 for (ii = 0; ii < atable->nextFree; ii++) {
687 sprintf(str, "%d: \"%s\"", ii, &atable->stable.strings[atable->amap[ii]]);
688 CPPDebugLogMsg(str);
689 }
690 sprintf(str, "Hash table: size=%d, entries=%d, collisions=",
691 atable->htable.size, atable->htable.entries);
692 CPPDebugLogMsg(str);
693 for (ii = 0; ii < HASH_TABLE_MAX_COLLISIONS; ii++) {
694 sprintf(str, " %d", atable->htable.counts[ii]);
695 CPPDebugLogMsg(str);
696 }
697
698 } // PrintAtomTable
699
700
701 /*
702 * GetStringOfAtom()
703 *
704 */
705
GetStringOfAtom(AtomTable * atable,int atom)706 char* GetStringOfAtom(AtomTable *atable, int atom)
707 {
708 char* chr_str;
709 chr_str=&atable->stable.strings[atable->amap[atom]];
710 return chr_str;
711 } // GetStringOfAtom
712
713 /*
714 * FreeAtomTable() - Free the atom table and associated memory
715 *
716 */
717
FreeAtomTable(AtomTable * atable)718 void FreeAtomTable(AtomTable *atable)
719 {
720 FreeStringTable(&atable->stable);
721 FreeHashTable(&atable->htable);
722 if (atable->amap)
723 free(atable->amap);
724 if (atable->arev)
725 free(atable->arev);
726 atable->amap = NULL;
727 atable->arev = NULL;
728 atable->nextFree = 0;
729 atable->size = 0;
730 } // FreeAtomTable
731
732 ///////////////////////////////////////////////////////////////////////////////////////////////
733 ///////////////////////////////////////// End of atom.c ///////////////////////////////////////
734 ///////////////////////////////////////////////////////////////////////////////////////////////
735
736