diff options
Diffstat (limited to 'src/3rdparty/angle/src/compiler/preprocessor')
43 files changed, 7604 insertions, 0 deletions
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/atom.c b/src/3rdparty/angle/src/compiler/preprocessor/atom.c new file mode 100644 index 0000000000..39158d2fa1 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/atom.c @@ -0,0 +1,737 @@ +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ + +// +// atom.c +// + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "common/angleutils.h" +#include "compiler/debug.h" +#include "compiler/preprocessor/slglobals.h" + +#undef malloc +#undef realloc +#undef free + +/////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////// String table: ////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +static const struct { + int val; + const char *str; +} tokens[] = { + { CPP_AND_OP, "&&" }, + { CPP_AND_ASSIGN, "&=" }, + { CPP_SUB_ASSIGN, "-=" }, + { CPP_MOD_ASSIGN, "%=" }, + { CPP_ADD_ASSIGN, "+=" }, + { CPP_DIV_ASSIGN, "/=" }, + { CPP_MUL_ASSIGN, "*=" }, + { CPP_RIGHT_BRACKET, ":>" }, + { CPP_EQ_OP, "==" }, + { CPP_XOR_OP, "^^" }, + { CPP_XOR_ASSIGN, "^=" }, + { CPP_FLOATCONSTANT, "<float-const>" }, + { CPP_GE_OP, ">=" }, + { CPP_RIGHT_OP, ">>" }, + { CPP_RIGHT_ASSIGN, ">>=" }, + { CPP_IDENTIFIER, "<ident>" }, + { CPP_INTCONSTANT, "<int-const>" }, + { CPP_LE_OP, "<=" }, + { CPP_LEFT_OP, "<<" }, + { CPP_LEFT_ASSIGN, "<<=" }, + { CPP_LEFT_BRACKET, "<:" }, + { CPP_LEFT_BRACE, "<%" }, + { CPP_DEC_OP, "--" }, + { CPP_RIGHT_BRACE, "%>" }, + { CPP_NE_OP, "!=" }, + { CPP_OR_OP, "||" }, + { CPP_OR_ASSIGN, "|=" }, + { CPP_INC_OP, "++" }, + { CPP_STRCONSTANT, "<string-const>" }, + { CPP_TYPEIDENTIFIER, "<type-ident>" }, +}; + +/////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////// String table: ////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +#define INIT_STRING_TABLE_SIZE 16384 + +typedef struct StringTable_Rec { + char *strings; + int nextFree; + int size; +} StringTable; + +/* + * InitStringTable() - Initialize the string table. + * + */ + +static int InitStringTable(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. + * + */ + +static void FreeStringTable(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. + * + */ + +static 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. + * + */ + +static 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. + * + */ + +static int AddString(StringTable *stable, const char *s) +{ + int len, loc; + char *str; + + len = (int) strlen(s); + while (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; + stable->size = stable->size*2; + } + loc = stable->nextFree; + strcpy(&stable->strings[loc], s); + stable->nextFree += len + 1; + return loc; +} // AddString + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////// Hash table: /////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +#define INIT_HASH_TABLE_SIZE 2047 +#define HASH_TABLE_MAX_COLLISIONS 3 + +typedef struct HashEntry_Rec { + int index; // String table offset of string representation + int value; // Atom (symbol) value +} HashEntry; + +typedef struct HashTable_Rec { + HashEntry *entry; + int size; + int entries; + int counts[HASH_TABLE_MAX_COLLISIONS + 1]; +} HashTable; + +/* + * InitHashTable() - Initialize the hash table. + * + */ + +static int InitHashTable(HashTable *htable, int fsize) +{ + int ii; + + htable->entry = (HashEntry *) malloc(sizeof(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 <= HASH_TABLE_MAX_COLLISIONS; ii++) + htable->counts[ii] = 0; + return 1; +} // InitHashTable + +/* + * FreeHashTable() - Free the hash table. + * + */ + +static void FreeHashTable(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. + * + */ + +static int Empty(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. + * + */ + +static int Match(HashTable *htable, 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 + + +struct AtomTable_Rec { + StringTable stable; // String table. + HashTable htable; // Hashes string to atom number and token value. Multiple strings can + // have the same token value but each unique string is a unique atom. + int *amap; // Maps atom value to offset in string table. Atoms all map to unique + // strings except for some undefined values in the lower, fixed part + // of the atom table that map to "<undefined>". The lowest 256 atoms + // correspond to single character ASCII values except for alphanumeric + // characters and '_', which can be other tokens. Next come the + // language tokens with their atom values equal to the token value. + // Then come predefined atoms, followed by user specified identifiers. + int *arev; // Reversed atom for symbol table use. + int nextFree; + int size; +}; + +static AtomTable latable = { { NULL, 0, 0 }, { NULL, 0, 0, {0} }, NULL, NULL, 0, 0 }; +AtomTable *atable = &latable; + +static int AddAtomFixed(AtomTable *atable, const char *s, int atom); + +/* + * GrowAtomTable() - Grow the atom table to at least "size" if it's smaller. + * + */ + +static int GrowAtomTable(AtomTable *atable, int size) +{ + int *newmap, *newrev; + + if (atable->size < size) { + if (atable->amap) { + newmap = realloc(atable->amap, sizeof(int)*size); + newrev = realloc(atable->arev, sizeof(int)*size); + } else { + newmap = malloc(sizeof(int)*size); + newrev = malloc(sizeof(int)*size); + atable->size = 0; + } + if (!newmap || !newrev) { + /* failed to grow -- error */ + if (newmap) + atable->amap = newmap; + if (newrev) + atable->arev = 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. + * + */ + +static 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. + * + */ + +static int AllocateAtom(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". + * + */ + +static void SetAtomValue(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. + * + */ + +static int FindHashLoc(AtomTable *atable, const char *s) +{ + int hashloc, hashdelta, count; + int FoundEmptySlot = 0; + int collision[HASH_TABLE_MAX_COLLISIONS + 1]; + + hashloc = HashString(s) % atable->htable.size; + if (!Empty(&atable->htable, hashloc)) { + if (Match(&atable->htable, &atable->stable, s, hashloc)) + return hashloc; + collision[0] = hashloc; + hashdelta = HashString2(s); + count = 0; + while (count < HASH_TABLE_MAX_COLLISIONS) { + 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++; + collision[count] = hashloc; + } + + if (!FoundEmptySlot) { + if (cpp->options.DumpAtomTable) { + int ii; + char str[200]; + snprintf(str, sizeof(str), "*** Hash failed with more than %d collisions. Must increase hash table size. ***", + HASH_TABLE_MAX_COLLISIONS); + CPPShInfoLogMsg(str); + + snprintf(str, sizeof(str), "*** New string \"%s\", hash=%04x, delta=%04x", s, collision[0], hashdelta); + CPPShInfoLogMsg(str); + for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++) { + snprintf(str, sizeof(str), "*** Collides on try %d at hash entry %04x with \"%s\"", + ii + 1, collision[ii], GetAtomString(atable, atable->htable.entry[collision[ii]].value)); + CPPShInfoLogMsg(str); + } + } + return -1; + } else { + atable->htable.counts[count]++; + } + } + return hashloc; +} // FindHashLoc + +/* + * IncreaseHashTableSize() + * + */ + +static int IncreaseHashTableSize(AtomTable *atable) +{ + 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. + */ + +static int 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 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 *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 GetReversedAtom(AtomTable *atable, int atom) +{ + if (atom > 0 && atom < atable->nextFree) { + return atable->arev[atom]; + } else { + return 0; + } +} // GetReversedAtom + +/* + * AddAtom() - Add a string to the atom, hash and string tables if it isn't already there. + * Return it's atom index. + */ + +int AddAtom(AtomTable *atable, const char *s) +{ + int atom; + + atom = LookUpAddString(atable, s); + 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". + */ + +static int AddAtomFixed(AtomTable *atable, const char *s, int atom) +{ + 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 InitAtomTable(AtomTable *atable, int htsize) +{ + unsigned 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; + 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 < 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]; + + t[1] = '\0'; + while (*s) { + t[0] = *s; + AddAtomFixed(atable, t, s[0]); + s++; + } + } + + // Add multiple character scanner tokens : + + for (ii = 0; ii < sizeof(tokens)/sizeof(tokens[0]); ii++) + AddAtomFixed(atable, tokens[ii].str, tokens[ii].val); + + // Add error symbol if running in error mode: + + if (cpp->options.ErrorMode) + AddAtomFixed(atable, "error", ERROR_SY); + + AddAtom(atable, "<*** end fixed atoms ***>"); + + return 1; +} // InitAtomTable + +/////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////// Debug Printing Functions: ////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +/* + * PrintAtomTable() + * + */ + +void PrintAtomTable(AtomTable *atable) +{ + int ii; + char str[200]; + + for (ii = 0; ii < atable->nextFree; ii++) { + snprintf(str, sizeof(str), "%d: \"%s\"", ii, &atable->stable.strings[atable->amap[ii]]); + CPPDebugLogMsg(str); + } + snprintf(str, sizeof(str), "Hash table: size=%d, entries=%d, collisions=", + atable->htable.size, atable->htable.entries); + CPPDebugLogMsg(str); + for (ii = 0; ii < HASH_TABLE_MAX_COLLISIONS; ii++) { + snprintf(str, sizeof(str), " %d", atable->htable.counts[ii]); + CPPDebugLogMsg(str); + } + +} // PrintAtomTable + + +/* + * GetStringOfAtom() + * + */ + +char* 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 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 + +/////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////// End of atom.c /////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/atom.h b/src/3rdparty/angle/src/compiler/preprocessor/atom.h new file mode 100644 index 0000000000..1d84c32515 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/atom.h @@ -0,0 +1,63 @@ +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// atom.h +// + +#if !defined(__ATOM_H) +#define __ATOM_H 1 + +typedef struct AtomTable_Rec AtomTable; + +extern AtomTable *atable; + +int InitAtomTable(AtomTable *atable, int htsize); +void FreeAtomTable(AtomTable *atable); +int AddAtom(AtomTable *atable, const char *s); +void PrintAtomTable(AtomTable *atable); +int LookUpAddString(AtomTable *atable, const char *s); +const char *GetAtomString(AtomTable *atable, int atom); +int GetReversedAtom(AtomTable *atable, int atom); +char* GetStringOfAtom(AtomTable *atable, int atom); +#endif // !defined(__ATOM_H) diff --git a/src/3rdparty/angle/src/compiler/preprocessor/compile.h b/src/3rdparty/angle/src/compiler/preprocessor/compile.h new file mode 100644 index 0000000000..11808531cc --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/compile.h @@ -0,0 +1,100 @@ +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// compile.h +// + +#if !defined(__COMPILE_H) +#define __COMPILE_H 1 + +int InitCPPStruct(void); + +typedef struct Options_Rec{ + const char *profileString; + int ErrorMode; + int Quiet; + + // Debug The Compiler options: + int DumpAtomTable; +} Options; + +#define MAX_IF_NESTING 64 +struct CPPStruct_Rec { + // Public members + SourceLoc *pLastSourceLoc; // Set at the start of each statement by the tree walkers + Options options; // Compile options and parameters + + // Private members + SourceLoc lastSourceLoc; + + // Scanner data: + + SourceLoc *tokenLoc; // Source location of most recent token seen by the scanner + int mostRecentToken; // Most recent token seen by the scanner + InputSrc *currentInput; + int previous_token; + int pastFirstStatement; // used to make sure that #version is the first statement seen in the file, if present + + void *pC; // storing the parseContext of the compile object in cpp. + + // Private members: + SourceLoc ltokenLoc; + int ifdepth; //current #if-#else-#endif nesting in the cpp.c file (pre-processor) + int elsedepth[MAX_IF_NESTING];//Keep a track of #if depth..Max allowed is 64. + int elsetracker; //#if-#else and #endif constructs...Counter. + const char *ErrMsg; + int CompileError; //Indicate compile error when #error, #else,#elif mismatch. + + // + // Globals used to communicate between PaParseStrings() and yy_input()and + // also across the files.(gen_glslang.cpp and scanner.c) + // + int PaWhichStr; // which string we're parsing + const int* PaStrLen; // array of lengths of the PaArgv strings + int PaArgc; // count of strings in the array + const char* const* PaArgv; // our array of strings to parse + unsigned int tokensBeforeEOF : 1; +}; + +#endif // !defined(__COMPILE_H) diff --git a/src/3rdparty/angle/src/compiler/preprocessor/cpp.c b/src/3rdparty/angle/src/compiler/preprocessor/cpp.c new file mode 100644 index 0000000000..8a1076b9df --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/cpp.c @@ -0,0 +1,1118 @@ +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// cpp.c +// + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "common/angleutils.h" +#include "compiler/preprocessor/slglobals.h" + +#if defined(_MSC_VER) +#pragma warning(disable: 4054) +#pragma warning(disable: 4152) +#pragma warning(disable: 4706) +#endif + +static int CPPif(yystypepp * yylvalpp); + +/* Don't use memory.c's replacements, as we clean up properly here */ +#undef malloc +#undef free + +static int bindAtom = 0; +static int constAtom = 0; +static int defaultAtom = 0; +static int defineAtom = 0; +static int definedAtom = 0; +static int elseAtom = 0; +static int elifAtom = 0; +static int endifAtom = 0; +static int ifAtom = 0; +static int ifdefAtom = 0; +static int ifndefAtom = 0; +static int includeAtom = 0; +static int lineAtom = 0; +static int pragmaAtom = 0; +static int texunitAtom = 0; +static int undefAtom = 0; +static int errorAtom = 0; +static int __LINE__Atom = 0; +static int __FILE__Atom = 0; +static int __VERSION__Atom = 0; +static int versionAtom = 0; +static int extensionAtom = 0; + +static Scope *macros = 0; +#define MAX_MACRO_ARGS 64 + +static SourceLoc ifloc; /* outermost #if */ + +int InitCPP(void) +{ + char buffer[64], *t; + const char *f; + + // Add various atoms needed by the CPP line scanner: + bindAtom = LookUpAddString(atable, "bind"); + constAtom = LookUpAddString(atable, "const"); + defaultAtom = LookUpAddString(atable, "default"); + defineAtom = LookUpAddString(atable, "define"); + definedAtom = LookUpAddString(atable, "defined"); + elifAtom = LookUpAddString(atable, "elif"); + elseAtom = LookUpAddString(atable, "else"); + endifAtom = LookUpAddString(atable, "endif"); + ifAtom = LookUpAddString(atable, "if"); + ifdefAtom = LookUpAddString(atable, "ifdef"); + ifndefAtom = LookUpAddString(atable, "ifndef"); + includeAtom = LookUpAddString(atable, "include"); + lineAtom = LookUpAddString(atable, "line"); + pragmaAtom = LookUpAddString(atable, "pragma"); + texunitAtom = LookUpAddString(atable, "texunit"); + undefAtom = LookUpAddString(atable, "undef"); + errorAtom = LookUpAddString(atable, "error"); + __LINE__Atom = LookUpAddString(atable, "__LINE__"); + __FILE__Atom = LookUpAddString(atable, "__FILE__"); + __VERSION__Atom = LookUpAddString(atable, "__VERSION__"); + versionAtom = LookUpAddString(atable, "version"); + extensionAtom = LookUpAddString(atable, "extension"); + macros = NewScopeInPool(mem_CreatePool(0, 0)); + strcpy(buffer, "PROFILE_"); + t = buffer + strlen(buffer); + f = cpp->options.profileString; + while ((isalnum(*f) || *f == '_') && t < buffer + sizeof(buffer) - 1) + *t++ = toupper(*f++); + *t = 0; + + PredefineIntMacro("GL_ES", 1); + PredefineIntMacro("GL_FRAGMENT_PRECISION_HIGH", 1); + + return 1; +} // InitCPP + +int FreeCPP(void) +{ + if (macros) + { + mem_FreePool(macros->pool); + macros = 0; + } + + return 1; +} + +int FinalCPP(void) +{ + if (cpp->ifdepth) + CPPErrorToInfoLog("#if mismatch"); + return 1; +} + +static int CPPdefine(yystypepp * yylvalpp) +{ + int token, name, args[MAX_MACRO_ARGS], argc; + const char *message; + MacroSymbol mac; + Symbol *symb; + SourceLoc dummyLoc; + memset(&mac, 0, sizeof(mac)); + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != CPP_IDENTIFIER) { + CPPErrorToInfoLog("#define"); + return token; + } + name = yylvalpp->sc_ident; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token == '(' && !yylvalpp->sc_int) { + // gather arguments + argc = 0; + do { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (argc == 0 && token == ')') break; + if (token != CPP_IDENTIFIER) { + CPPErrorToInfoLog("#define"); + return token; + } + if (argc < MAX_MACRO_ARGS) + args[argc++] = yylvalpp->sc_ident; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } while (token == ','); + if (token != ')') { + CPPErrorToInfoLog("#define"); + return token; + } + mac.argc = argc; + mac.args = mem_Alloc(macros->pool, argc * sizeof(int)); + memcpy(mac.args, args, argc * sizeof(int)); + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + mac.body = NewTokenStream(GetAtomString(atable, name), macros->pool); + while (token != '\n') { + if (token == '\\') { + CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language"); + return token; + } else if (token <= 0) { // EOF or error + CPPErrorToInfoLog("unexpected end of input in #define preprocessor directive - expected a newline"); + return 0; + } + RecordToken(mac.body, token, yylvalpp); + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + }; + + symb = LookUpSymbol(macros, name); + if (symb) { + if (!symb->details.mac.undef) { + // already defined -- need to make sure they are identical + if (symb->details.mac.argc != mac.argc) goto error; + for (argc=0; argc < mac.argc; argc++) + if (symb->details.mac.args[argc] != mac.args[argc]) + goto error; + RewindTokenStream(symb->details.mac.body); + RewindTokenStream(mac.body); + do { + int old_lval, old_token; + old_token = ReadToken(symb->details.mac.body, yylvalpp); + old_lval = yylvalpp->sc_int; + token = ReadToken(mac.body, yylvalpp); + if (token != old_token || yylvalpp->sc_int != old_lval) { + error: + StoreStr("Macro Redefined"); + StoreStr(GetStringOfAtom(atable,name)); + message=GetStrfromTStr(); + DecLineNumber(); + CPPShInfoLogMsg(message); + IncLineNumber(); + ResetTString(); + break; } + } while (token > 0); + } + //FreeMacro(&symb->details.mac); + } else { + dummyLoc.file = 0; + dummyLoc.line = 0; + symb = AddSymbol(&dummyLoc, macros, name, MACRO_S); + } + symb->details.mac = mac; + return '\n'; +} // CPPdefine + +static int CPPundef(yystypepp * yylvalpp) +{ + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + Symbol *symb; + if(token == '\n'){ + CPPErrorToInfoLog("#undef"); + return token; + } + if (token != CPP_IDENTIFIER) + goto error; + symb = LookUpSymbol(macros, yylvalpp->sc_ident); + if (symb) { + symb->details.mac.undef = 1; + } + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != '\n') { + error: + CPPErrorToInfoLog("#undef"); + } + return token; +} // CPPundef + +/* CPPelse -- skip forward to appropriate spot. This is actually used +** to skip to and #endif after seeing an #else, AND to skip to a #else, +** #elif, or #endif after a #if/#ifdef/#ifndef/#elif test was false +*/ + +static int CPPelse(int matchelse, yystypepp * yylvalpp) +{ + int atom,depth=0; + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + + while (token > 0) { + if (token != '#') { + while (token != '\n') { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token <= 0) { // EOF or error + CPPErrorToInfoLog("unexpected end of input in #else preprocessor directive - expected a newline"); + return 0; + } + } + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + continue; + } + if ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) != CPP_IDENTIFIER) + continue; + atom = yylvalpp->sc_ident; + if (atom == ifAtom || atom == ifdefAtom || atom == ifndefAtom){ + depth++; cpp->ifdepth++; cpp->elsetracker++; + if (cpp->ifdepth > MAX_IF_NESTING) { + CPPErrorToInfoLog("max #if nesting depth exceeded"); + cpp->CompileError = 1; + return 0; + } + // sanity check elsetracker + if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) { + CPPErrorToInfoLog("mismatched #if/#endif statements"); + cpp->CompileError = 1; + return 0; + } + cpp->elsedepth[cpp->elsetracker] = 0; + } + else if (atom == endifAtom) { + if(--depth<0){ + if (cpp->elsetracker) + --cpp->elsetracker; + if (cpp->ifdepth) + --cpp->ifdepth; + break; + } + --cpp->elsetracker; + --cpp->ifdepth; + } + else if (((int)(matchelse) != 0)&& depth==0) { + if (atom == elseAtom ) { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != '\n') { + CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline"); + while (token != '\n') { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token <= 0) { // EOF or error + CPPErrorToInfoLog("unexpected end of input following #else preprocessor directive - expected a newline"); + return 0; + } + } + } + break; + } + else if (atom == elifAtom) { + /* we decrement cpp->ifdepth here, because CPPif will increment + * it and we really want to leave it alone */ + if (cpp->ifdepth){ + --cpp->ifdepth; + --cpp->elsetracker; + } + return CPPif(yylvalpp); + } + } + else if((atom==elseAtom) && (!ChkCorrectElseNesting())){ + CPPErrorToInfoLog("#else after a #else"); + cpp->CompileError=1; + return 0; + } + }; + return token; +} + +enum eval_prec { + MIN_PREC, + COND, LOGOR, LOGAND, OR, XOR, AND, EQUAL, RELATION, SHIFT, ADD, MUL, UNARY, + MAX_PREC +}; + +static int op_logor(int a, int b) { return a || b; } +static int op_logand(int a, int b) { return a && b; } +static int op_or(int a, int b) { return a | b; } +static int op_xor(int a, int b) { return a ^ b; } +static int op_and(int a, int b) { return a & b; } +static int op_eq(int a, int b) { return a == b; } +static int op_ne(int a, int b) { return a != b; } +static int op_ge(int a, int b) { return a >= b; } +static int op_le(int a, int b) { return a <= b; } +static int op_gt(int a, int b) { return a > b; } +static int op_lt(int a, int b) { return a < b; } +static int op_shl(int a, int b) { return a << b; } +static int op_shr(int a, int b) { return a >> b; } +static int op_add(int a, int b) { return a + b; } +static int op_sub(int a, int b) { return a - b; } +static int op_mul(int a, int b) { return a * b; } +static int op_div(int a, int b) { return a / b; } +static int op_mod(int a, int b) { return a % b; } +static int op_pos(int a) { return a; } +static int op_neg(int a) { return -a; } +static int op_cmpl(int a) { return ~a; } +static int op_not(int a) { return !a; } + +struct { + int token, prec, (*op)(int, int); +} binop[] = { + { CPP_OR_OP, LOGOR, op_logor }, + { CPP_AND_OP, LOGAND, op_logand }, + { '|', OR, op_or }, + { '^', XOR, op_xor }, + { '&', AND, op_and }, + { CPP_EQ_OP, EQUAL, op_eq }, + { CPP_NE_OP, EQUAL, op_ne }, + { '>', RELATION, op_gt }, + { CPP_GE_OP, RELATION, op_ge }, + { '<', RELATION, op_lt }, + { CPP_LE_OP, RELATION, op_le }, + { CPP_LEFT_OP, SHIFT, op_shl }, + { CPP_RIGHT_OP, SHIFT, op_shr }, + { '+', ADD, op_add }, + { '-', ADD, op_sub }, + { '*', MUL, op_mul }, + { '/', MUL, op_div }, + { '%', MUL, op_mod }, +}; + +struct { + int token, (*op)(int); +} unop[] = { + { '+', op_pos }, + { '-', op_neg }, + { '~', op_cmpl }, + { '!', op_not }, +}; + +#define ALEN(A) (sizeof(A)/sizeof(A[0])) + +static int eval(int token, int prec, int *res, int *err, yystypepp * yylvalpp) +{ + int i, val; + Symbol *s; + if (token == CPP_IDENTIFIER) { + if (yylvalpp->sc_ident == definedAtom) { + int needclose = 0; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token == '(') { + needclose = 1; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + if (token != CPP_IDENTIFIER) + goto error; + *res = (s = LookUpSymbol(macros, yylvalpp->sc_ident)) + ? !s->details.mac.undef : 0; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (needclose) { + if (token != ')') + goto error; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + } else if (MacroExpand(yylvalpp->sc_ident, yylvalpp)) { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + return eval(token, prec, res, err, yylvalpp); + } else { + goto error; + } + } else if (token == CPP_INTCONSTANT) { + *res = yylvalpp->sc_int; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } else if (token == '(') { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + token = eval(token, MIN_PREC, res, err, yylvalpp); + if (!*err) { + if (token != ')') + goto error; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + } else { + for (i = ALEN(unop) - 1; i >= 0; i--) { + if (unop[i].token == token) + break; + } + if (i >= 0) { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + token = eval(token, UNARY, res, err, yylvalpp); + *res = unop[i].op(*res); + } else { + goto error; + } + } + while (!*err) { + if (token == ')' || token == '\n') break; + for (i = ALEN(binop) - 1; i >= 0; i--) { + if (binop[i].token == token) + break; + } + if (i < 0 || binop[i].prec <= prec) + break; + val = *res; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + token = eval(token, binop[i].prec, res, err, yylvalpp); + + if (binop[i].op == op_div || binop[i].op == op_mod) + { + if (*res == 0) + { + CPPErrorToInfoLog("preprocessor divide or modulo by zero"); + *err = 1; + return token; + } + } + + *res = binop[i].op(val, *res); + } + return token; +error: + CPPErrorToInfoLog("incorrect preprocessor directive"); + *err = 1; + *res = 0; + return token; +} // eval + +static int CPPif(yystypepp * yylvalpp) { + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + int res = 0, err = 0; + + if (!cpp->ifdepth++) + ifloc = *cpp->tokenLoc; + if(cpp->ifdepth > MAX_IF_NESTING){ + CPPErrorToInfoLog("max #if nesting depth exceeded"); + cpp->CompileError = 1; + return 0; + } + cpp->elsetracker++; + // sanity check elsetracker + if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) { + CPPErrorToInfoLog("mismatched #if/#endif statements"); + cpp->CompileError = 1; + return 0; + } + cpp->elsedepth[cpp->elsetracker] = 0; + + token = eval(token, MIN_PREC, &res, &err, yylvalpp); + if (token != '\n') { + CPPWarningToInfoLog("unexpected tokens following #if preprocessor directive - expected a newline"); + while (token != '\n') { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token <= 0) { // EOF or error + CPPErrorToInfoLog("unexpected end of input in #if preprocessor directive - expected a newline"); + return 0; + } + } + } + if (!res && !err) { + token = CPPelse(1, yylvalpp); + } + + return token; +} // CPPif + +static int CPPifdef(int defined, yystypepp * yylvalpp) +{ + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + int name = yylvalpp->sc_ident; + if(++cpp->ifdepth > MAX_IF_NESTING){ + CPPErrorToInfoLog("max #if nesting depth exceeded"); + cpp->CompileError = 1; + return 0; + } + cpp->elsetracker++; + // sanity check elsetracker + if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) { + CPPErrorToInfoLog("mismatched #if/#endif statements"); + cpp->CompileError = 1; + return 0; + } + cpp->elsedepth[cpp->elsetracker] = 0; + + if (token != CPP_IDENTIFIER) { + defined ? CPPErrorToInfoLog("ifdef"):CPPErrorToInfoLog("ifndef"); + } else { + Symbol *s = LookUpSymbol(macros, name); + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != '\n') { + CPPWarningToInfoLog("unexpected tokens following #ifdef preprocessor directive - expected a newline"); + while (token != '\n') { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token <= 0) { // EOF or error + CPPErrorToInfoLog("unexpected end of input in #ifdef preprocessor directive - expected a newline"); + return 0; + } + } + } + if (((s && !s->details.mac.undef) ? 1 : 0) != defined) + token = CPPelse(1, yylvalpp); + } + return token; +} // CPPifdef + +static int CPPline(yystypepp * yylvalpp) +{ + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if(token=='\n'){ + DecLineNumber(); + CPPErrorToInfoLog("#line"); + IncLineNumber(); + return token; + } + else if (token == CPP_INTCONSTANT) { + yylvalpp->sc_int=atoi(yylvalpp->symbol_name); + SetLineNumber(yylvalpp->sc_int); + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + + if (token == CPP_INTCONSTANT) { + yylvalpp->sc_int=atoi(yylvalpp->symbol_name); + SetStringNumber(yylvalpp->sc_int); + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if(token!='\n') + CPPErrorToInfoLog("#line"); + } + else if (token == '\n'){ + return token; + } + else{ + CPPErrorToInfoLog("#line"); + } + } + else{ + CPPErrorToInfoLog("#line"); + } + return token; +} + +static int CPPerror(yystypepp * yylvalpp) { + + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + const char *message; + + while (token != '\n') { + if (token <= 0){ + CPPErrorToInfoLog("unexpected end of input in #error preprocessor directive - expected a newline"); + return 0; + }else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){ + StoreStr(yylvalpp->symbol_name); + }else if(token == CPP_IDENTIFIER || token == CPP_STRCONSTANT){ + StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident)); + }else { + StoreStr(GetStringOfAtom(atable,token)); + } + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + DecLineNumber(); + //store this msg into the shader's information log..set the Compile Error flag!!!! + message=GetStrfromTStr(); + CPPShInfoLogMsg(message); + ResetTString(); + cpp->CompileError=1; + IncLineNumber(); + return '\n'; +}//CPPerror + +static int CPPpragma(yystypepp * yylvalpp) +{ + char SrcStrName[2]; + char** allTokens; + int tokenCount = 0; + int maxTokenCount = 10; + const char* SrcStr; + int i; + + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + + if (token=='\n') { + DecLineNumber(); + CPPErrorToInfoLog("#pragma"); + IncLineNumber(); + return token; + } + + allTokens = (char**)malloc(sizeof(char*) * maxTokenCount); + + while (token != '\n') { + if (tokenCount >= maxTokenCount) { + maxTokenCount *= 2; + allTokens = (char**)realloc((char**)allTokens, sizeof(char*) * maxTokenCount); + } + switch (token) { + case CPP_IDENTIFIER: + SrcStr = GetAtomString(atable, yylvalpp->sc_ident); + allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1); + strcpy(allTokens[tokenCount++], SrcStr); + break; + case CPP_INTCONSTANT: + SrcStr = yylvalpp->symbol_name; + allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1); + strcpy(allTokens[tokenCount++], SrcStr); + break; + case CPP_FLOATCONSTANT: + SrcStr = yylvalpp->symbol_name; + allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1); + strcpy(allTokens[tokenCount++], SrcStr); + break; + case -1: + // EOF + CPPShInfoLogMsg("#pragma directive must end with a newline"); + goto freeMemoryAndReturnToken; + default: + SrcStrName[0] = token; + SrcStrName[1] = '\0'; + allTokens[tokenCount] = (char*)malloc(2); + strcpy(allTokens[tokenCount++], SrcStrName); + } + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + + HandlePragma((const char**)allTokens, tokenCount); + +freeMemoryAndReturnToken: + for (i = 0; i < tokenCount; ++i) { + free (allTokens[i]); + } + free (allTokens); + + return token; +} // CPPpragma + +#define ESSL_VERSION_NUMBER 100 +#define ESSL_VERSION_STRING "100" + +static int CPPversion(yystypepp * yylvalpp) +{ + + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + + if (cpp->pastFirstStatement == 1) + CPPShInfoLogMsg("#version must occur before any other statement in the program"); + + if(token=='\n'){ + DecLineNumber(); + CPPErrorToInfoLog("#version"); + IncLineNumber(); + return token; + } + if (token != CPP_INTCONSTANT) + CPPErrorToInfoLog("#version"); + + yylvalpp->sc_int=atoi(yylvalpp->symbol_name); + //SetVersionNumber(yylvalpp->sc_int); + + if (yylvalpp->sc_int != ESSL_VERSION_NUMBER) + CPPShInfoLogMsg("Version number not supported by ESSL"); + + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + + if (token == '\n'){ + return token; + } + else{ + CPPErrorToInfoLog("#version"); + } + return token; +} // CPPversion + +static int CPPextension(yystypepp * yylvalpp) +{ + + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + char extensionName[MAX_SYMBOL_NAME_LEN + 1]; + + if(token=='\n'){ + DecLineNumber(); + CPPShInfoLogMsg("extension name not specified"); + IncLineNumber(); + return token; + } + + if (token != CPP_IDENTIFIER) + CPPErrorToInfoLog("#extension"); + + strncpy(extensionName, GetAtomString(atable, yylvalpp->sc_ident), MAX_SYMBOL_NAME_LEN); + extensionName[MAX_SYMBOL_NAME_LEN] = '\0'; + + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != ':') { + CPPShInfoLogMsg("':' missing after extension name"); + return token; + } + + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != CPP_IDENTIFIER) { + CPPShInfoLogMsg("behavior for extension not specified"); + return token; + } + + updateExtensionBehavior(extensionName, GetAtomString(atable, yylvalpp->sc_ident)); + + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token == '\n'){ + return token; + } + else{ + CPPErrorToInfoLog("#extension"); + } + return token; +} // CPPextension + +int readCPPline(yystypepp * yylvalpp) +{ + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + const char *message; + + if (token == CPP_IDENTIFIER) { + if (yylvalpp->sc_ident == defineAtom) { + token = CPPdefine(yylvalpp); + } else if (yylvalpp->sc_ident == elseAtom) { + if(ChkCorrectElseNesting()){ + if (!cpp->ifdepth ){ + CPPErrorToInfoLog("#else mismatch"); + cpp->CompileError=1; + return 0; + } + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != '\n') { + CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline"); + while (token != '\n') { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token <= 0) { // EOF or error + CPPErrorToInfoLog("unexpected end of input in #ifdef preprocessor directive - expected a newline"); + return 0; + } + } + } + token = CPPelse(0, yylvalpp); + }else{ + CPPErrorToInfoLog("#else after a #else"); + cpp->ifdepth = 0; + cpp->elsetracker = 0; + cpp->pastFirstStatement = 1; + cpp->CompileError = 1; + return 0; + } + } else if (yylvalpp->sc_ident == elifAtom) { + if (!cpp->ifdepth){ + CPPErrorToInfoLog("#elif mismatch"); + cpp->CompileError=1; + return 0; + } + // this token is really a dont care, but we still need to eat the tokens + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + while (token != '\n') { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token <= 0) { // EOF or error + CPPErrorToInfoLog("unexpect tokens following #elif preprocessor directive - expected a newline"); + cpp->CompileError = 1; + return 0; + } + } + token = CPPelse(0, yylvalpp); + } else if (yylvalpp->sc_ident == endifAtom) { + if (!cpp->ifdepth){ + CPPErrorToInfoLog("#endif mismatch"); + cpp->CompileError=1; + return 0; + } + else + --cpp->ifdepth; + + if (cpp->elsetracker) + --cpp->elsetracker; + + } else if (yylvalpp->sc_ident == ifAtom) { + token = CPPif(yylvalpp); + } else if (yylvalpp->sc_ident == ifdefAtom) { + token = CPPifdef(1, yylvalpp); + } else if (yylvalpp->sc_ident == ifndefAtom) { + token = CPPifdef(0, yylvalpp); + } else if (yylvalpp->sc_ident == lineAtom) { + token = CPPline(yylvalpp); + } else if (yylvalpp->sc_ident == pragmaAtom) { + token = CPPpragma(yylvalpp); + } else if (yylvalpp->sc_ident == undefAtom) { + token = CPPundef(yylvalpp); + } else if (yylvalpp->sc_ident == errorAtom) { + token = CPPerror(yylvalpp); + } else if (yylvalpp->sc_ident == versionAtom) { + token = CPPversion(yylvalpp); + } else if (yylvalpp->sc_ident == extensionAtom) { + token = CPPextension(yylvalpp); + } else { + StoreStr("Invalid Directive"); + StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident)); + message=GetStrfromTStr(); + CPPShInfoLogMsg(message); + ResetTString(); + } + } + while (token != '\n' && token != 0 && token != EOF) { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + + cpp->pastFirstStatement = 1; + + return token; +} // readCPPline + +void FreeMacro(MacroSymbol *s) { + DeleteTokenStream(s->body); +} + +void PredefineIntMacro(const char *name, int value) { + SourceLoc location = {0, 0}; + Symbol *symbol = NULL; + MacroSymbol macro = {0, NULL, NULL, 0, 0}; + yystypepp val = {0, 0.0, 0, {0}}; + int atom = 0; + + macro.body = NewTokenStream(name, macros->pool); + val.sc_int = value; + snprintf(val.symbol_name, MAX_SYMBOL_NAME_LEN+1, "%d", value); + RecordToken(macro.body, CPP_INTCONSTANT, &val); + atom = LookUpAddString(atable, name); + symbol = AddSymbol(&location, macros, atom, MACRO_S); + symbol->details.mac = macro; +} + +static int eof_scan(InputSrc *in, yystypepp * yylvalpp) { return -1; } +static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) { } + +static void PushEofSrc() { + InputSrc *in = malloc(sizeof(InputSrc)); + memset(in, 0, sizeof(InputSrc)); + in->scan = eof_scan; + in->getch = eof_scan; + in->ungetch = noop; + in->prev = cpp->currentInput; + cpp->currentInput = in; +} + +static void PopEofSrc() { + if (cpp->currentInput->scan == eof_scan) { + InputSrc *in = cpp->currentInput; + cpp->currentInput = in->prev; + free(in); + } +} + +static TokenStream *PrescanMacroArg(TokenStream *a, yystypepp * yylvalpp) { + int token; + TokenStream *n; + RewindTokenStream(a); + do { + token = ReadToken(a, yylvalpp); + if (token == CPP_IDENTIFIER && LookUpSymbol(macros, yylvalpp->sc_ident)) + break; + } while (token > 0); + if (token <= 0) return a; + n = NewTokenStream("macro arg", 0); + PushEofSrc(); + ReadFromTokenStream(a, 0, 0); + while ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) > 0) { + if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp->sc_ident, yylvalpp)) + continue; + RecordToken(n, token, yylvalpp); + } + PopEofSrc(); + DeleteTokenStream(a); + return n; +} // PrescanMacroArg + +typedef struct MacroInputSrc { + InputSrc base; + MacroSymbol *mac; + TokenStream **args; +} MacroInputSrc; + +/* macro_scan --- +** return the next token for a macro expanion, handling macro args +*/ +static int macro_scan(MacroInputSrc *in, yystypepp * yylvalpp) { + int i; + int token = ReadToken(in->mac->body, yylvalpp); + if (token == CPP_IDENTIFIER) { + for (i = in->mac->argc-1; i>=0; i--) + if (in->mac->args[i] == yylvalpp->sc_ident) break; + if (i >= 0) { + ReadFromTokenStream(in->args[i], yylvalpp->sc_ident, 0); + return cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + } + if (token > 0) return token; + in->mac->busy = 0; + cpp->currentInput = in->base.prev; + if (in->args) { + for (i=in->mac->argc-1; i>=0; i--) + DeleteTokenStream(in->args[i]); + free(in->args); + } + free(in); + return cpp->currentInput->scan(cpp->currentInput, yylvalpp); +} // macro_scan + +/* MacroExpand +** check an identifier (atom) to see if it a macro that should be expanded. +** If it is, push an InputSrc that will produce the appropriate expansion +** and return TRUE. If not, return FALSE. +*/ + +int MacroExpand(int atom, yystypepp * yylvalpp) +{ + Symbol *sym = LookUpSymbol(macros, atom); + MacroInputSrc *in; + int i,j, token, depth=0; + const char *message; + if (atom == __LINE__Atom) { + yylvalpp->sc_int = GetLineNumber(); + snprintf(yylvalpp->symbol_name, MAX_SYMBOL_NAME_LEN+1, "%d", yylvalpp->sc_int); + UngetToken(CPP_INTCONSTANT, yylvalpp); + return 1; + } + if (atom == __FILE__Atom) { + yylvalpp->sc_int = GetStringNumber(); + snprintf(yylvalpp->symbol_name, MAX_SYMBOL_NAME_LEN+1, "%d", yylvalpp->sc_int); + UngetToken(CPP_INTCONSTANT, yylvalpp); + return 1; + } + if (atom == __VERSION__Atom) { + strcpy(yylvalpp->symbol_name,ESSL_VERSION_STRING); + yylvalpp->sc_int = atoi(yylvalpp->symbol_name); + UngetToken(CPP_INTCONSTANT, yylvalpp); + return 1; + } + if (!sym || sym->details.mac.undef) return 0; + if (sym->details.mac.busy) return 0; // no recursive expansions + in = malloc(sizeof(*in)); + memset(in, 0, sizeof(*in)); + in->base.scan = (void *)macro_scan; + in->base.line = cpp->currentInput->line; + in->base.name = cpp->currentInput->name; + in->mac = &sym->details.mac; + if (sym->details.mac.args) { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != '(') { + UngetToken(token, yylvalpp); + yylvalpp->sc_ident = atom; + return 0; + } + in->args = malloc(in->mac->argc * sizeof(TokenStream *)); + for (i=0; i<in->mac->argc; i++) + in->args[i] = NewTokenStream("macro arg", 0); + i=0;j=0; + do{ + depth = 0; + while(1) { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token <= 0) { + StoreStr("EOF in Macro "); + StoreStr(GetStringOfAtom(atable,atom)); + message=GetStrfromTStr(); + CPPShInfoLogMsg(message); + ResetTString(); + return 1; + } + if((in->mac->argc==0) && (token!=')')) break; + if (depth == 0 && (token == ',' || token == ')')) break; + if (token == '(') depth++; + if (token == ')') depth--; + RecordToken(in->args[i], token, yylvalpp); + j=1; + } + if (token == ')') { + if((in->mac->argc==1) &&j==0) + break; + i++; + break; + } + i++; + }while(i < in->mac->argc); + + if (i < in->mac->argc) { + StoreStr("Too few args in Macro "); + StoreStr(GetStringOfAtom(atable,atom)); + message=GetStrfromTStr(); + CPPShInfoLogMsg(message); + ResetTString(); + } else if (token != ')') { + depth=0; + while (token >= 0 && (depth > 0 || token != ')')) { + if (token == ')') depth--; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token == '(') depth++; + } + + if (token <= 0) { + StoreStr("EOF in Macro "); + StoreStr(GetStringOfAtom(atable,atom)); + message=GetStrfromTStr(); + CPPShInfoLogMsg(message); + ResetTString(); + return 1; + } + StoreStr("Too many args in Macro "); + StoreStr(GetStringOfAtom(atable,atom)); + message=GetStrfromTStr(); + CPPShInfoLogMsg(message); + ResetTString(); + } + for (i=0; i<in->mac->argc; i++) { + in->args[i] = PrescanMacroArg(in->args[i], yylvalpp); + } + } +#if 0 + printf(" <%s:%d>found macro %s\n", GetAtomString(atable, loc.file), + loc.line, GetAtomString(atable, atom)); + for (i=0; i<in->mac->argc; i++) { + printf("\targ %s = '", GetAtomString(atable, in->mac->args[i])); + DumpTokenStream(stdout, in->args[i]); + printf("'\n"); + } +#endif + /*retain the input source*/ + in->base.prev = cpp->currentInput; + sym->details.mac.busy = 1; + RewindTokenStream(sym->details.mac.body); + cpp->currentInput = &in->base; + return 1; +} // MacroExpand + +int ChkCorrectElseNesting(void) +{ + // sanity check to make sure elsetracker is in a valid range + if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) { + return 0; + } + + if (cpp->elsedepth[cpp->elsetracker] == 0) { + cpp->elsedepth[cpp->elsetracker] = 1; + return 1; + } + return 0; +} + + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/cpp.h b/src/3rdparty/angle/src/compiler/preprocessor/cpp.h new file mode 100644 index 0000000000..802e23ef07 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/cpp.h @@ -0,0 +1,86 @@ +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// cpp.h +// + +#if !defined(__CPP_H) +#define __CPP_H 1 + +#include "compiler/preprocessor/parser.h" +#include "compiler/preprocessor/tokens.h" + +int InitCPP(void); +int FinalCPP(void); +int readCPPline(yystypepp * yylvalpp); +int MacroExpand(int atom, yystypepp * yylvalpp); +int ChkCorrectElseNesting(void); + +typedef struct MacroSymbol { + int argc; + int *args; + TokenStream *body; + unsigned busy:1; + unsigned undef:1; +} MacroSymbol; + +void FreeMacro(MacroSymbol *); +void PredefineIntMacro(const char *name, int value); + +void CPPDebugLogMsg(const char *msg); // Prints information into debug log +void CPPShInfoLogMsg(const char*); // Store cpp Err Msg into Sh.Info.Log +void CPPWarningToInfoLog(const char *msg); // Prints warning messages into info log +void HandlePragma(const char**, int numTokens); // #pragma directive container. +void ResetTString(void); // #error Message as TString. +void CPPErrorToInfoLog(const char*); // Stick all cpp errors into Sh.Info.log. +void StoreStr(const char*); // Store the TString in Parse Context. +void SetLineNumber(int); // Set line number. +void SetStringNumber(int); // Set string number. +int GetLineNumber(void); // Get the current String Number. +int GetStringNumber(void); // Get the current String Number. +const char* GetStrfromTStr(void); // Convert TString to String. +void updateExtensionBehavior(const char* extName, const char* behavior); +int FreeCPP(void); + +#endif // !(defined(__CPP_H) diff --git a/src/3rdparty/angle/src/compiler/preprocessor/cppstruct.c b/src/3rdparty/angle/src/compiler/preprocessor/cppstruct.c new file mode 100644 index 0000000000..58cff31091 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/cppstruct.c @@ -0,0 +1,152 @@ +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// cppstruct.c +// + +#include <stdio.h> +#include <stdlib.h> + +#include "compiler/preprocessor/slglobals.h" + +CPPStruct *cpp = NULL; +static int refCount = 0; + +int InitPreprocessor(void); +int ResetPreprocessor(void); +int FreeCPPStruct(void); +int FinalizePreprocessor(void); + +/* + * InitCPPStruct() - Initilaize the CPP structure. + * + */ + +int InitCPPStruct(void) +{ + int len; + char *p; + + cpp = (CPPStruct *) malloc(sizeof(CPPStruct)); + if (cpp == NULL) + return 0; + + refCount++; + + // Initialize public members: + cpp->pLastSourceLoc = &cpp->lastSourceLoc; + + p = (char *) &cpp->options; + len = sizeof(cpp->options); + while (--len >= 0) + p[len] = 0; + + ResetPreprocessor(); + return 1; +} // InitCPPStruct + +int ResetPreprocessor(void) +{ + // Initialize private members: + + cpp->lastSourceLoc.file = 0; + cpp->lastSourceLoc.line = 0; + cpp->pC = 0; + cpp->CompileError = 0; + cpp->ifdepth = 0; + for(cpp->elsetracker = 0; cpp->elsetracker < MAX_IF_NESTING; cpp->elsetracker++) + cpp->elsedepth[cpp->elsetracker] = 0; + cpp->elsetracker = 0; + cpp->tokensBeforeEOF = 0; + return 1; +} + +//Intializing the Preprocessor. + +int InitPreprocessor(void) +{ + # define CPP_STUFF true + # ifdef CPP_STUFF + FreeCPPStruct(); + InitCPPStruct(); + cpp->options.Quiet = 1; + cpp->options.profileString = "generic"; + if (!InitAtomTable(atable, 0)) + return 1; + if (!InitScanner(cpp)) + return 1; + # endif + return 0; +} + +//FreeCPPStruct() - Free the CPP structure. + +int FreeCPPStruct(void) +{ + if (refCount) + { + free(cpp); + refCount--; + } + + return 1; +} + +//Finalizing the Preprocessor. + +int FinalizePreprocessor(void) +{ + # define CPP_STUFF true + # ifdef CPP_STUFF + FreeAtomTable(atable); + FreeCPPStruct(); + FreeScanner(); + # endif + return 0; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////// End of cppstruct.c ////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/3rdparty/angle/src/compiler/preprocessor/length_limits.h b/src/3rdparty/angle/src/compiler/preprocessor/length_limits.h new file mode 100644 index 0000000000..4f1f71319f --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/length_limits.h @@ -0,0 +1,21 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// +// length_limits.h +// + +#if !defined(__LENGTH_LIMITS_H) +#define __LENGTH_LIMITS_H 1 + +// These constants are factored out from the rest of the headers to +// make it easier to reference them from the compiler sources. + +// These lengths do not include the NULL terminator. +#define MAX_SYMBOL_NAME_LEN 256 +#define MAX_STRING_LEN 511 + +#endif // !(defined(__LENGTH_LIMITS_H) diff --git a/src/3rdparty/angle/src/compiler/preprocessor/memory.c b/src/3rdparty/angle/src/compiler/preprocessor/memory.c new file mode 100644 index 0000000000..029521a559 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/memory.c @@ -0,0 +1,158 @@ +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#ifndef _MSC_VER +#include <stdint.h> +#endif + +#include "compiler/preprocessor/memory.h" + +#if defined(_MSC_VER) +#pragma warning(disable: 4706) +#endif + +// default alignment and chunksize, if called with 0 arguments +#define CHUNKSIZE (64*1024) +#define ALIGN 8 + +// we need to call the `real' malloc and free, not our replacements +#undef malloc +#undef free + +struct chunk { + struct chunk *next; +}; + +struct cleanup { + struct cleanup *next; + void (*fn)(void *); + void *arg; +}; + +struct MemoryPool_rec { + struct chunk *next; + uintptr_t free, end; + size_t chunksize; + uintptr_t alignmask; + struct cleanup *cleanup; +}; + +MemoryPool *mem_CreatePool(size_t chunksize, unsigned int align) +{ + MemoryPool *pool; + + if (align == 0) align = ALIGN; + if (chunksize == 0) chunksize = CHUNKSIZE; + if (align & (align-1)) return 0; + if (chunksize < sizeof(MemoryPool)) return 0; + if (chunksize & (align-1)) return 0; + if (!(pool = malloc(chunksize))) return 0; + pool->next = 0; + pool->chunksize = chunksize; + pool->alignmask = (uintptr_t)(align)-1; + pool->free = ((uintptr_t)(pool + 1) + pool->alignmask) & ~pool->alignmask; + pool->end = (uintptr_t)pool + chunksize; + pool->cleanup = 0; + return pool; +} + +void mem_FreePool(MemoryPool *pool) +{ + struct cleanup *cleanup; + struct chunk *p, *next; + + for (cleanup = pool->cleanup; cleanup; cleanup = cleanup->next) { + cleanup->fn(cleanup->arg); + } + for (p = (struct chunk *)pool; p; p = next) { + next = p->next; + free(p); + } +} + +void *mem_Alloc(MemoryPool *pool, size_t size) +{ + struct chunk *ch; + void *rv = (void *)pool->free; + size = (size + pool->alignmask) & ~pool->alignmask; + if (size <= 0) size = pool->alignmask; + pool->free += size; + if (pool->free > pool->end || pool->free < (uintptr_t)rv) { + size_t minreq = (size + sizeof(struct chunk) + pool->alignmask) + & ~pool->alignmask; + pool->free = (uintptr_t)rv; + if (minreq >= pool->chunksize) { + // request size is too big for the chunksize, so allocate it as + // a single chunk of the right size + ch = malloc(minreq); + if (!ch) return 0; + } else { + ch = malloc(pool->chunksize); + if (!ch) return 0; + pool->free = (uintptr_t)ch + minreq; + pool->end = (uintptr_t)ch + pool->chunksize; + } + ch->next = pool->next; + pool->next = ch; + rv = (void *)(((uintptr_t)(ch+1) + pool->alignmask) & ~pool->alignmask); + } + return rv; +} + +int mem_AddCleanup(MemoryPool *pool, void (*fn)(void *), void *arg) { + struct cleanup *cleanup; + + pool->free = (pool->free + sizeof(void *) - 1) & ~(sizeof(void *)-1); + cleanup = mem_Alloc(pool, sizeof(struct cleanup)); + if (!cleanup) return -1; + cleanup->next = pool->cleanup; + cleanup->fn = fn; + cleanup->arg = arg; + pool->cleanup = cleanup; + return 0; +} diff --git a/src/3rdparty/angle/src/compiler/preprocessor/memory.h b/src/3rdparty/angle/src/compiler/preprocessor/memory.h new file mode 100644 index 0000000000..5fcadb32f6 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/memory.h @@ -0,0 +1,58 @@ +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +#ifndef __MEMORY_H +#define __MEMORY_H + +#include <stddef.h> + +typedef struct MemoryPool_rec MemoryPool; + +extern MemoryPool *mem_CreatePool(size_t chunksize, unsigned int align); +extern void mem_FreePool(MemoryPool *); +extern void *mem_Alloc(MemoryPool *p, size_t size); +extern void *mem_Realloc(MemoryPool *p, void *old, size_t oldsize, size_t newsize); +extern int mem_AddCleanup(MemoryPool *p, void (*fn)(void *), void *arg); + +#endif /* __MEMORY_H */ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Diagnostics.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/Diagnostics.cpp new file mode 100644 index 0000000000..3f50dfc98a --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/Diagnostics.cpp @@ -0,0 +1,127 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "Diagnostics.h" + +#include <cassert> + +namespace pp +{ + +Diagnostics::~Diagnostics() +{ +} + +void Diagnostics::report(ID id, + const SourceLocation& loc, + const std::string& text) +{ + // TODO(alokp): Keep a count of errors and warnings. + print(id, loc, text); +} + +Diagnostics::Severity Diagnostics::severity(ID id) +{ + if ((id > ERROR_BEGIN) && (id < ERROR_END)) + return ERROR; + + if ((id > WARNING_BEGIN) && (id < WARNING_END)) + return WARNING; + + assert(false); + return ERROR; +} + +std::string Diagnostics::message(ID id) +{ + switch (id) + { + // Errors begin. + case INTERNAL_ERROR: + return "internal error"; + case OUT_OF_MEMORY: + return "out of memory"; + case INVALID_CHARACTER: + return "invalid character"; + case INVALID_NUMBER: + return "invalid number"; + case INTEGER_OVERFLOW: + return "integer overflow"; + case FLOAT_OVERFLOW: + return "float overflow"; + case TOKEN_TOO_LONG: + return "token too long"; + case INVALID_EXPRESSION: + return "invalid expression"; + case DIVISION_BY_ZERO: + return "division by zero"; + case EOF_IN_COMMENT: + return "unexpected end of file found in comment"; + case UNEXPECTED_TOKEN: + return "unexpected token"; + case DIRECTIVE_INVALID_NAME: + return "invalid directive name"; + case MACRO_NAME_RESERVED: + return "macro name is reserved"; + case MACRO_REDEFINED: + return "macro redefined"; + case MACRO_PREDEFINED_REDEFINED: + return "predefined macro redefined"; + case MACRO_PREDEFINED_UNDEFINED: + return "predefined macro undefined"; + case MACRO_UNTERMINATED_INVOCATION: + return "unterminated macro invocation"; + case MACRO_TOO_FEW_ARGS: + return "Not enough arguments for macro"; + case MACRO_TOO_MANY_ARGS: + return "Too many arguments for macro"; + case CONDITIONAL_ENDIF_WITHOUT_IF: + return "unexpected #endif found without a matching #if"; + case CONDITIONAL_ELSE_WITHOUT_IF: + return "unexpected #else found without a matching #if"; + case CONDITIONAL_ELSE_AFTER_ELSE: + return "unexpected #else found after another #else"; + case CONDITIONAL_ELIF_WITHOUT_IF: + return "unexpected #elif found without a matching #if"; + case CONDITIONAL_ELIF_AFTER_ELSE: + return "unexpected #elif found after #else"; + case CONDITIONAL_UNTERMINATED: + return "unexpected end of file found in conditional block"; + case INVALID_EXTENSION_NAME: + return "invalid extension name"; + case INVALID_EXTENSION_BEHAVIOR: + return "invalid extension behavior"; + case INVALID_EXTENSION_DIRECTIVE: + return "invalid extension directive"; + case INVALID_VERSION_NUMBER: + return "invalid version number"; + case INVALID_VERSION_DIRECTIVE: + return "invalid version directive"; + case VERSION_NOT_FIRST_STATEMENT: + return "#version directive must occur before anything else, " + "except for comments and white space"; + case INVALID_LINE_NUMBER: + return "invalid line number"; + case INVALID_FILE_NUMBER: + return "invalid file number"; + case INVALID_LINE_DIRECTIVE: + return "invalid line directive"; + // Errors end. + // Warnings begin. + case EOF_IN_DIRECTIVE: + return "unexpected end of file found in directive"; + case CONDITIONAL_UNEXPECTED_TOKEN: + return "unexpected token after conditional expression"; + case UNRECOGNIZED_PRAGMA: + return "unrecognized pragma"; + // Warnings end. + default: + assert(false); + return ""; + } +} + +} // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Diagnostics.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Diagnostics.h new file mode 100644 index 0000000000..07bc411846 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/Diagnostics.h @@ -0,0 +1,87 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_DIAGNOSTICS_H_ +#define COMPILER_PREPROCESSOR_DIAGNOSTICS_H_ + +#include <string> + +namespace pp +{ + +struct SourceLocation; + +// Base class for reporting diagnostic messages. +// Derived classes are responsible for formatting and printing the messages. +class Diagnostics +{ + public: + enum Severity + { + ERROR, + WARNING + }; + enum ID + { + ERROR_BEGIN, + INTERNAL_ERROR, + OUT_OF_MEMORY, + INVALID_CHARACTER, + INVALID_NUMBER, + INTEGER_OVERFLOW, + FLOAT_OVERFLOW, + TOKEN_TOO_LONG, + INVALID_EXPRESSION, + DIVISION_BY_ZERO, + EOF_IN_COMMENT, + UNEXPECTED_TOKEN, + DIRECTIVE_INVALID_NAME, + MACRO_NAME_RESERVED, + MACRO_REDEFINED, + MACRO_PREDEFINED_REDEFINED, + MACRO_PREDEFINED_UNDEFINED, + MACRO_UNTERMINATED_INVOCATION, + MACRO_TOO_FEW_ARGS, + MACRO_TOO_MANY_ARGS, + CONDITIONAL_ENDIF_WITHOUT_IF, + CONDITIONAL_ELSE_WITHOUT_IF, + CONDITIONAL_ELSE_AFTER_ELSE, + CONDITIONAL_ELIF_WITHOUT_IF, + CONDITIONAL_ELIF_AFTER_ELSE, + CONDITIONAL_UNTERMINATED, + INVALID_EXTENSION_NAME, + INVALID_EXTENSION_BEHAVIOR, + INVALID_EXTENSION_DIRECTIVE, + INVALID_VERSION_NUMBER, + INVALID_VERSION_DIRECTIVE, + VERSION_NOT_FIRST_STATEMENT, + INVALID_LINE_NUMBER, + INVALID_FILE_NUMBER, + INVALID_LINE_DIRECTIVE, + ERROR_END, + + WARNING_BEGIN, + EOF_IN_DIRECTIVE, + CONDITIONAL_UNEXPECTED_TOKEN, + UNRECOGNIZED_PRAGMA, + WARNING_END + }; + + virtual ~Diagnostics(); + + void report(ID id, const SourceLocation& loc, const std::string& text); + + protected: + Severity severity(ID id); + std::string message(ID id); + + virtual void print(ID id, + const SourceLocation& loc, + const std::string& text) = 0; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_DIAGNOSTICS_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveHandler.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveHandler.cpp new file mode 100644 index 0000000000..ca91e1c71b --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveHandler.cpp @@ -0,0 +1,16 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "DirectiveHandler.h" + +namespace pp +{ + +DirectiveHandler::~DirectiveHandler() +{ +} + +} // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveHandler.h b/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveHandler.h new file mode 100644 index 0000000000..2aaeec2818 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveHandler.h @@ -0,0 +1,43 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_ +#define COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_ + +#include <string> + +namespace pp +{ + +struct SourceLocation; + +// Base class for handling directives. +// Preprocessor uses this class to notify the clients about certain +// preprocessor directives. Derived classes are responsible for +// handling them in an appropriate manner. +class DirectiveHandler +{ + public: + virtual ~DirectiveHandler(); + + virtual void handleError(const SourceLocation& loc, + const std::string& msg) = 0; + + // Handle pragma of form: #pragma name[(value)] + virtual void handlePragma(const SourceLocation& loc, + const std::string& name, + const std::string& value) = 0; + + virtual void handleExtension(const SourceLocation& loc, + const std::string& name, + const std::string& behavior) = 0; + + virtual void handleVersion(const SourceLocation& loc, + int version) = 0; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveParser.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveParser.cpp new file mode 100644 index 0000000000..f2e42d06bf --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveParser.cpp @@ -0,0 +1,932 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "DirectiveParser.h" + +#include <cassert> +#include <cstdlib> +#include <sstream> + +#include "Diagnostics.h" +#include "DirectiveHandler.h" +#include "ExpressionParser.h" +#include "MacroExpander.h" +#include "Token.h" +#include "Tokenizer.h" + +namespace { +enum DirectiveType +{ + DIRECTIVE_NONE, + DIRECTIVE_DEFINE, + DIRECTIVE_UNDEF, + DIRECTIVE_IF, + DIRECTIVE_IFDEF, + DIRECTIVE_IFNDEF, + DIRECTIVE_ELSE, + DIRECTIVE_ELIF, + DIRECTIVE_ENDIF, + DIRECTIVE_ERROR, + DIRECTIVE_PRAGMA, + DIRECTIVE_EXTENSION, + DIRECTIVE_VERSION, + DIRECTIVE_LINE +}; +} // namespace + +static DirectiveType getDirective(const pp::Token* token) +{ + static const std::string kDirectiveDefine("define"); + static const std::string kDirectiveUndef("undef"); + static const std::string kDirectiveIf("if"); + static const std::string kDirectiveIfdef("ifdef"); + static const std::string kDirectiveIfndef("ifndef"); + static const std::string kDirectiveElse("else"); + static const std::string kDirectiveElif("elif"); + static const std::string kDirectiveEndif("endif"); + static const std::string kDirectiveError("error"); + static const std::string kDirectivePragma("pragma"); + static const std::string kDirectiveExtension("extension"); + static const std::string kDirectiveVersion("version"); + static const std::string kDirectiveLine("line"); + + if (token->type != pp::Token::IDENTIFIER) + return DIRECTIVE_NONE; + + if (token->text == kDirectiveDefine) + return DIRECTIVE_DEFINE; + else if (token->text == kDirectiveUndef) + return DIRECTIVE_UNDEF; + else if (token->text == kDirectiveIf) + return DIRECTIVE_IF; + else if (token->text == kDirectiveIfdef) + return DIRECTIVE_IFDEF; + else if (token->text == kDirectiveIfndef) + return DIRECTIVE_IFNDEF; + else if (token->text == kDirectiveElse) + return DIRECTIVE_ELSE; + else if (token->text == kDirectiveElif) + return DIRECTIVE_ELIF; + else if (token->text == kDirectiveEndif) + return DIRECTIVE_ENDIF; + else if (token->text == kDirectiveError) + return DIRECTIVE_ERROR; + else if (token->text == kDirectivePragma) + return DIRECTIVE_PRAGMA; + else if (token->text == kDirectiveExtension) + return DIRECTIVE_EXTENSION; + else if (token->text == kDirectiveVersion) + return DIRECTIVE_VERSION; + else if (token->text == kDirectiveLine) + return DIRECTIVE_LINE; + + return DIRECTIVE_NONE; +} + +static bool isConditionalDirective(DirectiveType directive) +{ + switch (directive) + { + case DIRECTIVE_IF: + case DIRECTIVE_IFDEF: + case DIRECTIVE_IFNDEF: + case DIRECTIVE_ELSE: + case DIRECTIVE_ELIF: + case DIRECTIVE_ENDIF: + return true; + default: + return false; + } +} + +// Returns true if the token represents End Of Directive. +static bool isEOD(const pp::Token* token) +{ + return (token->type == '\n') || (token->type == pp::Token::LAST); +} + +static void skipUntilEOD(pp::Lexer* lexer, pp::Token* token) +{ + while(!isEOD(token)) + { + lexer->lex(token); + } +} + +static bool isMacroNameReserved(const std::string& name) +{ + // Names prefixed with "GL_" are reserved. + if (name.substr(0, 3) == "GL_") + return true; + + // Names containing two consecutive underscores are reserved. + if (name.find("__") != std::string::npos) + return true; + + return false; +} + +static bool isMacroPredefined(const std::string& name, + const pp::MacroSet& macroSet) +{ + pp::MacroSet::const_iterator iter = macroSet.find(name); + return iter != macroSet.end() ? iter->second.predefined : false; +} + +namespace pp +{ + +class DefinedParser : public Lexer +{ + public: + DefinedParser(Lexer* lexer, + const MacroSet* macroSet, + Diagnostics* diagnostics) : + mLexer(lexer), + mMacroSet(macroSet), + mDiagnostics(diagnostics) + { + } + + protected: + virtual void lex(Token* token) + { + static const std::string kDefined("defined"); + + mLexer->lex(token); + if (token->type != Token::IDENTIFIER) + return; + if (token->text != kDefined) + return; + + bool paren = false; + mLexer->lex(token); + if (token->type == '(') + { + paren = true; + mLexer->lex(token); + } + + if (token->type != Token::IDENTIFIER) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + skipUntilEOD(mLexer, token); + return; + } + MacroSet::const_iterator iter = mMacroSet->find(token->text); + std::string expression = iter != mMacroSet->end() ? "1" : "0"; + + if (paren) + { + mLexer->lex(token); + if (token->type != ')') + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + skipUntilEOD(mLexer, token); + return; + } + } + + // We have a valid defined operator. + // Convert the current token into a CONST_INT token. + token->type = Token::CONST_INT; + token->text = expression; + } + + private: + Lexer* mLexer; + const MacroSet* mMacroSet; + Diagnostics* mDiagnostics; +}; + +DirectiveParser::DirectiveParser(Tokenizer* tokenizer, + MacroSet* macroSet, + Diagnostics* diagnostics, + DirectiveHandler* directiveHandler) : + mPastFirstStatement(false), + mTokenizer(tokenizer), + mMacroSet(macroSet), + mDiagnostics(diagnostics), + mDirectiveHandler(directiveHandler) +{ +} + +void DirectiveParser::lex(Token* token) +{ + do + { + mTokenizer->lex(token); + + if (token->type == Token::PP_HASH) + { + parseDirective(token); + mPastFirstStatement = true; + } + + if (token->type == Token::LAST) + { + if (!mConditionalStack.empty()) + { + const ConditionalBlock& block = mConditionalStack.back(); + mDiagnostics->report(Diagnostics::CONDITIONAL_UNTERMINATED, + block.location, block.type); + } + break; + } + + } while (skipping() || (token->type == '\n')); + + mPastFirstStatement = true; +} + +void DirectiveParser::parseDirective(Token* token) +{ + assert(token->type == Token::PP_HASH); + + mTokenizer->lex(token); + if (isEOD(token)) + { + // Empty Directive. + return; + } + + DirectiveType directive = getDirective(token); + + // While in an excluded conditional block/group, + // we only parse conditional directives. + if (skipping() && !isConditionalDirective(directive)) + { + skipUntilEOD(mTokenizer, token); + return; + } + + switch(directive) + { + case DIRECTIVE_NONE: + mDiagnostics->report(Diagnostics::DIRECTIVE_INVALID_NAME, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + break; + case DIRECTIVE_DEFINE: + parseDefine(token); + break; + case DIRECTIVE_UNDEF: + parseUndef(token); + break; + case DIRECTIVE_IF: + parseIf(token); + break; + case DIRECTIVE_IFDEF: + parseIfdef(token); + break; + case DIRECTIVE_IFNDEF: + parseIfndef(token); + break; + case DIRECTIVE_ELSE: + parseElse(token); + break; + case DIRECTIVE_ELIF: + parseElif(token); + break; + case DIRECTIVE_ENDIF: + parseEndif(token); + break; + case DIRECTIVE_ERROR: + parseError(token); + break; + case DIRECTIVE_PRAGMA: + parsePragma(token); + break; + case DIRECTIVE_EXTENSION: + parseExtension(token); + break; + case DIRECTIVE_VERSION: + parseVersion(token); + break; + case DIRECTIVE_LINE: + parseLine(token); + break; + default: + assert(false); + break; + } + + skipUntilEOD(mTokenizer, token); + if (token->type == Token::LAST) + { + mDiagnostics->report(Diagnostics::EOF_IN_DIRECTIVE, + token->location, token->text); + } +} + +void DirectiveParser::parseDefine(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_DEFINE); + + mTokenizer->lex(token); + if (token->type != Token::IDENTIFIER) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + return; + } + if (isMacroPredefined(token->text, *mMacroSet)) + { + mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_REDEFINED, + token->location, token->text); + return; + } + if (isMacroNameReserved(token->text)) + { + mDiagnostics->report(Diagnostics::MACRO_NAME_RESERVED, + token->location, token->text); + return; + } + + Macro macro; + macro.type = Macro::kTypeObj; + macro.name = token->text; + + mTokenizer->lex(token); + if (token->type == '(' && !token->hasLeadingSpace()) + { + // Function-like macro. Collect arguments. + macro.type = Macro::kTypeFunc; + do { + mTokenizer->lex(token); + if (token->type != Token::IDENTIFIER) + break; + macro.parameters.push_back(token->text); + + mTokenizer->lex(token); // Get ','. + } while (token->type == ','); + + if (token->type != ')') + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, + token->text); + return; + } + mTokenizer->lex(token); // Get ')'. + } + + while ((token->type != '\n') && (token->type != Token::LAST)) + { + // Reset the token location because it is unnecessary in replacement + // list. Resetting it also allows us to reuse Token::equals() to + // compare macros. + token->location = SourceLocation(); + macro.replacements.push_back(*token); + mTokenizer->lex(token); + } + if (!macro.replacements.empty()) + { + // Whitespace preceding the replacement list is not considered part of + // the replacement list for either form of macro. + macro.replacements.front().setHasLeadingSpace(false); + } + + // Check for macro redefinition. + MacroSet::const_iterator iter = mMacroSet->find(macro.name); + if (iter != mMacroSet->end() && !macro.equals(iter->second)) + { + mDiagnostics->report(Diagnostics::MACRO_REDEFINED, + token->location, + macro.name); + return; + } + mMacroSet->insert(std::make_pair(macro.name, macro)); +} + +void DirectiveParser::parseUndef(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_UNDEF); + + mTokenizer->lex(token); + if (token->type != Token::IDENTIFIER) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + return; + } + + MacroSet::iterator iter = mMacroSet->find(token->text); + if (iter != mMacroSet->end()) + { + if (iter->second.predefined) + { + mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_UNDEFINED, + token->location, token->text); + } + else + { + mMacroSet->erase(iter); + } + } + + mTokenizer->lex(token); +} + +void DirectiveParser::parseIf(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_IF); + parseConditionalIf(token); +} + +void DirectiveParser::parseIfdef(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_IFDEF); + parseConditionalIf(token); +} + +void DirectiveParser::parseIfndef(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_IFNDEF); + parseConditionalIf(token); +} + +void DirectiveParser::parseElse(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_ELSE); + + if (mConditionalStack.empty()) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_WITHOUT_IF, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return; + } + + ConditionalBlock& block = mConditionalStack.back(); + if (block.skipBlock) + { + // No diagnostics. Just skip the whole line. + skipUntilEOD(mTokenizer, token); + return; + } + if (block.foundElseGroup) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_AFTER_ELSE, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return; + } + + block.foundElseGroup = true; + block.skipGroup = block.foundValidGroup; + block.foundValidGroup = true; + + // Warn if there are extra tokens after #else. + mTokenizer->lex(token); + if (!isEOD(token)) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + } +} + +void DirectiveParser::parseElif(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_ELIF); + + if (mConditionalStack.empty()) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_WITHOUT_IF, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return; + } + + ConditionalBlock& block = mConditionalStack.back(); + if (block.skipBlock) + { + // No diagnostics. Just skip the whole line. + skipUntilEOD(mTokenizer, token); + return; + } + if (block.foundElseGroup) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_AFTER_ELSE, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return; + } + if (block.foundValidGroup) + { + // Do not parse the expression. + // Also be careful not to emit a diagnostic. + block.skipGroup = true; + skipUntilEOD(mTokenizer, token); + return; + } + + int expression = parseExpressionIf(token); + block.skipGroup = expression == 0; + block.foundValidGroup = expression != 0; +} + +void DirectiveParser::parseEndif(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_ENDIF); + + if (mConditionalStack.empty()) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_ENDIF_WITHOUT_IF, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return; + } + + mConditionalStack.pop_back(); + + // Warn if there are tokens after #endif. + mTokenizer->lex(token); + if (!isEOD(token)) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + } +} + +void DirectiveParser::parseError(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_ERROR); + + std::ostringstream stream; + mTokenizer->lex(token); + while ((token->type != '\n') && (token->type != Token::LAST)) + { + stream << *token; + mTokenizer->lex(token); + } + mDirectiveHandler->handleError(token->location, stream.str()); +} + +// Parses pragma of form: #pragma name[(value)]. +void DirectiveParser::parsePragma(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_PRAGMA); + + enum State + { + PRAGMA_NAME, + LEFT_PAREN, + PRAGMA_VALUE, + RIGHT_PAREN + }; + + bool valid = true; + std::string name, value; + int state = PRAGMA_NAME; + + mTokenizer->lex(token); + while ((token->type != '\n') && (token->type != Token::LAST)) + { + switch(state++) + { + case PRAGMA_NAME: + name = token->text; + valid = valid && (token->type == Token::IDENTIFIER); + break; + case LEFT_PAREN: + valid = valid && (token->type == '('); + break; + case PRAGMA_VALUE: + value = token->text; + valid = valid && (token->type == Token::IDENTIFIER); + break; + case RIGHT_PAREN: + valid = valid && (token->type == ')'); + break; + default: + valid = false; + break; + } + mTokenizer->lex(token); + } + + valid = valid && ((state == PRAGMA_NAME) || // Empty pragma. + (state == LEFT_PAREN) || // Without value. + (state == RIGHT_PAREN + 1)); // With value. + if (!valid) + { + mDiagnostics->report(Diagnostics::UNRECOGNIZED_PRAGMA, + token->location, name); + } + else if (state > PRAGMA_NAME) // Do not notify for empty pragma. + { + mDirectiveHandler->handlePragma(token->location, name, value); + } +} + +void DirectiveParser::parseExtension(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_EXTENSION); + + enum State + { + EXT_NAME, + COLON, + EXT_BEHAVIOR + }; + + bool valid = true; + std::string name, behavior; + int state = EXT_NAME; + + mTokenizer->lex(token); + while ((token->type != '\n') && (token->type != Token::LAST)) + { + switch (state++) + { + case EXT_NAME: + if (valid && (token->type != Token::IDENTIFIER)) + { + mDiagnostics->report(Diagnostics::INVALID_EXTENSION_NAME, + token->location, token->text); + valid = false; + } + if (valid) name = token->text; + break; + case COLON: + if (valid && (token->type != ':')) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + valid = false; + } + break; + case EXT_BEHAVIOR: + if (valid && (token->type != Token::IDENTIFIER)) + { + mDiagnostics->report(Diagnostics::INVALID_EXTENSION_BEHAVIOR, + token->location, token->text); + valid = false; + } + if (valid) behavior = token->text; + break; + default: + if (valid) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + valid = false; + } + break; + } + mTokenizer->lex(token); + } + if (valid && (state != EXT_BEHAVIOR + 1)) + { + mDiagnostics->report(Diagnostics::INVALID_EXTENSION_DIRECTIVE, + token->location, token->text); + valid = false; + } + if (valid) + mDirectiveHandler->handleExtension(token->location, name, behavior); +} + +void DirectiveParser::parseVersion(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_VERSION); + + if (mPastFirstStatement) + { + mDiagnostics->report(Diagnostics::VERSION_NOT_FIRST_STATEMENT, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return; + } + + enum State + { + VERSION_NUMBER + }; + + bool valid = true; + int version = 0; + int state = VERSION_NUMBER; + + mTokenizer->lex(token); + while ((token->type != '\n') && (token->type != Token::LAST)) + { + switch (state++) + { + case VERSION_NUMBER: + if (valid && (token->type != Token::CONST_INT)) + { + mDiagnostics->report(Diagnostics::INVALID_VERSION_NUMBER, + token->location, token->text); + valid = false; + } + if (valid && !token->iValue(&version)) + { + mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, + token->location, token->text); + valid = false; + } + break; + default: + if (valid) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + valid = false; + } + break; + } + mTokenizer->lex(token); + } + if (valid && (state != VERSION_NUMBER + 1)) + { + mDiagnostics->report(Diagnostics::INVALID_VERSION_DIRECTIVE, + token->location, token->text); + valid = false; + } + if (valid) + mDirectiveHandler->handleVersion(token->location, version); +} + +void DirectiveParser::parseLine(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_LINE); + + enum State + { + LINE_NUMBER, + FILE_NUMBER + }; + + bool valid = true; + int line = 0, file = 0; + int state = LINE_NUMBER; + + MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics); + macroExpander.lex(token); + while ((token->type != '\n') && (token->type != Token::LAST)) + { + switch (state++) + { + case LINE_NUMBER: + if (valid && (token->type != Token::CONST_INT)) + { + mDiagnostics->report(Diagnostics::INVALID_LINE_NUMBER, + token->location, token->text); + valid = false; + } + if (valid && !token->iValue(&line)) + { + mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, + token->location, token->text); + valid = false; + } + break; + case FILE_NUMBER: + if (valid && (token->type != Token::CONST_INT)) + { + mDiagnostics->report(Diagnostics::INVALID_FILE_NUMBER, + token->location, token->text); + valid = false; + } + if (valid && !token->iValue(&file)) + { + mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, + token->location, token->text); + valid = false; + } + break; + default: + if (valid) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + valid = false; + } + break; + } + macroExpander.lex(token); + } + + if (valid && (state != FILE_NUMBER) && (state != FILE_NUMBER + 1)) + { + mDiagnostics->report(Diagnostics::INVALID_LINE_DIRECTIVE, + token->location, token->text); + valid = false; + } + if (valid) + { + mTokenizer->setLineNumber(line); + if (state == FILE_NUMBER + 1) mTokenizer->setFileNumber(file); + } +} + +bool DirectiveParser::skipping() const +{ + if (mConditionalStack.empty()) return false; + + const ConditionalBlock& block = mConditionalStack.back(); + return block.skipBlock || block.skipGroup; +} + +void DirectiveParser::parseConditionalIf(Token* token) +{ + ConditionalBlock block; + block.type = token->text; + block.location = token->location; + + if (skipping()) + { + // This conditional block is inside another conditional group + // which is skipped. As a consequence this whole block is skipped. + // Be careful not to parse the conditional expression that might + // emit a diagnostic. + skipUntilEOD(mTokenizer, token); + block.skipBlock = true; + } + else + { + DirectiveType directive = getDirective(token); + + int expression = 0; + switch (directive) + { + case DIRECTIVE_IF: + expression = parseExpressionIf(token); + break; + case DIRECTIVE_IFDEF: + expression = parseExpressionIfdef(token); + break; + case DIRECTIVE_IFNDEF: + expression = parseExpressionIfdef(token) == 0 ? 1 : 0; + break; + default: + assert(false); + break; + } + block.skipGroup = expression == 0; + block.foundValidGroup = expression != 0; + } + mConditionalStack.push_back(block); +} + +int DirectiveParser::parseExpressionIf(Token* token) +{ + assert((getDirective(token) == DIRECTIVE_IF) || + (getDirective(token) == DIRECTIVE_ELIF)); + + DefinedParser definedParser(mTokenizer, mMacroSet, mDiagnostics); + MacroExpander macroExpander(&definedParser, mMacroSet, mDiagnostics); + ExpressionParser expressionParser(¯oExpander, mDiagnostics); + + int expression = 0; + macroExpander.lex(token); + expressionParser.parse(token, &expression); + + // Warn if there are tokens after #if expression. + if (!isEOD(token)) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + } + + return expression; +} + +int DirectiveParser::parseExpressionIfdef(Token* token) +{ + assert((getDirective(token) == DIRECTIVE_IFDEF) || + (getDirective(token) == DIRECTIVE_IFNDEF)); + + mTokenizer->lex(token); + if (token->type != Token::IDENTIFIER) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return 0; + } + + MacroSet::const_iterator iter = mMacroSet->find(token->text); + int expression = iter != mMacroSet->end() ? 1 : 0; + + // Warn if there are tokens after #ifdef expression. + mTokenizer->lex(token); + if (!isEOD(token)) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + } + return expression; +} + +} // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveParser.h b/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveParser.h new file mode 100644 index 0000000000..8a7f0072ba --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveParser.h @@ -0,0 +1,82 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_ +#define COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_ + +#include "Lexer.h" +#include "Macro.h" +#include "pp_utils.h" +#include "SourceLocation.h" + +namespace pp +{ + +class Diagnostics; +class DirectiveHandler; +class Tokenizer; + +class DirectiveParser : public Lexer +{ + public: + DirectiveParser(Tokenizer* tokenizer, + MacroSet* macroSet, + Diagnostics* diagnostics, + DirectiveHandler* directiveHandler); + + virtual void lex(Token* token); + + private: + PP_DISALLOW_COPY_AND_ASSIGN(DirectiveParser); + + void parseDirective(Token* token); + void parseDefine(Token* token); + void parseUndef(Token* token); + void parseIf(Token* token); + void parseIfdef(Token* token); + void parseIfndef(Token* token); + void parseElse(Token* token); + void parseElif(Token* token); + void parseEndif(Token* token); + void parseError(Token* token); + void parsePragma(Token* token); + void parseExtension(Token* token); + void parseVersion(Token* token); + void parseLine(Token* token); + + bool skipping() const; + void parseConditionalIf(Token* token); + int parseExpressionIf(Token* token); + int parseExpressionIfdef(Token* token); + + struct ConditionalBlock + { + std::string type; + SourceLocation location; + bool skipBlock; + bool skipGroup; + bool foundValidGroup; + bool foundElseGroup; + + ConditionalBlock() : + skipBlock(false), + skipGroup(false), + foundValidGroup(false), + foundElseGroup(false) + { + } + }; + bool mPastFirstStatement; + std::vector<ConditionalBlock> mConditionalStack; + Tokenizer* mTokenizer; + MacroSet* mMacroSet; + Diagnostics* mDiagnostics; + DirectiveHandler* mDirectiveHandler; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_ + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/ExpressionParser.h b/src/3rdparty/angle/src/compiler/preprocessor/new/ExpressionParser.h new file mode 100644 index 0000000000..092d059413 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/ExpressionParser.h @@ -0,0 +1,34 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_ +#define COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_ + +#include "pp_utils.h" + +namespace pp +{ + +class Diagnostics; +class Lexer; +struct Token; + +class ExpressionParser +{ + public: + ExpressionParser(Lexer* lexer, Diagnostics* diagnostics); + + bool parse(Token* token, int* result); + + private: + PP_DISALLOW_COPY_AND_ASSIGN(ExpressionParser); + + Lexer* mLexer; + Diagnostics* mDiagnostics; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/ExpressionParser.y b/src/3rdparty/angle/src/compiler/preprocessor/new/ExpressionParser.y new file mode 100644 index 0000000000..832ad4001e --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/ExpressionParser.y @@ -0,0 +1,279 @@ +/* +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +This file contains the Yacc grammar for GLSL ES preprocessor expression. + +IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh, +WHICH GENERATES THE GLSL ES preprocessor expression parser. +*/ + +%{ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// This file is auto-generated by generate_parser.sh. DO NOT EDIT! + +#if defined(__GNUC__) +// Triggered by the auto-generated pplval variable. +#pragma GCC diagnostic ignored "-Wuninitialized" +#elif defined(_MSC_VER) +#pragma warning(disable: 4065 4701) +#endif + +#include "ExpressionParser.h" + +#include <cassert> +#include <sstream> + +#include "Diagnostics.h" +#include "Lexer.h" +#include "Token.h" + +#if defined(_MSC_VER) +typedef __int64 YYSTYPE; +#else +#include <stdint.h> +typedef intmax_t YYSTYPE; +#endif // _MSC_VER +#define YYSTYPE_IS_TRIVIAL 1 +#define YYSTYPE_IS_DECLARED 1 + +namespace { +struct Context +{ + pp::Diagnostics* diagnostics; + pp::Lexer* lexer; + pp::Token* token; + int* result; +}; +} // namespace +%} + +%pure-parser +%name-prefix="pp" +%parse-param {Context *context} +%lex-param {Context *context} + +%{ +static int yylex(YYSTYPE* lvalp, Context* context); +static void yyerror(Context* context, const char* reason); +%} + +%token TOK_CONST_INT +%left TOK_OP_OR +%left TOK_OP_AND +%left '|' +%left '^' +%left '&' +%left TOK_OP_EQ TOK_OP_NE +%left '<' '>' TOK_OP_LE TOK_OP_GE +%left TOK_OP_LEFT TOK_OP_RIGHT +%left '+' '-' +%left '*' '/' '%' +%right TOK_UNARY + +%% + +input + : expression { + *(context->result) = static_cast<int>($1); + YYACCEPT; + } +; + +expression + : TOK_CONST_INT + | expression TOK_OP_OR expression { + $$ = $1 || $3; + } + | expression TOK_OP_AND expression { + $$ = $1 && $3; + } + | expression '|' expression { + $$ = $1 | $3; + } + | expression '^' expression { + $$ = $1 ^ $3; + } + | expression '&' expression { + $$ = $1 & $3; + } + | expression TOK_OP_NE expression { + $$ = $1 != $3; + } + | expression TOK_OP_EQ expression { + $$ = $1 == $3; + } + | expression TOK_OP_GE expression { + $$ = $1 >= $3; + } + | expression TOK_OP_LE expression { + $$ = $1 <= $3; + } + | expression '>' expression { + $$ = $1 > $3; + } + | expression '<' expression { + $$ = $1 < $3; + } + | expression TOK_OP_RIGHT expression { + $$ = $1 >> $3; + } + | expression TOK_OP_LEFT expression { + $$ = $1 << $3; + } + | expression '-' expression { + $$ = $1 - $3; + } + | expression '+' expression { + $$ = $1 + $3; + } + | expression '%' expression { + if ($3 == 0) { + std::ostringstream stream; + stream << $1 << " % " << $3; + std::string text = stream.str(); + context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO, + context->token->location, + text.c_str()); + YYABORT; + } else { + $$ = $1 % $3; + } + } + | expression '/' expression { + if ($3 == 0) { + std::ostringstream stream; + stream << $1 << " / " << $3; + std::string text = stream.str(); + context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO, + context->token->location, + text.c_str()); + YYABORT; + } else { + $$ = $1 / $3; + } + } + | expression '*' expression { + $$ = $1 * $3; + } + | '!' expression %prec TOK_UNARY { + $$ = ! $2; + } + | '~' expression %prec TOK_UNARY { + $$ = ~ $2; + } + | '-' expression %prec TOK_UNARY { + $$ = - $2; + } + | '+' expression %prec TOK_UNARY { + $$ = + $2; + } + | '(' expression ')' { + $$ = $2; + } +; + +%% + +int yylex(YYSTYPE* lvalp, Context* context) +{ + int type = 0; + + pp::Token* token = context->token; + switch (token->type) + { + case pp::Token::CONST_INT: + { + unsigned int val = 0; + if (!token->uValue(&val)) + { + context->diagnostics->report(pp::Diagnostics::INTEGER_OVERFLOW, + token->location, token->text); + } + *lvalp = static_cast<YYSTYPE>(val); + type = TOK_CONST_INT; + break; + } + case pp::Token::OP_OR: type = TOK_OP_OR; break; + case pp::Token::OP_AND: type = TOK_OP_AND; break; + case pp::Token::OP_NE: type = TOK_OP_NE; break; + case pp::Token::OP_EQ: type = TOK_OP_EQ; break; + case pp::Token::OP_GE: type = TOK_OP_GE; break; + case pp::Token::OP_LE: type = TOK_OP_LE; break; + case pp::Token::OP_RIGHT: type = TOK_OP_RIGHT; break; + case pp::Token::OP_LEFT: type = TOK_OP_LEFT; break; + case '|': type = '|'; break; + case '^': type = '^'; break; + case '&': type = '&'; break; + case '>': type = '>'; break; + case '<': type = '<'; break; + case '-': type = '-'; break; + case '+': type = '+'; break; + case '%': type = '%'; break; + case '/': type = '/'; break; + case '*': type = '*'; break; + case '!': type = '!'; break; + case '~': type = '~'; break; + case '(': type = '('; break; + case ')': type = ')'; break; + + default: break; + } + + // Advance to the next token if the current one is valid. + if (type != 0) context->lexer->lex(token); + + return type; +} + +void yyerror(Context* context, const char* reason) +{ + context->diagnostics->report(pp::Diagnostics::INVALID_EXPRESSION, + context->token->location, + reason); +} + +namespace pp { + +ExpressionParser::ExpressionParser(Lexer* lexer, Diagnostics* diagnostics) : + mLexer(lexer), + mDiagnostics(diagnostics) +{ +} + +bool ExpressionParser::parse(Token* token, int* result) +{ + Context context; + context.diagnostics = mDiagnostics; + context.lexer = mLexer; + context.token = token; + context.result = result; + int ret = yyparse(&context); + switch (ret) + { + case 0: + case 1: + break; + + case 2: + mDiagnostics->report(Diagnostics::OUT_OF_MEMORY, token->location, ""); + break; + + default: + assert(false); + mDiagnostics->report(Diagnostics::INTERNAL_ERROR, token->location, ""); + break; + } + + return ret == 0; +} + +} // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Input.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/Input.cpp new file mode 100644 index 0000000000..c3de95f313 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/Input.cpp @@ -0,0 +1,55 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "Input.h" + +#include <algorithm> +#include <cassert> +#include <cstring> + +namespace pp +{ + +Input::Input() : mCount(0), mString(0) +{ +} + +Input::Input(int count, const char* const string[], const int length[]) : + mCount(count), + mString(string) +{ + assert(mCount >= 0); + mLength.reserve(mCount); + for (int i = 0; i < mCount; ++i) + { + int len = length ? length[i] : -1; + mLength.push_back(len < 0 ? strlen(mString[i]) : len); + } +} + +int Input::read(char* buf, int maxSize) +{ + int nRead = 0; + while ((nRead < maxSize) && (mReadLoc.sIndex < mCount)) + { + int size = mLength[mReadLoc.sIndex] - mReadLoc.cIndex; + size = std::min(size, maxSize); + memcpy(buf + nRead, mString[mReadLoc.sIndex] + mReadLoc.cIndex, size); + nRead += size; + mReadLoc.cIndex += size; + + // Advance string if we reached the end of current string. + if (mReadLoc.cIndex == mLength[mReadLoc.sIndex]) + { + ++mReadLoc.sIndex; + mReadLoc.cIndex = 0; + } + } + return nRead; +} + +} // namespace pp + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Input.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Input.h new file mode 100644 index 0000000000..dac734b68d --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/Input.h @@ -0,0 +1,48 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_INPUT_H_ +#define COMPILER_PREPROCESSOR_INPUT_H_ + +#include <vector> + +namespace pp +{ + +// Holds and reads input for Lexer. +class Input +{ + public: + Input(); + Input(int count, const char* const string[], const int length[]); + + int count() const { return mCount; } + const char* string(int index) const { return mString[index]; } + int length(int index) const { return mLength[index]; } + + int read(char* buf, int maxSize); + + struct Location + { + int sIndex; // String index; + int cIndex; // Char index. + + Location() : sIndex(0), cIndex(0) { } + }; + const Location& readLoc() const { return mReadLoc; } + + private: + // Input. + int mCount; + const char* const* mString; + std::vector<int> mLength; + + Location mReadLoc; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_INPUT_H_ + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Lexer.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/Lexer.cpp new file mode 100644 index 0000000000..7c663ee761 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/Lexer.cpp @@ -0,0 +1,16 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "Lexer.h" + +namespace pp +{ + +Lexer::~Lexer() +{ +} + +} // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Lexer.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Lexer.h new file mode 100644 index 0000000000..eb85cea873 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/Lexer.h @@ -0,0 +1,25 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_LEXER_H_ +#define COMPILER_PREPROCESSOR_LEXER_H_ + +namespace pp +{ + +struct Token; + +class Lexer +{ + public: + virtual ~Lexer(); + + virtual void lex(Token* token) = 0; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_LEXER_H_ + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Macro.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/Macro.cpp new file mode 100644 index 0000000000..b2e3088e32 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/Macro.cpp @@ -0,0 +1,23 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "Macro.h" + +#include "Token.h" + +namespace pp +{ + +bool Macro::equals(const Macro& other) const +{ + return (type == other.type) && + (name == other.name) && + (parameters == other.parameters) && + (replacements == other.replacements); +} + +} // namespace pp + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Macro.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Macro.h new file mode 100644 index 0000000000..7ec0149116 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/Macro.h @@ -0,0 +1,44 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_MACRO_H_ +#define COMPILER_PREPROCESSOR_MACRO_H_ + +#include <map> +#include <string> +#include <vector> + +namespace pp +{ + +struct Token; + +struct Macro +{ + enum Type + { + kTypeObj, + kTypeFunc + }; + typedef std::vector<std::string> Parameters; + typedef std::vector<Token> Replacements; + + Macro() : predefined(false), disabled(false), type(kTypeObj) { } + bool equals(const Macro& other) const; + + bool predefined; + mutable bool disabled; + + Type type; + std::string name; + Parameters parameters; + Replacements replacements; +}; + +typedef std::map<std::string, Macro> MacroSet; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_MACRO_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/MacroExpander.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/MacroExpander.cpp new file mode 100644 index 0000000000..701cec9a4b --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/MacroExpander.cpp @@ -0,0 +1,370 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "MacroExpander.h" + +#include <algorithm> +#include <sstream> + +#include "Diagnostics.h" +#include "Token.h" + +namespace pp +{ + +class TokenLexer : public Lexer +{ + public: + typedef std::vector<Token> TokenVector; + + TokenLexer(TokenVector* tokens) + { + tokens->swap(mTokens); + mIter = mTokens.begin(); + } + + virtual void lex(Token* token) + { + if (mIter == mTokens.end()) + { + token->reset(); + token->type = Token::LAST; + } + else + { + *token = *mIter++; + } + } + + private: + PP_DISALLOW_COPY_AND_ASSIGN(TokenLexer); + + TokenVector mTokens; + TokenVector::const_iterator mIter; +}; + +MacroExpander::MacroExpander(Lexer* lexer, + MacroSet* macroSet, + Diagnostics* diagnostics) : + mLexer(lexer), + mMacroSet(macroSet), + mDiagnostics(diagnostics) +{ +} + +MacroExpander::~MacroExpander() +{ + for (size_t i = 0; i < mContextStack.size(); ++i) + { + delete mContextStack[i]; + } +} + +void MacroExpander::lex(Token* token) +{ + while (true) + { + getToken(token); + + if (token->type != Token::IDENTIFIER) + break; + + if (token->expansionDisabled()) + break; + + MacroSet::const_iterator iter = mMacroSet->find(token->text); + if (iter == mMacroSet->end()) + break; + + const Macro& macro = iter->second; + if (macro.disabled) + { + // If a particular token is not expanded, it is never expanded. + token->setExpansionDisabled(true); + break; + } + if ((macro.type == Macro::kTypeFunc) && !isNextTokenLeftParen()) + { + // If the token immediately after the macro name is not a '(', + // this macro should not be expanded. + break; + } + + pushMacro(macro, *token); + } +} + +void MacroExpander::getToken(Token* token) +{ + if (mReserveToken.get()) + { + *token = *mReserveToken; + mReserveToken.reset(); + return; + } + + // First pop all empty macro contexts. + while (!mContextStack.empty() && mContextStack.back()->empty()) + { + popMacro(); + } + + if (!mContextStack.empty()) + { + *token = mContextStack.back()->get(); + } + else + { + mLexer->lex(token); + } +} + +void MacroExpander::ungetToken(const Token& token) +{ + if (!mContextStack.empty()) + { + MacroContext* context = mContextStack.back(); + context->unget(); + assert(context->replacements[context->index] == token); + } + else + { + assert(!mReserveToken.get()); + mReserveToken.reset(new Token(token)); + } +} + +bool MacroExpander::isNextTokenLeftParen() +{ + Token token; + getToken(&token); + + bool lparen = token.type == '('; + ungetToken(token); + + return lparen; +} + +bool MacroExpander::pushMacro(const Macro& macro, const Token& identifier) +{ + assert(!macro.disabled); + assert(!identifier.expansionDisabled()); + assert(identifier.type == Token::IDENTIFIER); + assert(identifier.text == macro.name); + + std::vector<Token> replacements; + if (!expandMacro(macro, identifier, &replacements)) + return false; + + // Macro is disabled for expansion until it is popped off the stack. + macro.disabled = true; + + MacroContext* context = new MacroContext; + context->macro = ¯o; + context->replacements.swap(replacements); + mContextStack.push_back(context); + return true; +} + +void MacroExpander::popMacro() +{ + assert(!mContextStack.empty()); + + MacroContext* context = mContextStack.back(); + mContextStack.pop_back(); + + assert(context->empty()); + assert(context->macro->disabled); + context->macro->disabled = false; + delete context; +} + +bool MacroExpander::expandMacro(const Macro& macro, + const Token& identifier, + std::vector<Token>* replacements) +{ + replacements->clear(); + if (macro.type == Macro::kTypeObj) + { + replacements->assign(macro.replacements.begin(), + macro.replacements.end()); + + if (macro.predefined) + { + static const std::string kLine = "__LINE__"; + static const std::string kFile = "__FILE__"; + + assert(replacements->size() == 1); + Token& repl = replacements->front(); + if (macro.name == kLine) + { + std::ostringstream stream; + stream << identifier.location.line; + repl.text = stream.str(); + } + else if (macro.name == kFile) + { + std::ostringstream stream; + stream << identifier.location.file; + repl.text = stream.str(); + } + } + } + else + { + assert(macro.type == Macro::kTypeFunc); + std::vector<MacroArg> args; + args.reserve(macro.parameters.size()); + if (!collectMacroArgs(macro, identifier, &args)) + return false; + + replaceMacroParams(macro, args, replacements); + } + + for (size_t i = 0; i < replacements->size(); ++i) + { + Token& repl = replacements->at(i); + if (i == 0) + { + // The first token in the replacement list inherits the padding + // properties of the identifier token. + repl.setAtStartOfLine(identifier.atStartOfLine()); + repl.setHasLeadingSpace(identifier.hasLeadingSpace()); + } + repl.location = identifier.location; + } + return true; +} + +bool MacroExpander::collectMacroArgs(const Macro& macro, + const Token& identifier, + std::vector<MacroArg>* args) +{ + Token token; + getToken(&token); + assert(token.type == '('); + + args->push_back(MacroArg()); + for (int openParens = 1; openParens != 0; ) + { + getToken(&token); + + if (token.type == Token::LAST) + { + mDiagnostics->report(Diagnostics::MACRO_UNTERMINATED_INVOCATION, + identifier.location, identifier.text); + // Do not lose EOF token. + ungetToken(token); + return false; + } + + bool isArg = false; // True if token is part of the current argument. + switch (token.type) + { + case '(': + ++openParens; + isArg = true; + break; + case ')': + --openParens; + isArg = openParens != 0; + break; + case ',': + // The individual arguments are separated by comma tokens, but + // the comma tokens between matching inner parentheses do not + // seperate arguments. + if (openParens == 1) args->push_back(MacroArg()); + isArg = openParens != 1; + break; + default: + isArg = true; + break; + } + if (isArg) + { + MacroArg& arg = args->back(); + // Initial whitespace is not part of the argument. + if (arg.empty()) token.setHasLeadingSpace(false); + arg.push_back(token); + } + } + + const Macro::Parameters& params = macro.parameters; + // If there is only one empty argument, it is equivalent to no argument. + if (params.empty() && (args->size() == 1) && args->front().empty()) + { + args->clear(); + } + // Validate the number of arguments. + if (args->size() != params.size()) + { + Diagnostics::ID id = args->size() < macro.parameters.size() ? + Diagnostics::MACRO_TOO_FEW_ARGS : + Diagnostics::MACRO_TOO_MANY_ARGS; + mDiagnostics->report(id, identifier.location, identifier.text); + return false; + } + + // Pre-expand each argument before substitution. + // This step expands each argument individually before they are + // inserted into the macro body. + for (size_t i = 0; i < args->size(); ++i) + { + MacroArg& arg = args->at(i); + TokenLexer lexer(&arg); + MacroExpander expander(&lexer, mMacroSet, mDiagnostics); + + arg.clear(); + expander.lex(&token); + while (token.type != Token::LAST) + { + arg.push_back(token); + expander.lex(&token); + } + } + return true; +} + +void MacroExpander::replaceMacroParams(const Macro& macro, + const std::vector<MacroArg>& args, + std::vector<Token>* replacements) +{ + for (size_t i = 0; i < macro.replacements.size(); ++i) + { + const Token& repl = macro.replacements[i]; + if (repl.type != Token::IDENTIFIER) + { + replacements->push_back(repl); + continue; + } + + // TODO(alokp): Optimize this. + // There is no need to search for macro params every time. + // The param index can be cached with the replacement token. + Macro::Parameters::const_iterator iter = std::find( + macro.parameters.begin(), macro.parameters.end(), repl.text); + if (iter == macro.parameters.end()) + { + replacements->push_back(repl); + continue; + } + + size_t iArg = std::distance(macro.parameters.begin(), iter); + const MacroArg& arg = args[iArg]; + if (arg.empty()) + { + continue; + } + size_t iRepl = replacements->size(); + replacements->insert(replacements->end(), arg.begin(), arg.end()); + // The replacement token inherits padding properties from + // macro replacement token. + replacements->at(iRepl).setHasLeadingSpace(repl.hasLeadingSpace()); + } +} + +} // namespace pp + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/MacroExpander.h b/src/3rdparty/angle/src/compiler/preprocessor/new/MacroExpander.h new file mode 100644 index 0000000000..7c5c543871 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/MacroExpander.h @@ -0,0 +1,75 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_ +#define COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_ + +#include <cassert> +#include <memory> +#include <vector> + +#include "Lexer.h" +#include "Macro.h" +#include "pp_utils.h" + +namespace pp +{ + +class Diagnostics; + +class MacroExpander : public Lexer +{ + public: + MacroExpander(Lexer* lexer, MacroSet* macroSet, Diagnostics* diagnostics); + virtual ~MacroExpander(); + + virtual void lex(Token* token); + + private: + PP_DISALLOW_COPY_AND_ASSIGN(MacroExpander); + + void getToken(Token* token); + void ungetToken(const Token& token); + bool isNextTokenLeftParen(); + + bool pushMacro(const Macro& macro, const Token& identifier); + void popMacro(); + + bool expandMacro(const Macro& macro, + const Token& identifier, + std::vector<Token>* replacements); + + typedef std::vector<Token> MacroArg; + bool collectMacroArgs(const Macro& macro, + const Token& identifier, + std::vector<MacroArg>* args); + void replaceMacroParams(const Macro& macro, + const std::vector<MacroArg>& args, + std::vector<Token>* replacements); + + struct MacroContext + { + const Macro* macro; + size_t index; + std::vector<Token> replacements; + + MacroContext() : macro(0), index(0) { } + bool empty() const { return index == replacements.size(); } + const Token& get() { return replacements[index++]; } + void unget() { assert(index > 0); --index; } + }; + + Lexer* mLexer; + MacroSet* mMacroSet; + Diagnostics* mDiagnostics; + + std::auto_ptr<Token> mReserveToken; + std::vector<MacroContext*> mContextStack; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_ + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Preprocessor.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/Preprocessor.cpp new file mode 100644 index 0000000000..ffa7225a8f --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/Preprocessor.cpp @@ -0,0 +1,142 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "Preprocessor.h" + +#include <cassert> +#include <sstream> + +#include "Diagnostics.h" +#include "DirectiveParser.h" +#include "Macro.h" +#include "MacroExpander.h" +#include "Token.h" +#include "Tokenizer.h" + +namespace pp +{ + +struct PreprocessorImpl +{ + Diagnostics* diagnostics; + MacroSet macroSet; + Tokenizer tokenizer; + DirectiveParser directiveParser; + MacroExpander macroExpander; + + PreprocessorImpl(Diagnostics* diag, + DirectiveHandler* directiveHandler) : + diagnostics(diag), + tokenizer(diag), + directiveParser(&tokenizer, ¯oSet, diag, directiveHandler), + macroExpander(&directiveParser, ¯oSet, diag) + { + } +}; + +Preprocessor::Preprocessor(Diagnostics* diagnostics, + DirectiveHandler* directiveHandler) +{ + mImpl = new PreprocessorImpl(diagnostics, directiveHandler); +} + +Preprocessor::~Preprocessor() +{ + delete mImpl; +} + +bool Preprocessor::init(int count, + const char* const string[], + const int length[]) +{ + static const int kGLSLVersion = 100; + + // Add standard pre-defined macros. + predefineMacro("__LINE__", 0); + predefineMacro("__FILE__", 0); + predefineMacro("__VERSION__", kGLSLVersion); + predefineMacro("GL_ES", 1); + + return mImpl->tokenizer.init(count, string, length); +} + +void Preprocessor::predefineMacro(const char* name, int value) +{ + std::ostringstream stream; + stream << value; + + Token token; + token.type = Token::CONST_INT; + token.text = stream.str(); + + Macro macro; + macro.predefined = true; + macro.type = Macro::kTypeObj; + macro.name = name; + macro.replacements.push_back(token); + + mImpl->macroSet[name] = macro; +} + +void Preprocessor::lex(Token* token) +{ + bool validToken = false; + while (!validToken) + { + mImpl->macroExpander.lex(token); + switch (token->type) + { + // We should not be returning internal preprocessing tokens. + // Convert preprocessing tokens to compiler tokens or report + // diagnostics. + case Token::PP_HASH: + assert(false); + break; + case Token::CONST_INT: + { + int val = 0; + if (!token->iValue(&val)) + { + // Do not mark the token as invalid. + // Just emit the diagnostic and reset value to 0. + mImpl->diagnostics->report(Diagnostics::INTEGER_OVERFLOW, + token->location, token->text); + token->text.assign("0"); + } + validToken = true; + break; + } + case Token::CONST_FLOAT: + { + float val = 0; + if (!token->fValue(&val)) + { + // Do not mark the token as invalid. + // Just emit the diagnostic and reset value to 0.0. + mImpl->diagnostics->report(Diagnostics::FLOAT_OVERFLOW, + token->location, token->text); + token->text.assign("0.0"); + } + validToken = true; + break; + } + case Token::PP_NUMBER: + mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER, + token->location, token->text); + break; + case Token::PP_OTHER: + mImpl->diagnostics->report(Diagnostics::INVALID_CHARACTER, + token->location, token->text); + break; + default: + validToken = true; + break; + } + } +} + +} // namespace pp + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Preprocessor.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Preprocessor.h new file mode 100644 index 0000000000..5fe35b27bd --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/Preprocessor.h @@ -0,0 +1,49 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_PREPROCESSOR_H_ +#define COMPILER_PREPROCESSOR_PREPROCESSOR_H_ + +#include "pp_utils.h" + +namespace pp +{ + +class Diagnostics; +class DirectiveHandler; +struct PreprocessorImpl; +struct Token; + +class Preprocessor +{ + public: + Preprocessor(Diagnostics* diagnostics, DirectiveHandler* directiveHandler); + ~Preprocessor(); + + // count: specifies the number of elements in the string and length arrays. + // string: specifies an array of pointers to strings. + // length: specifies an array of string lengths. + // If length is NULL, each string is assumed to be null terminated. + // If length is a value other than NULL, it points to an array containing + // a string length for each of the corresponding elements of string. + // Each element in the length array may contain the length of the + // corresponding string or a value less than 0 to indicate that the string + // is null terminated. + bool init(int count, const char* const string[], const int length[]); + // Adds a pre-defined macro. + void predefineMacro(const char* name, int value); + + void lex(Token* token); + + private: + PP_DISALLOW_COPY_AND_ASSIGN(Preprocessor); + + PreprocessorImpl* mImpl; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_PREPROCESSOR_H_ + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/SourceLocation.h b/src/3rdparty/angle/src/compiler/preprocessor/new/SourceLocation.h new file mode 100644 index 0000000000..6982613ac7 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/SourceLocation.h @@ -0,0 +1,38 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_ +#define COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_ + +namespace pp +{ + +struct SourceLocation +{ + SourceLocation() : file(0), line(0) { } + SourceLocation(int f, int l) : file(f), line(l) { } + + bool equals(const SourceLocation& other) const + { + return (file == other.file) && (line == other.line); + } + + int file; + int line; +}; + +inline bool operator==(const SourceLocation& lhs, const SourceLocation& rhs) +{ + return lhs.equals(rhs); +} + +inline bool operator!=(const SourceLocation& lhs, const SourceLocation& rhs) +{ + return !lhs.equals(rhs); +} + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Token.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/Token.cpp new file mode 100644 index 0000000000..67f50aa32c --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/Token.cpp @@ -0,0 +1,83 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "Token.h" + +#include <cassert> + +#include "numeric_lex.h" + +namespace pp +{ + +void Token::reset() +{ + type = 0; + flags = 0; + location = SourceLocation(); + text.clear(); +} + +bool Token::equals(const Token& other) const +{ + return (type == other.type) && + (flags == other.flags) && + (location == other.location) && + (text == other.text); +} + +void Token::setAtStartOfLine(bool start) +{ + if (start) + flags |= AT_START_OF_LINE; + else + flags &= ~AT_START_OF_LINE; +} + +void Token::setHasLeadingSpace(bool space) +{ + if (space) + flags |= HAS_LEADING_SPACE; + else + flags &= ~HAS_LEADING_SPACE; +} + +void Token::setExpansionDisabled(bool disable) +{ + if (disable) + flags |= EXPANSION_DISABLED; + else + flags &= ~EXPANSION_DISABLED; +} + +bool Token::iValue(int* value) const +{ + assert(type == CONST_INT); + return numeric_lex_int(text, value); +} + +bool Token::uValue(unsigned int* value) const +{ + assert(type == CONST_INT); + return numeric_lex_int(text, value); +} + +bool Token::fValue(float* value) const +{ + assert(type == CONST_FLOAT); + return numeric_lex_float(text, value); +} + +std::ostream& operator<<(std::ostream& out, const Token& token) +{ + if (token.hasLeadingSpace()) + out << " "; + + out << token.text; + return out; +} + +} // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Token.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Token.h new file mode 100644 index 0000000000..8b553aecb6 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/Token.h @@ -0,0 +1,106 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_TOKEN_H_ +#define COMPILER_PREPROCESSOR_TOKEN_H_ + +#include <ostream> +#include <string> + +#include "SourceLocation.h" + +namespace pp +{ + +struct Token +{ + enum Type + { + LAST = 0, // EOF. + + IDENTIFIER = 258, + + CONST_INT, + CONST_FLOAT, + + OP_INC, + OP_DEC, + OP_LEFT, + OP_RIGHT, + OP_LE, + OP_GE, + OP_EQ, + OP_NE, + OP_AND, + OP_XOR, + OP_OR, + OP_ADD_ASSIGN, + OP_SUB_ASSIGN, + OP_MUL_ASSIGN, + OP_DIV_ASSIGN, + OP_MOD_ASSIGN, + OP_LEFT_ASSIGN, + OP_RIGHT_ASSIGN, + OP_AND_ASSIGN, + OP_XOR_ASSIGN, + OP_OR_ASSIGN, + + // Preprocessing token types. + // These types are used by the preprocessor internally. + // Preprocessor clients must not depend or check for them. + PP_HASH, + PP_NUMBER, + PP_OTHER + }; + enum Flags + { + AT_START_OF_LINE = 1 << 0, + HAS_LEADING_SPACE = 1 << 1, + EXPANSION_DISABLED = 1 << 2 + }; + + Token() : type(0), flags(0) { } + + void reset(); + bool equals(const Token& other) const; + + // Returns true if this is the first token on line. + // It disregards any leading whitespace. + bool atStartOfLine() const { return (flags & AT_START_OF_LINE) != 0; } + void setAtStartOfLine(bool start); + + bool hasLeadingSpace() const { return (flags & HAS_LEADING_SPACE) != 0; } + void setHasLeadingSpace(bool space); + + bool expansionDisabled() const { return (flags & EXPANSION_DISABLED) != 0; } + void setExpansionDisabled(bool disable); + + // Converts text into numeric value for CONST_INT and CONST_FLOAT token. + // Returns false if the parsed value cannot fit into an int or float. + bool iValue(int* value) const; + bool uValue(unsigned int* value) const; + bool fValue(float* value) const; + + int type; + unsigned int flags; + SourceLocation location; + std::string text; +}; + +inline bool operator==(const Token& lhs, const Token& rhs) +{ + return lhs.equals(rhs); +} + +inline bool operator!=(const Token& lhs, const Token& rhs) +{ + return !lhs.equals(rhs); +} + +extern std::ostream& operator<<(std::ostream& out, const Token& token); + +} // namepsace pp +#endif // COMPILER_PREPROCESSOR_TOKEN_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Tokenizer.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Tokenizer.h new file mode 100644 index 0000000000..a594d2d865 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/Tokenizer.h @@ -0,0 +1,58 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_TOKENIZER_H_ +#define COMPILER_PREPROCESSOR_TOKENIZER_H_ + +#include "Input.h" +#include "Lexer.h" +#include "pp_utils.h" + +namespace pp +{ + +class Diagnostics; + +class Tokenizer : public Lexer +{ + public: + struct Context + { + Diagnostics* diagnostics; + + Input input; + // The location where yytext points to. Token location should track + // scanLoc instead of Input::mReadLoc because they may not be the same + // if text is buffered up in the scanner input buffer. + Input::Location scanLoc; + + bool leadingSpace; + bool lineStart; + }; + static const size_t kMaxTokenLength; + + Tokenizer(Diagnostics* diagnostics); + ~Tokenizer(); + + bool init(int count, const char* const string[], const int length[]); + + void setFileNumber(int file); + void setLineNumber(int line); + + virtual void lex(Token* token); + + private: + PP_DISALLOW_COPY_AND_ASSIGN(Tokenizer); + bool initScanner(); + void destroyScanner(); + + void* mHandle; // Scanner handle. + Context mContext; // Scanner extra. +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_TOKENIZER_H_ + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Tokenizer.l b/src/3rdparty/angle/src/compiler/preprocessor/new/Tokenizer.l new file mode 100644 index 0000000000..9762988350 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/Tokenizer.l @@ -0,0 +1,340 @@ +/* +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +This file contains the Lex specification for GLSL ES preprocessor. +Based on Microsoft Visual Studio 2010 Preprocessor Grammar: +http://msdn.microsoft.com/en-us/library/2scxys89.aspx + +IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh. +*/ + +%top{ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// This file is auto-generated by generate_parser.sh. DO NOT EDIT! +} + +%{ +#include "Tokenizer.h" + +#include "Diagnostics.h" +#include "Token.h" + +#if defined(__GNUC__) +// Triggered by the auto-generated yy_fatal_error function. +#pragma GCC diagnostic ignored "-Wmissing-noreturn" +#endif + +typedef std::string YYSTYPE; +typedef pp::SourceLocation YYLTYPE; + +// Use the unused yycolumn variable to track file (string) number. +#define yyfileno yycolumn + +#define YY_USER_INIT \ + do { \ + yyfileno = 0; \ + yylineno = 1; \ + yyextra->leadingSpace = false; \ + yyextra->lineStart = true; \ + } while(0); + +#define YY_USER_ACTION \ + do \ + { \ + pp::Input* input = &yyextra->input; \ + pp::Input::Location* scanLoc = &yyextra->scanLoc; \ + while ((scanLoc->sIndex < input->count()) && \ + (scanLoc->cIndex >= input->length(scanLoc->sIndex))) \ + { \ + scanLoc->cIndex -= input->length(scanLoc->sIndex++); \ + ++yyfileno; yylineno = 1; \ + } \ + yylloc->file = yyfileno; \ + yylloc->line = yylineno; \ + scanLoc->cIndex += yyleng; \ + } while(0); + +#define YY_INPUT(buf, result, maxSize) \ + result = yyextra->input.read(buf, maxSize); + +%} + +%option noyywrap nounput never-interactive +%option reentrant bison-bridge bison-locations +%option prefix="pp" +%option extra-type="pp::Tokenizer::Context*" +%x COMMENT + +NEWLINE \n|\r|\r\n +IDENTIFIER [_a-zA-Z][_a-zA-Z0-9]* +PUNCTUATOR [][<>(){}.+-/*%^|&~=!:;,?] + +DECIMAL_CONSTANT [1-9][0-9]* +OCTAL_CONSTANT 0[0-7]* +HEXADECIMAL_CONSTANT 0[xX][0-9a-fA-F]+ + +DIGIT [0-9] +EXPONENT_PART [eE][+-]?{DIGIT}+ +FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".") + +%% + + /* Line comment */ +"//"[^\r\n]* + + /* Block comment */ + /* Line breaks are just counted - not returned. */ + /* The comment is replaced by a single space. */ +"/*" { BEGIN(COMMENT); } +<COMMENT>[^*\r\n]+ +<COMMENT>"*" +<COMMENT>{NEWLINE} { ++yylineno; } +<COMMENT>"*/" { + yyextra->leadingSpace = true; + BEGIN(INITIAL); +} + +# { + // # is only valid at start of line for preprocessor directives. + yylval->assign(1, yytext[0]); + return yyextra->lineStart ? pp::Token::PP_HASH : pp::Token::PP_OTHER; +} + +{IDENTIFIER} { + yylval->assign(yytext, yyleng); + return pp::Token::IDENTIFIER; +} + +{DECIMAL_CONSTANT}|{OCTAL_CONSTANT}|{HEXADECIMAL_CONSTANT} { + yylval->assign(yytext, yyleng); + return pp::Token::CONST_INT; +} + +({DIGIT}+{EXPONENT_PART})|({FRACTIONAL_CONSTANT}{EXPONENT_PART}?) { + yylval->assign(yytext, yyleng); + return pp::Token::CONST_FLOAT; +} + + /* Anything that starts with a {DIGIT} or .{DIGIT} must be a number. */ + /* Rule to catch all invalid integers and floats. */ +({DIGIT}+[_a-zA-Z0-9.]*)|("."{DIGIT}+[_a-zA-Z0-9.]*) { + yylval->assign(yytext, yyleng); + return pp::Token::PP_NUMBER; +} + +"++" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_INC; +} +"--" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_DEC; +} +"<<" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_LEFT; +} +">>" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_RIGHT; +} +"<=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_LE; +} +">=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_GE; +} +"==" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_EQ; +} +"!=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_NE; +} +"&&" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_AND; +} +"^^" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_XOR; +} +"||" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_OR; +} +"+=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_ADD_ASSIGN; +} +"-=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_SUB_ASSIGN; +} +"*=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_MUL_ASSIGN; +} +"/=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_DIV_ASSIGN; +} +"%=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_MOD_ASSIGN; +} +"<<=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_LEFT_ASSIGN; +} +">>=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_RIGHT_ASSIGN; +} +"&=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_AND_ASSIGN; +} +"^=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_XOR_ASSIGN; +} +"|=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_OR_ASSIGN; +} + +{PUNCTUATOR} { + yylval->assign(1, yytext[0]); + return yytext[0]; +} + +[ \t\v\f]+ { yyextra->leadingSpace = true; } + +{NEWLINE} { + ++yylineno; + yylval->assign(1, '\n'); + return '\n'; +} + +. { + yylval->assign(1, yytext[0]); + return pp::Token::PP_OTHER; +} + +<*><<EOF>> { + // YY_USER_ACTION is not invoked for handling EOF. + // Set the location for EOF token manually. + pp::Input* input = &yyextra->input; + pp::Input::Location* scanLoc = &yyextra->scanLoc; + int sIndexMax = std::max(0, input->count() - 1); + if (scanLoc->sIndex != sIndexMax) + { + // We can only reach here if there are empty strings at the + // end of the input. + scanLoc->sIndex = sIndexMax; scanLoc->cIndex = 0; + yyfileno = sIndexMax; yylineno = 1; + } + yylloc->file = yyfileno; + yylloc->line = yylineno; + yylval->clear(); + + if (YY_START == COMMENT) + { + yyextra->diagnostics->report(pp::Diagnostics::EOF_IN_COMMENT, + pp::SourceLocation(yyfileno, yylineno), + ""); + } + yyterminate(); +} + +%% + +namespace pp { + +// TODO(alokp): Maximum token length should ideally be specified by +// the preprocessor client, i.e., the compiler. +const size_t Tokenizer::kMaxTokenLength = 256; + +Tokenizer::Tokenizer(Diagnostics* diagnostics) : mHandle(0) +{ + mContext.diagnostics = diagnostics; +} + +Tokenizer::~Tokenizer() +{ + destroyScanner(); +} + +bool Tokenizer::init(int count, const char* const string[], const int length[]) +{ + if (count < 0) return false; + if ((count > 0) && (string == 0)) return false; + + mContext.input = Input(count, string, length); + return initScanner(); +} + +void Tokenizer::setFileNumber(int file) +{ + // We use column number as file number. + // See macro yyfileno. + yyset_column(file, mHandle); +} + +void Tokenizer::setLineNumber(int line) +{ + yyset_lineno(line, mHandle); +} + +void Tokenizer::lex(Token* token) +{ + token->type = yylex(&token->text, &token->location, mHandle); + if (token->text.size() > kMaxTokenLength) + { + mContext.diagnostics->report(Diagnostics::TOKEN_TOO_LONG, + token->location, token->text); + token->text.erase(kMaxTokenLength); + } + + token->flags = 0; + + token->setAtStartOfLine(mContext.lineStart); + mContext.lineStart = token->type == '\n'; + + token->setHasLeadingSpace(mContext.leadingSpace); + mContext.leadingSpace = false; +} + +bool Tokenizer::initScanner() +{ + if ((mHandle == NULL) && yylex_init_extra(&mContext, &mHandle)) + return false; + + yyrestart(0, mHandle); + return true; +} + +void Tokenizer::destroyScanner() +{ + if (mHandle == NULL) + return; + + yylex_destroy(mHandle); + mHandle = NULL; +} + +} // namespace pp + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/numeric_lex.h b/src/3rdparty/angle/src/compiler/preprocessor/new/numeric_lex.h new file mode 100644 index 0000000000..b04125d230 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/numeric_lex.h @@ -0,0 +1,61 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// numeric_lex.h: Functions to extract numeric values from string. + +#ifndef COMPILER_PREPROCESSOR_NUMERIC_LEX_H_ +#define COMPILER_PREPROCESSOR_NUMERIC_LEX_H_ + +#include <sstream> + +namespace pp { + +inline std::ios::fmtflags numeric_base_int(const std::string& str) +{ + if ((str.size() >= 2) && + (str[0] == '0') && + (str[1] == 'x' || str[1] == 'X')) + { + return std::ios::hex; + } + else if ((str.size() >= 1) && (str[0] == '0')) + { + return std::ios::oct; + } + return std::ios::dec; +} + +// The following functions parse the given string to extract a numerical +// value of the given type. These functions assume that the string is +// of the correct form. They can only fail if the parsed value is too big, +// in which case false is returned. + +template<typename IntType> +bool numeric_lex_int(const std::string& str, IntType* value) +{ + std::istringstream stream(str); + // This should not be necessary, but MSVS has a buggy implementation. + // It returns incorrect results if the base is not specified. + stream.setf(numeric_base_int(str), std::ios::basefield); + + stream >> (*value); + return !stream.fail(); +} + +template<typename FloatType> +bool numeric_lex_float(const std::string& str, FloatType* value) +{ + std::istringstream stream(str); + // Force "C" locale so that decimal character is always '.', and + // not dependent on the current locale. + stream.imbue(std::locale::classic()); + + stream >> (*value); + return !stream.fail(); +} + +} // namespace pp. +#endif // COMPILER_PREPROCESSOR_NUMERIC_LEX_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/pp_utils.h b/src/3rdparty/angle/src/compiler/preprocessor/new/pp_utils.h new file mode 100644 index 0000000000..17164ea8b0 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/new/pp_utils.h @@ -0,0 +1,18 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// pp_utils.h: Common preprocessor utilities + +#ifndef COMPILER_PREPROCESSOR_PPUTILS_H_ +#define COMPILER_PREPROCESSOR_PPUTILS_H_ + +// A macro to disallow the copy constructor and operator= functions +// This must be used in the private: declarations for a class. +#define PP_DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +#endif // COMPILER_PREPROCESSOR_PPUTILS_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/parser.h b/src/3rdparty/angle/src/compiler/preprocessor/parser.h new file mode 100644 index 0000000000..f67342b670 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/parser.h @@ -0,0 +1,93 @@ +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ + +#ifndef BISON_PARSER_H +# define BISON_PARSER_H + +#ifndef yystypepp +typedef struct { + int sc_int; + float sc_fval; + int sc_ident; + char symbol_name[MAX_SYMBOL_NAME_LEN+1]; +} yystypepp; + +# define YYSTYPE_IS_TRIVIAL 1 +#endif +# define CPP_AND_OP 257 +# define CPP_SUB_ASSIGN 259 +# define CPP_MOD_ASSIGN 260 +# define CPP_ADD_ASSIGN 261 +# define CPP_DIV_ASSIGN 262 +# define CPP_MUL_ASSIGN 263 +# define CPP_EQ_OP 264 +# define CPP_XOR_OP 265 +# define ERROR_SY 266 +# define CPP_FLOATCONSTANT 267 +# define CPP_GE_OP 268 +# define CPP_RIGHT_OP 269 +# define CPP_IDENTIFIER 270 +# define CPP_INTCONSTANT 271 +# define CPP_LE_OP 272 +# define CPP_LEFT_OP 273 +# define CPP_DEC_OP 274 +# define CPP_NE_OP 275 +# define CPP_OR_OP 276 +# define CPP_INC_OP 277 +# define CPP_STRCONSTANT 278 +# define CPP_TYPEIDENTIFIER 279 + +# define FIRST_USER_TOKEN_SY 289 + +# define CPP_RIGHT_ASSIGN 280 +# define CPP_LEFT_ASSIGN 281 +# define CPP_AND_ASSIGN 282 +# define CPP_OR_ASSIGN 283 +# define CPP_XOR_ASSIGN 284 +# define CPP_LEFT_BRACKET 285 +# define CPP_RIGHT_BRACKET 286 +# define CPP_LEFT_BRACE 287 +# define CPP_RIGHT_BRACE 288 + +#endif /* not BISON_PARSER_H */ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/preprocess.h b/src/3rdparty/angle/src/compiler/preprocessor/preprocess.h new file mode 100644 index 0000000000..15056da2c9 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/preprocess.h @@ -0,0 +1,50 @@ +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ + +#include "compiler/preprocessor/slglobals.h" +extern CPPStruct *cpp; +int InitCPPStruct(void); +int InitScanner(CPPStruct *cpp); +int InitAtomTable(AtomTable *atable, int htsize); +char* GetStringOfAtom(AtomTable *atable, int atom); diff --git a/src/3rdparty/angle/src/compiler/preprocessor/scanner.c b/src/3rdparty/angle/src/compiler/preprocessor/scanner.c new file mode 100644 index 0000000000..fde853c1e0 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/scanner.c @@ -0,0 +1,698 @@ +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// scanner.c +// + +#include <assert.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#if 0 + #include <ieeefp.h> +#else + #define isinff(x) (((*(int *)&(x) & 0x7f800000L)==0x7f800000L) && \ + ((*(int *)&(x) & 0x007fffffL)==0000000000L)) +#endif + +#include "compiler/preprocessor/slglobals.h" +#include "compiler/util.h" + +typedef struct StringInputSrc { + InputSrc base; + char *p; +} StringInputSrc; + +static int ScanFromString(const char *s); + +static int eof_scan(InputSrc *is, yystypepp * yylvalpp) +{ + return EOF; +} // eof_scan + +static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) {} + +static InputSrc eof_inputsrc = { 0, &eof_scan, &eof_scan, &noop, 0, 0 }; + +static int byte_scan(InputSrc *, yystypepp * yylvalpp); + +#define EOL_SY '\n' + +#if defined(_MSC_VER) + #define DBG_BREAKPOINT() __asm int 3 +#elif defined(_M_AMD64) + #define DBG_BREAKPOINT() assert(!"Dbg_Breakpoint"); +#else + #define DBG_BREAKPOINT() +#endif + +#if defined(_MSC_VER) && !defined(_M_AMD64) + __int64 RDTSC ( void ) { + + __int64 v; + + __asm __emit 0x0f + __asm __emit 0x31 + __asm mov dword ptr v, eax + __asm mov dword ptr v+4, edx + + return v; + } +#endif + + +int InitScanner(CPPStruct *cpp) +{ + // Add various atoms needed by the CPP line scanner: + if (!InitCPP()) + return 0; + + cpp->mostRecentToken = 0; + cpp->tokenLoc = &cpp->ltokenLoc; + + cpp->ltokenLoc.file = 0; + cpp->ltokenLoc.line = 0; + + cpp->currentInput = &eof_inputsrc; + cpp->previous_token = '\n'; + cpp->pastFirstStatement = 0; + + return 1; +} // InitScanner + +int FreeScanner(void) +{ + return (FreeCPP()); +} + +int InitScannerInput(CPPStruct *cpp, int count, const char* const string[], const int length[]) +{ + cpp->PaWhichStr = 0; + cpp->PaArgv = string; + cpp->PaArgc = count; + cpp->PaStrLen = length; + ScanFromString(string[0]); + return 0; +} + +/* + * str_getch() + * takes care of reading from multiple strings. + * returns the next-char from the input stream. + * returns EOF when the complete shader is parsed. + */ +static int str_getch(StringInputSrc *in) +{ + for(;;){ + if (*in->p){ + if (*in->p == '\n') { + in->base.line++; + IncLineNumber(); + } + return *in->p++; + } + if(++(cpp->PaWhichStr) < cpp->PaArgc){ + free(in); + SetStringNumber(cpp->PaWhichStr); + SetLineNumber(1); + ScanFromString(cpp->PaArgv[cpp->PaWhichStr]); + in=(StringInputSrc*)cpp->currentInput; + continue; + } + else{ + cpp->currentInput = in->base.prev; + cpp->PaWhichStr=0; + free(in); + return EOF; + } + } +} // str_getch + +static void str_ungetch(StringInputSrc *in, int ch, yystypepp *type) { + if (in->p[-1] == ch)in->p--; + else { + *(in->p)='\0'; //this would take care of shifting to the previous string. + cpp->PaWhichStr--; + } + if (ch == '\n') { + in->base.line--; + DecLineNumber(); + } +} // str_ungetch + +int ScanFromString(const char *s) +{ + + StringInputSrc *in = malloc(sizeof(StringInputSrc)); + memset(in, 0, sizeof(StringInputSrc)); + in->p = (char*) s; + in->base.line = 1; + in->base.scan = byte_scan; + in->base.getch = (int (*)(InputSrc *, yystypepp *))str_getch; + in->base.ungetch = (void (*)(InputSrc *, int, yystypepp *))str_ungetch; + in->base.prev = cpp->currentInput; + cpp->currentInput = &in->base; + + return 1; +} // ScanFromString; + + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////// Floating point constants: ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +#define APPEND_CHAR_S(ch, str, len, max_len) \ + if (len < max_len) { \ + str[len++] = ch; \ + } else if (!alreadyComplained) { \ + CPPErrorToInfoLog("BUFFER OVERFLOW"); \ + alreadyComplained = 1; \ + } + +/* + * lFloatConst() - Scan a floating point constant. Assumes that the scanner + * has seen at least one digit, followed by either a decimal '.' or the + * letter 'e'. + * ch - '.' or 'e' + * len - length of string already copied into yylvalpp->symbol_name. + */ + +static int lFloatConst(int ch, int len, yystypepp * yylvalpp) +{ + int alreadyComplained = 0; + assert((ch == '.') || (ch == 'e') || (ch == 'E')); + + if (ch == '.') { + do { + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } while (ch >= '0' && ch <= '9'); + } + + // Exponent: + if (ch == 'e' || ch == 'E') { + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '+') { + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } else if (ch == '-') { + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } + if (ch >= '0' && ch <= '9') { + while (ch >= '0' && ch <= '9') { + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } + } else { + CPPErrorToInfoLog("EXPONENT INVALID"); + } + } + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + + assert(len <= MAX_SYMBOL_NAME_LEN); + yylvalpp->symbol_name[len] = '\0'; + yylvalpp->sc_fval = (float) atof_dot(yylvalpp->symbol_name); + if (isinff(yylvalpp->sc_fval)) { + CPPErrorToInfoLog("FLOAT CONSTANT OVERFLOW"); + } + return CPP_FLOATCONSTANT; +} // lFloatConst + +/////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////// Normal Scanner ////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +static int byte_scan(InputSrc *in, yystypepp * yylvalpp) +{ + char string_val[MAX_STRING_LEN + 1]; + int alreadyComplained = 0; + int len, ch, ii, ival = 0; + + for (;;) { + yylvalpp->sc_int = 0; + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + + while (ch == ' ' || ch == '\t' || ch == '\r') { + yylvalpp->sc_int = 1; + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } + + cpp->ltokenLoc.file = cpp->currentInput->name; + cpp->ltokenLoc.line = cpp->currentInput->line; + alreadyComplained = 0; + len = 0; + switch (ch) { + default: + return ch; // Single character token + case EOF: + return -1; + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': case '_': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': + do { + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } while ((ch >= 'a' && ch <= 'z') || + (ch >= 'A' && ch <= 'Z') || + (ch >= '0' && ch <= '9') || + ch == '_'); + assert(len <= MAX_SYMBOL_NAME_LEN); + yylvalpp->symbol_name[len] = '\0'; + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + yylvalpp->sc_ident = LookUpAddString(atable, yylvalpp->symbol_name); + return CPP_IDENTIFIER; + break; + case '0': + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == 'x' || ch == 'X') { // hexadecimal integer constants + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if ((ch >= '0' && ch <= '9') || + (ch >= 'A' && ch <= 'F') || + (ch >= 'a' && ch <= 'f')) + { + ival = 0; + do { + if ((ival <= 0x0fffffff) && (len < MAX_SYMBOL_NAME_LEN)) { + yylvalpp->symbol_name[len++] = ch; + if (ch >= '0' && ch <= '9') { + ii = ch - '0'; + } else if (ch >= 'A' && ch <= 'F') { + ii = ch - 'A' + 10; + } else { + ii = ch - 'a' + 10; + } + ival = (ival << 4) | ii; + } else if (!alreadyComplained) { + CPPErrorToInfoLog("HEX CONSTANT OVERFLOW"); + alreadyComplained = 1; + } + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } while ((ch >= '0' && ch <= '9') || + (ch >= 'A' && ch <= 'F') || + (ch >= 'a' && ch <= 'f')); + } else { + CPPErrorToInfoLog("HEX CONSTANT INVALID"); + } + assert(len <= MAX_SYMBOL_NAME_LEN); + yylvalpp->symbol_name[len] = '\0'; + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + yylvalpp->sc_int = ival; + return CPP_INTCONSTANT; + } else if (ch >= '0' && ch <= '7') { // octal integer constants + ival = 0; + do { + if ((ival <= 0x1fffffff) && (len < MAX_SYMBOL_NAME_LEN)) { + yylvalpp->symbol_name[len++] = ch; + ii = ch - '0'; + ival = (ival << 3) | ii; + } else if (!alreadyComplained) { + CPPErrorToInfoLog("OCT CONSTANT OVERFLOW"); + alreadyComplained = 1; + } + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } while (ch >= '0' && ch <= '7'); + if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') + return lFloatConst(ch, len, yylvalpp); + assert(len <= MAX_SYMBOL_NAME_LEN); + yylvalpp->symbol_name[len] = '\0'; + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + yylvalpp->sc_int = ival; + return CPP_INTCONSTANT; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + ch = '0'; + } + // Fall through... + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + do { + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } while (ch >= '0' && ch <= '9'); + if (ch == '.' || ch == 'e' || ch == 'E') { + return lFloatConst(ch, len, yylvalpp); + } else { + assert(len <= MAX_SYMBOL_NAME_LEN); + yylvalpp->symbol_name[len] = '\0'; + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + ival = 0; + for (ii = 0; ii < len; ii++) { + ch = yylvalpp->symbol_name[ii] - '0'; + ival = ival*10 + ch; + if ((ival > 214748364) || (ival == 214748364 && ch >= 8)) { + CPPErrorToInfoLog("INTEGER CONSTANT OVERFLOW"); + break; + } + } + yylvalpp->sc_int = ival; + if(ival==0) + strcpy(yylvalpp->symbol_name,"0"); + return CPP_INTCONSTANT; + } + break; + case '-': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '-') { + return CPP_DEC_OP; + } else if (ch == '=') { + return CPP_SUB_ASSIGN; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '-'; + } + case '+': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '+') { + return CPP_INC_OP; + } else if (ch == '=') { + return CPP_ADD_ASSIGN; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '+'; + } + case '*': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '=') { + return CPP_MUL_ASSIGN; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '*'; + } + case '%': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '=') { + return CPP_MOD_ASSIGN; + } else if (ch == '>'){ + return CPP_RIGHT_BRACE; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '%'; + } + case ':': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '>') { + return CPP_RIGHT_BRACKET; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return ':'; + } + case '^': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '^') { + return CPP_XOR_OP; + } else { + if (ch == '=') + return CPP_XOR_ASSIGN; + else{ + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '^'; + } + } + + case '=': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '=') { + return CPP_EQ_OP; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '='; + } + case '!': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '=') { + return CPP_NE_OP; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '!'; + } + case '|': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '|') { + return CPP_OR_OP; + } else { + if (ch == '=') + return CPP_OR_ASSIGN; + else{ + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '|'; + } + } + case '&': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '&') { + return CPP_AND_OP; + } else { + if (ch == '=') + return CPP_AND_ASSIGN; + else{ + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '&'; + } + } + case '<': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '<') { + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if(ch == '=') + return CPP_LEFT_ASSIGN; + else{ + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return CPP_LEFT_OP; + } + } else { + if (ch == '=') { + return CPP_LE_OP; + } else { + if (ch == '%') + return CPP_LEFT_BRACE; + else if (ch == ':') + return CPP_LEFT_BRACKET; + else{ + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '<'; + } + } + } + case '>': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '>') { + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if(ch == '=') + return CPP_RIGHT_ASSIGN; + else{ + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return CPP_RIGHT_OP; + } + } else { + if (ch == '=') { + return CPP_GE_OP; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '>'; + } + } + case '.': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch >= '0' && ch <= '9') { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return lFloatConst('.', 0, yylvalpp); + } else { + if (ch == '.') { + return -1; // Special EOF hack + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '.'; + } + } + case '/': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '/') { + do { + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } while (ch != '\n' && ch != EOF); + if (ch == EOF) + return -1; + return '\n'; + } else if (ch == '*') { + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + do { + while (ch != '*') { + if (ch == EOF) { + CPPErrorToInfoLog("EOF IN COMMENT"); + return -1; + } + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == EOF) { + CPPErrorToInfoLog("EOF IN COMMENT"); + return -1; + } + } while (ch != '/'); + // Go try it again... + } else if (ch == '=') { + return CPP_DIV_ASSIGN; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '/'; + } + break; + case '"': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + while (ch != '"' && ch != '\n' && ch != EOF) { + if (ch == '\\') { + CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language"); + return -1; + } + APPEND_CHAR_S(ch, string_val, len, MAX_STRING_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + }; + assert(len <= MAX_STRING_LEN); + string_val[len] = '\0'; + if (ch == '"') { + yylvalpp->sc_ident = LookUpAddString(atable, string_val); + return CPP_STRCONSTANT; + } else { + CPPErrorToInfoLog("EOL IN STRING"); + return ERROR_SY; + } + break; + } + } +} // byte_scan + +int yylex_CPP(char* buf, int maxSize) +{ + yystypepp yylvalpp; + int token = '\n'; + + for(;;) { + + char* tokenString = 0; + token = cpp->currentInput->scan(cpp->currentInput, &yylvalpp); + if(check_EOF(token)) + return 0; + if (token < 0) { + // This check may need to be improved to support UTF-8 + // characters in comments. + CPPErrorToInfoLog("preprocessor encountered non-ASCII character in shader source"); + return 0; + } + if (token == '#') { + if (cpp->previous_token == '\n'|| cpp->previous_token == 0) { + token = readCPPline(&yylvalpp); + if(check_EOF(token)) + return 0; + continue; + } else { + CPPErrorToInfoLog("preprocessor command must not be preceded by any other statement in that line"); + return 0; + } + } + cpp->previous_token = token; + // expand macros + if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp.sc_ident, &yylvalpp)) { + cpp->pastFirstStatement = 1; + continue; + } + + if (token == '\n') + continue; + cpp->pastFirstStatement = 1; + + if (token == CPP_IDENTIFIER) { + tokenString = GetStringOfAtom(atable,yylvalpp.sc_ident); + } else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){ + tokenString = yylvalpp.symbol_name; + } else { + tokenString = GetStringOfAtom(atable,token); + } + + if (tokenString) { + int len = strlen(tokenString); + cpp->tokensBeforeEOF = 1; + if (len >= maxSize) { + return maxSize; + } else if (len > 0) { + strcpy(buf, tokenString); + return len; + } + + return 0; + } + } +} // yylex + +//Checks if the token just read is EOF or not. +int check_EOF(int token) +{ + if(token==-1){ + if(cpp->ifdepth >0){ + CPPErrorToInfoLog("#endif missing!! Compilation stopped"); + cpp->CompileError=1; + } + return 1; + } + return 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////// End of scanner.c ////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/scanner.h b/src/3rdparty/angle/src/compiler/preprocessor/scanner.h new file mode 100644 index 0000000000..b67c1d644e --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/scanner.h @@ -0,0 +1,81 @@ +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// scanner.h +// + +#if !defined(__SCANNER_H) +#define __SCANNER_H 1 + +#include "compiler/preprocessor/length_limits.h" +#include "compiler/preprocessor/parser.h" + +// Not really atom table stuff but needed first... + +typedef struct SourceLoc_Rec { + unsigned short file, line; +} SourceLoc; + +int yylex_CPP(char* buf, int maxSize); + +typedef struct InputSrc { + struct InputSrc *prev; + int (*scan)(struct InputSrc *, yystypepp *); + int (*getch)(struct InputSrc *, yystypepp *); + void (*ungetch)(struct InputSrc *, int, yystypepp *); + int name; /* atom */ + int line; +} InputSrc; + +int InitScanner(CPPStruct *cpp); // Intialise the cpp scanner. +int InitScannerInput(CPPStruct *cpp, int count, const char* const string[], const int length[]); +int check_EOF(int); // check if we hit a EOF abruptly +void CPPErrorToInfoLog(const char *); // sticking the msg,line into the Shader's.Info.log +void SetLineNumber(int); +void SetStringNumber(int); +void IncLineNumber(void); +void DecLineNumber(void); +int FreeScanner(void); // Free the cpp scanner +#endif // !(defined(__SCANNER_H) + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/slglobals.h b/src/3rdparty/angle/src/compiler/preprocessor/slglobals.h new file mode 100644 index 0000000000..4634626643 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/slglobals.h @@ -0,0 +1,82 @@ +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// slglobals.h +// + +#if !defined(__SLGLOBALS_H) +#define __SLGLOBALS_H 1 + +typedef struct CPPStruct_Rec CPPStruct; + +extern CPPStruct *cpp; + +#undef CPPC_DEBUG_THE_COMPILER +#if defined(_DEBUG) +#define CPPC_DEBUG_THE_COMPILER 1 +#endif + +#undef CPPC_ENABLE_TOOLS +#define CPPC_ENABLE_TOOLS 1 + +#include "compiler/preprocessor/memory.h" +#include "compiler/preprocessor/atom.h" +#include "compiler/preprocessor/scanner.h" +#include "compiler/preprocessor/cpp.h" +#include "compiler/preprocessor/tokens.h" +#include "compiler/preprocessor/symbols.h" +#include "compiler/preprocessor/compile.h" +#if !defined(NO_PARSER) +#include "compiler/preprocessor/parser.h" +#endif + +#if !defined(NULL) +#define NULL 0 +#endif + +#endif // !(defined(__SLGLOBALS_H) + + + + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/symbols.c b/src/3rdparty/angle/src/compiler/preprocessor/symbols.c new file mode 100644 index 0000000000..f18b2569b3 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/symbols.c @@ -0,0 +1,288 @@ +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// symbols.c +// + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "compiler/preprocessor/slglobals.h" + +#if defined(_MSC_VER) +#pragma warning(disable: 4706) +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////// Symbol Table Variables: /////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +Scope *ScopeList = NULL; +Scope *CurrentScope = NULL; +Scope *GlobalScope = NULL; + +static void unlinkScope(void *_scope) { + Scope *scope = _scope; + + if (scope->next) + scope->next->prev = scope->prev; + if (scope->prev) + scope->prev->next = scope->next; + else + ScopeList = scope->next; +} + +/* + * NewScope() + * + */ +Scope *NewScopeInPool(MemoryPool *pool) +{ + Scope *lScope; + + lScope = mem_Alloc(pool, sizeof(Scope)); + lScope->pool = pool; + lScope->parent = NULL; + lScope->funScope = NULL; + lScope->symbols = NULL; + + lScope->level = 0; + + lScope->programs = NULL; + if ((lScope->next = ScopeList)) + ScopeList->prev = lScope; + lScope->prev = 0; + ScopeList = lScope; + mem_AddCleanup(pool, unlinkScope, lScope); + return lScope; +} // NewScope + +/* + * PushScope() + * + */ + +void PushScope(Scope *fScope) +{ + Scope *lScope; + + if (CurrentScope) { + fScope->level = CurrentScope->level + 1; + if (fScope->level == 1) { + if (!GlobalScope) { + /* HACK - CTD -- if GlobalScope==NULL and level==1, we're + * defining a function in the superglobal scope. Things + * will break if we leave the level as 1, so we arbitrarily + * set it to 2 */ + fScope->level = 2; + } + } + if (fScope->level >= 2) { + lScope = fScope; + while (lScope->level > 2) + lScope = lScope->next; + fScope->funScope = lScope; + } + } else { + fScope->level = 0; + } + fScope->parent = CurrentScope; + CurrentScope = fScope; +} // PushScope + +/* + * PopScope() + * + */ + +Scope *PopScope(void) +{ + Scope *lScope; + + lScope = CurrentScope; + if (CurrentScope) + CurrentScope = CurrentScope->parent; + return lScope; +} // PopScope + +/* + * NewSymbol() - Allocate a new symbol node; + * + */ + +Symbol *NewSymbol(SourceLoc *loc, Scope *fScope, int name, symbolkind kind) +{ + Symbol *lSymb; + char *pch; + unsigned int ii; + + lSymb = (Symbol *) mem_Alloc(fScope->pool, sizeof(Symbol)); + lSymb->left = NULL; + lSymb->right = NULL; + lSymb->next = NULL; + lSymb->name = name; + lSymb->loc = *loc; + lSymb->kind = kind; + + // Clear union area: + + pch = (char *) &lSymb->details; + for (ii = 0; ii < sizeof(lSymb->details); ii++) + *pch++ = 0; + return lSymb; +} // NewSymbol + +/* + * lAddToTree() - Using a binary tree is not a good idea for basic atom values because they + * are generated in order. We'll fix this later (by reversing the bit pattern). + */ + +static void lAddToTree(Symbol **fSymbols, Symbol *fSymb) +{ + Symbol *lSymb; + int lrev, frev; + + lSymb = *fSymbols; + if (lSymb) { + frev = GetReversedAtom(atable, fSymb->name); + while (lSymb) { + lrev = GetReversedAtom(atable, lSymb->name); + if (lrev == frev) { + CPPErrorToInfoLog("GetAtomString(atable, fSymb->name)"); + break; + } else { + if (lrev > frev) { + if (lSymb->left) { + lSymb = lSymb->left; + } else { + lSymb->left = fSymb; + break; + } + } else { + if (lSymb->right) { + lSymb = lSymb->right; + } else { + lSymb->right = fSymb; + break; + } + } + } + } + } else { + *fSymbols = fSymb; + } +} // lAddToTree + + +/* + * AddSymbol() - Add a variable, type, or function name to a scope. + * + */ + +Symbol *AddSymbol(SourceLoc *loc, Scope *fScope, int atom, symbolkind kind) +{ + Symbol *lSymb; + + if (!fScope) + fScope = CurrentScope; + lSymb = NewSymbol(loc, fScope, atom, kind); + lAddToTree(&fScope->symbols, lSymb); + return lSymb; +} // AddSymbol + + +/*********************************************************************************************/ +/************************************ Symbol Semantic Functions ******************************/ +/*********************************************************************************************/ + +/* + * LookUpLocalSymbol() + * + */ + +Symbol *LookUpLocalSymbol(Scope *fScope, int atom) +{ + Symbol *lSymb; + int rname, ratom; + + ratom = GetReversedAtom(atable, atom); + if (!fScope) + fScope = CurrentScope; + lSymb = fScope->symbols; + while (lSymb) { + rname = GetReversedAtom(atable, lSymb->name); + if (rname == ratom) { + return lSymb; + } else { + if (rname > ratom) { + lSymb = lSymb->left; + } else { + lSymb = lSymb->right; + } + } + } + return NULL; +} // LookUpLocalSymbol + +/* + * LookUpSymbol() + * + */ + +Symbol *LookUpSymbol(Scope *fScope, int atom) +{ + Symbol *lSymb; + + if (!fScope) + fScope = CurrentScope; + while (fScope) { + lSymb = LookUpLocalSymbol(fScope, atom); + if (lSymb) + return lSymb; + fScope = fScope->parent; + } + return NULL; +} // LookUpSymbol + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/symbols.h b/src/3rdparty/angle/src/compiler/preprocessor/symbols.h new file mode 100644 index 0000000000..e7d0b075fa --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/symbols.h @@ -0,0 +1,111 @@ +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// symbols.h +// + +#if !defined(__SYMBOLS_H) +#define __SYMBOLS_H 1 + +#include "compiler/preprocessor/memory.h" + +typedef enum symbolkind { + MACRO_S +} symbolkind; + +// Typedefs for things defined here in "symbols.h": + +typedef struct Scope_Rec Scope; +typedef struct Symbol_Rec Symbol; + +typedef struct SymbolList_Rec { + struct SymbolList_Rec *next; + Symbol *symb; +} SymbolList; + +struct Scope_Rec { + Scope *next, *prev; // doubly-linked list of all scopes + Scope *parent; + Scope *funScope; // Points to base scope of enclosing function + MemoryPool *pool; // pool used for allocation in this scope + Symbol *symbols; + + int level; // 0 = super globals, 1 = globals, etc. + + // Only used at global scope (level 1): + SymbolList *programs; // List of programs for this compilation. +}; + + +// Symbol table is a simple binary tree. + +#include "compiler/preprocessor/cpp.h" // to get MacroSymbol def + +struct Symbol_Rec { + Symbol *left, *right; + Symbol *next; + int name; // Name atom + SourceLoc loc; + symbolkind kind; + union { + MacroSymbol mac; + } details; +}; + +extern Scope *CurrentScope; +extern Scope *GlobalScope; +extern Scope *ScopeList; + +Scope *NewScopeInPool(MemoryPool *); +#define NewScope() NewScopeInPool(CurrentScope->pool) +void PushScope(Scope *fScope); +Scope *PopScope(void); +Symbol *NewSymbol(SourceLoc *loc, Scope *fScope, int name, symbolkind kind); +Symbol *AddSymbol(SourceLoc *loc, Scope *fScope, int atom, symbolkind kind); +Symbol *LookUpLocalSymbol(Scope *fScope, int atom); +Symbol *LookUpSymbol(Scope *fScope, int atom); + + +#endif // !defined(__SYMBOLS_H) + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/tokens.c b/src/3rdparty/angle/src/compiler/preprocessor/tokens.c new file mode 100644 index 0000000000..b94c05ebd4 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/tokens.c @@ -0,0 +1,467 @@ +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// tokens.c +// + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +#include "common/angleutils.h" +#include "compiler/debug.h" +#include "compiler/preprocessor/slglobals.h" +#include "compiler/util.h" + +#if defined(_MSC_VER) +#pragma warning(disable: 4054) +#pragma warning(disable: 4152) +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////// Preprocessor and Token Recorder and Playback: //////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +/* + * idstr() + * Copy a string to a malloc'ed block and convert it into something suitable + * for an ID + * + */ + +static char *idstr(const char *fstr, MemoryPool *pool) +{ + size_t len; + char *str, *t; + const char *f; + + len = strlen(fstr); + if (!pool) + str = (char *) malloc(len + 1); + else + str = (char *) mem_Alloc(pool, len + 1); + + for (f=fstr, t=str; *f; f++) { + if (isalnum(*f)) *t++ = *f; + else if (*f == '.' || *f == '/') *t++ = '_'; + } + *t = 0; + return str; +} // idstr + + +/* + * lNewBlock() + * + */ + +static TokenBlock *lNewBlock(TokenStream *fTok, MemoryPool *pool) +{ + TokenBlock *lBlock; + + if (!pool) + lBlock = (TokenBlock *) malloc(sizeof(TokenBlock) + 256); + else + lBlock = (TokenBlock *) mem_Alloc(pool, sizeof(TokenBlock) + 256); + lBlock->count = 0; + lBlock->current = 0; + lBlock->data = (unsigned char *) lBlock + sizeof(TokenBlock); + lBlock->max = 256; + lBlock->next = NULL; + if (fTok->head) { + fTok->current->next = lBlock; + } else { + fTok->head = lBlock; + } + fTok->current = lBlock; + return lBlock; +} // lNewBlock + +/* + * lAddByte() + * + */ + +static void lAddByte(TokenStream *fTok, unsigned char fVal) +{ + TokenBlock *lBlock; + lBlock = fTok->current; + if (lBlock->count >= lBlock->max) + lBlock = lNewBlock(fTok, 0); + lBlock->data[lBlock->count++] = fVal; +} // lAddByte + + + +/* + * lReadByte() - Get the next byte from a stream. + * + */ + +static int lReadByte(TokenStream *pTok) +{ + TokenBlock *lBlock; + int lval = -1; + + lBlock = pTok->current; + if (lBlock) { + if (lBlock->current >= lBlock->count) { + lBlock = lBlock->next; + if (lBlock) + lBlock->current = 0; + pTok->current = lBlock; + } + if (lBlock) + lval = lBlock->data[lBlock->current++]; + } + return lval; +} // lReadByte + +/////////////////////////////////////// Global Functions:////////////////////////////////////// + +/* + * NewTokenStream() + * + */ + +TokenStream *NewTokenStream(const char *name, MemoryPool *pool) +{ + TokenStream *pTok; + + if (!pool) + pTok = (TokenStream *) malloc(sizeof(TokenStream)); + else + pTok = (TokenStream*)mem_Alloc(pool, sizeof(TokenStream)); + pTok->next = NULL; + pTok->name = idstr(name, pool); + pTok->head = NULL; + pTok->current = NULL; + lNewBlock(pTok, pool); + return pTok; +} // NewTokenStream + +/* + * DeleteTokenStream() + * + */ + +void DeleteTokenStream(TokenStream *pTok) +{ + TokenBlock *pBlock, *nBlock; + + if (pTok) { + pBlock = pTok->head; + while (pBlock) { + nBlock = pBlock->next; + free(pBlock); + pBlock = nBlock; + } + if (pTok->name) + free(pTok->name); + free(pTok); + } +} // DeleteTokenStream + +/* + * RecordToken() - Add a token to the end of a list for later playback or printout. + * + */ + +void RecordToken(TokenStream *pTok, int token, yystypepp * yylvalpp) +{ + const char *s; + char *str=NULL; + + if (token > 256) + lAddByte(pTok, (unsigned char)((token & 0x7f) + 0x80)); + else + lAddByte(pTok, (unsigned char)(token & 0x7f)); + switch (token) { + case CPP_IDENTIFIER: + case CPP_TYPEIDENTIFIER: + case CPP_STRCONSTANT: + s = GetAtomString(atable, yylvalpp->sc_ident); + while (*s) + lAddByte(pTok, (unsigned char) *s++); + lAddByte(pTok, 0); + break; + case CPP_FLOATCONSTANT: + case CPP_INTCONSTANT: + str=yylvalpp->symbol_name; + while (*str){ + lAddByte(pTok, (unsigned char) *str++); + } + lAddByte(pTok, 0); + break; + case '(': + lAddByte(pTok, (unsigned char)(yylvalpp->sc_int ? 1 : 0)); + default: + break; + } +} // RecordToken + +/* + * RewindTokenStream() - Reset a token stream in preperation for reading. + * + */ + +void RewindTokenStream(TokenStream *pTok) +{ + if (pTok->head) { + pTok->current = pTok->head; + pTok->current->current = 0; + } +} // RewindTokenStream + +/* + * ReadToken() - Read the next token from a stream. + * + */ + +int ReadToken(TokenStream *pTok, yystypepp * yylvalpp) +{ + char symbol_name[MAX_SYMBOL_NAME_LEN + 1]; + char string_val[MAX_STRING_LEN + 1]; + int ltoken, len; + char ch; + int base, accum; + char ch_val; + + ltoken = lReadByte(pTok); + if (ltoken >= 0) { + if (ltoken > 127) + ltoken += 128; + switch (ltoken) { + case CPP_IDENTIFIER: + case CPP_TYPEIDENTIFIER: + len = 0; + ch = lReadByte(pTok); + while ((ch >= 'a' && ch <= 'z') || + (ch >= 'A' && ch <= 'Z') || + (ch >= '0' && ch <= '9') || + ch == '_') + { + if (len < MAX_SYMBOL_NAME_LEN) { + symbol_name[len++] = ch; + ch = lReadByte(pTok); + } + } + symbol_name[len] = '\0'; + assert(ch == '\0'); + yylvalpp->sc_ident = LookUpAddString(atable, symbol_name); + return CPP_IDENTIFIER; + break; + case CPP_STRCONSTANT: + len = 0; + while ((ch = lReadByte(pTok)) != 0) + if (len < MAX_STRING_LEN) + string_val[len++] = ch; + string_val[len] = '\0'; + yylvalpp->sc_ident = LookUpAddString(atable, string_val); + break; + case CPP_FLOATCONSTANT: + len = 0; + ch = lReadByte(pTok); + while ((ch >= '0' && ch <= '9')||(ch=='e'||ch=='E'||ch=='.')||(ch=='+'||ch=='-')) + { + if (len < MAX_SYMBOL_NAME_LEN) { + symbol_name[len++] = ch; + ch = lReadByte(pTok); + } + } + symbol_name[len] = '\0'; + assert(ch == '\0'); + strcpy(yylvalpp->symbol_name,symbol_name); + yylvalpp->sc_fval=(float)atof_dot(yylvalpp->symbol_name); + break; + case CPP_INTCONSTANT: + len = 0; + accum = 0; + ch = lReadByte(pTok); + if (ch == '0') { + symbol_name[len++] = ch; + ch = lReadByte(pTok); + if (ch == 'x' || ch == 'X') { + symbol_name[len++] = ch; + base = 16; + ch = lReadByte(pTok); + } else { + base = 8; + } + } else { + base = 10; + } + + while (len < MAX_SYMBOL_NAME_LEN) + { + ch_val = -1; + if (isdigit(ch)) + ch_val = ch - '0'; + else if (isxdigit(ch)) + ch_val = tolower(ch) - 'a' + 10; + + if (ch_val < 0 || ch_val >= base) + break; + + symbol_name[len++] = ch; + accum = accum * base + ch_val; + ch = lReadByte(pTok); + } + symbol_name[len] = '\0'; + assert(ch == '\0'); + strcpy(yylvalpp->symbol_name, symbol_name); + yylvalpp->sc_int = accum; + break; + case '(': + yylvalpp->sc_int = lReadByte(pTok); + break; + } + return ltoken; + } + return EOF_SY; +} // ReadToken + +typedef struct TokenInputSrc { + InputSrc base; + TokenStream *tokens; + int (*final)(CPPStruct *); +} TokenInputSrc; + +static int scan_token(TokenInputSrc *in, yystypepp * yylvalpp) +{ + int token = ReadToken(in->tokens, yylvalpp); + int (*final)(CPPStruct *); + cpp->tokenLoc->file = cpp->currentInput->name; + cpp->tokenLoc->line = cpp->currentInput->line; + if (token == '\n') { + in->base.line++; + return token; + } + if (token > 0) return token; + cpp->currentInput = in->base.prev; + final = in->final; + free(in); + if (final && !final(cpp)) return -1; + return cpp->currentInput->scan(cpp->currentInput, yylvalpp); +} + +int ReadFromTokenStream(TokenStream *ts, int name, int (*final)(CPPStruct *)) +{ + TokenInputSrc *in = malloc(sizeof(TokenInputSrc)); + memset(in, 0, sizeof(TokenInputSrc)); + in->base.name = name; + in->base.prev = cpp->currentInput; + in->base.scan = (int (*)(InputSrc *, yystypepp *))scan_token; + in->base.line = 1; + in->tokens = ts; + in->final = final; + RewindTokenStream(ts); + cpp->currentInput = &in->base; + return 1; +} + +typedef struct UngotToken { + InputSrc base; + int token; + yystypepp lval; +} UngotToken; + +static int reget_token(UngotToken *t, yystypepp * yylvalpp) +{ + int token = t->token; + *yylvalpp = t->lval; + cpp->currentInput = t->base.prev; + free(t); + return token; +} + +void UngetToken(int token, yystypepp * yylvalpp) { + UngotToken *t = malloc(sizeof(UngotToken)); + memset(t, 0, sizeof(UngotToken)); + t->token = token; + t->lval = *yylvalpp; + t->base.scan = (void *)reget_token; + t->base.prev = cpp->currentInput; + t->base.name = cpp->currentInput->name; + t->base.line = cpp->currentInput->line; + cpp->currentInput = &t->base; +} + + +void DumpTokenStream(FILE *fp, TokenStream *s, yystypepp * yylvalpp) { + int token; + char str[100]; + + if (fp == 0) fp = stdout; + RewindTokenStream(s); + while ((token = ReadToken(s, yylvalpp)) > 0) { + switch (token) { + case CPP_IDENTIFIER: + case CPP_TYPEIDENTIFIER: + snprintf(str, sizeof(str), "%s ", GetAtomString(atable, yylvalpp->sc_ident)); + break; + case CPP_STRCONSTANT: + snprintf(str, sizeof(str), "\"%s\"", GetAtomString(atable, yylvalpp->sc_ident)); + break; + case CPP_FLOATCONSTANT: + //printf("%g9.6 ", yylvalpp->sc_fval); + break; + case CPP_INTCONSTANT: + //printf("%d ", yylvalpp->sc_int); + break; + default: + if (token >= 127) + snprintf(str, sizeof(str), "%s ", GetAtomString(atable, token)); + else + snprintf(str, sizeof(str), "%c", token); + break; + } + CPPDebugLogMsg(str); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////// End of tokens.c /////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/3rdparty/angle/src/compiler/preprocessor/tokens.h b/src/3rdparty/angle/src/compiler/preprocessor/tokens.h new file mode 100644 index 0000000000..dbf4a2ccfe --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/tokens.h @@ -0,0 +1,90 @@ +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// tokens.h +// + +#if !defined(__TOKENS_H) +#define __TOKENS_H 1 + +#include <stdio.h> +#include "compiler/preprocessor/parser.h" + +#define EOF_SY (-1) + +typedef struct TokenBlock_Rec TokenBlock; + +typedef struct TokenStream_Rec { + struct TokenStream_Rec *next; + char *name; + TokenBlock *head; + TokenBlock *current; +} TokenStream; + +struct TokenBlock_Rec { + TokenBlock *next; + int current; + int count; + int max; + unsigned char *data; +}; + +extern TokenStream stdlib_cpp_stream; + + +TokenStream *NewTokenStream(const char *name, MemoryPool *pool); +void DeleteTokenStream(TokenStream *pTok); +void RecordToken(TokenStream *pTok, int token, yystypepp * yylvalpp); +void RewindTokenStream(TokenStream *pTok); +int ReadToken(TokenStream *pTok, yystypepp * yylvalpp); +int ReadFromTokenStream(TokenStream *pTok, int name, int (*final)(CPPStruct *)); +void UngetToken(int, yystypepp * yylvalpp); + +#if defined(CPPC_ENABLE_TOOLS) + +void DumpTokenStream(FILE *, TokenStream *, yystypepp * yylvalpp); + +#endif // defined(CPPC_ENABLE_TOOLS) + +#endif // !defined(__TOKENS_H) |