t2 engine svn checkout

This commit is contained in:
loop 2024-01-07 04:36:33 +00:00
commit ff569bd2ae
988 changed files with 394180 additions and 0 deletions

439
console/ast.h Normal file
View file

@ -0,0 +1,439 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _AST_H_
#define _AST_H_
// TO-DO: Console debugger stuff to be cleaned up later
// extern void dbgDebuggerAddBreakPosition(const char *fileName, S32 lineNumber);
// extern void dbgDebuggerRemoveBreakPosition(const char *fileName, S32 lineNumber);
class ExprEvalState;
class Namespace;
class SimObject;
class SimGroup;
enum TypeReq {
TypeReqNone,
TypeReqUInt,
TypeReqFloat,
TypeReqString
};
struct StmtNode
{
StmtNode *next;
StmtNode();
void append(StmtNode *next);
StmtNode *getNext() { return next; }
StringTableEntry dbgFileName;
S32 dbgLineNumber;
void addBreakCount();
void addBreakLine(U32 ip);
virtual U32 precompileStmt(U32 loopCount) = 0;
virtual U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint) = 0;
virtual void setPackage(StringTableEntry packageName);
};
struct BreakStmtNode : StmtNode
{
static BreakStmtNode *alloc();
U32 precompileStmt(U32 loopCount);
U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint);
};
struct ContinueStmtNode : StmtNode
{
static ContinueStmtNode *alloc();
U32 precompileStmt(U32 loopCount);
U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint);
};
struct ExprNode : StmtNode
{
U32 precompileStmt(U32 loopCount);
U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint);
virtual U32 precompile(TypeReq type) = 0;
virtual U32 compile(U32 *codeStream, U32 ip, TypeReq type) = 0;
U32 compileX(U32 *codeStream, U32 ip, TypeReq type);
virtual TypeReq getPreferredType() = 0;
};
struct ReturnStmtNode : StmtNode
{
ExprNode *expr;
static ReturnStmtNode *alloc(ExprNode *expr);
U32 precompileStmt(U32 loopCount);
U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint);
};
struct IfStmtNode : StmtNode
{
ExprNode *testExpr;
StmtNode *ifBlock, *elseBlock;
U32 endifOffset;
U32 elseOffset;
bool integer;
bool propagate;
static IfStmtNode *alloc(S32 lineNumber, ExprNode *testExpr, StmtNode *ifBlock, StmtNode *elseBlock, bool propagateThrough);
void propagateSwitchExpr(ExprNode *left, bool string);
ExprNode *getSwitchOR(ExprNode *left, ExprNode *list, bool string);
U32 precompileStmt(U32 loopCount);
U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint);
};
struct LoopStmtNode : StmtNode
{
ExprNode *testExpr;
ExprNode *initExpr;
ExprNode *endLoopExpr;
StmtNode *loopBlock;
bool isDoLoop;
U32 breakOffset;
U32 continueOffset;
U32 loopBlockStartOffset;
bool integer;
static LoopStmtNode *alloc(S32 lineNumber, ExprNode *testExpr, ExprNode *initExpr, ExprNode *endLoopExpr, StmtNode *loopBlock, bool isDoLoop);
U32 precompileStmt(U32 loopCount);
U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint);
};
struct BinaryExprNode : ExprNode
{
S32 op;
ExprNode *left;
ExprNode *right;
};
struct FloatBinaryExprNode : BinaryExprNode
{
static FloatBinaryExprNode *alloc(S32 op, ExprNode *left, ExprNode *right);
U32 precompile(TypeReq type);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
};
struct ConditionalExprNode : ExprNode
{
ExprNode *testExpr;
ExprNode *trueExpr;
ExprNode *falseExpr;
bool integer;
static ConditionalExprNode *alloc(ExprNode *testExpr, ExprNode *trueExpr, ExprNode *falseExpr);
virtual U32 precompile(TypeReq type);
virtual U32 compile(U32 *codeStream, U32 ip, TypeReq type);
virtual TypeReq getPreferredType();
};
struct IntBinaryExprNode : BinaryExprNode
{
TypeReq subType;
U32 operand;
static IntBinaryExprNode *alloc(S32 op, ExprNode *left, ExprNode *right);
void getSubTypeOperand();
U32 precompile(TypeReq type);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
};
struct StreqExprNode : BinaryExprNode
{
bool eq;
static StreqExprNode *alloc(ExprNode *left, ExprNode *right, bool eq);
U32 precompile(TypeReq type);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
};
struct StrcatExprNode : BinaryExprNode
{
int appendChar;
static StrcatExprNode *alloc(ExprNode *left, ExprNode *right, int appendChar);
U32 precompile(TypeReq type);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
};
struct CommaCatExprNode : BinaryExprNode
{
static CommaCatExprNode *alloc(ExprNode *left, ExprNode *right);
U32 precompile(TypeReq type);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
};
struct IntUnaryExprNode : ExprNode
{
S32 op;
ExprNode *expr;
bool integer;
static IntUnaryExprNode *alloc(S32 op, ExprNode *expr);
U32 precompile(TypeReq type);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
};
struct FloatUnaryExprNode : ExprNode
{
S32 op;
ExprNode *expr;
static FloatUnaryExprNode *alloc(S32 op, ExprNode *expr);
U32 precompile(TypeReq type);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
};
struct VarNode : ExprNode
{
StringTableEntry varName;
ExprNode *arrayIndex;
static VarNode *alloc(StringTableEntry varName, ExprNode *arrayIndex);
U32 precompile(TypeReq type);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
};
struct IntNode : ExprNode
{
S32 value;
U32 index; // if it's converted to float/string
static IntNode *alloc(S32 value);
U32 precompile(TypeReq type);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
};
struct FloatNode : ExprNode
{
F64 value;
U32 index;
static FloatNode *alloc(F64 value);
U32 precompile(TypeReq type);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
};
struct StrConstNode : ExprNode
{
char *str;
F64 fVal;
U32 index;
bool tag;
static StrConstNode *alloc(char *str, bool tag);
U32 precompile(TypeReq type);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
};
struct ConstantNode : ExprNode
{
StringTableEntry value;
F64 fVal;
U32 index;
static ConstantNode *alloc(StringTableEntry value);
U32 precompile(TypeReq type);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
};
struct AssignExprNode : ExprNode
{
StringTableEntry varName;
ExprNode *expr;
ExprNode *arrayIndex;
TypeReq subType;
static AssignExprNode *alloc(StringTableEntry varName, ExprNode *arrayIndex, ExprNode *expr);
U32 precompile(TypeReq type);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
};
struct AssignDecl
{
S32 token;
ExprNode *expr;
bool integer;
};
struct AssignOpExprNode : ExprNode
{
StringTableEntry varName;
ExprNode *expr;
ExprNode *arrayIndex;
S32 op;
U32 operand;
TypeReq subType;
static AssignOpExprNode *alloc(StringTableEntry varName, ExprNode *arrayIndex, ExprNode *expr, S32 op);
U32 precompile(TypeReq type);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
};
struct TTagSetStmtNode : StmtNode
{
StringTableEntry tag;
ExprNode *valueExpr;
ExprNode *stringExpr;
static TTagSetStmtNode *alloc(StringTableEntry tag, ExprNode *valueExpr, ExprNode *stringExpr);
U32 precompileStmt(U32 loopCount);
U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint);
};
struct TTagDerefNode : ExprNode
{
ExprNode *expr;
static TTagDerefNode *alloc(ExprNode *expr);
U32 precompile(TypeReq type);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
};
struct TTagExprNode : ExprNode
{
StringTableEntry tag;
static TTagExprNode *alloc(StringTableEntry tag);
U32 precompile(TypeReq type);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
};
struct FuncCallExprNode : ExprNode
{
StringTableEntry funcName;
StringTableEntry nameSpace;
ExprNode *args;
U32 callType;
enum {
FunctionCall,
MethodCall,
ParentCall
};
static FuncCallExprNode *alloc(StringTableEntry funcName, StringTableEntry nameSpace, ExprNode *args, bool dot);
U32 precompile(TypeReq type);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
};
struct SlotDecl
{
ExprNode *object;
StringTableEntry slotName;
ExprNode *array;
};
struct SlotAccessNode : ExprNode
{
ExprNode *objectExpr, *arrayExpr;
StringTableEntry slotName;
static SlotAccessNode *alloc(ExprNode *objectExpr, ExprNode *arrayExpr, StringTableEntry slotName);
U32 precompile(TypeReq type);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
};
struct SlotAssignNode : ExprNode
{
ExprNode *objectExpr, *arrayExpr;
StringTableEntry slotName;
ExprNode *valueExpr;
static SlotAssignNode *alloc(ExprNode *objectExpr, ExprNode *arrayExpr, StringTableEntry slotName, ExprNode *valueExpr);
U32 precompile(TypeReq type);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
};
struct SlotAssignOpNode : ExprNode
{
ExprNode *objectExpr, *arrayExpr;
StringTableEntry slotName;
S32 op;
ExprNode *valueExpr;
U32 operand;
TypeReq subType;
static SlotAssignOpNode *alloc(ExprNode *objectExpr, StringTableEntry slotName, ExprNode *arrayExpr, S32 op, ExprNode *valueExpr);
U32 precompile(TypeReq type);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
};
struct ObjectDeclNode : ExprNode
{
ExprNode *classNameExpr;
StringTableEntry parentObject;
ExprNode *objectNameExpr;
ExprNode *argList;
SlotAssignNode *slotDecls;
ObjectDeclNode *subObjects;
bool structDecl;
U32 failOffset;
static ObjectDeclNode *alloc(ExprNode *classNameExpr, ExprNode *objectNameExpr, ExprNode *argList, StringTableEntry parentObject, SlotAssignNode *slotDecls, ObjectDeclNode *subObjects, bool structDecl);
U32 precompile(TypeReq type);
U32 precompileSubObject(bool);
U32 compile(U32 *codeStream, U32 ip, TypeReq type);
U32 compileSubObject(U32 *codeStream, U32 ip, bool);
TypeReq getPreferredType();
};
struct ObjectBlockDecl
{
SlotAssignNode *slots;
ObjectDeclNode *decls;
};
struct FunctionDeclStmtNode : StmtNode
{
StringTableEntry fnName;
VarNode *args;
StmtNode *stmts;
StringTableEntry nameSpace;
StringTableEntry package;
U32 endOffset;
U32 argc;
static FunctionDeclStmtNode *alloc(StringTableEntry fnName, StringTableEntry nameSpace, VarNode *args, StmtNode *stmts);
U32 precompileStmt(U32 loopCount);
U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint);
void setPackage(StringTableEntry packageName);
};
extern StmtNode *statementList;
extern void createFunction(const char *fnName, VarNode *args, StmtNode *statements);
extern ExprEvalState gEvalState;
extern bool lookupFunction(const char *fnName, VarNode **args, StmtNode **statements);
typedef const char *(*cfunc)(S32 argc, char **argv);
extern bool lookupCFunction(const char *fnName, cfunc *f);
#endif

1222
console/compiledEval.cc Normal file

File diff suppressed because it is too large Load diff

2609
console/compiler.cc Normal file

File diff suppressed because it is too large Load diff

246
console/compiler.h Normal file
View file

@ -0,0 +1,246 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
enum CompiledInstructions
{
OP_FUNC_DECL,
OP_CREATE_OBJECT,
OP_CREATE_DATABLOCK,
OP_NAME_OBJECT,
OP_ADD_OBJECT,
OP_END_OBJECT,
OP_JMPIFFNOT,
OP_JMPIFNOT,
OP_JMPIFF,
OP_JMPIF,
OP_JMPIFNOT_NP,
OP_JMPIF_NP,
OP_JMP,
OP_RETURN,
OP_CMPEQ,
OP_CMPGR,
OP_CMPGE,
OP_CMPLT,
OP_CMPLE,
OP_CMPNE,
OP_XOR,
OP_MOD,
OP_BITAND,
OP_BITOR,
OP_NOT,
OP_NOTF,
OP_ONESCOMPLEMENT,
OP_SHR,
OP_SHL,
OP_AND,
OP_OR,
OP_ADD,
OP_SUB,
OP_MUL,
OP_DIV,
OP_NEG,
OP_SETCURVAR,
OP_SETCURVAR_CREATE,
OP_SETCURVAR_ARRAY,
OP_SETCURVAR_ARRAY_CREATE,
OP_LOADVAR_UINT,
OP_LOADVAR_FLT,
OP_LOADVAR_STR,
OP_SAVEVAR_UINT,
OP_SAVEVAR_FLT,
OP_SAVEVAR_STR,
OP_SETCUROBJECT,
OP_SETCUROBJECT_NEW,
OP_SETCURFIELD,
OP_SETCURFIELD_ARRAY,
OP_LOADFIELD_UINT,
OP_LOADFIELD_FLT,
OP_LOADFIELD_STR,
OP_SAVEFIELD_UINT,
OP_SAVEFIELD_FLT,
OP_SAVEFIELD_STR,
OP_STR_TO_UINT,
OP_STR_TO_FLT,
OP_STR_TO_NONE,
OP_FLT_TO_UINT,
OP_FLT_TO_STR,
OP_FLT_TO_NONE,
OP_UINT_TO_FLT,
OP_UINT_TO_STR,
OP_UINT_TO_NONE,
OP_LOADIMMED_UINT,
OP_LOADIMMED_FLT,
OP_TAG_TO_STR,
OP_LOADIMMED_STR,
OP_LOADIMMED_IDENT,
OP_CALLFUNC_RESOLVE,
OP_CALLFUNC,
OP_PROCESS_ARGS,
OP_ADVANCE_STR,
OP_ADVANCE_STR_APPENDCHAR,
OP_ADVANCE_STR_COMMA,
OP_ADVANCE_STR_NUL,
OP_REWIND_STR,
OP_TERMINATE_REWIND_STR,
OP_COMPARE_STR,
OP_PUSH,
OP_PUSH_FRAME,
OP_BREAK,
OP_INVALID
};
// DON'T CHANGE THESE LINES!
// DON'T CHANGE THESE LINES!
// The script updateConsoleVersion.pl in //Dev/environment/usr/bin/ depends on them
// being exactly as follows
//
enum {
ConsoleDSOVersion = 33
};
//
// DON'T CHANGE THESE LINES!
// DON'T CHANGE THESE LINES!
// DON'T CHANGE THESE LINES!
class Stream;
class CodeBlock
{
public:
StringTableEntry name;
char *globalStrings;
char *functionStrings;
F64 *globalFloats;
F64 *functionFloats;
U32 codeSize;
U32 *code;
U32 refCount;
U32 lineBreakPairCount;
U32 *lineBreakPairs;
U32 breakListSize;
U32 *breakList;
CodeBlock *nextFile;
static CodeBlock *find(StringTableEntry);
CodeBlock();
~CodeBlock();
void addToCodeList();
void removeFromCodeList();
void calcBreakList();
void clearAllBreaks();
void setAllBreaks();
void clearBreakpoint(U32 lineNumber);
void setBreakpoint(U32 lineNumber);
void findBreakLine(U32 ip, U32 &line, U32 &instruction);
const char *getFileLine(U32 ip);
bool read(StringTableEntry fileName, Stream &st);
bool compile(const char *dsoName, StringTableEntry fileName, const char *script);
void incRefCount();
void decRefCount();
const char *compileExec(StringTableEntry fileName, const char *script, bool noCalls);
const char *exec(U32 offset, const char *fnName, Namespace *ns, U32 argc, const char **argv, bool noCalls);
};
extern CodeBlock *codeBlockList;
extern F64 consoleStringToNumber(const char *str, StringTableEntry file = 0, U32 line = 0);
extern U32 precompileBlock(StmtNode *block, U32 loopCount);
extern U32 compileBlock(StmtNode *block, U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint);
struct CompilerIdentTable
{
struct Entry
{
U32 offset;
U32 ip;
Entry *next;
Entry *nextIdent;
};
Entry *list;
void add(StringTableEntry ste, U32 ip);
void reset();
void write(Stream &st);
};
struct CompilerStringTable
{
U32 totalLen;
struct Entry
{
char *string;
U32 start;
U32 len;
bool tag;
Entry *next;
};
Entry *list;
char buf[256];
U32 add(const char *str, bool caseSens = true, bool tag = false);
U32 addIntString(U32 value);
U32 addFloatString(F64 value);
void reset();
char *build();
void write(Stream &st);
};
extern CompilerStringTable *currentStringTable;
extern CompilerStringTable gGlobalStringTable;
extern CompilerStringTable gFunctionStringTable;
//------------------------------------------------------------
struct CompilerFloatTable
{
struct Entry
{
F64 val;
Entry *next;
};
U32 count;
Entry *list;
U32 add(F64 value);
void reset();
F64 *build();
void write(Stream &st);
};
extern CompilerFloatTable *currentFloatTable, gGlobalFloatTable, gFunctionFloatTable;
extern U32 (*STEtoU32)(StringTableEntry ste, U32 ip);
inline StringTableEntry U32toSTE(U32 u)
{
return *((StringTableEntry *) &u);
}

688
console/console.cc Normal file
View file

@ -0,0 +1,688 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "Platform/platform.h"
#include "console/console.h"
#include "console/consoleInternal.h"
#include "console/consoleObject.h"
#include "Core/fileStream.h"
#include "Core/resManager.h"
#include "console/ast.h"
#include "Core/tAlgorithm.h"
#include "console/consoleTypes.h"
#include "console/telnetDebugger.h"
#include "console/simBase.h"
#include "console/compiler.h"
#include <stdarg.h>
ExprEvalState gEvalState;
StmtNode *statementList;
ConsoleConstructor *ConsoleConstructor::first = NULL;
static char scratchBuffer[1024];
// TO-DO: Console debugger stuff to be cleaned up later
static S32 dbgGetCurrentFrame(void)
{
return gEvalState.stack.size() - 1;
}
static const char * prependDollar ( const char * name )
{
if(name[0] != '$'){
S32 len = dStrlen(name);
AssertFatal(len < sizeof(scratchBuffer)-2, "CONSOLE: name too long");
scratchBuffer[0] = '$';
dMemcpy(scratchBuffer + 1, name, len + 1);
name = scratchBuffer;
}
return name;
}
static const char * prependPercent ( const char * name )
{
if(name[0] != '%'){
S32 len = dStrlen(name);
AssertFatal(len < sizeof(scratchBuffer)-2, "CONSOLE: name too long");
scratchBuffer[0] = '%';
dMemcpy(scratchBuffer + 1, name, len + 1);
name = scratchBuffer;
}
return name;
}
//--------------------------------------
void ConsoleConstructor::init(const char *cName, const char *fName, const char *usg, S32 minArgs, S32 maxArgs)
{
mina = minArgs;
maxa = maxArgs;
funcName = fName;
usage = usg;
className = cName;
sc = 0; fc = 0; vc = 0; bc = 0; ic = 0;
next = first;
first = this;
}
void ConsoleConstructor::setup()
{
for(ConsoleConstructor *walk = first; walk; walk = walk->next)
{
if(walk->sc)
Con::addCommand(walk->className, walk->funcName, walk->sc, walk->usage, walk->mina, walk->maxa);
else if(walk->ic)
Con::addCommand(walk->className, walk->funcName, walk->ic, walk->usage, walk->mina, walk->maxa);
else if(walk->fc)
Con::addCommand(walk->className, walk->funcName, walk->fc, walk->usage, walk->mina, walk->maxa);
else if(walk->vc)
Con::addCommand(walk->className, walk->funcName, walk->vc, walk->usage, walk->mina, walk->maxa);
else if(walk->bc)
Con::addCommand(walk->className, walk->funcName, walk->bc, walk->usage, walk->mina, walk->maxa);
}
}
ConsoleConstructor::ConsoleConstructor(const char *className, const char *funcName, StringCallback sfunc, const char *usage, S32 minArgs, S32 maxArgs)
{
init(className, funcName, usage, minArgs, maxArgs);
sc = sfunc;
}
ConsoleConstructor::ConsoleConstructor(const char *className, const char *funcName, IntCallback ifunc, const char *usage, S32 minArgs, S32 maxArgs)
{
init(className, funcName, usage, minArgs, maxArgs);
ic = ifunc;
}
ConsoleConstructor::ConsoleConstructor(const char *className, const char *funcName, FloatCallback ffunc, const char *usage, S32 minArgs, S32 maxArgs)
{
init(className, funcName, usage, minArgs, maxArgs);
fc = ffunc;
}
ConsoleConstructor::ConsoleConstructor(const char *className, const char *funcName, VoidCallback vfunc, const char *usage, S32 minArgs, S32 maxArgs)
{
init(className, funcName, usage, minArgs, maxArgs);
vc = vfunc;
}
ConsoleConstructor::ConsoleConstructor(const char *className, const char *funcName, BoolCallback bfunc, const char *usage, S32 minArgs, S32 maxArgs)
{
init(className, funcName, usage, minArgs, maxArgs);
bc = bfunc;
}
namespace Con
{
static Vector<ConsumerCallback> gConsumers(__FILE__, __LINE__);
static DataChunker consoleLogChunker;
static Vector<ConsoleLogEntry> consoleLog(__FILE__, __LINE__);
static bool logBufferEnabled=true;
static S32 printLevel = 10;
static FileStream consoleLogFile;
static const char *defLogFileName = "console.log";
static S32 consoleLogMode = 2; // default to no logging
static bool active = false;
static bool newLogFile;
static const char *logFileName;
static void cClearScreen(SimObject *, S32 , const char **)
{
consoleLogChunker.freeBlocks();
consoleLog.setSize(0);
};
static const char* cGetClipboard(SimObject *, S32 , const char **)
{
return Platform::getClipboard();
};
static bool cSetClipboard(SimObject *, S32 , const char **argv)
{
return Platform::setClipboard(argv[1]);
};
void init()
{
AssertFatal(active == false, "Con::init should only be called once.");
active = true;
logFileName = NULL;
newLogFile = true;
Namespace::init();
// Commands
addCommand("getClipboard", cGetClipboard, "getClipboard()", 1, 1);
addCommand("cls", cClearScreen, "cls()", 1, 1);
addCommand("getClipboard", cGetClipboard, "getClipboard()", 1, 1);
addCommand("setClipboard", cSetClipboard, "setClipboard(text)", 2, 2);
ConsoleConstructor::setup();
// Variables
setVariable("Con::prompt", "% ");
addVariable("Con::logBufferEnabled", TypeBool, &logBufferEnabled);
addVariable("Con::printLevel", TypeS32, &printLevel);
AbstractClassRep::initialize();
}
//--------------------------------------
void shutdown()
{
AssertFatal(active == true, "Con::shutdown should only be called once.");
active = false;
consoleLogFile.close();
Namespace::shutdown();
}
bool isActive()
{
return active;
}
//--------------------------------------
void getLog(ConsoleLogEntry *&log, U32 &size)
{
log = &consoleLog[0];
size = consoleLog.size();
}
const char *tabComplete(const char *prevText, S32 baseLen, bool fForward)
{
if (!prevText[0])
return "";
else if(prevText[0] == '$')
return gEvalState.globalVars.tabComplete(prevText, baseLen, fForward);
else
return Namespace::global()->tabComplete(prevText, baseLen, fForward);
}
//------------------------------------------------------------------------------
static void log(const char *string)
{
if(!consoleLogMode)
return;
if(consoleLogMode == 1)
consoleLogFile.open(defLogFileName, FileStream::ReadWrite);
if(consoleLogFile.getStatus() == Stream::Ok)
{
consoleLogFile.setPosition(consoleLogFile.getStreamSize());
if (newLogFile)
{
Platform::LocalTime lt;
Platform::getLocalTime(lt);
char buffer[128];
dSprintf(buffer, sizeof(buffer), "-------------------------- %d/%d/%d -- %02d:%02d:%02d -----\r\n",
lt.month,
lt.monthday,
lt.year,
lt.hour,
lt.min,
lt.sec);
consoleLogFile.write(dStrlen(buffer), buffer);
newLogFile = false;
}
consoleLogFile.write(dStrlen(string), string);
consoleLogFile.write(2, "\r\n");
}
if(consoleLogMode == 1)
consoleLogFile.close();
}
//------------------------------------------------------------------------------
static void _printf(ConsoleLogEntry::Level level, ConsoleLogEntry::Type type, const char* fmt, va_list argptr)
{
char buffer[1024];
U32 offset = 0;
if(gEvalState.traceOn && gEvalState.stack.size())
{
offset = (gEvalState.stack.size() - 1) * 2;
for(U32 i = 0; i < offset; i++)
buffer[i] = ' ';
}
dVsprintf(buffer + offset, sizeof(buffer) - offset, fmt, argptr);
for(U32 i = 0; i < gConsumers.size(); i++)
gConsumers[i](level, buffer);
if(logBufferEnabled || consoleLogMode)
{
char *pos = buffer;
while(*pos)
{
if(*pos == '\t')
*pos = '^';
pos++;
}
pos = buffer;
for(;;)
{
char *eofPos = dStrchr(pos, '\n');
if(eofPos)
*eofPos = 0;
log(pos);
if(logBufferEnabled)
{
ConsoleLogEntry entry;
entry.mLevel = level;
entry.mType = type;
entry.mString = (const char *)consoleLogChunker.alloc(dStrlen(pos) + 1);
dStrcpy(const_cast<char*>(entry.mString), pos);
consoleLog.push_back(entry);
}
if(!eofPos)
break;
pos = eofPos + 1;
}
}
}
//------------------------------------------------------------------------------
void printf(const char* fmt,...)
{
va_list argptr;
va_start(argptr, fmt);
_printf(ConsoleLogEntry::Normal, ConsoleLogEntry::General, fmt, argptr);
va_end(argptr);
}
void warnf(ConsoleLogEntry::Type type, const char* fmt,...)
{
va_list argptr;
va_start(argptr, fmt);
_printf(ConsoleLogEntry::Warning, type, fmt, argptr);
va_end(argptr);
}
void errorf(ConsoleLogEntry::Type type, const char* fmt,...)
{
va_list argptr;
va_start(argptr, fmt);
_printf(ConsoleLogEntry::Error, type, fmt, argptr);
va_end(argptr);
}
void warnf(const char* fmt,...)
{
va_list argptr;
va_start(argptr, fmt);
_printf(ConsoleLogEntry::Warning, ConsoleLogEntry::General, fmt, argptr);
va_end(argptr);
}
void errorf(const char* fmt,...)
{
va_list argptr;
va_start(argptr, fmt);
_printf(ConsoleLogEntry::Error, ConsoleLogEntry::General, fmt, argptr);
va_end(argptr);
}
//---------------------------------------------------------------------------
void setVariable(const char *name, const char *value)
{
name = prependDollar(name);
gEvalState.globalVars.setVariable(StringTable->insert(name), value);
}
void setLocalVariable(const char *name, const char *value)
{
name = prependPercent(name);
gEvalState.stack.last()->setVariable(StringTable->insert(name), value);
}
void setBoolVariable(const char *varName, bool value)
{
setVariable(varName, value ? "1" : "0");
}
void setIntVariable(const char *varName, S32 value)
{
char scratchBuffer[32];
dSprintf(scratchBuffer, sizeof(scratchBuffer), "%d", value);
setVariable(varName, scratchBuffer);
}
void setFloatVariable(const char *varName, F32 value)
{
char scratchBuffer[32];
dSprintf(scratchBuffer, sizeof(scratchBuffer), "%f", value);
setVariable(varName, scratchBuffer);
}
//---------------------------------------------------------------------------
void addConsumer(ConsumerCallback consumer)
{
gConsumers.push_back(consumer);
}
void removeConsumer(ConsumerCallback)
{
}
const char *getVariable(const char *name)
{
// get the field info from the object..
if(name[0] != '$' && dStrchr(name, '.') && !isFunction(name))
{
S32 len = dStrlen(name);
AssertFatal(len < sizeof(scratchBuffer)-1, "CONSOLE: name too long");
dMemcpy(scratchBuffer, name, len+1);
char * token = dStrtok(scratchBuffer, ".");
SimObject * obj = Sim::findObject(token);
if(!obj)
return("");
token = dStrtok(0, ".\0");
if(!token)
return("");
while(token != NULL)
{
const char * val = obj->getDataField(StringTable->insert(token), 0);
if(!val)
return("");
token = dStrtok(0, ".\0");
if(token)
{
obj = Sim::findObject(token);
if(!obj)
return("");
}
else
return(val);
}
}
name = prependDollar(name);
return gEvalState.globalVars.getVariable(StringTable->insert(name));
}
const char *getLocalVariable(const char *name)
{
name = prependPercent(name);
return gEvalState.stack.last()->getVariable(StringTable->insert(name));
}
bool getBoolVariable(const char *varName, bool def)
{
const char *value = getVariable(varName);
return *value ? dAtob(value) : def;
}
S32 getIntVariable(const char *varName, S32 def)
{
const char *value = getVariable(varName);
return *value ? dAtoi(value) : def;
}
F32 getFloatVariable(const char *varName, F32 def)
{
const char *value = getVariable(varName);
return *value ? dAtof(value) : def;
}
//---------------------------------------------------------------------------
bool addVariable(const char *name, S32 t, void *dp)
{
gEvalState.globalVars.addVariable(name, t, dp);
return true;
}
bool removeVariable(const char *name)
{
name = StringTable->lookup(prependDollar(name));
return name!=0 && gEvalState.globalVars.removeVariable(name);
}
//---------------------------------------------------------------------------
void addCommand(const char *nsName, const char *name,StringCallback cb, const char *usage, S32 minArgs, S32 maxArgs)
{
Namespace *ns = lookupNamespace(nsName);
ns->addCommand(StringTable->insert(name), cb, usage, minArgs, maxArgs);
}
void addCommand(const char *nsName, const char *name,VoidCallback cb, const char *usage, S32 minArgs, S32 maxArgs)
{
Namespace *ns = lookupNamespace(nsName);
ns->addCommand(StringTable->insert(name), cb, usage, minArgs, maxArgs);
}
void addCommand(const char *nsName, const char *name,IntCallback cb, const char *usage, S32 minArgs, S32 maxArgs)
{
Namespace *ns = lookupNamespace(nsName);
ns->addCommand(StringTable->insert(name), cb, usage, minArgs, maxArgs);
}
void addCommand(const char *nsName, const char *name,FloatCallback cb, const char *usage, S32 minArgs, S32 maxArgs)
{
Namespace *ns = lookupNamespace(nsName);
ns->addCommand(StringTable->insert(name), cb, usage, minArgs, maxArgs);
}
void addCommand(const char *nsName, const char *name,BoolCallback cb, const char *usage, S32 minArgs, S32 maxArgs)
{
Namespace *ns = lookupNamespace(nsName);
ns->addCommand(StringTable->insert(name), cb, usage, minArgs, maxArgs);
}
void addCommand(const char *name,StringCallback cb,const char *usage, S32 minArgs, S32 maxArgs)
{
Namespace::global()->addCommand(StringTable->insert(name), cb, usage, minArgs, maxArgs);
}
void addCommand(const char *name,VoidCallback cb,const char *usage, S32 minArgs, S32 maxArgs)
{
Namespace::global()->addCommand(StringTable->insert(name), cb, usage, minArgs, maxArgs);
}
void addCommand(const char *name,IntCallback cb,const char *usage, S32 minArgs, S32 maxArgs)
{
Namespace::global()->addCommand(StringTable->insert(name), cb, usage, minArgs, maxArgs);
}
void addCommand(const char *name,FloatCallback cb,const char *usage, S32 minArgs, S32 maxArgs)
{
Namespace::global()->addCommand(StringTable->insert(name), cb, usage, minArgs, maxArgs);
}
void addCommand(const char *name,BoolCallback cb,const char *usage, S32 minArgs, S32 maxArgs)
{
Namespace::global()->addCommand(StringTable->insert(name), cb, usage, minArgs, maxArgs);
}
const char *evaluate(const char* string, bool echo, const char *fileName)
{
if (echo)
printf("%s%s", getVariable( "$Con::Prompt" ), string);
if(fileName)
fileName = StringTable->insert(fileName);
CodeBlock *newCodeBlock = new CodeBlock();
return newCodeBlock->compileExec(fileName, string, false);
}
//------------------------------------------------------------------------------
const char *evaluatef(const char* string, ...)
{
char buffer[512];
va_list args;
va_start(args, string);
dVsprintf(buffer, sizeof(buffer), string, args);
CodeBlock *newCodeBlock = new CodeBlock();
return newCodeBlock->compileExec(NULL, buffer, false);
}
const char *execute(S32 argc, const char *argv[])
{
Namespace::Entry *ent;
StringTableEntry funcName = StringTable->insert(argv[0]);
ent = Namespace::global()->lookup(funcName);
if(!ent)
{
warnf(ConsoleLogEntry::Script, "%s: Unknown command.", argv[0]);
return "";
}
return ent->execute(argc, argv, &gEvalState);
}
//------------------------------------------------------------------------------
const char *execute(SimObject *object, S32 argc, const char *argv[])
{
static char idBuf[12];
if(argc < 2)
return "";
if(object->getNamespace())
{
dSprintf(idBuf, sizeof(idBuf), "%d", object->getId());
argv[1] = idBuf;
StringTableEntry funcName = StringTable->insert(argv[0]);
Namespace::Entry *ent = object->getNamespace()->lookup(funcName);
if(!ent)
{
//warnf(ConsoleLogEntry::Script, "%s: undefined for object '%s' - id %d", funcName, object->getName(), object->getId());
return "";
}
else
{
SimObject *save = gEvalState.thisObject;
gEvalState.thisObject = object;
const char *ret = ent->execute(argc, argv, &gEvalState);
gEvalState.thisObject = save;
return ret;
}
}
warnf(ConsoleLogEntry::Script, "Con::execute - %d has no namespace: %s", object->getId(), argv[0]);
return "";
}
const char *executef(SimObject *object, S32 argc, ...)
{
static char idBuf[12];
const char *argv[128];
va_list args;
va_start(args, argc);
for(S32 i = 0; i < argc; i++)
argv[i+1] = va_arg(args, const char *);
va_end(args);
argv[0] = argv[1];
argc++;
return execute(object, argc, argv);
}
//------------------------------------------------------------------------------
const char *executef(S32 argc, ...)
{
const char *argv[128];
va_list args;
va_start(args, argc);
for(S32 i = 0; i < argc; i++)
argv[i] = va_arg(args, const char *);
va_end(args);
return execute(argc, argv);
}
//------------------------------------------------------------------------------
bool isFunction(const char *fn)
{
const char *string = StringTable->lookup(fn);
if(!string)
return false;
else
return Namespace::global()->lookup(string) != NULL;
}
//------------------------------------------------------------------------------
void setLogMode(S32 newMode)
{
if(newMode != consoleLogMode)
{
if(newMode && !consoleLogMode)
newLogFile = true;
if(consoleLogMode == 2)
consoleLogFile.close();
else if(newMode == 2)
consoleLogFile.open(defLogFileName, FileStream::Write);
consoleLogMode = newMode;
}
}
Namespace *lookupNamespace(const char *ns)
{
if(!ns)
return Namespace::global();
return Namespace::find(StringTable->insert(ns));
}
void linkNamespaces(const char *parent, const char *child)
{
Namespace *pns = lookupNamespace(parent);
Namespace *cns = lookupNamespace(child);
if(pns && cns)
cns->classLinkTo(pns);
}
void classLinkNamespaces(Namespace *parent, Namespace *child)
{
if(parent && child)
child->classLinkTo(parent);
}
enum {
MaxDataTypes = 256
};
static S32 typeSizes[MaxDataTypes];
static GetDataFunction fnGetData[MaxDataTypes];
static SetDataFunction fnSetData[MaxDataTypes];
void registerType(S32 type, S32 size, GetDataFunction gdf, SetDataFunction sdf)
{
fnGetData[type] = gdf;
fnSetData[type] = sdf;
typeSizes[type] = size;
}
void setData(S32 type, void *dptr, S32 index, S32 argc, const char **argv, EnumTable *tbl, BitSet32 flag)
{
SetDataFunction fn = fnSetData[type];
AssertFatal(fn != NULL, "Error, mull setData fn");
fn((void *) (U32(dptr) + index * typeSizes[type]),argc, argv, tbl, flag);
}
const char *getData(S32 type, void *dptr, S32 index, EnumTable *tbl, BitSet32 flag)
{
GetDataFunction fn = fnGetData[type];
AssertFatal(fn != NULL, "Error, mull getData fn");
return fn((void *) (U32(dptr) + index * typeSizes[type]), tbl, flag);
}
} // end of Console namespace

