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