//deletempeg() : unload mpeg video void basDeleteMpeg() { int ret; ret=deletempeg(); if (ret==-1) ePrintf( Runtime, "SDLengine Error \n"); pushNumber(ret); }
//pausempeg() : Pause/Resume playback of an SMPEG object void basPauseMpeg() { int ret; ret=pausempeg(); if (ret==-1) ePrintf( Runtime, "SDLengine Error \n"); pushNumber(ret); }
//rewindmpeg() : Rewind the play position of an SMPEG object to the beginning of the MPEG void basRewindMpeg() { int ret; ret=rewindmpeg(); if (ret==-1) ePrintf( Runtime, "SDLengine Error \n"); pushNumber(ret); }
//stopmpeg() : terminate the video play void basStopMpeg() { int ret; ret=stopmpeg(); if (ret==-1) ePrintf( Runtime, "SDLengine Error \n"); pushNumber(ret); }
void Gameplay::initializeNumbers() { std::fill(reachable, reachable + MAX_SUM, false); reachable[0] = true; sumOfNumbers = 0; for (Number n : numbers) { pushNumber(n, false); } }
//seekmpeg(p) : Seek 'bytes' bytes in the MPEG stream void basSeekMpeg() { int p; int ret; p=popNumber(); ret=seekmpeg(p); if (ret==-1) ePrintf( Runtime, "SDLengine Error \n"); pushNumber(ret); }
//skipmpeg(s) : Skip 'seconds' seconds in the MPEG stream void basSkipMpeg() { double p; int ret; p=popNumber(); ret=skipmpeg(p); if (ret==-1) ePrintf( Runtime, "SDLengine Error \n"); pushNumber(ret); }
/* numberRangeCompare: range test for case */ void numberRangeCompare() { Number high, low, n; high = popNumber(); low = popNumber(); n = stack[tos].value.number; pushNumber( n >= low && n <= high ); }
void basLoadMpeg() { char *fname; int usesound; int ret; usesound=popNumber(); fname=popString(); ret=loadmpeg(fname,usesound); if (ret==-1) ePrintf( Runtime, "SDLengine Error \n"); pushNumber(ret); }
//plaympeg(optional loop) : play a mpeg1 video void basPlayMpeg() { int loop; int ret; if (argCount==1) loop=popNumber(); else loop=0; ret=plaympeg(loop); if (ret==-1) ePrintf( Runtime, "SDLengine Error \n"); pushNumber(ret); }
/* stringRangeCompare: range test for case */ void stringRangeCompare() { char *stringHigh, *stringLow, *string; stringHigh = popString(); stringLow = popString(); string = stack[tos].value.string; pushNumber( strcmp(string, stringLow) > -1 && strcmp(string, stringHigh) < 1 ); eFree( stringLow ); eFree( stringHigh ); }
/* stringCompare: compare two strings on the stack */ void stringCompare( int op, int popFlag ) { char *string1, *string2; string2 = popString(); if (popFlag) { string1 = popString(); } else { string1 = stack[tos].value.string; } eMemTest( "stringCompare: string1", string1 ); eMemTest( "stringCompare: string2", string2 ); switch( op ) { case EQ: pushNumber( strcmp(string1,string2) == 0 ); break; case NE: pushNumber( strcmp(string1,string2) != 0 ); break; case GT: pushNumber( strcmp(string1,string2) == 1 ); break; case LT: pushNumber( strcmp(string1,string2) == -1 ); break; case GE: pushNumber( strcmp(string1,string2) > -1 ); break; case LE: pushNumber( strcmp(string1,string2) < 1 ); break; default: ePrintf( Runtime, "OpCmp: bad operator" ); } eFree( string2 ); if (popFlag) { eFree( string1 ); } }
/* numberCompare: compare two numbers on the stack */ void numberCompare( int op, int popFlag ) { Number n1, n2; n2 = popNumber(); if (popFlag) { n1 = popNumber(); } else { n1 = stack[tos].value.number; } switch (op) { case EQ: pushNumber( abs(n1 - n2) <= ALLOWABLE_ERROR ); break; case NE: pushNumber( n1 != n2 ); break; case GT: pushNumber( n1 > n2 ); break; case LT: pushNumber( n1 < n2 ); break; case GE: pushNumber( n1 >= n2 ); break; case LE: pushNumber( n1 <= n2 ); break; default: ePrintf( Runtime, "numberCompare: bad operator" ); } }
/** * Parses the postfix expression for the given code line in the parameter. * While doing this, prints the intermediate states of the number stack * using printNumberStackContent function. * @param codeLine The code line which will be calculated. * @param destination The name of destination variable. */ void parsePostfixExpression(struct code_line *codeLine, char destination) { int i = 0; while (i < codeLine->lineContentPostfix.postfixLength) { if (isspace(codeLine->lineContentPostfix.postfixExpression[i])) { i++; } else { if (isNumberOrVariable( codeLine->lineContentPostfix.postfixExpression[i])) { if (isalpha( (codeLine->lineContentPostfix.postfixExpression[i]))) { // if the character is a variable pushNumber( variableValues[tolower( codeLine->lineContentPostfix.postfixExpression[i++]) - 'a']); } else { // if the character is a number char numberString[NUMBER_LENGTH]; size_t j = 0; while (!isspace( codeLine->lineContentPostfix.postfixExpression[i])) { numberString[j++] = codeLine->lineContentPostfix.postfixExpression[i++]; } numberString[j] = '\0'; double numberValue = strToDouble(numberString, j); pushNumber(numberValue); } } else { // if the character is an operation sign character double number1, number2; number2 = popNumber(); number1 = popNumber(); switch (codeLine->lineContentPostfix.postfixExpression[i++]) { case '+': pushNumber(number1 + number2); break; case '-': pushNumber(number1 - number2); break; case '*': pushNumber(number1 * number2); break; case '/': if (number2 == 0) { fprintf(stderr, "ERROR: You can not divide by zero."); exit(EXIT_FAILURE); } pushNumber(number1 / number2); break; default: fprintf(stderr, "ERROR: Unexpected character in the postfix expression."); exit(EXIT_FAILURE); break; } } printf("Stack: "); printNumberStackContent(); printf("\n"); } } double finalValue = popNumber(); variableValues[tolower(destination) - 'a'] = finalValue; codeLine->finalValue = finalValue; }
/* callFunction: call a user defined function */ void callFunction( Node *node ) { int priorLocalStart, priorTos, numArgs, localCount, i; Symbol *s; /* return value */ pushNumber( 0 ); /* argc */ pushNumber( 0 ); /* start of local variables */ priorLocalStart = localstart; priorTos = tos; /* mark start of created objects */ pushCreateStack( 0 ); /* evaluate parameters */ eval( node->left ); /* number of args */ numArgs = (tos-priorTos); stack[priorTos].value.number = (Number)numArgs; /* get routine */ s = node->value.symbol; if (s->forward) { ePrintf( Runtime, "%s has not been defined yet", s->name ); } /* currentScope in runtime */ oldScope[++oldScopeP]=currentScope; if (oldScopeP>255)ePrintf( Runtime, "stack oldScope overflow"); currentScope=s; /* allocate locals */ localCount = s->optargs + s->locals; for ( i = 0; i < (localCount - numArgs); i++ ) { pushNumber( 0 ); } /* set start of locals */ localstart = priorTos; /* run code */ eval( s->code ); /* exit routine flag set? */ if (exitRoutineFlag != 0) { exitRoutineFlag = 0; } /* resume oldScope */ currentScope=oldScope[oldScopeP--]; if (oldScopeP<0)ePrintf( Runtime, "stack oldScope underflow"); /* destroy created objects */ clearCreateStack(); /* clear locals off stack */ for ( i = localCount; i > 0; i-- ) { /* need to free record? */ if ( i > numArgs && stack[tos].datatype == DATA_ARRAY) { freeArray( stack[tos].value.array ); } popNumber(); } /* drop argc */ dropTos(); /* check stack */ if (priorTos > tos+1) { ePrintf( Runtime, "callFunction: %s(): stack underflow", s->name ); } else if (priorTos < tos+1) { ePrintf( Runtime, "callFunction: %s(): garbage on stack", s->name ); } /* drop result? */ if (node->op == OpFunctionCall) { dropTos(); } /* restore marker */ localstart = priorLocalStart; }
void eval( Node *node ) { int i, j; Number n1, n2, n3, n4; char *string1; Symbol *s; Node *n; Array *a; /* debugging */ #ifdef __DEBUG_TRACE__ SourceCode *sc; #endif /* init vars */ n1=0; n2=0; n3=0; n4=0; if (node == NULL) { return; } /* test node */ eMemTest( "eval: node is corrupt", node ); eMemTest( "eval: node->left is corrupt", node->left ); eMemTest( "eval: node->right is corrupt", node->right ); /* tracing */ if (node->trace != -1) { runLineId = node->trace; #ifdef __DEBUG_TRACE__ sc = eFindSource( runLineId ); eConsole("%d: %s\n", sc->lineNum, sc->text ); #endif /* sdlBasic_debugging */ if (debug==1){ screendebug(); //////////////////////////////////// } } /* debugging */ #ifdef __DEBUG_TRACE__ eConsole( "Op:%s\n", opcodeName[node->op] ); #endif switch( node->op ) { //case NULL: // break; case OpAdd: eval( node->left ); eval( node->right ); /* add or concat? */ if (getStackType( tos ) == DATA_STRING) { basConcat(); } else { n2 = popNumber(); n1 = popNumber(); pushNumber( n1 + n2 ); } break; case OpAnd: /* short circuit */ eval( node->left ); if (!popNumber()) { pushNumber( (Number)0 ); } else { eval( node->right ); if (popNumber()) { pushNumber( (Number)1 ); } else { pushNumber( (Number)0 ); } } break; case OpArgList: eval( node->left ); eval( node->right ); break; case OpArrayGet: eval( node->left ); /* indices and index */ getArrayElement( node->value.symbol ); break; case OpArrayPtr: pushArray( node->value.symbol ); break; case OpArraySet: eval( node->right ); /* value to store */ eval( node->left ); /* indices and index */ setArrayElement( node->value.symbol ); break; case OpAssign: /* value to be assigned. note the *right* node is used */ eval( node->right ); /* variable to assign to */ setVar( node->value.symbol ); break; case OpBuiltin: case OpBuiltinCall: /* for argcount */ n1 = tos; /* mark start of created objects */ pushCreateStack( 0 ); /* the args */ eval( node->left ); /* builtin symbol */ s = node->value.symbol; if (s == NULL) { ePrintf( Runtime, "builtin pointer is null"); } /* set args */ argCount = (int)(tos - n1); /* call the c function */ (*s->builtin)(); /* destroy created objects */ clearCreateStack(); /* drop result? */ if (node->op == OpBuiltinCall) { dropTos(); } break; case OpCaseSelect: /* top level of a case statement */ /* value to compare */ eval( node->left ); /* resolve into real data */ switch (getStackType( tos )) { case DATA_NUMBER: pushNumber( popNumber() ); break; case DATA_STRING: pushString( popString() ); break; default: ePrintf( Runtime, "OpCaseSelect: can't resolve type %s", datumName[getStackType( tos )] ); } /* get first test */ if (node == NULL) { /* no tests */ break; } else { node = node->right; } /* walk the chain of cases */ while (1) { /* get a test/action pair */ n = node->left; /* perform the tests */ eval( n->left ); /* true? */ if (popNumber()) { /* perform action and leave loop */ eval( n->right ); break; } /* move to next test */ node = node->right; if (node == NULL) { break; } } /* drop the test value from the stack */ dropTos(); break; case OpCaseCmp: case OpCaseRange: case OpCaseElse: /* perform chain of tests until true or end */ while (1) { switch (node->op) { case OpCaseCmp: /* value to compare */ eval(node->left); /* what type of test? */ switch (getStackType( tos-1 )) { case DATA_NUMBER: numberCompare( node->value.iValue, 0 ); break; case DATA_STRING: stringCompare( node->value.iValue, 0 ); break; default: ePrintf( Runtime, "OpCaseCmp: bad data type" ); } break; case OpCaseRange: /* values to compare */ n = node->left; eval( n->left ); eval( n->right ); /* what type of comparison? */ switch (getStackType( tos-2 )) { case DATA_NUMBER: numberRangeCompare(); break; case DATA_STRING: stringRangeCompare(); break; default: ePrintf( Runtime, "OpCaseRange: bad data type" ); break; } break; case OpCaseElse: /* put true on stack */ pushNumber( 1 ); break; default: ePrintf( Runtime, "opcode %s found in Case test chain", opcodeName[node->op] ); } /* was result true? */ if (stack[tos].value.number) { /* leave true flag on stack and exit */ break; } /* move to next test */ node = node->right; if (node == NULL) { /* exit with false flag */ break; } /* drop test result flag */ dropTos(); } break; case OpClassMethod: case OpClassMethodCall: /* the args */ n1 = tos; /* mark start of created objects */ pushCreateStack( 0 ); /* the args */ eval( node->right ); argCount = (int)(tos - n1); me = 0; runMethod( node->left->value.symbol->klass, node->value.string ); /* destroy created objects */ clearCreateStack(); /* drop result? */ if (node->op == OpClassMethodCall) { dropTos(); } break; case OpClose: if (node->left == NULL) { fileCloseAll(); } else { eval( node->left ); i = (int)popNumber(); fileClose( i ); } break; case OpCmp: eval( node->left ); eval( node->right ); switch(getStackType(tos)) { case DATA_NUMBER: numberCompare( node->value.iValue, 1 ); break; case DATA_STRING: stringCompare( node->value.iValue, 1 ); break; default: ePrintf( Runtime, "opCmp: can't handle datatype" ); } break; case OpComma: /* optimized for linked lists */ while (1) { /* exit flag set? */ if (exitForFlag != 0 || exitRoutineFlag != 0 || exitDoFlag != 0 || exitWhileFlag != 0 || continueFlag ) { break; } if (node->left != NULL ) { eval( node->left ); } /* end of list? */ if (node->right == NULL ) { break; /* linked list? */ } else if (node->right->op == OpComma) { node = node->right; /* not a list */ } else { eval( node->right ); break; } } break; case OpConcat: eval( node->left ); eval( node->right ); basConcat(); break; case OpConstGet: s = node->value.symbol; i = s->stackPos; /* this better not be indirected! */ switch (stack[i].datatype) { case DATA_STRING: pushString( stack[i].value.string ); break; case DATA_NUMBER: pushNumber( stack[i].value.number ); break; default: ePrintf( Runtime, "Can't fetch Const type %s", datumName[stack[i].datatype] ); break; } break; case OpConstSet: s = node->value.symbol; eval( node->left ); switch (stack[tos].datatype) { case DATA_STRING: stack[s->stackPos].datatype = DATA_STRING; stack[s->stackPos].value.string = stack[tos].value.string; stack[tos].datatype = DATA_NUMBER; tos--; break; case DATA_NUMBER: stack[s->stackPos].datatype = DATA_NUMBER; stack[s->stackPos].value.number = stack[tos].value.number; tos--; break; default: ePrintf( Runtime, "Can't set Const to %s", datumName[stack[tos].datatype] ); break; } break; case OpDelete: eval( node->left ); runDestructor( (int)popNumber(), OpDelete ); break; case OpDestroy: eval( node->left ); runDestructor( (int)popNumber(), OpDestroy ); break; case OpContinue: continueFlag = 1; break; case OpDiv: eval( node->left ); eval( node->right ); n2 = popNumber(); n1 = popNumber(); if (n2 == 0.0) { ePrintf( Runtime, "Division by zero" ); } pushNumber( n1 / n2 ); break; case OpDo: while (1) { /* test */ eval( node->left ); /*if (!popNumber()){ break; }*/ /* code */ eval( node->right ); //printf("exitDoFlag:%d\n",exitDoFlag); if (exitDoFlag != 0) { exitDoFlag = 0; break; } else if (continueFlag) { continueFlag = 0; } } break; case OpEnd: eShutdown(0); break; case OpErase: if (node->left == NULL) { /* erase entire array */ eraseArray( node->value.symbol ); } else { /* evaluate the indexes */ eval( node->left ); /* erase single element from array */ eraseArrayElement( node->value.symbol ); } break; case OpExitDo: exitDoFlag = 1; break; case OpExitFor: exitForFlag = 1; break; case OpExitRoutine: currentScope=oldScope[oldScopeP--]; exitRoutineFlag = 1; break; case OpExitWhile: exitWhileFlag = 1; break; case OpFloat: pushNumber( node->value.fValue ); break; case OpFor: s = node->value.symbol; eval( node->left ); n2 = popNumber(); n1 = popNumber(); /* initial value */ pushNumber( n3 ); setVar( s ); for( n3=n1; n3 <= n2; n3++ ) { /* set loop variable */ pushNumber( n3 ); setVar( s ); /* run code */ eval( node->right ); /* special exit condition? */ if (exitForFlag) { exitForFlag = 0; break; } else if (continueFlag) { continueFlag = 0; } /* get loop value (in case it changed) */ getVar( s ); n3 = popNumber(); } break; case OpForEach: /* variable to assign */ s = node->value.symbol; /* array to read from */ a = getArray( node->left->value.symbol ); /* iterate through keys */ i = 0; /* put key on stack, or exit */ while (getDynamicKey( a, i )) { /* assign to variable */ setVar( s ); /* run block */ eval( node->right ); /* next */ i += 1; } break; case OpForStep: s = node->value.symbol; eval( node->left ); n3 = popNumber(); /* step */ n2 = popNumber(); /* end */ n1 = popNumber(); /* start */ /* which direction? */ if (n3 > 0) { n2 += ALLOWABLE_ERROR; for( n4=n1; n2 >= n4; n4 += n3 ) { /* set loop variable */ pushNumber( n4 ); setVar( s ); /* run code */ eval( node->right ); /* special exit condition? */ if (exitForFlag) { exitForFlag = 0; break; } else if (continueFlag) { continueFlag = 0; } /* get loop value (in case it changed) */ getVar( s ); n4 = popNumber(); } } else { n2 -= ALLOWABLE_ERROR; for( n4=n1; n2 <= n4; n4 += n3 ) { /* set loop variable */ pushNumber( n4 ); setVar( s ); /* run code */ eval( node->right ); /* special exit condition? */ if (exitForFlag) { exitForFlag = 0; break; } else if (continueFlag) { continueFlag = 0; } /* get loop value (in case it changed) */ getVar( s ); n4 = popNumber(); } } break; case OpFunction: case OpFunctionCall: callFunction( node ); break; case OpInitArray: if (node->left == NULL) { createDynamicArray( node->value.symbol ); } else { eval( node->left ); createStaticArray( node->value.symbol ); } break; case OpInput: if (node->value.iValue == 1) { eval( node->left ); i = (int)popNumber(); string1 = fileLineInput( i ); pushString( string1 ); } else { /* command line */ ePrintf( Runtime, "Input statement is not currently supported" ); } break; case OpInt: pushNumber( node->value.iValue ); break; case OpMethod: case OpMethodCall: /* the index */ eval( node->left ); n1 = popNumber(); /* method name */ string1 = node->value.string; /* mark start of created objects */ pushCreateStack( 0 ); /* args */ n2 = tos; eval( node->right ); argCount = (int)(tos - n2); /* resolve and run method */ resolveMethod( (int)n1, string1 ); /* drop result? */ if (node->op == OpMethodCall) { dropTos(); } /* destroy created objects */ clearCreateStack(); break; case OpMod: eval( node->left ); eval( node->right ); n2 = popNumber(); n1 = popNumber(); //pushNumber( (long)n1 % (long)n2 ); pushNumber( fmod(n1,n2) ); break; case OpMul: eval( node->left ); eval( node->right ); n2 = popNumber(); n1 = popNumber(); pushNumber( n1 * n2 ); break; case OpOpen: /* file name */ eval( node->left ); string1 = popString(); /* mode */ i = node->value.iValue; /* file number */ eval( node->right ); n1 = popNumber(); fileOpen( string1, i, (int)n1 ); free( string1 ); break; case OpOr: /* short circuit */ eval( node->left ); if (popNumber()) { pushNumber( (Number)1 ); } else { eval( node->right ); if (popNumber()) { pushNumber( (Number)1 ); } else { pushNumber( (Number)0 ); } } break; case OpOrBits: eval( node->left ); eval( node->right); i = popNumber(); j = popNumber(); pushNumber( i | j ); break; case OpIDiv: eval( node->left ); eval( node->right ); n2 = popNumber(); n1 = popNumber(); /* check for division by zero */ if (n2 == 0.0) { ePrintf( Runtime, "Division by zero" ); } pushNumber( floor(n1 / n2) ); break; case OpIf: n = node->left; /* test */ eval( n->left ); n1 = popNumber(); if (n1 != 0) { /* true portion */ eval( n->right ); } else { /* false portion */ eval( node->right ); } break; case OpIfTrue: ePrintf( Runtime, "OpIfTrue: internal error" ); break; case OpIn: /* evaluate key */ eval( node->left ); /* look for it in array */ pushNumber( inArray( node->value.symbol ) ); break; case OpInv: ePrintf( Runtime, "Inv is not implemented yet" ); break; case OpNegate: eval( node->left ); n1 = popNumber(); pushNumber( -n1 ); break; case OpNew: case OpNewTmp: /* mark start of created objects */ pushCreateStack( 0 ); /* the args */ n1 = tos; eval( node->left ); argCount = (int)(tos - n1); runMethod( node->value.symbol->klass, "new" ); /* destroy created objects *before* adding new object to stack */ clearCreateStack(); /* add new object to create stack? */ if (node->op == OpNewTmp) { /* track on stack */ copyStackItem( tos ); pushCreateStack( (int)popNumber() ); } break; case OpNoOp: break; case OpNot: eval( node->left ); n1 = popNumber(); pushNumber( !n1 ); break; case OpPower: eval( node->left ); eval( node->right ); n2 = popNumber(); n1 = popNumber(); pushNumber( pow( n1, n2 ) ); break; case OpPrint: if (node->left == NULL) { i = 0; } else { eval( node->left ); i = (int)popNumber(); } node = node->right; /* empty print statement */ if (node == NULL) { if (i==0) { eConsole("\n"); } else { filePrintString( i, "\n" ); } } /* process nodes */ while(node != NULL) { /* data value */ if (node->left != NULL) { eval( node->left ); string1 = popString(); if (i==0) { eConsole("%s", string1 ); } else { filePrintString( i, string1 ); } eFree( string1 ); } /* field delimiter */ switch (node->value.iValue) { case PRINT_TAB: if (i==0) { eConsole("\t"); } else { filePrintString( i, "\t" ); } break; case PRINT_NEWLINE: if (i==0) { eConsole("\n"); } else { filePrintString( i, "\n" ); } break; default: /* no action */ break; } /* link */ node = node->right; } break; case OpReturnValue: eval( node->left ); setReturn(); exitRoutineFlag = 1; break; case OpReturnSetValue: eval( node->left ); setReturn(); break; case OpShl: eval( node->left ); eval( node->right ); n2 = popNumber(); n1 = popNumber(); pushNumber( (long)n1 << (long)n2 ); break; case OpShr: eval( node->left ); eval( node->right ); n2 = popNumber(); n1 = popNumber(); pushNumber( (long)n1 >> (long)n2 ); break; case OpString: pushStringCopy( node->value.string ); break; case OpSub: eval( node->left ); eval( node->right ); n2 = popNumber(); n1 = popNumber(); pushNumber( n1 - n2 ); break; case OpUndefined: ePrintf( Runtime, "Opcode is undefined" ); break; case OpVar: /* check type */ getVar( node->value.symbol ); if (getStackType(tos) == DATA_UNDEFINED) { ePrintf( Runtime, "the value of %s is undefined", node->value.symbol->name ); } break; case OpWhile: while (1) { /* test */ eval( node->left ); if (!popNumber()){ break; } /* code */ eval( node->right ); if (exitWhileFlag != 0) { exitWhileFlag = 0; break; } else if (continueFlag) { continueFlag = 0; } } break; case OpXor: eval( node->left ); eval( node->right ); n2 = popNumber(); n1 = popNumber(); pushNumber( (long)n1 ^ (long)n2 ); break; default: ePrintf( Runtime, "Unknown Opcode: %d", node->op ); } }
void Gameplay::addNumber() { pushNumber(currentLevel->nextNumber()); setNextNumberTimer(); }