199
console/console.h Normal file
View file

@ -0,0 +1,199 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _CONSOLE_H_
#define _CONSOLE_H_
#ifndef _PLATFORM_H_
#include "Platform/platform.h"
#endif
#ifndef _BITSET_H_
#include "Core/bitSet.h"
#endif
class SimObject;
struct EnumTable;
class Namespace;
enum
{
StringTagPrefixByte = 0x01
};
struct ConsoleLogEntry
{
enum Level
{
Normal = 0,
Warning,
Error,
NUM_CLASS
} mLevel;
enum Type
{
General = 0,
Assert,
Script,
GUI,
Network,
NUM_TYPE
} mType;
const char *mString;
};
struct EnumTable
{
S32 size;
struct Enums
{
S32 index;
const char *label;
};
Enums *table;
EnumTable(S32 sSize, Enums *sTable)
{ size = sSize; table = sTable; }
};
//---------------------------------------------------------------------------
typedef const char *StringTableEntry;
typedef const char *(*StringCallback)(SimObject *obj, S32 argc, const char *argv[]);
typedef S32 (*IntCallback)(SimObject *obj, S32 argc, const char *argv[]);
typedef F32 (*FloatCallback)(SimObject *obj, S32 argc, const char *argv[]);
typedef void (*VoidCallback)(SimObject *obj, S32 argc, const char *argv[]);
typedef bool (*BoolCallback)(SimObject *obj, S32 argc, const char *argv[]);
typedef void (*ConsumerCallback)(ConsoleLogEntry::Level level, const char *consoleLine);
typedef const char* (*GetDataFunction)(void *dptr, EnumTable *tbl, BitSet32 flag);
typedef void (*SetDataFunction)(void *dptr, S32 argc, const char **argv, EnumTable *tbl, BitSet32 flag);
namespace Con
{
enum {
MaxLineLength = 512
};
void init();
void shutdown();
bool isActive();
void addConsumer(ConsumerCallback cb);
void removeConsumer(ConsumerCallback cb);
void setVariable(const char *name, const char *value);
bool addVariable(const char *name, S32, void *);
bool removeVariable(const char *name);
const char* getVariable(const char* name);
const char* getLocalVariable(const char* name);
void setLocalVariable(const char *name, const char *value);
void addCommand(const char *name, StringCallback, const char *usage, S32 minArgs, S32 maxArgs);
void addCommand(const char *name, IntCallback, const char *usage, S32 minArgs, S32 maxArgs);
void addCommand(const char *name, FloatCallback, const char *usage, S32 minArgs, S32 maxArgs);
void addCommand(const char *name, VoidCallback, const char *usage, S32 minArgs, S32 maxArgs);
void addCommand(const char *name, BoolCallback, const char *usage, S32 minArgs, S32 maxArgs);
void addCommand(const char *nameSpace, const char *name,StringCallback, const char *usage, S32 minArgs, S32 maxArgs);
void addCommand(const char *nameSpace, const char *name,IntCallback, const char *usage, S32 minArgs, S32 maxArgs);
void addCommand(const char *nameSpace, const char *name,FloatCallback, const char *usage, S32 minArgs, S32 maxArgs);
void addCommand(const char *nameSpace, const char *name,VoidCallback, const char *usage, S32 minArgs, S32 maxArgs);
void addCommand(const char *nameSpace, const char *name,BoolCallback, const char *usage, S32 minArgs, S32 maxArgs);
bool removeCommand(const char *name);
void printf(const char *_format, ...);
void warnf(ConsoleLogEntry::Type type, const char *_format, ...);
void errorf(ConsoleLogEntry::Type type, const char *_format, ...);
void warnf(const char *_format, ...);
void errorf(const char *_format, ...);
const char *execute(S32 argc, const char* argv[]);
const char *executef(S32 argc, ...); // first param is funcName, remaining params are args
// first param is func name, second param MUST be empty (gets filled with object ID)
// also, MUST have at least those two params
const char *execute(SimObject *, S32 argc, const char *argv[]);
const char *executef(SimObject *, S32 argc, ...); // first param is funcName, remaining params are args
const char *evaluate(const char* string, bool echo = false, const char *fileName = NULL);
const char *evaluatef(const char* string, ...);
bool isFunction(const char *fn);
void setBoolVariable(const char* name,bool var);
bool getBoolVariable(const char* name,bool def = false);
void setIntVariable(const char* name,S32 var);
S32 getIntVariable(const char* name,S32 def = 0);
void setFloatVariable(const char* name,F32 var);
F32 getFloatVariable(const char* name,F32 def = .0f);
// console function implementation helpers
char *getReturnBuffer(U32 bufferSize);
char *getArgBuffer(U32 bufferSize);
char *getFloatArg(F64 arg);
char *getIntArg(S32 arg);
const char *tabComplete(const char *prevText, S32 baseLen, bool);
void exportVariables(const char *varString, Vector<const char *> &varName, Vector<const char *> &value);
Namespace *lookupNamespace(const char *nsName);
void linkNamespaces(const char *parentName, const char *childName);
// this should only be called from consoleObject.h
void classLinkNamespaces(Namespace *parent, Namespace *child);
void getLog(ConsoleLogEntry * &log, U32 &size);
// dynamic data management functions:
void setLogMode(S32 mode);
void registerType(S32 type, S32 size, GetDataFunction gdf, SetDataFunction sdf);
void setData(S32 type, void *dptr, S32 index, S32 argc, const char **argv, EnumTable *tbl = NULL, BitSet32 flag = 0);
const char *getData(S32 type, void *dptr, S32 index, EnumTable *tbl = NULL, BitSet32 flag = 0);
}
extern void expandEscape(char *dest, const char *src);
extern bool collapseEscape(char *buf);
extern S32 HashPointer(StringTableEntry ptr);
struct ConsoleConstructor
{
StringCallback sc;
IntCallback ic;
FloatCallback fc;
VoidCallback vc;
BoolCallback bc;
S32 mina, maxa;
const char *usage;
const char *funcName;
const char *className;
ConsoleConstructor *next;
static ConsoleConstructor *first;
void init(const char *cName, const char *fName, const char *usg, S32 minArgs, S32 maxArgs);
static void setup();
ConsoleConstructor(const char *className, const char *funcName, StringCallback sfunc, const char *usage, S32 minArgs, S32 maxArgs);
ConsoleConstructor(const char *className, const char *funcName, IntCallback ifunc, const char *usage, S32 minArgs, S32 maxArgs);
ConsoleConstructor(const char *className, const char *funcName, FloatCallback ffunc, const char *usage, S32 minArgs, S32 maxArgs);
ConsoleConstructor(const char *className, const char *funcName, VoidCallback vfunc, const char *usage, S32 minArgs, S32 maxArgs);
ConsoleConstructor(const char *className, const char *funcName, BoolCallback bfunc, const char *usage, S32 minArgs, S32 maxArgs);
};
#define ConsoleFunction(name,returnType,minArgs,maxArgs,usage) \
static returnType c##name(SimObject *, S32, const char **argv); \
static ConsoleConstructor g##name##obj(NULL,#name,c##name,usage,minArgs,maxArgs);\
static returnType c##name(SimObject *, S32 argc, const char **argv)
#define ConsoleMethod(className,name,returnType,minArgs,maxArgs,usage) \
static returnType c##className##name(SimObject *, S32, const char **argv); \
static ConsoleConstructor className##name##obj(#className,#name,c##className##name,usage,minArgs,maxArgs);\
static returnType c##className##name(SimObject *object, S32 argc, const char **argv)
#endif

136
console/consoleDoc.cc Normal file
View file

@ -0,0 +1,136 @@
#include "platform/platform.h"
#include "console/console.h"
#include "console/ast.h"
#include "core/tAlgorithm.h"
#include "core/resManager.h"
#include "core/findMatch.h"
#include "console/consoleInternal.h"
#include "console/consoleObject.h"
#include "core/fileStream.h"
#include "console/compiler.h"
ConsoleFunction(dumpConsoleClasses, void, 1, 1, "()dumps all declared console classes to the console in C++ syntax for documenting with dOxygen or another auto documentation tool")
{
Namespace::dumpClasses();
}
const char *typeNames[] = {
"Script",
"string",
"int",
"float",
"void",
"bool",
};
void Namespace::dumpClasses()
{
Vector<Namespace *> vec;
// the program
trashCache();
for(Namespace *walk = mNamespaceList; walk; walk = walk->mNext)
walk->mHashSequence = 0;
for(Namespace *walk = mNamespaceList; walk; walk = walk->mNext)
{
Vector<Namespace *> stack;
Namespace *parentWalk = walk;
while(parentWalk)
{
if(parentWalk->mHashSequence != 0)
break;
if(parentWalk->mPackage == 0)
{
parentWalk->mHashSequence = 1;
stack.push_back(parentWalk);
}
parentWalk = parentWalk->mParent;
}
while(stack.size())
{
vec.push_back(stack[stack.size() - 1]);
stack.pop_back();
}
}
U32 i;
for(i = 0; i < vec.size(); i++)
{
const char *className = vec[i]->mName;
const char *superClassName = vec[i]->mParent ? vec[i]->mParent->mName : NULL;
const char *virt = "virtual ";
if(vec[i]->mEntryList == NULL && vec[i]->mClassRep == NULL)
continue;
if(!className)
{
Con::printf("namespace Global {");
virt = "";
}
else if(!superClassName)
Con::printf("class %s { public:", className);
else
Con::printf("class %s : public %s { public:", className, superClassName);
for(Entry *ewalk = vec[i]->mEntryList; ewalk; ewalk = ewalk->mNext)
{
char buffer[1024];
if(ewalk->mType > Entry::ScriptFunctionType)
{
if(ewalk->mUsage[0] != '(')
Con::printf(" %s %s %s() {} // %s", virt, typeNames[ewalk->mType], ewalk->mFunctionName, ewalk->mUsage);
else
{
const char *use = ewalk->mUsage;
const char *end = dStrchr(use, ')');
if(!end)
end = use + 1;
use++;
U32 len = end - use;
dStrncpy(buffer, use, len);
buffer[len] = 0;
Con::printf(" %s %s %s(%s) {} // %s", virt, typeNames[ewalk->mType], ewalk->mFunctionName, buffer, end + 1);
}
}
else if(ewalk->mFunctionOffset)
{
ewalk->mCode->getFunctionArgs(buffer, ewalk->mFunctionOffset);
Con::printf(" %s void %s(%s) {} // declared script function", virt, ewalk->mFunctionName, buffer);
}
}
AbstractClassRep *rep = vec[i]->mClassRep;
AbstractClassRep::FieldList emptyList;
AbstractClassRep::FieldList *parentList = &emptyList;
AbstractClassRep::FieldList *fieldList = &emptyList;
if(rep)
{
AbstractClassRep *parentRep = vec[i]->mParent ? vec[i]->mParent->mClassRep : NULL;
if(parentRep)
parentList = &(parentRep->mFieldList);
fieldList = &(rep->mFieldList);
for(U32 j = 0; j < fieldList->size(); j++)
{
if((*fieldList)[j].type == AbstractClassRep::DepricatedFieldType)
continue;
bool found = false;
for(U32 k = 0; k < parentList->size(); k++)
{
if((*parentList)[k].pFieldname == (*fieldList)[j].pFieldname)
{
found = true;
break;
}
}
if(!found)
Con::printf(" %s %s;", Con::getTypeName((*fieldList)[j].type), (*fieldList)[j].pFieldname);
}
}
Con::printf("};");
}
}

1110
console/consoleFunctions.cc Normal file

File diff suppressed because it is too large Load diff

943
console/consoleInternal.cc Normal file
View file

@ -0,0 +1,943 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "console/console.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"
#define ST_INIT_SIZE 15
static char scratchBuffer[1024];
U32 Namespace::mCacheSequence = 0;
DataChunker Namespace::mCacheAllocator;
DataChunker Namespace::mAllocator;
Namespace *Namespace::mNamespaceList = NULL;
Namespace *Namespace::mGlobalNamespace = NULL;
bool canTabComplete(const char *prevText, const char *bestMatch,
const char *newText, S32 baseLen, bool fForward)
{
// test if it matches the first baseLen chars:
if(dStrnicmp(newText, prevText, baseLen))
return false;
if (fForward)
{
if(!bestMatch)
return dStricmp(newText, prevText) > 0;
else
return (dStricmp(newText, prevText) > 0) &&
(dStricmp(newText, bestMatch) < 0);
}
else
{
if (dStrlen(prevText) == (U32) baseLen)
{
// look for the 'worst match'
if(!bestMatch)
return dStricmp(newText, prevText) > 0;
else
return dStricmp(newText, bestMatch) > 0;
}
else
{
if (!bestMatch)
return (dStricmp(newText, prevText) < 0);
else
return (dStricmp(newText, prevText) < 0) &&
(dStricmp(newText, bestMatch) > 0);
}
}
}
//---------------------------------------------------------------
//
// Dictionary functions
//
//---------------------------------------------------------------
struct StringValue
{
S32 size;
char *val;
operator char *() { return val; }
StringValue &operator=(const char *string);
StringValue() { size = 0; val = NULL; }
~StringValue() { dFree(val); }
};
StringValue & StringValue::operator=(const char *string)
{
if(!val)
{
val = dStrdup(string);
size = dStrlen(val);
}
else
{
S32 len = dStrlen(string);
if(len < size)
dStrcpy(val, string);
else
{
size = len;
dFree(val);
val = dStrdup(string);
}
}
return *this;
}
static S32 QSORT_CALLBACK varCompare(const void* a,const void* b)
{
return dStricmp( (*((Dictionary::Entry **) a))->name, (*((Dictionary::Entry **) b))->name );
}
void Dictionary::exportVariables(const char *varString, const char *fileName, bool append)
{
const char *searchStr = varString;
Vector<Entry *> sortList(__FILE__, __LINE__);
for(S32 i = 0; i < hashTableSize;i ++)
{
Entry *walk = hashTable[i];
while(walk)
{
if(FindMatch::isMatch((char *) searchStr, (char *) walk->name))
sortList.push_back(walk);
walk = walk->nextEntry;
}
}
if(!sortList.size())
return;
dQsort((void *) &sortList[0], sortList.size(), sizeof(Entry *), varCompare);
Vector<Entry *>::iterator s;
char expandBuffer[1024];
FileStream strm;
if(fileName)
{
if(!ResourceManager->openFileForWrite(strm, ResourceManager->getBasePath(), fileName, append ? FileStream::ReadWrite : FileStream::Write))
{
Con::errorf(ConsoleLogEntry::General, "Unable to open file '%s for writing.", fileName);
return;
}
if(append)
strm.setPosition(strm.getStreamSize());
}
char buffer[1024];
const char *cat = fileName ? "\r\n" : "";
for(s = sortList.begin(); s != sortList.end(); s++)
{
switch((*s)->type)
{
case Entry::TypeInternalInt:
dSprintf(buffer, sizeof(buffer), "%s = %d;%s", (*s)->name, (*s)->ival, cat);
break;
case Entry::TypeInternalFloat:
dSprintf(buffer, sizeof(buffer), "%s = %g;%s", (*s)->name, (*s)->fval, cat);
break;
default:
expandEscape(expandBuffer, (*s)->getStringValue());
dSprintf(buffer, sizeof(buffer), "%s = \"%s\";%s", (*s)->name, expandBuffer, cat);
break;
}
if(fileName)
strm.write(dStrlen(buffer), buffer);
else
Con::printf("%s", buffer);
}
if(fileName)
strm.close();
}
void Dictionary::deleteVariables(const char *varString)
{
const char *searchStr = varString;
for(S32 i = 0; i < hashTableSize; i++)
{
Entry *walk = hashTable[i];
while(walk)
{
Entry *matchedEntry = (FindMatch::isMatch((char *) searchStr, (char *) walk->name)) ? walk : NULL;
walk = walk->nextEntry;
if (matchedEntry)
remove(matchedEntry); // assumes remove() is a stable remove (will not reorder entries on remove)
}
}
}
S32 HashPointer(StringTableEntry ptr)
{
return S32(U32(ptr) >> 2);
}
Dictionary::Entry *Dictionary::lookup(StringTableEntry name)
{
Entry *walk = hashTable[HashPointer(name) % hashTableSize];
while(walk)
{
if(walk->name == name)
return walk;
else
walk = walk->nextEntry;
}
return NULL;
}
Dictionary::Entry *Dictionary::add(StringTableEntry name)
{
Entry *walk = hashTable[HashPointer(name) % hashTableSize];
while(walk)
{
if(walk->name == name)
return walk;
else
walk = walk->nextEntry;
}
Entry *ret;
entryCount++;
if(entryCount > hashTableSize * 2)
{
Entry head(NULL), *walk;
S32 i;
walk = &head;
walk->nextEntry = 0;
for(i = 0; i < hashTableSize; i++) {
while(walk->nextEntry) {
walk = walk->nextEntry;
}
walk->nextEntry = hashTable[i];
}
delete[] hashTable;
hashTableSize = hashTableSize * 4 - 1;
hashTable = new Entry *[hashTableSize];
for(i = 0; i < hashTableSize; i++)
hashTable[i] = NULL;
walk = head.nextEntry;
while(walk)
{
Entry *temp = walk->nextEntry;
S32 idx = HashPointer(walk->name) % hashTableSize;
walk->nextEntry = hashTable[idx];
hashTable[idx] = walk;
walk = temp;
}
}
ret = new Entry(name);
S32 idx = HashPointer(name) % hashTableSize;
ret->nextEntry = hashTable[idx];
hashTable[idx] = ret;
return ret;
}
// deleteVariables() assumes remove() is a stable remove (will not reorder entries on remove)
void Dictionary::remove(Dictionary::Entry *ent)
{
Entry **walk = &hashTable[HashPointer(ent->name) % hashTableSize];
while(*walk != ent)
walk = &((*walk)->nextEntry);
*walk = (ent->nextEntry);
delete ent;
entryCount--;
}
Dictionary::Dictionary(ExprEvalState *state)
{
setState(state);
}
void Dictionary::setState(ExprEvalState *state)
{
S32 i;
entryCount = 0;
exprState = state;
hashTableSize = ST_INIT_SIZE;
hashTable = new Entry *[hashTableSize];
for(i = 0; i < hashTableSize; i++)
hashTable[i] = NULL;
}
Dictionary::~Dictionary()
{
reset();
delete [] hashTable;
}
void Dictionary::reset()
{
S32 i;
Entry *walk, *temp;
for(i = 0; i < hashTableSize; i++)
{
walk = hashTable[i];
while(walk)
{
temp = walk->nextEntry;
delete walk;
walk = temp;
}
hashTable[i] = NULL;
}
hashTableSize = ST_INIT_SIZE;
entryCount = 0;
}
const char *Dictionary::tabComplete(const char *prevText, S32 baseLen, bool fForward)
{
S32 i;
const char *bestMatch = NULL;
for(i = 0; i < hashTableSize; i++)
{
Entry *walk = hashTable[i];
while(walk)
{
if(canTabComplete(prevText, bestMatch, walk->name, baseLen, fForward))
bestMatch = walk->name;
walk = walk->nextEntry;
}
}
return bestMatch;
}
char *typeValueEmpty = "";
Dictionary::Entry::Entry(StringTableEntry in_name)
{
dataPtr = NULL;
name = in_name;
type = -1;
ival = 0;
fval = 0;
sval = typeValueEmpty;
}
Dictionary::Entry::~Entry()
{
if(sval != typeValueEmpty)
dFree(sval);
}
struct InternalPoint3F { F32 x,y,z; InternalPoint3F(F32 F){x=y=z=F;} };
const char *Dictionary::getVariable(StringTableEntry name, bool *entValid)
{
Entry *ent = lookup(name);
if(ent)
{
if(entValid)
*entValid = true;
return ent->getStringValue();
}
if(entValid)
*entValid = false;
return "";
}
void Dictionary::Entry::setStringValue(const char * value)
{
if(type <= TypeInternalString)
{
if(!value[0] && name[0] == '$')
{
gEvalState.globalVars.remove(this);
return;
}
fval = dAtof(value);
ival = fval;
type = TypeInternalString;
// may as well add to the next cache line
U32 newLen = ((dStrlen(value) + 1) + 15) & ~15;
if(sval == typeValueEmpty)
sval = (char *) dMalloc(newLen);
else if(newLen > bufferLen)
sval = (char *) dRealloc(sval, newLen);
bufferLen = newLen;
dStrcpy(sval, value);
}
else
Con::setData(type, dataPtr, 0, 1, &value);
}
void Dictionary::setVariable(StringTableEntry name, const char *value)
{
Entry *ent = add(name);
if(!value)
value = "";
ent->setStringValue(value);
}
void Dictionary::addVariable(const char *name, S32 type, void *dataPtr)
{
if(name[0] != '$')
{
scratchBuffer[0] = '$';
dStrcpy(scratchBuffer + 1, name);
name = scratchBuffer;
}
Entry *ent = add(StringTable->insert(name));
ent->type = type;
if(ent->sval != typeValueEmpty)
{
dFree(ent->sval);
ent->sval = typeValueEmpty;
}
ent->dataPtr = dataPtr;
}
bool Dictionary::removeVariable(StringTableEntry name)
{
if( Entry *ent = lookup(name) ){
remove( ent );
return true;
}
return false;
}
void ExprEvalState::pushFrame(StringTableEntry frameName, Namespace *ns)
{
Dictionary *newFrame = new Dictionary(this);
newFrame->scopeName = frameName;
newFrame->scopeNamespace = ns;
stack.push_back(newFrame);
}
void ExprEvalState::popFrame()
{
Dictionary *last = stack.last();
stack.pop_back();
delete last;
}
ExprEvalState::ExprEvalState()
{
VECTOR_SET_ASSOCIATION(stack);
globalVars.setState(this);
thisObject = NULL;
traceOn = false;
}
ExprEvalState::~ExprEvalState()
{
while(stack.size())
popFrame();
}
ConsoleFunction(backtrace, void, 1, 1, "backtrace();")
{
argc; argv;
U32 totalSize = 1;
for(U32 i = 0; i < gEvalState.stack.size(); i++)
{
totalSize += dStrlen(gEvalState.stack[i]->scopeName) + 3;
if(gEvalState.stack[i]->scopeNamespace && gEvalState.stack[i]->scopeNamespace->mName)
totalSize += dStrlen(gEvalState.stack[i]->scopeNamespace->mName) + 2;
}
char *buf = Con::getReturnBuffer(totalSize);
buf[0] = 0;
for(U32 i = 0; i < gEvalState.stack.size(); i++)
{
dStrcat(buf, "->");
if(gEvalState.stack[i]->scopeNamespace && gEvalState.stack[i]->scopeNamespace->mName)
{
dStrcat(buf, gEvalState.stack[i]->scopeNamespace->mName);
dStrcat(buf, "::");
}
dStrcat(buf, gEvalState.stack[i]->scopeName);
}
Con::printf("BackTrace: %s", buf);
}
Namespace::Entry::Entry()
{
mCode = NULL;
mType = InvalidFunctionType;
}
void Namespace::Entry::clear()
{
if(mCode)
{
mCode->decRefCount();
mCode = NULL;
}
}
Namespace::Namespace()
{
mPackage = NULL;
mName = NULL;
mParent = NULL;
mNext = NULL;
mEntryList = NULL;
mHashSize = 0;
mHashTable = 0;
mHashSequence = 0;
mRefCountToParent = 0;
}
void Namespace::clearEntries()
{
for(Entry *walk = mEntryList; walk; walk = walk->mNext)
walk->clear();
}
Namespace *Namespace::find(StringTableEntry name, StringTableEntry package)
{
for(Namespace *walk = mNamespaceList; walk; walk = walk->mNext)
if(walk->mName == name && walk->mPackage == package)
return walk;
Namespace *ret = (Namespace *) mAllocator.alloc(sizeof(Namespace));
constructInPlace(ret);
ret->mPackage = package;
ret->mName = name;
ret->mNext = mNamespaceList;
mNamespaceList = ret;
return ret;
}
void Namespace::classLinkTo(Namespace *parent)
{
Namespace *walk = this;
while(walk->mParent && walk->mParent->mName == mName)
walk = walk->mParent;
if(walk->mParent && walk->mParent != parent)
{
AssertFatal(0, avar("ERROR: Attempting to re-link namespace %s from %s to %s with non-zero refcount.", walk->mName, walk->mParent->mName, parent->mName));
Con::errorf(ConsoleLogEntry::General, "Attempting to re-link namespace %s from %s to %s with non-zero refcount.",
walk->mName, walk->mParent->mName, parent->mName);
return;
}
mRefCountToParent++;
walk->mParent = parent;
}
void Namespace::buildHashTable()
{
if(mHashSequence == mCacheSequence)
return;
if(!mEntryList && mParent)
{
mParent->buildHashTable();
mHashTable = mParent->mHashTable;
mHashSize = mParent->mHashSize;
mHashSequence = mCacheSequence;
return;
}
U32 entryCount = 0;
Namespace * ns;
for(ns = this; ns; ns = ns->mParent)
for(Entry *walk = ns->mEntryList; walk; walk = walk->mNext)
if(lookupRecursive(walk->mFunctionName) == walk)
entryCount++;
mHashSize = entryCount + (entryCount >> 1) + 1;
if(!(mHashSize &1))
mHashSize++;
mHashTable = (Entry **) mCacheAllocator.alloc(sizeof(Entry *) * mHashSize);
for(U32 i = 0; i < mHashSize; i++)
mHashTable[i] = NULL;
for(ns = this; ns; ns = ns->mParent)
{
for(Entry *walk = ns->mEntryList; walk; walk = walk->mNext)
{
U32 index = HashPointer(walk->mFunctionName) % mHashSize;
while(mHashTable[index] && mHashTable[index]->mFunctionName != walk->mFunctionName)
{
index++;
if(index >= mHashSize)
index = 0;
}
if(!mHashTable[index])
mHashTable[index] = walk;
}
}
mHashSequence = mCacheSequence;
}
void Namespace::init()
{
// create the global namespace
mGlobalNamespace = find(NULL);
}
Namespace *Namespace::global()
{
return mGlobalNamespace;
}
void Namespace::shutdown()
{
for(Namespace *walk = mNamespaceList; walk; walk = walk->mNext)
walk->clearEntries();
}
void Namespace::trashCache()
{
mCacheSequence++;
mCacheAllocator.freeBlocks();
}
const char *Namespace::tabComplete(const char *prevText, S32 baseLen, bool fForward)
{
if(mHashSequence != mCacheSequence)
buildHashTable();
const char *bestMatch = NULL;
for(U32 i = 0; i < mHashSize; i++)
if(mHashTable[i] && canTabComplete(prevText, bestMatch, mHashTable[i]->mFunctionName, baseLen, fForward))
bestMatch = mHashTable[i]->mFunctionName;
return bestMatch;
}
Namespace::Entry *Namespace::lookupRecursive(StringTableEntry name)
{
for(Namespace *ns = this; ns; ns = ns->mParent)
for(Entry *walk = ns->mEntryList; walk; walk = walk->mNext)
if(walk->mFunctionName == name)
return walk;
return NULL;
}
Namespace::Entry *Namespace::lookup(StringTableEntry name)
{
if(mHashSequence != mCacheSequence)
buildHashTable();
U32 index = HashPointer(name) % mHashSize;
while(mHashTable[index] && mHashTable[index]->mFunctionName != name)
{
index++;
if(index >= mHashSize)
index = 0;
}
return mHashTable[index];
}
static S32 QSORT_CALLBACK compareEntries(const void* a,const void* b)
{
const Namespace::Entry* fa = *((Namespace::Entry**)a);
const Namespace::Entry* fb = *((Namespace::Entry**)b);
return dStricmp(fa->mFunctionName, fb->mFunctionName);
}
void Namespace::getEntryList(Vector<Entry *> *vec)
{
if(mHashSequence != mCacheSequence)
buildHashTable();
for(U32 i = 0; i < mHashSize; i++)
if(mHashTable[i])
vec->push_back(mHashTable[i]);
dQsort(vec->address(),vec->size(),sizeof(Namespace::Entry *),compareEntries);
}
Namespace::Entry *Namespace::createLocalEntry(StringTableEntry name)
{
for(Entry *walk = mEntryList; walk; walk = walk->mNext)
{
if(walk->mFunctionName == name)
{
walk->clear();
return walk;
}
}
Entry *ent = (Entry *) mAllocator.alloc(sizeof(Entry));
constructInPlace(ent);
ent->mNamespace = this;
ent->mFunctionName = name;
ent->mNext = mEntryList;
mEntryList = ent;
return ent;
}
void Namespace::addFunction(StringTableEntry name, CodeBlock *cb, U32 functionOffset)
{
Entry *ent = createLocalEntry(name);
trashCache();
ent->mUsage = NULL;
ent->mCode = cb;
ent->mFunctionOffset = functionOffset;
ent->mCode->incRefCount();
ent->mType = Entry::ScriptFunctionType;
}
void Namespace::addCommand(StringTableEntry name,StringCallback cb, const char *usage, S32 minArgs, S32 maxArgs)
{
Entry *ent = createLocalEntry(name);
trashCache();
ent->mUsage = usage;
ent->mMinArgs = minArgs;
ent->mMaxArgs = maxArgs;
ent->mType = Entry::StringCallbackType;
ent->cb.mStringCallbackFunc = cb;
}
void Namespace::addCommand(StringTableEntry name,IntCallback cb, const char *usage, S32 minArgs, S32 maxArgs)
{
Entry *ent = createLocalEntry(name);
trashCache();
ent->mUsage = usage;
ent->mMinArgs = minArgs;
ent->mMaxArgs = maxArgs;
ent->mType = Entry::IntCallbackType;
ent->cb.mIntCallbackFunc = cb;
}
void Namespace::addCommand(StringTableEntry name,VoidCallback cb, const char *usage, S32 minArgs, S32 maxArgs)
{
Entry *ent = createLocalEntry(name);
trashCache();
ent->mUsage = usage;
ent->mMinArgs = minArgs;
ent->mMaxArgs = maxArgs;
ent->mType = Entry::VoidCallbackType;
ent->cb.mVoidCallbackFunc = cb;
}
void Namespace::addCommand(StringTableEntry name,FloatCallback cb, const char *usage, S32 minArgs, S32 maxArgs)
{
Entry *ent = createLocalEntry(name);
trashCache();
ent->mUsage = usage;
ent->mMinArgs = minArgs;
ent->mMaxArgs = maxArgs;
ent->mType = Entry::FloatCallbackType;
ent->cb.mFloatCallbackFunc = cb;
}
void Namespace::addCommand(StringTableEntry name,BoolCallback cb, const char *usage, S32 minArgs, S32 maxArgs)
{
Entry *ent = createLocalEntry(name);
trashCache();
ent->mUsage = usage;
ent->mMinArgs = minArgs;
ent->mMaxArgs = maxArgs;
ent->mType = Entry::BoolCallbackType;
ent->cb.mBoolCallbackFunc = cb;
}
extern S32 executeBlock(StmtNode *block, ExprEvalState *state);
const char *Namespace::Entry::execute(S32 argc, const char **argv, ExprEvalState *state)
{
if(mType == ScriptFunctionType)
{
if(mFunctionOffset)
return mCode->exec(mFunctionOffset, argv[0], mNamespace, argc, argv, false);
else
return "";
}
if((mMinArgs && argc < mMinArgs) || (mMaxArgs && argc > mMaxArgs))
{
Con::warnf(ConsoleLogEntry::Script, "%s::%s - wrong number of arguments.", mNamespace->mName, mFunctionName);
Con::warnf(ConsoleLogEntry::Script, "usage: %s", mUsage);
return "";
}
static char returnBuffer[32];
switch(mType)
{
case StringCallbackType:
return cb.mStringCallbackFunc(state->thisObject, argc, argv);
case IntCallbackType:
dSprintf(returnBuffer, sizeof(returnBuffer), "%d",
cb.mIntCallbackFunc(state->thisObject, argc, argv));
return returnBuffer;
case FloatCallbackType:
dSprintf(returnBuffer, sizeof(returnBuffer), "%g",
cb.mFloatCallbackFunc(state->thisObject, argc, argv));
return returnBuffer;
case VoidCallbackType:
cb.mVoidCallbackFunc(state->thisObject, argc, argv);
return "";
case BoolCallbackType:
dSprintf(returnBuffer, sizeof(returnBuffer), "%d",
(U32)cb.mBoolCallbackFunc(state->thisObject, argc, argv));
return returnBuffer;
}
return "";
}
StringTableEntry Namespace::mActivePackages[Namespace::MaxActivePackages];
U32 Namespace::mNumActivePackages = 0;
U32 Namespace::mOldNumActivePackages = 0;
bool Namespace::isPackage(StringTableEntry name)
{
for(Namespace *walk = mNamespaceList; walk; walk = walk->mNext)
if(walk->mPackage == name)
return true;
return false;
}
void Namespace::activatePackage(StringTableEntry name)
{
if(mNumActivePackages == MaxActivePackages)
{
Con::printf("ActivatePackage(%s) failed - Max package limit reached: %d", name, MaxActivePackages);
return;
}
if(!name)
return;
// see if this one's already active
for(U32 i = 0; i < mNumActivePackages; i++)
if(mActivePackages[i] == name)
return;
// kill the cache
trashCache();
// find all the package namespaces...
for(Namespace *walk = mNamespaceList; walk; walk = walk->mNext)
{
if(walk->mPackage == name)
{
Namespace *parent = Namespace::find(walk->mName);
// hook the parent
walk->mParent = parent->mParent;
parent->mParent = walk;
// now swap the entries:
Entry *ew;
for(ew = parent->mEntryList; ew; ew = ew->mNext)
ew->mNamespace = walk;
for(ew = walk->mEntryList; ew; ew = ew->mNext)
ew->mNamespace = parent;
ew = walk->mEntryList;
walk->mEntryList = parent->mEntryList;
parent->mEntryList = ew;
}
}
mActivePackages[mNumActivePackages++] = name;
}
void Namespace::deactivatePackage(StringTableEntry name)
{
S32 i, j;
for(i = 0; i < mNumActivePackages; i++)
if(mActivePackages[i] == name)
break;
if(i == mNumActivePackages)
return;
trashCache();
for(j = mNumActivePackages - 1; j >= i; j--)
{
// gotta unlink em in reverse order...
for(Namespace *walk = mNamespaceList; walk; walk = walk->mNext)
{
if(walk->mPackage == mActivePackages[j])
{
Namespace *parent = Namespace::find(walk->mName);
// hook the parent
parent->mParent = walk->mParent;
walk->mParent = NULL;
// now swap the entries:
Entry *ew;
for(ew = parent->mEntryList; ew; ew = ew->mNext)
ew->mNamespace = walk;
for(ew = walk->mEntryList; ew; ew = ew->mNext)
ew->mNamespace = parent;
ew = walk->mEntryList;
walk->mEntryList = parent->mEntryList;
parent->mEntryList = ew;
}
}
}
mNumActivePackages = i;
}
void Namespace::unlinkPackages()
{
mOldNumActivePackages = mNumActivePackages;
if(!mNumActivePackages)
return;
deactivatePackage(mActivePackages[0]);
}
void Namespace::relinkPackages()
{
if(!mOldNumActivePackages)
return;
for(U32 i = 0; i < mOldNumActivePackages; i++)
activatePackage(mActivePackages[i]);
}
ConsoleFunction(isPackage,bool,2,2,"isPackage(packageName)")
{
argc;
StringTableEntry packageName = StringTable->insert(argv[1]);
return Namespace::isPackage(packageName);
}
ConsoleFunction(activatePackage, void,2,2,"activatePackage(packageName)")
{
argc;
StringTableEntry packageName = StringTable->insert(argv[1]);
Namespace::activatePackage(packageName);
}
ConsoleFunction(deactivatePackage, void,2,2,"deactivatePackage(packageName)")
{
argc;
StringTableEntry packageName = StringTable->insert(argv[1]);
Namespace::deactivatePackage(packageName);
}

