summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Radomski <sradomski@mintwerk.de>2016-02-06 13:59:11 (GMT)
committerStefan Radomski <sradomski@mintwerk.de>2016-02-06 13:59:11 (GMT)
commit0bf6dfca862e7057b96237213ee91a6fa3925c6c (patch)
treee9458f19a34092da7128dd9ea1d51ab3658c42ff
parent9cf37e17d745a1f8533ea784a34562e67e6d7f2f (diff)
downloaduscxml-0bf6dfca862e7057b96237213ee91a6fa3925c6c.zip
uscxml-0bf6dfca862e7057b96237213ee91a6fa3925c6c.tar.gz
uscxml-0bf6dfca862e7057b96237213ee91a6fa3925c6c.tar.bz2
Fixes bugs and memory leaks with generated C state-charts
-rw-r--r--README.md4
-rw-r--r--src/uscxml/DOMUtils.h30
-rw-r--r--src/uscxml/transform/ChartToC.cpp75
-rw-r--r--test/CMakeLists.txt6
-rw-r--r--test/ctest/CTestCustom.ctest.in77
-rw-r--r--test/src/test-c-machine.cpp432
-rw-r--r--test/src/test-c-machine.machine.c488
7 files changed, 475 insertions, 637 deletions
diff --git a/README.md b/README.md
index 53d9e68..1466009 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# uSCXML ReadMe
-[![Build Status](https://travis-ci.org/sradomski/uscxml.png?branch=master)](https://travis-ci.org/sradomski/uscxml)
+[![Build Status](https://travis-ci.org/tklab-tud/uscxml.png?branch=master)](https://travis-ci.org/sradomski/uscxml)
#### Related Documents
@@ -98,7 +98,7 @@ so maybe restrict yourself to some subset.
| | XPath | 107/211 | <tt>$ ctest -L "^fsm/xpath/test"</tt> |
| | PROMELA | 147/165 | <tt>$ ctest -L "^fsm/promela/test"</tt> |
| | Lua | 165/201 | <tt>$ ctest -L "^fsm/lua/test"</tt> |
-| Generated C | ECMAScript | 173/176 | <tt>$ ctest -L "^gen/c/ecma/test"</tt> |
+| Generated C | ECMAScript | 180/180 | <tt>$ ctest -L "^gen/c/ecma/test"</tt> |
| Verification | PROMELA | 130/181 | <tt>$ ctest -L "^spin/promela/test"</tt> |
diff --git a/src/uscxml/DOMUtils.h b/src/uscxml/DOMUtils.h
index b3b87c8..ab99759 100644
--- a/src/uscxml/DOMUtils.h
+++ b/src/uscxml/DOMUtils.h
@@ -50,26 +50,26 @@ public:
// deprecated, use stringIsTrue from Convenience.h instead
DEPRECATED static bool attributeIsTrue(const::std::string& value);
- static Arabica::XPath::NodeSet<std::string> inPostFixOrder(const std::string& element,
- const Arabica::DOM::Element<std::string>& root,
- const bool includeEmbeddedDoc = false) {
- std::set<std::string> elements;
- elements.insert(element);
- return inPostFixOrder(elements, root, includeEmbeddedDoc);
- }
+ static Arabica::XPath::NodeSet<std::string> inPostFixOrder(const std::string& element,
+ const Arabica::DOM::Element<std::string>& root,
+ const bool includeEmbeddedDoc = false) {
+ std::set<std::string> elements;
+ elements.insert(element);
+ return inPostFixOrder(elements, root, includeEmbeddedDoc);
+ }
static Arabica::XPath::NodeSet<std::string> inPostFixOrder(const std::set<std::string>& elements,
const Arabica::DOM::Element<std::string>& root,
const bool includeEmbeddedDoc = false);
- static Arabica::XPath::NodeSet<std::string> inDocumentOrder(const std::string& element,
- const Arabica::DOM::Element<std::string>& root,
- const bool includeEmbeddedDoc = false) {
- std::set<std::string> elements;
- elements.insert(element);
- return inDocumentOrder(elements, root, includeEmbeddedDoc);
- }
-
+ static Arabica::XPath::NodeSet<std::string> inDocumentOrder(const std::string& element,
+ const Arabica::DOM::Element<std::string>& root,
+ const bool includeEmbeddedDoc = false) {
+ std::set<std::string> elements;
+ elements.insert(element);
+ return inDocumentOrder(elements, root, includeEmbeddedDoc);
+ }
+
static Arabica::XPath::NodeSet<std::string> inDocumentOrder(const std::set<std::string>& elements,
const Arabica::DOM::Element<std::string>& root,
const bool includeEmbeddedDoc = false);
diff --git a/src/uscxml/transform/ChartToC.cpp b/src/uscxml/transform/ChartToC.cpp
index d9f1f0e..3c92e4a 100644
--- a/src/uscxml/transform/ChartToC.cpp
+++ b/src/uscxml/transform/ChartToC.cpp
@@ -405,6 +405,12 @@ void ChartToC::prepare() {
void ChartToC::writeTo(std::ostream& stream) {
+ stream << "/**" << std::endl;
+ stream << " Generated from source:" << std::endl;
+ stream << " " << _sourceURL.asString() << std::endl;
+ stream << "*/" << std::endl;
+ stream << std::endl;
+
writeIncludes(stream);
writeMacros(stream);
writeTypes(stream);
@@ -439,11 +445,11 @@ void ChartToC::findNestedMachines() {
ChartToC* c2c = NULL;
if (HAS_ATTR(invoke, "src")) {
- URL srcURL(ATTR(invoke, "src"));
- if (!srcURL.toAbsolute(getBaseURLForNode(invoke))) {
- LOG(ERROR) << "invoke element has relative src URL with no baseURL set.";
- return;
- }
+ URL srcURL(ATTR(invoke, "src"));
+ if (!srcURL.toAbsolute(getBaseURLForNode(invoke))) {
+ LOG(ERROR) << "invoke element has relative src URL with no baseURL set.";
+ return;
+ }
c2c = new ChartToC(Interpreter::fromURL(srcURL.asString()));
} else {
// is there a nested scxml machine inside?
@@ -556,8 +562,8 @@ void ChartToC::writeMacros(std::ostream& stream) {
stream << "#define SCXML_CTX_SPONTANEOUS 0x01" << std::endl;
stream << "#define SCXML_CTX_INITIALIZED 0x02" << std::endl;
stream << "#define SCXML_CTX_TOP_LEVEL_FINAL 0x04" << std::endl;
- stream << "#define SCXML_CTX_TRANSITION_FOUND 0x08" << std::endl;
- stream << "#define SCXML_CTX_FINISHED 0x10" << std::endl;
+ stream << "#define SCXML_CTX_TRANSITION_FOUND 0x08" << std::endl;
+ stream << "#define SCXML_CTX_FINISHED 0x10" << std::endl;
stream << std::endl;
@@ -692,8 +698,8 @@ void ChartToC::writeTypes(std::ostream& stream) {
stream << " const char* src;" << std::endl;
stream << " const char* srcexpr;" << std::endl;
stream << " const char* id;" << std::endl;
- stream << " const char* idlocation;" << std::endl;
- stream << " const char* sourcename;" << std::endl;
+ stream << " const char* idlocation;" << std::endl;
+ stream << " const char* sourcename;" << std::endl;
stream << " const char* namelist;" << std::endl;
stream << " const uint8_t autoforward;" << std::endl;
stream << " const scxml_elem_param* params;" << std::endl;
@@ -1146,8 +1152,8 @@ void ChartToC::writeElementInfoInvocation(std::ostream& stream) {
stream << " const char* src;" << std::endl;
stream << " const char* srcexpr;" << std::endl;
stream << " const char* id;" << std::endl;
- stream << " const char* idlocation;" << std::endl;
- stream << " const char* sourcename;" << std::endl;
+ stream << " const char* idlocation;" << std::endl;
+ stream << " const char* sourcename;" << std::endl;
stream << " const char* namelist;" << std::endl;
stream << " const uint8_t autoforward;" << std::endl;
stream << " const scxml_elem_param* params;" << std::endl;
@@ -1197,9 +1203,9 @@ void ChartToC::writeElementInfoInvocation(std::ostream& stream) {
stream << (HAS_ATTR(invoke, "idlocation") ? "\"" + escape(ATTR(invoke, "idlocation")) + "\"" : "NULL");
stream << ", " << std::endl;
- stream << " /* sourcename */ ";
- stream << (HAS_ATTR_CAST(invoke.getParentNode(), "id") ? "\"" + escape(ATTR_CAST(invoke.getParentNode(), "id")) + "\"" : "NULL");
- stream << ", " << std::endl;
+ stream << " /* sourcename */ ";
+ stream << (HAS_ATTR_CAST(invoke.getParentNode(), "id") ? "\"" + escape(ATTR_CAST(invoke.getParentNode(), "id")) + "\"" : "NULL");
+ stream << ", " << std::endl;
stream << " /* namelist */ ";
stream << (HAS_ATTR(invoke, "namelist") ? "\"" + escape(ATTR(invoke, "namelist")) + "\"" : "NULL");
@@ -1253,7 +1259,7 @@ void ChartToC::writeElementInfoInvocation(std::ostream& stream) {
}
void ChartToC::writeElementInfo(std::ostream& stream) {
- NodeSet<std::string> foreachs = DOMUtils::inDocumentOrder(_nsInfo.xmlNSPrefix + "foreach", _scxml);
+ NodeSet<std::string> foreachs = DOMUtils::inDocumentOrder(_nsInfo.xmlNSPrefix + "foreach", _scxml);
if (foreachs.size() > 0) {
_hasElement.insert("foreach");
stream << "static const scxml_elem_foreach " << _prefix << "_elem_foreachs[" << foreachs.size() << "] = {" << std::endl;
@@ -1315,7 +1321,7 @@ void ChartToC::writeElementInfo(std::ostream& stream) {
if (dataTexts.size() > 0) {
if (boost::trim_copy(dataTexts[0].getNodeValue()).length() > 0) {
std::string escaped = escape(dataTexts[0].getNodeValue());
- stream << "\"" << escaped << "\"" << std::endl;
+ stream << "\"" << escaped << "\"";
}
} else {
stream << "NULL";
@@ -1507,7 +1513,7 @@ void ChartToC::writeMachineInfo(std::ostream& stream) {
stream << " }," << std::endl;
}
- stream << " {0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL }" << std::endl;
+ stream << " {0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }" << std::endl;
stream << "};" << std::endl;
stream << std::endl;
}
@@ -1759,18 +1765,18 @@ void ChartToC::writeFSM(std::ostream& stream) {
stream << "int scxml_step(scxml_ctx* ctx) {" << std::endl;
stream << std::endl;
- stream << " " << (_states.size() > _transitions.size() ? "SCXML_NR_STATES_TYPE" : "SCXML_NR_TRANS_TYPE") << " i, j, k;" << std::endl;
- stream << " SCXML_NR_STATES_TYPE nr_states_bytes = ((SCXML_NUMBER_STATES + 7) & ~7) >> 3;" << std::endl;
- stream << " SCXML_NR_TRANS_TYPE nr_trans_bytes = ((SCXML_NUMBER_TRANS + 7) & ~7) >> 3;" << std::endl;
- stream << " int err = SCXML_ERR_OK;" << std::endl;
-
- stream << " char conflicts [SCXML_MAX_NR_TRANS_BYTES];" << std::endl;
- stream << " char trans_set [SCXML_MAX_NR_TRANS_BYTES];" << std::endl;
- stream << " char target_set [SCXML_MAX_NR_STATES_BYTES];" << std::endl;
- stream << " char exit_set [SCXML_MAX_NR_STATES_BYTES];" << std::endl;
- stream << " char entry_set [SCXML_MAX_NR_STATES_BYTES];" << std::endl;
- stream << " char tmp_states [SCXML_MAX_NR_STATES_BYTES];" << std::endl;
- stream << std::endl;
+ stream << " " << (_states.size() > _transitions.size() ? "SCXML_NR_STATES_TYPE" : "SCXML_NR_TRANS_TYPE") << " i, j, k;" << std::endl;
+ stream << " SCXML_NR_STATES_TYPE nr_states_bytes = ((SCXML_NUMBER_STATES + 7) & ~7) >> 3;" << std::endl;
+ stream << " SCXML_NR_TRANS_TYPE nr_trans_bytes = ((SCXML_NUMBER_TRANS + 7) & ~7) >> 3;" << std::endl;
+ stream << " int err = SCXML_ERR_OK;" << std::endl;
+
+ stream << " char conflicts [SCXML_MAX_NR_TRANS_BYTES];" << std::endl;
+ stream << " char trans_set [SCXML_MAX_NR_TRANS_BYTES];" << std::endl;
+ stream << " char target_set [SCXML_MAX_NR_STATES_BYTES];" << std::endl;
+ stream << " char exit_set [SCXML_MAX_NR_STATES_BYTES];" << std::endl;
+ stream << " char entry_set [SCXML_MAX_NR_STATES_BYTES];" << std::endl;
+ stream << " char tmp_states [SCXML_MAX_NR_STATES_BYTES];" << std::endl;
+ stream << std::endl;
stream << "#ifdef SCXML_VERBOSE" << std::endl;
stream << " printf(\"Config: \");" << std::endl;
@@ -1778,9 +1784,9 @@ void ChartToC::writeFSM(std::ostream& stream) {
stream << "#endif" << std::endl;
stream << std::endl;
- stream << " if (ctx->flags & SCXML_CTX_FINISHED)" << std::endl;
- stream << " return SCXML_ERR_DONE;" << std::endl;
- stream << std::endl;
+ stream << " if (ctx->flags & SCXML_CTX_FINISHED)" << std::endl;
+ stream << " return SCXML_ERR_DONE;" << std::endl;
+ stream << std::endl;
stream << " if (ctx->flags & SCXML_CTX_TOP_LEVEL_FINAL) {" << std::endl;
stream << " // exit all remaining states" << std::endl;
@@ -1794,6 +1800,11 @@ void ChartToC::writeFSM(std::ostream& stream) {
stream << " }" << std::endl;
// stream << " BIT_CLEAR(i, ctx->config);" << std::endl;
stream << " }" << std::endl;
+ stream << " if (BIT_HAS(i, ctx->invocations)) {" << std::endl;
+ stream << " if (ctx->machine->states[i].invoke != NULL)" << std::endl;
+ stream << " ctx->machine->states[i].invoke(ctx, &ctx->machine->states[i], NULL, 1);" << std::endl;
+ stream << " BIT_CLEAR(i, ctx->invocations);" << std::endl;
+ stream << " }" << std::endl;
stream << " }" << std::endl;
stream << " ctx->flags |= SCXML_CTX_FINISHED;" << std::endl;
stream << " return SCXML_ERR_DONE;" << std::endl;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 42e518b..c4486eb 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -133,7 +133,11 @@ if (NOT BUILD_MINIMAL)
# prepare directories for test classes and copy resources over
foreach(W3C_RESOURCE ${W3C_RESOURCES} )
- get_filename_component(TEST_DATAMODEL ${W3C_RESOURCE} NAME)
+ get_filename_component(TEST_DATAMODEL ${W3C_RESOURCE} PATH)
+ get_filename_component(TEST_DATAMODEL ${TEST_DATAMODEL} NAME)
+
+ # message(STATUS "W3C_RESOURCE: ${W3C_RESOURCE}")
+ # message(STATUS "TEST_DATAMODEL: ${TEST_DATAMODEL}")
foreach(TEST_CLASS ${TEST_CLASSES})
# datamodel has to be the suffix of the test class
diff --git a/test/ctest/CTestCustom.ctest.in b/test/ctest/CTestCustom.ctest.in
index a140476..a9a96ad 100644
--- a/test/ctest/CTestCustom.ctest.in
+++ b/test/ctest/CTestCustom.ctest.in
@@ -197,63 +197,24 @@ set(CTEST_CUSTOM_TESTS_IGNORE
### Ignore for generated C sources
- # we do not support invokers yet
- # "gen/c/ecma/test187.scxml"
- # "gen/c/ecma/test191.scxml"
- # "gen/c/ecma/test192.scxml"
- # "gen/c/ecma/test207.scxml"
- # "gen/c/ecma/test215.scxml"
"gen/c/ecma/test216.scxml" // invoke srcexpr
- # "gen/c/ecma/test220.scxml"
- # "gen/c/ecma/test223.scxml"
- # "gen/c/ecma/test224.scxml"
- # "gen/c/ecma/test225.scxml"
- # "gen/c/ecma/test226.scxml"
- # "gen/c/ecma/test228.scxml"
- # "gen/c/ecma/test229.scxml"
- # "gen/c/ecma/test230.scxml"
- # "gen/c/ecma/test232.scxml"
- # "gen/c/ecma/test233.scxml"
- # "gen/c/ecma/test234.scxml"
- # "gen/c/ecma/test235.scxml"
- # "gen/c/ecma/test236.scxml"
- # "gen/c/ecma/test237.scxml"
- # "gen/c/ecma/test239.scxml"
- # "gen/c/ecma/test240.scxml"
- # "gen/c/ecma/test241.scxml"
- # "gen/c/ecma/test242.scxml"
- # "gen/c/ecma/test243.scxml"
- # "gen/c/ecma/test244.scxml"
- # "gen/c/ecma/test245.scxml"
- # "gen/c/ecma/test247.scxml"
- # "gen/c/ecma/test250.scxml"
- # "gen/c/ecma/test252.scxml"
- # "gen/c/ecma/test253.scxml"
- # "gen/c/ecma/test276.scxml"
- # "gen/c/ecma/test338.scxml"
- # "gen/c/ecma/test347.scxml"
- # "gen/c/ecma/test422.scxml"
- # "gen/c/ecma/test530.scxml"
- # "gen/c/ecma/test554.scxml"
# we do not support io processors yet
- "gen/c/ecma/test201.scxml"
- "gen/c/ecma/test496.scxml"
- "gen/c/ecma/test500.scxml"
- "gen/c/ecma/test501.scxml"
- "gen/c/ecma/test509.scxml"
- "gen/c/ecma/test510.scxml"
- "gen/c/ecma/test518.scxml"
- "gen/c/ecma/test519.scxml"
- "gen/c/ecma/test520.scxml"
- "gen/c/ecma/test521.scxml"
- "gen/c/ecma/test522.scxml"
- "gen/c/ecma/test531.scxml"
- "gen/c/ecma/test532.scxml"
- "gen/c/ecma/test534.scxml"
- "gen/c/ecma/test567.scxml"
- "gen/c/ecma/test569.scxml"
- "gen/c/ecma/test577.scxml"
+ "gen/c/ecma/test201.scxml" # basichttp
+ "gen/c/ecma/test500.scxml" # _ioprocessors
+ "gen/c/ecma/test501.scxml" # _ioprocessors
+ "gen/c/ecma/test509.scxml" # _ioprocessors / basichttp
+ "gen/c/ecma/test510.scxml" # _ioprocessors / basichttp
+ "gen/c/ecma/test518.scxml" # _ioprocessors / basichttp
+ "gen/c/ecma/test519.scxml" # _ioprocessors / basichttp
+ "gen/c/ecma/test520.scxml" # _ioprocessors / basichttp
+ "gen/c/ecma/test522.scxml" # _ioprocessors / basichttp
+ "gen/c/ecma/test531.scxml" # _ioprocessors / basichttp
+ "gen/c/ecma/test532.scxml" # _ioprocessors / basichttp
+ "gen/c/ecma/test534.scxml" # _ioprocessors / basichttp
+ "gen/c/ecma/test567.scxml" # _ioprocessors / basichttp
+ "gen/c/ecma/test569.scxml" # _ioprocessors
+ "gen/c/ecma/test577.scxml" # basichttp
# failing is succeeding
"gen/c/ecma/test301.scxml"
@@ -261,13 +222,9 @@ set(CTEST_CUSTOM_TESTS_IGNORE
# manual test
"gen/c/ecma/test307.scxml"
- # data from file
- "gen/c/ecma/test446.scxml"
- "gen/c/ecma/test552.scxml"
- "gen/c/ecma/test557.scxml"
- "gen/c/ecma/test558.scxml"
-
# XML DOM in data
+ "gen/c/ecma/test530.scxml"
+ "gen/c/ecma/test557.scxml"
"gen/c/ecma/test561.scxml"
diff --git a/test/src/test-c-machine.cpp b/test/src/test-c-machine.cpp
index b80ef72..85571e4 100644
--- a/test/src/test-c-machine.cpp
+++ b/test/src/test-c-machine.cpp
@@ -21,6 +21,7 @@
#endif
#include "uscxml/Convenience.h"
+#include "uscxml/URL.h"
#include "uscxml/concurrency/Timer.h"
//#include "uscxml/DOMUtils.h"
#include "uscxml/Factory.h"
@@ -40,23 +41,24 @@ using namespace uscxml;
class StateMachine : public InterpreterInfo {
public:
- StateMachine(const scxml_machine* machine) : parentMachine(NULL), topMostMachine(NULL), invocation(NULL) {
- init(machine);
+ StateMachine(const scxml_machine* machine) : machine(machine), parentMachine(NULL), topMostMachine(NULL), invocation(NULL) {
allMachines[sessionId] = this;
topMostMachine = this;
currentMachine = allMachines.begin();
+ init();
}
- StateMachine(StateMachine* parent, const scxml_machine* machine, const scxml_elem_invoke* invoke) : invocation(invoke) {
+ StateMachine(StateMachine* parent, const scxml_machine* machine, const scxml_elem_invoke* invoke) : machine(machine), invocation(invoke) {
parentMachine = parent;
topMostMachine = parent->topMostMachine;
- init(machine);
+ init();
}
- void init(const scxml_machine* machine) {
+ void init() {
sessionId = UUID::getUUID();
- isFinalized = false;
-
+ isFinalized = false;
+ currEvent = NULL;
+
// clear and initialize machine context
memset(&ctx, 0, sizeof(scxml_ctx));
ctx.machine = machine;
@@ -84,58 +86,62 @@ 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());
- }
- }
- }
- }
+
+ if (invocation != NULL) {
+ /// test 226/240 - initialize from invoke request
+ if (invocation->params != NULL) {
+ const scxml_elem_param* param = invocation->params;
+ while(ELEM_PARAM_IS_SET(param)) {
+ std::string identifier;
+ if (param->name != NULL) {
+ identifier = param->name;
+ } else if (param->location != NULL) {
+ identifier = param->location;
+ }
+ invokeData[identifier] = parentMachine->dataModel.getStringAsData(param->expr);
+ 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);
+ invokeData[identifier] = parentMachine->dataModel.getStringAsData(identifier);
+ }
+ }
+ }
}
virtual ~StateMachine() {
+ if (parentMachine != NULL) {
+ topMostMachine->allMachines.erase(topMostMachine->invocationIds[invocation]);
+ }
+// finalize();
+
delayQueue.stop();
+ delayQueue.cancelAllEvents();
+
+ while(eq.size() > 0) {
+ delete eq.front();
+ eq.pop_front();
+ }
+ eq.clear();
+ while(iq.size() > 0) {
+ delete iq.front();
+ iq.pop_front();
+ }
+ iq.clear();
}
bool hasPendingWork() {
@@ -150,27 +156,41 @@ public:
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 finalize() {
+ if (isFinalized)
+ return;
+
+ delayQueue.stop();
+ delayQueue.cancelAllEvents();
+
+ if (parentMachine != NULL) {
+ tthread::lock_guard<tthread::mutex> lock(mutex);
+
+ Event* done = new Event();
+ done->invokeid = invokeId;
+ done->name = "done.invoke." + invokeId;
+ parentMachine->eq.push_back(done);
+ }
+ isFinalized = true;
+ }
void reset() {
- sessionId = UUID::getUUID();
+ delayQueue.stop();
+ delayQueue.cancelAllEvents();
+
+ while(eq.size() > 0) {
+ delete eq.front();
+ eq.pop_front();
+ }
+ while(iq.size() > 0) {
+ delete iq.front();
+ iq.pop_front();
+ }
+
iq.clear();
eq.clear();
- delayQueue.cancelAllEvents();
- dataModel = Factory::getInstance()->createDataModel(ctx.machine->datamodel, this);
+ init();
}
@@ -185,13 +205,19 @@ public:
return SCXML_ERR_IDLE;
}
- // test 187
- if (toRun->isDone()) {
- toRun->finalize();
- return SCXML_ERR_IDLE;
- }
-
- return scxml_step(&toRun->ctx);
+ // test 187
+ if (toRun->isDone()) {
+ toRun->finalize();
+ return SCXML_ERR_IDLE;
+ }
+
+ state = scxml_step(&toRun->ctx);
+ if (toRun->currEvent != NULL) {
+ delete toRun->currEvent;
+ toRun->currEvent = NULL;
+ }
+
+ return state;
}
// InterpreterInfo
@@ -238,10 +264,10 @@ public:
}
}
- // real event but spontaneous transition
- if (t->event == NULL)
- return false;
-
+ // 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)
@@ -261,44 +287,49 @@ public:
}
static int invoke(const scxml_ctx* ctx, const scxml_state* s, const scxml_elem_invoke* invocation, uint8_t uninvoke) {
- 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;
+ 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 = NULL;
+ try {
+ invokedMachine = new StateMachine(USER_DATA(ctx), invocation->machine, invocation);
+ } catch (Event e) {
+ delete invokedMachine;
+ return SCXML_ERR_EXEC_CONTENT;
+ }
+ 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) {
@@ -383,8 +414,8 @@ public:
}
e->origintype = e->type;
- e->invokeid = USER_DATA(ctx)->invokeId;
-
+ e->invokeid = USER_DATA(ctx)->invokeId;
+
if (send->eventexpr != NULL) {
e->name = USER_DATA(ctx)->dataModel.evalAsString(send->eventexpr);
} else {
@@ -595,22 +626,51 @@ public:
static int execContentInit(const scxml_ctx* ctx, const scxml_elem_data* data) {
while(ELEM_DATA_IS_SET(data)) {
- // 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());
- }
- }
+ if (USER_DATA(ctx)->invokeData.find(data->id) != USER_DATA(ctx)->invokeData.end()) {
+ // passed via param or namelist: test245
+ try {
+ USER_DATA(ctx)->dataModel.init(data->id, USER_DATA(ctx)->invokeData[data->id]);
+ } catch (Event e) {
+ execContentRaise(ctx, e.name.c_str());
+ }
+ } else {
+ Data d;
+ std::stringstream content;
+
+ if (data->expr != NULL) {
+ d = Data(data->expr, Data::INTERPRETED);
+ } else if (data->content != NULL) {
+ content << data->content;
+ d = Data(content.str(), Data::INTERPRETED);
+ } else if (data->src != NULL) {
+ URL sourceURL(data->src);
+ if (USER_DATA(ctx)->baseURL.size() > 0) {
+ sourceURL.toAbsolute(USER_DATA(ctx)->baseURL);
+ } else {
+ sourceURL.toAbsoluteCwd();
+ }
+ content << sourceURL;
+ d = Data(content.str(), Data::INTERPRETED);
+
+ } else {
+ d = Data("undefined", Data::INTERPRETED);
+ }
+ try {
+ // this might fail with an unquoted string literal in content
+ USER_DATA(ctx)->dataModel.init(data->id, d);
+ } catch (Event e) {
+ if (content.str().size() > 0) {
+ try {
+ d = Data(escape(spaceNormalize(content.str())), Data::VERBATIM);
+ USER_DATA(ctx)->dataModel.init(data->id, d);
+ } catch (Event e) {
+ execContentRaise(ctx, e.name.c_str());
+ }
+ } else {
+ execContentRaise(ctx, e.name.c_str());
+ }
+ }
+ }
data++;
}
return SCXML_ERR_OK;
@@ -632,9 +692,10 @@ public:
Event* e = USER_DATA(ctx)->eq.front();
USER_DATA(ctx)->eq.pop_front();
+ USER_DATA(ctx)->currEvent = e;
USER_DATA(ctx)->dataModel.setEvent(*e);
- std::map<std::string, StateMachine*>& allMachines = USER_DATA(ctx)->topMostMachine->allMachines;
+ 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 = allMachines[e->invokeid];
@@ -643,16 +704,19 @@ public:
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);
- }
- }
-
+
+ // 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) {
+ tthread::lock_guard<tthread::mutex> lock(machIter->second->mutex);
+
+ Event* ne = new Event(*e);
+ machIter->second->eq.push_back(ne);
+ }
+ }
+
#ifdef SCXML_VERBOSE
printf("Popping External Event: %s\n", e->name.c_str());
#endif
@@ -664,6 +728,7 @@ public:
return NULL;
Event* e = USER_DATA(ctx)->iq.front();
USER_DATA(ctx)->iq.pop_front();
+ USER_DATA(ctx)->currEvent = e;
USER_DATA(ctx)->dataModel.setEvent(*e);
#ifdef SCXML_VERBOSE
printf("Popping Internal Event: %s\n", e->name.c_str());
@@ -683,36 +748,44 @@ public:
printf("Pushing Internal Event: %s\n", e->name.c_str());
#endif
USER_DATA(ctx)->iq.push_back(e);
- } else if (sr->target == "#_external") {
- e->eventType = Event::EXTERNAL;
+ } else if (sr->target == "#_external") {
+ e->eventType = Event::EXTERNAL;
#ifdef SCXML_VERBOSE
- printf("Pushing External Event: %s\n", e->name.c_str());
+ printf("Pushing External Event: %s\n", e->name.c_str());
#endif
- USER_DATA(ctx)->eq.push_back(e);
- } else if (sr->target == "#_parent") {
+ 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 if (sr->target.substr(0,8) == "#_scxml_") {
+ std::string sessionId = sr->target.substr(8);
+ bool sessionFound = false;
+ 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);
+ sessionFound = true;
+ break;
+ }
+ }
+ if (!sessionFound) {
+ // test496
+ execContentRaise((scxml_ctx*)ctx, "error.communication");
+ }
+ } 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 {
+ execContentRaise((scxml_ctx*)ctx, "error.communication");
+ }
} else {
- assert(false);
+ assert(false);
}
USER_DATA(ctx)->monitor.notify_all();
delete sr;
@@ -790,24 +863,28 @@ NEXT_DESC:
return false;
}
- std::map<const scxml_elem_invoke*, std::string> invocationIds;
+ Event* currEvent;
+
+ std::map<const scxml_elem_invoke*, std::string> invocationIds;
std::map<std::string, StateMachine*> allMachines;
+ bool isFinalized;
+ int state;
+ scxml_ctx ctx;
+ const scxml_machine* machine;
+
StateMachine* parentMachine;
StateMachine* topMostMachine;
std::map<std::string, StateMachine* >::iterator currentMachine; // next machine to advance
- bool isFinalized;
- int state;
- scxml_ctx ctx;
-
+ std::string baseURL;
std::string sessionId;
std::string name;
// in case we were invoked
std::string invokeId;
const scxml_elem_invoke* invocation;
- std::set<std::string> invokeIdentifiers;
+ std::map<std::string, Data> invokeData;
std::deque<Event*> iq;
std::deque<Event*> eq;
@@ -893,6 +970,7 @@ int main(int argc, char** argv) {
std::cerr << "Interpreter did not end in pass" << std::endl;
exit(EXIT_FAILURE);
}
+ rootMachine.reset();
}
tTotal.stop();
std::cout << benchmarkRuns << " iterations" << std::endl;
diff --git a/test/src/test-c-machine.machine.c b/test/src/test-c-machine.machine.c
index f3ec413..cb9fcae 100644
--- a/test/src/test-c-machine.machine.c
+++ b/test/src/test-c-machine.machine.c
@@ -1,3 +1,8 @@
+/**
+ Generated from source:
+ file:///Users/sradomski/Documents/TK/Code/uscxml/test/w3c/ecma/test237.scxml
+*/
+
#include <stdint.h> // explicit types
#include <stddef.h> // NULL
@@ -119,7 +124,7 @@ struct scxml_machine {
};
// forward declare machines to allow references
-extern const scxml_machine scxml_machines[4];
+extern const scxml_machine scxml_machines[3];
struct scxml_elem_data {
const char* id;
@@ -236,21 +241,9 @@ struct scxml_ctx {
invoke_t invoke;
};
-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_22A28DED_elem_params[2] = {
- /* name, expr, location */
- { "Var1", "1", NULL },
- { NULL, NULL, NULL }
-};
-
-static const scxml_elem_send _scxml_22A28DED_elem_sends[1] = {
+static const scxml_elem_send _scxml_290B2E91_elem_sends[2] = {
{
- /* event */ "timeout",
+ /* event */ "timeout1",
/* eventexpr */ NULL,
/* target */ NULL,
/* targetexpr */ NULL,
@@ -258,8 +251,24 @@ static const scxml_elem_send _scxml_22A28DED_elem_sends[1] = {
/* typeexpr */ NULL,
/* id */ NULL,
/* idlocation */ NULL,
- /* delay */ "2s",
- /* delayexpr */ NULL,
+ /* delay */ NULL,
+ /* delayexpr */ "'1s'",
+ /* namelist */ NULL,
+ /* content */ NULL,
+ /* contentexpr */ NULL,
+ /* params */ NULL
+ },
+ {
+ /* event */ "timeout2",
+ /* eventexpr */ NULL,
+ /* target */ NULL,
+ /* targetexpr */ NULL,
+ /* type */ NULL,
+ /* typeexpr */ NULL,
+ /* id */ NULL,
+ /* idlocation */ NULL,
+ /* delay */ NULL,
+ /* delayexpr */ "'1.5s'",
/* namelist */ NULL,
/* content */ NULL,
/* contentexpr */ NULL,
@@ -267,72 +276,66 @@ static const scxml_elem_send _scxml_22A28DED_elem_sends[1] = {
}
};
-static const scxml_elem_donedata _scxml_22A28DED_elem_donedatas[1] = {
+static const scxml_elem_donedata _scxml_290B2E91_elem_donedatas[1] = {
/* source, content, contentexpr, params */
{ 0, NULL, NULL, NULL }
};
-static const scxml_elem_invoke _scxml_22A28DED_elem_invokes[2] = {
+static const scxml_elem_invoke _scxml_290B2E91_elem_invokes[1] = {
{
/* machine */ &scxml_machines[1],
/* type */ "http://www.w3.org/TR/scxml/",
/* typeexpr */ NULL,
/* src */ NULL,
/* srcexpr */ NULL,
- /* id */ "43b1f997-4793-4391-8786-d387b411529d",
- /* idlocation */ NULL,
- /* sourcename */ "s01",
- /* namelist */ "Var1",
- /* autoforward */ 0,
- /* params */ NULL,
- /* 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",
+ /* id */ "6be2e509-b4f4-4179-8cba-1e8701b5d7a8",
/* idlocation */ NULL,
- /* sourcename */ "s02",
+ /* sourcename */ "s0",
/* namelist */ NULL,
/* autoforward */ 0,
- /* params */ &_scxml_22A28DED_elem_params[0],
+ /* params */ NULL,
/* finalize */ NULL,
/* content */ NULL,
/* contentexpr */ NULL,
}
};
-static int _scxml_22A28DED_s0_on_entry_0(const scxml_ctx* ctx, const scxml_state* state, const void* event) {
+static int _scxml_290B2E91_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_22A28DED_elem_sends[0])) != SCXML_ERR_OK) return err;
+ if ((ctx->exec_content_send(ctx, &_scxml_290B2E91_elem_sends[0])) != SCXML_ERR_OK) return err;
} else {
return SCXML_ERR_MISSING_CALLBACK;
}
return SCXML_ERR_OK;
}
-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);
+static int _scxml_290B2E91_s0_on_entry(const scxml_ctx* ctx, const scxml_state* state, const void* event) {
+ _scxml_290B2E91_s0_on_entry_0(ctx, state, event);
return SCXML_ERR_OK;
}
-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);
+static int _scxml_290B2E91_s0_invoke(const scxml_ctx* ctx, const scxml_state* s, const scxml_elem_invoke* invocation, uint8_t uninvoke) {
+ ctx->invoke(ctx, s, &_scxml_290B2E91_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);
+static int _scxml_290B2E91_s1_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_290B2E91_elem_sends[1])) != SCXML_ERR_OK) return err;
+ } else {
+ return SCXML_ERR_MISSING_CALLBACK;
+ }
+ return SCXML_ERR_OK;
+}
+static int _scxml_290B2E91_s1_on_entry(const scxml_ctx* ctx, const scxml_state* state, const void* event) {
+ _scxml_290B2E91_s1_on_entry_0(ctx, state, event);
return SCXML_ERR_OK;
}
-static int _scxml_22A28DED_pass_on_entry_0(const scxml_ctx* ctx, const scxml_state* state, const void* event) {
+
+static int _scxml_290B2E91_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;
@@ -342,12 +345,12 @@ static int _scxml_22A28DED_pass_on_entry_0(const scxml_ctx* ctx, const scxml_sta
return SCXML_ERR_OK;
}
-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);
+static int _scxml_290B2E91_pass_on_entry(const scxml_ctx* ctx, const scxml_state* state, const void* event) {
+ _scxml_290B2E91_pass_on_entry_0(ctx, state, event);
return SCXML_ERR_OK;
}
-static int _scxml_22A28DED_fail_on_entry_0(const scxml_ctx* ctx, const scxml_state* state, const void* event) {
+static int _scxml_290B2E91_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;
@@ -357,183 +360,125 @@ static int _scxml_22A28DED_fail_on_entry_0(const scxml_ctx* ctx, const scxml_sta
return SCXML_ERR_OK;
}
-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);
+static int _scxml_290B2E91_fail_on_entry(const scxml_ctx* ctx, const scxml_state* state, const void* event) {
+ _scxml_290B2E91_fail_on_entry_0(ctx, state, event);
return SCXML_ERR_OK;
}
-static const scxml_state _scxml_22A28DED_states[6] = {
+static const scxml_state _scxml_290B2E91_states[5] = {
{ /* state number 0 */
/* name */ NULL,
/* parent */ 0,
/* onentry */ NULL,
/* onexit */ NULL,
/* invoke */ NULL,
- /* children */ { 0x32 /* 010011 */ },
- /* completion */ { 0x02 /* 010000 */ },
- /* ancestors */ { 0x00 /* 000000 */ },
- /* data */ &_scxml_22A28DED_elem_datas[0],
+ /* children */ { 0x1e /* 01111 */ },
+ /* completion */ { 0x02 /* 01000 */ },
+ /* ancestors */ { 0x00 /* 00000 */ },
+ /* data */ NULL,
/* type */ SCXML_STATE_COMPOUND,
},
{ /* state number 1 */
/* name */ "s0",
/* parent */ 0,
- /* onentry */ _scxml_22A28DED_s0_on_entry,
+ /* onentry */ _scxml_290B2E91_s0_on_entry,
/* onexit */ NULL,
- /* invoke */ NULL,
- /* children */ { 0x0c /* 001100 */ },
- /* completion */ { 0x04 /* 001000 */ },
- /* ancestors */ { 0x01 /* 100000 */ },
+ /* invoke */ _scxml_290B2E91_s0_invoke,
+ /* children */ { 0x00 /* 00000 */ },
+ /* completion */ { 0x00 /* 00000 */ },
+ /* ancestors */ { 0x01 /* 10000 */ },
/* data */ NULL,
- /* type */ SCXML_STATE_COMPOUND,
+ /* type */ SCXML_STATE_ATOMIC,
},
{ /* state number 2 */
- /* name */ "s01",
- /* parent */ 1,
- /* onentry */ NULL,
+ /* name */ "s1",
+ /* parent */ 0,
+ /* onentry */ _scxml_290B2E91_s1_on_entry,
/* onexit */ NULL,
- /* invoke */ _scxml_22A28DED_s01_invoke,
- /* children */ { 0x00 /* 000000 */ },
- /* completion */ { 0x00 /* 000000 */ },
- /* ancestors */ { 0x03 /* 110000 */ },
+ /* invoke */ NULL,
+ /* children */ { 0x00 /* 00000 */ },
+ /* completion */ { 0x00 /* 00000 */ },
+ /* ancestors */ { 0x01 /* 10000 */ },
/* 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_22A28DED_pass_on_entry,
+ /* onentry */ _scxml_290B2E91_pass_on_entry,
/* onexit */ NULL,
/* invoke */ NULL,
- /* children */ { 0x00 /* 000000 */ },
- /* completion */ { 0x00 /* 000000 */ },
- /* ancestors */ { 0x01 /* 100000 */ },
+ /* children */ { 0x00 /* 00000 */ },
+ /* completion */ { 0x00 /* 00000 */ },
+ /* ancestors */ { 0x01 /* 10000 */ },
/* data */ NULL,
/* type */ SCXML_STATE_FINAL,
},
- { /* state number 5 */
+ { /* state number 4 */
/* name */ "fail",
/* parent */ 0,
- /* onentry */ _scxml_22A28DED_fail_on_entry,
+ /* onentry */ _scxml_290B2E91_fail_on_entry,
/* onexit */ NULL,
/* invoke */ NULL,
- /* children */ { 0x00 /* 000000 */ },
- /* completion */ { 0x00 /* 000000 */ },
- /* ancestors */ { 0x01 /* 100000 */ },
+ /* children */ { 0x00 /* 00000 */ },
+ /* completion */ { 0x00 /* 00000 */ },
+ /* ancestors */ { 0x01 /* 10000 */ },
/* data */ NULL,
/* type */ SCXML_STATE_FINAL,
}
};
-static const scxml_transition _scxml_22A28DED_transitions[5] = {
- { /* transition number 1 with priority 0
- target: s02
+static const scxml_transition _scxml_290B2E91_transitions[3] = {
+ { /* transition number 0 with priority 0
+ target: s1
*/
- /* source */ 2,
- /* target */ { 0x08 /* 000100 */ },
- /* event */ "success",
+ /* source */ 1,
+ /* target */ { 0x04 /* 00100 */ },
+ /* event */ "timeout1",
/* condition */ NULL,
/* ontrans */ NULL,
/* type */ 0,
- /* conflicts */ { 0x1f /* 11111 */ },
- /* exit set */ { 0x0c /* 001100 */ }
+ /* conflicts */ { 0x07 /* 111 */ },
+ /* exit set */ { 0x1e /* 01111 */ }
},
- { /* transition number 2 with priority 1
+ { /* transition number 1 with priority 1
target: fail
*/
/* source */ 2,
- /* target */ { 0x20 /* 000001 */ },
- /* event */ "failure",
+ /* target */ { 0x10 /* 00001 */ },
+ /* event */ "done.invoke",
/* condition */ NULL,
/* ontrans */ NULL,
/* type */ 0,
- /* conflicts */ { 0x1f /* 11111 */ },
- /* exit set */ { 0x3e /* 011111 */ }
+ /* conflicts */ { 0x07 /* 111 */ },
+ /* exit set */ { 0x1e /* 01111 */ }
},
- { /* transition number 3 with priority 2
+ { /* transition number 2 with priority 2
target: pass
*/
- /* source */ 3,
- /* target */ { 0x10 /* 000010 */ },
- /* event */ "success",
- /* condition */ NULL,
- /* ontrans */ NULL,
- /* type */ 0,
- /* conflicts */ { 0x1f /* 11111 */ },
- /* exit set */ { 0x3e /* 011111 */ }
- },
- { /* 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 */ { 0x20 /* 000001 */ },
- /* event */ "timeout",
+ /* source */ 2,
+ /* target */ { 0x08 /* 00010 */ },
+ /* event */ "*",
/* condition */ NULL,
/* ontrans */ NULL,
/* type */ 0,
- /* conflicts */ { 0x1f /* 11111 */ },
- /* exit set */ { 0x3e /* 011111 */ }
+ /* conflicts */ { 0x07 /* 111 */ },
+ /* exit set */ { 0x1e /* 01111 */ }
}
};
-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_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
- },
+static const scxml_elem_send _scxml_740A1EEF_elem_sends[1] = {
{
- /* event */ "failure",
+ /* event */ "timeout",
/* eventexpr */ NULL,
- /* target */ "#_parent",
+ /* target */ NULL,
/* targetexpr */ NULL,
/* type */ NULL,
/* typeexpr */ NULL,
/* id */ NULL,
/* idlocation */ NULL,
/* delay */ NULL,
- /* delayexpr */ NULL,
+ /* delayexpr */ "'2s'",
/* namelist */ NULL,
/* content */ NULL,
/* contentexpr */ NULL,
@@ -541,32 +486,27 @@ static const scxml_elem_send _scxml_FD9C4306_elem_sends[2] = {
}
};
-static const scxml_elem_donedata _scxml_FD9C4306_elem_donedatas[1] = {
+static const scxml_elem_donedata _scxml_740A1EEF_elem_donedatas[1] = {
/* source, content, contentexpr, params */
{ 0, NULL, NULL, NULL }
};
-static int _scxml_FD9C4306_sub01_transition0_on_trans(const scxml_ctx* ctx, const scxml_state* state, const void* event) {
+static int _scxml_740A1EEF_sub0_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_FD9C4306_elem_sends[0])) != SCXML_ERR_OK) return err;
+ if ((ctx->exec_content_send(ctx, &_scxml_740A1EEF_elem_sends[0])) != SCXML_ERR_OK) return err;
} else {
return SCXML_ERR_MISSING_CALLBACK;
}
return SCXML_ERR_OK;
}
-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;
- }
+static int _scxml_740A1EEF_sub0_on_entry(const scxml_ctx* ctx, const scxml_state* state, const void* event) {
+ _scxml_740A1EEF_sub0_on_entry_0(ctx, state, event);
return SCXML_ERR_OK;
}
-static const scxml_state _scxml_FD9C4306_states[3] = {
+static const scxml_state _scxml_740A1EEF_states[3] = {
{ /* state number 0 */
/* name */ NULL,
/* parent */ 0,
@@ -576,145 +516,13 @@ static const scxml_state _scxml_FD9C4306_states[3] = {
/* 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 */ "sub02",
+ /* name */ "sub0",
/* parent */ 0,
- /* onentry */ NULL,
+ /* onentry */ _scxml_740A1EEF_sub0_on_entry,
/* onexit */ NULL,
/* invoke */ NULL,
/* children */ { 0x00 /* 000 */ },
@@ -724,7 +532,7 @@ static const scxml_state _scxml_50B9C583_states[3] = {
/* type */ SCXML_STATE_ATOMIC,
},
{ /* state number 2 */
- /* name */ "subFinal2",
+ /* name */ "subFinal",
/* parent */ 0,
/* onentry */ NULL,
/* onexit */ NULL,
@@ -737,74 +545,49 @@ static const scxml_state _scxml_50B9C583_states[3] = {
}
};
-static const scxml_transition _scxml_50B9C583_transitions[2] = {
+static const scxml_transition _scxml_740A1EEF_transitions[1] = {
{ /* 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
+ target: subFinal
*/
/* source */ 1,
/* target */ { 0x04 /* 001 */ },
- /* event */ NULL,
+ /* event */ "timeout",
/* condition */ NULL,
- /* ontrans */ _scxml_50B9C583_sub02_transition1_on_trans,
- /* type */ SCXML_TRANS_SPONTANEOUS,
- /* conflicts */ { 0x03 /* 11 */ },
+ /* ontrans */ NULL,
+ /* type */ 0,
+ /* conflicts */ { 0x01 /* 1 */ },
/* exit set */ { 0x06 /* 011 */ }
}
};
-const scxml_machine scxml_machines[4] = {
+const scxml_machine scxml_machines[3] = {
{
/* flags */ 0,
- /* nr_states */ 6,
- /* nr_transitions */ 5,
+ /* nr_states */ 5,
+ /* nr_transitions */ 3,
/* name */ "",
/* datamodel */ "ecmascript",
- /* uuid */ "22A28DEDB4EF5C2066BF1D2C022A8AD9",
- /* states */ &_scxml_22A28DED_states[0],
- /* transitions */ &_scxml_22A28DED_transitions[0],
+ /* uuid */ "290B2E91E83BC4AC61271D1C9891410E",
+ /* states */ &_scxml_290B2E91_states[0],
+ /* transitions */ &_scxml_290B2E91_transitions[0],
/* parent */ NULL,
- /* donedata */ &_scxml_22A28DED_elem_donedatas[0],
+ /* donedata */ &_scxml_290B2E91_elem_donedatas[0],
/* script */ NULL
},
{
/* flags */ 0,
/* nr_states */ 3,
- /* nr_transitions */ 2,
+ /* nr_transitions */ 1,
/* name */ "",
/* datamodel */ "ecmascript",
- /* uuid */ "FD9C43066AC6FCEE1EC61755B4F2ED11",
- /* states */ &_scxml_FD9C4306_states[0],
- /* transitions */ &_scxml_FD9C4306_transitions[0],
+ /* uuid */ "740A1EEF39B05367B78DF059D2C8F917",
+ /* states */ &_scxml_740A1EEF_states[0],
+ /* transitions */ &_scxml_740A1EEF_transitions[0],
/* parent */ &scxml_machines[0],
- /* donedata */ &_scxml_FD9C4306_elem_donedatas[0],
+ /* donedata */ &_scxml_740A1EEF_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 }
+ {0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
#ifdef SCXML_VERBOSE
@@ -911,6 +694,11 @@ int scxml_step(scxml_ctx* ctx) {
return err;
}
}
+ if (BIT_HAS(i, ctx->invocations)) {
+ if (ctx->machine->states[i].invoke != NULL)
+ ctx->machine->states[i].invoke(ctx, &ctx->machine->states[i], NULL, 1);
+ BIT_CLEAR(i, ctx->invocations);
+ }
}
ctx->flags |= SCXML_CTX_FINISHED;
return SCXML_ERR_DONE;