2 //Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
5 //Redistribution and use in source and binary forms, with or without
6 //modification, are permitted provided that the following conditions
9 // Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
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.
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.
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.
34 /****************************************************************************\
35 Copyright (c) 2002, NVIDIA Corporation.
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
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.
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
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 \****************************************************************************/
87 #include "slglobals.h"
93 ///////////////////////////////////////////////////////////////////////////////////////////////
94 ////////////////////////////////////////// String table: //////////////////////////////////////
95 ///////////////////////////////////////////////////////////////////////////////////////////////
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, ":>" },
110 { CPP_XOR_OP, "^^" },
111 { CPP_XOR_ASSIGN, "^=" },
112 { CPP_FLOATCONSTANT, "<float-const>" },
114 { CPP_RIGHT_OP, ">>" },
115 { CPP_RIGHT_ASSIGN, ">>=" },
116 { CPP_IDENTIFIER, "<ident>" },
117 { CPP_INTCONSTANT, "<int-const>" },
119 { CPP_LEFT_OP, "<<" },
120 { CPP_LEFT_ASSIGN, "<<=" },
121 { CPP_LEFT_BRACKET, "<:" },
122 { CPP_LEFT_BRACE, "<%" },
123 { CPP_DEC_OP, "--" },
124 { CPP_RIGHT_BRACE, "%>" },
127 { CPP_OR_ASSIGN, "|=" },
128 { CPP_INC_OP, "++" },
129 { CPP_STRCONSTANT, "<string-const>" },
130 { CPP_TYPEIDENTIFIER, "<type-ident>" },
133 ///////////////////////////////////////////////////////////////////////////////////////////////
134 ////////////////////////////////////////// String table: //////////////////////////////////////
135 ///////////////////////////////////////////////////////////////////////////////////////////////
137 #define INIT_STRING_TABLE_SIZE 16384
139 typedef struct StringTable_Rec {
146 * InitStringTable() - Initialize the string table.
150 static int InitStringTable(StringTable *stable)
152 stable->strings = (char *) malloc(INIT_STRING_TABLE_SIZE);
153 if (!stable->strings)
155 // Zero-th offset means "empty" so don't use it.
156 stable->nextFree = 1;
157 stable->size = INIT_STRING_TABLE_SIZE;
162 * FreeStringTable() - Free the string table.
166 static void FreeStringTable(StringTable *stable)
169 free(stable->strings);
170 stable->strings = NULL;
171 stable->nextFree = 0;
176 * HashString() - Hash a string with the base hash function.
180 static int HashString(const char *s)
185 hval = (hval*13507 + *s*197) ^ (hval >> 2);
188 return hval & 0x7fffffff;
192 * HashString2() - Hash a string with the incrimenting hash function.
196 static int HashString2(const char *s)
201 hval = (hval*729 + *s*37) ^ (hval >> 1);
208 * AddString() - Add a string to a string table. Return it's offset.
212 static int AddString(StringTable *stable, const char *s)
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;
225 loc = stable->nextFree;
226 strcpy(&stable->strings[loc], s);
227 stable->nextFree += len + 1;
231 ///////////////////////////////////////////////////////////////////////////////////////////////
232 /////////////////////////////////////////// Hash table: ///////////////////////////////////////
233 ///////////////////////////////////////////////////////////////////////////////////////////////
235 #define INIT_HASH_TABLE_SIZE 2047
236 #define HASH_TABLE_MAX_COLLISIONS 3
238 typedef struct HashEntry_Rec {
239 int index; // String table offset of string representation
240 int value; // Atom (symbol) value
243 typedef struct HashTable_Rec {
247 int counts[HASH_TABLE_MAX_COLLISIONS + 1];
251 * InitHashTable() - Initialize the hash table.
255 static int InitHashTable(HashTable *htable, int fsize)
259 htable->entry = (HashEntry *) malloc(sizeof(HashEntry)*fsize);
262 htable->size = fsize;
263 for (ii = 0; ii < fsize; ii++) {
264 htable->entry[ii].index = 0;
265 htable->entry[ii].value = 0;
268 for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++)
269 htable->counts[ii] = 0;
274 * FreeHashTable() - Free the hash table.
278 static void FreeHashTable(HashTable *htable)
282 htable->entry = NULL;
288 * Empty() - See if a hash table entry is empty.
292 static int Empty(HashTable *htable, int hashloc)
294 assert(hashloc >= 0 && hashloc < htable->size);
295 if (htable->entry[hashloc].index == 0) {
303 * Match() - See if a hash table entry is matches a string.
307 static int Match(HashTable *htable, StringTable *stable, const char *s, int hashloc)
311 strloc = htable->entry[hashloc].index;
312 if (!strcmp(s, &stable->strings[strloc])) {
319 ///////////////////////////////////////////////////////////////////////////////////////////////
320 /////////////////////////////////////////// Atom table: ///////////////////////////////////////
321 ///////////////////////////////////////////////////////////////////////////////////////////////
323 #define INIT_ATOM_TABLE_SIZE 1024
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.
342 static AtomTable latable = { { 0 } };
343 AtomTable *atable = &latable;
345 static int AddAtomFixed(AtomTable *atable, const char *s, int atom);
348 * GrowAtomTable() - Grow the atom table to at least "size" if it's smaller.
352 static int GrowAtomTable(AtomTable *atable, int size)
354 int *newmap, *newrev;
356 if (atable->size < size) {
358 newmap = realloc(atable->amap, sizeof(int)*size);
359 newrev = realloc(atable->arev, sizeof(int)*size);
361 newmap = malloc(sizeof(int)*size);
362 newrev = malloc(sizeof(int)*size);
365 if (!newmap || !newrev) {
366 /* failed to grow -- error */
368 atable->amap = newmap;
370 atable->amap = newrev;
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;
383 * lReverse() - Reverse the bottom 20 bits of a 32 bit int.
387 static int lReverse(int fval)
389 unsigned int in = fval;
390 int result = 0, cnt = 0;
399 // Don't use all 31 bits. One million atoms is plenty and sometimes the
400 // upper bits are used for other things.
408 * AllocateAtom() - Allocate a new atom. Associated with the "undefined" value of -1.
412 static int AllocateAtom(AtomTable *atable)
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);
419 return atable->nextFree - 1;
423 * SetAtomValue() - Allocate a new atom associated with "hashindex".
427 static void SetAtomValue(AtomTable *atable, int atomnumber, int hashindex)
429 atable->amap[atomnumber] = atable->htable.entry[hashindex].index;
430 atable->htable.entry[hashindex].value = atomnumber;
434 * FindHashLoc() - Find the hash location for this string. Return -1 it hash table is full.
438 static int FindHashLoc(AtomTable *atable, const char *s)
440 int hashloc, hashdelta, count;
441 int FoundEmptySlot = 0;
442 int collision[HASH_TABLE_MAX_COLLISIONS + 1];
444 hashloc = HashString(s) % atable->htable.size;
445 if (!Empty(&atable->htable, hashloc)) {
446 if (Match(&atable->htable, &atable->stable, s, hashloc))
448 collision[0] = hashloc;
449 hashdelta = HashString2(s);
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)) {
462 collision[count] = hashloc;
465 if (!FoundEmptySlot) {
466 if (cpp->options.DumpAtomTable) {
469 sprintf(str, "*** Hash failed with more than %d collisions. Must increase hash table size. ***",
470 HASH_TABLE_MAX_COLLISIONS);
471 CPPShInfoLogMsg(str);
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);
483 atable->htable.counts[count]++;
490 * IncreaseHashTableSize()
494 static int IncreaseHashTableSize(AtomTable *atable)
496 int ii, strloc, oldhashloc, value, size;
500 // Save the old atom table and create a new one:
503 size = oldtable.htable.size*2 + 1;
504 if (!InitAtomTable(atable, size))
507 // Add all the existing values to the new atom table preserving their atom values:
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);
517 FreeAtomTable(&oldtable);
519 } // IncreaseHashTableSize
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.
526 static int LookUpAddStringHash(AtomTable *atable, const char *s)
531 hashloc = FindHashLoc(atable, s);
534 IncreaseHashTableSize(atable);
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;
544 } // LookUpAddStringHash
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.
552 int LookUpAddString(AtomTable *atable, const char *s)
556 hashindex = LookUpAddStringHash(atable, s);
557 atom = atable->htable.entry[hashindex].value;
559 atom = AllocateAtom(atable);
560 SetAtomValue(atable, atom, hashindex);
570 const char *GetAtomString(AtomTable *atable, int atom)
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];
579 return "<internal error: bad soffset>";
583 return "<null atom>";
588 return "<invalid atom>";
599 int GetReversedAtom(AtomTable *atable, int atom)
601 if (atom > 0 && atom < atable->nextFree) {
602 return atable->arev[atom];
609 * AddAtom() - Add a string to the atom, hash and string tables if it isn't already there.
610 * Return it's atom index.
613 int AddAtom(AtomTable *atable, const char *s)
617 atom = LookUpAddString(atable, s);
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".
626 static int AddAtomFixed(AtomTable *atable, const char *s, int atom)
628 int hashindex, lsize;
630 hashindex = LookUpAddStringHash(atable, s);
631 if (atable->nextFree >= atable->size || atom >= atable->size) {
632 lsize = atable->size*2;
635 GrowAtomTable(atable, lsize);
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);
649 * InitAtomTable() - Initialize the atom table.
653 int InitAtomTable(AtomTable *atable, int htsize)
657 htsize = htsize <= 0 ? INIT_HASH_TABLE_SIZE : htsize;
658 if (!InitStringTable(&atable->stable))
660 if (!InitHashTable(&atable->htable, htsize))
663 atable->nextFree = 0;
666 GrowAtomTable(atable, INIT_ATOM_TABLE_SIZE);
670 // Initialize lower part of atom table to "<undefined>" atom:
672 AddAtomFixed(atable, "<undefined>", 0);
673 for (ii = 0; ii < FIRST_USER_TOKEN_SY; ii++)
674 atable->amap[ii] = atable->amap[0];
676 // Add single character tokens to the atom table:
679 const char *s = "~!%^&*()-+=|,.<>/?;:[]{}#";
685 AddAtomFixed(atable, t, s[0]);
690 // Add multiple character scanner tokens :
692 for (ii = 0; ii < sizeof(tokens)/sizeof(tokens[0]); ii++)
693 AddAtomFixed(atable, tokens[ii].str, tokens[ii].val);
695 // Add error symbol if running in error mode:
697 if (cpp->options.ErrorMode)
698 AddAtomFixed(atable, "error", ERROR_SY);
700 AddAtom(atable, "<*** end fixed atoms ***>");
705 ///////////////////////////////////////////////////////////////////////////////////////////////
706 ////////////////////////////////// Debug Printing Functions: //////////////////////////////////
707 ///////////////////////////////////////////////////////////////////////////////////////////////
714 void PrintAtomTable(AtomTable *atable)
719 for (ii = 0; ii < atable->nextFree; ii++) {
720 sprintf(str, "%d: \"%s\"", ii, &atable->stable.strings[atable->amap[ii]]);
723 sprintf(str, "Hash table: size=%d, entries=%d, collisions=",
724 atable->htable.size, atable->htable.entries);
726 for (ii = 0; ii < HASH_TABLE_MAX_COLLISIONS; ii++) {
727 sprintf(str, " %d", atable->htable.counts[ii]);
739 char* GetStringOfAtom(AtomTable *atable, int atom)
742 chr_str=&atable->stable.strings[atable->amap[atom]];
747 * FreeAtomTable() - Free the atom table and associated memory
751 void FreeAtomTable(AtomTable *atable)
753 FreeStringTable(&atable->stable);
754 FreeHashTable(&atable->htable);
761 atable->nextFree = 0;
765 ///////////////////////////////////////////////////////////////////////////////////////////////
766 ///////////////////////////////////////// End of atom.c ///////////////////////////////////////
767 ///////////////////////////////////////////////////////////////////////////////////////////////