Scripting Engine Update:
-added simple function support Limitations: -void return type only -no arguments support Example: function void myFunc() {<code>} git-svn-id: svn+ssh://svn.gna.org/svn/warzone/trunk@557 4a71c877-e1ca-e34f-864e-861f7616d084master
parent
8adf85a21b
commit
223ea92358
|
@ -25,7 +25,7 @@ static BOOL enabled_debug_parts[LOG_LAST];
|
|||
/* This list _must_ match the enum in debug.h! */
|
||||
static const char *code_part_names[] = {
|
||||
"all", "main", "sound", "video", "wz", "3d", "texture",
|
||||
"net", "memory", "error", "never", "last"
|
||||
"net", "memory", "error", "never", "script", "last"
|
||||
};
|
||||
|
||||
/**********************************************************************
|
||||
|
|
|
@ -214,6 +214,7 @@ do { \
|
|||
#define wz__attribute(x)
|
||||
#endif
|
||||
|
||||
/* Must match code_part_names in debug.c */
|
||||
enum code_part {
|
||||
LOG_ALL, /* special: sets all to on */
|
||||
LOG_MAIN,
|
||||
|
@ -226,6 +227,7 @@ enum code_part {
|
|||
LOG_MEMORY,
|
||||
LOG_ERROR, /* special; on by default */
|
||||
LOG_NEVER, /* if too verbose for anything but dedicated debugging... */
|
||||
LOG_SCRIPT,
|
||||
LOG_LAST /* _must_ be last! */
|
||||
};
|
||||
|
||||
|
|
|
@ -216,6 +216,9 @@ BOOL interpRunScript(SCRIPT_CONTEXT *psContext, INTERP_RUNTYPE runType, UDWORD i
|
|||
// SDWORD arrayIndex, dimensions, arrayElements[VAR_MAX_DIMENSIONS];
|
||||
SDWORD instructionCount = 0;
|
||||
|
||||
UDWORD CurEvent;
|
||||
BOOL bStop;
|
||||
|
||||
ASSERT((PTRVALID(psContext, sizeof(SCRIPT_CONTEXT)),
|
||||
"interpRunScript: invalid context pointer"));
|
||||
psProg=psContext->psCode;
|
||||
|
@ -236,6 +239,9 @@ BOOL interpRunScript(SCRIPT_CONTEXT *psContext, INTERP_RUNTYPE runType, UDWORD i
|
|||
// Reset the stack in case another script messed up
|
||||
stackReset();
|
||||
|
||||
//reset return stack
|
||||
retStackReset();
|
||||
|
||||
// Turn off tracing initially
|
||||
interpTrace = FALSE;
|
||||
|
||||
|
@ -276,276 +282,357 @@ BOOL interpRunScript(SCRIPT_CONTEXT *psContext, INTERP_RUNTYPE runType, UDWORD i
|
|||
opcode = (*ip) >> OPCODE_SHIFT;
|
||||
instructionCount = 0;
|
||||
|
||||
// Run the code
|
||||
while (ip < pCodeEnd)// && opcode != OP_EXIT)
|
||||
{
|
||||
if (instructionCount > INTERP_MAXINSTRUCTIONS)
|
||||
{
|
||||
ASSERT((FALSE,
|
||||
"interpRunScript: max instruction count exceeded - infinite loop ?"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
instructionCount += 1;
|
||||
CurEvent = index;
|
||||
bStop = FALSE;
|
||||
|
||||
TRCPRINTF(("%-6d ", ip - psProg->pCode));
|
||||
opcode = (*ip) >> OPCODE_SHIFT;
|
||||
data = (*ip) & OPCODE_DATAMASK;
|
||||
switch (opcode)
|
||||
while(!bStop)
|
||||
{
|
||||
// Run the code
|
||||
if (ip < pCodeEnd)// && opcode != OP_EXIT)
|
||||
{
|
||||
case OP_PUSH:
|
||||
// The type of the value is stored in with the opcode
|
||||
sVal.type = (*ip) & OPCODE_DATAMASK;
|
||||
// Copy the data as a DWORD
|
||||
sVal.v.ival = (SDWORD)(*(ip+1));
|
||||
TRCPRINTF(("PUSH "));
|
||||
TRCPRINTVAL(&sVal);
|
||||
TRCPRINTF(("\n"));
|
||||
if (!stackPush(&sVal))
|
||||
if (instructionCount > INTERP_MAXINSTRUCTIONS)
|
||||
{
|
||||
// Eeerk, out of memory
|
||||
ASSERT((FALSE, "interpRunScript: out of memory!"));
|
||||
ASSERT((FALSE,
|
||||
"interpRunScript: max instruction count exceeded - infinite loop ?"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
ip += aOpSize[opcode];
|
||||
break;
|
||||
case OP_PUSHREF:
|
||||
// The type of the variable is stored in with the opcode
|
||||
sVal.type = (*ip) & OPCODE_DATAMASK;
|
||||
// store the pointer
|
||||
psVar = interpGetVarData(psGlobals, *(ip + 1));
|
||||
sVal.v.oval = &(psVar->v.ival);
|
||||
TRCPRINTF(("PUSHREF "));
|
||||
TRCPRINTVAL(&sVal);
|
||||
TRCPRINTF(("\n"));
|
||||
if (!stackPush(&sVal))
|
||||
{
|
||||
// Eeerk, out of memory
|
||||
ASSERT((FALSE, "interpRunScript: out of memory!"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
ip += aOpSize[opcode];
|
||||
break;
|
||||
case OP_POP:
|
||||
TRCPRINTF(("POP\n"));
|
||||
if (!stackPop(&sVal))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do stack pop"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
ip += aOpSize[opcode];
|
||||
break;
|
||||
case OP_BINARYOP:
|
||||
TRCPRINTMATHSOP(data);
|
||||
if (!stackBinaryOp((OPCODE)data))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do binary op"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
TRCPRINTSTACKTOP();
|
||||
TRCPRINTF(("\n"));
|
||||
ip += aOpSize[opcode];
|
||||
break;
|
||||
case OP_UNARYOP:
|
||||
TRCPRINTMATHSOP(data);
|
||||
if (!stackUnaryOp((OPCODE)data))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do unary op"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
TRCPRINTSTACKTOP();
|
||||
TRCPRINTF(("\n"));
|
||||
ip += aOpSize[opcode];
|
||||
break;
|
||||
case OP_PUSHGLOBAL:
|
||||
TRCPRINTF(("PUSHGLOBAL %d\n", data));
|
||||
if (data >= numGlobals)
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: variable index out of range"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
if (!stackPush(interpGetVarData(psGlobals, data)))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do stack push"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
ip += aOpSize[opcode];
|
||||
break;
|
||||
case OP_POPGLOBAL:
|
||||
TRCPRINTF(("POPGLOBAL %d ", data));
|
||||
TRCPRINTSTACKTOP();
|
||||
TRCPRINTF(("\n"));
|
||||
if (data >= numGlobals)
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: variable index out of range"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
if (!stackPopType(interpGetVarData(psGlobals, data)))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do stack pop"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
ip += aOpSize[opcode];
|
||||
break;
|
||||
case OP_PUSHARRAYGLOBAL:
|
||||
// get the number of array elements
|
||||
// arrayElements = (data & ARRAY_ELEMENT_MASK) >> ARRAY_ELEMENT_SHIFT;
|
||||
// data = data & ARRAY_INDEX_MASK;
|
||||
// get the array index
|
||||
// if (!stackPopParams(1, VAL_INT, &arrayIndex))
|
||||
// {
|
||||
// goto exit_with_error;
|
||||
// }
|
||||
// TRCPRINTF(("PUSHARRAYGLOBAL [%d] %d(+%d)\n", arrayIndex, data, arrayElements));
|
||||
// if (data + arrayElements > numGlobals)
|
||||
// {
|
||||
// ASSERT((FALSE, "interpRunScript: variable index out of range"));
|
||||
// goto exit_with_error;
|
||||
// }
|
||||
// if (arrayIndex < 0 || arrayIndex >= arrayElements)
|
||||
// {
|
||||
// ASSERT((FALSE, "interpRunScript: array index out of range"));
|
||||
// goto exit_with_error;
|
||||
// }
|
||||
TRCPRINTF(("PUSHARRAYGLOBAL "));
|
||||
if (!interpGetArrayVarData(&ip, psGlobals, psProg, &psVar))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not get array var data"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
TRCPRINTF(("\n"));
|
||||
if (!stackPush(psVar))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do stack push"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
break;
|
||||
case OP_POPARRAYGLOBAL:
|
||||
// get the number of array elements
|
||||
// arrayElements = (data & ARRAY_ELEMENT_MASK) >> ARRAY_ELEMENT_SHIFT;
|
||||
// data = data & ARRAY_INDEX_MASK;
|
||||
// get the array index
|
||||
/* if (!stackPopParams(1, VAL_INT, &arrayIndex))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do pop of params"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
TRCPRINTF(("POPARRAYGLOBAL [%d] %d(+%d) ", arrayIndex, data, arrayElements));
|
||||
TRCPRINTSTACKTOP();
|
||||
TRCPRINTF(("\n"));
|
||||
if (data + arrayElements > numGlobals)
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: variable index out of range"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
if (arrayIndex < 0 || arrayIndex >= arrayElements)
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: array index out of range"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
if (!stackPopType(interpGetVarData(psGlobals, data + arrayIndex)))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do pop stack of type"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
ip += aOpSize[opcode];*/
|
||||
TRCPRINTF(("POPARRAYGLOBAL "));
|
||||
if (!interpGetArrayVarData(&ip, psGlobals, psProg, &psVar))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not get array var data"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
TRCPRINTSTACKTOP();
|
||||
TRCPRINTF(("\n"));
|
||||
if (!stackPopType(psVar))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do pop stack of type"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
break;
|
||||
case OP_JUMPFALSE:
|
||||
TRCPRINTF(("JUMPFALSE %d (%d)",
|
||||
(SWORD)data, ip - psProg->pCode + (SWORD)data));
|
||||
if (!stackPop(&sVal))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do pop of stack"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
if (!sVal.v.bval)
|
||||
instructionCount += 1;
|
||||
|
||||
TRCPRINTF(("%-6d ", ip - psProg->pCode));
|
||||
opcode = (*ip) >> OPCODE_SHIFT;
|
||||
data = (*ip) & OPCODE_DATAMASK;
|
||||
switch (opcode)
|
||||
{
|
||||
/* Custom function call */
|
||||
case OP_FUNC:
|
||||
debug( LOG_SCRIPT, "OP_FUNC" );
|
||||
if(!RetStackRemember(CurEvent, (UDWORD)(ip + 2))) //Remember where to jump back later
|
||||
{
|
||||
debug( LOG_ERROR, "interpRunScript() - RetStackRemember() failed.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CurEvent = *(ip+1); //Current event = event to jump to
|
||||
|
||||
if (CurEvent > psProg->numEvents)
|
||||
{
|
||||
debug( LOG_ERROR, "interpRunScript: trigger index out of range");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//Set new code execution boundries
|
||||
//----------------------------------
|
||||
pCodeBase = psProg->pCode + psProg->pEventTab[CurEvent];
|
||||
pCodeStart = pCodeBase;
|
||||
pCodeEnd = psProg->pCode + psProg->pEventTab[CurEvent+1];
|
||||
|
||||
ip = pCodeStart; //Start at the beginning of the new event
|
||||
|
||||
break;
|
||||
|
||||
case OP_PUSH:
|
||||
// The type of the value is stored in with the opcode
|
||||
sVal.type = (*ip) & OPCODE_DATAMASK;
|
||||
// Copy the data as a DWORD
|
||||
sVal.v.ival = (SDWORD)(*(ip+1));
|
||||
TRCPRINTF(("PUSH "));
|
||||
TRCPRINTVAL(&sVal);
|
||||
TRCPRINTF(("\n"));
|
||||
if (!stackPush(&sVal))
|
||||
{
|
||||
// Eeerk, out of memory
|
||||
ASSERT((FALSE, "interpRunScript: out of memory!"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
ip += aOpSize[opcode];
|
||||
break;
|
||||
case OP_PUSHREF:
|
||||
// The type of the variable is stored in with the opcode
|
||||
sVal.type = (*ip) & OPCODE_DATAMASK;
|
||||
// store the pointer
|
||||
psVar = interpGetVarData(psGlobals, *(ip + 1));
|
||||
sVal.v.oval = &(psVar->v.ival);
|
||||
TRCPRINTF(("PUSHREF "));
|
||||
TRCPRINTVAL(&sVal);
|
||||
TRCPRINTF(("\n"));
|
||||
if (!stackPush(&sVal))
|
||||
{
|
||||
// Eeerk, out of memory
|
||||
ASSERT((FALSE, "interpRunScript: out of memory!"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
ip += aOpSize[opcode];
|
||||
break;
|
||||
case OP_POP:
|
||||
TRCPRINTF(("POP\n"));
|
||||
if (!stackPop(&sVal))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do stack pop"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
ip += aOpSize[opcode];
|
||||
break;
|
||||
case OP_BINARYOP:
|
||||
TRCPRINTMATHSOP(data);
|
||||
if (!stackBinaryOp((OPCODE)data))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do binary op"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
TRCPRINTSTACKTOP();
|
||||
TRCPRINTF(("\n"));
|
||||
ip += aOpSize[opcode];
|
||||
break;
|
||||
case OP_UNARYOP:
|
||||
TRCPRINTMATHSOP(data);
|
||||
if (!stackUnaryOp((OPCODE)data))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do unary op"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
TRCPRINTSTACKTOP();
|
||||
TRCPRINTF(("\n"));
|
||||
ip += aOpSize[opcode];
|
||||
break;
|
||||
case OP_PUSHGLOBAL:
|
||||
TRCPRINTF(("PUSHGLOBAL %d\n", data));
|
||||
if (data >= numGlobals)
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: variable index out of range"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
if (!stackPush(interpGetVarData(psGlobals, data)))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do stack push"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
ip += aOpSize[opcode];
|
||||
break;
|
||||
case OP_POPGLOBAL:
|
||||
TRCPRINTF(("POPGLOBAL %d ", data));
|
||||
TRCPRINTSTACKTOP();
|
||||
TRCPRINTF(("\n"));
|
||||
if (data >= numGlobals)
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: variable index out of range"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
if (!stackPopType(interpGetVarData(psGlobals, data)))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do stack pop"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
ip += aOpSize[opcode];
|
||||
break;
|
||||
case OP_PUSHARRAYGLOBAL:
|
||||
// get the number of array elements
|
||||
// arrayElements = (data & ARRAY_ELEMENT_MASK) >> ARRAY_ELEMENT_SHIFT;
|
||||
// data = data & ARRAY_INDEX_MASK;
|
||||
// get the array index
|
||||
// if (!stackPopParams(1, VAL_INT, &arrayIndex))
|
||||
// {
|
||||
// goto exit_with_error;
|
||||
// }
|
||||
// TRCPRINTF(("PUSHARRAYGLOBAL [%d] %d(+%d)\n", arrayIndex, data, arrayElements));
|
||||
// if (data + arrayElements > numGlobals)
|
||||
// {
|
||||
// ASSERT((FALSE, "interpRunScript: variable index out of range"));
|
||||
// goto exit_with_error;
|
||||
// }
|
||||
// if (arrayIndex < 0 || arrayIndex >= arrayElements)
|
||||
// {
|
||||
// ASSERT((FALSE, "interpRunScript: array index out of range"));
|
||||
// goto exit_with_error;
|
||||
// }
|
||||
TRCPRINTF(("PUSHARRAYGLOBAL "));
|
||||
if (!interpGetArrayVarData(&ip, psGlobals, psProg, &psVar))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not get array var data"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
TRCPRINTF(("\n"));
|
||||
if (!stackPush(psVar))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do stack push"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
break;
|
||||
case OP_POPARRAYGLOBAL:
|
||||
// get the number of array elements
|
||||
// arrayElements = (data & ARRAY_ELEMENT_MASK) >> ARRAY_ELEMENT_SHIFT;
|
||||
// data = data & ARRAY_INDEX_MASK;
|
||||
// get the array index
|
||||
/* if (!stackPopParams(1, VAL_INT, &arrayIndex))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do pop of params"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
TRCPRINTF(("POPARRAYGLOBAL [%d] %d(+%d) ", arrayIndex, data, arrayElements));
|
||||
TRCPRINTSTACKTOP();
|
||||
TRCPRINTF(("\n"));
|
||||
if (data + arrayElements > numGlobals)
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: variable index out of range"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
if (arrayIndex < 0 || arrayIndex >= arrayElements)
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: array index out of range"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
if (!stackPopType(interpGetVarData(psGlobals, data + arrayIndex)))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do pop stack of type"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
ip += aOpSize[opcode];*/
|
||||
TRCPRINTF(("POPARRAYGLOBAL "));
|
||||
if (!interpGetArrayVarData(&ip, psGlobals, psProg, &psVar))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not get array var data"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
TRCPRINTSTACKTOP();
|
||||
TRCPRINTF(("\n"));
|
||||
if (!stackPopType(psVar))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do pop stack of type"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
break;
|
||||
case OP_JUMPFALSE:
|
||||
TRCPRINTF(("JUMPFALSE %d (%d)",
|
||||
(SWORD)data, ip - psProg->pCode + (SWORD)data));
|
||||
if (!stackPop(&sVal))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do pop of stack"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
if (!sVal.v.bval)
|
||||
{
|
||||
// Do the jump
|
||||
TRCPRINTF((" - done -\n"));
|
||||
ip += (SWORD)data;
|
||||
if (ip < pCodeStart || ip > pCodeEnd)
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: jump out of range"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TRCPRINTF(("\n"));
|
||||
ip += aOpSize[opcode];
|
||||
}
|
||||
break;
|
||||
case OP_JUMP:
|
||||
TRCPRINTF(("JUMP %d (%d)\n",
|
||||
(SWORD)data, ip - psProg->pCode + (SWORD)data));
|
||||
// Do the jump
|
||||
TRCPRINTF((" - done -\n"));
|
||||
ip += (SWORD)data;
|
||||
if (ip < pCodeStart || ip > pCodeEnd)
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: jump out of range"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
break;
|
||||
case OP_CALL:
|
||||
TRCPRINTF(("CALL "));
|
||||
TRCPRINTFUNC( (SCRIPT_FUNC)(*(ip+1)) );
|
||||
TRCPRINTF(("\n"));
|
||||
scriptFunc = (SCRIPT_FUNC)*(ip+1);
|
||||
if (!scriptFunc())
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do func"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
ip += aOpSize[opcode];
|
||||
break;
|
||||
case OP_VARCALL:
|
||||
TRCPRINTF(("VARCALL "));
|
||||
TRCPRINTVARFUNC( (SCRIPT_VARFUNC)(*(ip+1)), data );
|
||||
TRCPRINTF(("(%d)\n", data));
|
||||
scriptVarFunc = (SCRIPT_VARFUNC)*(ip+1);
|
||||
if (!scriptVarFunc(data))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do var func"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
ip += aOpSize[opcode];
|
||||
break;
|
||||
case OP_EXIT:
|
||||
// jump out of the code
|
||||
ip = pCodeEnd;
|
||||
break;
|
||||
case OP_PAUSE:
|
||||
TRCPRINTF(("PAUSE %d\n", data));
|
||||
ASSERT((stackEmpty(),
|
||||
"interpRunScript: OP_PAUSE without empty stack"));
|
||||
ip += aOpSize[opcode];
|
||||
// tell the event system to reschedule this event
|
||||
if (!eventAddPauseTrigger(psContext, index, ip - pCodeBase, data))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not add pause trigger"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
// now jump out of the event
|
||||
ip = pCodeEnd;
|
||||
break;
|
||||
default:
|
||||
ASSERT((FALSE, "interpRunScript: unknown opcode"));
|
||||
goto exit_with_error;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else //End of the event reached, see if we have to jump back to the caller function or just exit
|
||||
{
|
||||
|
||||
//reset local vars
|
||||
//if(!resetLocalVars(psProg, CurEvent))
|
||||
// goto exit_with_error;
|
||||
|
||||
if(!IsRetStackEmpty()) //There was a caller function before this one
|
||||
{
|
||||
if(!PopRetStack(&ip)) //Pop return address
|
||||
{
|
||||
debug( LOG_ERROR, "interpRunScript() - PopRetStack(): failed to pop return adress.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(!PopRetStack(&CurEvent)) //Pop event index
|
||||
{
|
||||
debug( LOG_ERROR, "interpRunScript() - PopRetStack(): failed to pop return event index.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
debug( LOG_SCRIPT, "RETURN" );
|
||||
|
||||
//Set new boundries
|
||||
//--------------------------
|
||||
pCodeBase = psProg->pCode + psProg->pEventTab[CurEvent];
|
||||
if(CurEvent == index) //If it's the original event, then also use the offset passed
|
||||
{pCodeStart = pCodeBase + offset;}
|
||||
else
|
||||
{pCodeStart = pCodeBase;}
|
||||
pCodeEnd = psProg->pCode + psProg->pEventTab[CurEvent+1];
|
||||
}
|
||||
else
|
||||
{
|
||||
TRCPRINTF(("\n"));
|
||||
ip += aOpSize[opcode];
|
||||
//reset local vars
|
||||
//if(!resetLocalVars(psProg, index))
|
||||
// goto exit_with_error;
|
||||
|
||||
bStop = TRUE; //Stop execution of this event here, no more calling functions stored
|
||||
}
|
||||
break;
|
||||
case OP_JUMP:
|
||||
TRCPRINTF(("JUMP %d (%d)\n",
|
||||
(SWORD)data, ip - psProg->pCode + (SWORD)data));
|
||||
// Do the jump
|
||||
ip += (SWORD)data;
|
||||
if (ip < pCodeStart || ip > pCodeEnd)
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: jump out of range"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
break;
|
||||
case OP_CALL:
|
||||
TRCPRINTF(("CALL "));
|
||||
TRCPRINTFUNC( (SCRIPT_FUNC)(*(ip+1)) );
|
||||
TRCPRINTF(("\n"));
|
||||
scriptFunc = (SCRIPT_FUNC)*(ip+1);
|
||||
if (!scriptFunc())
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do func"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
ip += aOpSize[opcode];
|
||||
break;
|
||||
case OP_VARCALL:
|
||||
TRCPRINTF(("VARCALL "));
|
||||
TRCPRINTVARFUNC( (SCRIPT_VARFUNC)(*(ip+1)), data );
|
||||
TRCPRINTF(("(%d)\n", data));
|
||||
scriptVarFunc = (SCRIPT_VARFUNC)*(ip+1);
|
||||
if (!scriptVarFunc(data))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not do var func"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
ip += aOpSize[opcode];
|
||||
break;
|
||||
case OP_EXIT:
|
||||
// jump out of the code
|
||||
ip = pCodeEnd;
|
||||
break;
|
||||
case OP_PAUSE:
|
||||
TRCPRINTF(("PAUSE %d\n", data));
|
||||
ASSERT((stackEmpty(),
|
||||
"interpRunScript: OP_PAUSE without empty stack"));
|
||||
ip += aOpSize[opcode];
|
||||
// tell the event system to reschedule this event
|
||||
if (!eventAddPauseTrigger(psContext, index, ip - pCodeBase, data))
|
||||
{
|
||||
ASSERT((FALSE, "interpRunScript: could not add pause trigger"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
// now jump out of the event
|
||||
ip = pCodeEnd;
|
||||
break;
|
||||
default:
|
||||
ASSERT((FALSE, "interpRunScript: unknown opcode"));
|
||||
goto exit_with_error;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TRCPRINTF(("%-6d EXIT\n", ip - psProg->pCode));
|
||||
|
||||
bInterpRunning = FALSE;
|
||||
|
@ -639,3 +726,60 @@ BOOL interpTraceOff(void)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Call stack stuff */
|
||||
|
||||
static UDWORD retStack[200]; //Primitive stack
|
||||
static SDWORD retStackPos; //Current Position, always points to the last valid element
|
||||
|
||||
void retStackReset(void)
|
||||
{
|
||||
retStackPos = -1; //Beginning of the stack
|
||||
}
|
||||
|
||||
//Remember current script execution adress
|
||||
UDWORD RetStackRemember(UDWORD EvTrigIndex, UDWORD address)
|
||||
{
|
||||
//DbgMsg("To remember: %d, %d, %d", EvTrigIndex, address, retStackPos);
|
||||
|
||||
if (retStackPos >= 200)
|
||||
{
|
||||
debug( LOG_ERROR, "RetStackRemember() - return address stack is full");
|
||||
return FALSE; //Stack full
|
||||
}
|
||||
|
||||
retStackPos = retStackPos + 2;
|
||||
retStack[retStackPos - 1] = EvTrigIndex; //First store event index
|
||||
retStack[retStackPos] = address; //current ip
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL IsRetStackEmpty()
|
||||
{
|
||||
if(retStackPos == (-1)) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL PopRetStack(UDWORD *psVal)
|
||||
{
|
||||
//DbgMsg("Popping: %d", retStackPos);
|
||||
if(retStackPos < 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*psVal = retStack[retStackPos];
|
||||
|
||||
retStackPos = retStackPos - 1;
|
||||
|
||||
//DbgMsg("Popped: %d, %d", retStackPos, *psVal);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
SDWORD GetCallDepth()
|
||||
{
|
||||
return (retStackPos + 1) / 2;
|
||||
}
|
|
@ -103,6 +103,8 @@ typedef enum _op_code
|
|||
OP_LESSEQUAL,
|
||||
OP_GREATER,
|
||||
OP_LESS,
|
||||
|
||||
OP_FUNC, //custom (in-script) function call
|
||||
} OPCODE;
|
||||
|
||||
/* How far the opcode is shifted up a UDWORD to allow other data to be
|
||||
|
|
|
@ -213,6 +213,15 @@ typedef struct _event_symbol
|
|||
UDWORD debugEntries;
|
||||
SCRIPT_DEBUG *psDebug;
|
||||
|
||||
//functions stuff
|
||||
UDWORD numParams; //Number of parameters to the function
|
||||
UDWORD numLocalVars; //local variables
|
||||
BOOL bFunction; //if this event is defined as a function
|
||||
BOOL bDeclared; //if function was declared before
|
||||
INTERP_TYPE retType; //return type if a function
|
||||
|
||||
INTERP_TYPE aParams[INST_MAXPARAMS];
|
||||
|
||||
struct _event_symbol *psNext;
|
||||
} EVENT_SYMBOL;
|
||||
|
||||
|
@ -258,7 +267,7 @@ extern BOOL scriptAddVariable(VAR_DECL *psStorage, VAR_IDENT_DECL *psVarIdent);
|
|||
extern BOOL scriptAddTrigger(STRING *pIdent, TRIGGER_DECL *psDecl, UDWORD line);
|
||||
|
||||
/* Add a new event symbol */
|
||||
extern BOOL scriptDeclareEvent(STRING *pIdent, EVENT_SYMBOL **ppsEvent);
|
||||
extern BOOL scriptDeclareEvent(STRING *pIdent, EVENT_SYMBOL **ppsEvent, INT numArgs);
|
||||
|
||||
// Add the code to a defined event
|
||||
extern BOOL scriptDefineEvent(EVENT_SYMBOL *psEvent, CODE_BLOCK *psCode, SDWORD trigger);
|
||||
|
|
|
@ -55,6 +55,18 @@ extern void scriptSetCallbackTab(CALLBACK_SYMBOL *psCallTab);
|
|||
/* Set the type equivalence table */
|
||||
extern void scriptSetTypeEquiv(TYPE_EQUIV *psTypeTab);
|
||||
|
||||
|
||||
/***********************************************************************************
|
||||
*
|
||||
* Return stack stuff
|
||||
*/
|
||||
extern void retStackReset(void);
|
||||
extern UDWORD RetStackRemember(UDWORD EvTrigIndex, UDWORD address);
|
||||
|
||||
extern BOOL IsRetStackEmpty();
|
||||
extern BOOL PopRetStack(UDWORD *psVal);
|
||||
extern SDWORD GetCallDepth();
|
||||
|
||||
/***********************************************************************************
|
||||
*
|
||||
* Compiler functions
|
||||
|
|
|
@ -1,384 +1,446 @@
|
|||
%{
|
||||
/*
|
||||
* script.l
|
||||
*
|
||||
* Script file lexer.
|
||||
*/
|
||||
|
||||
#include "lib/framework/frame.h"
|
||||
#include "interp.h"
|
||||
#include "parse.h"
|
||||
#include "script.h"
|
||||
|
||||
/* Get the Yacc definitions */
|
||||
#include "script_parser.h"
|
||||
|
||||
/* Maximum length for any TEXT value */
|
||||
#ifndef YYLMAX
|
||||
#define YYLMAX 255
|
||||
#endif
|
||||
|
||||
/* Store for any string values */
|
||||
static STRING aText[TEXT_BUFFERS][YYLMAX];
|
||||
static UDWORD currText=0;
|
||||
|
||||
// Note if we are in a comment
|
||||
static BOOL inComment = FALSE;
|
||||
|
||||
/* Pointer to the input buffer */
|
||||
static UBYTE *pInputBuffer = NULL;
|
||||
static UBYTE *pEndBuffer = NULL;
|
||||
|
||||
#define YY_INPUT(buf, result, max_size) \
|
||||
if (pInputBuffer != pEndBuffer) { \
|
||||
buf[0] = *(pInputBuffer++); result = 1; \
|
||||
} else { \
|
||||
buf[0] = EOF; result = YY_NULL; \
|
||||
}
|
||||
|
||||
#undef scr_getc
|
||||
#define scr_getc() (pInputBuffer != pEndBuffer ? *(pInputBuffer++) : EOF)
|
||||
|
||||
/* Get the token type for a variable symbol */
|
||||
SDWORD scriptGetVarToken(VAR_SYMBOL *psVar)
|
||||
{
|
||||
BOOL object;
|
||||
|
||||
// See if this is an object pointer
|
||||
if (!asScrTypeTab || psVar->type < VAL_USERTYPESTART)
|
||||
{
|
||||
object = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
object = asScrTypeTab[psVar->type - VAL_USERTYPESTART].accessType == AT_OBJECT;
|
||||
}
|
||||
|
||||
if (psVar->storage == ST_OBJECT)
|
||||
{
|
||||
/* This is an object member variable */
|
||||
if (object)
|
||||
{
|
||||
return OBJ_OBJVAR;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (psVar->type)
|
||||
{
|
||||
case VAL_BOOL:
|
||||
return BOOL_OBJVAR;
|
||||
break;
|
||||
case VAL_INT:
|
||||
// case VAL_FLOAT:
|
||||
return NUM_OBJVAR;
|
||||
break;
|
||||
default:
|
||||
return USER_OBJVAR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (psVar->dimensions > 0)
|
||||
{
|
||||
/* This is an array variable */
|
||||
if (object)
|
||||
{
|
||||
return OBJ_ARRAY;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (psVar->type)
|
||||
{
|
||||
case VAL_BOOL:
|
||||
return BOOL_ARRAY;
|
||||
break;
|
||||
case VAL_INT:
|
||||
// case VAL_FLOAT:
|
||||
return NUM_ARRAY;
|
||||
break;
|
||||
default:
|
||||
return VAR_ARRAY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is a standard variable */
|
||||
if (object)
|
||||
{
|
||||
return OBJ_VAR;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (psVar->type)
|
||||
{
|
||||
case VAL_BOOL:
|
||||
return BOOL_VAR;
|
||||
break;
|
||||
case VAL_INT:
|
||||
// case VAL_FLOAT:
|
||||
return NUM_VAR;
|
||||
break;
|
||||
default:
|
||||
return VAR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the token type for a constant symbol */
|
||||
SDWORD scriptGetConstToken(CONST_SYMBOL *psConst)
|
||||
{
|
||||
BOOL object;
|
||||
|
||||
// See if this is an object constant
|
||||
if (!asScrTypeTab || psConst->type < VAL_USERTYPESTART)
|
||||
{
|
||||
object = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
object = asScrTypeTab[psConst->type - VAL_USERTYPESTART].accessType == AT_OBJECT;
|
||||
}
|
||||
|
||||
switch (psConst->type)
|
||||
{
|
||||
case VAL_BOOL:
|
||||
return BOOL_CONSTANT;
|
||||
break;
|
||||
case VAL_INT:
|
||||
// case VAL_FLOAT:
|
||||
return NUM_CONSTANT;
|
||||
break;
|
||||
default:
|
||||
if (object)
|
||||
{
|
||||
return OBJ_CONSTANT;
|
||||
}
|
||||
else
|
||||
{
|
||||
return USER_CONSTANT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the token type for a function symbol */
|
||||
SDWORD scriptGetFuncToken(FUNC_SYMBOL *psFunc)
|
||||
{
|
||||
BOOL object;
|
||||
|
||||
// See if this is an object pointer
|
||||
if (!asScrTypeTab || psFunc->type < VAL_USERTYPESTART)
|
||||
{
|
||||
object = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
object = asScrTypeTab[psFunc->type - VAL_USERTYPESTART].accessType == AT_OBJECT;
|
||||
}
|
||||
|
||||
if (object)
|
||||
{
|
||||
return OBJ_FUNC;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (psFunc->type)
|
||||
{
|
||||
case VAL_BOOL:
|
||||
return BOOL_FUNC;
|
||||
break;
|
||||
case VAL_INT:
|
||||
// case VAL_FLOAT:
|
||||
return NUM_FUNC;
|
||||
break;
|
||||
case VAL_VOID:
|
||||
return FUNC;
|
||||
break;
|
||||
default:
|
||||
return USER_FUNC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
%}
|
||||
|
||||
%option prefix="scr_"
|
||||
%option nounput
|
||||
%option yylineno
|
||||
|
||||
%x COMMENT
|
||||
%x SLCOMMENT
|
||||
%x QUOTE
|
||||
|
||||
%%
|
||||
/* Match to key words */
|
||||
/*begin return START;*/
|
||||
/*end return END;*/
|
||||
wait return WAIT;
|
||||
every return EVERY;
|
||||
trigger return TRIGGER;
|
||||
event return EVENT;
|
||||
inactive return INACTIVE;
|
||||
init return INITIALISE;
|
||||
link return LINK;
|
||||
ref return REF;
|
||||
|
||||
/* function return FUNCTION;*/
|
||||
/* cond return COND; */
|
||||
|
||||
public { scr_lval.stype = ST_PUBLIC; return STORAGE; }
|
||||
private { scr_lval.stype = ST_PRIVATE; return STORAGE; }
|
||||
while return WHILE;
|
||||
if return IF;
|
||||
else return ELSE;
|
||||
exit return EXIT;
|
||||
pause return PAUSE;
|
||||
|
||||
/* Match to type key words */
|
||||
bool { scr_lval.tval = VAL_BOOL; return TYPE; }
|
||||
BOOL { scr_lval.tval = VAL_BOOL; return TYPE; }
|
||||
int { scr_lval.tval = VAL_INT; return TYPE; }
|
||||
INT { scr_lval.tval = VAL_INT; return TYPE; }
|
||||
/*float { ais_lval.tval = VAL_FLOAT; return TYPE; }*/
|
||||
/* string type isn't implemented yet */
|
||||
/* string { ais_lval.tval = VAL_STRING; return TYPE; } */
|
||||
/* object { scr_lval.tval = VAL_OBJECT; return TYPE; } */
|
||||
|
||||
/* Match boolean values */
|
||||
TRUE { scr_lval.bval = TRUE; return BOOLEAN_T; }
|
||||
true { scr_lval.bval = TRUE; return BOOLEAN_T; }
|
||||
FALSE { scr_lval.bval = FALSE; return BOOLEAN_T; }
|
||||
false { scr_lval.bval = FALSE; return BOOLEAN_T; }
|
||||
|
||||
/* Match boolean operators */
|
||||
"==" return BOOLEQUAL;
|
||||
"!=" return NOTEQUAL;
|
||||
">=" return GREATEQUAL;
|
||||
"<=" return LESSEQUAL;
|
||||
">" return GREATER;
|
||||
"<" return LESS;
|
||||
and return _AND;
|
||||
AND return _AND;
|
||||
or return _OR;
|
||||
OR return _OR;
|
||||
not return _NOT;
|
||||
NOT return _NOT;
|
||||
|
||||
/* Match floating point numbers */
|
||||
/*-?[0-9]*"."[0-9]+ { scr_lval.fval = (float)atof(scr_text); return FLOAT; }*/
|
||||
|
||||
/* Match integer numbers */
|
||||
-?[0-9]+ { scr_lval.ival = atol(scr_text); return INTEGER; }
|
||||
|
||||
/* Match identifiers */
|
||||
[a-zA-Z][0-9_a-zA-Z]* {
|
||||
/* See if this identifier has been defined as a type */
|
||||
if (scriptLookUpType(scr_text, &scr_lval.tval))
|
||||
{
|
||||
DBP0(("[lex] TYPE\n"));
|
||||
return TYPE;
|
||||
}
|
||||
/* See if this identifier has been defined as a variable */
|
||||
else if (scriptLookUpVariable(scr_text, &scr_lval.vSymbol))
|
||||
{
|
||||
DBP0(("[lex] variable\n"));
|
||||
return scriptGetVarToken(scr_lval.vSymbol);
|
||||
}
|
||||
/* See if this identifier has been defined as a constant */
|
||||
else if (scriptLookUpConstant(scr_text, &scr_lval.cSymbol))
|
||||
{
|
||||
DBP0(("[lex] constant\n"));
|
||||
return scriptGetConstToken(scr_lval.cSymbol);
|
||||
}
|
||||
/* See if this identifier has been defined as a function */
|
||||
else if (scriptLookUpFunction(scr_text, &scr_lval.fSymbol))
|
||||
{
|
||||
DBP0(("[lex] func\n"));
|
||||
return scriptGetFuncToken(scr_lval.fSymbol);
|
||||
}
|
||||
else if (scriptLookUpTrigger(scr_text, &scr_lval.tSymbol))
|
||||
{
|
||||
DBP0(("[lex] TRIG_SYM\n"));
|
||||
return TRIG_SYM;
|
||||
}
|
||||
else if (scriptLookUpEvent(scr_text, &scr_lval.eSymbol))
|
||||
{
|
||||
DBP0(("[lex] EVENT_SYM\n"));
|
||||
return EVENT_SYM;
|
||||
}
|
||||
else if (scriptLookUpCallback(scr_text, &scr_lval.cbSymbol))
|
||||
{
|
||||
DBP0(("[lex] CALLBACK_SYM\n"));
|
||||
return CALLBACK_SYM;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(aText[currText], scr_text);
|
||||
scr_lval.sval = aText[currText];
|
||||
currText = (currText + 1) % TEXT_BUFFERS;
|
||||
DBP0(("[lex] IDENT\n"));
|
||||
return IDENT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Match quoted text */
|
||||
\" { BEGIN QUOTE; }
|
||||
<QUOTE>\" { BEGIN 0; }
|
||||
<QUOTE>[^\"\n]* {
|
||||
strcpy(aText[currText], scr_text);
|
||||
scr_lval.sval = aText[currText];
|
||||
currText = (currText + 1) % TEXT_BUFFERS;
|
||||
return QTEXT;
|
||||
}
|
||||
|
||||
/* Skip white space */
|
||||
[ \t\n\x0d\x0a] ;
|
||||
|
||||
/* Strip comments */
|
||||
"/*" { inComment=TRUE; BEGIN COMMENT; }
|
||||
<COMMENT>"*/" |
|
||||
<COMMENT>"*/"\n { inComment=FALSE; BEGIN 0; }
|
||||
<COMMENT>. |
|
||||
<COMMENT>\n ;
|
||||
|
||||
/* Strip single line comments */
|
||||
"//" { BEGIN SLCOMMENT; }
|
||||
<SLCOMMENT>\n { BEGIN 0; }
|
||||
<SLCOMMENT>[^\n]* ;
|
||||
|
||||
/* Match anything that's been missed and pass it as a char */
|
||||
. return scr_text[0];
|
||||
|
||||
%%
|
||||
|
||||
/* Set the current input buffer for the lexer */
|
||||
void scriptSetInputBuffer(UBYTE *pBuffer, UDWORD size)
|
||||
{
|
||||
pInputBuffer = pBuffer;
|
||||
pEndBuffer = pBuffer + size;
|
||||
|
||||
/* Reset the lexer in case it's been used before */
|
||||
scr__flush_buffer( YY_CURRENT_BUFFER );
|
||||
}
|
||||
|
||||
void scriptGetErrorData(int *pLine, char **ppText)
|
||||
{
|
||||
*pLine = scr_lineno;
|
||||
*ppText = scr_text;
|
||||
}
|
||||
|
||||
int scr_wrap(void)
|
||||
{
|
||||
if (inComment)
|
||||
{
|
||||
DBERROR(("Warning: reched end of file in a comment"));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
%{
|
||||
/*
|
||||
* script.l
|
||||
*
|
||||
* Script file lexer.
|
||||
*/
|
||||
|
||||
#include "lib/framework/frame.h"
|
||||
#include "interp.h"
|
||||
#include "parse.h"
|
||||
#include "script.h"
|
||||
|
||||
/* Get the Yacc definitions */
|
||||
#include "script_parser.h"
|
||||
|
||||
/* Maximum length for any TEXT value */
|
||||
#ifndef YYLMAX
|
||||
#define YYLMAX 255
|
||||
#endif
|
||||
|
||||
/* Store for any string values */
|
||||
static STRING aText[TEXT_BUFFERS][YYLMAX];
|
||||
static UDWORD currText=0;
|
||||
|
||||
// Note if we are in a comment
|
||||
static BOOL inComment = FALSE;
|
||||
|
||||
/* Pointer to the input buffer */
|
||||
static UBYTE *pInputBuffer = NULL;
|
||||
static UBYTE *pEndBuffer = NULL;
|
||||
|
||||
#define YY_INPUT(buf, result, max_size) \
|
||||
if (pInputBuffer != pEndBuffer) { \
|
||||
buf[0] = *(pInputBuffer++); result = 1; \
|
||||
} else { \
|
||||
buf[0] = EOF; result = YY_NULL; \
|
||||
}
|
||||
|
||||
#undef scr_getc
|
||||
#define scr_getc() (pInputBuffer != pEndBuffer ? *(pInputBuffer++) : EOF)
|
||||
|
||||
/* Get the token type for a variable symbol */
|
||||
SDWORD scriptGetVarToken(VAR_SYMBOL *psVar)
|
||||
{
|
||||
BOOL object;
|
||||
|
||||
// See if this is an object pointer
|
||||
if (!asScrTypeTab || psVar->type < VAL_USERTYPESTART)
|
||||
{
|
||||
object = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
object = asScrTypeTab[psVar->type - VAL_USERTYPESTART].accessType == AT_OBJECT;
|
||||
}
|
||||
|
||||
if (psVar->storage == ST_OBJECT)
|
||||
{
|
||||
/* This is an object member variable */
|
||||
if (object)
|
||||
{
|
||||
return OBJ_OBJVAR;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (psVar->type)
|
||||
{
|
||||
case VAL_BOOL:
|
||||
return BOOL_OBJVAR;
|
||||
break;
|
||||
case VAL_INT:
|
||||
// case VAL_FLOAT:
|
||||
return NUM_OBJVAR;
|
||||
break;
|
||||
default:
|
||||
return USER_OBJVAR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (psVar->dimensions > 0)
|
||||
{
|
||||
/* This is an array variable */
|
||||
if (object)
|
||||
{
|
||||
return OBJ_ARRAY;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (psVar->type)
|
||||
{
|
||||
case VAL_BOOL:
|
||||
return BOOL_ARRAY;
|
||||
break;
|
||||
case VAL_INT:
|
||||
// case VAL_FLOAT:
|
||||
return NUM_ARRAY;
|
||||
break;
|
||||
default:
|
||||
return VAR_ARRAY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is a standard variable */
|
||||
if (object)
|
||||
{
|
||||
return OBJ_VAR;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (psVar->type)
|
||||
{
|
||||
case VAL_BOOL:
|
||||
return BOOL_VAR;
|
||||
break;
|
||||
case VAL_INT:
|
||||
// case VAL_FLOAT:
|
||||
return NUM_VAR;
|
||||
break;
|
||||
default:
|
||||
return VAR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the token type for a constant symbol */
|
||||
SDWORD scriptGetConstToken(CONST_SYMBOL *psConst)
|
||||
{
|
||||
BOOL object;
|
||||
|
||||
// See if this is an object constant
|
||||
if (!asScrTypeTab || psConst->type < VAL_USERTYPESTART)
|
||||
{
|
||||
object = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
object = asScrTypeTab[psConst->type - VAL_USERTYPESTART].accessType == AT_OBJECT;
|
||||
}
|
||||
|
||||
switch (psConst->type)
|
||||
{
|
||||
case VAL_BOOL:
|
||||
return BOOL_CONSTANT;
|
||||
break;
|
||||
case VAL_INT:
|
||||
// case VAL_FLOAT:
|
||||
return NUM_CONSTANT;
|
||||
break;
|
||||
default:
|
||||
if (object)
|
||||
{
|
||||
return OBJ_CONSTANT;
|
||||
}
|
||||
else
|
||||
{
|
||||
return USER_CONSTANT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the token type for a function symbol */
|
||||
SDWORD scriptGetFuncToken(FUNC_SYMBOL *psFunc)
|
||||
{
|
||||
BOOL object;
|
||||
|
||||
// See if this is an object pointer
|
||||
if (!asScrTypeTab || psFunc->type < VAL_USERTYPESTART)
|
||||
{
|
||||
object = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
object = asScrTypeTab[psFunc->type - VAL_USERTYPESTART].accessType == AT_OBJECT;
|
||||
}
|
||||
|
||||
if (object)
|
||||
{
|
||||
return OBJ_FUNC;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (psFunc->type)
|
||||
{
|
||||
case VAL_BOOL:
|
||||
return BOOL_FUNC;
|
||||
break;
|
||||
case VAL_INT:
|
||||
// case VAL_FLOAT:
|
||||
return NUM_FUNC;
|
||||
break;
|
||||
case VAL_VOID:
|
||||
return FUNC;
|
||||
break;
|
||||
default:
|
||||
return USER_FUNC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Get the token type for a custom function symbol */
|
||||
SDWORD scriptGetCustomFuncToken(EVENT_SYMBOL *psFunc)
|
||||
{
|
||||
BOOL object;
|
||||
|
||||
debug( LOG_SCRIPT, "scriptGetCustomFuncToken" );
|
||||
|
||||
// See if this is an object pointer
|
||||
object = asScrTypeTab[psFunc->retType - VAL_USERTYPESTART].accessType == AT_OBJECT;
|
||||
|
||||
debug( LOG_SCRIPT, "scriptGetCustomFuncToken 3" );
|
||||
|
||||
if (object)
|
||||
{
|
||||
debug( LOG_SCRIPT, "scriptGetCustomFuncToken: object" );
|
||||
return OBJ_FUNC_CUST;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (psFunc->retType)
|
||||
{
|
||||
case VAL_BOOL:
|
||||
debug( LOG_SCRIPT, "scriptGetCustomFuncToken: VAL_BOOL" );
|
||||
return BOOL_FUNC_CUST;
|
||||
break;
|
||||
case VAL_INT:
|
||||
// case VAL_FLOAT:
|
||||
debug( LOG_SCRIPT, "scriptGetCustomFuncToken: VAL_INT" );
|
||||
return NUM_FUNC_CUST;
|
||||
break;
|
||||
case VAL_STRING: /* <NEW> */
|
||||
debug( LOG_SCRIPT, "scriptGetCustomFuncToken: VAL_STRING" );
|
||||
return STRING_FUNC_CUST;
|
||||
break;
|
||||
case VAL_VOID:
|
||||
debug( LOG_SCRIPT, "scriptGetCustomFuncToken: void function" );
|
||||
return VOID_FUNC_CUST;
|
||||
break;
|
||||
default:
|
||||
debug( LOG_SCRIPT, "scriptGetCustomFuncToken: default" );
|
||||
return USER_FUNC_CUST;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
debug( LOG_SCRIPT, "END scriptGetCustomFuncToken" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
%}
|
||||
|
||||
%option prefix="scr_"
|
||||
%option nounput
|
||||
%option yylineno
|
||||
|
||||
%x COMMENT
|
||||
%x SLCOMMENT
|
||||
%x QUOTE
|
||||
|
||||
%%
|
||||
/* Match to key words */
|
||||
/*begin return START;*/
|
||||
/*end return END;*/
|
||||
wait return WAIT;
|
||||
every return EVERY;
|
||||
trigger return TRIGGER;
|
||||
event return EVENT;
|
||||
inactive return INACTIVE;
|
||||
init return INITIALISE;
|
||||
link return LINK;
|
||||
ref return REF;
|
||||
|
||||
/* new stuff */
|
||||
function return FUNCTION;
|
||||
return return RETURN;
|
||||
|
||||
public { scr_lval.stype = ST_PUBLIC; return STORAGE; }
|
||||
private { scr_lval.stype = ST_PRIVATE; return STORAGE; }
|
||||
while return WHILE;
|
||||
if return IF;
|
||||
else return ELSE;
|
||||
exit return EXIT;
|
||||
pause return PAUSE;
|
||||
|
||||
/* Match to type key words */
|
||||
bool { scr_lval.tval = VAL_BOOL; return TYPE; }
|
||||
BOOL { scr_lval.tval = VAL_BOOL; return TYPE; }
|
||||
int { scr_lval.tval = VAL_INT; return TYPE; }
|
||||
INT { scr_lval.tval = VAL_INT; return TYPE; }
|
||||
|
||||
/* return value for void functions */
|
||||
void { scr_lval.tval = VAL_VOID; return TYPE; }
|
||||
VOID { scr_lval.tval = VAL_VOID; return TYPE; }
|
||||
|
||||
/* string type isn't implemented yet */
|
||||
/* string { ais_lval.tval = VAL_STRING; return TYPE; } */
|
||||
/* object { scr_lval.tval = VAL_OBJECT; return TYPE; } */
|
||||
|
||||
/* Match boolean values */
|
||||
TRUE { scr_lval.bval = TRUE; return BOOLEAN_T; }
|
||||
true { scr_lval.bval = TRUE; return BOOLEAN_T; }
|
||||
FALSE { scr_lval.bval = FALSE; return BOOLEAN_T; }
|
||||
false { scr_lval.bval = FALSE; return BOOLEAN_T; }
|
||||
|
||||
/* Match boolean operators */
|
||||
"==" return BOOLEQUAL;
|
||||
"!=" return NOTEQUAL;
|
||||
">=" return GREATEQUAL;
|
||||
"<=" return LESSEQUAL;
|
||||
">" return GREATER;
|
||||
"<" return LESS;
|
||||
and return _AND;
|
||||
AND return _AND;
|
||||
or return _OR;
|
||||
OR return _OR;
|
||||
not return _NOT;
|
||||
NOT return _NOT;
|
||||
|
||||
/* Match floating point numbers */
|
||||
/*-?[0-9]*"."[0-9]+ { scr_lval.fval = (float)atof(scr_text); return FLOAT; }*/
|
||||
|
||||
/* Match integer numbers */
|
||||
-?[0-9]+ { scr_lval.ival = atol(scr_text); return INTEGER; }
|
||||
|
||||
/* Match identifiers */
|
||||
[a-zA-Z][0-9_a-zA-Z]* {
|
||||
/* See if this identifier has been defined as a type */
|
||||
if (scriptLookUpType(scr_text, &scr_lval.tval))
|
||||
{
|
||||
DBP0(("[lex] TYPE\n"));
|
||||
return TYPE;
|
||||
}
|
||||
/* See if this identifier has been defined as a variable */
|
||||
else if (scriptLookUpVariable(scr_text, &scr_lval.vSymbol))
|
||||
{
|
||||
DBP0(("[lex] variable\n"));
|
||||
return scriptGetVarToken(scr_lval.vSymbol);
|
||||
}
|
||||
/* See if this identifier has been defined as a constant */
|
||||
else if (scriptLookUpConstant(scr_text, &scr_lval.cSymbol))
|
||||
{
|
||||
DBP0(("[lex] constant\n"));
|
||||
return scriptGetConstToken(scr_lval.cSymbol);
|
||||
}
|
||||
/* See if this identifier has been defined as a function */
|
||||
else if (scriptLookUpFunction(scr_text, &scr_lval.fSymbol))
|
||||
{
|
||||
DBP0(("[lex] func\n"));
|
||||
return scriptGetFuncToken(scr_lval.fSymbol);
|
||||
}
|
||||
|
||||
/* See if this identifier has been defined as a custom function */
|
||||
else if (scriptLookUpCustomFunction(scr_text, &scr_lval.eSymbol))
|
||||
{
|
||||
debug( LOG_SCRIPT, "scriptLookUpCustomFunction: '%s' - custom function", scr_text );
|
||||
return scriptGetCustomFuncToken(scr_lval.eSymbol);
|
||||
}
|
||||
|
||||
else if (scriptLookUpTrigger(scr_text, &scr_lval.tSymbol))
|
||||
{
|
||||
DBP0(("[lex] TRIG_SYM\n"));
|
||||
return TRIG_SYM;
|
||||
}
|
||||
else if (scriptLookUpEvent(scr_text, &scr_lval.eSymbol))
|
||||
{
|
||||
DBP0(("[lex] EVENT_SYM\n"));
|
||||
return EVENT_SYM;
|
||||
}
|
||||
else if (scriptLookUpCallback(scr_text, &scr_lval.cbSymbol))
|
||||
{
|
||||
DBP0(("[lex] CALLBACK_SYM\n"));
|
||||
return CALLBACK_SYM;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(aText[currText], scr_text);
|
||||
scr_lval.sval = aText[currText];
|
||||
currText = (currText + 1) % TEXT_BUFFERS;
|
||||
DBP0(("[lex] IDENT\n"));
|
||||
return IDENT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Match quoted text */
|
||||
\" { BEGIN QUOTE; }
|
||||
<QUOTE>\" { BEGIN 0; }
|
||||
<QUOTE>[^\"\n]* {
|
||||
strcpy(aText[currText], scr_text);
|
||||
scr_lval.sval = aText[currText];
|
||||
currText = (currText + 1) % TEXT_BUFFERS;
|
||||
return QTEXT;
|
||||
}
|
||||
|
||||
/* Skip white space */
|
||||
[ \t\n\x0d\x0a] ;
|
||||
|
||||
/* Strip comments */
|
||||
"/*" { inComment=TRUE; BEGIN COMMENT; }
|
||||
<COMMENT>"*/" |
|
||||
<COMMENT>"*/"\n { inComment=FALSE; BEGIN 0; }
|
||||
<COMMENT>. |
|
||||
<COMMENT>\n ;
|
||||
|
||||
/* Strip single line comments */
|
||||
"//" { BEGIN SLCOMMENT; }
|
||||
<SLCOMMENT>\n { BEGIN 0; }
|
||||
<SLCOMMENT>[^\n]* ;
|
||||
|
||||
/* Match anything that's been missed and pass it as a char */
|
||||
. return scr_text[0];
|
||||
|
||||
%%
|
||||
|
||||
/* Set the current input buffer for the lexer */
|
||||
void scriptSetInputBuffer(UBYTE *pBuffer, UDWORD size)
|
||||
{
|
||||
pInputBuffer = pBuffer;
|
||||
pEndBuffer = pBuffer + size;
|
||||
|
||||
/* Reset the lexer in case it's been used before */
|
||||
scr__flush_buffer( YY_CURRENT_BUFFER );
|
||||
}
|
||||
|
||||
void scriptGetErrorData(int *pLine, char **ppText)
|
||||
{
|
||||
*pLine = scr_lineno;
|
||||
*ppText = scr_text;
|
||||
}
|
||||
|
||||
int scr_wrap(void)
|
||||
{
|
||||
if (inComment)
|
||||
{
|
||||
DBERROR(("Warning: reched end of file in a comment"));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue