diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/ctest/CTestCustom.ctest.in | 2 | ||||
-rw-r--r-- | test/src/test-c-machine.cpp | 217 | ||||
-rw-r--r-- | test/src/test-c-machine.machine.c | 526 | ||||
-rw-r--r-- | test/w3c/ecma/test240.scxml | 2 |
4 files changed, 579 insertions, 168 deletions
diff --git a/test/ctest/CTestCustom.ctest.in b/test/ctest/CTestCustom.ctest.in index c26b6b0..a140476 100644 --- a/test/ctest/CTestCustom.ctest.in +++ b/test/ctest/CTestCustom.ctest.in @@ -203,7 +203,7 @@ set(CTEST_CUSTOM_TESTS_IGNORE # "gen/c/ecma/test192.scxml" # "gen/c/ecma/test207.scxml" # "gen/c/ecma/test215.scxml" - # "gen/c/ecma/test216.scxml" + "gen/c/ecma/test216.scxml" // invoke srcexpr # "gen/c/ecma/test220.scxml" # "gen/c/ecma/test223.scxml" # "gen/c/ecma/test224.scxml" diff --git a/test/src/test-c-machine.cpp b/test/src/test-c-machine.cpp index 1dc95d4..b80ef72 100644 --- a/test/src/test-c-machine.cpp +++ b/test/src/test-c-machine.cpp @@ -40,22 +40,23 @@ using namespace uscxml; class StateMachine : public InterpreterInfo { public: - StateMachine(const scxml_machine* machine) : parentMachine(NULL), topMostMachine(NULL) { + StateMachine(const scxml_machine* machine) : parentMachine(NULL), topMostMachine(NULL), invocation(NULL) { init(machine); allMachines[sessionId] = this; topMostMachine = this; currentMachine = allMachines.begin(); } - StateMachine(StateMachine* parent, const scxml_machine* machine) { - init(machine); + StateMachine(StateMachine* parent, const scxml_machine* machine, const scxml_elem_invoke* invoke) : invocation(invoke) { parentMachine = parent; topMostMachine = parent->topMostMachine; + init(machine); } void init(const scxml_machine* machine) { sessionId = UUID::getUUID(); - + isFinalized = false; + // clear and initialize machine context memset(&ctx, 0, sizeof(scxml_ctx)); ctx.machine = machine; @@ -83,6 +84,54 @@ public: delayQueue.start(); dataModel = Factory::getInstance()->createDataModel(machine->datamodel, this); + + if (invocation != NULL) { + /// test 226/240 - initialize from invoke request + + // TODO: Only set if there is a corresponding data element: test245 + if (invocation->params != NULL) { + const scxml_elem_param* param = invocation->params; + while(ELEM_PARAM_IS_SET(param)) { + try { + std::string identifier; + if (param->name != NULL) { + identifier = param->name; + } else if (param->location != NULL) { + identifier = param->location; + } + dataModel.init(identifier, parentMachine->dataModel.getStringAsData(param->expr)); + invokeIdentifiers.insert(identifier); + + } catch (Event e) { + execContentRaise(&ctx, e.name.c_str()); + } + param++; + } + } + + if (invocation->namelist != NULL) { + const char* cPtr = invocation->namelist; + const char* aPtr = invocation->namelist; + while(cPtr) { + while (isspace(*cPtr)) + cPtr++; + aPtr = cPtr; + while(*cPtr && !isspace(*cPtr)) + cPtr++; + + if (aPtr == cPtr) + break; + + std::string identifier = std::string(aPtr, cPtr - aPtr); + try { + dataModel.init(identifier, parentMachine->dataModel.getStringAsData(identifier)); + invokeIdentifiers.insert(identifier); + } catch (Event e) { + execContentRaise(&ctx, e.name.c_str()); + } + } + } + } } virtual ~StateMachine() { @@ -98,8 +147,22 @@ public: } bool isDone() { - return ctx.flags & SCXML_CTX_TOP_LEVEL_FINAL; - } + return ctx.flags & SCXML_CTX_FINISHED; + } + + void finalize() { + if (isFinalized) + return; + + delayQueue.stop(); + if (parentMachine != NULL) { + Event* done = new Event(); + done->invokeid = invokeId; + done->name = "done.invoke." + invokeId; + parentMachine->eq.push_back(done); + } + isFinalized = true; + } void reset() { sessionId = UUID::getUUID(); @@ -122,6 +185,12 @@ public: return SCXML_ERR_IDLE; } + // test 187 + if (toRun->isDone()) { + toRun->finalize(); + return SCXML_ERR_IDLE; + } + return scxml_step(&toRun->ctx); } @@ -169,6 +238,10 @@ public: } } + // real event but spontaneous transition + if (t->event == NULL) + return false; + // real transition, real event if (nameMatch(t->event, event->name.c_str())) { if (t->condition != NULL) @@ -188,17 +261,44 @@ public: } static int invoke(const scxml_ctx* ctx, const scxml_state* s, const scxml_elem_invoke* invocation, uint8_t uninvoke) { - if (invocation->machine != NULL) { - StateMachine* INSTANCE = USER_DATA(ctx); - // invoke a nested SCXML machine - StateMachine* invokedMachine = new StateMachine(INSTANCE, invocation->machine); - invokedMachine->invocation = invocation; - invokedMachine->invokeId = invocation->id; - assert(invocation->id != NULL); - - INSTANCE->topMostMachine->allMachines[invokedMachine->invokeId] = invokedMachine; - } - return SCXML_ERR_UNSUPPORTED; + std::map<std::string, StateMachine*> &allMachines = USER_DATA(ctx)->topMostMachine->allMachines; + StateMachine* topMachine = USER_DATA(ctx)->topMostMachine; + + if (uninvoke) { + if (invocation->machine != NULL) { + if (topMachine->invocationIds.find(invocation) != topMachine->invocationIds.end() && + allMachines.find(topMachine->invocationIds[invocation]) != allMachines.end()) { + + delete allMachines[topMachine->invocationIds[invocation]]; + topMachine->allMachines.erase(topMachine->invocationIds[invocation]); + topMachine->invocationIds.erase(invocation); + } + } else { + return SCXML_ERR_UNSUPPORTED; + } + } else { + // invocations + if (invocation->machine != NULL) { + // invoke a nested SCXML machine + StateMachine* invokedMachine = new StateMachine(USER_DATA(ctx), invocation->machine, invocation); + + if (invocation->id != NULL) { + invokedMachine->invokeId = invocation->id; + } else if (invocation->idlocation != NULL) { + // test224 + invokedMachine->invokeId = (invocation->sourcename != NULL ? std::string(invocation->sourcename) + "." : "") + UUID::getUUID(); + ctx->exec_content_assign(ctx, invocation->idlocation, std::string("\"" + invokedMachine->invokeId + "\"").c_str()); + } else { + delete invokedMachine; + return SCXML_ERR_UNSUPPORTED; + } + allMachines[invokedMachine->invokeId] = invokedMachine; + topMachine->invocationIds[invocation] = invokedMachine->invokeId; + } else { + return SCXML_ERR_UNSUPPORTED; + } + } + return SCXML_ERR_OK; } static int raiseDoneEvent(const scxml_ctx* ctx, const scxml_state* state, const scxml_elem_donedata* donedata) { @@ -283,7 +383,8 @@ public: } e->origintype = e->type; - + e->invokeid = USER_DATA(ctx)->invokeId; + if (send->eventexpr != NULL) { e->name = USER_DATA(ctx)->dataModel.evalAsString(send->eventexpr); } else { @@ -494,19 +595,22 @@ public: static int execContentInit(const scxml_ctx* ctx, const scxml_elem_data* data) { while(ELEM_DATA_IS_SET(data)) { - Data d; - if (data->expr != NULL) { - d = Data(data->expr, Data::INTERPRETED); - } else if (data->content != NULL) { - d = Data(data->content, Data::INTERPRETED); - } else { - d = Data("undefined", Data::INTERPRETED); - } - try { - USER_DATA(ctx)->dataModel.init(data->id, d); - } catch (Event e) { - execContentRaise(ctx, e.name.c_str()); - } + // only initialize data that was not already passed per invocation + if (USER_DATA(ctx)->invokeIdentifiers.find(data->id) == USER_DATA(ctx)->invokeIdentifiers.end()) { + Data d; + if (data->expr != NULL) { + d = Data(data->expr, Data::INTERPRETED); + } else if (data->content != NULL) { + d = Data(data->content, Data::INTERPRETED); + } else { + d = Data("undefined", Data::INTERPRETED); + } + try { + USER_DATA(ctx)->dataModel.init(data->id, d); + } catch (Event e) { + execContentRaise(ctx, e.name.c_str()); + } + } data++; } return SCXML_ERR_OK; @@ -530,15 +634,25 @@ public: USER_DATA(ctx)->eq.pop_front(); USER_DATA(ctx)->dataModel.setEvent(*e); - if (e->invokeid.size() > 0) { + std::map<std::string, StateMachine*>& allMachines = USER_DATA(ctx)->topMostMachine->allMachines; + if (e->invokeid.size() > 0 && allMachines.find(e->invokeid) != allMachines.end()) { // we need to check for finalize content - StateMachine* invokedMachine = USER_DATA(ctx)->allMachines[e->invokeid]; - if (invokedMachine->invocation->finalize != NULL) + StateMachine* invokedMachine = allMachines[e->invokeid]; + if (invokedMachine->invocation != NULL && invokedMachine->invocation->finalize != NULL) invokedMachine->invocation->finalize(ctx, invokedMachine->invocation, e); } - + + // auto forward event + for (std::map<std::string, StateMachine*>::iterator machIter = allMachines.begin(); machIter != allMachines.end(); machIter++) { + if (machIter->second->parentMachine != NULL && + machIter->second->parentMachine == USER_DATA(ctx) && + machIter->second->invocation->autoforward) { + machIter->second->eq.push_back(e); + } + } + #ifdef SCXML_VERBOSE printf("Popping External Event: %s\n", e->name.c_str()); #endif @@ -569,18 +683,36 @@ public: printf("Pushing Internal Event: %s\n", e->name.c_str()); #endif USER_DATA(ctx)->iq.push_back(e); - } else if (sr->target == "#_parent") { + } else if (sr->target == "#_external") { + e->eventType = Event::EXTERNAL; +#ifdef SCXML_VERBOSE + printf("Pushing External Event: %s\n", e->name.c_str()); +#endif + USER_DATA(ctx)->eq.push_back(e); + } else if (sr->target == "#_parent") { e->eventType = Event::EXTERNAL; if (USER_DATA(ctx)->parentMachine != NULL) { USER_DATA(ctx)->parentMachine->eq.push_back(e); } // TODO: handle invalid parent + } else if (sr->target.substr(0,8) == "#_scxml_") { + std::string sessionId = sr->target.substr(8); + for (std::map<std::string, StateMachine*>::iterator machIter = USER_DATA(ctx)->topMostMachine->allMachines.begin(); + machIter != USER_DATA(ctx)->topMostMachine->allMachines.end(); machIter++) { + if (machIter->second->sessionId == sessionId) { + e->eventType = Event::EXTERNAL; + machIter->second->eq.push_back(e); + break; + } + } + } else if (sr->target.substr(0,2) == "#_") { + e->eventType = Event::EXTERNAL; + std::string targetId = sr->target.substr(2); + if (USER_DATA(ctx)->topMostMachine->allMachines.find(targetId) != USER_DATA(ctx)->topMostMachine->allMachines.end()) { + USER_DATA(ctx)->topMostMachine->allMachines[targetId]->eq.push_back(e); + } } else { - e->eventType = Event::EXTERNAL; -#ifdef SCXML_VERBOSE - printf("Pushing External Event: %s\n", e->name.c_str()); -#endif - USER_DATA(ctx)->eq.push_back(e); + assert(false); } USER_DATA(ctx)->monitor.notify_all(); delete sr; @@ -658,12 +790,14 @@ NEXT_DESC: return false; } + std::map<const scxml_elem_invoke*, std::string> invocationIds; std::map<std::string, StateMachine*> allMachines; StateMachine* parentMachine; StateMachine* topMostMachine; std::map<std::string, StateMachine* >::iterator currentMachine; // next machine to advance + bool isFinalized; int state; scxml_ctx ctx; @@ -673,6 +807,7 @@ NEXT_DESC: // in case we were invoked std::string invokeId; const scxml_elem_invoke* invocation; + std::set<std::string> invokeIdentifiers; std::deque<Event*> iq; std::deque<Event*> eq; diff --git a/test/src/test-c-machine.machine.c b/test/src/test-c-machine.machine.c index a69b7c7..f3ec413 100644 --- a/test/src/test-c-machine.machine.c +++ b/test/src/test-c-machine.machine.c @@ -64,6 +64,7 @@ #define SCXML_CTX_INITIALIZED 0x02 #define SCXML_CTX_TOP_LEVEL_FINAL 0x04 #define SCXML_CTX_TRANSITION_FOUND 0x08 +#define SCXML_CTX_FINISHED 0x10 #define ELEM_DATA_IS_SET(data) (data->id != NULL) #define ELEM_DONEDATA_IS_SET(donedata) (donedata->content != NULL || donedata->contentexpr != NULL || donedata->params != NULL) @@ -118,7 +119,7 @@ struct scxml_machine { }; // forward declare machines to allow references -extern const scxml_machine scxml_machines[3]; +extern const scxml_machine scxml_machines[4]; struct scxml_elem_data { const char* id; @@ -178,6 +179,7 @@ struct scxml_elem_invoke { const char* srcexpr; const char* id; const char* idlocation; + const char* sourcename; const char* namelist; const uint8_t autoforward; const scxml_elem_param* params; @@ -234,19 +236,19 @@ struct scxml_ctx { invoke_t invoke; }; -static const scxml_elem_data _scxml_6A932FF1_elem_datas[2] = { +static const scxml_elem_data _scxml_22A28DED_elem_datas[2] = { /* id, src, expr, content */ { "Var1", NULL, "1", NULL }, { NULL, NULL, NULL, NULL } }; -static const scxml_elem_param _scxml_6A932FF1_elem_params[2] = { +static const scxml_elem_param _scxml_22A28DED_elem_params[2] = { /* name, expr, location */ - { "aParam", "2", NULL }, + { "Var1", "1", NULL }, { NULL, NULL, NULL } }; -static const scxml_elem_send _scxml_6A932FF1_elem_sends[2] = { +static const scxml_elem_send _scxml_22A28DED_elem_sends[1] = { { /* event */ "timeout", /* eventexpr */ NULL, @@ -256,85 +258,81 @@ static const scxml_elem_send _scxml_6A932FF1_elem_sends[2] = { /* typeexpr */ NULL, /* id */ NULL, /* idlocation */ NULL, - /* delay */ "300s", + /* delay */ "2s", /* delayexpr */ NULL, /* namelist */ NULL, /* content */ NULL, /* contentexpr */ NULL, /* params */ NULL - }, - { - /* event */ "childToParent", - /* eventexpr */ NULL, - /* target */ "#_parent", - /* targetexpr */ NULL, - /* type */ NULL, - /* typeexpr */ NULL, - /* id */ NULL, - /* idlocation */ NULL, - /* delay */ NULL, - /* delayexpr */ NULL, - /* namelist */ NULL, - /* content */ NULL, - /* contentexpr */ NULL, - /* params */ &_scxml_6A932FF1_elem_params[0] } }; -static const scxml_elem_donedata _scxml_6A932FF1_elem_donedatas[1] = { +static const scxml_elem_donedata _scxml_22A28DED_elem_donedatas[1] = { /* source, content, contentexpr, params */ { 0, NULL, NULL, NULL } }; -static int _scxml_6A932FF1_s0_invoke0_finalize0(const scxml_ctx* ctx, const scxml_elem_invoke* invocation, const void* event) { - int err = SCXML_ERR_OK; - if likely(ctx->exec_content_assign != NULL) { - if ((ctx->exec_content_assign(ctx, "Var1", "_event.data.aParam")) != SCXML_ERR_OK) return err; - } else { - return SCXML_ERR_MISSING_CALLBACK; - } - return SCXML_ERR_OK; -} - -static const scxml_elem_invoke _scxml_6A932FF1_elem_invokes[1] = { +static const scxml_elem_invoke _scxml_22A28DED_elem_invokes[2] = { { /* machine */ &scxml_machines[1], /* type */ "http://www.w3.org/TR/scxml/", /* typeexpr */ NULL, /* src */ NULL, /* srcexpr */ NULL, - /* id */ "d2170d67-da91-4aba-99a1-b1c021513e75", + /* id */ "43b1f997-4793-4391-8786-d387b411529d", /* idlocation */ NULL, - /* namelist */ NULL, + /* sourcename */ "s01", + /* namelist */ "Var1", /* autoforward */ 0, /* params */ NULL, - /* finalize */ _scxml_6A932FF1_s0_invoke0_finalize0, + /* finalize */ NULL, + /* content */ NULL, + /* contentexpr */ NULL, + }, + { + /* machine */ &scxml_machines[2], + /* type */ "http://www.w3.org/TR/scxml/", + /* typeexpr */ NULL, + /* src */ NULL, + /* srcexpr */ NULL, + /* id */ "8283f07f-2eac-469d-9e43-49c655c7590f", + /* idlocation */ NULL, + /* sourcename */ "s02", + /* namelist */ NULL, + /* autoforward */ 0, + /* params */ &_scxml_22A28DED_elem_params[0], + /* finalize */ NULL, /* content */ NULL, /* contentexpr */ NULL, } }; -static int _scxml_6A932FF1_s0_on_entry_0(const scxml_ctx* ctx, const scxml_state* state, const void* event) { +static int _scxml_22A28DED_s0_on_entry_0(const scxml_ctx* ctx, const scxml_state* state, const void* event) { int err = SCXML_ERR_OK; if likely(ctx->exec_content_send != NULL) { - if ((ctx->exec_content_send(ctx, &_scxml_6A932FF1_elem_sends[0])) != SCXML_ERR_OK) return err; + if ((ctx->exec_content_send(ctx, &_scxml_22A28DED_elem_sends[0])) != SCXML_ERR_OK) return err; } else { return SCXML_ERR_MISSING_CALLBACK; } return SCXML_ERR_OK; } -static int _scxml_6A932FF1_s0_on_entry(const scxml_ctx* ctx, const scxml_state* state, const void* event) { - _scxml_6A932FF1_s0_on_entry_0(ctx, state, event); +static int _scxml_22A28DED_s0_on_entry(const scxml_ctx* ctx, const scxml_state* state, const void* event) { + _scxml_22A28DED_s0_on_entry_0(ctx, state, event); return SCXML_ERR_OK; } -static int _scxml_6A932FF1_s0_invoke(const scxml_ctx* ctx, const scxml_state* s, const scxml_elem_invoke* invocation, uint8_t uninvoke) { - ctx->invoke(ctx, s, &_scxml_6A932FF1_elem_invokes[0], uninvoke); +static int _scxml_22A28DED_s01_invoke(const scxml_ctx* ctx, const scxml_state* s, const scxml_elem_invoke* invocation, uint8_t uninvoke) { + ctx->invoke(ctx, s, &_scxml_22A28DED_elem_invokes[0], uninvoke); + + return SCXML_ERR_OK; +} +static int _scxml_22A28DED_s02_invoke(const scxml_ctx* ctx, const scxml_state* s, const scxml_elem_invoke* invocation, uint8_t uninvoke) { + ctx->invoke(ctx, s, &_scxml_22A28DED_elem_invokes[1], uninvoke); return SCXML_ERR_OK; } -static int _scxml_6A932FF1_pass_on_entry_0(const scxml_ctx* ctx, const scxml_state* state, const void* event) { +static int _scxml_22A28DED_pass_on_entry_0(const scxml_ctx* ctx, const scxml_state* state, const void* event) { int err = SCXML_ERR_OK; if likely(ctx->exec_content_log != NULL) { if unlikely((ctx->exec_content_log(ctx, "Outcome", "'pass'")) != SCXML_ERR_OK) return err; @@ -344,12 +342,12 @@ static int _scxml_6A932FF1_pass_on_entry_0(const scxml_ctx* ctx, const scxml_sta return SCXML_ERR_OK; } -static int _scxml_6A932FF1_pass_on_entry(const scxml_ctx* ctx, const scxml_state* state, const void* event) { - _scxml_6A932FF1_pass_on_entry_0(ctx, state, event); +static int _scxml_22A28DED_pass_on_entry(const scxml_ctx* ctx, const scxml_state* state, const void* event) { + _scxml_22A28DED_pass_on_entry_0(ctx, state, event); return SCXML_ERR_OK; } -static int _scxml_6A932FF1_fail_on_entry_0(const scxml_ctx* ctx, const scxml_state* state, const void* event) { +static int _scxml_22A28DED_fail_on_entry_0(const scxml_ctx* ctx, const scxml_state* state, const void* event) { int err = SCXML_ERR_OK; if likely(ctx->exec_content_log != NULL) { if unlikely((ctx->exec_content_log(ctx, "Outcome", "'fail'")) != SCXML_ERR_OK) return err; @@ -359,98 +357,174 @@ static int _scxml_6A932FF1_fail_on_entry_0(const scxml_ctx* ctx, const scxml_sta return SCXML_ERR_OK; } -static int _scxml_6A932FF1_fail_on_entry(const scxml_ctx* ctx, const scxml_state* state, const void* event) { - _scxml_6A932FF1_fail_on_entry_0(ctx, state, event); +static int _scxml_22A28DED_fail_on_entry(const scxml_ctx* ctx, const scxml_state* state, const void* event) { + _scxml_22A28DED_fail_on_entry_0(ctx, state, event); return SCXML_ERR_OK; } -static const scxml_state _scxml_6A932FF1_states[4] = { +static const scxml_state _scxml_22A28DED_states[6] = { { /* state number 0 */ /* name */ NULL, /* parent */ 0, /* onentry */ NULL, /* onexit */ NULL, /* invoke */ NULL, - /* children */ { 0x0e /* 0111 */ }, - /* completion */ { 0x02 /* 0100 */ }, - /* ancestors */ { 0x00 /* 0000 */ }, - /* data */ &_scxml_6A932FF1_elem_datas[0], + /* children */ { 0x32 /* 010011 */ }, + /* completion */ { 0x02 /* 010000 */ }, + /* ancestors */ { 0x00 /* 000000 */ }, + /* data */ &_scxml_22A28DED_elem_datas[0], /* type */ SCXML_STATE_COMPOUND, }, { /* state number 1 */ /* name */ "s0", /* parent */ 0, - /* onentry */ _scxml_6A932FF1_s0_on_entry, + /* onentry */ _scxml_22A28DED_s0_on_entry, /* onexit */ NULL, - /* invoke */ _scxml_6A932FF1_s0_invoke, - /* children */ { 0x00 /* 0000 */ }, - /* completion */ { 0x00 /* 0000 */ }, - /* ancestors */ { 0x01 /* 1000 */ }, + /* invoke */ NULL, + /* children */ { 0x0c /* 001100 */ }, + /* completion */ { 0x04 /* 001000 */ }, + /* ancestors */ { 0x01 /* 100000 */ }, /* data */ NULL, - /* type */ SCXML_STATE_ATOMIC, + /* type */ SCXML_STATE_COMPOUND, }, { /* state number 2 */ + /* name */ "s01", + /* parent */ 1, + /* onentry */ NULL, + /* onexit */ NULL, + /* invoke */ _scxml_22A28DED_s01_invoke, + /* children */ { 0x00 /* 000000 */ }, + /* completion */ { 0x00 /* 000000 */ }, + /* ancestors */ { 0x03 /* 110000 */ }, + /* data */ NULL, + /* type */ SCXML_STATE_ATOMIC, + }, + { /* state number 3 */ + /* name */ "s02", + /* parent */ 1, + /* onentry */ NULL, + /* onexit */ NULL, + /* invoke */ _scxml_22A28DED_s02_invoke, + /* children */ { 0x00 /* 000000 */ }, + /* completion */ { 0x00 /* 000000 */ }, + /* ancestors */ { 0x03 /* 110000 */ }, + /* data */ NULL, + /* type */ SCXML_STATE_ATOMIC, + }, + { /* state number 4 */ /* name */ "pass", /* parent */ 0, - /* onentry */ _scxml_6A932FF1_pass_on_entry, + /* onentry */ _scxml_22A28DED_pass_on_entry, /* onexit */ NULL, /* invoke */ NULL, - /* children */ { 0x00 /* 0000 */ }, - /* completion */ { 0x00 /* 0000 */ }, - /* ancestors */ { 0x01 /* 1000 */ }, + /* children */ { 0x00 /* 000000 */ }, + /* completion */ { 0x00 /* 000000 */ }, + /* ancestors */ { 0x01 /* 100000 */ }, /* data */ NULL, /* type */ SCXML_STATE_FINAL, }, - { /* state number 3 */ + { /* state number 5 */ /* name */ "fail", /* parent */ 0, - /* onentry */ _scxml_6A932FF1_fail_on_entry, + /* onentry */ _scxml_22A28DED_fail_on_entry, /* onexit */ NULL, /* invoke */ NULL, - /* children */ { 0x00 /* 0000 */ }, - /* completion */ { 0x00 /* 0000 */ }, - /* ancestors */ { 0x01 /* 1000 */ }, + /* children */ { 0x00 /* 000000 */ }, + /* completion */ { 0x00 /* 000000 */ }, + /* ancestors */ { 0x01 /* 100000 */ }, /* data */ NULL, /* type */ SCXML_STATE_FINAL, } }; -static const scxml_transition _scxml_6A932FF1_transitions[2] = { - { /* transition number 0 with priority 0 +static const scxml_transition _scxml_22A28DED_transitions[5] = { + { /* transition number 1 with priority 0 + target: s02 + */ + /* source */ 2, + /* target */ { 0x08 /* 000100 */ }, + /* event */ "success", + /* condition */ NULL, + /* ontrans */ NULL, + /* type */ 0, + /* conflicts */ { 0x1f /* 11111 */ }, + /* exit set */ { 0x0c /* 001100 */ } + }, + { /* transition number 2 with priority 1 + target: fail + */ + /* source */ 2, + /* target */ { 0x20 /* 000001 */ }, + /* event */ "failure", + /* condition */ NULL, + /* ontrans */ NULL, + /* type */ 0, + /* conflicts */ { 0x1f /* 11111 */ }, + /* exit set */ { 0x3e /* 011111 */ } + }, + { /* transition number 3 with priority 2 target: pass */ - /* source */ 1, - /* target */ { 0x04 /* 0010 */ }, - /* event */ "childToParent", - /* condition */ "Var1==2", + /* source */ 3, + /* target */ { 0x10 /* 000010 */ }, + /* event */ "success", + /* condition */ NULL, /* ontrans */ NULL, /* type */ 0, - /* conflicts */ { 0x03 /* 11 */ }, - /* exit set */ { 0x0e /* 0111 */ } + /* conflicts */ { 0x1f /* 11111 */ }, + /* exit set */ { 0x3e /* 011111 */ } }, - { /* transition number 1 with priority 1 + { /* transition number 4 with priority 3 + target: fail + */ + /* source */ 3, + /* target */ { 0x20 /* 000001 */ }, + /* event */ "failure", + /* condition */ NULL, + /* ontrans */ NULL, + /* type */ 0, + /* conflicts */ { 0x1f /* 11111 */ }, + /* exit set */ { 0x3e /* 011111 */ } + }, + { /* transition number 0 with priority 4 target: fail */ /* source */ 1, - /* target */ { 0x08 /* 0001 */ }, - /* event */ "*", + /* target */ { 0x20 /* 000001 */ }, + /* event */ "timeout", /* condition */ NULL, /* ontrans */ NULL, /* type */ 0, - /* conflicts */ { 0x03 /* 11 */ }, - /* exit set */ { 0x0e /* 0111 */ } + /* conflicts */ { 0x1f /* 11111 */ }, + /* exit set */ { 0x3e /* 011111 */ } } }; -static const scxml_elem_param _scxml_74EC8913_elem_params[2] = { - /* name, expr, location */ - { "aParam", "2", NULL }, - { NULL, NULL, NULL } +static const scxml_elem_data _scxml_FD9C4306_elem_datas[2] = { + /* id, src, expr, content */ + { "Var1", NULL, "0", NULL }, + { NULL, NULL, NULL, NULL } }; -static const scxml_elem_send _scxml_74EC8913_elem_sends[1] = { +static const scxml_elem_send _scxml_FD9C4306_elem_sends[2] = { + { + /* event */ "success", + /* eventexpr */ NULL, + /* target */ "#_parent", + /* targetexpr */ NULL, + /* type */ NULL, + /* typeexpr */ NULL, + /* id */ NULL, + /* idlocation */ NULL, + /* delay */ NULL, + /* delayexpr */ NULL, + /* namelist */ NULL, + /* content */ NULL, + /* contentexpr */ NULL, + /* params */ NULL + }, { - /* event */ "childToParent", + /* event */ "failure", /* eventexpr */ NULL, /* target */ "#_parent", /* targetexpr */ NULL, @@ -463,85 +537,271 @@ static const scxml_elem_send _scxml_74EC8913_elem_sends[1] = { /* namelist */ NULL, /* content */ NULL, /* contentexpr */ NULL, - /* params */ &_scxml_74EC8913_elem_params[0] + /* params */ NULL } }; -static const scxml_elem_donedata _scxml_74EC8913_elem_donedatas[1] = { +static const scxml_elem_donedata _scxml_FD9C4306_elem_donedatas[1] = { /* source, content, contentexpr, params */ { 0, NULL, NULL, NULL } }; -static int _scxml_74EC8913_subFinal_on_entry_0(const scxml_ctx* ctx, const scxml_state* state, const void* event) { +static int _scxml_FD9C4306_sub01_transition0_on_trans(const scxml_ctx* ctx, const scxml_state* state, const void* event) { int err = SCXML_ERR_OK; if likely(ctx->exec_content_send != NULL) { - if ((ctx->exec_content_send(ctx, &_scxml_74EC8913_elem_sends[0])) != SCXML_ERR_OK) return err; + if ((ctx->exec_content_send(ctx, &_scxml_FD9C4306_elem_sends[0])) != SCXML_ERR_OK) return err; } else { return SCXML_ERR_MISSING_CALLBACK; } return SCXML_ERR_OK; } -static int _scxml_74EC8913_subFinal_on_entry(const scxml_ctx* ctx, const scxml_state* state, const void* event) { - _scxml_74EC8913_subFinal_on_entry_0(ctx, state, event); +static int _scxml_FD9C4306_sub01_transition1_on_trans(const scxml_ctx* ctx, const scxml_state* state, const void* event) { + int err = SCXML_ERR_OK; + if likely(ctx->exec_content_send != NULL) { + if ((ctx->exec_content_send(ctx, &_scxml_FD9C4306_elem_sends[1])) != SCXML_ERR_OK) return err; + } else { + return SCXML_ERR_MISSING_CALLBACK; + } return SCXML_ERR_OK; } -static const scxml_state _scxml_74EC8913_states[2] = { +static const scxml_state _scxml_FD9C4306_states[3] = { { /* state number 0 */ /* name */ NULL, /* parent */ 0, /* onentry */ NULL, /* onexit */ NULL, /* invoke */ NULL, - /* children */ { 0x02 /* 01 */ }, - /* completion */ { 0x02 /* 01 */ }, - /* ancestors */ { 0x00 /* 00 */ }, + /* children */ { 0x06 /* 011 */ }, + /* completion */ { 0x02 /* 010 */ }, + /* ancestors */ { 0x00 /* 000 */ }, + /* data */ &_scxml_FD9C4306_elem_datas[0], + /* type */ SCXML_STATE_COMPOUND, + }, + { /* state number 1 */ + /* name */ "sub01", + /* parent */ 0, + /* onentry */ NULL, + /* onexit */ NULL, + /* invoke */ NULL, + /* children */ { 0x00 /* 000 */ }, + /* completion */ { 0x00 /* 000 */ }, + /* ancestors */ { 0x01 /* 100 */ }, /* data */ NULL, + /* type */ SCXML_STATE_ATOMIC, + }, + { /* state number 2 */ + /* name */ "subFinal1", + /* parent */ 0, + /* onentry */ NULL, + /* onexit */ NULL, + /* invoke */ NULL, + /* children */ { 0x00 /* 000 */ }, + /* completion */ { 0x00 /* 000 */ }, + /* ancestors */ { 0x01 /* 100 */ }, + /* data */ NULL, + /* type */ SCXML_STATE_FINAL, + } +}; + +static const scxml_transition _scxml_FD9C4306_transitions[2] = { + { /* transition number 0 with priority 0 + target: subFinal1 + */ + /* source */ 1, + /* target */ { 0x04 /* 001 */ }, + /* event */ NULL, + /* condition */ "Var1===1", + /* ontrans */ _scxml_FD9C4306_sub01_transition0_on_trans, + /* type */ SCXML_TRANS_SPONTANEOUS, + /* conflicts */ { 0x03 /* 11 */ }, + /* exit set */ { 0x06 /* 011 */ } + }, + { /* transition number 1 with priority 1 + target: subFinal1 + */ + /* source */ 1, + /* target */ { 0x04 /* 001 */ }, + /* event */ NULL, + /* condition */ NULL, + /* ontrans */ _scxml_FD9C4306_sub01_transition1_on_trans, + /* type */ SCXML_TRANS_SPONTANEOUS, + /* conflicts */ { 0x03 /* 11 */ }, + /* exit set */ { 0x06 /* 011 */ } + } +}; + +static const scxml_elem_data _scxml_50B9C583_elem_datas[2] = { + /* id, src, expr, content */ + { "Var1", NULL, "0", NULL }, + { NULL, NULL, NULL, NULL } +}; + +static const scxml_elem_send _scxml_50B9C583_elem_sends[2] = { + { + /* event */ "success", + /* eventexpr */ NULL, + /* target */ "#_parent", + /* targetexpr */ NULL, + /* type */ NULL, + /* typeexpr */ NULL, + /* id */ NULL, + /* idlocation */ NULL, + /* delay */ NULL, + /* delayexpr */ NULL, + /* namelist */ NULL, + /* content */ NULL, + /* contentexpr */ NULL, + /* params */ NULL + }, + { + /* event */ "failure", + /* eventexpr */ NULL, + /* target */ "#_parent", + /* targetexpr */ NULL, + /* type */ NULL, + /* typeexpr */ NULL, + /* id */ NULL, + /* idlocation */ NULL, + /* delay */ NULL, + /* delayexpr */ NULL, + /* namelist */ NULL, + /* content */ NULL, + /* contentexpr */ NULL, + /* params */ NULL + } +}; + +static const scxml_elem_donedata _scxml_50B9C583_elem_donedatas[1] = { + /* source, content, contentexpr, params */ + { 0, NULL, NULL, NULL } +}; + +static int _scxml_50B9C583_sub02_transition0_on_trans(const scxml_ctx* ctx, const scxml_state* state, const void* event) { + int err = SCXML_ERR_OK; + if likely(ctx->exec_content_send != NULL) { + if ((ctx->exec_content_send(ctx, &_scxml_50B9C583_elem_sends[0])) != SCXML_ERR_OK) return err; + } else { + return SCXML_ERR_MISSING_CALLBACK; + } + return SCXML_ERR_OK; +} + +static int _scxml_50B9C583_sub02_transition1_on_trans(const scxml_ctx* ctx, const scxml_state* state, const void* event) { + int err = SCXML_ERR_OK; + if likely(ctx->exec_content_send != NULL) { + if ((ctx->exec_content_send(ctx, &_scxml_50B9C583_elem_sends[1])) != SCXML_ERR_OK) return err; + } else { + return SCXML_ERR_MISSING_CALLBACK; + } + return SCXML_ERR_OK; +} + +static const scxml_state _scxml_50B9C583_states[3] = { + { /* state number 0 */ + /* name */ NULL, + /* parent */ 0, + /* onentry */ NULL, + /* onexit */ NULL, + /* invoke */ NULL, + /* children */ { 0x06 /* 011 */ }, + /* completion */ { 0x02 /* 010 */ }, + /* ancestors */ { 0x00 /* 000 */ }, + /* data */ &_scxml_50B9C583_elem_datas[0], /* type */ SCXML_STATE_COMPOUND, }, { /* state number 1 */ - /* name */ "subFinal", + /* name */ "sub02", + /* parent */ 0, + /* onentry */ NULL, + /* onexit */ NULL, + /* invoke */ NULL, + /* children */ { 0x00 /* 000 */ }, + /* completion */ { 0x00 /* 000 */ }, + /* ancestors */ { 0x01 /* 100 */ }, + /* data */ NULL, + /* type */ SCXML_STATE_ATOMIC, + }, + { /* state number 2 */ + /* name */ "subFinal2", /* parent */ 0, - /* onentry */ _scxml_74EC8913_subFinal_on_entry, + /* onentry */ NULL, /* onexit */ NULL, /* invoke */ NULL, - /* children */ { 0x00 /* 00 */ }, - /* completion */ { 0x00 /* 00 */ }, - /* ancestors */ { 0x01 /* 10 */ }, + /* children */ { 0x00 /* 000 */ }, + /* completion */ { 0x00 /* 000 */ }, + /* ancestors */ { 0x01 /* 100 */ }, /* data */ NULL, /* type */ SCXML_STATE_FINAL, } }; -static const scxml_transition _scxml_74EC8913_transitions[0] = { +static const scxml_transition _scxml_50B9C583_transitions[2] = { + { /* transition number 0 with priority 0 + target: subFinal2 + */ + /* source */ 1, + /* target */ { 0x04 /* 001 */ }, + /* event */ NULL, + /* condition */ "Var1==1", + /* ontrans */ _scxml_50B9C583_sub02_transition0_on_trans, + /* type */ SCXML_TRANS_SPONTANEOUS, + /* conflicts */ { 0x03 /* 11 */ }, + /* exit set */ { 0x06 /* 011 */ } + }, + { /* transition number 1 with priority 1 + target: subFinal2 + */ + /* source */ 1, + /* target */ { 0x04 /* 001 */ }, + /* event */ NULL, + /* condition */ NULL, + /* ontrans */ _scxml_50B9C583_sub02_transition1_on_trans, + /* type */ SCXML_TRANS_SPONTANEOUS, + /* conflicts */ { 0x03 /* 11 */ }, + /* exit set */ { 0x06 /* 011 */ } + } }; -const scxml_machine scxml_machines[3] = { +const scxml_machine scxml_machines[4] = { { /* flags */ 0, - /* nr_states */ 4, - /* nr_transitions */ 2, + /* nr_states */ 6, + /* nr_transitions */ 5, /* name */ "", /* datamodel */ "ecmascript", - /* uuid */ "6A932FF17BFF1735E3F3C77F7B54C218", - /* states */ &_scxml_6A932FF1_states[0], - /* transitions */ &_scxml_6A932FF1_transitions[0], + /* uuid */ "22A28DEDB4EF5C2066BF1D2C022A8AD9", + /* states */ &_scxml_22A28DED_states[0], + /* transitions */ &_scxml_22A28DED_transitions[0], /* parent */ NULL, - /* donedata */ &_scxml_6A932FF1_elem_donedatas[0], + /* donedata */ &_scxml_22A28DED_elem_donedatas[0], /* script */ NULL }, { /* flags */ 0, - /* nr_states */ 2, - /* nr_transitions */ 0, + /* nr_states */ 3, + /* nr_transitions */ 2, /* name */ "", /* datamodel */ "ecmascript", - /* uuid */ "74EC8913A9386F1A7EC5EF2A0426752B", - /* states */ &_scxml_74EC8913_states[0], - /* transitions */ &_scxml_74EC8913_transitions[0], + /* uuid */ "FD9C43066AC6FCEE1EC61755B4F2ED11", + /* states */ &_scxml_FD9C4306_states[0], + /* transitions */ &_scxml_FD9C4306_transitions[0], /* parent */ &scxml_machines[0], - /* donedata */ &_scxml_74EC8913_elem_donedatas[0], + /* donedata */ &_scxml_FD9C4306_elem_donedatas[0], + /* script */ NULL + }, + { + /* flags */ 0, + /* nr_states */ 3, + /* nr_transitions */ 2, + /* name */ "", + /* datamodel */ "ecmascript", + /* uuid */ "50B9C5830D90CE26DE76391506C882A0", + /* states */ &_scxml_50B9C583_states[0], + /* transitions */ &_scxml_50B9C583_transitions[0], + /* parent */ &scxml_machines[0], + /* donedata */ &_scxml_50B9C583_elem_donedatas[0], /* script */ NULL }, {0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL } @@ -621,14 +881,6 @@ static void bit_and(char* dest, const char* mask, size_t i) { int scxml_step(scxml_ctx* ctx) { -#ifdef SCXML_VERBOSE - printf("Config: "); - printStateNames(ctx, ctx->config, SCXML_NUMBER_STATES); -#endif - - if (ctx->flags & SCXML_CTX_TOP_LEVEL_FINAL) - return SCXML_ERR_DONE; - SCXML_NR_STATES_TYPE i, j, k; SCXML_NR_STATES_TYPE nr_states_bytes = ((SCXML_NUMBER_STATES + 7) & ~7) >> 3; SCXML_NR_TRANS_TYPE nr_trans_bytes = ((SCXML_NUMBER_TRANS + 7) & ~7) >> 3; @@ -640,6 +892,30 @@ int scxml_step(scxml_ctx* ctx) { char entry_set [SCXML_MAX_NR_STATES_BYTES]; char tmp_states [SCXML_MAX_NR_STATES_BYTES]; +#ifdef SCXML_VERBOSE + printf("Config: "); + printStateNames(ctx, ctx->config, SCXML_NUMBER_STATES); +#endif + + if (ctx->flags & SCXML_CTX_FINISHED) + return SCXML_ERR_DONE; + + if (ctx->flags & SCXML_CTX_TOP_LEVEL_FINAL) { + // exit all remaining states + i = SCXML_NUMBER_STATES; + while(i-- > 0) { + if (BIT_HAS(i, ctx->config)) { + // call all on exit handlers + if (ctx->machine->states[i].on_exit != NULL) { + if unlikely((err = ctx->machine->states[i].on_exit(ctx, &ctx->machine->states[i], ctx->event)) != SCXML_ERR_OK) + return err; + } + } + } + ctx->flags |= SCXML_CTX_FINISHED; + return SCXML_ERR_DONE; + } + bit_clear_all(target_set, nr_states_bytes); bit_clear_all(trans_set, nr_trans_bytes); if unlikely(ctx->flags == SCXML_CTX_PRISTINE) { diff --git a/test/w3c/ecma/test240.scxml b/test/w3c/ecma/test240.scxml index 381b04b..00e8c5b 100644 --- a/test/w3c/ecma/test240.scxml +++ b/test/w3c/ecma/test240.scxml @@ -46,7 +46,7 @@ should run correctly. --> <transition cond="Var1==1" target="subFinal2"> <send target="#_parent" event="success"/> </transition> - <transition target="subFinal1"> + <transition target="subFinal2"> <send target="#_parent" event="failure"/> </transition> </state> |