Fix memory corruption problem in the preprocessor, removing custom hash-tables/etc. and replacing with std containers.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@23623 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
ab3080353a
commit
1f4104fbb1
7 changed files with 172 additions and 957 deletions
|
|
@ -98,10 +98,6 @@ namespace {
|
|||
|
||||
using namespace glslang;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////// String table: //////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const struct {
|
||||
int val;
|
||||
const char *str;
|
||||
|
|
@ -129,579 +125,71 @@ const struct {
|
|||
{ CPP_INC_OP, "++" },
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////// String table: //////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define INIT_STRING_TABLE_SIZE 16384
|
||||
|
||||
/*
|
||||
* InitStringTable() - Initialize the string table.
|
||||
*
|
||||
*/
|
||||
int InitStringTable(TPpContext::StringTable *stable)
|
||||
{
|
||||
stable->strings = (char *) malloc(INIT_STRING_TABLE_SIZE);
|
||||
if (!stable->strings)
|
||||
return 0;
|
||||
// Zero-th offset means "empty" so don't use it.
|
||||
stable->nextFree = 1;
|
||||
stable->size = INIT_STRING_TABLE_SIZE;
|
||||
return 1;
|
||||
} // InitStringTable
|
||||
|
||||
/*
|
||||
* FreeStringTable() - Free the string table.
|
||||
*
|
||||
*/
|
||||
void FreeStringTable(TPpContext::StringTable *stable)
|
||||
{
|
||||
if (stable->strings)
|
||||
free(stable->strings);
|
||||
stable->strings = NULL;
|
||||
stable->nextFree = 0;
|
||||
stable->size = 0;
|
||||
} // FreeStringTable
|
||||
|
||||
/*
|
||||
* HashString() - Hash a string with the base hash function.
|
||||
*
|
||||
*/
|
||||
int HashString(const char *s)
|
||||
{
|
||||
int hval = 0;
|
||||
|
||||
while (*s) {
|
||||
hval = (hval*13507 + *s*197) ^ (hval >> 2);
|
||||
s++;
|
||||
}
|
||||
return hval & 0x7fffffff;
|
||||
} // HashString
|
||||
|
||||
/*
|
||||
* HashString2() - Hash a string with the incrimenting hash function.
|
||||
*
|
||||
*/
|
||||
int HashString2(const char *s)
|
||||
{
|
||||
int hval = 0;
|
||||
|
||||
while (*s) {
|
||||
hval = (hval*729 + *s*37) ^ (hval >> 1);
|
||||
s++;
|
||||
}
|
||||
return hval;
|
||||
} // HashString2
|
||||
|
||||
/*
|
||||
* AddString() - Add a string to a string table. Return it's offset.
|
||||
*
|
||||
*/
|
||||
int AddString(TPpContext::StringTable *stable, const char *s)
|
||||
{
|
||||
int len, loc;
|
||||
char *str;
|
||||
|
||||
len = (int) strlen(s);
|
||||
if (stable->nextFree + len + 1 >= stable->size) {
|
||||
assert(stable->size < 1000000);
|
||||
str = (char *) malloc(stable->size*2);
|
||||
memcpy(str, stable->strings, stable->size);
|
||||
free(stable->strings);
|
||||
stable->strings = str;
|
||||
}
|
||||
loc = stable->nextFree;
|
||||
strcpy(&stable->strings[loc], s);
|
||||
stable->nextFree += len + 1;
|
||||
return loc;
|
||||
} // AddString
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////// Hash table: ///////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define INIT_HASH_TABLE_SIZE 2047
|
||||
|
||||
/*
|
||||
* InitHashTable() - Initialize the hash table.
|
||||
*
|
||||
*/
|
||||
int InitHashTable(TPpContext::HashTable *htable, int fsize)
|
||||
{
|
||||
int ii;
|
||||
|
||||
htable->entry = (TPpContext::HashEntry *) malloc(sizeof(TPpContext::HashEntry)*fsize);
|
||||
if (! htable->entry)
|
||||
return 0;
|
||||
htable->size = fsize;
|
||||
for (ii = 0; ii < fsize; ii++) {
|
||||
htable->entry[ii].index = 0;
|
||||
htable->entry[ii].value = 0;
|
||||
}
|
||||
htable->entries = 0;
|
||||
for (ii = 0; ii <= TPpContext::hashTableMaxCollisions; ii++)
|
||||
htable->counts[ii] = 0;
|
||||
return 1;
|
||||
} // InitHashTable
|
||||
|
||||
/*
|
||||
* FreeHashTable() - Free the hash table.
|
||||
*
|
||||
*/
|
||||
void FreeHashTable(TPpContext::HashTable *htable)
|
||||
{
|
||||
if (htable->entry)
|
||||
free(htable->entry);
|
||||
htable->entry = NULL;
|
||||
htable->size = 0;
|
||||
htable->entries = 0;
|
||||
} // FreeHashTable
|
||||
|
||||
/*
|
||||
* Empty() - See if a hash table entry is empty.
|
||||
*
|
||||
*/
|
||||
int Empty(TPpContext::HashTable *htable, int hashloc)
|
||||
{
|
||||
assert(hashloc >= 0 && hashloc < htable->size);
|
||||
if (htable->entry[hashloc].index == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} // Empty
|
||||
|
||||
/*
|
||||
* Match() - See if a hash table entry is matches a string.
|
||||
*
|
||||
*/
|
||||
int Match(TPpContext::HashTable *htable, TPpContext::StringTable *stable, const char *s, int hashloc)
|
||||
{
|
||||
int strloc;
|
||||
|
||||
strloc = htable->entry[hashloc].index;
|
||||
if (!strcmp(s, &stable->strings[strloc])) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} // Match
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////// Atom table: ///////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define INIT_ATOM_TABLE_SIZE 1024
|
||||
|
||||
/*
|
||||
* GrowAtomTable() - Grow the atom table to at least "size" if it's smaller.
|
||||
*
|
||||
*/
|
||||
int GrowAtomTable(TPpContext::AtomTable *atable, int size)
|
||||
{
|
||||
int *newmap, *newrev;
|
||||
|
||||
if (atable->size < size) {
|
||||
if (atable->amap) {
|
||||
newmap = (int*)realloc(atable->amap, sizeof(int)*size);
|
||||
newrev = (int*)realloc(atable->arev, sizeof(int)*size);
|
||||
} else {
|
||||
newmap = (int*)malloc(sizeof(int)*size);
|
||||
newrev = (int*)malloc(sizeof(int)*size);
|
||||
atable->size = 0;
|
||||
}
|
||||
if (!newmap || !newrev) {
|
||||
/* failed to grow -- error */
|
||||
if (newmap)
|
||||
atable->amap = newmap;
|
||||
if (newrev)
|
||||
atable->amap = newrev;
|
||||
return -1;
|
||||
}
|
||||
memset(&newmap[atable->size], 0, (size - atable->size) * sizeof(int));
|
||||
memset(&newrev[atable->size], 0, (size - atable->size) * sizeof(int));
|
||||
atable->amap = newmap;
|
||||
atable->arev = newrev;
|
||||
atable->size = size;
|
||||
}
|
||||
return 0;
|
||||
} // GrowAtomTable
|
||||
|
||||
/*
|
||||
* lReverse() - Reverse the bottom 20 bits of a 32 bit int.
|
||||
*
|
||||
*/
|
||||
int lReverse(int fval)
|
||||
{
|
||||
unsigned int in = fval;
|
||||
int result = 0, cnt = 0;
|
||||
|
||||
while(in) {
|
||||
result <<= 1;
|
||||
result |= in&1;
|
||||
in >>= 1;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
// Don't use all 31 bits. One million atoms is plenty and sometimes the
|
||||
// upper bits are used for other things.
|
||||
|
||||
if (cnt < 20)
|
||||
result <<= 20 - cnt;
|
||||
return result;
|
||||
} // lReverse
|
||||
|
||||
/*
|
||||
* AllocateAtom() - Allocate a new atom. Associated with the "undefined" value of -1.
|
||||
*
|
||||
*/
|
||||
int AllocateAtom(TPpContext::AtomTable *atable)
|
||||
{
|
||||
if (atable->nextFree >= atable->size)
|
||||
GrowAtomTable(atable, atable->nextFree*2);
|
||||
atable->amap[atable->nextFree] = -1;
|
||||
atable->arev[atable->nextFree] = lReverse(atable->nextFree);
|
||||
atable->nextFree++;
|
||||
return atable->nextFree - 1;
|
||||
} // AllocateAtom
|
||||
|
||||
/*
|
||||
* SetAtomValue() - Allocate a new atom associated with "hashindex".
|
||||
*
|
||||
*/
|
||||
void SetAtomValue(TPpContext::AtomTable *atable, int atomnumber, int hashindex)
|
||||
{
|
||||
atable->amap[atomnumber] = atable->htable.entry[hashindex].index;
|
||||
atable->htable.entry[hashindex].value = atomnumber;
|
||||
} // SetAtomValue
|
||||
|
||||
/*
|
||||
* FindHashLoc() - Find the hash location for this string. Return -1 it hash table is full.
|
||||
*
|
||||
*/
|
||||
int FindHashLoc(TPpContext::AtomTable *atable, const char *s)
|
||||
{
|
||||
int hashloc, hashdelta, count;
|
||||
int FoundEmptySlot = 0;
|
||||
#ifdef DUMP_TABLE
|
||||
int collision[TPpContext::hashTableMaxCollisions + 1];
|
||||
#endif
|
||||
|
||||
hashloc = HashString(s) % atable->htable.size;
|
||||
if (!Empty(&atable->htable, hashloc)) {
|
||||
if (Match(&atable->htable, &atable->stable, s, hashloc))
|
||||
return hashloc;
|
||||
#ifdef DUMP_TABLE
|
||||
collision[0] = hashloc;
|
||||
#endif
|
||||
hashdelta = HashString2(s);
|
||||
count = 0;
|
||||
while (count < TPpContext::hashTableMaxCollisions) {
|
||||
hashloc = ((hashloc + hashdelta) & 0x7fffffff) % atable->htable.size;
|
||||
if (!Empty(&atable->htable, hashloc)) {
|
||||
if (Match(&atable->htable, &atable->stable, s, hashloc)) {
|
||||
return hashloc;
|
||||
}
|
||||
} else {
|
||||
FoundEmptySlot = 1;
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
#ifdef DUMP_TABLE
|
||||
collision[count] = hashloc;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (! FoundEmptySlot) {
|
||||
#ifdef DUMP_TABLE
|
||||
{
|
||||
int ii;
|
||||
char str[200];
|
||||
printf(str, "*** Hash failed with more than %d collisions. Must increase hash table size. ***",
|
||||
hashTableMaxCollisions);
|
||||
printf(str, "*** New string \"%s\", hash=%04x, delta=%04x", s, collision[0], hashdelta);
|
||||
for (ii = 0; ii <= hashTableMaxCollisions; ii++) {
|
||||
printf(str, "*** Collides on try %d at hash entry %04x with \"%s\"",
|
||||
ii + 1, collision[ii], GetAtomString(atable, atable->htable.entry[collision[ii]].value));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
} else {
|
||||
atable->htable.counts[count]++;
|
||||
}
|
||||
}
|
||||
return hashloc;
|
||||
} // FindHashLoc
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace glslang {
|
||||
|
||||
/*
|
||||
* IncreaseHashTableSize()
|
||||
*
|
||||
*/
|
||||
int TPpContext::IncreaseHashTableSize(AtomTable *atable)
|
||||
//
|
||||
// Map a new or existing string to an atom, inventing a new atom if necessary.
|
||||
//
|
||||
int TPpContext::LookUpAddString(const char *s)
|
||||
{
|
||||
int ii, strloc, oldhashloc, value, size;
|
||||
AtomTable oldtable;
|
||||
char *s;
|
||||
|
||||
// Save the old atom table and create a new one:
|
||||
|
||||
oldtable = *atable;
|
||||
size = oldtable.htable.size*2 + 1;
|
||||
if (! InitAtomTable(atable, size))
|
||||
return 0;
|
||||
|
||||
// Add all the existing values to the new atom table preserving their atom values:
|
||||
|
||||
for (ii = atable->nextFree; ii < oldtable.nextFree; ii++) {
|
||||
strloc = oldtable.amap[ii];
|
||||
s = &oldtable.stable.strings[strloc];
|
||||
oldhashloc = FindHashLoc(&oldtable, s);
|
||||
assert(oldhashloc >= 0);
|
||||
value = oldtable.htable.entry[oldhashloc].value;
|
||||
AddAtomFixed(atable, s, value);
|
||||
}
|
||||
FreeAtomTable(&oldtable);
|
||||
|
||||
return 1;
|
||||
} // IncreaseHashTableSize
|
||||
|
||||
/*
|
||||
* LookUpAddStringHash() - Lookup a string in the hash table. If it's not there, add it and
|
||||
* initialize the atom value in the hash table to 0. Return the hash table index.
|
||||
*/
|
||||
|
||||
int TPpContext::LookUpAddStringHash(AtomTable *atable, const char *s)
|
||||
{
|
||||
int hashloc, strloc;
|
||||
|
||||
while(1) {
|
||||
hashloc = FindHashLoc(atable, s);
|
||||
if (hashloc >= 0)
|
||||
break;
|
||||
IncreaseHashTableSize(atable);
|
||||
}
|
||||
|
||||
if (Empty(&atable->htable, hashloc)) {
|
||||
atable->htable.entries++;
|
||||
strloc = AddString(&atable->stable, s);
|
||||
atable->htable.entry[hashloc].index = strloc;
|
||||
atable->htable.entry[hashloc].value = 0;
|
||||
}
|
||||
return hashloc;
|
||||
} // LookUpAddStringHash
|
||||
|
||||
/*
|
||||
* LookUpAddString() - Lookup a string in the hash table. If it's not there, add it and
|
||||
* initialize the atom value in the hash table to the next atom number.
|
||||
* Return the atom value of string.
|
||||
*/
|
||||
|
||||
int TPpContext::LookUpAddString(AtomTable *atable, const char *s)
|
||||
{
|
||||
int hashindex, atom;
|
||||
|
||||
hashindex = LookUpAddStringHash(atable, s);
|
||||
atom = atable->htable.entry[hashindex].value;
|
||||
if (atom == 0) {
|
||||
atom = AllocateAtom(atable);
|
||||
SetAtomValue(atable, atom, hashindex);
|
||||
}
|
||||
return atom;
|
||||
} // LookUpAddString
|
||||
|
||||
/*
|
||||
* GetAtomString()
|
||||
*
|
||||
*/
|
||||
|
||||
const char *TPpContext::GetAtomString(AtomTable *atable, int atom)
|
||||
{
|
||||
int soffset;
|
||||
|
||||
if (atom > 0 && atom < atable->nextFree) {
|
||||
soffset = atable->amap[atom];
|
||||
if (soffset > 0 && soffset < atable->stable.nextFree) {
|
||||
return &atable->stable.strings[soffset];
|
||||
} else {
|
||||
return "<internal error: bad soffset>";
|
||||
}
|
||||
} else {
|
||||
if (atom == 0) {
|
||||
return "<null atom>";
|
||||
} else {
|
||||
if (atom == EOF) {
|
||||
return "<EOF>";
|
||||
} else {
|
||||
return "<invalid atom>";
|
||||
}
|
||||
}
|
||||
}
|
||||
} // GetAtomString
|
||||
|
||||
/*
|
||||
* GetReversedAtom()
|
||||
*
|
||||
*/
|
||||
|
||||
int TPpContext::GetReversedAtom(TPpContext::AtomTable *atable, int atom)
|
||||
{
|
||||
if (atom > 0 && atom < atable->nextFree)
|
||||
return atable->arev[atom];
|
||||
TAtomMap::const_iterator it = atomMap.find(s);
|
||||
if (it == atomMap.end())
|
||||
return AddAtomFixed(s, nextAtom++);
|
||||
else
|
||||
return 0;
|
||||
} // GetReversedAtom
|
||||
return it->second;
|
||||
}
|
||||
|
||||
/*
|
||||
* AddAtom() - Add a string to the atom, hash and string tables if it isn't already there.
|
||||
* Return it's atom index.
|
||||
*/
|
||||
|
||||
int TPpContext::AddAtom(TPpContext::AtomTable *atable, const char *s)
|
||||
//
|
||||
// Map an already created atom to its string.
|
||||
//
|
||||
const char *TPpContext::GetAtomString(int atom)
|
||||
{
|
||||
int atom = LookUpAddString(atable, s);
|
||||
if (atom == 0)
|
||||
return "<null atom>";
|
||||
if (atom < 0)
|
||||
return "<EOF>";
|
||||
if ((size_t)atom < stringMap.size())
|
||||
return stringMap[atom]->c_str();
|
||||
|
||||
return "<invalid atom>";
|
||||
}
|
||||
|
||||
//
|
||||
// Add forced mapping of string to atom.
|
||||
//
|
||||
int TPpContext::AddAtomFixed(const char *s, int atom)
|
||||
{
|
||||
TAtomMap::const_iterator it = atomMap.insert(std::pair<TString, int>(s, atom)).first;
|
||||
if (stringMap.size() < (size_t)atom + 1)
|
||||
stringMap.resize(atom + 100);
|
||||
stringMap[atom] = &it->first;
|
||||
|
||||
return atom;
|
||||
} // AddAtom
|
||||
}
|
||||
|
||||
/*
|
||||
* AddAtomFixed() - Add an atom to the hash and string tables if it isn't already there.
|
||||
* Assign it the atom value of "atom".
|
||||
*/
|
||||
|
||||
int TPpContext::AddAtomFixed(AtomTable *atable, const char *s, int atom)
|
||||
//
|
||||
// Initialize the atom table.
|
||||
//
|
||||
void TPpContext::InitAtomTable()
|
||||
{
|
||||
int hashindex, lsize;
|
||||
|
||||
hashindex = LookUpAddStringHash(atable, s);
|
||||
if (atable->nextFree >= atable->size || atom >= atable->size) {
|
||||
lsize = atable->size*2;
|
||||
if (lsize <= atom)
|
||||
lsize = atom + 1;
|
||||
GrowAtomTable(atable, lsize);
|
||||
}
|
||||
atable->amap[atom] = atable->htable.entry[hashindex].index;
|
||||
atable->htable.entry[hashindex].value = atom;
|
||||
//if (atom >= atable->nextFree)
|
||||
// atable->nextFree = atom + 1;
|
||||
while (atom >= atable->nextFree) {
|
||||
atable->arev[atable->nextFree] = lReverse(atable->nextFree);
|
||||
atable->nextFree++;
|
||||
}
|
||||
return atom;
|
||||
} // AddAtomFixed
|
||||
|
||||
/*
|
||||
* InitAtomTable() - Initialize the atom table.
|
||||
*
|
||||
*/
|
||||
|
||||
int TPpContext::InitAtomTable(AtomTable *atable, int htsize)
|
||||
{
|
||||
int ii;
|
||||
|
||||
htsize = htsize <= 0 ? INIT_HASH_TABLE_SIZE : htsize;
|
||||
if (! InitStringTable(&atable->stable))
|
||||
return 0;
|
||||
if (! InitHashTable(&atable->htable, htsize))
|
||||
return 0;
|
||||
|
||||
atable->nextFree = 0;
|
||||
atable->amap = NULL;
|
||||
atable->size = 0;
|
||||
atable->arev = 0;
|
||||
GrowAtomTable(atable, INIT_ATOM_TABLE_SIZE);
|
||||
if (!atable->amap)
|
||||
return 0;
|
||||
|
||||
// Initialize lower part of atom table to "<undefined>" atom:
|
||||
|
||||
AddAtomFixed(atable, "<undefined>", 0);
|
||||
for (ii = 0; ii < CPP_FIRST_USER_TOKEN_SY; ii++)
|
||||
atable->amap[ii] = atable->amap[0];
|
||||
|
||||
// Add single character tokens to the atom table:
|
||||
const char *s = "~!%^&*()-+=|,.<>/?;:[]{}#";
|
||||
char t[2];
|
||||
|
||||
{
|
||||
const char *s = "~!%^&*()-+=|,.<>/?;:[]{}#";
|
||||
char t[2];
|
||||
|
||||
t[1] = '\0';
|
||||
while (*s) {
|
||||
t[0] = *s;
|
||||
AddAtomFixed(atable, t, s[0]);
|
||||
s++;
|
||||
}
|
||||
t[1] = '\0';
|
||||
while (*s) {
|
||||
t[0] = *s;
|
||||
AddAtomFixed(t, s[0]);
|
||||
s++;
|
||||
}
|
||||
|
||||
// Add multiple character scanner tokens :
|
||||
for (int ii = 0; ii < sizeof(tokens)/sizeof(tokens[0]); ii++)
|
||||
AddAtomFixed(tokens[ii].str, tokens[ii].val);
|
||||
|
||||
for (ii = 0; ii < sizeof(tokens)/sizeof(tokens[0]); ii++)
|
||||
AddAtomFixed(atable, tokens[ii].str, tokens[ii].val);
|
||||
|
||||
AddAtom(atable, "<*** end fixed atoms ***>");
|
||||
|
||||
return 1;
|
||||
} // InitAtomTable
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////// Debug Printing Functions: //////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* PrintAtomTable()
|
||||
*
|
||||
*/
|
||||
|
||||
void TPpContext::PrintAtomTable(AtomTable *atable)
|
||||
{
|
||||
int ii;
|
||||
char str[200];
|
||||
|
||||
for (ii = 0; ii < atable->nextFree; ii++) {
|
||||
printf(str, "%d: \"%s\"", ii, &atable->stable.strings[atable->amap[ii]]);
|
||||
}
|
||||
printf(str, "Hash table: size=%d, entries=%d, collisions=",
|
||||
atable->htable.size, atable->htable.entries);
|
||||
for (ii = 0; ii < hashTableMaxCollisions; ii++) {
|
||||
printf(str, " %d", atable->htable.counts[ii]);
|
||||
}
|
||||
|
||||
} // PrintAtomTable
|
||||
|
||||
|
||||
/*
|
||||
* GetStringOfAtom()
|
||||
*
|
||||
*/
|
||||
|
||||
char* TPpContext::GetStringOfAtom(AtomTable *atable, int atom)
|
||||
{
|
||||
char* chr_str;
|
||||
chr_str=&atable->stable.strings[atable->amap[atom]];
|
||||
return chr_str;
|
||||
} // GetStringOfAtom
|
||||
|
||||
/*
|
||||
* FreeAtomTable() - Free the atom table and associated memory
|
||||
*
|
||||
*/
|
||||
|
||||
void TPpContext::FreeAtomTable(AtomTable *atable)
|
||||
{
|
||||
FreeStringTable(&atable->stable);
|
||||
FreeHashTable(&atable->htable);
|
||||
if (atable->amap)
|
||||
free(atable->amap);
|
||||
if (atable->arev)
|
||||
free(atable->arev);
|
||||
atable->amap = NULL;
|
||||
atable->arev = NULL;
|
||||
atable->nextFree = 0;
|
||||
atable->size = 0;
|
||||
} // FreeAtomTable
|
||||
nextAtom = CPP_FIRST_USER_TOKEN_SY;
|
||||
}
|
||||
|
||||
} // end namespace glslang
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue