Scripting engine update:
-implemented string support -functions can now have arguments, example: function STRING myFunc(DROID myDroid, int myInt2){<code>} -functions can have return values: return <statement>; or just "return;" for void functions -function calls are made the normal c/c++ way (using the function from the first example): myString = myFunc(myDroid, 156); git-svn-id: svn+ssh://svn.gna.org/svn/warzone/trunk@583 4a71c877-e1ca-e34f-864e-861f7616d084master
parent
77ed8b86a7
commit
92284dc7bc
|
@ -14,6 +14,7 @@
|
|||
#include "interp.h"
|
||||
#include "script.h"
|
||||
#include "event.h"
|
||||
#include "scripttabs.h" //because of ST_GROUP
|
||||
|
||||
// array to store release functions
|
||||
static VAL_CREATE_FUNC *asCreateFuncs;
|
||||
|
@ -87,16 +88,19 @@ BOOL eventInitialise(EVENT_INIT *psInit)
|
|||
// Create the value heap
|
||||
if (!HEAP_CREATE(&psValHeap, sizeof(VAL_CHUNK), psInit->valInit, psInit->valExt))
|
||||
{
|
||||
debug(LOG_ERROR, "eventInitialise: HEAP_CREATE failed for values");
|
||||
return FALSE;
|
||||
}
|
||||
// Create the trigger heap
|
||||
if (!HEAP_CREATE(&psTrigHeap, sizeof(ACTIVE_TRIGGER), psInit->trigInit, psInit->trigExt))
|
||||
{
|
||||
debug(LOG_ERROR, "eventInitialise: HEAP_CREATE failed for triggers");
|
||||
return FALSE;
|
||||
}
|
||||
// Create the context heap
|
||||
if (!HEAP_CREATE(&psContHeap, sizeof(SCRIPT_CONTEXT), psInit->contInit, psInit->contExt))
|
||||
{
|
||||
debug(LOG_ERROR, "eventInitialise: HEAP_CREATE failed for context");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -303,19 +307,22 @@ void eventPrintTriggerInfo(ACTIVE_TRIGGER *psTrigger)
|
|||
// Initialise the create/release function array - specify the maximum value type
|
||||
BOOL eventInitValueFuncs(SDWORD maxType)
|
||||
{
|
||||
if(asReleaseFuncs != NULL) //<NEW> 13.05.05
|
||||
debug(LOG_ERROR, "eventInitValueFuncs: array already initialised");
|
||||
|
||||
ASSERT((asReleaseFuncs == NULL,
|
||||
"eventInitValueFuncs: array already initialised"));
|
||||
|
||||
asCreateFuncs = (VAL_CREATE_FUNC *)MALLOC(sizeof(VAL_CREATE_FUNC) * maxType);
|
||||
if (!asCreateFuncs)
|
||||
{
|
||||
DBERROR(("eventInitValueFuncs: Out of memory"));
|
||||
debug(LOG_ERROR, "eventInitValueFuncs: Out of memory");
|
||||
return FALSE;
|
||||
}
|
||||
asReleaseFuncs = (VAL_RELEASE_FUNC *)MALLOC(sizeof(VAL_RELEASE_FUNC) * maxType);
|
||||
if (!asReleaseFuncs)
|
||||
{
|
||||
DBERROR(("eventInitValueFuncs: Out of memory"));
|
||||
debug(LOG_ERROR, "eventInitValueFuncs: Out of memory");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -331,7 +338,7 @@ BOOL eventAddValueCreate(INTERP_TYPE type, VAL_CREATE_FUNC create)
|
|||
{
|
||||
if (type >= numFuncs)
|
||||
{
|
||||
DBERROR(("eventAddValueCreate: type out of range"));
|
||||
debug(LOG_ERROR, "eventAddValueCreate: type out of range");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -345,6 +352,7 @@ BOOL eventAddValueRelease(INTERP_TYPE type, VAL_RELEASE_FUNC release)
|
|||
{
|
||||
if (type >= numFuncs)
|
||||
{
|
||||
debug(LOG_ERROR, "eventAddValueRelease: type out of range");
|
||||
DBERROR(("eventAddValueRelease: type out of range"));
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -415,9 +423,9 @@ BOOL eventNewContext(SCRIPT_CODE *psCode, CONTEXT_RELEASE release,
|
|||
//initialize Strings and integers
|
||||
if(type == VAL_STRING)
|
||||
{
|
||||
debug(LOG_SCRIPT,"eventNewContext: STRING type variables are not implemented");
|
||||
//debug(LOG_ERROR,"eventNewContext: STRING type variables are not implemented");
|
||||
|
||||
psCode->ppsLocalVarVal[i][j].v.sval = (char*)MALLOC(255); //TODO: MAXSTRLEN
|
||||
psCode->ppsLocalVarVal[i][j].v.sval = (char*)MALLOC(MAXSTRLEN);
|
||||
strcpy(psCode->ppsLocalVarVal[i][j].v.sval,"\0");
|
||||
}
|
||||
else
|
||||
|
@ -474,7 +482,21 @@ BOOL eventNewContext(SCRIPT_CODE *psCode, CONTEXT_RELEASE release,
|
|||
type = psCode->pGlobals[val];
|
||||
}
|
||||
psNewChunk->asVals[storeIndex].type = type;
|
||||
psNewChunk->asVals[storeIndex].v.ival = 0;
|
||||
|
||||
|
||||
//initialize Strings
|
||||
if(type == VAL_STRING)
|
||||
{
|
||||
//debug(LOG_ERROR, "eventNewContext: STRING data type is not implemented");
|
||||
psNewChunk->asVals[storeIndex].v.sval = (char*)MALLOC(MAXSTRLEN);
|
||||
strcpy(psNewChunk->asVals[storeIndex].v.sval,"\0");
|
||||
}
|
||||
else
|
||||
{
|
||||
psNewChunk->asVals[storeIndex].v.ival = 0;
|
||||
}
|
||||
|
||||
|
||||
if (asCreateFuncs != NULL && type < numFuncs && asCreateFuncs[type])
|
||||
{
|
||||
if (!asCreateFuncs[type](psNewChunk->asVals + storeIndex))
|
||||
|
@ -1377,3 +1399,47 @@ BOOL eventSetTraceLevel(void)
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//reset local vars
|
||||
BOOL resetLocalVars(SCRIPT_CODE *psCode, UDWORD EventIndex)
|
||||
{
|
||||
|
||||
SDWORD i;
|
||||
|
||||
if(EventIndex >= psCode->numEvents)
|
||||
{
|
||||
debug(LOG_ERROR, "resetLocalVars: wrong event index: %d", EventIndex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for(i=0; i < psCode->numLocalVars[EventIndex]; i++)
|
||||
{
|
||||
//Initialize main value
|
||||
if(psCode->ppsLocalVarVal[EventIndex][i].type == VAL_STRING)
|
||||
{
|
||||
//debug(LOG_ERROR , "resetLocalVars: String type is not implemented");
|
||||
psCode->ppsLocalVarVal[EventIndex][i].v.sval = (char*)MALLOC(MAXSTRLEN);
|
||||
|
||||
strcpy(psCode->ppsLocalVarVal[EventIndex][i].v.sval,"\0");
|
||||
}
|
||||
else
|
||||
{
|
||||
psCode->ppsLocalVarVal[EventIndex][i].v.ival = 0;
|
||||
}
|
||||
|
||||
/* only group (!) must be re-created each time */
|
||||
if (psCode->ppsLocalVarVal[EventIndex][i].type == ST_GROUP)
|
||||
{
|
||||
debug(LOG_SCRIPT, "resetLocalVars - created");
|
||||
|
||||
if (!asCreateFuncs[psCode->ppsLocalVarVal[EventIndex][i].type](&(psCode->ppsLocalVarVal[EventIndex][i]) ))
|
||||
{
|
||||
debug(LOG_ERROR, "asCreateFuncs failed for local var (re-init)");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//debug(LOG_SCRIPT, "Reset local vars for event %d", EventIndex);
|
||||
return TRUE;
|
||||
}
|
|
@ -95,5 +95,8 @@ extern BOOL eventLoadTrigger(UDWORD time, SCRIPT_CONTEXT *psContext,
|
|||
//resets the event timer - updateTime
|
||||
extern void eventTimeReset(UDWORD initTime);
|
||||
|
||||
extern STRING *eventGetEventID(SCRIPT_CODE *psCode, SDWORD event);
|
||||
extern STRING *eventGetTriggerID(SCRIPT_CODE *psCode, SDWORD trigger);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -12,12 +12,15 @@
|
|||
#include "stack.h"
|
||||
#include "codeprint.h"
|
||||
#include "script.h"
|
||||
#include "event.h" //needed for eventGetEventID()
|
||||
|
||||
|
||||
// the maximum number of instructions to execute before assuming
|
||||
// an infinite loop
|
||||
#define INTERP_MAXINSTRUCTIONS 100000
|
||||
|
||||
|
||||
|
||||
/* The size of each opcode */
|
||||
SDWORD aOpSize[] =
|
||||
{
|
||||
|
@ -202,50 +205,6 @@ BOOL interpInitialise(void)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
//reset local vars
|
||||
BOOL resetLocalVars(SCRIPT_CODE *psCode, UDWORD EventIndex)
|
||||
{
|
||||
|
||||
SDWORD i;
|
||||
|
||||
if(EventIndex >= psCode->numEvents)
|
||||
{
|
||||
debug(LOG_ERROR, "resetLocalVars: wrong event index: %d", EventIndex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for(i=0; i < psCode->numLocalVars[EventIndex]; i++)
|
||||
{
|
||||
//Initialize main value
|
||||
if(psCode->ppsLocalVarVal[EventIndex][i].type == VAL_STRING)
|
||||
{
|
||||
debug(LOG_ERROR , "resetLocalVars: String type is not implemented");
|
||||
psCode->ppsLocalVarVal[EventIndex][i].v.sval = (char*)MALLOC(255); //MAXSTRLEN
|
||||
|
||||
strcpy(psCode->ppsLocalVarVal[EventIndex][i].v.sval,"\0");
|
||||
}
|
||||
else
|
||||
{
|
||||
psCode->ppsLocalVarVal[EventIndex][i].v.ival = 0;
|
||||
}
|
||||
|
||||
/* only group (!) must be re-created each time */
|
||||
//if (psCode->ppsLocalVarVal[EventIndex][i].type == ST_GROUP)
|
||||
//{
|
||||
// //DB_INTERP(("resetLocalVars - created\n"));
|
||||
//
|
||||
// if (!asCreateFuncs[psCode->ppsLocalVarVal[EventIndex][i].type](&(psCode->ppsLocalVarVal[EventIndex][i]) ))
|
||||
// {
|
||||
// debug(LOG_ERROR, "asCreateFuncs failed for local var (re-init)");
|
||||
// return FALSE;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
//debug(LOG_SCRIPT, "Reset local vars for event %d", EventIndex);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Run a compiled script */
|
||||
BOOL interpRunScript(SCRIPT_CONTEXT *psContext, INTERP_RUNTYPE runType, UDWORD index, UDWORD offset)
|
||||
{
|
||||
|
@ -262,6 +221,10 @@ BOOL interpRunScript(SCRIPT_CONTEXT *psContext, INTERP_RUNTYPE runType, UDWORD i
|
|||
|
||||
UDWORD CurEvent;
|
||||
BOOL bStop,bEvent;
|
||||
SDWORD callDepth;
|
||||
STRING *pTrigLab, *pEventLab;
|
||||
|
||||
//debug(LOG_SCRIPT, "interpRunScript 1");
|
||||
|
||||
ASSERT((PTRVALID(psContext, sizeof(SCRIPT_CONTEXT)),
|
||||
"interpRunScript: invalid context pointer"));
|
||||
|
@ -338,6 +301,8 @@ BOOL interpRunScript(SCRIPT_CONTEXT *psContext, INTERP_RUNTYPE runType, UDWORD i
|
|||
CurEvent = index;
|
||||
bStop = FALSE;
|
||||
|
||||
//debug(LOG_SCRIPT, "interpRunScript 2");
|
||||
|
||||
while(!bStop)
|
||||
{
|
||||
// Run the code
|
||||
|
@ -698,17 +663,20 @@ BOOL interpRunScript(SCRIPT_CONTEXT *psContext, INTERP_RUNTYPE runType, UDWORD i
|
|||
}
|
||||
break;
|
||||
case OP_CALL:
|
||||
TRCPRINTF(("CALL "));
|
||||
//debug(LOG_SCRIPT, "OP_CALL");
|
||||
TRCPRINTFUNC( (SCRIPT_FUNC)(*(ip+1)) );
|
||||
TRCPRINTF(("\n"));
|
||||
scriptFunc = (SCRIPT_FUNC)*(ip+1);
|
||||
//debug(LOG_SCRIPT, "OP_CALL 1");
|
||||
if (!scriptFunc())
|
||||
{
|
||||
debug( LOG_ERROR, "interpRunScript: could not do func" );
|
||||
ASSERT((FALSE, "interpRunScript: could not do func"));
|
||||
goto exit_with_error;
|
||||
}
|
||||
//debug(LOG_SCRIPT, "OP_CALL 2");
|
||||
ip += aOpSize[opcode];
|
||||
//debug(LOG_SCRIPT, "OP_CALL 3");
|
||||
break;
|
||||
case OP_VARCALL:
|
||||
TRCPRINTF(("VARCALL "));
|
||||
|
@ -808,7 +776,7 @@ BOOL interpRunScript(SCRIPT_CONTEXT *psContext, INTERP_RUNTYPE runType, UDWORD i
|
|||
}
|
||||
|
||||
|
||||
|
||||
//debug(LOG_SCRIPT, "interpRunScript 3");
|
||||
|
||||
|
||||
TRCPRINTF(("%-6d EXIT\n", ip - psProg->pCode));
|
||||
|
@ -819,6 +787,35 @@ BOOL interpRunScript(SCRIPT_CONTEXT *psContext, INTERP_RUNTYPE runType, UDWORD i
|
|||
exit_with_error:
|
||||
// Deal with the script crashing or running out of memory
|
||||
debug(LOG_ERROR,"interpRunScript: *** ERROR EXIT *** (CurEvent=%d)", CurEvent);
|
||||
|
||||
|
||||
debug(LOG_ERROR,"Original event/trigger ID: %d (of %d)", index, psProg->numEvents);
|
||||
debug(LOG_ERROR,"Current event ID: %d (of %d)", CurEvent, psProg->numEvents);
|
||||
callDepth = GetCallDepth();
|
||||
debug(LOG_ERROR,"Call depth : %d", callDepth);
|
||||
|
||||
if(psProg->psDebug != NULL)
|
||||
{
|
||||
debug(LOG_ERROR,"Displaying debug info:");
|
||||
|
||||
if(bEvent)
|
||||
{
|
||||
// find the debug info for the original (caller) event
|
||||
pEventLab = eventGetEventID(psProg, index);
|
||||
debug(LOG_ERROR,"Original event name: %s", pEventLab);
|
||||
|
||||
pEventLab = eventGetEventID(psProg, CurEvent);
|
||||
debug(LOG_ERROR,"Current event name: %s", pEventLab);
|
||||
}
|
||||
else
|
||||
{
|
||||
// find the debug info for the trigger
|
||||
pTrigLab = eventGetTriggerID(psProg, index);
|
||||
debug(LOG_ERROR,"Trigger: %s", pTrigLab);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TRCPRINTF(("*** ERROR EXIT ***\n"));
|
||||
bInterpRunning = FALSE;
|
||||
return FALSE;
|
||||
|
|
|
@ -6,6 +6,13 @@
|
|||
#ifndef _interp_h
|
||||
#define _interp_h
|
||||
|
||||
//String support
|
||||
//-----------------------------
|
||||
static UDWORD CURSTACKSTR = 0; //Points to the top of the string stack
|
||||
#define MAXSTRLEN 255 //Max len of a single string
|
||||
#define MAXSTACKLEN 6000
|
||||
static char STRSTACK[MAXSTACKLEN][MAXSTRLEN]; //simple string 'stack'
|
||||
|
||||
/* The possible value types for scripts */
|
||||
typedef enum _interp_type
|
||||
{
|
||||
|
@ -96,6 +103,9 @@ typedef enum _op_code
|
|||
OP_OR,
|
||||
OP_NOT,
|
||||
|
||||
//String cancatenation
|
||||
OP_CANC,
|
||||
|
||||
// Comparison operators
|
||||
OP_EQUAL,
|
||||
OP_NOTEQUAL,
|
||||
|
@ -107,7 +117,7 @@ typedef enum _op_code
|
|||
OP_FUNC, //custom (in-script) function call
|
||||
OP_POPLOCAL, //local var
|
||||
OP_PUSHLOCAL,
|
||||
OP_PUSHLOCALREF,
|
||||
OP_PUSHLOCALREF, //variable of object type (pointer)
|
||||
} OPCODE;
|
||||
|
||||
/* How far the opcode is shifted up a UDWORD to allow other data to be
|
||||
|
|
|
@ -122,6 +122,7 @@ typedef struct _const_symbol
|
|||
BOOL bval;
|
||||
SDWORD ival;
|
||||
void *oval;
|
||||
STRING *sval; //String values
|
||||
// float fval;
|
||||
} CONST_SYMBOL;
|
||||
|
||||
|
@ -309,5 +310,9 @@ extern BOOL scriptLookUpFunction(STRING *pIdent, FUNC_SYMBOL **ppsSym);
|
|||
/* Look up an in-script custom function symbol */
|
||||
extern BOOL scriptLookUpCustomFunction(STRING *pIdent, EVENT_SYMBOL **ppsSym);
|
||||
|
||||
extern BOOL popArguments(UDWORD **ip_temp, SDWORD numParams);
|
||||
|
||||
extern void widgCopyString(STRING *pDest, STRING *pSrc);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -44,8 +44,6 @@ SDWORD scriptGetVarToken(VAR_SYMBOL *psVar)
|
|||
{
|
||||
BOOL object;
|
||||
|
||||
//debug( LOG_SCRIPT, "scriptGetVarToken" );
|
||||
|
||||
// See if this is an object pointer
|
||||
if (!asScrTypeTab || psVar->type < VAL_USERTYPESTART)
|
||||
{
|
||||
|
@ -120,17 +118,17 @@ SDWORD scriptGetVarToken(VAR_SYMBOL *psVar)
|
|||
break;
|
||||
case VAL_INT:
|
||||
// case VAL_FLOAT:
|
||||
//debug( LOG_SCRIPT, "scriptGetVarToken: VAL_INT (NUM_VAR)" );
|
||||
return NUM_VAR;
|
||||
break;
|
||||
case VAL_STRING:
|
||||
return STRING_VAR;
|
||||
break;
|
||||
default:
|
||||
return VAR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//debug( LOG_SCRIPT, "END scriptGetVarToken" );
|
||||
}
|
||||
|
||||
/* Get the token type for a constant symbol */
|
||||
|
@ -138,8 +136,6 @@ SDWORD scriptGetConstToken(CONST_SYMBOL *psConst)
|
|||
{
|
||||
BOOL object;
|
||||
|
||||
//debug( LOG_SCRIPT, "scriptGetConstToken" );
|
||||
|
||||
// See if this is an object constant
|
||||
if (!asScrTypeTab || psConst->type < VAL_USERTYPESTART)
|
||||
{
|
||||
|
@ -159,9 +155,13 @@ SDWORD scriptGetConstToken(CONST_SYMBOL *psConst)
|
|||
// case VAL_FLOAT:
|
||||
return NUM_CONSTANT;
|
||||
break;
|
||||
case VAL_STRING:
|
||||
return STRING_CONSTANT;
|
||||
break;
|
||||
default:
|
||||
if (object)
|
||||
{
|
||||
//debug(LOG_SCRIPT, "scriptGetConstToken: OBJ_CONSTANT");
|
||||
return OBJ_CONSTANT;
|
||||
}
|
||||
else
|
||||
|
@ -170,8 +170,6 @@ SDWORD scriptGetConstToken(CONST_SYMBOL *psConst)
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//debug( LOG_SCRIPT, "END scriptGetConstToken" );
|
||||
}
|
||||
|
||||
/* Get the token type for a function symbol */
|
||||
|
@ -179,17 +177,8 @@ SDWORD scriptGetFuncToken(FUNC_SYMBOL *psFunc)
|
|||
{
|
||||
BOOL object;
|
||||
|
||||
//debug( LOG_SCRIPT, "scriptGetFuncToken" );
|
||||
|
||||
// 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;
|
||||
}
|
||||
object = asScrTypeTab[psFunc->type - VAL_USERTYPESTART].accessType == AT_OBJECT;
|
||||
|
||||
if (object)
|
||||
{
|
||||
|
@ -206,6 +195,9 @@ SDWORD scriptGetFuncToken(FUNC_SYMBOL *psFunc)
|
|||
// case VAL_FLOAT:
|
||||
return NUM_FUNC;
|
||||
break;
|
||||
case VAL_STRING:
|
||||
return STRING_FUNC;
|
||||
break;
|
||||
case VAL_VOID:
|
||||
return FUNC;
|
||||
break;
|
||||
|
@ -214,26 +206,18 @@ SDWORD scriptGetFuncToken(FUNC_SYMBOL *psFunc)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//debug( LOG_SCRIPT, "END scriptGetFuncToken" );
|
||||
}
|
||||
|
||||
|
||||
/* 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
|
||||
|
@ -241,30 +225,23 @@ SDWORD scriptGetCustomFuncToken(EVENT_SYMBOL *psFunc)
|
|||
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" );
|
||||
case 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" );
|
||||
}
|
||||
|
||||
|
||||
|
@ -291,10 +268,12 @@ inactive return INACTIVE;
|
|||
init return INITIALISE;
|
||||
link return LINK;
|
||||
ref return REF;
|
||||
return return RET;
|
||||
function return FUNCTION;
|
||||
|
||||
/* function return FUNCTION;*/
|
||||
/* cond return COND; */
|
||||
|
||||
/* new stuff */
|
||||
function return FUNCTION;
|
||||
return { return RET; }
|
||||
|
||||
public { scr_lval.stype = ST_PUBLIC; return STORAGE; }
|
||||
private { scr_lval.stype = ST_PRIVATE; return STORAGE; }
|
||||
|
@ -306,15 +285,15 @@ exit return EXIT;
|
|||
pause return PAUSE;
|
||||
|
||||
/* Match to type key words */
|
||||
void { scr_lval.tval = VAL_VOID; return TYPE; }
|
||||
VOID { scr_lval.tval = VAL_VOID; return TYPE; }
|
||||
string { scr_lval.tval = VAL_STRING; return TYPE; }
|
||||
STRING { scr_lval.tval = VAL_STRING; return TYPE; }
|
||||
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; }
|
||||
|
||||
/*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; } */
|
||||
|
@ -346,64 +325,63 @@ NOT return _NOT;
|
|||
-?[0-9]+ { scr_lval.ival = atol(scr_text); return INTEGER; }
|
||||
|
||||
/* Match identifiers */
|
||||
[a-zA-Z][0-9_a-zA-Z]* {
|
||||
//debug( LOG_SCRIPT, "FLEX: looking up '%s'", scr_text );
|
||||
|
||||
[a-zA-Z_][0-9_a-zA-Z_]* {
|
||||
debug(LOG_SCRIPT, "looking up '%s'", scr_text);
|
||||
/* See if this identifier has been defined as a type */
|
||||
if (scriptLookUpType(scr_text, &scr_lval.tval))
|
||||
{
|
||||
DBP0(("[lex] TYPE\n"));
|
||||
debug(LOG_SCRIPT, "'%s' is a type", scr_text);
|
||||
return TYPE;
|
||||
}
|
||||
/* See if this identifier has been defined as a variable */
|
||||
else if (scriptLookUpVariable(scr_text, &scr_lval.vSymbol))
|
||||
{
|
||||
DBP0(("[lex] variable\n"));
|
||||
debug(LOG_SCRIPT, "'%s' is a var", scr_text);
|
||||
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"));
|
||||
debug(LOG_SCRIPT, "'%s' is a constant", scr_text);
|
||||
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"));
|
||||
debug(LOG_SCRIPT, "'%s' is a function", scr_text);
|
||||
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 );
|
||||
debug(LOG_SCRIPT, "'%s' is a cust func", scr_text);
|
||||
return scriptGetCustomFuncToken(scr_lval.eSymbol);
|
||||
}
|
||||
|
||||
else if (scriptLookUpTrigger(scr_text, &scr_lval.tSymbol))
|
||||
{
|
||||
DBP0(("[lex] TRIG_SYM\n"));
|
||||
debug(LOG_SCRIPT, "'%s' is a trigger", scr_text);
|
||||
return TRIG_SYM;
|
||||
}
|
||||
else if (scriptLookUpEvent(scr_text, &scr_lval.eSymbol))
|
||||
{
|
||||
DBP0(("[lex] EVENT_SYM\n"));
|
||||
debug(LOG_SCRIPT, "'%s' is an event", scr_text);
|
||||
|
||||
return EVENT_SYM;
|
||||
}
|
||||
else if (scriptLookUpCallback(scr_text, &scr_lval.cbSymbol))
|
||||
{
|
||||
DBP0(("[lex] CALLBACK_SYM\n"));
|
||||
debug(LOG_SCRIPT, "'%s' is a callback", scr_text);
|
||||
return CALLBACK_SYM;
|
||||
}
|
||||
else
|
||||
{
|
||||
//debug( LOG_SCRIPT, "FLEX: '%s' is an ident", scr_text );
|
||||
|
||||
debug(LOG_SCRIPT, "'%s' is an ident", scr_text);
|
||||
|
||||
strcpy(aText[currText], scr_text);
|
||||
scr_lval.sval = aText[currText];
|
||||
currText = (currText + 1) % TEXT_BUFFERS;
|
||||
DBP0(("[lex] IDENT\n"));
|
||||
return IDENT;
|
||||
}
|
||||
}
|
||||
|
@ -415,6 +393,7 @@ NOT return _NOT;
|
|||
strcpy(aText[currText], scr_text);
|
||||
scr_lval.sval = aText[currText];
|
||||
currText = (currText + 1) % TEXT_BUFFERS;
|
||||
debug(LOG_SCRIPT, "%s is QTEXT", scr_text);
|
||||
return QTEXT;
|
||||
}
|
||||
|
||||
|
@ -458,7 +437,7 @@ int scr_wrap(void)
|
|||
{
|
||||
if (inComment)
|
||||
{
|
||||
DBERROR(("Warning: reched end of file in a comment"));
|
||||
DBERROR(("Warning: reached end of file in a comment"));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -12,10 +12,13 @@
|
|||
#include "codeprint.h"
|
||||
#include "script.h"
|
||||
|
||||
#include "script_parser.h"
|
||||
|
||||
/* number of values in each stack chunk */
|
||||
#define INIT_SIZE 15
|
||||
#define EXT_SIZE 2
|
||||
|
||||
|
||||
/* store for a 'chunk' of the stack */
|
||||
typedef struct _stack_chunk
|
||||
{
|
||||
|
@ -92,6 +95,15 @@ BOOL stackPush(INTERP_VAL *psVal)
|
|||
valid space */
|
||||
memcpy(&(psCurrChunk->aVals[currEntry]), psVal, sizeof(INTERP_VAL));
|
||||
|
||||
/* String support: Copy the string, otherwise the stack will operate directly on the
|
||||
original string (like & opcode will actually store the result in the first
|
||||
variable which would point to the original string) */
|
||||
if(psVal->type == VAL_STRING)
|
||||
{
|
||||
psCurrChunk->aVals[currEntry].v.sval = (char*)MALLOC(MAXSTRLEN);
|
||||
strcpy(psCurrChunk->aVals[currEntry].v.sval,psVal->v.sval);
|
||||
}
|
||||
|
||||
/* Now update psCurrChunk and currEntry */
|
||||
currEntry++;
|
||||
if (currEntry == psCurrChunk->size)
|
||||
|
@ -100,6 +112,7 @@ BOOL stackPush(INTERP_VAL *psVal)
|
|||
if (!stackNewChunk(EXT_SIZE))
|
||||
{
|
||||
/* Out of memory */
|
||||
debug(LOG_ERROR, "stackPush: Out of memory");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -114,6 +127,7 @@ BOOL stackPop(INTERP_VAL *psVal)
|
|||
{
|
||||
if ((psCurrChunk->psPrev == NULL) && (currEntry == 0))
|
||||
{
|
||||
debug(LOG_ERROR, "stackPop: stack empty");
|
||||
ASSERT((FALSE, "stackPop: stack empty"));
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -171,11 +185,39 @@ BOOL stackPopType(INTERP_VAL *psVal)
|
|||
|
||||
//debug(LOG_SCRIPT, "stackPopType 4");
|
||||
|
||||
if (!interpCheckEquiv(psVal->type,psTop->type))
|
||||
//String support
|
||||
if(psVal->type == VAL_STRING) //If we are about to assign something to a string variable (psVal)
|
||||
{
|
||||
debug(LOG_ERROR, "stackPopType: type mismatch");
|
||||
ASSERT((FALSE, "stackPopType: type mismatch"));
|
||||
return FALSE;
|
||||
if(psTop->type != VAL_STRING) //if assigning a non-string to a string, then convert it
|
||||
{
|
||||
/* Check for compatible types */
|
||||
if((psTop->type == VAL_INT) || (psTop->type == VAL_BOOL))
|
||||
{
|
||||
STRING *tempstr;
|
||||
tempstr = (char*)MALLOC(MAXSTRLEN);
|
||||
sprintf(tempstr, "%d", psTop->v.ival);
|
||||
|
||||
psVal->v.sval = tempstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug(LOG_ERROR, "stackPopType: trying to assign an incompatible data type to a string variable (type = %d)", psTop->type);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else //Assigning a string to a string, just do the default action
|
||||
{
|
||||
psVal->v.ival = psTop->v.ival;
|
||||
}
|
||||
}
|
||||
else // we are about to assign something to a non-string variable (psVal)
|
||||
{
|
||||
if (!interpCheckEquiv(psVal->type,psTop->type))
|
||||
{
|
||||
debug(LOG_ERROR, "stackPopType: type mismatch");
|
||||
ASSERT((FALSE, "stackPopType: type mismatch"));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//debug(LOG_SCRIPT, "stackPopType 5");
|
||||
|
@ -202,6 +244,8 @@ BOOL stackPopParams(SDWORD numParams, ...)
|
|||
UDWORD index, params;
|
||||
STACK_CHUNK *psCurr;
|
||||
|
||||
//debug(LOG_SCRIPT,"stackPopParams");
|
||||
|
||||
va_start(args, numParams);
|
||||
|
||||
// Find the position of the first parameter, and set
|
||||
|
@ -232,12 +276,19 @@ BOOL stackPopParams(SDWORD numParams, ...)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//debug(LOG_SCRIPT,"stackPopParams 1");
|
||||
|
||||
if (!psCurr)
|
||||
{
|
||||
debug(LOG_ERROR,"stackPopParams: not enough parameters on stack");
|
||||
ASSERT((FALSE, "stackPopParams: not enough parameters on stack"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//debug(LOG_SCRIPT,"stackPopParams 2");
|
||||
|
||||
//string support
|
||||
// Get the values, checking their types
|
||||
index = currEntry;
|
||||
for (i=0; i< numParams; i++)
|
||||
|
@ -245,14 +296,45 @@ BOOL stackPopParams(SDWORD numParams, ...)
|
|||
type = va_arg(args, int);
|
||||
pData = va_arg(args, UDWORD *);
|
||||
|
||||
//debug(LOG_SCRIPT,"stackPopParams 3 (%d parameter)", i);
|
||||
|
||||
psVal = psCurr->aVals + index;
|
||||
if (!interpCheckEquiv(type,psVal->type))
|
||||
|
||||
if(type != VAL_STRING) //Allow param to be any type, if function expects a string (auto-convert later)
|
||||
{
|
||||
ASSERT((FALSE, "stackPopParams: type mismatch"));
|
||||
va_end(args);
|
||||
return FALSE;
|
||||
//debug(LOG_SCRIPT,"stackPopParams 4 - non string");
|
||||
|
||||
if (!interpCheckEquiv(type,psVal->type))
|
||||
{
|
||||
ASSERT((FALSE, "stackPopParams: type mismatch"));
|
||||
va_end(args);
|
||||
return FALSE;
|
||||
}
|
||||
*pData = (UDWORD)psVal->v.ival;
|
||||
}
|
||||
else //TODO: allow only compatible types
|
||||
{
|
||||
//debug(LOG_SCRIPT,"stackPopParams 5 - string");
|
||||
|
||||
if(psVal->type == VAL_STRING) //Passing a String
|
||||
{
|
||||
|
||||
//debug(LOG_SCRIPT, "stackPopParams - string");
|
||||
*pData = (UDWORD)psVal->v.ival;
|
||||
debug(LOG_SCRIPT, "%s",*pData);
|
||||
}
|
||||
else //Integer
|
||||
{
|
||||
STRING *tempstr;
|
||||
//debug(LOG_SCRIPT, "stackPopParams - non string");
|
||||
tempstr = (char*)MALLOC(MAXSTRLEN);
|
||||
sprintf(tempstr, "%d", psVal->v.ival);
|
||||
|
||||
*pData = tempstr;
|
||||
|
||||
//itoa(psVal->v.ival,tmpstr,10);
|
||||
}
|
||||
}
|
||||
*pData = (UDWORD)psVal->v.ival;
|
||||
|
||||
index += 1;
|
||||
if (index >= psCurr->size)
|
||||
|
@ -262,6 +344,8 @@ BOOL stackPopParams(SDWORD numParams, ...)
|
|||
}
|
||||
}
|
||||
|
||||
//debug(LOG_SCRIPT,"END stackPopParams");
|
||||
|
||||
va_end(args);
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -356,6 +440,7 @@ BOOL stackBinaryOp(OPCODE opcode)
|
|||
// Get the parameters
|
||||
if (psCurrChunk->psPrev == NULL && currEntry < 2)
|
||||
{
|
||||
debug(LOG_ERROR, "stackBinaryOp: not enough entries on stack");
|
||||
ASSERT((FALSE, "stackBinaryOp: not enough entries on stack"));
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -383,10 +468,14 @@ BOOL stackBinaryOp(OPCODE opcode)
|
|||
psV2 = psCurrChunk->aVals + psCurrChunk->size - 1;
|
||||
}
|
||||
|
||||
if (!interpCheckEquiv(psV1->type, psV2->type))
|
||||
if(opcode != OP_CANC) //string - Don't check if OP_CANC, since types can be mixed here
|
||||
{
|
||||
ASSERT((FALSE, "stackBinaryOp: type mismatch"));
|
||||
return FALSE;
|
||||
if (!interpCheckEquiv(psV1->type, psV2->type))
|
||||
{
|
||||
debug(LOG_ERROR, "stackBinaryOp: type mismatch");
|
||||
ASSERT((FALSE, "stackBinaryOp: type mismatch"));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// do the operation
|
||||
|
@ -434,7 +523,53 @@ BOOL stackBinaryOp(OPCODE opcode)
|
|||
psV1->type = VAL_BOOL;
|
||||
psV1->v.bval = psV1->v.ival < psV2->v.ival;
|
||||
break;
|
||||
case OP_CANC: //String cancatenation
|
||||
{
|
||||
char *tempstr1[MAXSTRLEN];
|
||||
char *tempstr2[MAXSTRLEN];
|
||||
|
||||
/* Check first value if it's compatible with Strings */
|
||||
if((psV1->type == VAL_INT) || (psV1->type == VAL_BOOL)) //First value isn't string, but can be converted to string
|
||||
{
|
||||
sprintf(tempstr1,"%d",psV1->v.ival); //Convert
|
||||
|
||||
psV1->type = VAL_STRING; //Mark as string now
|
||||
}
|
||||
else if(psV1->type == VAL_STRING) //Is a string
|
||||
{
|
||||
strcpy(tempstr1,psV1->v.sval);
|
||||
}
|
||||
else
|
||||
{
|
||||
debug(LOG_ERROR, "stackBinaryOp: OP_CANC: first parameter is not compatible with Strings");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check first value if it's compatible with Strings */
|
||||
if((psV2->type == VAL_INT) || (psV2->type == VAL_BOOL))
|
||||
{
|
||||
sprintf(tempstr2,"%d",psV2->v.ival); //Convert
|
||||
}
|
||||
else if(psV2->type == VAL_STRING) //Is a string
|
||||
{
|
||||
strcpy(tempstr2,psV2->v.sval);
|
||||
}
|
||||
else
|
||||
{
|
||||
debug(LOG_ERROR, "stackBinaryOp: OP_CANC: first parameter is not compatible with Strings");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
strcat(tempstr1,tempstr2);
|
||||
|
||||
strcpy(psV1->v.sval,tempstr1); //Assign
|
||||
|
||||
psV1->type = VAL_STRING;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
debug(LOG_ERROR, "stackBinaryOp: unknown opcode");
|
||||
ASSERT((FALSE, "stackBinaryOp: unknown opcode"));
|
||||
return FALSE;
|
||||
break;
|
||||
|
@ -512,12 +647,14 @@ BOOL stackInitialise(void)
|
|||
psStackBase = (STACK_CHUNK *)MALLOC(sizeof(STACK_CHUNK));
|
||||
if (psStackBase == NULL)
|
||||
{
|
||||
debug(LOG_ERROR, "Out of memory");
|
||||
DBERROR(("Out of memory"));
|
||||
return FALSE;
|
||||
}
|
||||
psStackBase->aVals = MALLOC(sizeof(INTERP_VAL) * INIT_SIZE);
|
||||
if (!psStackBase->aVals)
|
||||
{
|
||||
debug(LOG_ERROR, "Out of memory");
|
||||
DBERROR(("Out of memory"));
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -527,6 +664,9 @@ BOOL stackInitialise(void)
|
|||
psStackBase->psNext = NULL;
|
||||
psCurrChunk = psStackBase;
|
||||
|
||||
//string support
|
||||
CURSTACKSTR = 0; //initialize string 'stack'
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,4 +46,6 @@ extern BOOL stackUnaryOp(OPCODE opcode);
|
|||
/* Reset the stack to an empty state */
|
||||
extern void stackReset(void);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -6405,3 +6405,35 @@ BOOL scrEnumDroid(void)
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------
|
||||
//New functions
|
||||
//-----------------------------------------
|
||||
|
||||
//compare two strings (0 means they are different)
|
||||
BOOL scrStrcmp(void)
|
||||
{
|
||||
STRING *ssval1=NULL;
|
||||
STRING *ssval2=NULL;
|
||||
|
||||
debug(LOG_SCRIPT,"scrStrcmp");
|
||||
|
||||
if (!stackPopParams(2, VAL_STRING, &ssval1, VAL_STRING, &ssval2))
|
||||
{
|
||||
debug(LOG_ERROR, "scrStrcmp(): stack failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
debug(LOG_SCRIPT,"scrStrcmp 1");
|
||||
|
||||
if (!stackPushResult(VAL_BOOL, !strcmp(ssval1, ssval2)))
|
||||
{
|
||||
debug(LOG_ERROR, "scrStrcmp: failed to push result");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
debug(LOG_SCRIPT,"scrStrcmp 2");
|
||||
|
||||
return TRUE;
|
||||
}
|
|
@ -496,6 +496,11 @@ extern BOOL scrResetLimboMission(void);
|
|||
// skirmish lassat fire.
|
||||
extern BOOL scrSkFireLassat(void);
|
||||
|
||||
//-----------------------------------------
|
||||
//New functions
|
||||
//-----------------------------------------
|
||||
|
||||
extern BOOL scrStrcmp(void);
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -698,6 +698,13 @@ FUNC_SYMBOL asFuncTable[] =
|
|||
{ "skFireLassat", scrSkFireLassat, VAL_VOID,
|
||||
2, {VAL_INT, (INTERP_TYPE)ST_BASEOBJECT } },
|
||||
|
||||
/* New functions */
|
||||
|
||||
{ "strcmp", scrStrcmp, VAL_BOOL,
|
||||
2, { VAL_STRING, VAL_STRING} },
|
||||
|
||||
/* END new functions */
|
||||
|
||||
|
||||
// { "skOrderDroidLineBuild", scrSkOrderDroidLineBuild, VAL_VOID,
|
||||
// 6, { (INTERP_TYPE)ST_DROID, (INTERP_TYPE)ST_STRUCTURESTAT, VAL_INT, VAL_INT, VAL_INT, VAL_INT } },
|
||||
|
|
Loading…
Reference in New Issue