280
console/consoleInternal.h Normal file
View file

@ -0,0 +1,280 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _CONSOLEINTERNAL_H_
#define _CONSOLEINTERNAL_H_
#ifndef _STRINGTABLE_H_
#include "core/stringTable.h"
#endif
#ifndef _TVECTOR_H_
#include "core/tVector.h"
#endif
#ifndef _CONSOLETYPES_H_
#include "console/consoleTypes.h"
#endif
class ExprEvalState;
struct FunctionDecl;
class CodeBlock;
class Namespace
{
enum {
MaxActivePackages = 512,
};
static U32 mNumActivePackages;
static U32 mOldNumActivePackages;
static StringTableEntry mActivePackages[MaxActivePackages];
public:
StringTableEntry mName;
StringTableEntry mPackage;
Namespace *mParent;
Namespace *mNext;
U32 mRefCountToParent;
struct Entry
{
enum {
InvalidFunctionType = -1,
ScriptFunctionType,
StringCallbackType,
IntCallbackType,
FloatCallbackType,
VoidCallbackType,
BoolCallbackType
};
Namespace *mNamespace;
Entry *mNext;
StringTableEntry mFunctionName;
S32 mType;
S32 mMinArgs;
S32 mMaxArgs;
const char *mUsage;
CodeBlock *mCode;
U32 mFunctionOffset;
union {
StringCallback mStringCallbackFunc;
IntCallback mIntCallbackFunc;
VoidCallback mVoidCallbackFunc;
FloatCallback mFloatCallbackFunc;
BoolCallback mBoolCallbackFunc;
} cb;
Entry();
void clear();
const char *execute(S32 argc, const char **argv, ExprEvalState *state);
};
Entry *mEntryList;
Entry **mHashTable;
U32 mHashSize;
U32 mHashSequence;
Namespace();
void addFunction(StringTableEntry name, CodeBlock *cb, U32 functionOffset);
void addCommand(StringTableEntry name,StringCallback, const char *usage, S32 minArgs, S32 maxArgs);
void addCommand(StringTableEntry name,IntCallback, const char *usage, S32 minArgs, S32 maxArgs);
void addCommand(StringTableEntry name,FloatCallback, const char *usage, S32 minArgs, S32 maxArgs);
void addCommand(StringTableEntry name,VoidCallback, const char *usage, S32 minArgs, S32 maxArgs);
void addCommand(StringTableEntry name,BoolCallback, const char *usage, S32 minArgs, S32 maxArgs);
void getEntryList(Vector<Entry *> *);
Entry *lookup(StringTableEntry name);
Entry *lookupRecursive(StringTableEntry name);
Entry *createLocalEntry(StringTableEntry name);
void buildHashTable();
void clearEntries();
void classLinkTo(Namespace *parent);
const char *tabComplete(const char *prevText, S32 baseLen, bool fForward);
static U32 mCacheSequence;
static DataChunker mCacheAllocator;
static DataChunker mAllocator;
static void trashCache();
static Namespace *mNamespaceList;
static Namespace *mGlobalNamespace;
static void init();
static void shutdown();
static Namespace *global();
static Namespace *find(StringTableEntry name, StringTableEntry package=NULL);
static void activatePackage(StringTableEntry name);
static void deactivatePackage(StringTableEntry name);
static void unlinkPackages();
static void relinkPackages();
static bool isPackage(StringTableEntry name);
};
extern char *typeValueEmpty;
class Dictionary
{
public:
struct Entry
{
enum
{
TypeInternalInt = -3,
TypeInternalFloat = -2,
TypeInternalString = -1,
};
StringTableEntry name;
Entry *nextEntry;
S32 type;
char *sval;
U32 ival; // doubles as strlen when type = -1
F32 fval;
U32 bufferLen;
void *dataPtr;
Entry(StringTableEntry name);
~Entry();
U32 getIntValue()
{
if(type <= TypeInternalString)
return ival;
else
return dAtoi(Con::getData(type, dataPtr, 0));
}
F32 getFloatValue()
{
if(type <= TypeInternalString)
return fval;
else
return dAtof(Con::getData(type, dataPtr, 0));
}
const char *getStringValue()
{
if(type == TypeInternalString)
return sval;
if(type == TypeInternalFloat)
return Con::getData(TypeF32, &fval, 0);
else if(type == TypeInternalInt)
return Con::getData(TypeS32, &ival, 0);
else
return Con::getData(type, dataPtr, 0);
}
void setIntValue(U32 val)
{
if(type <= TypeInternalString)
{
fval = val;
ival = val;
if(sval != typeValueEmpty)
{
dFree(sval);
sval = typeValueEmpty;
}
type = TypeInternalInt;
return;
}
else
{
const char *dptr = Con::getData(TypeS32, &val, 0);
Con::setData(type, dataPtr, 0, 1, &dptr);
}
}
void setFloatValue(F32 val)
{
if(type <= TypeInternalString)
{
fval = val;
ival = val;
if(sval != typeValueEmpty)
{
dFree(sval);
sval = typeValueEmpty;
}
type = TypeInternalFloat;
return;
}
else
{
const char *dptr = Con::getData(TypeF32, &val, 0);
Con::setData(type, dataPtr, 0, 1, &dptr);
}
}
void setStringValue(const char *value);
};
private:
S32 hashTableSize;
S32 entryCount;
Entry **hashTable;
ExprEvalState *exprState;
public:
StringTableEntry scopeName;
Namespace *scopeNamespace;
CodeBlock *code;
U32 ip;
Dictionary() {}
Dictionary(ExprEvalState *state);
~Dictionary();
Entry *lookup(StringTableEntry name);
Entry *add(StringTableEntry name);
void setState(ExprEvalState *state);
void remove(Entry *);
void reset();
void exportVariables(const char *varString, const char *fileName, bool append);
void deleteVariables(const char *varString);
void setVariable(StringTableEntry name, const char *value);
const char *getVariable(StringTableEntry name, bool *valid = NULL);
void addVariable(const char *name, S32 type, void *dataPtr);
bool removeVariable(StringTableEntry name);
// return the best tab completion for prevText, with the length
// of the pre-tab string in baseLen
const char *tabComplete(const char *prevText, S32 baseLen, bool);
};
class ExprEvalState
{
public:
// stuff for doing expression evaluation
SimObject *thisObject;
Dictionary::Entry *currentVariable;
bool traceOn;
ExprEvalState();
~ExprEvalState();
// stack management
Dictionary globalVars;
Vector<Dictionary *> stack;
void setCurVarName(StringTableEntry name);
void setCurVarNameCreate(StringTableEntry name);
S32 getIntVariable();
F64 getFloatVariable();
const char *getStringVariable();
void setIntVariable(S32 val);
void setFloatVariable(F64 val);
void setStringVariable(const char *str);
void pushFrame(const char *frameName, Namespace *ns);
void popFrame();
};
#endif

191
console/consoleObject.cc Normal file
View file

@ -0,0 +1,191 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "console/consoleObject.h"
#include "core/stringTable.h"
#include "console/console.h"
static AbstractClassRep::FieldList sg_tempFieldList;
AbstractClassRep *AbstractClassRep::classLinkList = NULL;
AbstractClassRep *AbstractClassRep::classTable[MaxClassId+1];
bool AbstractClassRep::initialized = false;
//--------------------------------------
const AbstractClassRep::Field *AbstractClassRep::findField(StringTableEntry name) const
{
for(U32 i = 0; i < mFieldList.size(); i++)
if(mFieldList[i].pFieldname == name)
return &mFieldList[i];
return NULL;
}
//--------------------------------------
void AbstractClassRep::registerClassRep(AbstractClassRep* in_pRep)
{
AssertFatal(in_pRep != NULL, "Hmph, that's odd...");
#ifdef DEBUG // assert if this class is already registered.
for(AbstractClassRep *walk = classLinkList; walk; walk = walk->nextClass)
{
AssertFatal(dStrcmp(in_pRep->mClassName, walk->mClassName),
"Duplicate Class name registered.");
}
#endif
in_pRep->nextClass = classLinkList;
classLinkList = in_pRep;
}
//--------------------------------------
ConsoleObject* AbstractClassRep::create(const char* in_pClassName)
{
AssertFatal(initialized, "creating an object before AbstractClassRep::initialize.");
for (AbstractClassRep *walk = classLinkList; walk; walk = walk->nextClass)
if (!dStrcmp(walk->getClassName(), in_pClassName))
return walk->create();
AssertWarn(0, avar("Couldn't find class rep for dynamic class: %s", in_pClassName));
return NULL;
}
//--------------------------------------
ConsoleObject* AbstractClassRep::create(const S32 in_classId)
{
AssertFatal(initialized, "creating an object before AbstractClassRep::initialize.");
AssertFatal(in_classId >= 0 && in_classId <= MaxClassId, "Class id out of range.");
AssertFatal(classTable[in_classId] != NULL, "No class with declared id type.");
if(classTable[in_classId])
return classTable[in_classId]->create();
return NULL;
}
//--------------------------------------
static S32 QSORT_CALLBACK ACRCompare(const void *aptr, const void *bptr)
{
const AbstractClassRep *a = *((const AbstractClassRep **) aptr);
const AbstractClassRep *b = *((const AbstractClassRep **) bptr);
if(a->mClassIdBase != b->mClassIdBase)
return a->mClassIdBase - b->mClassIdBase;
if(a->mClassVersion != b->mClassVersion)
return a->mClassVersion - b->mClassVersion;
return dStrcmp(a->getClassName(), b->getClassName());
}
void AbstractClassRep::initialize()
{
AssertFatal(!initialized, "Duplicate call to AbstractClassRep::initialize()");
U32 i;
for(i = 0; i <= MaxClassId; i++)
classTable[i] = NULL;
Vector<AbstractClassRep *> dynamicTable(__FILE__, __LINE__);
AbstractClassRep *walk;
for (walk = classLinkList; walk; walk = walk->nextClass)
walk->mNamespace = Con::lookupNamespace(StringTable->insert(walk->getClassName()));
for (walk = classLinkList; walk; walk = walk->nextClass)
{
sg_tempFieldList.setSize(0);
walk->init();
if (sg_tempFieldList.size() != 0)
walk->mFieldList = sg_tempFieldList;
if(walk->mClassIdBase != -1)
dynamicTable.push_back(walk);
}
dQsort((void *) &dynamicTable[0], dynamicTable.size(), sizeof(AbstractClassRep *), ACRCompare);
S32 prevClassBase = -1;
S32 curClassId = 0;
for(i = 0; i < dynamicTable.size(); i++)
{
AbstractClassRep *cur = dynamicTable[i];
if(cur->mClassIdBase != prevClassBase)
{
AssertFatal(cur->mClassIdBase >= curClassId, avar("Class range too small %d", prevClassBase));
prevClassBase = cur->mClassIdBase;
curClassId = cur->mClassIdBase;
}
cur->mClassId = curClassId++;
classTable[cur->mClassId] = cur;
}
initialized = true;
sg_tempFieldList.clear();
}
//------------------------------------------------------------------------------
//-------------------------------------- ConsoleObject
void ConsoleObject::addField(const char* in_pFieldname,
const U32 in_fieldType,
const U32 in_fieldOffset,
const U32 in_elementCount,
EnumTable *in_table)
{
AbstractClassRep::Field f;
f.pFieldname = StringTable->insert(in_pFieldname);
f.type = in_fieldType;
f.offset = in_fieldOffset;
f.elementCount = in_elementCount;
f.table = in_table;
sg_tempFieldList.push_back(f);
}
void ConsoleObject::addDepricatedField(const char *fieldName)
{
AbstractClassRep::Field f;
f.pFieldname = StringTable->insert(fieldName);
f.type = AbstractClassRep::DepricatedFieldType;
sg_tempFieldList.push_back(f);
}
bool ConsoleObject::removeField(const char* in_pFieldname)
{
for (U32 i = 0; i < sg_tempFieldList.size(); i++) {
if (dStricmp(in_pFieldname, sg_tempFieldList[i].pFieldname) == 0) {
sg_tempFieldList.erase(i);
return true;
}
}
return false;
}
//--------------------------------------
void ConsoleObject::initPersistFields()
{
}
//--------------------------------------
void ConsoleObject::consoleInit()
{
}
ConsoleObject::~ConsoleObject()
{
}
//--------------------------------------
AbstractClassRep* ConsoleObject::getClassRep() const
{
return NULL;
}

334
console/consoleObject.h Normal file
View file

@ -0,0 +1,334 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _CONSOLEOBJECT_H_
#define _CONSOLEOBJECT_H_
//Includes
#ifndef _PLATFORM_H_
#include "platform/platform.h"
#endif
#ifndef _TVECTOR_H_
#include "core/tVector.h"
#endif
#ifndef _STRINGTABLE_H_
#include "core/stringTable.h"
#endif
#ifndef _BITSET_H_
#include "core/bitSet.h"
#endif
#ifndef _CONSOLE_H_
#include "console/console.h"
#endif
//------------------------------------------------------------------------------
//-------------------------------------- AbstractClassRep
//
class Namespace;
enum {
NetObjectClassFirst = 0,
NetObjectClassLast = 127,
NetObjectClassBitSize = 7,
DataBlockClassFirst = 128,
DataBlockClassLast = 255,
DataBlockClassBitSize = 7,
NetEventClassFirst = 255,
NetEventClassLast = 318,
NetEventClassBitSize = 6,
MaxClassId = 318
};
class AbstractClassRep
{
friend class ConsoleObject;
//-------------------------------------- Public interface
public:
enum
{
DepricatedFieldType = 0xFFFFFFFF
};
virtual ~AbstractClassRep() { }
AbstractClassRep() {
VECTOR_SET_ASSOCIATION(mFieldList);
}
S32 getClassId() const;
const char* getClassName() const;
Namespace * getNameSpace();
virtual ConsoleObject* create() const = 0;
AbstractClassRep *getNextClass();
static AbstractClassRep *getClassList();
//-------------------------------------- Field interface
public:
struct Field {
const char* pFieldname;
U32 type;
U32 offset;
S32 elementCount;
EnumTable *table;
BitSet32 flag;
};
typedef Vector<Field> FieldList;
FieldList mFieldList;
const Field *findField(StringTableEntry fieldName) const;
public:
S32 mClassIdBase;
S32 mClassVersion;
S32 mClassNetClass;
static void initialize(); // Called from CMDCon::init once on startup
protected:
static AbstractClassRep *classTable[MaxClassId+1];
static AbstractClassRep *classLinkList;
static bool initialized;
static void registerClassRep(AbstractClassRep*);
protected:
virtual void init() const = 0;
//---------------------------------------------------------------
// each registered tagged class has a id tag and a compiler
// independant class name
// if the class can be constructed by tag (network)
// the tag is >= 0.
protected:
const char *mClassName;
S32 mClassId;
AbstractClassRep *nextClass;
Namespace *mNamespace;
// Helper functions for ConsoleObject
protected:
static ConsoleObject* create(const char* in_pClassName);
static ConsoleObject* create(const S32 in_classId);
};
inline AbstractClassRep *AbstractClassRep::getClassList()
{
return classLinkList;
}
inline AbstractClassRep *AbstractClassRep::getNextClass()
{
return nextClass;
}
inline S32 AbstractClassRep::getClassId() const
{
return mClassId;
}
inline const char* AbstractClassRep::getClassName() const
{
return mClassName;
}
inline Namespace *AbstractClassRep::getNameSpace()
{
return mNamespace;
}
//------------------------------------------------------------------------------
//-------------------------------------- ConcreteClassRep
//
enum
{
NetEventClassAny,
NetEventClassClient,
NetEventClassServer
};
template <class T>
class ConcreteClassRep : public AbstractClassRep
{
public:
ConcreteClassRep(const char *name, S32 idBase = -1, S32 version=1,S32 netClass = NetEventClassAny)
{
// name is a static compiler string so no need to worry about copying or deleting
mClassName = name;
mClassId = -1;
mClassIdBase = idBase;
mClassVersion = version;
mClassNetClass = netClass;
registerClassRep(this);
};
void init() const
{
AbstractClassRep *parent = T::getParentStaticClassRep();
AbstractClassRep *child = T::getStaticClassRep();
if(parent && child)
Con::classLinkNamespaces(parent->getNameSpace(), child->getNameSpace());
T::initPersistFields();
T::consoleInit();
}
ConsoleObject* create() const { return new T; }
};
//------------------------------------------------------------------------------
//-------------------------------------- USER interface class. Derive from this,
// and access functionality through its
// static interface.
class ConsoleObject
{
protected:
ConsoleObject() { /* disallowed */ }
ConsoleObject(const ConsoleObject&); // disallowed ?
protected:
const AbstractClassRep::Field *findField(StringTableEntry fieldName) const;
public:
virtual AbstractClassRep* getClassRep() const;
bool setField(const char *fieldName, const char *value);
virtual ~ConsoleObject();
// Object creation interface
public:
static ConsoleObject* create(const char* in_pClassName);
static ConsoleObject* create(const U32 in_classId);
// Query interface
public:
static const char* lookupClassName(const U32 in_classTag);
// Field interface
protected:
static void addField(const char* in_pFieldname,
const U32 in_fieldType,
const U32 in_fieldOffset,
const U32 in_elementCount = 1,
EnumTable *in_table = NULL);
static void addDepricatedField(const char *fieldName);
static bool removeField(const char* in_pFieldname);
public:
static void initPersistFields(); // declare one of these in a class to register dynamic fields in a class.
static void consoleInit(); // declare one of these in a class to register console functions and establish namespace linkage
const AbstractClassRep::FieldList& getFieldList() const;
static AbstractClassRep *getStaticClassRep() { return NULL; }
static AbstractClassRep *getParentStaticClassRep() { return NULL; }
S32 getClassId() const;
const char *getClassName() const;
};
//------------------------------------------------------------------------------
//-------------------------------------- Inlines
//
inline S32 ConsoleObject::getClassId() const
{
AssertFatal(getClassRep() != NULL,
"Cannot get tag from non-declared dynamic class");
return getClassRep()->getClassId();
}
inline const char * ConsoleObject::getClassName() const
{
AssertFatal(getClassRep() != NULL,
"Cannot get tag from non-declared dynamic class");
return getClassRep()->getClassName();
}
inline const AbstractClassRep::Field * ConsoleObject::findField(StringTableEntry name) const
{
AssertFatal(getClassRep() != NULL,
"Cannot get tag from non-declared dynamic class");
return getClassRep()->findField(name);
}
inline bool ConsoleObject::setField(const char *fieldName, const char *value)
{
//sanity check
if ((! fieldName) || (! fieldName[0]) || (! value))
return false;
if (! getClassRep())
return false;
const AbstractClassRep::Field *myField = getClassRep()->findField(StringTable->insert(fieldName));
if (! myField)
return false;
Con::setData(myField->type, (void *) (S32(this) + myField->offset), 0, 1, &value, myField->table, myField->flag);
return true;
}
inline ConsoleObject* ConsoleObject::create(const char* in_pClassName)
{
return AbstractClassRep::create(in_pClassName);
}
inline ConsoleObject* ConsoleObject::create(const U32 in_classId)
{
return AbstractClassRep::create(in_classId);
}
inline const AbstractClassRep::FieldList& ConsoleObject::getFieldList() const
{
return getClassRep()->mFieldList;
}
//------------------------------------------------------------------------------
//-------------------------------------- MACROS for dynamic objects...
//
#define DECLARE_CONOBJECT(className) \
static ConcreteClassRep<className> dynClassRep; \
static AbstractClassRep* getParentStaticClassRep(); \
static AbstractClassRep* getStaticClassRep(); \
virtual AbstractClassRep* getClassRep() const
#define IMPLEMENT_CONOBJECT(className) \
AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
ConcreteClassRep<className> className::dynClassRep(#className)
#define IMPLEMENT_CO_NETOBJECT_V1(className) \
AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
ConcreteClassRep<className> className::dynClassRep(#className,NetObjectClassFirst,1)
#define IMPLEMENT_CO_DATABLOCK_V1(className) \
AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
ConcreteClassRep<className> className::dynClassRep(#className,DataBlockClassFirst,1)
#define IMPLEMENT_CO_NETEVENT_V1(className) \
AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
ConcreteClassRep<className> className::dynClassRep(#className,NetEventClassFirst,1,NetEventClassAny)
#define IMPLEMENT_CO_CLIENTEVENT_V1(className) \
AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
ConcreteClassRep<className> className::dynClassRep(#className,NetEventClassFirst,1,NetEventClassClient)
#define IMPLEMENT_CO_SERVEREVENT_V1(className) \
AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
ConcreteClassRep<className> className::dynClassRep(#className,NetEventClassFirst,1,NetEventClassServer)
#endif //_CONSOLEOBJECT_H_

429
console/consoleTypes.cc Normal file
View file

@ -0,0 +1,429 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "console/console.h"
#include "console/consoleTypes.h"
#include "Core/stringTable.h"
#include "Core/color.h"
#include "console/simBase.h"
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
static const char *getDataTypeString(void *dptr, EnumTable *, BitSet32)
{
return *((const char **)(dptr));
}
static void setDataTypeString(void *dptr, S32 argc, const char **argv, EnumTable *, BitSet32)
{
if(argc == 1)
*((const char **) dptr) = StringTable->insert(argv[0]);
else
Con::printf("(TypeString) Cannot set multiple args to a single string.");
}
static void setDataTypeCaseString(void *dptr, S32 argc, const char **argv, EnumTable *, BitSet32)
{
if(argc == 1)
*((const char **) dptr) = StringTable->insert(argv[0], true);
else
Con::printf("(TypeCaseString) Cannot set multiple args to a single string.");
}
static const char *getDataTypeCharArray(void *dptr, EnumTable *, BitSet32)
{
return (const char *)(dptr);
}
//----------------------------------------------------------------------------
static const char *getDataTypeU8(void *dptr, EnumTable *, BitSet32)
{
char* returnBuffer = Con::getReturnBuffer(256);
dSprintf(returnBuffer, 256, "%d", *((U8 *) dptr) );
return returnBuffer;
}
static void setDataTypeU8(void *dptr, S32 argc, const char **argv, EnumTable *, BitSet32)
{
if(argc == 1)
*((U8 *) dptr) = dAtoi(argv[0]);
else
Con::printf("(TypeU8) Cannot set multiple args to a single S32.");
}
static const char *getDataTypeS32(void *dptr, EnumTable *, BitSet32)
{
char* returnBuffer = Con::getReturnBuffer(256);
dSprintf(returnBuffer, 256, "%d", *((S32 *) dptr) );
return returnBuffer;
}
static void setDataTypeS32(void *dptr, S32 argc, const char **argv, EnumTable *, BitSet32)
{
if(argc == 1)
*((S32 *) dptr) = dAtoi(argv[0]);
else
Con::printf("(TypeS32) Cannot set multiple args to a single S32.");
}
//-----------------------------------------------------------------------------
static const char *getDataTypeS32Vector(void *dptr, EnumTable *, BitSet32)
{
Vector<S32> *vec = (Vector<S32> *)dptr;
char* returnBuffer = Con::getReturnBuffer(1024);
S32 maxReturn = 1024;
returnBuffer[0] = '\0';
S32 returnLeng = 0;
for (Vector<S32>::iterator itr = vec->begin(); itr != vec->end(); itr++)
{
// concatenate the next value onto the return string
dSprintf(returnBuffer + returnLeng, maxReturn - returnLeng, "%d ", *itr);
// update the length of the return string (so far)
returnLeng = dStrlen(returnBuffer);
}
// trim off that last extra space
if (returnLeng > 0 && returnBuffer[returnLeng - 1] == ' ')
returnBuffer[returnLeng - 1] = '\0';
return returnBuffer;
}
static void setDataTypeS32Vector(void *dptr, S32 argc, const char **argv, EnumTable *, BitSet32)
{
Vector<S32> *vec = (Vector<S32> *)dptr;
// we assume the vector should be cleared first (not just appending)
vec->clear();
if(argc == 1)
{
const char *values = argv[0];
const char *endValues = values + dStrlen(values);
S32 value;
// advance through the string, pulling off S32's and advancing the pointer
while (values < endValues && dSscanf(values, "%d", &value) != 0)
{
vec->push_back(value);
const char *nextValues = dStrchr(values, ' ');
if (nextValues != 0 && nextValues < endValues)
values = nextValues + 1;
else
break;
}
}
else if (argc > 1)
{
for (S32 i = 0; i < argc; i++)
vec->push_back(dAtoi(argv[i]));
}
else
Con::printf("Vector<S32> must be set as { a, b, c, ... } or \"a b c ...\"");
}
//-----------------------------------------------------------------------------
static const char *getDataTypeF32(void *dptr, EnumTable *, BitSet32)
{
char* returnBuffer = Con::getReturnBuffer(256);
dSprintf(returnBuffer, 256, "%g", *((F32 *) dptr) );
return returnBuffer;
}
static void setDataTypeF32(void *dptr, S32 argc, const char **argv, EnumTable *, BitSet32)
{
if(argc == 1)
*((F32 *) dptr) = dAtof(argv[0]);
else
Con::printf("(TypeF32) Cannot set multiple args to a single F32.");
}
//-----------------------------------------------------------------------------
static const char *getDataTypeF32Vector(void *dptr, EnumTable *, BitSet32)
{
Vector<F32> *vec = (Vector<F32> *)dptr;
char* returnBuffer = Con::getReturnBuffer(1024);
S32 maxReturn = 1024;
returnBuffer[0] = '\0';
S32 returnLeng = 0;
for (Vector<F32>::iterator itr = vec->begin(); itr != vec->end(); itr++)
{
// concatenate the next value onto the return string
dSprintf(returnBuffer + returnLeng, maxReturn - returnLeng, "%f ", *itr);
// update the length of the return string (so far)
returnLeng = dStrlen(returnBuffer);
}
// trim off that last extra space
if (returnLeng > 0 && returnBuffer[returnLeng - 1] == ' ')
returnBuffer[returnLeng - 1] = '\0';
return returnBuffer;
}
static void setDataTypeF32Vector(void *dptr, S32 argc, const char **argv, EnumTable *, BitSet32)
{
Vector<F32> *vec = (Vector<F32> *)dptr;
// we assume the vector should be cleared first (not just appending)
vec->clear();
if(argc == 1)
{
const char *values = argv[0];
const char *endValues = values + dStrlen(values);
F32 value;
// advance through the string, pulling off F32's and advancing the pointer
while (values < endValues && dSscanf(values, "%f", &value) != 0)
{
vec->push_back(value);
const char *nextValues = dStrchr(values, ' ');
if (nextValues != 0 && nextValues < endValues)
values = nextValues + 1;
else
break;
}
}
else if (argc > 1)
{
for (S32 i = 0; i < argc; i++)
vec->push_back(dAtof(argv[i]));
}
else
Con::printf("Vector<F32> must be set as { a, b, c, ... } or \"a b c ...\"");
}
//-----------------------------------------------------------------------------
static const char *getDataTypeBool(void *dptr, EnumTable *, BitSet32)
{
return *((bool *) dptr) ? "1" : "0";
}
static void setDataTypeBool(void *dptr, S32 argc, const char **argv, EnumTable *, BitSet32)
{
if(argc == 1)
*((bool *) dptr) = dAtob(argv[0]);
else
Con::printf("(TypeBool) Cannot set multiple args to a single bool.");
}
static const char *getDataTypeBoolVector(void *dptr, EnumTable *, BitSet32)
{
Vector<bool> *vec = (Vector<bool>*)dptr;
char* returnBuffer = Con::getReturnBuffer(1024);
S32 maxReturn = 1024;
returnBuffer[0] = '\0';
S32 returnLeng = 0;
for (Vector<bool>::iterator itr = vec->begin(); itr < vec->end(); itr++)
{
// concatenate the next value onto the return string
dSprintf(returnBuffer + returnLeng, maxReturn - returnLeng, "%d ", (*itr == true ? 1 : 0));
returnLeng = dStrlen(returnBuffer);
}
// trim off that last extra space
if (returnLeng > 0 && returnBuffer[returnLeng - 1] == ' ')
returnBuffer[returnLeng - 1] = '\0';
return(returnBuffer);
}
static void setDataTypeBoolVector(void *dptr, S32 argc, const char **argv, EnumTable *, BitSet32)
{
Vector<bool> *vec = (Vector<bool>*)dptr;
// we assume the vector should be cleared first (not just appending)
vec->clear();
if (argc == 1)
{
const char *values = argv[0];
const char *endValues = values + dStrlen(values);
S32 value;
// advance through the string, pulling off bool's and advancing the pointer
while (values < endValues && dSscanf(values, "%d", &value) != 0)
{
vec->push_back(value == 0 ? false : true);
const char *nextValues = dStrchr(values, ' ');
if (nextValues != 0 && nextValues < endValues)
values = nextValues + 1;
else
break;
}
}
else if (argc > 1)
{
for (S32 i = 0; i < argc; i++)
vec->push_back(dAtob(argv[i]));
}
else
Con::printf("Vector<bool> must be set as { a, b, c, ... } or \"a b c ...\"");
}
static const char *getDataTypeEnum(void *dptr, EnumTable *tbl, BitSet32)
{
AssertFatal(tbl, "Null enum table passed to getDataTypeEnum()");
S32 dptrVal = *(S32*)dptr;
for (S32 i = 0; i < tbl->size; i++)
{
if (dptrVal == tbl->table[i].index)
{
return tbl->table[i].label;
}
}
//not found
return "";
}
static void setDataTypeEnum(void *dptr, S32 argc, const char **argv, EnumTable *tbl, BitSet32)
{
AssertFatal(tbl, "Null enum table passed to setDataTypeEnum()");
if (argc != 1) return;
S32 val = 0;
for (S32 i = 0; i < tbl->size; i++)
{
if (! dStricmp(argv[0], tbl->table[i].label))
{
val = tbl->table[i].index;
break;
}
}
*((S32 *) dptr) = val;
}
static const char *getDataTypeFlag(void *dptr, EnumTable *, BitSet32 flag)
{
BitSet32 tempFlags = *(BitSet32 *)dptr;
if (tempFlags.test(flag)) return "true";
else return "false";
}
static void setDataTypeFlag(void *dptr, S32 argc, const char **argv, EnumTable *, BitSet32 flag)
{
bool value = true;
if (argc != 1)
{
Con::printf("flag must be true or false");
}
else
{
value = dAtob(argv[0]);
}
((BitSet32 *)dptr)->set(flag, value);
}
static const char *getDataTypeColorF(void *dptr, EnumTable *, BitSet32)
{
ColorF * color = (ColorF*)dptr;
char* returnBuffer = Con::getReturnBuffer(256);
dSprintf(returnBuffer, 256, "%f %f %f %f", color->red, color->green, color->blue, color->alpha);
return(returnBuffer);
}
static void setDataTypeColorF(void *dptr, S32 argc, const char ** argv, EnumTable *, BitSet32)
{
ColorF *tmpColor = (ColorF *) dptr;
if(argc == 1)
{
tmpColor->set(0, 0, 0, 1);
F32 r,g,b,a;
S32 args = dSscanf(argv[0], "%f %f %f %f", &r, &g, &b, &a);
tmpColor->red = r;
tmpColor->green = g;
tmpColor->blue = b;
if (args == 4)
tmpColor->alpha = a;
}
else if(argc == 3)
{
tmpColor->red = dAtof(argv[0]);
tmpColor->green = dAtof(argv[1]);
tmpColor->blue = dAtof(argv[2]);
tmpColor->alpha = 1.f;
}
else if(argc == 4)
{
tmpColor->red = dAtof(argv[0]);
tmpColor->green = dAtof(argv[1]);
tmpColor->blue = dAtof(argv[2]);
tmpColor->alpha = dAtof(argv[3]);
}
else
Con::printf("Color must be set as { r, g, b [,a] }");
}
static const char *getDataTypeColorI(void *dptr, EnumTable *, BitSet32)
{
ColorI *color = (ColorI *) dptr;
char* returnBuffer = Con::getReturnBuffer(256);
dSprintf(returnBuffer, 256, "%d %d %d %d", color->red, color->green, color->blue, color->alpha);
return returnBuffer;
}
static void setDataTypeColorI(void *dptr, S32 argc, const char **argv, EnumTable *, BitSet32)
{
ColorI *tmpColor = (ColorI *) dptr;
if(argc == 1)
{
tmpColor->set(0, 0, 0, 255);
S32 r,g,b,a;
S32 args = dSscanf(argv[0], "%d %d %d %d", &r, &g, &b, &a);
tmpColor->red = r;
tmpColor->green = g;
tmpColor->blue = b;
if (args == 4)
tmpColor->alpha = a;
}
else if(argc == 3)
{
tmpColor->red = dAtoi(argv[0]);
tmpColor->green = dAtoi(argv[1]);
tmpColor->blue = dAtoi(argv[2]);
tmpColor->alpha = 255;
}
else if(argc == 4)
{
tmpColor->red = dAtoi(argv[0]);
tmpColor->green = dAtoi(argv[1]);
tmpColor->blue = dAtoi(argv[2]);
tmpColor->alpha = dAtoi(argv[3]);
}
else
Con::printf("Color must be set as { r, g, b [,a] }");
}
static void setDataTypeSimObjectPtr(void *dptr, S32 argc, const char **argv, EnumTable *, BitSet32)
{
if(argc == 1)
{
SimObject **obj = (SimObject **)dptr;
*obj = Sim::findObject(argv[0]);
}
else
Con::printf("(TypeSimObjectPtr) Cannot set multiple args to a single S32.");
}
static const char *getDataTypeSimObjectPtr(void *dptr, EnumTable *, BitSet32)
{
SimObject **obj = (SimObject**)dptr;
char* returnBuffer = Con::getReturnBuffer(256);
dSprintf(returnBuffer, 256, "%s", *obj ? (*obj)->getName() : "");
return returnBuffer;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void RegisterCoreTypes(void)
{
Con::registerType(TypeS8, sizeof(U8), getDataTypeU8, setDataTypeU8);
Con::registerType(TypeS32, sizeof(S32), getDataTypeS32, setDataTypeS32);
Con::registerType(TypeS32Vector, sizeof(Vector<S32>), getDataTypeS32Vector, setDataTypeS32Vector);
Con::registerType(TypeBool, sizeof(bool), getDataTypeBool, setDataTypeBool);
Con::registerType(TypeBoolVector, sizeof(Vector<bool>), getDataTypeBoolVector, setDataTypeBoolVector);
Con::registerType(TypeF32, sizeof(F32), getDataTypeF32, setDataTypeF32);
Con::registerType(TypeF32Vector, sizeof(Vector<F32>), getDataTypeF32Vector, setDataTypeF32Vector);
Con::registerType(TypeString, sizeof(const char *), getDataTypeString, setDataTypeString);
Con::registerType(TypeCaseString, sizeof(const char *), getDataTypeString, setDataTypeCaseString);
Con::registerType(TypeEnum, sizeof(S32), getDataTypeEnum, setDataTypeEnum);
Con::registerType(TypeFlag, sizeof(S32), getDataTypeFlag, setDataTypeFlag);
Con::registerType(TypeColorI, sizeof(ColorI), getDataTypeColorI, setDataTypeColorI);
Con::registerType(TypeColorF, sizeof(ColorF), getDataTypeColorF, setDataTypeColorF);
Con::registerType(TypeSimObjectPtr, sizeof(SimObject*), getDataTypeSimObjectPtr, setDataTypeSimObjectPtr);
}

71
console/consoleTypes.h Normal file
View file

@ -0,0 +1,71 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _CONSOLETYPES_H_
#define _CONSOLETYPES_H_
#define Offset(x, cls) (S32)&(((cls *)0)->x)
enum ConsoleDynamicTypes {
//Registered in ConsoleTypes.cc
TypeS8 = 0,
TypeS32,
TypeS32Vector,
TypeBool,
TypeBoolVector,
TypeF32,
TypeF32Vector,
TypeString,
TypeCaseString,
TypeEnum,
TypeFlag,
TypeColorI,
TypeColorF,
TypeSimObjectPtr,
//Registered in MathTypes.cc
TypePoint2I,
TypePoint2F,
TypePoint3F,
TypePoint4F,
TypeRectI,
TypeRectF,
TypeMatrixPosition,
TypeMatrixRotation,
TypeBox3F,
//Registered in GuiTypes.cc
TypeGuiProfile,
// Game types
TypeGameBaseDataPtr,
TypeExplosionDataPtr,
TypeShockwaveDataPtr,
TypeSplashDataPtr,
TypeEnergyProjectileDataPtr,
TypeBombProjectileDataPtr,
TypeParticleEmitterDataPtr,
TypeAudioDescriptionPtr,
TypeAudioProfilePtr,
TypeTriggerPolyhedron,
TypeProjectileDataPtr,
TypeCannedChatItemPtr,
TypeWayPointTeam,
TypeDebrisDataPtr,
TypeCommanderIconDataPtr,
TypeDecalDataPtr,
TypeEffectProfilePtr,
TypeAudioEnvironmentPtr,
TypeAudioSampleEnvironmentPtr,
NumConsoleTypes
};
void RegisterCoreTypes(void);
#endif

2439
console/gram.cc Normal file

File diff suppressed because it is too large Load diff

84
console/gram.h Normal file
View file

@ -0,0 +1,84 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#define rwDEFINE 257
#define rwENDDEF 258
#define rwDECLARE 259
#define rwBREAK 260
#define rwELSE 261
#define rwCONTINUE 262
#define rwGLOBAL 263
#define rwIF 264
#define rwNIL 265
#define rwRETURN 266
#define rwWHILE 267
#define rwENDIF 268
#define rwENDWHILE 269
#define rwENDFOR 270
#define rwDEFAULT 271
#define rwFOR 272
#define rwDATABLOCK 273
#define rwSWITCH 274
#define rwCASE 275
#define rwSWITCHSTR 276
#define rwCASEOR 277
#define rwPACKAGE 278
#define ILLEGAL_TOKEN 279
#define CHRCONST 280
#define INTCONST 281
#define TTAG 282
#define VAR 283
#define IDENT 284
#define STRATOM 285
#define TAGATOM 286
#define FLTCONST 287
#define opMINUSMINUS 288
#define opPLUSPLUS 289
#define STMT_SEP 290
#define opSHL 291
#define opSHR 292
#define opPLASN 293
#define opMIASN 294
#define opMLASN 295
#define opDVASN 296
#define opMODASN 297
#define opANDASN 298
#define opXORASN 299
#define opORASN 300
#define opSLASN 301
#define opSRASN 302
#define opCAT 303
#define opEQ 304
#define opNE 305
#define opGE 306
#define opLE 307
#define opAND 308
#define opOR 309
#define opSTREQ 310
#define opCOLONCOLON 311
typedef union {
char c;
int i;
const char *s;
char *str;
double f;
StmtNode *stmt;
ExprNode *expr;
SlotAssignNode *slist;
VarNode *var;
SlotDecl slot;
ObjectBlockDecl odcl;
ObjectDeclNode *od;
AssignDecl asn;
IfStmtNode *ifnode;
} YYSTYPE;
#define opMDASN 312
#define opNDASN 313
#define opNTASN 314
#define opSTRNE 315
#define UNARY 316
extern YYSTYPE CMDlval;

493
console/gram.y Normal file
View file

@ -0,0 +1,493 @@
%{
#include "console.h"
#include "ast.h"
#include <stdlib.h>
#include "stdio.h"
#include "consoleInternal.h"
#ifndef YYDEBUG
#define YYDEBUG
#endif
#define YYSSIZE 350
int outtext(char *fmt, ...);
extern int serrors;
#define nil 0
#undef YY_ARGS
#define YY_ARGS(x) x
%}
%{
/* Reserved Word Definitions */
%}
%token <i> rwDEFINE rwENDDEF rwDECLARE
%token <i> rwBREAK rwELSE rwCONTINUE rwGLOBAL
%token <i> rwIF rwNIL rwRETURN rwWHILE
%token <i> rwENDIF rwENDWHILE rwENDFOR rwDEFAULT
%token <i> rwFOR rwDATABLOCK rwSWITCH rwCASE rwSWITCHSTR
%token <i> rwCASEOR rwPACKAGE
%token ILLEGAL_TOKEN
%{
/* Constants and Identifier Definitions */
%}
%token <c> CHRCONST
%token <i> INTCONST
%token <s> TTAG
%token <s> VAR
%token <s> IDENT
%token <str> STRATOM
%token <str> TAGATOM
%token <f> FLTCONST
%{
/* Operator Definitions */
%}
%token <i> '+' '-' '*' '/' '<' '>' '=' '.' '|' '&' '%'
%token <i> '(' ')' ',' ':' ';' '{' '}' '^' '~' '!' '@'
%token <i> opMINUSMINUS opPLUSPLUS
%token <i> STMT_SEP
%token <i> opSHL opSHR opPLASN opMIASN opMLASN opDVASN opMODASN opANDASN
%token <i> opXORASN opORASN opSLASN opSRASN opCAT
%token <i> opEQ opNE opGE opLE opAND opOR opSTREQ
%token <i> opCOLONCOLON
%union {
char c;
int i;
const char *s;
char *str;
double f;
StmtNode *stmt;
ExprNode *expr;
SlotAssignNode *slist;
VarNode *var;
SlotDecl slot;
ObjectBlockDecl odcl;
ObjectDeclNode *od;
AssignDecl asn;
IfStmtNode *ifnode;
}
%type <ifnode> case_block
%type <stmt> switch_stmt
%type <stmt> decl
%type <stmt> decl_list
%type <stmt> package_decl
%type <stmt> fn_decl_stmt
%type <stmt> fn_decl_list
%type <stmt> statement_list
%type <stmt> stmt
%type <expr> expr_list
%type <expr> expr_list_decl
%type <expr> aidx_expr
%type <expr> funcall_expr
%type <expr> object_name
%type <expr> object_args
%type <expr> stmt_expr
%type <expr> case_expr
%type <expr> class_name_expr
%type <stmt> if_stmt
%type <stmt> while_stmt
%type <stmt> for_stmt
%type <stmt> stmt_block
%type <stmt> datablock_decl
%type <od> object_decl
%type <od> object_decl_list
%type <odcl> object_declare_block
%type <expr> expr
%type <slist> slot_assign_list
%type <slist> slot_assign
%type <slot> slot_acc
%type <stmt> expression_stmt
%type <var> var_list
%type <var> var_list_decl
%type <asn> assign_op_struct
%left '['
%right opMODASN opANDASN opXORASN opPLASN opMIASN opMLASN opDVASN opMDASN opNDASN opNTASN opORASN opSLASN opSRASN '='
%left '?' ':'
%left opOR
%left opAND
%left '|'
%left '^'
%left '&'
%left opEQ opNE
%left '<' opLE '>' opGE
%left '@' opCAT opSTREQ opSTRNE
%left opSHL opSHR
%left '+' '-'
%left '*' '/' '%'
%right '!' '~' opPLUSPLUS opMINUSMINUS UNARY
%left '.'
%%
start
: decl_list
{ }
;
decl_list
:
{ $$ = nil; }
| decl_list decl
{ if(!statementList) { statementList = $2; } else { statementList->append($2); } }
;
decl
: stmt
{ $$ = $1; }
| fn_decl_stmt
{ $$ = $1; }
| package_decl
{ $$ = $1; }
;
package_decl
: rwPACKAGE IDENT '{' fn_decl_list '}' ';'
{ $$ = $4; for(StmtNode *walk = ($4);walk;walk = walk->getNext() ) walk->setPackage($2); }
;
fn_decl_list
: fn_decl_stmt
{ $$ = $1; }
| fn_decl_list fn_decl_stmt
{ $$ = $1; ($1)->append($2); }
;
statement_list
:
{ $$ = nil; }
| statement_list stmt
{ if(!$1) { $$ = $2; } else { ($1)->append($2); $$ = $1; } }
;
stmt
: if_stmt
| while_stmt
| for_stmt
| datablock_decl
| switch_stmt
| rwBREAK ';'
{ $$ = BreakStmtNode::alloc(); }
| rwCONTINUE ';'
{ $$ = ContinueStmtNode::alloc(); }
| rwRETURN ';'
{ $$ = ReturnStmtNode::alloc(NULL); }
| rwRETURN expr ';'
{ $$ = ReturnStmtNode::alloc($2); }
| expression_stmt ';'
{ $$ = $1; }
| TTAG '=' expr ';'
{ $$ = TTagSetStmtNode::alloc($1, $3, NULL); }
| TTAG '=' expr ',' expr ';'
{ $$ = TTagSetStmtNode::alloc($1, $3, $5); }
;
fn_decl_stmt
: rwDEFINE IDENT '(' var_list_decl ')' '{' statement_list '}'
{ $$ = FunctionDeclStmtNode::alloc($2, NULL, $4, $7); }
| rwDEFINE IDENT opCOLONCOLON IDENT '(' var_list_decl ')' '{' statement_list '}'
{ $$ = FunctionDeclStmtNode::alloc($4, $2, $6, $9); }
;
var_list_decl
:
{ $$ = NULL; }
| var_list
{ $$ = $1; }
;
var_list
: VAR
{ $$ = VarNode::alloc($1, NULL); }
| var_list ',' VAR
{ $$ = $1; ((StmtNode*)($1))->append((StmtNode*)VarNode::alloc($3, NULL)); }
;
datablock_decl
: rwDATABLOCK IDENT '(' IDENT ')' '{' slot_assign_list '}' ';'
{ $$ = ObjectDeclNode::alloc(ConstantNode::alloc($2), ConstantNode::alloc($4), NULL, NULL, $7, NULL, true); }
| rwDATABLOCK IDENT '(' IDENT ')' ':' IDENT '{' slot_assign_list '}' ';'
{ $$ = ObjectDeclNode::alloc(ConstantNode::alloc($2), ConstantNode::alloc($4), NULL, $7, $9, NULL, true); }
;
object_decl
: rwDECLARE class_name_expr '(' object_name object_args ')' '{' object_declare_block '}'
{ $$ = ObjectDeclNode::alloc($2, $4, $5, NULL, $8.slots, $8.decls, false); }
| rwDECLARE class_name_expr '(' object_name object_args ')'
{ $$ = ObjectDeclNode::alloc($2, $4, $5, NULL, NULL, NULL, false); }
;
object_name
:
{ $$ = StrConstNode::alloc("", false); }
| expr
{ $$ = $1; }
;
object_args
:
{ $$ = NULL; }
| ',' expr_list
{ $$ = $2; }
;
object_declare_block
:
{ $$.slots = NULL; $$.decls = NULL; }
| slot_assign_list
{ $$.slots = $1; $$.decls = NULL; }
| object_decl_list
{ $$.slots = NULL; $$.decls = $1; }
| slot_assign_list object_decl_list
{ $$.slots = $1; $$.decls = $2; }
;
object_decl_list
: object_decl ';'
{ $$ = $1; }
| object_decl_list object_decl ';'
{ $1->append($2); $$ = $1; }
;
stmt_block
: '{' statement_list '}'
{ $$ = $2; }
| stmt
{ $$ = $1; }
;
switch_stmt
: rwSWITCH '(' expr ')' '{' case_block '}'
{ $$ = $6; $6->propagateSwitchExpr($3, false); }
| rwSWITCHSTR '(' expr ')' '{' case_block '}'
{ $$ = $6; $6->propagateSwitchExpr($3, true); }
;
case_block
: rwCASE case_expr ':' statement_list
{ $$ = IfStmtNode::alloc($1, $2, $4, NULL, false); }
| rwCASE case_expr ':' statement_list rwDEFAULT ':' statement_list
{ $$ = IfStmtNode::alloc($1, $2, $4, $7, false); }
| rwCASE case_expr ':' statement_list case_block
{ $$ = IfStmtNode::alloc($1, $2, $4, $5, true); }
;
case_expr
: expr
{ $$ = $1;}
| case_expr rwCASEOR expr
{ ($1)->append($3); $$=$1; }
;
if_stmt
: rwIF '(' expr ')' stmt_block
{ $$ = IfStmtNode::alloc($1, $3, $5, NULL, false); }
| rwIF '(' expr ')' stmt_block rwELSE stmt_block
{ $$ = IfStmtNode::alloc($1, $3, $5, $7, false); }
;
while_stmt
: rwWHILE '(' expr ')' stmt_block
{ $$ = LoopStmtNode::alloc($1, nil, $3, nil, $5, false); }
;
for_stmt
: rwFOR '(' expr ';' expr ';' expr ')' stmt_block
{ $$ = LoopStmtNode::alloc($1, $3, $5, $7, $9, false); }
;
expression_stmt
: stmt_expr
{ $$ = $1; }
;
expr
: stmt_expr
{ $$ = $1; }
| '(' expr ')'
{ $$ = $2; }
| expr '^' expr
{ $$ = IntBinaryExprNode::alloc($2, $1, $3); }
| expr '%' expr
{ $$ = IntBinaryExprNode::alloc($2, $1, $3); }
| expr '&' expr
{ $$ = IntBinaryExprNode::alloc($2, $1, $3); }
| expr '|' expr
{ $$ = IntBinaryExprNode::alloc($2, $1, $3); }
| expr '+' expr
{ $$ = FloatBinaryExprNode::alloc($2, $1, $3); }
| expr '-' expr
{ $$ = FloatBinaryExprNode::alloc($2, $1, $3); }
| expr '*' expr
{ $$ = FloatBinaryExprNode::alloc($2, $1, $3); }
| expr '/' expr
{ $$ = FloatBinaryExprNode::alloc($2, $1, $3); }
| '-' expr %prec UNARY
{ $$ = FloatUnaryExprNode::alloc($1, $2); }
| '*' expr %prec UNARY
{ $$ = TTagDerefNode::alloc($2); }
| TTAG
{ $$ = TTagExprNode::alloc($1); }
| expr '?' expr ':' expr
{ $$ = ConditionalExprNode::alloc($1, $3, $5); }
| expr '<' expr
{ $$ = IntBinaryExprNode::alloc($2, $1, $3); }
| expr '>' expr
{ $$ = IntBinaryExprNode::alloc($2, $1, $3); }
| expr opGE expr
{ $$ = IntBinaryExprNode::alloc($2, $1, $3); }
| expr opLE expr
{ $$ = IntBinaryExprNode::alloc($2, $1, $3); }
| expr opEQ expr
{ $$ = IntBinaryExprNode::alloc($2, $1, $3); }
| expr opNE expr
{ $$ = IntBinaryExprNode::alloc($2, $1, $3); }
| expr opOR expr
{ $$ = IntBinaryExprNode::alloc($2, $1, $3); }
| expr opSHL expr
{ $$ = IntBinaryExprNode::alloc($2, $1, $3); }
| expr opSHR expr
{ $$ = IntBinaryExprNode::alloc($2, $1, $3); }
| expr opAND expr
{ $$ = IntBinaryExprNode::alloc($2, $1, $3); }
| expr opSTREQ expr
{ $$ = StreqExprNode::alloc($1, $3, true); }
| expr opSTRNE expr
{ $$ = StreqExprNode::alloc($1, $3, false); }
| expr '@' expr
{ $$ = StrcatExprNode::alloc($1, $3, $2); }
| '!' expr
{ $$ = IntUnaryExprNode::alloc($1, $2); }
| '~' expr
{ $$ = IntUnaryExprNode::alloc($1, $2); }
| TAGATOM
{ $$ = StrConstNode::alloc($1, true); }
| FLTCONST
{ $$ = FloatNode::alloc($1); }
| INTCONST
{ $$ = IntNode::alloc($1); }
| rwBREAK
{ $$ = ConstantNode::alloc(StringTable->insert("break")); }
| slot_acc
{ $$ = SlotAccessNode::alloc($1.object, $1.array, $1.slotName); }
| IDENT
{ $$ = ConstantNode::alloc($1); }
| STRATOM
{ $$ = StrConstNode::alloc($1, false); }
| VAR
{ $$ = (ExprNode*)VarNode::alloc($1, NULL); }
| VAR '[' aidx_expr ']'
{ $$ = (ExprNode*)VarNode::alloc($1, $3); }
;
slot_acc
: expr '.' IDENT
{ $$.object = $1; $$.slotName = $3; $$.array = NULL; }
| expr '.' IDENT '[' aidx_expr ']'
{ $$.object = $1; $$.slotName = $3; $$.array = $5; }
;
class_name_expr
: IDENT
{ $$ = ConstantNode::alloc($1); }
| '(' expr ')'
{ $$ = $2; }
;
assign_op_struct
: opPLUSPLUS
{ $$.token = '+'; $$.expr = FloatNode::alloc(1); }
| opMINUSMINUS
{ $$.token = '-'; $$.expr = FloatNode::alloc(1); }
| opPLASN expr
{ $$.token = '+'; $$.expr = $2; }
| opMIASN expr
{ $$.token = '-'; $$.expr = $2; }
| opMLASN expr
{ $$.token = '*'; $$.expr = $2; }
| opDVASN expr
{ $$.token = '/'; $$.expr = $2; }
| opMODASN expr
{ $$.token = '%'; $$.expr = $2; }
| opANDASN expr
{ $$.token = '&'; $$.expr = $2; }
| opXORASN expr
{ $$.token = '^'; $$.expr = $2; }
| opORASN expr
{ $$.token = '|'; $$.expr = $2; }
| opSLASN expr
{ $$.token = opSHL; $$.expr = $2; }
| opSRASN expr
{ $$.token = opSHR; $$.expr = $2; }
;
stmt_expr
: funcall_expr
{ $$ = $1; }
| object_decl
{ $$ = $1; }
| VAR '=' expr
{ $$ = AssignExprNode::alloc($1, NULL, $3); }
| VAR '[' aidx_expr ']' '=' expr
{ $$ = AssignExprNode::alloc($1, $3, $6); }
| VAR assign_op_struct
{ $$ = AssignOpExprNode::alloc($1, NULL, $2.expr, $2.token); }
| VAR '[' aidx_expr ']' assign_op_struct
{ $$ = AssignOpExprNode::alloc($1, $3, $5.expr, $5.token); }
| slot_acc assign_op_struct
{ $$ = SlotAssignOpNode::alloc($1.object, $1.slotName, $1.array, $2.token, $2.expr); }
| slot_acc '=' expr
{ $$ = SlotAssignNode::alloc($1.object, $1.array, $1.slotName, $3); }
| slot_acc '=' '{' expr_list '}'
{ $$ = SlotAssignNode::alloc($1.object, $1.array, $1.slotName, $4); }
;
funcall_expr
: IDENT '(' expr_list_decl ')'
{ $$ = FuncCallExprNode::alloc($1, NULL, $3, false); }
| IDENT opCOLONCOLON IDENT '(' expr_list_decl ')'
{ $$ = FuncCallExprNode::alloc($3, $1, $5, false); }
| expr '.' IDENT '(' expr_list_decl ')'
{ $1->append($5); $$ = FuncCallExprNode::alloc($3, NULL, $1, true); }
;
expr_list_decl
:
{ $$ = NULL; }
| expr_list
{ $$ = $1; }
;
expr_list
: expr
{ $$ = $1; }
| expr_list ',' expr
{ ($1)->append($3); $$ = $1; }
;
slot_assign_list
: slot_assign
{ $$ = $1; }
| slot_assign_list slot_assign
{ $1->append($2); $$ = $1; }
;
slot_assign
: IDENT '=' expr ';'
{ $$ = SlotAssignNode::alloc(NULL, NULL, $1, $3); }
| rwDATABLOCK '=' expr ';'
{ $$ = SlotAssignNode::alloc(NULL, NULL, StringTable->insert("datablock"), $3); }
| IDENT '[' aidx_expr ']' '=' expr ';'
{ $$ = SlotAssignNode::alloc(NULL, $3, $1, $6); }
;
aidx_expr
: expr
{ $$ = $1; }
| aidx_expr ',' expr
{ $$ = CommaCatExprNode::alloc($1, $3); }
;
%%

79
console/objectTypes.h Normal file
View file

@ -0,0 +1,79 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _OBJECTTYPES_H_
#define _OBJECTTYPES_H_
// Types used for SimObject type masks (SimObject::mTypeMask)
//
/* NB! If a new object type is added, don't forget to add it to the
* consoleInit function in simBase.cc
*/
// SimObjectTypes
// Types used by the SceneObject class
#define DefaultObjectType 0
#define StaticObjectType (1<<0)
// Basic Engine Types
#define EnvironmentObjectType (1<<1)
#define TerrainObjectType (1<<2)
#define InteriorObjectType (1<<3)
#define WaterObjectType (1<<4)
#define TriggerObjectType (1<<5)
#define MarkerObjectType (1<<6)
#define PathedObjectType (1<<7)
#define ForceFieldObjectType (1<<8)
#define DecalManagerObjectType (1<<9)
#define PlayerObjectType (1<<14)
#define GuiControlObjectType (1<<25)
#define StaticRenderedObjectType (1<<26)
// Game Types
#define GameBaseObjectType (1<<10)
#define ShapeBaseObjectType (1<<11)
#define CameraObjectType (1<<12)
#define StaticShapeObjectType (1<<13)
#define ItemObjectType (1<<15)
#define VehicleObjectType (1<<16)
#define MoveableObjectType (1<<17)
#define ProjectileObjectType (1<<18)
#define ExplosionObjectType (1<<19)
#define CorpseObjectType (1<<20)
#define TurretObjectType (1<<21)
#define DebrisObjectType (1<<22)
#define PhysicalZoneObjectType (1<<23)
#define StaticTSObjectType (1<<24)
// The following are allowed types that can be set on datablocks for static shapes
//
#define DamagableItemObjectType (1<<27)
#define SensorObjectType (1<<28)
#define StationObjectType (1<<29)
#define GeneratorObjectType (1<<30)
#define STATIC_COLLISION_MASK ( TerrainObjectType | \
InteriorObjectType | \
ForceFieldObjectType | \
StaticObjectType ) \
#define DAMAGEABLE_MASK ( PlayerObjectType | \
VehicleObjectType | \
MoveableObjectType | \
StationObjectType | \
GeneratorObjectType | \
SensorObjectType | \
PathedObjectType | \
DamagableItemObjectType | \
TurretObjectType ) \
#endif

1560
console/scan.cc Normal file

File diff suppressed because it is too large Load diff

405
console/scan.l Normal file
View file

@ -0,0 +1,405 @@
%{
#define YYLMAX 4096
#include "platform.h"
#include "console.h"
#include "ast.h"
#include "gram.h"
#include "stringTable.h"
static int Sc_ScanString(int ret);
static int Sc_ScanNum();
static int Sc_ScanVar();
static int Sc_ScanHex();
#define FLEX_DEBUG 1
//#undef input
//#undef unput
#undef CMDgetc
int CMDgetc();
static int lineIndex;
extern DataChunker consoleAllocator;
// Prototypes
void SetScanBuffer(const char *sb, const char *fn);
const char * CMDgetFileLine(int &lineNumber);
void CMDerror(char * s, ...);
%}
DIGIT [0-9]
INTEGER {DIGIT}+
FLOAT ({INTEGER}\.{INTEGER})|({INTEGER}(\.{INTEGER})?[eE][+-]?{INTEGER})
LETTER [A-Za-z_]
FILECHAR [A-Za-z_\.]
VARMID [:A-Za-z0-9_]
IDTAIL [A-Za-z0-9_]
VARTAIL {VARMID}*{IDTAIL}
VAR [$%]{LETTER}{VARTAIL}*
ID {LETTER}{IDTAIL}*
ILID [$%]{DIGIT}+{LETTER}{VARTAIL}*
FILENAME {FILECHAR}+
SPACE [ \t\v\f]
HEXDIGIT [a-fA-F0-9]
%%
;
{SPACE}+ { }
"//"[^\n\r]* ;
[\r] ;
[\n] {lineIndex++;}
\"(\\.|[^\\"\n\r])*\" { return(Sc_ScanString(STRATOM)); }
\'(\\.|[^\\'\n\r])*\' { return(Sc_ScanString(TAGATOM)); }
"==" return(CMDlval.i = opEQ);
"!=" return(CMDlval.i = opNE);
">=" return(CMDlval.i = opGE);
"<=" return(CMDlval.i = opLE);
"&&" return(CMDlval.i = opAND);
"||" return(CMDlval.i = opOR);
"::" return(CMDlval.i = opCOLONCOLON);
"--" return(CMDlval.i = opMINUSMINUS);
"++" return(CMDlval.i = opPLUSPLUS);
"$=" return(CMDlval.i = opSTREQ);
"!$=" return(CMDlval.i = opSTRNE);
"<<" return(CMDlval.i = opSHL);
">>" return(CMDlval.i = opSHR);
"+=" return(CMDlval.i = opPLASN);
"-=" return(CMDlval.i = opMIASN);
"*=" return(CMDlval.i = opMLASN);
"/=" return(CMDlval.i = opDVASN);
"%=" return(CMDlval.i = opMODASN);
"&=" return(CMDlval.i = opANDASN);
"^=" return(CMDlval.i = opXORASN);
"|=" return(CMDlval.i = opORASN);
"<<=" return(CMDlval.i = opSLASN);
">>=" return(CMDlval.i = opSRASN);
"NL" {CMDlval.i = '\n'; return '@'; }
"TAB" {CMDlval.i = '\t'; return '@'; }
"SPC" {CMDlval.i = ' '; return '@'; }
"@" {CMDlval.i = 0; return '@'; }
"?" |
"[" |
"]" |
"(" |
")" |
"+" |
"-" |
"*" |
"/" |
"<" |
">" |
"|" |
"." |
"!" |
":" |
";" |
"{" |
"}" |
"," |
"&" |
"%" |
"^" |
"~" |
"=" { return(CMDlval.i = CMDtext[0]); }
"or" { CMDlval.i = lineIndex; return(rwCASEOR); }
"break" { CMDlval.i = lineIndex; return(rwBREAK); }
"return" { CMDlval.i = lineIndex; return(rwRETURN); }
"else" { CMDlval.i = lineIndex; return(rwELSE); }
"while" { CMDlval.i = lineIndex; return(rwWHILE); }
"if" { CMDlval.i = lineIndex; return(rwIF); }
"for" { CMDlval.i = lineIndex; return(rwFOR); }
"continue" { CMDlval.i = lineIndex; return(rwCONTINUE); }
"function" { CMDlval.i = lineIndex; return(rwDEFINE); }
"new" { CMDlval.i = lineIndex; return(rwDECLARE); }
"datablock" { CMDlval.i = lineIndex; return(rwDATABLOCK); }
"case" { CMDlval.i = lineIndex; return(rwCASE); }
"switch$" { CMDlval.i = lineIndex; return(rwSWITCHSTR); }
"switch" { CMDlval.i = lineIndex; return(rwSWITCH); }
"default" { CMDlval.i = lineIndex; return(rwDEFAULT); }
"package" { CMDlval.i = lineIndex; return(rwPACKAGE); }
"true" { CMDlval.i = 1; return INTCONST; }
"false" { CMDlval.i = 0; return INTCONST; }
{VAR} return(Sc_ScanVar());
{ID} { CMDtext[CMDleng] = 0; CMDlval.s = StringTable->insert(CMDtext); return(IDENT); }
0[xX]{HEXDIGIT}+ return(Sc_ScanHex());
{INTEGER} { CMDtext[CMDleng] = 0; CMDlval.i = atoi(CMDtext); return INTCONST; }
{FLOAT} return Sc_ScanNum();
{ILID} return(ILLEGAL_TOKEN);
. return(ILLEGAL_TOKEN);
%%
/*
* Scan character constant.
*/
/*
* Scan identifier.
*/
static const char *scanBuffer;
static const char *fileName;
static int scanIndex;
const char * CMDGetCurrentFile()
{
return fileName;
}
int CMDGetCurrentLine()
{
return lineIndex;
}
extern bool gConsoleSyntaxError;
void CMDerror(char *, ...)
{
gConsoleSyntaxError = true;
if(fileName)
Con::errorf(ConsoleLogEntry::Script, "%s Line: %d - Syntax error.",
fileName, lineIndex);
else
Con::errorf(ConsoleLogEntry::Script, "Syntax error in input.");
}
void SetScanBuffer(const char *sb, const char *fn)
{
scanBuffer = sb;
fileName = fn;
scanIndex = 0;
lineIndex = 1;
}
int CMDgetc()
{
int ret = scanBuffer[scanIndex];
if(ret)
scanIndex++;
else
ret = -1;
return ret;
}
int CMDwrap()
{
return 1;
}
static int Sc_ScanVar()
{
CMDtext[CMDleng] = 0;
CMDlval.s = StringTable->insert(CMDtext);
return(VAR);
}
/*
* Scan string constant.
*/
static int charConv(int in)
{
switch(in)
{
case 'r':
return '\r';
case 'n':
return '\n';
case 't':
return '\t';
default:
return in;
}
}
static int getHexDigit(char c)
{
if(c >= '0' && c <= '9')
return c - '0';
if(c >= 'A' && c <= 'F')
return c - 'A' + 10;
if(c >= 'a' && c <= 'f')
return c - 'a' + 10;
return -1;
}
static int Sc_ScanString(int ret)
{
CMDtext[CMDleng - 1] = 0;
if(!collapseEscape(CMDtext+1))
return -1;
CMDlval.str = (char *) consoleAllocator.alloc(dStrlen(CMDtext));
dStrcpy(CMDlval.str, CMDtext + 1);
return(ret);
}
void expandEscape(char *dest, const char *src)
{
unsigned char c;
while((c = (unsigned char) *src++) != 0)
{
if(c == '\"')
{
*dest++ = '\\';
*dest++ = '\"';
}
else if(c == '\\')
{
*dest++ = '\\';
*dest++ = '\\';
}
else if(c == '\r')
{
*dest++ = '\\';
*dest++ = 'r';
}
else if(c == '\n')
{
*dest++ = '\\';
*dest++ = 'n';
}
else if(c == '\t')
{
*dest++ = '\\';
*dest++ = 't';
}
else if(c == '\'')
{
*dest++ = '\\';
*dest++ = '\'';
}
else if((c >= 2 && c <= 8) ||
(c >= 11 && c <= 12) ||
(c >= 14 && c <= 15))
{
/* Remap around: \t = 0x9, \n = 0xa, \r = 0xd */
static char expandRemap[15] = { 0x0,
0x0,
0x0,
0x1,
0x2,
0x3,
0x4,
0x5,
0x6,
0x0,
0x0,
0x7,
0x8,
0x0,
0x9 };
*dest++ = '\\';
*dest++ = 'c';
if(c == 15)
*dest++ = 'r';
else if(c == 16)
*dest++ = 'p';
else if(c == 17)
*dest++ = 'o';
else
*dest++ = expandRemap[c] + '0';
}
else if(c < 32)
{
*dest++ = '\\';
*dest++ = 'x';
S32 dig1 = c >> 4;
S32 dig2 = c & 0xf;
if(dig1 < 10)
dig1 += '0';
else
dig1 += 'A' - 10;
if(dig2 < 10)
dig2 += '0';
else
dig2 += 'A' - 10;
*dest++ = dig1;
*dest++ = dig2;
}
else
*dest++ = c;
}
*dest = '\0';
}
bool collapseEscape(char *buf)
{
int len = dStrlen(buf) + 1;
for(int i = 0; i < len;)
{
if(buf[i] == '\\')
{
if(buf[i+1] == 'x')
{
int dig1 = getHexDigit(buf[i+2]);
if(dig1 == -1)
return false;
int dig2 = getHexDigit(buf[i+3]);
if(dig2 == -1)
return false;
buf[i] = dig1 * 16 + dig2;
dMemmove(buf + i + 1, buf + i + 4, len - i - 3);
len -= 3;
i++;
}
else if(buf[i+1] == 'c')
{
/* Remap around: \t = 0x9, \n = 0xa, \r = 0xd */
static char collapseRemap[10] = { 0x2,
0x3,
0x4,
0x5,
0x6,
0x7,
0x8,
0xb,
0xc,
0xe };
if(buf[i+2] == 'r')
buf[i] = 15;
else if(buf[i+2] == 'p')
buf[i] = 16;
else if(buf[i+2] == 'o')
buf[i] = 17;
else
{
int dig1 = buf[i+2] - '0';
if(dig1 < 0 || dig1 > 9)
return false;
buf[i] = collapseRemap[dig1];
}
dMemmove(buf + i + 1, buf + i + 3, len - i - 2);
len -= 2;
i++;
}
else
{
buf[i] = charConv(buf[i+1]);
dMemmove(buf + i + 1, buf + i + 2, len - i - 1);
len--;
i++;
}
}
else
i++;
}
return true;
}
static int Sc_ScanNum()
{
CMDtext[CMDleng] = 0;
CMDlval.f = atof(CMDtext);
return(FLTCONST);
}
static int Sc_ScanHex()
{
int val = 0;
dSscanf(CMDtext, "%x", &val);
CMDlval.i = val;
return INTCONST;
}

64
console/scriptObject.cc Normal file
View file

@ -0,0 +1,64 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "Platform/platform.h"
#include "console/simBase.h"
#include "console/consoleTypes.h"
class ScriptObject : public SimObject
{
typedef SimObject Parent;
StringTableEntry mClassName;
StringTableEntry mSuperClassName;
public:
ScriptObject();
bool onAdd();
void onRemove();
DECLARE_CONOBJECT(ScriptObject);
static void initPersistFields();
};
IMPLEMENT_CONOBJECT(ScriptObject);
void ScriptObject::initPersistFields()
{
addField("class", TypeString, Offset(mClassName, ScriptObject));
addField("superClass", TypeString, Offset(mSuperClassName, ScriptObject));
}
ScriptObject::ScriptObject()
{
mClassName = "";
mSuperClassName = "";
}
bool ScriptObject::onAdd()
{
if(!Parent::onAdd())
return false;
if(mClassName[0])
{
if(mSuperClassName[0])
{
Con::linkNamespaces(mSuperClassName, mClassName);
Con::linkNamespaces("ScriptObject", mSuperClassName);
}
else
Con::linkNamespaces("ScriptObject", mClassName);
mNameSpace = Con::lookupNamespace(mClassName);
}
return true;
}
void ScriptObject::onRemove()
{
Parent::onRemove();
}

1527
console/simBase.cc Normal file

File diff suppressed because it is too large Load diff

599
console/simBase.h Normal file
View file

@ -0,0 +1,599 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _SIMBASE_H_
#define _SIMBASE_H_
#ifndef _TVECTOR_H_
#include "Core/tVector.h"
#endif
#ifndef _TALGORITHM_H_
#include "Core/tAlgorithm.h"
#endif
#ifndef _BITSET_H_
#include "Core/bitSet.h"
#endif
#ifndef _CONSOLEOBJECT_H_
#include "console/consoleObject.h"
#endif
#ifndef _SIMDICTIONARY_H_
#include "console/simDictionary.h"
#endif
//---------------------------------------------------------------------------
enum
{
DataBlockObjectIdFirst = 3,
DataBlockObjectIdBitSize = 10,
DataBlockObjectIdLast = DataBlockObjectIdFirst + (1 << DataBlockObjectIdBitSize) - 1,
DynamicObjectIdFirst = DataBlockObjectIdLast + 1,
InvalidEventId = 0,
RootGroupId = 0xFFFFFFFF,
};
class SimEvent;
class SimObject;
class SimGroup;
class SimManager;
class Namespace;
class BitStream;
class Stream;
class LightManager;
typedef U32 SimTime;
typedef U32 SimObjectId;
class SimObjectList: public VectorPtr<SimObject*>
{
static S32 QSORT_CALLBACK compareId(const void* a,const void* b);
public:
void pushBack(SimObject*);
void pushBackForce(SimObject*);
void pushFront(SimObject*);
void remove(SimObject*);
void removeStable(SimObject* pObject) { /* remove is stable at the moment */ remove(pObject); }
void sortId();
};
//---------------------------------------------------------------------------
class SimEvent
{
public:
SimEvent *nextEvent;
SimTime time;
U32 sequenceCount;
SimObject *destObject;
SimEvent() { destObject = NULL; }
virtual ~SimEvent() {} // dummy virtual destructor is required
// so that subclasses can be deleted properly
virtual void process(SimObject *object)=0;
};
class SimConsoleEvent : public SimEvent
{
S32 mArgc;
char **mArgv;
bool mOnObject;
public:
SimConsoleEvent(S32 argc, const char **argv, bool onObject);
~SimConsoleEvent();
virtual void process(SimObject *object);
};
//---------------------------------------------------------------------------
class SimFieldDictionary
{
friend class SimFieldDictionaryIterator;
public:
struct Entry
{
StringTableEntry slotName;
char *value;
Entry *next;
};
private:
enum
{
HashTableSize = 19
};
Entry *mHashTable[HashTableSize];
static Entry *mFreeList;
static void freeEntry(Entry *entry);
static Entry *allocEntry();
public:
SimFieldDictionary();
~SimFieldDictionary();
void setFieldValue(StringTableEntry slotName, const char *value);
const char *getFieldValue(StringTableEntry slotName);
void writeFields(SimObject *obj, Stream &strem, U32 tabStop);
void printFields(SimObject *obj);
void assignFrom(SimFieldDictionary *dict);
};
class SimFieldDictionaryIterator
{
SimFieldDictionary * mDictionary;
S32 mHashIndex;
SimFieldDictionary::Entry * mEntry;
public:
SimFieldDictionaryIterator(SimFieldDictionary*);
SimFieldDictionary::Entry* operator++();
SimFieldDictionary::Entry* operator*();
};
//---------------------------------------------------------------------------
class SimObject: public ConsoleObject
{
typedef ConsoleObject Parent;
friend class SimManager;
friend class SimGroup;
friend class SimNameDictionary;
friend class SimManagerNameDictionary;
friend class SimIdDictionary;
//-------------------------------------- Structures and enumerations
private:
enum {
Deleted = 1 << 0,
Removed = 1 << 1,
Added = 1 << 3,
Selected = 1 << 4,
Expanded = 1 << 5,
ModStaticFields = 1 << 6, // can read/modify static fields
ModDynamicFields = 1 << 7 // can read/modify dynamic fields
};
public:
struct Notify {
enum Type {
ClearNotify,
DeleteNotify,
ObjectRef,
Invalid
} type;
void *ptr;
Notify *next;
};
enum WriteFlags {
SelectedOnly = BIT(0)
};
private:
// dictionary information stored on the object
StringTableEntry objectName;
SimObject* nextNameObject;
SimObject* nextManagerNameObject;
SimObject* nextIdObject;
SimGroup* mGroup;
BitSet32 mFlags;
Notify* mNotifyList;
protected:
SimObjectId mId;
Namespace* mNameSpace;
U32 mTypeMask;
protected:
static SimObject::Notify *mNotifyFreeList;
static SimObject::Notify *allocNotify();
static void freeNotify(SimObject::Notify*);
private:
SimFieldDictionary *mFieldDictionary;
public:
const char *getDataField(StringTableEntry slotName, const char *array);
void setDataField(StringTableEntry slotName, const char *array, const char *value);
SimFieldDictionary * getFieldDictionary() {return(mFieldDictionary);}
SimObject();
virtual ~SimObject();
virtual bool processArguments(S32 argc, const char **argv);
virtual bool onAdd();
virtual void onRemove();
virtual void onGroupAdd();
virtual void onGroupRemove();
virtual void onNameChange(const char *name);
virtual void onStaticModified(const char* slotName);
virtual void inspectPreApply();
virtual void inspectPostApply();
virtual void onDeleteNotify(SimObject *object);
virtual void onEditorEnable(){};
virtual void onEditorDisable(){};
virtual SimObject *findObject(const char *name); // find a named sub-object of this object
Notify *removeNotify(void *ptr, Notify::Type);
void deleteNotify(SimObject* obj);
void clearNotify(SimObject* obj);
void clearAllNotifications();
void processDeleteNotifies();
void registerReference(SimObject **obj);
void unregisterReference(SimObject **obj);
bool registerObject();
bool registerObject(U32 id);
bool registerObject(const char *name);
bool registerObject(const char *name, U32 id);
void unregisterObject();
void deleteObject();
SimObjectId getId() const { return mId; }
const char* getIdString();
U32 getType() const { return mTypeMask; }
const char* getName() const { return objectName; };
void setId(SimObjectId id);
void assignName(const char* name);
SimGroup* getGroup() const { return mGroup; }
bool isProperlyAdded() const { return mFlags.test(Added); }
bool isDeleted() const { return mFlags.test(Deleted); }
bool isRemoved() const { return mFlags.test(Deleted | Removed); }
bool isLocked();
void setLocked( bool b );
bool isHidden();
void setHidden(bool b);
bool addToSet(SimObjectId);
bool addToSet(const char *);
bool removeFromSet(SimObjectId);
bool removeFromSet(const char *);
virtual void write(Stream &stream, U32 tabStop, U32 flags = 0);
void writeFields(Stream &stream, U32 tabStop);
void assignFieldsFrom(SimObject *obj);
Namespace* getNamespace() { return mNameSpace; }
const char *tabComplete(const char *prevText, S32 baseLen, bool);
bool isSelected() const { return mFlags.test(Selected); }
bool isExpanded() const { return mFlags.test(Expanded); }
void setSelected(bool sel) { if(sel) mFlags.set(Selected); else mFlags.clear(Selected); }
void setExpanded(bool exp) { if(exp) mFlags.set(Expanded); else mFlags.clear(Expanded); }
void setModDynamicFields(bool dyn) { if(dyn) mFlags.set(ModDynamicFields); else mFlags.clear(ModDynamicFields); }
void setModStaticFields(bool sta) { if(sta) mFlags.set(ModStaticFields); else mFlags.clear(ModStaticFields); }
virtual void registerLights(LightManager *, bool) {};
static void consoleInit();
DECLARE_CONOBJECT(SimObject);
};
//---------------------------------------------------------------------------
template <class T> class SimObjectPtr
{
private:
SimObject *mObj;
public:
SimObjectPtr() { mObj = 0; }
SimObjectPtr(T* ptr)
{
mObj = ptr;
if(mObj)
mObj->registerReference(&mObj);
}
SimObjectPtr(const SimObjectPtr<T>& rhs)
{
mObj = const_cast<T*>(static_cast<const T*>(rhs));
if(mObj)
mObj->registerReference(&mObj);
}
SimObjectPtr<T>& operator=(const SimObjectPtr<T>& rhs)
{
if(this == &rhs)
return(*this);
if(mObj)
mObj->unregisterReference(&mObj);
mObj = const_cast<T*>(static_cast<const T*>(rhs));
if(mObj)
mObj->registerReference(&mObj);
return(*this);
}
~SimObjectPtr()
{
if(mObj)
mObj->unregisterReference(&mObj);
}
SimObjectPtr<T>& operator= (T *ptr)
{
if(mObj != (SimObject *) ptr)
{
if(mObj)
mObj->unregisterReference(&mObj);
mObj = (SimObject *) ptr;
if (mObj)
mObj->registerReference(&mObj);
}
return *this;
}
operator bool() const { return mObj != 0; }
bool isNull() const { return mObj == 0; }
T* operator->() { return static_cast<T*>(mObj); }
T& operator*() { return *static_cast<T*>(mObj); }
operator T*() { return static_cast<T*>(mObj)? static_cast<T*>(mObj) : 0; }
const T* operator->() const { return static_cast<const T*>(mObj); }
const T& operator*() const { return *static_cast<const T*>(mObj); }
operator const T*() const { return static_cast<T*>(mObj) ? static_cast<const T*>(mObj) : 0; }
};
//---------------------------------------------------------------------------
class SimDataBlock: public SimObject
{
typedef SimObject Parent;
protected:
S32 modifiedKey;
public:
static SimObjectId sNextObjectId;
static S32 sNextModifiedKey;
SimDataBlock();
DECLARE_CONOBJECT(SimDataBlock);
static S32 getNextModifiedKey() { return sNextModifiedKey; }
S32 getModifiedKey() const { return modifiedKey; }
bool onAdd();
void onStaticModified(const char* slotName);
void setLastError(const char*);
void assignId();
virtual bool preload(bool server, char errorBuffer[256]);
//
virtual void packData(BitStream* stream);
virtual void unpackData(BitStream* stream);
};
//---------------------------------------------------------------------------
class SimSet: public SimObject
{
typedef SimObject Parent;
protected:
SimObjectList objectList;
public:
SimSet() {
VECTOR_SET_ASSOCIATION(objectList);
}
typedef SimObjectList::iterator iterator;
typedef SimObjectList::value_type value;
SimObject* front() { return objectList.front(); }
SimObject* first() { return objectList.first(); }
SimObject* last() { return objectList.last(); }
bool empty() { return objectList.empty(); }
S32 size() { return objectList.size(); }
iterator begin() { return objectList.begin(); }
iterator end() { return objectList.end(); }
value operator[] (S32 index) { return objectList[U32(index)]; }
iterator find( iterator first, iterator last, SimObject *obj)
{ return ::find(first, last, obj); }
bool reOrder( SimObject *obj, SimObject *target=0 );
virtual void onRemove();
virtual void onDeleteNotify(SimObject *object);
virtual void addObject(SimObject*);
virtual void removeObject(SimObject*);
virtual void pushObject(SimObject*);
virtual void popObject();
void bringObjectToFront(SimObject* obj) { reOrder(obj, front()); }
void pushObjectToBack(SimObject* obj) { reOrder(obj, NULL); }
void write(Stream &stream, U32 tabStop, U32 flags = 0);
virtual SimObject *findObject(const char *name); // find a named sub-object of this object
DECLARE_CONOBJECT(SimSet);
};
class SimSetIterator
{
struct Entry {
SimSet* set;
SimSet::iterator itr;
};
class Stack: public Vector<Entry> {
public:
void push_back(SimSet*);
};
Stack stack;
public:
SimSetIterator(SimSet*);
SimObject* operator++();
SimObject* operator*() {
return stack.empty()? 0: *stack.last().itr;
}
};
//---------------------------------------------------------------------------
class SimGroup: public SimSet
{
private:
friend class SimManager;
friend class SimObject;
typedef SimSet Parent;
SimNameDictionary nameDictionary;
public:
~SimGroup();
void addObject(SimObject*);
void addObject(SimObject*, SimObjectId);
void addObject(SimObject*, const char *name);
void removeObject(SimObject*);
void onRemove();
virtual SimObject* findObject(const char* name);
bool processArguments(S32 argc, const char **argv);
DECLARE_CONOBJECT(SimGroup);
};
inline void SimGroup::addObject(SimObject* obj, SimObjectId id)
{
// AddObject will assign it whatever id it already has.
// This should normally be done only with reserved id's.
obj->mId = id;
addObject( obj );
}
inline void SimGroup::addObject(SimObject *obj, const char *name)
{
addObject( obj );
obj->assignName(name);
}
//---------------------------------------------------------------------------
class SimDataBlockGroup : public SimGroup
{
private:
S32 mLastModifiedKey;
public:
static S32 QSORT_CALLBACK compareModifiedKey(const void* a,const void* b);
void sort();
SimDataBlockGroup();
};
//---------------------------------------------------------------------------
// helper macros for named sets and groups in the manager:
#define DeclareNamedSet(set) extern SimSet *g##set;inline SimSet *get##set() { return g##set; }
#define DeclareNamedGroup(set) extern SimGroup *g##set;inline SimGroup *get##set() { return g##set; }
#define ImplementNamedSet(set) SimSet *g##set;
#define ImplementNamedGroup(set) SimGroup *g##set;
//---------------------------------------------------------------------------
namespace Sim
{
DeclareNamedSet(ActiveActionMapSet)
DeclareNamedSet(GhostAlwaysSet)
DeclareNamedSet(LightSet)
DeclareNamedSet(WayPointSet)
DeclareNamedSet(ClientTargetSet)
DeclareNamedSet(ServerTargetSet)
DeclareNamedSet(FlareSet)
DeclareNamedSet(MissileSet)
DeclareNamedSet(CommandTargetSet)
DeclareNamedSet(ScopeSensorVisibleSet)
DeclareNamedGroup(ActionMapGroup)
DeclareNamedGroup(ClientGroup)
DeclareNamedGroup(GuiGroup)
DeclareNamedGroup(GuiDataGroup)
DeclareNamedGroup(TCPGroup)
DeclareNamedGroup(ClientConnectionGroup)
void init();
void shutdown();
SimDataBlockGroup *getDataBlockGroup();
SimGroup* getRootGroup();
SimObject* findObject(SimObjectId);
SimObject* findObject(const char* name);
template<class T> inline bool findObject(SimObjectId id,T*&t)
{
t = dynamic_cast<T*>(findObject(id));
return t != NULL;
}
template<class T> inline bool findObject(const char *objectName,T*&t)
{
t = dynamic_cast<T*>(findObject(objectName));
return t != NULL;
}
void advanceToTime(SimTime time);
void advanceTime(SimTime delta);
SimTime getCurrentTime();
SimTime getTargetTime();
// a target time of 0 on an event means current event
U32 postEvent(SimObject*, SimEvent*, U32 targetTime);
inline U32 postEvent(SimObjectId id,SimEvent*evt, U32 targetTime)
{
return postEvent(findObject(id), evt, targetTime);
}
inline U32 postEvent(const char *objectName,SimEvent*evt, U32 targetTime)
{
return postEvent(findObject(objectName), evt, targetTime);
}
inline U32 postCurrentEvent(SimObject*obj, SimEvent*evt)
{
return postEvent(obj,evt,getCurrentTime());
}
inline U32 postCurrentEvent(SimObjectId obj,SimEvent*evt)
{
return postEvent(obj,evt,getCurrentTime());
}
inline U32 postCurrentEvent(const char *obj,SimEvent*evt)
{
return postEvent(obj,evt,getCurrentTime());
}
void cancelEvent(U32 eventId);
bool isEventPending(U32 eventId);
}
//----------------------------------------------------------------------------
#define IMPLEMENT_SETDATATYPE(T) \
void setDataTypeDataBlockPtr##T(void *dptr, S32 argc, const char **argv, EnumTable *, BitSet32) \
{ \
volatile SimDataBlock* pConstraint = static_cast<SimDataBlock*>((T*)NULL); \
\
if (argc == 1) { \
*reinterpret_cast<T**>(dptr) = NULL; \
if (argv[0] && argv[0][0] && !Sim::findObject(argv[0],*reinterpret_cast<T**>(dptr))) \
Con::printf("Object \"%s\" is not a member of the expected data block class", argv[0]); \
} \
else \
Con::printf("Cannot set multiple args to a single pointer."); \
}
#define IMPLEMENT_GETDATATYPE(T) \
const char* getDataTypeDataBlockPtr##T(void *dptr, EnumTable *, BitSet32) \
{ \
volatile SimDataBlock* pConstraint = static_cast<SimDataBlock*>((T*)NULL); \
\
T** obj = reinterpret_cast<T**>(dptr); \
return *obj ? (*obj)->getName() : ""; \
}
#define REF_SETDATATYPE(T) setDataTypeDataBlockPtr##T
#define REF_GETDATATYPE(T) getDataTypeDataBlockPtr##T
//---------------------------------------------------------------------------
#endif

247
console/simDictionary.cc Normal file
View file

@ -0,0 +1,247 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "console/simDictionary.h"
#include "console/simBase.h"
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
extern S32 HashPointer(StringTableEntry e);
SimNameDictionary::SimNameDictionary()
{
hashTable = NULL;
}
SimNameDictionary::~SimNameDictionary()
{
delete[] hashTable;
}
void SimNameDictionary::insert(SimObject* obj)
{
if(!obj->objectName)
return;
if(!hashTable)
{
hashTable = new SimObject *[DefaultTableSize];
hashTableSize = DefaultTableSize;
hashEntryCount = 0;
S32 i;
for(i = 0; i < hashTableSize; i++)
hashTable[i] = NULL;
}
S32 idx = HashPointer(obj->objectName) % hashTableSize;
obj->nextNameObject = hashTable[idx];
hashTable[idx] = obj;
hashEntryCount++;
if(hashEntryCount > hashTableSize)
{
// resize the hash table
S32 i;
SimObject *head = NULL, *walk, *temp;
for(i = 0; i < hashTableSize; i++) {
walk = hashTable[i];
while(walk)
{
temp = walk->nextNameObject;
walk->nextNameObject = head;
head = walk;
walk = temp;
}
}
delete[] hashTable;
hashTableSize = hashTableSize * 2 + 1;
hashTable = new SimObject *[hashTableSize];
for(i = 0; i < hashTableSize;i++)
hashTable[i] = NULL;
while(head)
{
temp = head->nextNameObject;
idx = HashPointer(head->objectName) % hashTableSize;
head->nextNameObject = hashTable[idx];
hashTable[idx] = head;
head = temp;
}
}
}
SimObject* SimNameDictionary::find(StringTableEntry name)
{
// NULL is a valid lookup - it will always return NULL
if(!hashTable)
return NULL;
S32 idx = HashPointer(name) % hashTableSize;
SimObject *walk = hashTable[idx];
while(walk)
{
if(walk->objectName == name)
return walk;
walk = walk->nextNameObject;
}
return NULL;
}
void SimNameDictionary::remove(SimObject* obj)
{
if(!obj->objectName)
return;
SimObject **walk = &hashTable[HashPointer(obj->objectName) % hashTableSize];
while(*walk)
{
if(*walk == obj)
{
*walk = obj->nextNameObject;
obj->nextNameObject = (SimObject*)-1;
hashEntryCount--;
return;
}
walk = &((*walk)->nextNameObject);
}
}
//----------------------------------------------------------------------------
SimManagerNameDictionary::SimManagerNameDictionary()
{
hashTable = new SimObject *[DefaultTableSize];
hashTableSize = DefaultTableSize;
hashEntryCount = 0;
S32 i;
for(i = 0; i < hashTableSize; i++)
hashTable[i] = NULL;
}
SimManagerNameDictionary::~SimManagerNameDictionary()
{
delete[] hashTable;
}
void SimManagerNameDictionary::insert(SimObject* obj)
{
if(!obj->objectName)
return;
S32 idx = HashPointer(obj->objectName) % hashTableSize;
obj->nextManagerNameObject = hashTable[idx];
hashTable[idx] = obj;
hashEntryCount++;
if(hashEntryCount > hashTableSize)
{
// resize the hash table
S32 i;
SimObject *head = NULL, *walk, *temp;
for(i = 0; i < hashTableSize; i++) {
walk = hashTable[i];
while(walk)
{
temp = walk->nextManagerNameObject;
walk->nextManagerNameObject = head;
head = walk;
walk = temp;
}
}
delete[] hashTable;
hashTableSize = hashTableSize * 2 + 1;
hashTable = new SimObject *[hashTableSize];
for(i = 0; i < hashTableSize;i++)
hashTable[i] = NULL;
while(head)
{
temp = head->nextManagerNameObject;
idx = HashPointer(head->objectName) % hashTableSize;
head->nextManagerNameObject = hashTable[idx];
hashTable[idx] = head;
head = temp;
}
}
}
SimObject* SimManagerNameDictionary::find(StringTableEntry name)
{
// NULL is a valid lookup - it will always return NULL
S32 idx = HashPointer(name) % hashTableSize;
SimObject *walk = hashTable[idx];
while(walk)
{
if(walk->objectName == name)
return walk;
walk = walk->nextManagerNameObject;
}
return NULL;
}
void SimManagerNameDictionary::remove(SimObject* obj)
{
if(!obj->objectName)
return;
SimObject **walk = &hashTable[HashPointer(obj->objectName) % hashTableSize];
while(*walk)
{
if(*walk == obj)
{
*walk = obj->nextManagerNameObject;
obj->nextManagerNameObject = (SimObject*)-1;
hashEntryCount--;
return;
}
walk = &((*walk)->nextManagerNameObject);
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
SimIdDictionary::SimIdDictionary()
{
for(S32 i = 0; i < DefaultTableSize; i++)
table[i] = NULL;
}
SimIdDictionary::~SimIdDictionary()
{
}
void SimIdDictionary::insert(SimObject* obj)
{
S32 idx = obj->getId() & TableBitMask;
obj->nextIdObject = table[idx];
table[idx] = obj;
}
SimObject* SimIdDictionary::find(S32 id)
{
S32 idx = id & TableBitMask;
SimObject *walk = table[idx];
while(walk)
{
if(walk->getId() == U32(id))
return walk;
walk = walk->nextIdObject;
}
return NULL;
}
void SimIdDictionary::remove(SimObject* obj)
{
SimObject **walk = &table[obj->getId() & TableBitMask];
while(*walk && *walk != obj)
walk = &((*walk)->nextIdObject);
if(*walk)
*walk = obj->nextIdObject;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

84
console/simDictionary.h Normal file
View file

@ -0,0 +1,84 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _SIMDICTIONARY_H_
#define _SIMDICTIONARY_H_
#ifndef _PLATFORM_H_
#include "Platform/platform.h"
#endif
#ifndef _STRINGTABLE_H_
#include "Core/stringTable.h"
#endif
class SimObject;
//----------------------------------------------------------------------------
// Map of Names to simObjects
// Provides fast lookup for name->object and
// for fast removal of an object given object*
//
class SimNameDictionary
{
enum
{
DefaultTableSize = 29
};
SimObject **hashTable; // hash the pointers of the names...
S32 hashTableSize;
S32 hashEntryCount;
public:
void insert(SimObject* obj);
void remove(SimObject* obj);
SimObject* find(StringTableEntry name);
SimNameDictionary();
~SimNameDictionary();
};
class SimManagerNameDictionary
{
enum
{
DefaultTableSize = 29
};
SimObject **hashTable; // hash the pointers of the names...
S32 hashTableSize;
S32 hashEntryCount;
public:
void insert(SimObject* obj);
void remove(SimObject* obj);
SimObject* find(StringTableEntry name);
SimManagerNameDictionary();
~SimManagerNameDictionary();
};
//----------------------------------------------------------------------------
// Map of ID's to simObjects
// Provides fast lookup for ID->object and
// for fast removal of an object given object*
//
class SimIdDictionary
{
enum
{
DefaultTableSize = 4096,
TableBitMask = 4095
};
SimObject *table[DefaultTableSize];
public:
void insert(SimObject* obj);
void remove(SimObject* obj);
SimObject* find(S32 id);
SimIdDictionary();
~SimIdDictionary();
};
#endif //_SIMDICTIONARY_H_

449
console/simManager.cc Normal file
View file

@ -0,0 +1,449 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "Platform/platform.h"
#include "console/simBase.h"
#include "Core/stringTable.h"
#include "console/console.h"
#include "Core/fileStream.h"
#include "Core/resManager.h"
#include "Core/fileObject.h"
#include "console/consoleInternal.h"
#include "Core/idGenerator.h"
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
namespace Sim
{
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// event queue variables:
SimTime gCurrentTime;
SimTime gTargetTime;
SimEvent *gEventQueue;
U32 gEventSequence;
//---------------------------------------------------------------------------
// event queue init/shutdown
static void initEventQueue()
{
gCurrentTime = 0;
gTargetTime = 0;
gEventSequence = 1;
gEventQueue = NULL;
}
static void shutdownEventQueue()
{
// Delete all pending events
SimEvent *walk = gEventQueue;
while(walk)
{
SimEvent *temp = walk->nextEvent;
delete walk;
walk = temp;
}
}
//---------------------------------------------------------------------------
// event post
U32 postEvent(SimObject *destObject, SimEvent* event,U32 time)
{
AssertFatal(time >= gCurrentTime,
"Sim::postEvent: Cannot go back in time.");
AssertFatal(destObject, "Destination object for event doesn't exist.");
event->time = time;
event->destObject = destObject;
if(!destObject)
{
delete event;
return InvalidEventId;
}
event->sequenceCount = gEventSequence++;
SimEvent **walk = &gEventQueue;
SimEvent *current;
while((current = *walk) != NULL && (current->time < event->time))
walk = &(current->nextEvent);
event->nextEvent = current;
*walk = event;
return event->sequenceCount;
}
//---------------------------------------------------------------------------
// event cancellation
void cancelEvent(U32 eventSequence)
{
SimEvent **walk = &gEventQueue;
SimEvent *current;
while((current = *walk) != NULL)
{
if(current->sequenceCount == eventSequence)
{
*walk = current->nextEvent;
delete current;
return;
}
else
walk = &(current->nextEvent);
}
}
static void cancelPendingEvents(SimObject *obj)
{
SimEvent **walk = &gEventQueue;
SimEvent *current;
while((current = *walk) != NULL)
{
if(current->destObject == obj)
{
*walk = current->nextEvent;
delete current;
}
else
walk = &(current->nextEvent);
}
}
//---------------------------------------------------------------------------
// event pending test
bool isEventPending(U32 eventSequence)
{
for(SimEvent *walk = gEventQueue; walk; walk = walk->nextEvent)
if(walk->sequenceCount == eventSequence)
return true;
return false;
}
//---------------------------------------------------------------------------
// event timing
void advanceToTime(SimTime targetTime)
{
AssertFatal(targetTime >= gCurrentTime, "EventQueue::process: cannot advance to time in the past.");
gTargetTime = targetTime;
while(gEventQueue && gEventQueue->time <= targetTime)
{
SimEvent *event = gEventQueue;
gEventQueue = gEventQueue->nextEvent;
AssertFatal(event->time >= gCurrentTime,
"SimEventQueue::pop: Cannot go back in time.");
gCurrentTime = event->time;
SimObject *obj = event->destObject;
if(!obj->isDeleted())
event->process(obj);
delete event;
}
gCurrentTime = targetTime;
}
void advanceTime(SimTime delta)
{
advanceToTime(gCurrentTime + delta);
}
U32 getCurrentTime()
{
return gCurrentTime;
}
U32 getTargetTime()
{
return gTargetTime;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
SimGroup *gRootGroup = NULL;
SimManagerNameDictionary *gNameDictionary;
SimIdDictionary *gIdDictionary;
U32 gNextObjectId;
static void initRoot()
{
gIdDictionary = new SimIdDictionary;
gNameDictionary = new SimManagerNameDictionary;
gRootGroup = new SimGroup();
gRootGroup->setId(RootGroupId);
gRootGroup->assignName("RootGroup");
gRootGroup->registerObject();
gNextObjectId = DynamicObjectIdFirst;
}
static void shutdownRoot()
{
gRootGroup->deleteObject();
delete gNameDictionary;
delete gIdDictionary;
}
//---------------------------------------------------------------------------
SimObject* findObject(const char* name)
{
SimObject *obj;
char c = *name;
if(c == '/')
return gRootGroup->findObject(name + 1 );
if(c >= '0' && c <= '9')
{
// it's an id group
const char* temp = name + 1;
for(;;)
{
c = *temp++;
if(!c)
return findObject(dAtoi(name));
else if(c == '/')
{
obj = findObject(dAtoi(name));
if(!obj)
return NULL;
return obj->findObject(temp);
}
}
}
S32 len;
for(len = 0; name[len] != 0 && name[len] != '/'; len++)
;
StringTableEntry stName = StringTable->lookupn(name, len);
if(!stName)
return NULL;
obj = gNameDictionary->find(stName);
if(!name[len])
return obj;
if(!obj)
return NULL;
return obj->findObject(name + len + 1);
}
SimObject* findObject(SimObjectId id)
{
return gIdDictionary->find(id);
}
SimGroup *getRootGroup()
{
return gRootGroup;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#define InstantiateNamedSet(set) g##set = new SimSet; g##set->registerObject(#set); gRootGroup->addObject(g##set)
#define InstantiateNamedGroup(set) g##set = new SimGroup; g##set->registerObject(#set); gRootGroup->addObject(g##set)
SimDataBlockGroup *gDataBlockGroup;
SimDataBlockGroup *getDataBlockGroup()
{
return gDataBlockGroup;
}
void init()
{
initEventQueue();
initRoot();
InstantiateNamedSet(ActiveActionMapSet);
InstantiateNamedSet(GhostAlwaysSet);
InstantiateNamedSet(LightSet);
InstantiateNamedSet(WayPointSet);
InstantiateNamedSet(ClientTargetSet);
InstantiateNamedSet(ServerTargetSet);
InstantiateNamedSet(FlareSet);
InstantiateNamedSet(MissileSet);
InstantiateNamedSet(CommandTargetSet);
InstantiateNamedSet(ScopeSensorVisibleSet);
InstantiateNamedGroup(ActionMapGroup);
InstantiateNamedGroup(ClientGroup);
InstantiateNamedGroup(GuiGroup);
InstantiateNamedGroup(GuiDataGroup);
InstantiateNamedGroup(TCPGroup);
InstantiateNamedGroup(ClientConnectionGroup);
gDataBlockGroup = new SimDataBlockGroup();
gDataBlockGroup->registerObject("DataBlockGroup");
gRootGroup->addObject(gDataBlockGroup);
}
void shutdown()
{
shutdownRoot();
shutdownEventQueue();
}
}
SimDataBlockGroup::SimDataBlockGroup()
{
mLastModifiedKey = 0;
}
S32 QSORT_CALLBACK SimDataBlockGroup::compareModifiedKey(const void* a,const void* b)
{
return (reinterpret_cast<const SimDataBlock* >(a))->getModifiedKey() -
(reinterpret_cast<const SimDataBlock*>(b))->getModifiedKey();
}
void SimDataBlockGroup::sort()
{
if(mLastModifiedKey != SimDataBlock::getNextModifiedKey())
{
mLastModifiedKey = SimDataBlock::getNextModifiedKey();
dQsort(objectList.address(),objectList.size(),sizeof(SimObject *),compareModifiedKey);
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
bool SimObject::registerObject()
{
mFlags.clear(Deleted | Removed);
if(!mId)
mId = Sim::gNextObjectId++;
Sim::gIdDictionary->insert(this);
Sim::gNameDictionary->insert(this);
// Notify object
bool ret = onAdd();
if(!ret)
unregisterObject();
AssertFatal(!ret || isProperlyAdded(), "Object did not call SimObject::onAdd()");
return ret;
}
//---------------------------------------------------------------------------
void SimObject::unregisterObject()
{
mFlags.set(Removed);
// Notify object first
onRemove();
// Clear out any pending notifications before
// we call our own, just in case they delete
// something that we have referenced.
clearAllNotifications();
// Notify all objects that are waiting for delete
// messages
if (getGroup())
getGroup()->removeObject(this);
processDeleteNotifies();
//
Sim::gNameDictionary->remove(this);
Sim::gIdDictionary->remove(this);
Sim::cancelPendingEvents(this);
}
//---------------------------------------------------------------------------
void SimObject::deleteObject()
{
AssertFatal(mFlags.test(Added),
"SimObject::deleteObject: Object not registered.");
AssertFatal(!isDeleted(),"SimManger::deleteObject: "
"Object has already been deleted");
AssertFatal(!isRemoved(),"SimManger::deleteObject: "
"Object in the process of being removed");
mFlags.set(Deleted);
unregisterObject();
delete this;
}
//---------------------------------------------------------------------------
void SimObject::setId(SimObjectId newId)
{
if(!mFlags.test(Added))
{
mId = newId;
return;
}
// get this object out of the id dictionary if it's in it
Sim::gIdDictionary->remove(this);
// Free current Id.
// Assign new one.
mId = newId ? newId : Sim::gNextObjectId++;
Sim::gIdDictionary->insert(this);
}
void SimObject::assignName(const char *name)
{
StringTableEntry newName = NULL;
if(name[0])
newName = StringTable->insert(name);
if(mGroup)
mGroup->nameDictionary.remove(this);
if(mFlags.test(Added))
Sim::gNameDictionary->remove(this);
objectName = newName;
if(mGroup)
mGroup->nameDictionary.insert(this);
if(mFlags.test(Added))
Sim::gNameDictionary->insert(this);
}
//---------------------------------------------------------------------------
bool SimObject::registerObject(U32 id)
{
setId(id);
return registerObject();
}
bool SimObject::registerObject(const char *name)
{
assignName(name);
return registerObject();
}
bool SimObject::registerObject(const char *name, U32 id)
{
setId(id);
assignName(name);
return registerObject();
}

256
console/telnetConsole.cc Normal file
View file

@ -0,0 +1,256 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "Platform/platform.h"
#include "Platform/event.h"
#include "console/telnetConsole.h"
#include "Platform/gameInterface.h"
TelnetConsole *TelConsole = NULL;
void TelnetConsole::create()
{
TelConsole = new TelnetConsole;
}
void TelnetConsole::destroy()
{
delete TelConsole;
TelConsole = NULL;
}
static void cTelnetSetParams(SimObject *, S32, const char **argv)
{
TelConsole->setTelnetParameters(dAtoi(argv[1]), argv[2], argv[3]);
}
static void telnetCallback(ConsoleLogEntry::Level level, const char *consoleLine)
{
TelConsole->processConsoleLine(consoleLine);
}
TelnetConsole::TelnetConsole()
{
Con::addConsumer(telnetCallback);
Con::addCommand("telnetSetParameters", cTelnetSetParams, "telnetSetParameters(port,consolePass,listenPass)", 4, 4);
mAcceptSocket = InvalidSocket;
mAcceptPort = -1;
mClientList = NULL;
}
TelnetConsole::~TelnetConsole()
{
Con::removeConsumer(telnetCallback);
if(mAcceptSocket != InvalidSocket)
Net::closeSocket(mAcceptSocket);
TelnetClient *walk = mClientList, *temp;
while(walk)
{
temp = walk->nextClient;
if(walk->socket != InvalidSocket)
Net::closeSocket(walk->socket);
delete walk;
walk = temp;
}
}
void TelnetConsole::setTelnetParameters(S32 port, const char *telnetPassword, const char *listenPassword)
{
if(port == mAcceptPort)
return;
if(mAcceptSocket != InvalidSocket)
{
Net::closeSocket(mAcceptSocket);
mAcceptSocket = InvalidSocket;
}
mAcceptPort = port;
if(mAcceptPort != -1 && mAcceptPort != 0)
{
mAcceptSocket = Net::openSocket();
Net::bind(mAcceptSocket, mAcceptPort);
Net::listen(mAcceptSocket, 4);
Net::setBlocking(mAcceptSocket, false);
}
dStrncpy(mTelnetPassword, telnetPassword, PasswordMaxLength);
dStrncpy(mListenPassword, listenPassword, PasswordMaxLength);
}
void TelnetConsole::processConsoleLine(const char *consoleLine)
{
// ok, spew this line out to all our subscribers...
S32 len = dStrlen(consoleLine)+1;
for(TelnetClient *walk = mClientList; walk; walk = walk->nextClient)
{
if(walk->state == FullAccessConnected || walk->state == ReadOnlyConnected)
{
Net::send(walk->socket, (const unsigned char*)consoleLine, len);
Net::send(walk->socket, (const unsigned char*)"\r\n", 2);
}
}
}
void TelnetConsole::process()
{
NetAddress address;
if(mAcceptSocket != InvalidSocket)
{
// ok, see if we have any new connections:
NetSocket newConnection;
newConnection = Net::accept(mAcceptSocket, &address);
if(newConnection != InvalidSocket)
{
Con::printf ("Telnet connection from %i.%i.%i.%i",
address.netNum[0], address.netNum[1], address.netNum[2], address.netNum[3]);
TelnetClient *cl = new TelnetClient;
cl->socket = newConnection;
cl->curPos = 0;
cl->state = PasswordTryOne;
Net::setBlocking(newConnection, false);
char *connectMessage = "Tribes 2 Telnet\r\n\r\nEnter Password:";
Net::send(cl->socket, (const unsigned char*)connectMessage, dStrlen(connectMessage)+1);
cl->nextClient = mClientList;
mClientList = cl;
}
}
char recvBuf[256];
char reply[1024];
// see if we have any input to process...
for(TelnetClient *client = mClientList; client; client = client->nextClient)
{
S32 numBytes;
Net::Error err = Net::recv(client->socket, (unsigned char*)recvBuf, sizeof(recvBuf), &numBytes);
if((err != Net::NoError && err != Net::WouldBlock) || numBytes == 0)
{
Net::closeSocket(client->socket);
client->socket = InvalidSocket;
continue;
}
S32 replyPos = 0;
for(S32 i = 0; i < numBytes;i++)
{
if(recvBuf[i] == '\r')
continue;
// execute the current command
if(recvBuf[i] == '\n')
{
reply[replyPos++] = '\r';
reply[replyPos++] = '\n';
client->curLine[client->curPos] = 0;
client->curPos = 0;
if(client->state == FullAccessConnected)
{
Net::send(client->socket, (const unsigned char*)reply, replyPos);
replyPos = 0;
dStrcpy(mPostEvent.data, client->curLine);
mPostEvent.size = ConsoleEventHeaderSize + dStrlen(client->curLine) + 1;
Game->postEvent(mPostEvent);
// note - send prompt next
const char *prompt = Con::getVariable("Con::Prompt");
Net::send(client->socket, (const unsigned char*)prompt, dStrlen(prompt));
}
else if(client->state == ReadOnlyConnected)
{
Net::send(client->socket, (const unsigned char*)reply, replyPos);
replyPos = 0;
}
else
{
client->state++;
if(!dStrncmp(client->curLine, mTelnetPassword, PasswordMaxLength))
{
Net::send(client->socket, (const unsigned char*)reply, replyPos);
replyPos = 0;
// send prompt
const char *prompt = Con::getVariable("Con::Prompt");
Net::send(client->socket, (const unsigned char*)prompt, dStrlen(prompt));
client->state = FullAccessConnected;
}
else if(!dStrncmp(client->curLine, mListenPassword, PasswordMaxLength))
{
Net::send(client->socket, (const unsigned char*)reply, replyPos);
replyPos = 0;
// send prompt
const char *listenConnected = "Connected.\r\n";
Net::send(client->socket, (const unsigned char*)listenConnected, dStrlen(listenConnected));
client->state = ReadOnlyConnected;
}
else
{
const char *sendStr;
if(client->state == DisconnectThisDude)
sendStr = "Too many tries... cya.";
else
sendStr = "Nope... try agian.\r\nEnter Password:";
Net::send(client->socket, (const unsigned char*)sendStr, dStrlen(sendStr));
if(client->state == DisconnectThisDude)
{
Net::closeSocket(client->socket);
client->socket = InvalidSocket;
}
}
}
}
else if(recvBuf[i] == '\b')
{
// pull the old backspace manuever...
if(client->curPos > 0)
{
client->curPos--;
if(client->state == FullAccessConnected)
{
reply[replyPos++] = '\b';
reply[replyPos++] = ' ';
reply[replyPos++] = '\b';
}
}
}
else if(client->curPos < Con::MaxLineLength-1)
{
client->curLine[client->curPos++] = recvBuf[i];
// don't echo password chars...
if(client->state == FullAccessConnected)
reply[replyPos++] = recvBuf[i];
}
}
if(replyPos)
Net::send(client->socket, (const unsigned char*)reply, replyPos);
}
TelnetClient ** walk = &mClientList;
TelnetClient *cl;
while((cl = *walk) != NULL)
{
if(cl->socket == InvalidSocket)
{
*walk = cl->nextClient;
delete cl;
}
else
walk = &cl->nextClient;
}
}

60
console/telnetConsole.h Normal file
View file

@ -0,0 +1,60 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _TELNETCONSOLE_H_
#define _TELNETCONSOLE_H_
#ifndef _CONSOLE_H_
#include "console/console.h"
#endif
class TelnetConsole
{
NetSocket mAcceptSocket;
S32 mAcceptPort;
enum {
PasswordMaxLength = 32
};
char mTelnetPassword[PasswordMaxLength+1];
char mListenPassword[PasswordMaxLength+1];
ConsoleEvent mPostEvent;
enum State
{
PasswordTryOne,
PasswordTryTwo,
PasswordTryThree,
DisconnectThisDude,
FullAccessConnected,
ReadOnlyConnected
};
struct TelnetClient
{
NetSocket socket;
char curLine[Con::MaxLineLength];
S32 curPos;
S32 state;
TelnetClient *nextClient;
};
TelnetClient *mClientList;
TelnetConsole();
~TelnetConsole();
public:
static void create();
static void destroy();
void process();
void setTelnetParameters(S32 port, const char *telnetPassword, const char *listenPassword);
void processConsoleLine(const char *line);
};
extern TelnetConsole *TelConsole;
#endif

557
console/telnetDebugger.cc Normal file
View file

@ -0,0 +1,557 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "Platform/platform.h"
#include "console/console.h"
#include "console/telnetDebugger.h"
#include "Platform/event.h"
#include "Core/stringTable.h"
#include "console/consoleInternal.h"
#include "console/ast.h"
#include "console/compiler.h"
#include "Platform/gameInterface.h"
//------------------------------------------------------------
// debugger commands:
// CEVAL console line - evaluate the console line
// output: none
// BRKVARSET varName passct expr
// output: none
// BRKVARCLR varName
// output: none
// BRKSET file line clear passct expr - set a breakpoint on the file,line
// it must pass passct times for it to break and if clear is true, it
// clears when hit
// output: none
// BRKCLR file line - clear a breakpoint on the file,line
// output: none
// BRKCLRALL - clear all breakpoints
// output: none
// CONTINUE - continue execution
// output: RUNNING
// STEPIN - run until next statement
// output: RUNNING
// STEPOVER - run until next break <= current frame
// output: RUNNING
// STEPOUT - run until next break <= current frame - 1
// output: RUNNING
// EVAL tag frame expr - evaluate the expr in the console, on the frame'th stack frame
// output: EVALOUT tag exprResult
// FILELIST - list script files loaded
// output: FILELISTOUT file1 file2 file3 file4 ...
// BREAKLIST file - get a list of breakpoint-able lines in the file
// output: BREAKLISTOUT file skipBreakPairs skiplinecount breaklinecount skiplinecount breaklinecount ...
//
// other output:
//
// when the debugger hits a breakpoint, it lists out:
// BREAK file1 line1 fn1 file2 line2 fn2 file3 line3 fn3 file4 line4 fn4 etc.
// where file1 line1 fn1 ... etc is the current call stack.
// COUT echo out a console line
static void cDebugSetParams(SimObject *, S32, const char **argv)
{
TelDebugger->setDebugParameters(dAtoi(argv[1]), argv[2]);
}
static void debuggerConsumer(ConsoleLogEntry::Level level, const char *line)
{
TelDebugger->processConsoleLine(line);
}
TelnetDebugger::TelnetDebugger()
{
Con::addCommand("dbgSetParameters", cDebugSetParams, "dbgSetParameters(port,pass);", 3, 3);
Con::addConsumer(debuggerConsumer);
mAcceptPort = -1;
mAcceptSocket = InvalidSocket;
mDebugSocket = InvalidSocket;
mState = NotConnected;
mBreakpoints = NULL;
mBreakOnNextStatement = false;
mStackPopBreakIndex = -1;
mProgramPaused = false;
}
TelnetDebugger::Breakpoint **TelnetDebugger::findBreakpoint(StringTableEntry fileName, S32 lineNumber)
{
Breakpoint **walk = &mBreakpoints;
Breakpoint *cur;
while((cur = *walk) != NULL)
{
if(cur->code->name == fileName && cur->lineNumber == U32(lineNumber))
return walk;
walk = &cur->next;
}
return NULL;
}
TelnetDebugger::~TelnetDebugger()
{
Con::removeConsumer(debuggerConsumer);
if(mAcceptSocket != InvalidSocket)
Net::closeSocket(mAcceptSocket);
if(mDebugSocket != InvalidSocket)
Net::closeSocket(mDebugSocket);
}
TelnetDebugger *TelDebugger = NULL;
void TelnetDebugger::create()
{
TelDebugger = new TelnetDebugger;
}
void TelnetDebugger::destroy()
{
delete TelDebugger;
TelDebugger = NULL;
}
void TelnetDebugger::send(const char *str)
{
Net::send(mDebugSocket, (const unsigned char*)str, dStrlen(str));
}
void TelnetDebugger::setDebugParameters(S32 port, const char *password)
{
if(port == mAcceptPort)
return;
if(mAcceptSocket != InvalidSocket)
{
Net::closeSocket(mAcceptSocket);
mAcceptSocket = InvalidSocket;
}
mAcceptPort = port;
if(mAcceptPort != -1 && mAcceptPort != 0)
{
mAcceptSocket = Net::openSocket();
Net::bind(mAcceptSocket, mAcceptPort);
Net::listen(mAcceptSocket, 4);
Net::setBlocking(mAcceptSocket, false);
}
dStrncpy(mDebuggerPassword, password, PasswordMaxLength);
}
void TelnetDebugger::processConsoleLine(const char *consoleLine)
{
if(mState == Connected)
{
send("COUT ");
send(consoleLine);
send("\r\n");
}
}
void TelnetDebugger::process()
{
NetAddress address;
if(mAcceptSocket != InvalidSocket)
{
// ok, see if we have any new connections:
NetSocket newConnection;
newConnection = Net::accept(mAcceptSocket, &address);
if(newConnection != InvalidSocket && mDebugSocket == InvalidSocket)
{
Con::printf ("Debugger connection from %i.%i.%i.%i",
address.netNum[0], address.netNum[1], address.netNum[2], address.netNum[3]);
mState = PasswordTry;
mDebugSocket = newConnection;
Net::setBlocking(newConnection, false);
}
else if(newConnection != InvalidSocket)
Net::closeSocket(newConnection);
}
// see if we have any input to process...
if(mDebugSocket == InvalidSocket)
return;
checkDebugRecv();
if(mDebugSocket == InvalidSocket)
removeAllBreakpoints();
}
void TelnetDebugger::checkDebugRecv()
{
S32 checked = false;
for(;;) {
// check for and recv one command:
for(S32 i = 0; i < mCurPos; i++)
{
if(mLineBuffer[i] == '\r' || mLineBuffer[i] == '\n')
{
if(i == 0)
{
mCurPos--;
dMemmove(mLineBuffer, mLineBuffer + 1, mCurPos);
}
else
{
mLineBuffer[i] = '\n';
processLineBuffer(i+1);
mCurPos -= i + 1;
dMemmove(mLineBuffer, mLineBuffer + i + 1, mCurPos);
return;
}
}
else if(mLineBuffer[i] == 0)
mLineBuffer[i] = '_';
}
// found no <CR> or <LF>
if(mCurPos == MaxCommandSize) // this shouldn't happen
{
Net::closeSocket(mDebugSocket);
mDebugSocket = InvalidSocket;
mState = NotConnected;
return;
}
if(checked)
return;
checked = false;
S32 numBytes;
Net::Error err = Net::recv(mDebugSocket, (unsigned char*)(mLineBuffer + mCurPos), MaxCommandSize - mCurPos, &numBytes);
if((err != Net::NoError && err != Net::WouldBlock) || numBytes == 0)
{
Net::closeSocket(mDebugSocket);
mDebugSocket = InvalidSocket;
mState = NotConnected;
return;
}
if(err == Net::WouldBlock)
return;
mCurPos += numBytes;
}
}
void TelnetDebugger::executionStopped(CodeBlock *code, U32 lineNumber)
{
if(mProgramPaused)
return;
if(mBreakOnNextStatement)
{
// loop through all the codeblocks clearing the breaks
for(CodeBlock *walk = codeBlockList; walk; walk = walk->nextFile)
walk->clearAllBreaks();
for(Breakpoint *w = mBreakpoints; w; w = w->next)
w->code->setBreakpoint(w->lineNumber);
breakProcess();
return;
}
Breakpoint **bp = findBreakpoint(code->name, lineNumber);
if(!bp)
return;
Breakpoint *brk = *bp;
mProgramPaused = true;
Con::evaluatef("$dbgResult = %s;", brk->testExpression);
if(Con::getBoolVariable("$dbgResult"))
{
brk->curCount++;
if(brk->curCount >= brk->passCount)
{
brk->curCount = 0;
if(brk->clearOnHit)
removeBreakpoint(code->name, lineNumber);
breakProcess();
}
}
mProgramPaused = false;
}
void TelnetDebugger::popStackFrame()
{
if(mState == NotConnected)
return;
if(U32(mStackPopBreakIndex) == gEvalState.stack.size())
breakOnNextStatement();
}
void TelnetDebugger::breakProcess()
{
mProgramPaused = true;
// echo out the break
send("BREAK");
char buffer[MaxCommandSize];
for(S32 i = (S32) gEvalState.stack.size() - 1; i >= 0; i--)
{
CodeBlock *code = gEvalState.stack[i]->code;
U32 ip = gEvalState.stack[i]->ip;
const char *file = code->name;
const char *scope = gEvalState.stack[i]->scopeName;
if ((! file) || (! file[0]))
file = "N/A";
if ((! scope) || (! scope[0]))
scope = "N/A";
U32 line, inst;
code->findBreakLine(ip, line, inst);
dSprintf(buffer, MaxCommandSize, " %s %d %s", file, line, scope);
send(buffer);
}
send("\r\n");
while(mProgramPaused)
{
checkDebugRecv();
if(mDebugSocket == InvalidSocket)
{
mProgramPaused = false;
removeAllBreakpoints();
debugContinue();
return;
}
}
}
void TelnetDebugger::processLineBuffer(S32 cmdLen)
{
if (mState == PasswordTry)
{
if(dStrncmp(mLineBuffer, mDebuggerPassword, cmdLen-1))
{
// failed password:
send("PASS WrongPassword.\r\n");
Net::closeSocket(mDebugSocket);
mDebugSocket = InvalidSocket;
mState = NotConnected;
}
else
{
send("PASS Connected.\r\n");
mState = Connected;
}
}
else
{
char evalBuffer[MaxCommandSize];
char varBuffer[MaxCommandSize];
char fileBuffer[MaxCommandSize];
char clear[MaxCommandSize];
S32 passCount, line, frame;
if(dSscanf(mLineBuffer, "CEVAL %[^\n]", evalBuffer) == 1)
{
ConsoleEvent postEvent;
dStrcpy(postEvent.data, evalBuffer);
postEvent.size = ConsoleEventHeaderSize + dStrlen(evalBuffer) + 1;
Game->postEvent(postEvent);
}
else if(dSscanf(mLineBuffer, "BRKVARSET %s %d %[^\n]", varBuffer, &passCount, evalBuffer) == 3)
addVariableBreakpoint(varBuffer, passCount, evalBuffer);
else if(dSscanf(mLineBuffer, "BRKVARCLR %s", varBuffer) == 1)
removeVariableBreakpoint(varBuffer);
else if(dSscanf(mLineBuffer, "BRKSET %s %d %s %d %[^\n]", fileBuffer,&line,&clear,&passCount,evalBuffer) == 5)
addBreakpoint(fileBuffer, line, dAtob(clear), passCount, evalBuffer);
else if(dSscanf(mLineBuffer, "BRKCLR %s %d", fileBuffer, &line) == 2)
removeBreakpoint(fileBuffer, line);
else if(!dStrncmp(mLineBuffer, "BRKCLRALL\n", cmdLen))
removeAllBreakpoints();
else if(!dStrncmp(mLineBuffer, "CONTINUE\n", cmdLen))
debugContinue();
else if(!dStrncmp(mLineBuffer, "STEPIN\n", cmdLen))
debugStepIn();
else if(!dStrncmp(mLineBuffer, "STEPOVER\n", cmdLen))
debugStepOver();
else if(!dStrncmp(mLineBuffer, "STEPOUT\n", cmdLen))
debugStepOut();
else if(dSscanf(mLineBuffer, "EVAL %s %d %[^\n]", varBuffer, &frame, evalBuffer) == 3)
evaluateExpression(varBuffer, frame, evalBuffer);
else if(!dStrncmp(mLineBuffer, "FILELIST\n", cmdLen))
dumpFileList();
else if(dSscanf(mLineBuffer, "BREAKLIST %s", fileBuffer) == 1)
dumpBreakableList(fileBuffer);
else
{
// invalid stuff.
send("DBGERR Invalid command!\r\n");
}
}
}
void TelnetDebugger::addVariableBreakpoint(const char*, S32, const char*)
{
send("addVariableBreakpoint\r\n");
}
void TelnetDebugger::removeVariableBreakpoint(const char*)
{
send("removeVariableBreakpoint\r\n");
}
void TelnetDebugger::addBreakpoint(const char *fileName, S32 line, bool clear, S32 passCount, const char *evalString)
{
fileName = StringTable->insert(fileName);
Breakpoint **bp = findBreakpoint(fileName, line);
if(bp)
{
// trying to add the same breakpoint...
Breakpoint *brk = *bp;
dFree(brk->testExpression);
brk->testExpression = dStrdup(evalString);
brk->passCount = passCount;
brk->clearOnHit = clear;
brk->curCount = 0;
}
else
{
CodeBlock *code = CodeBlock::find(fileName);
if(code)
{
Breakpoint *brk = new Breakpoint;
brk->code = code;
code->setBreakpoint(line);
brk->lineNumber = line;
brk->passCount = passCount;
brk->clearOnHit = clear;
brk->curCount = 0;
brk->testExpression = dStrdup(evalString);
brk->next = mBreakpoints;
mBreakpoints = brk;
}
}
}
void TelnetDebugger::removeBreakpointsFromCode(CodeBlock *code)
{
Breakpoint **walk = &mBreakpoints;
Breakpoint *cur;
while((cur = *walk) != NULL)
{
if(cur->code == code)
{
dFree(cur->testExpression);
*walk = cur->next;
delete walk;
}
else
walk = &cur->next;
}
}
void TelnetDebugger::removeBreakpoint(const char *fileName, S32 line)
{
fileName = StringTable->insert(fileName);
Breakpoint **bp = findBreakpoint(fileName, line);
if(bp)
{
Breakpoint *brk = *bp;
*bp = brk->next;
brk->code->clearBreakpoint(brk->lineNumber);
dFree(brk->testExpression);
delete brk;
}
}
void TelnetDebugger::removeAllBreakpoints()
{
Breakpoint *walk = mBreakpoints;
while(walk)
{
Breakpoint *temp = walk->next;
walk->code->clearBreakpoint(walk->lineNumber);
dFree(walk->testExpression);
delete walk;
walk = temp;
}
mBreakpoints = NULL;
}
void TelnetDebugger::debugContinue()
{
mBreakOnNextStatement = false;
mStackPopBreakIndex = -1;
mProgramPaused = false;
send("RUNNING\r\n");
}
void TelnetDebugger::breakOnNextStatement()
{
for(CodeBlock *walk = codeBlockList; walk; walk = walk->nextFile)
walk->setAllBreaks();
mBreakOnNextStatement = true;
}
void TelnetDebugger::debugStepIn()
{
breakOnNextStatement();
mStackPopBreakIndex = -1;
mProgramPaused = false;
send("RUNNING\r\n");
}
void TelnetDebugger::debugStepOver()
{
mBreakOnNextStatement = false;
mStackPopBreakIndex = gEvalState.stack.size();
mProgramPaused = false;
send("RUNNING\r\n");
}
void TelnetDebugger::debugStepOut()
{
mBreakOnNextStatement = false;
mStackPopBreakIndex = gEvalState.stack.size() - 1;
mProgramPaused = false;
send("RUNNING\r\n");
}
void TelnetDebugger::evaluateExpression(const char *tag, S32, const char *evalBuffer)
{
char buffer[MaxCommandSize];
Con::evaluatef("$dbgResult = %s;", evalBuffer);
const char *result = Con::getVariable("$dbgResult");
dSprintf(buffer, MaxCommandSize, "EVALOUT %s %s\r\n", tag, result[0] ? result : "\"\"");
send(buffer);
}
void TelnetDebugger::dumpFileList()
{
send("FILELISTOUT ");
for(CodeBlock *walk = codeBlockList; walk; walk = walk->nextFile)
{
send(walk->name);
if(walk->nextFile)
send(" ");
}
send("\r\n");
}
void TelnetDebugger::dumpBreakableList(const char *fileName)
{
fileName = StringTable->insert(fileName);
CodeBlock *file = CodeBlock::find(fileName);
char buffer[MaxCommandSize];
if(file)
{
dSprintf(buffer, MaxCommandSize, "BREAKLISTOUT %s %d", fileName, file->breakListSize >> 1);
send(buffer);
for(U32 i = 0; i < file->breakListSize; i += 2)
{
dSprintf(buffer, MaxCommandSize, " %d %d", file->breakList[i], file->breakList[i+1]);
send(buffer);
}
send("\r\n");
}
else
send("DBGERR No Such file!");
}

90
console/telnetDebugger.h Normal file
View file

@ -0,0 +1,90 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _TELNETDEBUGGER_H_
#define _TELNETDEBUGGER_H_
class CodeBlock;
class TelnetDebugger
{
S32 mAcceptPort;
NetSocket mAcceptSocket;
NetSocket mDebugSocket;
enum {
PasswordMaxLength = 32,
MaxCommandSize = 2048
};
char mDebuggerPassword[PasswordMaxLength+1];
enum State
{
NotConnected,
PasswordTry,
Connected
};
S32 mState;
char mLineBuffer[MaxCommandSize];
S32 mCurPos;
TelnetDebugger();
~TelnetDebugger();
struct Breakpoint
{
CodeBlock *code;
U32 lineNumber;
S32 passCount;
S32 curCount;
char *testExpression;
bool clearOnHit;
Breakpoint *next;
};
Breakpoint *mBreakpoints;
Breakpoint **findBreakpoint(StringTableEntry fileName, S32 lineNumber);
bool mProgramPaused;
bool mBreakOnNextStatement;
S32 mStackPopBreakIndex;
void addVariableBreakpoint(const char *varName, S32 passCount, const char *evalString);
void removeVariableBreakpoint(const char *varName);
void addBreakpoint(const char *fileName, S32 line, bool clear, S32 passCount, const char *evalString);
void removeBreakpoint(const char *fileName, S32 line);
void removeAllBreakpoints();
void debugContinue();
void debugStepIn();
void debugStepOver();
void debugStepOut();
void evaluateExpression(const char *tag, S32 frame, const char *evalBuffer);
void dumpFileList();
void dumpBreakableList(const char *fileName);
void removeBreakpointsFromCode(CodeBlock *code);
void checkDebugRecv();
void processLineBuffer(S32);
void breakProcess();
void breakOnNextStatement();
public:
static void create();
static void destroy();
void process();
void popStackFrame();
virtual void executionStopped(CodeBlock *code, U32 lineNumber);
void send(const char *s);
void setDebugParameters(S32 port, const char *password);
void processConsoleLine(const char *consoleLine);
};
extern TelnetDebugger *TelDebugger;
#endif

72
console/typeValidators.cc Normal file
View file

@ -0,0 +1,72 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "console/console.h"
#include "console/consoleObject.h"
#include "console/typeValidators.h"
#include "console/simBase.h"
#include <stdarg.h>
void TypeValidator::consoleError(SimObject *object, const char *format, ...)
{
char buffer[1024];
va_list argptr;
va_start(argptr, format);
dVsprintf(buffer, sizeof(buffer), format, argptr);
va_end(argptr);
AbstractClassRep *rep = object->getClassRep();
AbstractClassRep::Field &fld = rep->mFieldList[fieldIndex];
const char *objectName = object->getName();
if(!objectName)
objectName = "unnamed";
Con::warnf("%s - %s(%d) - invalid value for %s: %s",
rep->getClassName(), objectName, object->getId(), fld.pFieldname, buffer);
}
void FRangeValidator::validateType(SimObject *object, void *typePtr)
{
F32 *v = (F32 *) typePtr;
if(*v < minV || *v > maxV)
{
consoleError(object, "Must be between %g and %g", minV, maxV);
if(*v < minV)
*v = minV;
else if(*v > maxV)
*v = maxV;
}
}
void IRangeValidator::validateType(SimObject *object, void *typePtr)
{
S32 *v = (S32 *) typePtr;
if(*v < minV || *v > maxV)
{
consoleError(object, "Must be between %d and %d", minV, maxV);
if(*v < minV)
*v = minV;
else if(*v > maxV)
*v = maxV;
}
}
void IRangeValidatorScaled::validateType(SimObject *object, void *typePtr)
{
S32 *v = (S32 *) typePtr;
*v /= factor;
if(*v < minV || *v > maxV)
{
consoleError(object, "Scaled value must be between %d and %d", minV, maxV);
if(*v < minV)
*v = minV;
else if(*v > maxV)
*v = maxV;
}
}

72
console/typeValidators.h Normal file
View file

@ -0,0 +1,72 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _TYPEVALIDATORS_H_
#define _TYPEVALIDATORS_H_
class TypeValidator
{
public:
S32 fieldIndex;
// prints a console error message, prefaces it with:
// className objectName (objectId) - invalid value for fieldName: msg
void consoleError(SimObject *object, const char *format, ...);
// validateType is called for each assigned value on the field this
// validator is attached to
virtual void validateType(SimObject *object, void *typePtr) = 0;
};
// Floating point min/max range validator
class FRangeValidator : public TypeValidator
{
F32 minV, maxV;
public:
FRangeValidator(F32 minValue, F32 maxValue)
{
minV = minValue;
maxV = maxValue;
}
void validateType(SimObject *object, void *typePtr);
};
// signed integer min/max range validator
class IRangeValidator : public TypeValidator
{
S32 minV, maxV;
public:
IRangeValidator(S32 minValue, S32 maxValue)
{
minV = minValue;
maxV = maxValue;
}
void validateType(SimObject *object, void *typePtr);
};
// scaled integer field validator - !note! should
// NOT be used on a field that gets exported -
// field is only converted once on initial assignment
class IRangeValidatorScaled : public TypeValidator
{
S32 minV, maxV;
S32 factor;
public:
IRangeValidatorScaled(S32 scaleFactor, S32 minValueScaled, S32 maxValueScaled)
{
minV = minValueScaled;
maxV = maxValueScaled;
factor = scaleFactor;
}
void validateType(SimObject *object, void *typePtr);
};
#endif

627
console/yylex.c Normal file
View file

@ -0,0 +1,627 @@
/*
* Copyright 1988, 1992 by Mortice Kern Systems Inc. All rights reserved.
* All rights reserved.
*
* $Header: /cvs/torque/torque/engine/console/yylex.c,v 1.1 2001/05/17 02:16:20 timg Exp $
*
*/
#include <stdlib.h>
#include <stdio.h>
#if __STDC__
#define YY_ARGS(args) args
#else
#define YY_ARGS(args) ()
#endif
#ifdef LEX_WINDOWS
#include <windows.h>
/*
* define, if not already defined
* the flag YYEXIT, which will allow
* graceful exits from yylex()
* without resorting to calling exit();
*/
#ifndef YYEXIT
#define YYEXIT 1
#endif
/*
* the following is the handle to the current
* instance of a windows program. The user
* program calling yylex must supply this!
*/
#ifdef STRICT
extern HINSTANCE hInst;
#else
extern HANDLE hInst;
#endif
#endif /* LEX_WINDOWS */
/*
* Define m_textmsg() to an appropriate function for internationalized messages
* or custom processing.
*/
#ifndef I18N
#define m_textmsg(id, str, cls) (str)
#else /*I18N*/
extern char* m_textmsg YY_ARGS((int id, const char* str, char* cls));
#endif/*I18N*/
/*
* Include string.h to get definition of memmove() and size_t.
* If you do not have string.h or it does not declare memmove
* or size_t, you will have to declare them here.
*/
#include <string.h>
/* Uncomment next line if memmove() is not declared in string.h */
/*extern char * memmove();*/
/* Uncomment next line if size_t is not available in stdio.h or string.h */
/*typedef unsigned size_t;*/
/* Drop this when LATTICE provides memmove */
#ifdef LATTICE
#define memmove memcopy
#endif
/*
* YY_STATIC determines the scope of variables and functions
* declared by the lex scanner. It must be set with a -DYY_STATIC
* option to the compiler (it cannot be defined in the lex program).
*/
#ifdef YY_STATIC
/* define all variables as static to allow more than one lex scanner */
#define YY_DECL static
#else
/* define all variables as global to allow other modules to access them */
#define YY_DECL
#endif
/*
* You can redefine yygetc. For YACC Tracing, compile this code
* with -DYYTRACE to get input from yt_getc
*/
#ifdef YYTRACE
extern int yt_getc YY_ARGS((void));
#define yygetc() yt_getc()
#else
#define yygetc() getc(yyin) /* yylex input source */
#endif
/*
* the following can be redefined by the user.
*/
#ifdef YYEXIT
#define YY_FATAL(msg) { fprintf(yyout, "yylex: %s\n", msg); yyLexFatal = 1; }
#else /* YYEXIT */
#define YY_FATAL(msg) { fprintf(stderr, "yylex: %s\n", msg); exit(1); }
#endif /* YYEXIT */
#undef ECHO
#define ECHO fputs(yytext, yyout)
#define output(c) putc((c), yyout) /* yylex sink for unmatched chars */
#define YY_INTERACTIVE 1 /* save micro-seconds if 0 */
#define BEGIN yy_start =
#define REJECT goto yy_reject
#define NLSTATE (yy_lastc = YYNEWLINE)
#define YY_INIT \
(yy_start = yyleng = yy_end = 0, yy_lastc = YYNEWLINE)
#define yymore() goto yy_more
#define yyless(n) if ((n) < 0 || (n) > yy_end) ; \
else { YY_SCANNER; yyleng = (n); YY_USER; }
YY_DECL void yy_reset YY_ARGS((void));
YY_DECL int input YY_ARGS((void));
YY_DECL int unput YY_ARGS((int c));
/* functions defined in libl.lib */
extern int yywrap YY_ARGS((void));
extern void yyerror YY_ARGS((char *fmt, ...));
extern void yycomment YY_ARGS((char *term));
extern int yymapch YY_ARGS((int delim, int escape));
@ GLOBAL DECLARATIONS @
#ifndef YYLMAX
#define YYLMAX 100 /* token and pushback buffer size */
#endif /* YYLMAX */
/*
* If %array is used (or defaulted), yytext[] contains the token.
* If %pointer is used, yytext is a pointer to yy_tbuf[].
*/
@aYY_DECL char yytext[YYLMAX+1];
@pYY_DECL char yy_tbuf[YYLMAX+1];
@pYY_DECL char * yytext = yy_tbuf;
#ifdef YY_DEBUG
#undef YY_DEBUG
#define YY_DEBUG(fmt, a1, a2) fprintf(stderr, fmt, a1, a2)
#else
#define YY_DEBUG(fmt, a1, a2)
#endif
/*
* The declaration for the lex scanner can be changed by
* redefining YYLEX or YYDECL. This must be done if you have
* more than one scanner in a program.
*/
#ifndef YYLEX
#define YYLEX yylex /* name of lex scanner */
#endif
#ifndef YYDECL
#define YYDECL int YYLEX YY_ARGS((void)) /* declaration for lex scanner */
#endif
/*
* stdin and stdout may not neccessarily be constants.
* If stdin and stdout are constant, and you want to save a few cycles, then
* #define YY_STATIC_STDIO 1 in this file or on the commandline when
* compiling this file
*/
#ifndef YY_STATIC_STDIO
#define YY_STATIC_STDIO 0
#endif
#if YY_STATIC_STDIO
YY_DECL FILE *yyin = stdin;
YY_DECL FILE *yyout = stdout;
#else
YY_DECL FILE *yyin = (FILE *)0;
YY_DECL FILE *yyout = (FILE *)0;
#endif
YY_DECL int yylineno = 1; /* line number */
/* yy_sbuf[0:yyleng-1] contains the states corresponding to yytext.
* yytext[0:yyleng-1] contains the current token.
* yytext[yyleng:yy_end-1] contains pushed-back characters.
* When the user action routine is active,
* yy_save contains yytext[yyleng], which is set to '\0'.
* Things are different when YY_PRESERVE is defined.
*/
static yy_state_t yy_sbuf [YYLMAX+1]; /* state buffer */
static int yy_end = 0; /* end of pushback */
static int yy_start = 0; /* start state */
static int yy_lastc = YYNEWLINE; /* previous char */
YY_DECL int yyleng = 0; /* yytext token length */
#ifdef YYEXIT
static int yyLexFatal;
#endif /* YYEXIT */
#ifndef YY_PRESERVE /* the efficient default push-back scheme */
static char yy_save; /* saved yytext[yyleng] */
#define YY_USER { /* set up yytext for user */ \
yy_save = yytext[yyleng]; \
yytext[yyleng] = 0; \
}
#define YY_SCANNER { /* set up yytext for scanner */ \
yytext[yyleng] = yy_save; \
}
#else /* not-so efficient push-back for yytext mungers */
static char yy_save [YYLMAX];
static char *yy_push = yy_save+YYLMAX;
#define YY_USER { \
size_t n = yy_end - yyleng; \
yy_push = yy_save+YYLMAX - n; \
if (n > 0) \
memmove(yy_push, yytext+yyleng, n); \
yytext[yyleng] = 0; \
}
#define YY_SCANNER { \
size_t n = yy_save+YYLMAX - yy_push; \
if (n > 0) \
memmove(yytext+yyleng, yy_push, n); \
yy_end = yyleng + n; \
}
#endif
#ifdef LEX_WINDOWS
/*
* When using the windows features of lex,
* it is necessary to load in the resources being
* used, and when done with them, the resources must
* be freed up, otherwise we have a windows app that
* is not following the rules. Thus, to make yylex()
* behave in a windows environment, create a new
* yylex() which will call the original yylex() as
* another function call. Observe ...
*/
/*
* The actual lex scanner (usually yylex(void)).
* NOTE: you should invoke yy_init() if you are calling yylex()
* with new input; otherwise old lookaside will get in your way
* and yylex() will die horribly.
*/
static int win_yylex(); /* prototype for windows yylex handler */
YYDECL {
int wReturnValue;
HANDLE hRes_table;
unsigned short far *old_yy_la_act; /* remember previous pointer values */
short far *old_yy_final;
yy_state_t far *old_yy_begin;
yy_state_t far *old_yy_next;
yy_state_t far *old_yy_check;
yy_state_t far *old_yy_default;
short far *old_yy_base;
/*
* the following code will load the required
* resources for a Windows based parser.
*/
hRes_table = LoadResource (hInst,
FindResource (hInst, "UD_RES_yyLEX", "yyLEXTBL"));
/*
* return an error code if any
* of the resources did not load
*/
if (hRes_table == NULL)
return (0);
/*
* the following code will lock the resources
* into fixed memory locations for the scanner
* (and remember previous pointer locations)
*/
old_yy_la_act = yy_la_act;
old_yy_final = yy_final;
old_yy_begin = yy_begin;
old_yy_next = yy_next;
old_yy_check = yy_check;
old_yy_default = yy_default;
old_yy_base = yy_base;
yy_la_act = (unsigned short far *)LockResource (hRes_table);
yy_final = (short far *)(yy_la_act + Sizeof_yy_la_act);
yy_begin = (yy_state_t far *)(yy_final + Sizeof_yy_final);
yy_next = (yy_state_t far *)(yy_begin + Sizeof_yy_begin);
yy_check = (yy_state_t far *)(yy_next + Sizeof_yy_next);
yy_default = (yy_state_t far *)(yy_check + Sizeof_yy_check);
yy_base = (yy_state_t far *)(yy_default + Sizeof_yy_default);
/*
* call the standard yylex() code
*/
wReturnValue = win_yylex();
/*
* unlock the resources
*/
UnlockResource (hRes_table);
/*
* and now free the resource
*/
FreeResource (hRes_table);
/*
* restore previously saved pointers
*/
yy_la_act = old_yy_la_act;
yy_final = old_yy_final;
yy_begin = old_yy_begin;
yy_next = old_yy_next;
yy_check = old_yy_check;
yy_default = old_yy_default;
yy_base = old_yy_base;
return (wReturnValue);
} /* end function */
static int win_yylex() {
#else /* LEX_WINDOWS */
/*
* The actual lex scanner (usually yylex(void)).
* NOTE: you should invoke yy_init() if you are calling yylex()
* with new input; otherwise old lookaside will get in your way
* and yylex() will die horribly.
*/
YYDECL {
#endif /* LEX_WINDOWS */
register int c, i, yybase;
unsigned yyst; /* state */
int yyfmin, yyfmax; /* yy_la_act indices of final states */
int yyoldi, yyoleng; /* base i, yyleng before look-ahead */
int yyeof; /* 1 if eof has already been read */
@ LOCAL DECLARATIONS @
#if !YY_STATIC_STDIO
if (yyin == (FILE *)0)
yyin = stdin;
if (yyout == (FILE *)0)
yyout = stdout;
#endif
#ifdef YYEXIT
yyLexFatal = 0;
#endif /* YYEXIT */
yyeof = 0;
i = yyleng;
YY_SCANNER;
yy_again:
yyleng = i;
/* determine previous char. */
if (i > 0)
yy_lastc = yytext[i-1];
/* scan previously accepted token adjusting yylineno */
while (i > 0)
if (yytext[--i] == YYNEWLINE)
yylineno++;
/* adjust pushback */
yy_end -= yyleng;
if (yy_end > 0)
memmove(yytext, yytext+yyleng, (size_t) yy_end);
i = 0;
yy_contin:
yyoldi = i;
/* run the state machine until it jams */
yyst = yy_begin[yy_start + ((yy_lastc == YYNEWLINE) ? 1 : 0)];
yy_sbuf[i] = (yy_state_t) yyst;
do {
YY_DEBUG(m_textmsg(1547, "<state %d, i = %d>\n", "I num1 num2"), yyst, i);
if (i >= YYLMAX) {
YY_FATAL(m_textmsg(1548, "Token buffer overflow", "E"));
#ifdef YYEXIT
if (yyLexFatal)
return -2;
#endif /* YYEXIT */
} /* endif */
/* get input char */
if (i < yy_end)
c = yytext[i]; /* get pushback char */
else if (!yyeof && (c = yygetc()) != EOF) {
yy_end = i+1;
yytext[i] = (char) c;
} else /* c == EOF */ {
c = EOF; /* just to make sure... */
if (i == yyoldi) { /* no token */
yyeof = 0;
if (yywrap())
return 0;
else
goto yy_again;
} else {
yyeof = 1; /* don't re-read EOF */
break;
}
}
YY_DEBUG(m_textmsg(1549, "<input %d = 0x%02x>\n", "I num hexnum"), c, c);
/* look up next state */
while ((yybase = yy_base[yyst]+(unsigned char)c) > yy_nxtmax
|| yy_check[yybase] != (yy_state_t) yyst) {
if (yyst == yy_endst)
goto yy_jammed;
yyst = yy_default[yyst];
}
yyst = yy_next[yybase];
yy_jammed: ;
yy_sbuf[++i] = (yy_state_t) yyst;
} while (!(yyst == yy_endst || YY_INTERACTIVE && yy_base[yyst] > yy_nxtmax && yy_default[yyst] == yy_endst));
YY_DEBUG(m_textmsg(1550, "<stopped %d, i = %d>\n", "I num1 num2"), yyst, i);
if (yyst != yy_endst)
++i;
yy_search:
/* search backward for a final state */
while (--i > yyoldi) {
yyst = yy_sbuf[i];
if ((yyfmin = yy_final[yyst]) < (yyfmax = yy_final[yyst+1]))
goto yy_found; /* found final state(s) */
}
/* no match, default action */
i = yyoldi + 1;
output(yytext[yyoldi]);
goto yy_again;
yy_found:
YY_DEBUG(m_textmsg(1551, "<final state %d, i = %d>\n", "I num1 num2"), yyst, i);
yyoleng = i; /* save length for REJECT */
/* pushback look-ahead RHS */
if ((c = (int)(yy_la_act[yyfmin]>>9) - 1) >= 0) { /* trailing context? */
unsigned char *bv = yy_look + c*YY_LA_SIZE;
static unsigned char bits [8] = {
1<<0, 1<<1, 1<<2, 1<<3, 1<<4, 1<<5, 1<<6, 1<<7
};
while (1) {
if (--i < yyoldi) { /* no / */
i = yyoleng;
break;
}
yyst = yy_sbuf[i];
if (bv[(unsigned)yyst/8] & bits[(unsigned)yyst%8])
break;
}
}
/* perform action */
yyleng = i;
YY_USER;
switch (yy_la_act[yyfmin] & 0777) {
@ ACTION CODE @
}
YY_SCANNER;
i = yyleng;
goto yy_again; /* action fell though */
yy_reject:
YY_SCANNER;
i = yyoleng; /* restore original yytext */
if (++yyfmin < yyfmax)
goto yy_found; /* another final state, same length */
else
goto yy_search; /* try shorter yytext */
yy_more:
YY_SCANNER;
i = yyleng;
if (i > 0)
yy_lastc = yytext[i-1];
goto yy_contin;
}
/*
* Safely switch input stream underneath LEX
*/
typedef struct yy_save_block_tag {
FILE * oldfp;
int oldline;
int oldend;
int oldstart;
int oldlastc;
int oldleng;
char savetext[YYLMAX+1];
yy_state_t savestate[YYLMAX+1];
} YY_SAVED;
void
yy_reset()
{
YY_INIT;
yylineno = 1; /* line number */
}
#if 0
YY_SAVED *
yySaveScan(fp)
FILE * fp;
{
YY_SAVED * p;
if ((p = (YY_SAVED *) malloc(sizeof(*p))) == NULL)
return p;
p->oldfp = yyin;
p->oldline = yylineno;
p->oldend = yy_end;
p->oldstart = yy_start;
p->oldlastc = yy_lastc;
p->oldleng = yyleng;
(void) memcpy(p->savetext, yytext, sizeof yytext);
(void) memcpy((char *) p->savestate, (char *) yy_sbuf,
sizeof yy_sbuf);
yyin = fp;
yylineno = 1;
YY_INIT;
return p;
}
/*f
* Restore previous LEX state
*/
void
yyRestoreScan(p)
YY_SAVED * p;
{
if (p == NULL)
return;
yyin = p->oldfp;
yylineno = p->oldline;
yy_end = p->oldend;
yy_start = p->oldstart;
yy_lastc = p->oldlastc;
yyleng = p->oldleng;
(void) memcpy(yytext, p->savetext, sizeof yytext);
(void) memcpy((char *) yy_sbuf, (char *) p->savestate,
sizeof yy_sbuf);
free(p);
}
/*
* User-callable re-initialization of yylex()
*/
/* get input char with pushback */
YY_DECL int
input()
{
int c;
#ifndef YY_PRESERVE
if (yy_end > yyleng) {
yy_end--;
memmove(yytext+yyleng, yytext+yyleng+1,
(size_t) (yy_end-yyleng));
c = yy_save;
YY_USER;
#else
if (yy_push < yy_save+YYLMAX) {
c = *yy_push++;
#endif
} else
c = yygetc();
yy_lastc = c;
if (c == YYNEWLINE)
yylineno++;
if (c == EOF) /* yygetc() can set c=EOF vsc4 wants c==EOF to return 0 */
return 0;
else
return c;
}
/*f
* pushback char
*/
YY_DECL int
unput(c)
int c;
{
#ifndef YY_PRESERVE
if (yy_end >= YYLMAX) {
YY_FATAL(m_textmsg(1552, "Push-back buffer overflow", "E"));
} else {
if (yy_end > yyleng) {
yytext[yyleng] = yy_save;
memmove(yytext+yyleng+1, yytext+yyleng,
(size_t) (yy_end-yyleng));
yytext[yyleng] = 0;
}
yy_end++;
yy_save = (char) c;
#else
if (yy_push <= yy_save) {
YY_FATAL(m_textmsg(1552, "Push-back buffer overflow", "E"));
} else {
*--yy_push = c;
#endif
if (c == YYNEWLINE)
yylineno--;
} /* endif */
return c;
}
#endif
@ end of yylex.c @

918
console/yyparse.c Normal file
View file

@ -0,0 +1,918 @@
#ifdef YYTRACE
#define YYDEBUG 1
#else
#ifndef YYDEBUG
#define YYDEBUG $Y
#endif
#endif
/*
* Portable way of defining ANSI C prototypes
*/
#ifndef YY_ARGS
#ifdef __STDC__
#define YY_ARGS(x) x
#else
#define YY_ARGS(x) ()
#endif
#endif
#ifdef YACC_WINDOWS
#include <windows.h>
/*
* the following is the handle to the current
* instance of a windows program. The user
* program calling yyparse must supply this!
*/
#ifdef STRICT
extern HINSTANCE hInst;
#else
extern HANDLE hInst;
#endif
#endif /* YACC_WINDOWS */
#if YYDEBUG
typedef struct yyNamedType_tag { /* Tokens */
char * name; /* printable name */
short token; /* token # */
short type; /* token type */
} yyNamedType;
typedef struct yyTypedRules_tag { /* Typed rule table */
char * name; /* compressed rule string */
short type; /* rule result type */
} yyTypedRules;
#endif
$@
#if YYDEBUG
/*
* Package up YACC context for tracing
*/
typedef struct yyTraceItems_tag {
int state, lookahead, errflag, done;
int rule, npop;
short * states;
int nstates;
YYSTYPE * values;
int nvalues;
short * types;
} yyTraceItems;
#endif
$L#line 2 "$P"
/*
* Copyright 1985, 1990 by Mortice Kern Systems Inc. All rights reserved.
*
* Automaton to interpret LALR(1) tables.
*
* Macros:
* yyclearin - clear the lookahead token.
* yyerrok - forgive a pending error
* YYERROR - simulate an error
* YYACCEPT - halt and return 0
* YYABORT - halt and return 1
* YYRETURN(value) - halt and return value. You should use this
* instead of return(value).
* YYREAD - ensure yychar contains a lookahead token by reading
* one if it does not. See also YYSYNC.
* YYRECOVERING - 1 if syntax error detected and not recovered
* yet; otherwise, 0.
*
* Preprocessor flags:
* YYDEBUG - includes debug code if 1. The parser will print
* a travelogue of the parse if this is defined as 1
* and yydebug is non-zero.
* yacc -t sets YYDEBUG to 1, but not yydebug.
* YYTRACE - turn on YYDEBUG, and undefine default trace functions
* so that the interactive functions in 'ytrack.c' will
* be used.
* YYSSIZE - size of state and value stacks (default 150).
* YYSTATIC - By default, the state stack is an automatic array.
* If this is defined, the stack will be static.
* In either case, the value stack is static.
* YYALLOC - Dynamically allocate both the state and value stacks
* by calling malloc() and free().
* YYDYNAMIC - Dynamically allocate (and reallocate, if necessary)
* both the state and value stacks by calling malloc(),
* realloc(), and free().
* YYSYNC - if defined, yacc guarantees to fetch a lookahead token
* before any action, even if it doesnt need it for a decision.
* If YYSYNC is defined, YYREAD will never be necessary unless
* the user explicitly sets yychar = -1
*
* Copyright (c) 1983, by the University of Waterloo
*/
/*
* Prototypes
*/
extern int yylex YY_ARGS((void));
extern void yyerror YY_ARGS((char *, ...));
#if YYDEBUG
#include <stdlib.h> /* common prototypes */
#include <string.h>
extern char * yyValue YY_ARGS((YYSTYPE, int)); /* print yylval */
extern void yyShowState YY_ARGS((yyTraceItems *));
extern void yyShowReduce YY_ARGS((yyTraceItems *));
extern void yyShowGoto YY_ARGS((yyTraceItems *));
extern void yyShowShift YY_ARGS((yyTraceItems *));
extern void yyShowErrRecovery YY_ARGS((yyTraceItems *));
extern void yyShowErrDiscard YY_ARGS((yyTraceItems *));
extern void yyShowRead YY_ARGS((int));
#endif
/*
* If YYDEBUG defined and yydebug set,
* tracing functions will be called at appropriate times in yyparse()
* Pass state of YACC parse, as filled into yyTraceItems yyx
* If yyx.done is set by the tracing function, yyparse() will terminate
* with a return value of -1
*/
#define YY_TRACE(fn) { \
yyx.state = yystate; yyx.lookahead = yychar; yyx.errflag =yyerrflag; \
yyx.states = yys+1; yyx.nstates = yyps-yys; \
yyx.values = yyv+1; yyx.nvalues = yypv-yyv; \
yyx.types = yytypev+1; yyx.done = 0; \
yyx.rule = yyi; yyx.npop = yyj; \
fn(&yyx); \
if (yyx.done) YYRETURN(-1); }
#ifndef I18N
#define m_textmsg(id, str, cls) (str)
#else /*I18N*/
#include <m_nls.h>
#endif/*I18N*/
#ifndef YYSSIZE
# define YYSSIZE 150
#endif
#ifdef YYDYNAMIC
#define YYALLOC
char *getenv();
int atoi();
int yysinc = -1; /* stack size increment, <0 = double, 0 = none, >0 = fixed */
#endif
#ifdef YYALLOC
int yyssize = YYSSIZE;
#endif
#define YYERROR goto yyerrlabel
#define yyerrok yyerrflag = 0
#if YYDEBUG
#define yyclearin { if (yydebug) yyShowRead(-1); yychar = -1; }
#else
#define yyclearin yychar = -1
#endif
#define YYACCEPT YYRETURN(0)
#define YYABORT YYRETURN(1)
#define YYRECOVERING() (yyerrflag != 0)
#ifdef YYALLOC
#define YYRETURN(val) { retval = (val); goto yyReturn; }
#else
#define YYRETURN(val) return(val);
#endif
#if YYDEBUG
/* The if..else makes this macro behave exactly like a statement */
# define YYREAD if (yychar < 0) { \
if ((yychar = yylex()) < 0) { \
if (yychar == -2) YYABORT; \
yychar = 0; \
} /* endif */ \
if (yydebug) \
yyShowRead(yychar); \
} else
#else
# define YYREAD if (yychar < 0) { \
if ((yychar = yylex()) < 0) { \
if (yychar == -2) YYABORT; \
yychar = 0; \
} /* endif */ \
} else
#endif
#define YYERRCODE $e /* value of `error' */
#define YYTOKEN_BASE 256
#define YYQYYP yyq[yyq-yyp]
/*
* Simulate bitwise negation as if was done on a two's complement machine.
* This makes the generated code portable to machines with different
* representations of integers (ie. signed magnitude).
*/
#define yyneg(s) (-((s)+1))
YYSTYPE yyval; /* $$ */
YYSTYPE *yypvt; /* $n */
YYSTYPE yylval; /* yylex() sets this */
int yychar, /* current token */
yyerrflag, /* error flag */
yynerrs; /* error count */
#if YYDEBUG
int yydebug = 0; /* debug if this flag is set */
extern char *yysvar[]; /* table of non-terminals (aka 'variables') */
extern yyNamedType yyTokenTypes[]; /* table of terminals & their types */
extern short yyrmap[], yysmap[]; /* map internal rule/states */
extern int yynstate, yynvar, yyntoken, yynrule;
extern int yyGetType YY_ARGS((int)); /* token type */
extern char *yyptok YY_ARGS((int)); /* printable token string */
extern int yyExpandName YY_ARGS((int, int, char *, int));
/* expand yyRules[] or yyStates[] */
static char * yygetState YY_ARGS((int));
#define yyassert(condition, msg, arg) \
if (!(condition)) { \
printf(m_textmsg(2824, "\nyacc bug: ", "E")); \
printf(msg, arg); \
YYABORT; }
#else /* !YYDEBUG */
#define yyassert(condition, msg, arg)
#endif
$T
#ifdef YACC_WINDOWS
/*
* the following is the yyparse() function that will be
* callable by a windows type program. It in turn will
* load all needed resources, obtain pointers to these
* resources, and call a statically defined function
* win_yyparse(), which is the original yyparse() fn
* When win_yyparse() is complete, it will return a
* value to the new yyparse(), where it will be stored
* away temporarily, all resources will be freed, and
* that return value will be given back to the caller
* yyparse(), as expected.
*/
static int win_yyparse(); /* prototype */
int yyparse()
{
int wReturnValue;
HANDLE hRes_table; /* handle of resource after loading */
short far *old_yydef; /* the following are used for saving */
short far *old_yyex; /* the current pointers */
short far *old_yyact;
short far *old_yypact;
short far *old_yygo;
short far *old_yypgo;
short far *old_yyrlen;
/*
* the following code will load the required
* resources for a Windows based parser.
*/
hRes_table = LoadResource (hInst,
FindResource (hInst, "UD_RES_yyYACC", "yyYACCTBL"));
/*
* return an error code if any
* of the resources did not load
*/
if (hRes_table == NULL)
return (1);
/*
* the following code will lock the resources
* into fixed memory locations for the parser
* (also, save the current pointer values first)
*/
old_yydef = yydef;
old_yyex = yyex;
old_yyact = yyact;
old_yypact = yypact;
old_yygo = yygo;
old_yypgo = yypgo;
old_yyrlen = yyrlen;
yydef = (short far *)LockResource (hRes_table);
yyex = (short far *)(yydef + Sizeof_yydef);
yyact = (short far *)(yyex + Sizeof_yyex);
yypact = (short far *)(yyact + Sizeof_yyact);
yygo = (short far *)(yypact + Sizeof_yypact);
yypgo = (short far *)(yygo + Sizeof_yygo);
yyrlen = (short far *)(yypgo + Sizeof_yypgo);
/*
* call the official yyparse() function
*/
wReturnValue = win_yyparse();
/*
* unlock the resources
*/
UnlockResource (hRes_table);
/*
* and now free the resource
*/
FreeResource (hRes_table);
/*
* restore previous pointer values
*/
yydef = old_yydef;
yyex = old_yyex;
yyact = old_yyact;
yypact = old_yypact;
yygo = old_yygo;
yypgo = old_yypgo;
yyrlen = old_yyrlen;
return (wReturnValue);
} /* end yyparse */
static int win_yyparse()
#else /* YACC_WINDOWS */
/*
* we are not compiling a windows resource
* based parser, so call yyparse() the old
* standard way.
*/
int yyparse()
#endif /* YACC_WINDOWS */
{
#ifdef YACC_WINDOWS
register short far *yyp; /* for table lookup */
register short far *yyq;
#else
register short *yyp; /* for table lookup */
register short *yyq;
#endif /* YACC_WINDOWS */
register short yyi;
register short *yyps; /* top of state stack */
register short yystate; /* current state */
register YYSTYPE *yypv; /* top of value stack */
register int yyj;
#if YYDEBUG
yyTraceItems yyx; /* trace block */
short * yytp;
int yyruletype = 0;
#endif
#ifdef YYSTATIC
static short yys[YYSSIZE + 1];
static YYSTYPE yyv[YYSSIZE + 1];
#if YYDEBUG
static short yytypev[YYSSIZE+1]; /* type assignments */
#endif
#else /* ! YYSTATIC */
#ifdef YYALLOC
YYSTYPE *yyv;
short *yys;
#if YYDEBUG
short *yytypev;
#endif
YYSTYPE save_yylval;
YYSTYPE save_yyval;
YYSTYPE *save_yypvt;
int save_yychar, save_yyerrflag, save_yynerrs;
int retval; /* return value holder */
#else
short yys[YYSSIZE + 1];
static YYSTYPE yyv[YYSSIZE + 1]; /* historically static */
#if YYDEBUG
short yytypev[YYSSIZE+1]; /* mirror type table */
#endif
#endif /* ! YYALLOC */
#endif /* ! YYSTATIC */
#ifdef YYDYNAMIC
char *envp;
#endif
$A
#ifdef YYDYNAMIC
if ((envp = getenv("YYSTACKSIZE")) != (char *)0) {
yyssize = atoi(envp);
if (yyssize <= 0)
yyssize = YYSSIZE;
}
if ((envp = getenv("YYSTACKINC")) != (char *)0)
yysinc = atoi(envp);
#endif
#ifdef YYALLOC
yys = (short *) malloc((yyssize + 1) * sizeof(short));
yyv = (YYSTYPE *) malloc((yyssize + 1) * sizeof(YYSTYPE));
#if YYDEBUG
yytypev = (short *) malloc((yyssize + 1) * sizeof(short));
#endif
if (yys == (short *)0 || yyv == (YYSTYPE *)0
#if YYDEBUG
|| yytypev == (short *) 0
#endif
) {
yyerror(m_textmsg(4967, "Not enough space for parser stacks",
"E"));
return 1;
}
save_yylval = yylval;
save_yyval = yyval;
save_yypvt = yypvt;
save_yychar = yychar;
save_yyerrflag = yyerrflag;
save_yynerrs = yynerrs;
#endif
yynerrs = 0;
yyerrflag = 0;
yyclearin;
yyps = yys;
yypv = yyv;
*yyps = yystate = YYS0; /* start state */
#if YYDEBUG
yytp = yytypev;
yyi = yyj = 0; /* silence compiler warnings */
#endif
yyStack:
yyassert((unsigned)yystate < yynstate, m_textmsg(587, "state %d\n", ""), yystate);
#ifdef YYDYNAMIC
if (++yyps > &yys[yyssize]) {
int yynewsize;
int yysindex = yyps - yys;
int yyvindex = yypv - yyv;
#if YYDEBUG
int yytindex = yytp - yytypev;
#endif
if (yysinc == 0) { /* no increment */
yyerror(m_textmsg(4968, "Parser stack overflow", "E"));
YYABORT;
} else if (yysinc < 0) /* binary-exponential */
yynewsize = yyssize * 2;
else /* fixed increment */
yynewsize = yyssize + yysinc;
if (yynewsize < yyssize) {
yyerror(m_textmsg(4967,
"Not enough space for parser stacks",
"E"));
YYABORT;
}
yyssize = yynewsize;
yys = (short *) realloc(yys, (yyssize + 1) * sizeof(short));
yyps = yys + yysindex;
yyv = (YYSTYPE *) realloc(yyv, (yyssize + 1) * sizeof(YYSTYPE));
yypv = yyv + yyvindex;
#if YYDEBUG
yytypev = (short *)realloc(yytypev,(yyssize + 1)*sizeof(short));
yytp = yytypev + yytindex;
#endif
if (yys == (short *)0 || yyv == (YYSTYPE *)0
#if YYDEBUG
|| yytypev == (short *) 0
#endif
) {
yyerror(m_textmsg(4967,
"Not enough space for parser stacks",
"E"));
YYABORT;
}
}
#else
if (++yyps > &yys[YYSSIZE]) {
yyerror(m_textmsg(4968, "Parser stack overflow", "E"));
YYABORT;
}
#endif /* !YYDYNAMIC */
*yyps = yystate; /* stack current state */
*++yypv = yyval; /* ... and value */
#if YYDEBUG
*++yytp = yyruletype; /* ... and type */
if (yydebug)
YY_TRACE(yyShowState)
#endif
/*
* Look up next action in action table.
*/
yyEncore:
#ifdef YYSYNC
YYREAD;
#endif
#ifdef YACC_WINDOWS
if (yystate >= Sizeof_yypact) /* simple state */
#else /* YACC_WINDOWS */
if (yystate >= sizeof yypact/sizeof yypact[0]) /* simple state */
#endif /* YACC_WINDOWS */
yyi = yystate - YYDELTA; /* reduce in any case */
else {
if(*(yyp = &yyact[yypact[yystate]]) >= 0) {
/* Look for a shift on yychar */
#ifndef YYSYNC
YYREAD;
#endif
yyq = yyp;
yyi = yychar;
while (yyi < *yyp++)
;
if (yyi == yyp[-1]) {
yystate = yyneg(YYQYYP);
#if YYDEBUG
if (yydebug) {
yyruletype = yyGetType(yychar);
YY_TRACE(yyShowShift)
}
#endif
yyval = yylval; /* stack what yylex() set */
yyclearin; /* clear token */
if (yyerrflag)
yyerrflag--; /* successful shift */
goto yyStack;
}
}
/*
* Fell through - take default action
*/
#ifdef YACC_WINDOWS
if (yystate >= Sizeof_yydef)
#else /* YACC_WINDOWS */
if (yystate >= sizeof yydef /sizeof yydef[0])
#endif /* YACC_WINDOWS */
goto yyError;
if ((yyi = yydef[yystate]) < 0) { /* default == reduce? */
/* Search exception table */
#ifdef YACC_WINDOWS
yyassert((unsigned)yyneg(yyi) < Sizeof_yyex,
m_textmsg(2825, "exception %d\n", "I num"), yystate);
#else /* YACC_WINDOWS */
yyassert((unsigned)yyneg(yyi) < sizeof yyex/sizeof yyex[0],
m_textmsg(2825, "exception %d\n", "I num"), yystate);
#endif /* YACC_WINDOWS */
yyp = &yyex[yyneg(yyi)];
#ifndef YYSYNC
YYREAD;
#endif
while((yyi = *yyp) >= 0 && yyi != yychar)
yyp += 2;
yyi = yyp[1];
yyassert(yyi >= 0,
m_textmsg(2826, "Ex table not reduce %d\n", "I num"), yyi);
}
}
yyassert((unsigned)yyi < yynrule, m_textmsg(2827, "reduce %d\n", "I num"), yyi);
yyj = yyrlen[yyi];
#if YYDEBUG
if (yydebug)
YY_TRACE(yyShowReduce)
yytp -= yyj;
#endif
yyps -= yyj; /* pop stacks */
yypvt = yypv; /* save top */
yypv -= yyj;
yyval = yypv[1]; /* default action $$ = $1 */
#if YYDEBUG
yyruletype = yyRules[yyrmap[yyi]].type;
#endif
switch (yyi) { /* perform semantic action */
$A
$L#line 314 "$P"
case YYrACCEPT:
YYACCEPT;
case YYrERROR:
goto yyError;
}
/*
* Look up next state in goto table.
*/
yyp = &yygo[yypgo[yyi]];
yyq = yyp++;
yyi = *yyps;
while (yyi < *yyp++)
;
yystate = yyneg(yyi == *--yyp? YYQYYP: *yyq);
#if YYDEBUG
if (yydebug)
YY_TRACE(yyShowGoto)
#endif
goto yyStack;
yyerrlabel: ; /* come here from YYERROR */
/*
#pragma used yyerrlabel
*/
yyerrflag = 1;
if (yyi == YYrERROR) {
yyps--;
yypv--;
#if YYDEBUG
yytp--;
#endif
}
yyError:
switch (yyerrflag) {
case 0: /* new error */
yynerrs++;
yyi = yychar;
yyerror(m_textmsg(4969, "Syntax error", "E"));
if (yyi != yychar) {
/* user has changed the current token */
/* try again */
yyerrflag++; /* avoid loops */
goto yyEncore;
}
case 1: /* partially recovered */
case 2:
yyerrflag = 3; /* need 3 valid shifts to recover */
/*
* Pop states, looking for a
* shift on `error'.
*/
for ( ; yyps > yys; yyps--, yypv--
#if YYDEBUG
, yytp--
#endif
) {
#ifdef YACC_WINDOWS
if (*yyps >= Sizeof_yypact)
#else /* YACC_WINDOWS */
if (*yyps >= sizeof yypact/sizeof yypact[0])
#endif /* YACC_WINDOWS */
continue;
yyp = &yyact[yypact[*yyps]];
yyq = yyp;
do {
if (YYERRCODE == *yyp) {
yyp++;
yystate = yyneg(YYQYYP);
goto yyStack;
}
} while (*yyp++ > YYTOKEN_BASE);
/* no shift in this state */
#if YYDEBUG
if (yydebug && yyps > yys+1)
YY_TRACE(yyShowErrRecovery)
#endif
/* pop stacks; try again */
}
/* no shift on error - abort */
break;
case 3:
/*
* Erroneous token after
* an error - discard it.
*/
if (yychar == 0) /* but not EOF */
break;
#if YYDEBUG
if (yydebug)
YY_TRACE(yyShowErrDiscard)
#endif
yyclearin;
goto yyEncore; /* try again in same state */
}
YYABORT;
#ifdef YYALLOC
yyReturn:
yylval = save_yylval;
yyval = save_yyval;
yypvt = save_yypvt;
yychar = save_yychar;
yyerrflag = save_yyerrflag;
yynerrs = save_yynerrs;
free((char *)yys);
free((char *)yyv);
#if YYDEBUG
free((char *)yytypev);
#endif
return(retval);
#endif
}
#if YYDEBUG
/*
* Return type of token
*/
int
yyGetType(tok)
int tok;
{
yyNamedType * tp;
for (tp = &yyTokenTypes[yyntoken-1]; tp > yyTokenTypes; tp--)
if (tp->token == tok)
return tp->type;
return 0;
}
/*
* Print a token legibly.
*/
char *
yyptok(tok)
int tok;
{
yyNamedType * tp;
for (tp = &yyTokenTypes[yyntoken-1]; tp > yyTokenTypes; tp--)
if (tp->token == tok)
return tp->name;
return "";
}
/*
* Read state 'num' from YYStatesFile
*/
#ifdef YYTRACE
static char *
yygetState(num)
int num;
{
int size;
static FILE *yyStatesFile = (FILE *) 0;
static char yyReadBuf[YYMAX_READ+1];
if (yyStatesFile == (FILE *) 0
&& (yyStatesFile = fopen(YYStatesFile, "r")) == (FILE *) 0)
return "yyExpandName: cannot open states file";
if (num < yynstate - 1)
size = (int)(yyStates[num+1] - yyStates[num]);
else {
/* length of last item is length of file - ptr(last-1) */
if (fseek(yyStatesFile, 0L, 2) < 0)
goto cannot_seek;
size = (int) (ftell(yyStatesFile) - yyStates[num]);
}
if (size < 0 || size > YYMAX_READ)
return "yyExpandName: bad read size";
if (fseek(yyStatesFile, yyStates[num], 0) < 0) {
cannot_seek:
return "yyExpandName: cannot seek in states file";
}
(void) fread(yyReadBuf, 1, size, yyStatesFile);
yyReadBuf[size] = '\0';
return yyReadBuf;
}
#endif /* YYTRACE */
/*
* Expand encoded string into printable representation
* Used to decode yyStates and yyRules strings.
* If the expansion of 's' fits in 'buf', return 1; otherwise, 0.
*/
int
yyExpandName(num, isrule, buf, len)
int num, isrule;
char * buf;
int len;
{
int i, n, cnt, type;
char * endp, * cp;
char *s;
if (isrule)
s = yyRules[num].name;
else
#ifdef YYTRACE
s = yygetState(num);
#else
s = "*no states*";
#endif
for (endp = buf + len - 8; *s; s++) {
if (buf >= endp) { /* too large: return 0 */
full: (void) strcpy(buf, " ...\n");
return 0;
} else if (*s == '%') { /* nonterminal */
type = 0;
cnt = yynvar;
goto getN;
} else if (*s == '&') { /* terminal */
type = 1;
cnt = yyntoken;
getN:
if (cnt < 100)
i = 2;
else if (cnt < 1000)
i = 3;
else
i = 4;
for (n = 0; i-- > 0; )
n = (n * 10) + *++s - '0';
if (type == 0) {
if (n >= yynvar)
goto too_big;
cp = yysvar[n];
} else if (n >= yyntoken) {
too_big:
cp = "<range err>";
} else
cp = yyTokenTypes[n].name;
if ((i = strlen(cp)) + buf > endp)
goto full;
(void) strcpy(buf, cp);
buf += i;
} else
*buf++ = *s;
}
*buf = '\0';
return 1;
}
#ifndef YYTRACE
/*
* Show current state of yyparse
*/
void
yyShowState(tp)
yyTraceItems * tp;
{
short * p;
YYSTYPE * q;
printf(
m_textmsg(2828, "state %d (%d), char %s (%d)\n", "I num1 num2 char num3"),
yysmap[tp->state], tp->state,
yyptok(tp->lookahead), tp->lookahead);
}
/*
* show results of reduction
*/
void
yyShowReduce(tp)
yyTraceItems * tp;
{
printf("reduce %d (%d), pops %d (%d)\n",
yyrmap[tp->rule], tp->rule,
tp->states[tp->nstates - tp->npop],
yysmap[tp->states[tp->nstates - tp->npop]]);
}
void
yyShowRead(val)
int val;
{
printf(m_textmsg(2829, "read %s (%d)\n", "I token num"), yyptok(val), val);
}
void
yyShowGoto(tp)
yyTraceItems * tp;
{
printf(m_textmsg(2830, "goto %d (%d)\n", "I num1 num2"), yysmap[tp->state], tp->state);
}
void
yyShowShift(tp)
yyTraceItems * tp;
{
printf(m_textmsg(2831, "shift %d (%d)\n", "I num1 num2"), yysmap[tp->state], tp->state);
}
void
yyShowErrRecovery(tp)
yyTraceItems * tp;
{
short * top = tp->states + tp->nstates - 1;
printf(
m_textmsg(2832, "Error recovery pops state %d (%d), uncovers %d (%d)\n", "I num1 num2 num3 num4"),
yysmap[*top], *top, yysmap[*(top-1)], *(top-1));
}
void
yyShowErrDiscard(tp)
yyTraceItems * tp;
{
printf(m_textmsg(2833, "Error recovery discards %s (%d), ", "I token num"),
yyptok(tp->lookahead), tp->lookahead);
}
#endif /* ! YYTRACE */
#endif /* YYDEBUG */