//----------------------------------------------------------------------------- // Torque Game Engine // Copyright (C) GarageGames.com, Inc. //----------------------------------------------------------------------------- #include "platform/platform.h" #include "console/console.h" #include "console/telnetDebugger.h" #include "platform/event.h" #include "console/ast.h" #include "core/tAlgorithm.h" #include "core/resManager.h" #include "core/findMatch.h" #include "console/consoleInternal.h" #include "core/fileStream.h" #include "console/compiler.h" #include "console/simBase.h" namespace Compiler { F64 consoleStringToNumber(const char *str, StringTableEntry file, U32 line) { F64 val = dAtof(str); if(val != 0) return val; else if(!dStricmp(str, "true")) return 1; else if(!dStricmp(str, "false")) return 0; else if(file) { Con::warnf(ConsoleLogEntry::General, "%s (%d): string always evaluates to 0.", file, line); return 0; } return 0; } //------------------------------------------------------------ CompilerStringTable *gCurrentStringTable, gGlobalStringTable, gFunctionStringTable; CompilerFloatTable *gCurrentFloatTable, gGlobalFloatTable, gFunctionFloatTable; DataChunker gConsoleAllocator; CompilerIdentTable gIdentTable; CodeBlock *gCurBreakBlock; //------------------------------------------------------------ CodeBlock *getBreakCodeBlock() { return gCurBreakBlock; } void setBreakCodeBlock(CodeBlock *cb) { gCurBreakBlock = cb; } //------------------------------------------------------------ U32 evalSTEtoU32(StringTableEntry ste, U32) { return *((U32 *) &ste); } U32 compileSTEtoU32(StringTableEntry ste, U32 ip) { if(ste) getIdentTable().add(ste, ip); return 0; } U32 (*STEtoU32)(StringTableEntry ste, U32 ip) = evalSTEtoU32; //------------------------------------------------------------ bool gSyntaxError = false; //------------------------------------------------------------ CompilerStringTable *getCurrentStringTable() { return gCurrentStringTable; } CompilerStringTable &getGlobalStringTable() { return gGlobalStringTable; } CompilerStringTable &getFunctionStringTable() { return gFunctionStringTable; } void setCurrentStringTable (CompilerStringTable* cst) { gCurrentStringTable = cst; } CompilerFloatTable *getCurrentFloatTable() { return gCurrentFloatTable; } CompilerFloatTable &getGlobalFloatTable() { return gGlobalFloatTable; } CompilerFloatTable &getFunctionFloatTable() { return gFunctionFloatTable; } void setCurrentFloatTable (CompilerFloatTable* cst) { gCurrentFloatTable = cst; } CompilerIdentTable &getIdentTable() { return gIdentTable; } void precompileIdent(StringTableEntry ident) { if(ident) gGlobalStringTable.add(ident); } void resetTables() { setCurrentStringTable(&gGlobalStringTable); setCurrentFloatTable(&gGlobalFloatTable); getGlobalFloatTable().reset(); getGlobalStringTable().reset(); getFunctionFloatTable().reset(); getFunctionStringTable().reset(); getIdentTable().reset(); } void *consoleAlloc(U32 size) { return gConsoleAllocator.alloc(size); } void consoleAllocReset() { gConsoleAllocator.freeBlocks(); } } //------------------------------------------------------------------------- using namespace Compiler; //------------------------------------------------------------------------- U32 CompilerStringTable::add(const char *str, bool caseSens, bool tag) { // Is it already in? Entry **walk; for(walk = &list; *walk; walk = &((*walk)->next)) { if((*walk)->tag != tag) continue; if(caseSens) { if(!dStrcmp((*walk)->string, str)) return (*walk)->start; } else { if(!dStricmp((*walk)->string, str)) return (*walk)->start; } } // Write it out. Entry *newStr = (Entry *) consoleAlloc(sizeof(Entry)); *walk = newStr; newStr->next = NULL; newStr->start = totalLen; U32 len = dStrlen(str) + 1; if(tag && len < 7) // alloc space for the numeric tag 1 for tag, 5 for # and 1 for nul len = 7; totalLen += len; newStr->string = (char *) consoleAlloc(len); newStr->len = len; newStr->tag = tag; dStrcpy(newStr->string, str); return newStr->start; } U32 CompilerStringTable::addIntString(U32 value) { dSprintf(buf, sizeof(buf), "%d", value); return add(buf); } U32 CompilerStringTable::addFloatString(F64 value) { dSprintf(buf, sizeof(buf), "%g", value); return add(buf); } void CompilerStringTable::reset() { list = NULL; totalLen = 0; } char *CompilerStringTable::build() { char *ret = new char[totalLen]; for(Entry *walk = list; walk; walk = walk->next) dStrcpy(ret + walk->start, walk->string); return ret; } void CompilerStringTable::write(Stream &st) { st.write(totalLen); for(Entry *walk = list; walk; walk = walk->next) st.write(walk->len, walk->string); } //------------------------------------------------------------ U32 CompilerFloatTable::add(F64 value) { Entry **walk; U32 i = 0; for(walk = &list; *walk; walk = &((*walk)->next), i++) if(value == (*walk)->val) return i; Entry *newFloat = (Entry *) consoleAlloc(sizeof(Entry)); newFloat->val = value; newFloat->next = NULL; count++; *walk = newFloat; return count-1; } void CompilerFloatTable::reset() { list = NULL; count = 0; } F64 *CompilerFloatTable::build() { F64 *ret = new F64[count]; U32 i = 0; for(Entry *walk = list; walk; walk = walk->next, i++) ret[i] = walk->val; return ret; } void CompilerFloatTable::write(Stream &st) { st.write(count); for(Entry *walk = list; walk; walk = walk->next) st.write(walk->val); } //------------------------------------------------------------ void CompilerIdentTable::reset() { list = NULL; } void CompilerIdentTable::add(StringTableEntry ste, U32 ip) { U32 index = gGlobalStringTable.add(ste, false); Entry *newEntry = (Entry *) consoleAlloc(sizeof(Entry)); newEntry->offset = index; newEntry->ip = ip; for(Entry *walk = list; walk; walk = walk->next) { if(walk->offset == index) { newEntry->nextIdent = walk->nextIdent; walk->nextIdent = newEntry; return; } } newEntry->next = list; list = newEntry; newEntry->nextIdent = NULL; } void CompilerIdentTable::write(Stream &st) { U32 count = 0; Entry * walk; for(walk = list; walk; walk = walk->next) count++; st.write(count); for(walk = list; walk; walk = walk->next) { U32 ec = 0; Entry * el; for(el = walk; el; el = el->nextIdent) ec++; st.write(walk->offset); st.write(ec); for(el = walk; el; el = el->nextIdent) st.write(el->ip); } }