tge/engine/console/compiler.cc
2017-04-17 06:17:10 -06:00

272 lines
7.2 KiB
C++
Executable File

//-----------------------------------------------------------------------------
// 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);
}
}