Home | History | Annotate | Download | only in preprocessor
      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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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