272 lines
7.2 KiB
C++
Executable File
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);
|
|
}
|
|
}
|