From 18bca76b4f4d81db962e97cfe79611461a8b7e61 Mon Sep 17 00:00:00 2001 From: Stefan Radomski Date: Tue, 26 Jan 2016 09:32:56 +0100 Subject: Some code beautifications --- README.md | 6 +- src/uscxml/DOMUtils.cpp | 6 +- src/uscxml/debug/InterpreterIssue.cpp | 6 +- src/uscxml/transform/ChartToC.cpp | 478 ++++++++++----------- src/uscxml/transform/ChartToC.h | 4 +- test/src/test-c-machine.cpp | 16 +- test/src/test-c-machine.machine.c | 398 ++++++----------- .../automated/ecma/uncompleted-history.scxml | 11 - 8 files changed, 387 insertions(+), 538 deletions(-) delete mode 100644 test/uscxml/automated/ecma/uncompleted-history.scxml diff --git a/README.md b/README.md index 4dd1388..6e29edd 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ #### Related Documents -- [Building form Source](docs/BUILDING.md) +- [Building from Source](docs/BUILDING.md) - [Open Issues](docs/ISSUES.md) - [Getting Started](docs/GETTING_STARTED.md) @@ -111,7 +111,7 @@ upon](https://github.com/tklab-tud/uscxml/blob/master/docs/BUILDING.md#build-dep We did some performance measurements in the scope of the C transformation. As you can see in the figure below, for most IRP tests we average to a duration of -5-20us per microstep on an early 2015 MacBook Pro 13" with 3.1Ghz in the case +5-20us per microstep on an early 2015 MacBook Pro 13" with 3.1GHz in the case of [generated/compiled C](https://github.com/tklab-tud/uscxml/blob/master/test/src/test-c-machine.machine.c). For interpretation at runtime, we average at around 70-130us per microstep. The generated C is rather optimized while the focus of the interpreter is more on correctness, feature completeness and extensibility. @@ -121,7 +121,7 @@ interpreter. For the tests, we took the [highest precision timer](https://github.com/tklab-tud/uscxml/blob/master/src/uscxml/concurrency/Timer.cpp) -we could attain and measured how long the execution of a given SCXML IRP tests took while +we could attain and measured how long the execution of a given SCXML IRP test took while subtracting initialization, tear-down and the time spent in the data-model's routines. Time is averaged over 1.000 iterations. diff --git a/src/uscxml/DOMUtils.cpp b/src/uscxml/DOMUtils.cpp index 50548c3..9703432 100644 --- a/src/uscxml/DOMUtils.cpp +++ b/src/uscxml/DOMUtils.cpp @@ -39,9 +39,9 @@ std::string DOMUtils::idForNode(const Arabica::DOM::Node& node) { case Arabica::DOM::Node_base::ELEMENT_NODE: { Arabica::DOM::Element elem = Arabica::DOM::Element(curr); if (HAS_ATTR(elem, "id") && !UUID::isUUID(ATTR(elem, "id"))) { - std::string elementId = ATTR(elem, "id"); - boost::replace_all(elementId, ".", "_"); - boost::replace_all(elementId, ",", "_"); + std::string elementId = ATTR(elem, "id"); + boost::replace_all(elementId, ".", "_"); + boost::replace_all(elementId, ",", "_"); nodeId.insert(0, elementId + seperator); seperator = "_"; return nodeId; diff --git a/src/uscxml/debug/InterpreterIssue.cpp b/src/uscxml/debug/InterpreterIssue.cpp index 5fb3965..6b97182 100644 --- a/src/uscxml/debug/InterpreterIssue.cpp +++ b/src/uscxml/debug/InterpreterIssue.cpp @@ -302,9 +302,9 @@ std::list InterpreterIssue::forInterpreter(InterpreterImpl* in NodeSet transitions = InterpreterImpl::filterChildElements(_nsInfo.xmlNSPrefix + "transition", state, false); if (transitions.size() > 1) { issues.push_back(InterpreterIssue("History pseudo-state with id '" + stateId + "' has multiple transitions", state, InterpreterIssue::USCXML_ISSUE_FATAL)); - } else if (transitions.size() == 0) { - issues.push_back(InterpreterIssue("History pseudo-state with id '" + stateId + "' has no default transition", state, InterpreterIssue::USCXML_ISSUE_FATAL)); - } else { + } else if (transitions.size() == 0) { + issues.push_back(InterpreterIssue("History pseudo-state with id '" + stateId + "' has no default transition", state, InterpreterIssue::USCXML_ISSUE_FATAL)); + } else { Element transition = Element(transitions[0]); if (HAS_ATTR(transition, "cond")) { issues.push_back(InterpreterIssue("Transition in history pseudo-state '" + stateId + "' must not have a condition", transition, InterpreterIssue::USCXML_ISSUE_FATAL)); diff --git a/src/uscxml/transform/ChartToC.cpp b/src/uscxml/transform/ChartToC.cpp index e726d7f..2fc392a 100644 --- a/src/uscxml/transform/ChartToC.cpp +++ b/src/uscxml/transform/ChartToC.cpp @@ -36,6 +36,8 @@ namespace uscxml { using namespace Arabica::DOM; using namespace Arabica::XPath; +// many more tricks: https://graphics.stanford.edu/~seander/bithacks.html + Transformer ChartToC::transform(const Interpreter& other) { ChartToC* c2c = new ChartToC(other); @@ -47,137 +49,137 @@ ChartToC::ChartToC(const Interpreter& other) : TransformerImpl() { } void ChartToC::setHistoryResponsibility(Arabica::DOM::Node& node) { - std::set elements; - elements.insert(_nsInfo.xmlNSPrefix + "history"); - Arabica::XPath::NodeSet histories = inPostFixOrder(elements, _scxml); - - NodeSet covered; - NodeSet perParentcovered; - Node parent; - - for (size_t i = 0; i < histories.size(); i++) { - Element history(histories[i]); - NodeSet completion; - - if (parent != history.getParentNode()) { - covered.push_back(perParentcovered); - perParentcovered = NodeSet(); - parent = history.getParentNode(); - } - - bool deep = (HAS_ATTR(history, "type") && iequals(ATTR(history, "type"), "deep")); - for (size_t j = 0; j < _states.size(); j++) { - if (_states[j] == history) - continue; - - if (isDescendant(_states[j], history.getParentNode()) && isHistory(Element(_states[j]))) { - history.setAttribute("hasNestedHistory", "true"); - } - - if (isMember(_states[j], covered)) - continue; - - if (deep) { - if (isDescendant(_states[j], history.getParentNode()) && !isHistory(Element(_states[j]))) { - completion.push_back(_states[j]); - } - } else { - if (_states[j].getParentNode() == history.getParentNode() && !isHistory(Element(_states[j]))) { - completion.push_back(_states[j]); - } - } - } - perParentcovered.push_back(completion); - - std::string respBools; - std::string respBoolsIdx; - for (size_t j = 0; j < _states.size(); j++) { - if (isMember(_states[j], completion)) { - respBools += "1"; - respBoolsIdx += " " + toStr(j); - } else { - respBools += "0"; - } - } - history.setAttribute("respBools", respBools); - history.setAttribute("respBoolsIdx", respBoolsIdx); - } + std::set elements; + elements.insert(_nsInfo.xmlNSPrefix + "history"); + Arabica::XPath::NodeSet histories = inPostFixOrder(elements, _scxml); + + NodeSet covered; + NodeSet perParentcovered; + Node parent; + + for (size_t i = 0; i < histories.size(); i++) { + Element history(histories[i]); + NodeSet completion; + + if (parent != history.getParentNode()) { + covered.push_back(perParentcovered); + perParentcovered = NodeSet(); + parent = history.getParentNode(); + } + + bool deep = (HAS_ATTR(history, "type") && iequals(ATTR(history, "type"), "deep")); + for (size_t j = 0; j < _states.size(); j++) { + if (_states[j] == history) + continue; + + if (isDescendant(_states[j], history.getParentNode()) && isHistory(Element(_states[j]))) { + history.setAttribute("hasNestedHistory", "true"); + } + + if (isMember(_states[j], covered)) + continue; + + if (deep) { + if (isDescendant(_states[j], history.getParentNode()) && !isHistory(Element(_states[j]))) { + completion.push_back(_states[j]); + } + } else { + if (_states[j].getParentNode() == history.getParentNode() && !isHistory(Element(_states[j]))) { + completion.push_back(_states[j]); + } + } + } + perParentcovered.push_back(completion); + + std::string respBools; + std::string respBoolsIdx; + for (size_t j = 0; j < _states.size(); j++) { + if (isMember(_states[j], completion)) { + respBools += "1"; + respBoolsIdx += " " + toStr(j); + } else { + respBools += "0"; + } + } + history.setAttribute("respBools", respBools); + history.setAttribute("respBoolsIdx", respBoolsIdx); + } } - + void ChartToC::resortStates(Arabica::DOM::Node& node) { - if (node.getNodeType() != Node_base::ELEMENT_NODE) - return; - - /** - initials - deep histories - shallow histories - everything else - */ - - Element element(node); - - // shallow history states to top - Node child = element.getFirstChild(); - while(child) { - resortStates(child); - if (child.getNodeType() == Node_base::ELEMENT_NODE && - TAGNAME_CAST(child) == _nsInfo.xmlNSPrefix + "history" && - (!HAS_ATTR(element, "type") || iequals(ATTR(element, "type"), "shallow"))) { - Node tmp = child.getNextSibling(); - if (child != element.getFirstChild()) { - element.insertBefore(child, element.getFirstChild()); - } - child = tmp; - } else { - child = child.getNextSibling(); - } - } - - // deep history states to top - child = element.getFirstChild(); - while(child) { - resortStates(child); - if (child.getNodeType() == Node_base::ELEMENT_NODE && - TAGNAME_CAST(child) == _nsInfo.xmlNSPrefix + "history" && - HAS_ATTR(element, "type") && - iequals(ATTR(element, "type"), "deep")) { - - Node tmp = child.getNextSibling(); - if (child != element.getFirstChild()) { - element.insertBefore(child, element.getFirstChild()); - } - child = tmp; - } else { - child = child.getNextSibling(); - } - } - - // initial states on top of histories even - child = element.getFirstChild(); - while(child) { - resortStates(child); - if (child.getNodeType() == Node_base::ELEMENT_NODE && TAGNAME_CAST(child) == _nsInfo.xmlNSPrefix + "initial") { - Node tmp = child.getNextSibling(); - if (child != element.getFirstChild()) { - element.insertBefore(child, element.getFirstChild()); - } - child = tmp; - } else { - child = child.getNextSibling(); - } - } + if (node.getNodeType() != Node_base::ELEMENT_NODE) + return; + + /** + initials + deep histories + shallow histories + everything else + */ + + Element element(node); + + // shallow history states to top + Node child = element.getFirstChild(); + while(child) { + resortStates(child); + if (child.getNodeType() == Node_base::ELEMENT_NODE && + TAGNAME_CAST(child) == _nsInfo.xmlNSPrefix + "history" && + (!HAS_ATTR(element, "type") || iequals(ATTR(element, "type"), "shallow"))) { + Node tmp = child.getNextSibling(); + if (child != element.getFirstChild()) { + element.insertBefore(child, element.getFirstChild()); + } + child = tmp; + } else { + child = child.getNextSibling(); + } + } + + // deep history states to top + child = element.getFirstChild(); + while(child) { + resortStates(child); + if (child.getNodeType() == Node_base::ELEMENT_NODE && + TAGNAME_CAST(child) == _nsInfo.xmlNSPrefix + "history" && + HAS_ATTR(element, "type") && + iequals(ATTR(element, "type"), "deep")) { + + Node tmp = child.getNextSibling(); + if (child != element.getFirstChild()) { + element.insertBefore(child, element.getFirstChild()); + } + child = tmp; + } else { + child = child.getNextSibling(); + } + } + + // initial states on top of histories even + child = element.getFirstChild(); + while(child) { + resortStates(child); + if (child.getNodeType() == Node_base::ELEMENT_NODE && TAGNAME_CAST(child) == _nsInfo.xmlNSPrefix + "initial") { + Node tmp = child.getNextSibling(); + if (child != element.getFirstChild()) { + element.insertBefore(child, element.getFirstChild()); + } + child = tmp; + } else { + child = child.getNextSibling(); + } + } } - + void ChartToC::writeTo(std::ostream& stream) { _binding = (HAS_ATTR(_scxml, "binding") && iequals(ATTR(_scxml, "binding"), "late") ? LATE : EARLY); _name = (HAS_ATTR(_scxml, "name") ? ATTR(_scxml, "name") : ""); - // make sure initial and history elements always precede propoer states - resortStates(_scxml); - + // make sure initial and history elements always precede propoer states + resortStates(_scxml); + std::set elements; elements.insert(_nsInfo.xmlNSPrefix + "scxml"); elements.insert(_nsInfo.xmlNSPrefix + "state"); @@ -246,8 +248,8 @@ void ChartToC::writeTo(std::ostream& stream) { _transDataType = "uint64_t"; } - // set the responsibility of history elements - setHistoryResponsibility(_scxml); + // set the responsibility of history elements + setHistoryResponsibility(_scxml); writeIncludes(stream); writeMacros(stream); @@ -270,9 +272,9 @@ void ChartToC::writeIncludes(std::ostream& stream) { } void ChartToC::writeMacros(std::ostream& stream) { - stream << "#define IS_SET(idx, bitset) ((bitset[idx >> 3] & (1 << (idx & 7))) != 0)" << std::endl; - stream << "#define SET_BIT(idx, bitset) bitset[idx >> 3] |= (1 << (idx & 7));" << std::endl; - stream << "#define CLEARBIT(idx, bitset) bitset[idx >> 3] &= (1 << (idx & 7)) ^ 0xFF;" << std::endl; + stream << "#define BIT_HAS(idx, bitset) ((bitset[idx >> 3] & (1 << (idx & 7))) != 0)" << std::endl; + stream << "#define BIT_SET_AT(idx, bitset) bitset[idx >> 3] |= (1 << (idx & 7));" << std::endl; + stream << "#define BIT_CLEAR(idx, bitset) bitset[idx >> 3] &= (1 << (idx & 7)) ^ 0xFF;" << std::endl; stream << std::endl; stream << "#ifdef __GNUC__" << std::endl; @@ -316,8 +318,8 @@ void ChartToC::writeMacros(std::ostream& stream) { stream << "#define SCXML_STATE_HISTORY_SHALLOW 0x06" << std::endl; stream << "#define SCXML_STATE_INITIAL 0x07" << std::endl; stream << "#define SCXML_STATE_HAS_HISTORY 0x80 // highest bit" << std::endl; - stream << "#define SCXML_STATE_MASK(t) (t & 0x7F) // mask highest bit" << std::endl; - + stream << "#define SCXML_STATE_MASK(t) (t & 0x7F) // mask highest bit" << std::endl; + stream << "" << std::endl; stream << "#define SCXML_CTX_PRISTINE 0x00" << std::endl; stream << "#define SCXML_CTX_SPONTANEOUS 0x01" << std::endl; @@ -498,7 +500,7 @@ void ChartToC::writeHelpers(std::ostream& stream) { stream << "static void printStateNames(const char* a) {" << std::endl; stream << " const char* seperator = \"\";" << std::endl; stream << " for (size_t i = 0; i < SCXML_NUMBER_STATES; i++) {" << std::endl; - stream << " if (IS_SET(i, a)) {" << std::endl; + stream << " if (BIT_HAS(i, a)) {" << std::endl; stream << " printf(\"%s%s\", seperator, (scxml_states[i].name != NULL ? scxml_states[i].name : \"UNK\"));" << std::endl; stream << " seperator = \", \";" << std::endl; stream << " }" << std::endl; @@ -510,7 +512,7 @@ void ChartToC::writeHelpers(std::ostream& stream) { stream << "static void printBitsetIndices(const char* a, size_t length) {" << std::endl; stream << " const char* seperator = \"\";" << std::endl; stream << " for (size_t i = 0; i < length; i++) {" << std::endl; - stream << " if (IS_SET(i, a)) {" << std::endl; + stream << " if (BIT_HAS(i, a)) {" << std::endl; stream << " printf(\"%s%lu\", seperator, i);" << std::endl; stream << " seperator = \", \";" << std::endl; stream << " }" << std::endl; @@ -521,49 +523,49 @@ void ChartToC::writeHelpers(std::ostream& stream) { stream << "#endif" << std::endl; stream << std::endl; - stream << "static void bit_or(char* dest, const char* mask, size_t i) {" << std::endl; + stream << "static int bit_has_and(const char* a, const char* b, size_t i) {" << std::endl; stream << " do {" << std::endl; - stream << " dest[i - 1] |= mask[i - 1];" << std::endl; + stream << " if (a[i - 1] & b[i - 1])" << std::endl; + stream << " return true;" << std::endl; stream << " } while(--i);" << std::endl; + stream << " return false;" << std::endl; stream << "}" << std::endl; stream << std::endl; - stream << "static void bit_copy(char* dest, const char* source, size_t i) {" << std::endl; + stream << "static int bit_has_any(const char* a, size_t i) {" << std::endl; stream << " do {" << std::endl; - stream << " dest[i - 1] = source[i - 1];" << std::endl; + stream << " if (a[i - 1] > 0)" << std::endl; + stream << " return true;" << std::endl; stream << " } while(--i);" << std::endl; + stream << " return false;" << std::endl; stream << "}" << std::endl; stream << std::endl; - stream << "static int bit_has_and(const char* a, const char* b, size_t i) {" << std::endl; + stream << "static void bit_or(char* dest, const char* mask, size_t i) {" << std::endl; stream << " do {" << std::endl; - stream << " if (a[i - 1] & b[i - 1])" << std::endl; - stream << " return true;" << std::endl; + stream << " dest[i - 1] |= mask[i - 1];" << std::endl; stream << " } while(--i);" << std::endl; - stream << " return false;" << std::endl; stream << "}" << std::endl; stream << std::endl; - stream << "static void bit_and_not(char* dest, const char* mask, size_t i) {" << std::endl; + stream << "static void bit_copy(char* dest, const char* source, size_t i) {" << std::endl; stream << " do {" << std::endl; - stream << " dest[i - 1] &= ~mask[i - 1];" << std::endl; + stream << " dest[i - 1] = source[i - 1];" << std::endl; stream << " } while(--i);" << std::endl; stream << "}" << std::endl; stream << std::endl; - stream << "static void bit_and(char* dest, const char* mask, size_t i) {" << std::endl; + stream << "static void bit_and_not(char* dest, const char* mask, size_t i) {" << std::endl; stream << " do {" << std::endl; - stream << " dest[i - 1] &= mask[i - 1];" << std::endl; + stream << " dest[i - 1] &= ~mask[i - 1];" << std::endl; stream << " } while(--i);" << std::endl; stream << "}" << std::endl; stream << std::endl; - stream << "static int bit_any_set(const char* a, size_t i) {" << std::endl; + stream << "static void bit_and(char* dest, const char* mask, size_t i) {" << std::endl; stream << " do {" << std::endl; - stream << " if (a[i - 1] > 0)" << std::endl; - stream << " return true;" << std::endl; + stream << " dest[i - 1] &= mask[i - 1];" << std::endl; stream << " } while(--i);" << std::endl; - stream << " return false;" << std::endl; stream << "}" << std::endl; stream << std::endl; @@ -624,12 +626,12 @@ void ChartToC::writeExecContent(std::ostream& stream) { stream << std::endl; } - /* - gen/c/ecma/test412.scxml (Failed) - gen/c/ecma/test579.scxml (Failed) - */ + /* + gen/c/ecma/test412.scxml (Failed) + gen/c/ecma/test579.scxml (Failed) + */ #if 0 - bool hasInitialState = false; + bool hasInitialState = false; NodeSet initial = filterChildElements(_nsInfo.xmlNSPrefix + "initial", state); if (initial.size() > 0) { NodeSet initialTransition = filterChildElements(_nsInfo.xmlNSPrefix + "transition", initial); @@ -1098,15 +1100,15 @@ void ChartToC::writeStates(std::ostream& stream) { stream << "," << std::endl; // children - bool hasHistoryChild = false; + bool hasHistoryChild = false; std::string childBools; std::string childBoolsIdx; for (size_t j = 0; j < _states.size(); j++) { if (_states[j].getParentNode() == state) { - if (isHistory(Element(_states[j]))) { - hasHistoryChild = true; - } - childBools += "1"; + if (isHistory(Element(_states[j]))) { + hasHistoryChild = true; + } + childBools += "1"; childBoolsIdx += " " + toStr(j); } else { childBools += "0"; @@ -1118,16 +1120,16 @@ void ChartToC::writeStates(std::ostream& stream) { stream << " }," << std::endl; // default completion - std::string descBools; - std::string descBoolsIdx; + std::string descBools; + std::string descBoolsIdx; NodeSet completion; if (isHistory(state)) { - // we already precalculated everything - descBools = ATTR(state, "respBools"); - descBoolsIdx = ATTR(state, "respBoolsIdx"); - hasHistoryChild = HAS_ATTR(state, "hasNestedHistory"); - goto WRITE_COMPLETION; + // we already precalculated everything + descBools = ATTR(state, "respBools"); + descBoolsIdx = ATTR(state, "respBoolsIdx"); + hasHistoryChild = HAS_ATTR(state, "hasNestedHistory"); + goto WRITE_COMPLETION; } if (isParallel(state)) { completion = getChildStates(state); @@ -1161,8 +1163,8 @@ void ChartToC::writeStates(std::ostream& stream) { descBools += "0"; } } - WRITE_COMPLETION: - +WRITE_COMPLETION: + stream << " /* completion */ { "; writeCharArrayInitList(stream, descBools); stream << " /* " << descBools << "," << descBoolsIdx << " */"; @@ -1209,10 +1211,10 @@ void ChartToC::writeStates(std::ostream& stream) { } else { // stream << "SCXML_STATE_COMPOUND"; } - if (hasHistoryChild) { - stream << " | SCXML_STATE_HAS_HISTORY"; - } - + if (hasHistoryChild) { + stream << " | SCXML_STATE_HAS_HISTORY"; + } + stream << "," << std::endl; stream << " }" << (i + 1 < _states.size() ? ",": "") << std::endl; @@ -1229,7 +1231,7 @@ void ChartToC::writeTransitions(std::ostream& stream) { elements.insert(_nsInfo.xmlNSPrefix + "transition"); NodeSet transDocOrder = inDocumentOrder(elements, _scxml); - std::stringstream transDocOrderSS; + std::stringstream transDocOrderSS; std::string seperator = ""; for (size_t i = 0; i < transDocOrder.size(); i++) { Element transition(_transitions[i]); @@ -1239,18 +1241,18 @@ void ChartToC::writeTransitions(std::ostream& stream) { } #if 0 - stream << "static const " << _transDataType << " scxml_transitions_doc_order[" << toStr(_transitions.size()) << "] = {" << std::endl; - stream << " " << transDocOrderSS; - stream << std::endl << "};" << std::endl; - stream << std::endl; + stream << "static const " << _transDataType << " scxml_transitions_doc_order[" << toStr(_transitions.size()) << "] = {" << std::endl; + stream << " " << transDocOrderSS; + stream << std::endl << "};" << std::endl; + stream << std::endl; #endif stream << "static const scxml_transition scxml_transitions[" << toStr(_transitions.size()) << "] = {" << std::endl; for (size_t i = 0; i < _transitions.size(); i++) { Element transition(_transitions[i]); - stream << " { /* transition number " << ATTR(transition, "documentOrder") << " with priority " << toStr(i) << std::endl; - stream << " target: " << ATTR(transition, "target") << std::endl; - stream << " */" << std::endl; + stream << " { /* transition number " << ATTR(transition, "documentOrder") << " with priority " << toStr(i) << std::endl; + stream << " target: " << ATTR(transition, "target") << std::endl; + stream << " */" << std::endl; /** uint16_t source; @@ -1264,7 +1266,7 @@ void ChartToC::writeTransitions(std::ostream& stream) { */ // source - stream << " /* name */ "; + stream << " /* source */ "; stream << ATTR_CAST(transition.getParentNode(), "documentOrder"); stream << "," << std::endl; @@ -1461,7 +1463,7 @@ void ChartToC::writeFSM(std::ostream& stream) { stream << std::endl; stream << "// MACRO_STEP:" << std::endl; - stream << " ctx->flags &= ~SCXML_CTX_TRANSITION_FOUND;" << std::endl; +// stream << " ctx->flags &= ~SCXML_CTX_TRANSITION_FOUND;" << std::endl; stream << std::endl; stream << " if (ctx->flags & SCXML_CTX_TOP_LEVEL_FINAL) " << std::endl; @@ -1474,6 +1476,7 @@ void ChartToC::writeFSM(std::ostream& stream) { stream << " char exit_set[" << _stateCharArraySize << "] = " << _stateCharArrayInit << ";" << std::endl; stream << " char trans_set[" << _transCharArraySize << "] = " << _transCharArrayInit << ";" << std::endl; stream << " char entry_set[" << _stateCharArraySize << "] = " << _stateCharArrayInit << ";" << std::endl; + stream << " char tmp_states[" << _stateCharArraySize << "] = " << _stateCharArrayInit << ";" << std::endl; stream << std::endl; stream << " if unlikely(ctx->flags == SCXML_CTX_PRISTINE) {" << std::endl; @@ -1503,9 +1506,9 @@ void ChartToC::writeFSM(std::ostream& stream) { stream << " continue;" << std::endl; stream << std::endl; stream << " // is the transition active?" << std::endl; - stream << " if (IS_SET(scxml_transitions[i].source, ctx->config)) {" << std::endl; + stream << " if (BIT_HAS(scxml_transitions[i].source, ctx->config)) {" << std::endl; stream << " // is it non-conflicting?" << std::endl; - stream << " if (!IS_SET(i, conflicts)) {" << std::endl; + stream << " if (!BIT_HAS(i, conflicts)) {" << std::endl; stream << " // is it enabled?" << std::endl; stream << " if (ctx->is_enabled(ctx, &scxml_transitions[i], ctx->event) > 0) {" << std::endl; stream << " // remember that we found a transition" << std::endl; @@ -1521,7 +1524,7 @@ void ChartToC::writeFSM(std::ostream& stream) { stream << " // states that will be left" << std::endl; stream << " bit_or(exit_set, scxml_transitions[i].exit_set, " << _stateCharArraySize << ");" << std::endl; stream << std::endl; - stream << " SET_BIT(i, trans_set);" << std::endl; + stream << " BIT_SET_AT(i, trans_set);" << std::endl; stream << " }" << std::endl; stream << " }" << std::endl; stream << " }" << std::endl; @@ -1531,6 +1534,7 @@ void ChartToC::writeFSM(std::ostream& stream) { stream << " if (ctx->flags & SCXML_CTX_TRANSITION_FOUND) {" << std::endl; stream << " ctx->flags |= SCXML_CTX_SPONTANEOUS;" << std::endl; + stream << " ctx->flags &= ~SCXML_CTX_TRANSITION_FOUND;" << std::endl; stream << " } else {" << std::endl; stream << " ctx->flags &= ~SCXML_CTX_SPONTANEOUS;" << std::endl; // stream << " return SCXML_ERR_OK;" << std::endl; @@ -1558,20 +1562,19 @@ void ChartToC::writeFSM(std::ostream& stream) { stream << "// REMEMBER_HISTORY:" << std::endl; stream << " for (size_t i = 0; i < SCXML_NUMBER_STATES; i++) {" << std::endl; stream << " if unlikely(SCXML_STATE_MASK(scxml_states[i].type) == SCXML_STATE_HISTORY_SHALLOW ||" << std::endl; - stream << " SCXML_STATE_MASK(scxml_states[i].type) == SCXML_STATE_HISTORY_DEEP) {" << std::endl; + stream << " SCXML_STATE_MASK(scxml_states[i].type) == SCXML_STATE_HISTORY_DEEP) {" << std::endl; stream << " // a history state whose parent is about to be exited" << std::endl; - stream << " if unlikely(IS_SET(scxml_states[i].parent, exit_set)) {" << std::endl; - stream << " char history[" << _stateCharArraySize << "] = " << _stateCharArrayInit << ";" << std::endl; - stream << " bit_copy(history, scxml_states[i].completion, " << _stateCharArraySize << ");" << std::endl; + stream << " if unlikely(BIT_HAS(scxml_states[i].parent, exit_set)) {" << std::endl; + stream << " bit_copy(tmp_states, scxml_states[i].completion, " << _stateCharArraySize << ");" << std::endl; stream << std::endl; stream << " // set those states who were enabled" << std::endl; - stream << " bit_and(history, ctx->config, " << _stateCharArraySize << ");" << std::endl; + stream << " bit_and(tmp_states, ctx->config, " << _stateCharArraySize << ");" << std::endl; stream << std::endl; - stream << " // clear current history with completion mask - TODO: errornously clears nested history" << std::endl; + stream << " // clear current history with completion mask" << std::endl; stream << " bit_and_not(ctx->history, scxml_states[i].completion, " << _stateCharArraySize << ");" << std::endl; stream << std::endl; stream << " // set history" << std::endl; - stream << " bit_or(ctx->history, history, " << _stateCharArraySize << ");" << std::endl; + stream << " bit_or(ctx->history, tmp_states, " << _stateCharArraySize << ");" << std::endl; stream << " }" << std::endl; stream << " }" << std::endl; stream << " }" << std::endl; @@ -1583,7 +1586,7 @@ void ChartToC::writeFSM(std::ostream& stream) { stream << std::endl; stream << " // iterate for ancestors" << std::endl; stream << " for (size_t i = 0; i < SCXML_NUMBER_STATES; i++) {" << std::endl; - stream << " if (IS_SET(i, entry_set)) {" << std::endl; + stream << " if (BIT_HAS(i, entry_set)) {" << std::endl; stream << " bit_or(entry_set, scxml_states[i].ancestors, " << _stateCharArraySize << ");" << std::endl; stream << " }" << std::endl; stream << " }" << std::endl; @@ -1591,7 +1594,7 @@ void ChartToC::writeFSM(std::ostream& stream) { stream << " // iterate for descendants" << std::endl; stream << " for (size_t i = 0; i < SCXML_NUMBER_STATES; i++) {" << std::endl; - stream << " if (IS_SET(i, entry_set)) {" << std::endl; + stream << " if (BIT_HAS(i, entry_set)) {" << std::endl; stream << " switch (SCXML_STATE_MASK(scxml_states[i].type)) {" << std::endl; stream << " case SCXML_STATE_PARALLEL: {" << std::endl; stream << " bit_or(entry_set, scxml_states[i].completion, " << _stateCharArraySize << ");" << std::endl; @@ -1599,35 +1602,43 @@ void ChartToC::writeFSM(std::ostream& stream) { stream << " }" << std::endl; stream << " case SCXML_STATE_HISTORY_SHALLOW:" << std::endl; stream << " case SCXML_STATE_HISTORY_DEEP: {" << std::endl; - stream << " char history_targets[" << _stateCharArraySize << "] = " << _stateCharArrayInit << ";" << std::endl; stream << " if (!bit_has_and(scxml_states[i].completion, ctx->history, " << _stateCharArraySize << ") &&" << std::endl; - stream << " !IS_SET(scxml_states[i].parent, ctx->config)) {" << std::endl; - stream << " // nothing set for history, look for a default transition or enter parents completion" << std::endl; + stream << " !BIT_HAS(scxml_states[i].parent, ctx->config)) {" << std::endl; + stream << " // nothing set for history, look for a default transition" << std::endl; stream << " for (size_t j = 0; j < SCXML_NUMBER_TRANSITIONS; j++) {" << std::endl; stream << " if unlikely(scxml_transitions[j].source == i) {" << std::endl; stream << " bit_or(entry_set, scxml_transitions[j].target, " << _stateCharArraySize << ");" << std::endl; - stream << " SET_BIT(j, trans_set);" << std::endl; + stream << " if(SCXML_STATE_MASK(scxml_states[i].type) == SCXML_STATE_HISTORY_DEEP &&" << std::endl; + stream << " !bit_has_and(scxml_transitions[j].target, scxml_states[i].children, " << _stateCharArraySize << ")) {" << std::endl; + stream << " for (size_t k = i + 1; k < SCXML_NUMBER_STATES; k++) {" << std::endl; + stream << " if (BIT_HAS(k, scxml_transitions[j].target)) {" << std::endl; + stream << " bit_or(entry_set, scxml_states[k].ancestors, " << _stateCharArraySize << ");" << std::endl; + stream << " break;" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " BIT_SET_AT(j, trans_set);" << std::endl; stream << " break;" << std::endl; stream << " }" << std::endl; - stream << " // Note: SCXML mandates every history to have a transition!" << std::endl; + stream << " // Note: SCXML mandates every history to have a transition!" << std::endl; stream << " }" << std::endl; stream << " } else {" << std::endl; - stream << " bit_copy(history_targets, scxml_states[i].completion, " << _stateCharArraySize << ");" << std::endl; - stream << " bit_and(history_targets, ctx->history, " << _stateCharArraySize << ");" << std::endl; - stream << " bit_or(entry_set, history_targets, " << _stateCharArraySize << ");" << std::endl; - stream << " if (scxml_states[i].type == (SCXML_STATE_HAS_HISTORY | SCXML_STATE_HISTORY_DEEP)) {" << std::endl; + stream << " bit_copy(tmp_states, scxml_states[i].completion, " << _stateCharArraySize << ");" << std::endl; + stream << " bit_and(tmp_states, ctx->history, " << _stateCharArraySize << ");" << std::endl; + stream << " bit_or(entry_set, tmp_states, " << _stateCharArraySize << ");" << std::endl; + stream << " if (scxml_states[i].type == (SCXML_STATE_HAS_HISTORY | SCXML_STATE_HISTORY_DEEP)) {" << std::endl; stream << " // a deep history state with nested histories -> more completion" << std::endl; stream << " for (size_t j = i + 1; j < SCXML_NUMBER_STATES; j++) {" << std::endl; - stream << " if (IS_SET(j, scxml_states[i].completion) &&" << std::endl; - stream << " IS_SET(j, entry_set) &&" << std::endl; + stream << " if (BIT_HAS(j, scxml_states[i].completion) &&" << std::endl; + stream << " BIT_HAS(j, entry_set) &&" << std::endl; stream << " (scxml_states[j].type & SCXML_STATE_HAS_HISTORY)) {" << std::endl; stream << " for (size_t k = j + 1; k < SCXML_NUMBER_STATES; k++) {" << std::endl; stream << " // add nested history to entry_set" << std::endl; stream << " if ((SCXML_STATE_MASK(scxml_states[k].type) == SCXML_STATE_HISTORY_DEEP ||" << std::endl; stream << " SCXML_STATE_MASK(scxml_states[k].type) == SCXML_STATE_HISTORY_SHALLOW) &&" << std::endl; - stream << " IS_SET(k, scxml_states[j].children)) {" << std::endl; + stream << " BIT_HAS(k, scxml_states[j].children)) {" << std::endl; stream << " // a nested history state" << std::endl; - stream << " SET_BIT(k, entry_set);" << std::endl; + stream << " BIT_SET_AT(k, entry_set);" << std::endl; stream << " }" << std::endl; stream << " }" << std::endl; stream << " }" << std::endl; @@ -1639,15 +1650,15 @@ void ChartToC::writeFSM(std::ostream& stream) { stream << " case SCXML_STATE_INITIAL: {" << std::endl; stream << " for (size_t j = 0; j < SCXML_NUMBER_TRANSITIONS; j++) {" << std::endl; stream << " if (scxml_transitions[j].source == i) {" << std::endl; - stream << " SET_BIT(j, trans_set);" << std::endl; - stream << " CLEARBIT(i, entry_set);" << std::endl; + stream << " BIT_SET_AT(j, trans_set);" << std::endl; + stream << " BIT_CLEAR(i, entry_set);" << std::endl; stream << " bit_or(entry_set, scxml_transitions[j].target, " << _stateCharArraySize << ");" << std::endl; stream << " for (size_t k = i + 1; k < SCXML_NUMBER_STATES; k++) {" << std::endl; - stream << " if (IS_SET(k, scxml_transitions[j].target)) {" << std::endl; + stream << " if (BIT_HAS(k, scxml_transitions[j].target)) {" << std::endl; stream << " bit_or(entry_set, scxml_states[k].ancestors, " << _stateCharArraySize << ");" << std::endl; stream << " }" << std::endl; stream << " }" << std::endl; - stream << " }" << std::endl; + stream << " }" << std::endl; stream << " }" << std::endl; stream << " break;" << std::endl; stream << " }" << std::endl; @@ -1660,7 +1671,7 @@ void ChartToC::writeFSM(std::ostream& stream) { stream << " if (!bit_has_and(scxml_states[i].completion, scxml_states[i].children, " << _stateCharArraySize << ")) {" << std::endl; stream << " // deep completion" << std::endl; stream << " for (size_t j = i + 1; j < SCXML_NUMBER_STATES; j++) {" << std::endl; - stream << " if (IS_SET(j, scxml_states[i].completion)) {" << std::endl; + stream << " if (BIT_HAS(j, scxml_states[i].completion)) {" << std::endl; stream << " bit_or(entry_set, scxml_states[j].ancestors, " << _stateCharArraySize << ");" << std::endl; stream << " break; // completion of compound is single state" << std::endl; stream << " }" << std::endl; @@ -1683,20 +1694,20 @@ void ChartToC::writeFSM(std::ostream& stream) { stream << "// EXIT_STATES:" << std::endl; stream << " size_t i = SCXML_NUMBER_STATES;" << std::endl; stream << " while(i-- > 0) {" << std::endl; - stream << " if (IS_SET(i, exit_set) && IS_SET(i, ctx->config)) {" << std::endl; + stream << " if (BIT_HAS(i, exit_set) && BIT_HAS(i, ctx->config)) {" << std::endl; stream << " // call all on exit handlers" << std::endl; stream << " if (scxml_states[i].on_exit != NULL) {" << std::endl; stream << " if unlikely((err = scxml_states[i].on_exit(ctx, &scxml_states[i], ctx->event)) != SCXML_ERR_OK)" << std::endl; stream << " return err;" << std::endl; stream << " }" << std::endl; - stream << " CLEARBIT(i, ctx->config);" << std::endl; + stream << " BIT_CLEAR(i, ctx->config);" << std::endl; stream << " }" << std::endl; stream << " }" << std::endl; stream << std::endl; stream << "// TAKE_TRANSITIONS:" << std::endl; stream << " for (size_t i = 0; i < SCXML_NUMBER_TRANSITIONS; i++) {" << std::endl; - stream << " if (IS_SET(i, trans_set) && (scxml_transitions[i].type & (SCXML_TRANS_HISTORY | SCXML_TRANS_INITIAL)) == 0) {" << std::endl; + stream << " if (BIT_HAS(i, trans_set) && (scxml_transitions[i].type & (SCXML_TRANS_HISTORY | SCXML_TRANS_INITIAL)) == 0) {" << std::endl; stream << " // call executable content in transition" << std::endl; stream << " if (scxml_transitions[i].on_transition != NULL) {" << std::endl; stream << " if unlikely((err = scxml_transitions[i].on_transition(ctx," << std::endl; @@ -1716,7 +1727,7 @@ void ChartToC::writeFSM(std::ostream& stream) { stream << "// ENTER_STATES:" << std::endl; stream << " for (size_t i = 0; i < SCXML_NUMBER_STATES; i++) {" << std::endl; - stream << " if (IS_SET(i, entry_set) && !IS_SET(i, ctx->config)) {" << std::endl; + stream << " if (BIT_HAS(i, entry_set) && !BIT_HAS(i, ctx->config)) {" << std::endl; stream << " // these are no proper states" << std::endl; stream << " if unlikely(SCXML_STATE_MASK(scxml_states[i].type) == SCXML_STATE_HISTORY_DEEP ||" << std::endl; stream << " SCXML_STATE_MASK(scxml_states[i].type) == SCXML_STATE_HISTORY_SHALLOW ||" << std::endl; @@ -1724,15 +1735,15 @@ void ChartToC::writeFSM(std::ostream& stream) { stream << " continue;" << std::endl; stream << std::endl; - stream << " SET_BIT(i, ctx->config);" << std::endl; + stream << " BIT_SET_AT(i, ctx->config);" << std::endl; stream << std::endl; stream << " // initialize data" << std::endl; - stream << " if (!IS_SET(i, ctx->initialized_data)) {" << std::endl; + stream << " if (!BIT_HAS(i, ctx->initialized_data)) {" << std::endl; stream << " if unlikely(scxml_states[i].data != NULL && ctx->exec_content_init != NULL) {" << std::endl; stream << " ctx->exec_content_init(ctx, scxml_states[i].data);" << std::endl; stream << " }" << std::endl; - stream << " SET_BIT(i, ctx->initialized_data);" << std::endl; + stream << " BIT_SET_AT(i, ctx->initialized_data);" << std::endl; stream << " }" << std::endl; stream << std::endl; @@ -1744,7 +1755,7 @@ void ChartToC::writeFSM(std::ostream& stream) { stream << " // take history and initial transitions" << std::endl; stream << " for (size_t j = 0; j < SCXML_NUMBER_TRANSITIONS; j++) {" << std::endl; - stream << " if unlikely(IS_SET(j, trans_set) &&" << std::endl; + stream << " if unlikely(BIT_HAS(j, trans_set) &&" << std::endl; stream << " (scxml_transitions[j].type & (SCXML_TRANS_HISTORY | SCXML_TRANS_INITIAL)) &&" << std::endl; stream << " scxml_states[scxml_transitions[j].source].parent == i) {" << std::endl; stream << " // call executable content in transition" << std::endl; @@ -1782,20 +1793,20 @@ void ChartToC::writeFSM(std::ostream& stream) { stream << " * 4. If a state remains, not all children of a parallel are final" << std::endl; stream << " */" << std::endl; stream << " for (size_t j = 0; j < SCXML_NUMBER_STATES; j++) {" << std::endl; - stream << " if unlikely(SCXML_STATE_MASK(scxml_states[j].type) == SCXML_STATE_PARALLEL) {" << std::endl; - stream << " char parallel_children[" << _stateCharArraySize << "] = " << _stateCharArrayInit << ";" << std::endl; - stream << " size_t parallel = j;" << std::endl; + stream << " if unlikely(SCXML_STATE_MASK(scxml_states[j].type) == SCXML_STATE_PARALLEL &&" << std::endl; + stream << " BIT_HAS(j, scxml_states[i].ancestors)) {" << std::endl; + stream << " bit_and_not(tmp_states, tmp_states, " << _stateCharArraySize << ");" << std::endl; stream << " for (size_t k = 0; k < SCXML_NUMBER_STATES; k++) {" << std::endl; - stream << " if unlikely(IS_SET(parallel, scxml_states[k].ancestors) && IS_SET(k, ctx->config)) {" << std::endl; + stream << " if unlikely(BIT_HAS(j, scxml_states[k].ancestors) && BIT_HAS(k, ctx->config)) {" << std::endl; stream << " if (SCXML_STATE_MASK(scxml_states[k].type) == SCXML_STATE_FINAL) {" << std::endl; - stream << " bit_and_not(parallel_children, scxml_states[k].ancestors, " << _stateCharArraySize << ");" << std::endl; + stream << " bit_and_not(tmp_states, scxml_states[k].ancestors, " << _stateCharArraySize << ");" << std::endl; stream << " } else {" << std::endl; - stream << " SET_BIT(k, parallel_children);" << std::endl; + stream << " BIT_SET_AT(k, tmp_states);" << std::endl; stream << " }" << std::endl; stream << " }" << std::endl; stream << " }" << std::endl; - stream << " if unlikely(!bit_any_set(parallel_children, " << _stateCharArraySize << ")) {" << std::endl; - stream << " ctx->raise_done_event(ctx, &scxml_states[parallel], NULL);" << std::endl; + stream << " if unlikely(!bit_has_any(tmp_states, " << _stateCharArraySize << ")) {" << std::endl; + stream << " ctx->raise_done_event(ctx, &scxml_states[j], NULL);" << std::endl; stream << " }" << std::endl; stream << " }" << std::endl; stream << " }" << std::endl; @@ -1808,21 +1819,6 @@ void ChartToC::writeFSM(std::ostream& stream) { stream << " }" << std::endl; stream << std::endl; -// stream << "// HISTORY_TRANSITIONS:" << std::endl; -// stream << " for (size_t i = 0; i < SCXML_NUMBER_TRANSITIONS; i++) {" << std::endl; -// stream << " if unlikely(IS_SET(i, trans_set) && (scxml_transitions[i].type & SCXML_TRANS_HISTORY)) {" << std::endl; -// stream << " // call executable content in transition" << std::endl; -// stream << " if (scxml_transitions[i].on_transition != NULL) {" << std::endl; -// stream << " if unlikely((err = scxml_transitions[i].on_transition(ctx," << std::endl; -// stream << " &scxml_states[scxml_transitions[i].source]," << std::endl; -// stream << " ctx->event)) != SCXML_ERR_OK)" << std::endl; -// stream << " return err;" << std::endl; -// stream << " }" << std::endl; -// stream << " }" << std::endl; -// stream << " }" << std::endl; -// stream << std::endl; - - stream << " return SCXML_ERR_OK;" << std::endl; stream << "}" << std::endl; stream << std::endl; diff --git a/src/uscxml/transform/ChartToC.h b/src/uscxml/transform/ChartToC.h index 74363dd..954aa63 100644 --- a/src/uscxml/transform/ChartToC.h +++ b/src/uscxml/transform/ChartToC.h @@ -71,8 +71,8 @@ protected: Arabica::XPath::NodeSet computeExitSet(const Arabica::DOM::Element& transition); - void resortStates(Arabica::DOM::Node& node); - void setHistoryResponsibility(Arabica::DOM::Node& node); + void resortStates(Arabica::DOM::Node& node); + void setHistoryResponsibility(Arabica::DOM::Node& node); Interpreter interpreter; diff --git a/test/src/test-c-machine.cpp b/test/src/test-c-machine.cpp index 33c149a..11bb1c7 100644 --- a/test/src/test-c-machine.cpp +++ b/test/src/test-c-machine.cpp @@ -60,7 +60,7 @@ public: } bool isInState(const std::string& stateId) { for (int i = 0 ; i < SCXML_NUMBER_STATES; i++) { - if (scxml_states[i].name != NULL && IS_SET(i, ctx->config) && stateId == scxml_states[i].name) + if (scxml_states[i].name != NULL && BIT_HAS(i, ctx->config) && stateId == scxml_states[i].name) return true; } return false; @@ -217,9 +217,9 @@ void delayedSend(void* ctx, std::string eventName) { tthread::lock_guard lock(USER_DATA(ctx)->mutex); SendRequest* sr = USER_DATA(ctx)->sendIds[eventName]; - Event* e = new Event(*sr); - - if (sr->target == "#_internal") { + Event* e = new Event(*sr); + + if (sr->target == "#_internal") { e->eventType = Event::INTERNAL; #ifdef SCXML_VERBOSE printf("Pushing Internal Event: %s\n", e->name.c_str()); @@ -233,7 +233,7 @@ void delayedSend(void* ctx, std::string eventName) { USER_DATA(ctx)->eq.push_back(e); } USER_DATA(ctx)->monitor.notify_all(); - delete sr; + delete sr; } int exec_content_cancel(const scxml_ctx* ctx, const char* sendid, const char* sendidexpr) { @@ -305,7 +305,7 @@ int exec_content_send(const scxml_ctx* ctx, const scxml_elem_send* send) { } } catch (Event exc) { exec_content_raise(ctx, exc.name.c_str()); - delete e; + delete e; return SCXML_ERR_EXEC_CONTENT; } @@ -371,7 +371,7 @@ int exec_content_send(const scxml_ctx* ctx, const scxml_elem_send* send) { } } - std::string sendid; + std::string sendid; if (send->id != NULL) { sendid = send->id; e->sendid = sendid; @@ -661,7 +661,7 @@ int main(int argc, char** argv) { } } - if(!IS_SET(passIdx, ctx.config)) { + if(!BIT_HAS(passIdx, ctx.config)) { std::cerr << "Interpreter did not end in pass" << std::endl; exit(EXIT_FAILURE); } diff --git a/test/src/test-c-machine.machine.c b/test/src/test-c-machine.machine.c index 09e7703..2b991ff 100644 --- a/test/src/test-c-machine.machine.c +++ b/test/src/test-c-machine.machine.c @@ -1,9 +1,9 @@ #include // explicit types #include // NULL -#define IS_SET(idx, bitset) ((bitset[idx >> 3] & (1 << (idx & 7))) != 0) -#define SET_BIT(idx, bitset) bitset[idx >> 3] |= (1 << (idx & 7)); -#define CLEARBIT(idx, bitset) bitset[idx >> 3] &= (1 << (idx & 7)) ^ 0xFF; +#define BIT_HAS(idx, bitset) ((bitset[idx >> 3] & (1 << (idx & 7))) != 0) +#define BIT_SET_AT(idx, bitset) bitset[idx >> 3] |= (1 << (idx & 7)); +#define BIT_CLEAR(idx, bitset) bitset[idx >> 3] &= (1 << (idx & 7)) ^ 0xFF; #ifdef __GNUC__ #define likely(x) (__builtin_expect(!!(x), 1)) @@ -25,8 +25,8 @@ #define SCXML_ERR_UNSUPPORTED 8 #define SCXML_MACHINE_NAME "" -#define SCXML_NUMBER_STATES 10 -#define SCXML_NUMBER_TRANSITIONS 5 +#define SCXML_NUMBER_STATES 5 +#define SCXML_NUMBER_TRANSITIONS 1 #define SCXML_TRANS_SPONTANEOUS 0x01 #define SCXML_TRANS_TARGETLESS 0x02 @@ -99,22 +99,22 @@ struct scxml_state { const exec_content_t on_entry; // on entry handlers const exec_content_t on_exit; // on exit handlers const invoke_t invoke; // invocations - const char children[2]; // all children - const char completion[2]; // default completion - const char ancestors[2]; // all ancestors + const char children[1]; // all children + const char completion[1]; // default completion + const char ancestors[1]; // all ancestors const scxml_elem_data* data; const uint8_t type; // atomic, parallel, compound, final, history }; struct scxml_transition { const uint8_t source; - const char target[2]; + const char target[1]; const char* event; const char* condition; const exec_content_t on_transition; const uint8_t type; const char conflicts[1]; - const char exit_set[2]; + const char exit_set[1]; }; struct scxml_elem_foreach { @@ -171,10 +171,10 @@ struct scxml_elem_send { struct scxml_ctx { uint8_t flags; - char config[2]; - char history[2]; - char pending_invokes[2]; - char initialized_data[2]; + char config[1]; + char history[1]; + char pending_invokes[1]; + char initialized_data[1]; void* user_data; void* event; @@ -198,12 +198,6 @@ struct scxml_ctx { invoke_t invoke; }; -static const scxml_elem_data scxml_elem_datas[2] = { - /* id, src, expr, content */ - { "Var1", NULL, "0", NULL }, - { NULL, NULL, NULL, NULL } -}; - static const scxml_elem_donedata scxml_elem_donedatas[1] = { /* source, content, contentexpr, params */ { 0, NULL, NULL, NULL } @@ -213,47 +207,17 @@ static int global_script(const scxml_ctx* ctx, const scxml_state* state, const v return SCXML_ERR_OK; } -static int s0_0_0_on_entry_0(const scxml_ctx* ctx, const scxml_state* state, const void* event) { - int err = SCXML_ERR_OK; - if likely(ctx->exec_content_assign != NULL) { - if ((ctx->exec_content_assign(ctx, "Var1", "Var1 + 1")) != SCXML_ERR_OK) return err; - } else { - return SCXML_ERR_MISSING_CALLBACK; - } - return SCXML_ERR_OK; -} - -static int s0_0_0_on_entry(const scxml_ctx* ctx, const scxml_state* state, const void* event) { - s0_0_0_on_entry_0(ctx, state, event); - return SCXML_ERR_OK; -} - -static int 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_assign != NULL) { - if ((ctx->exec_content_assign(ctx, "Var1", "Var1 + 1")) != SCXML_ERR_OK) return err; - } else { - return SCXML_ERR_MISSING_CALLBACK; - } - return SCXML_ERR_OK; -} - -static int s1_on_entry(const scxml_ctx* ctx, const scxml_state* state, const void* event) { - s1_on_entry_0(ctx, state, event); - return SCXML_ERR_OK; -} - -static const scxml_state scxml_states[10] = { +static const scxml_state scxml_states[5] = { { /* state number 0 */ /* name */ NULL, /* parent */ 0, /* onentry */ NULL, /* onexit */ NULL, /* invoke */ NULL, - /* children */ { 0x82, 0x03 /* 0100000111, 1 7 8 9 */ }, - /* completion */ { 0x02, 0x00 /* 0100000000, 1 */ }, - /* ancestors */ { 0x00, 0x00 /* 0000000000, */ }, - /* data */ &scxml_elem_datas[0], + /* children */ { 0x1a /* 01011, 1 3 4 */ }, + /* completion */ { 0x02 /* 01000, 1 */ }, + /* ancestors */ { 0x00 /* 00000, */ }, + /* data */ NULL, /* type */ SCXML_STATE_COMPOUND, }, { /* state number 1 */ @@ -262,170 +226,62 @@ static const scxml_state scxml_states[10] = { /* onentry */ NULL, /* onexit */ NULL, /* invoke */ NULL, - /* children */ { 0x0c, 0x00 /* 0011000000, 2 3 */ }, - /* completion */ { 0x08, 0x00 /* 0001000000, 3 */ }, - /* ancestors */ { 0x01, 0x00 /* 1000000000, 0 */ }, + /* children */ { 0x04 /* 00100, 2 */ }, + /* completion */ { 0x04 /* 00100, 2 */ }, + /* ancestors */ { 0x01 /* 10000, 0 */ }, /* data */ NULL, - /* type */ SCXML_STATE_COMPOUND | SCXML_STATE_HAS_HISTORY, + /* type */ SCXML_STATE_COMPOUND, }, { /* state number 2 */ - /* name */ "h0", - /* parent */ 1, - /* onentry */ NULL, - /* onexit */ NULL, - /* invoke */ NULL, - /* children */ { 0x00, 0x00 /* 0000000000, */ }, - /* completion */ { 0x08, 0x00 /* 0001000000, 3 */ }, - /* ancestors */ { 0x03, 0x00 /* 1100000000, 0 1 */ }, - /* data */ NULL, - /* type */ SCXML_STATE_HISTORY_DEEP | SCXML_STATE_HAS_HISTORY, - }, - { /* state number 3 */ /* name */ "s0.0", /* parent */ 1, /* onentry */ NULL, /* onexit */ NULL, /* invoke */ NULL, - /* children */ { 0x70, 0x00 /* 0000111000, 4 5 6 */ }, - /* completion */ { 0x20, 0x00 /* 0000010000, 5 */ }, - /* ancestors */ { 0x03, 0x00 /* 1100000000, 0 1 */ }, - /* data */ NULL, - /* type */ SCXML_STATE_COMPOUND | SCXML_STATE_HAS_HISTORY, - }, - { /* state number 4 */ - /* name */ "h1", - /* parent */ 3, - /* onentry */ NULL, - /* onexit */ NULL, - /* invoke */ NULL, - /* children */ { 0x00, 0x00 /* 0000000000, */ }, - /* completion */ { 0x60, 0x00 /* 0000011000, 5 6 */ }, - /* ancestors */ { 0x0b, 0x00 /* 1101000000, 0 1 3 */ }, - /* data */ NULL, - /* type */ SCXML_STATE_HISTORY_DEEP, - }, - { /* state number 5 */ - /* name */ "s0.0.0", - /* parent */ 3, - /* onentry */ s0_0_0_on_entry, - /* onexit */ NULL, - /* invoke */ NULL, - /* children */ { 0x00, 0x00 /* 0000000000, */ }, - /* completion */ { 0x00, 0x00 /* 0000000000, */ }, - /* ancestors */ { 0x0b, 0x00 /* 1101000000, 0 1 3 */ }, - /* data */ NULL, - /* type */ SCXML_STATE_ATOMIC, - }, - { /* state number 6 */ - /* name */ "s0.0.1", - /* parent */ 3, - /* onentry */ NULL, - /* onexit */ NULL, - /* invoke */ NULL, - /* children */ { 0x00, 0x00 /* 0000000000, */ }, - /* completion */ { 0x00, 0x00 /* 0000000000, */ }, - /* ancestors */ { 0x0b, 0x00 /* 1101000000, 0 1 3 */ }, - /* data */ NULL, - /* type */ SCXML_STATE_ATOMIC, - }, - { /* state number 7 */ - /* name */ "s1", - /* parent */ 0, - /* onentry */ s1_on_entry, - /* onexit */ NULL, - /* invoke */ NULL, - /* children */ { 0x00, 0x00 /* 0000000000, */ }, - /* completion */ { 0x00, 0x00 /* 0000000000, */ }, - /* ancestors */ { 0x01, 0x00 /* 1000000000, 0 */ }, + /* children */ { 0x00 /* 00000, */ }, + /* completion */ { 0x00 /* 00000, */ }, + /* ancestors */ { 0x03 /* 11000, 0 1 */ }, /* data */ NULL, /* type */ SCXML_STATE_ATOMIC, }, - { /* state number 8 */ + { /* state number 3 */ /* name */ "pass", /* parent */ 0, /* onentry */ NULL, /* onexit */ NULL, /* invoke */ NULL, - /* children */ { 0x00, 0x00 /* 0000000000, */ }, - /* completion */ { 0x00, 0x00 /* 0000000000, */ }, - /* ancestors */ { 0x01, 0x00 /* 1000000000, 0 */ }, + /* children */ { 0x00 /* 00000, */ }, + /* completion */ { 0x00 /* 00000, */ }, + /* ancestors */ { 0x01 /* 10000, 0 */ }, /* data */ NULL, /* type */ SCXML_STATE_FINAL, }, - { /* state number 9 */ + { /* state number 4 */ /* name */ "fail", /* parent */ 0, /* onentry */ NULL, /* onexit */ NULL, /* invoke */ NULL, - /* children */ { 0x00, 0x00 /* 0000000000, */ }, - /* completion */ { 0x00, 0x00 /* 0000000000, */ }, - /* ancestors */ { 0x01, 0x00 /* 1000000000, 0 */ }, + /* children */ { 0x00 /* 00000, */ }, + /* completion */ { 0x00 /* 00000, */ }, + /* ancestors */ { 0x01 /* 10000, 0 */ }, /* data */ NULL, /* type */ SCXML_STATE_FINAL, } }; -static const scxml_transition scxml_transitions[5] = { +static const scxml_transition scxml_transitions[1] = { { /* transition number 0 with priority 0 - target: s0.0.1 - */ - /* name */ 5, - /* target */ { 0x40, 0x00 /* 0000001000, 6 */ }, - /* event */ NULL, - /* condition */ "Var1 == 1", - /* ontrans */ NULL, - /* type */ SCXML_TRANS_SPONTANEOUS, - /* conflicts */ { 0x0f /* 11110, 0 1 2 3 */ }, - /* exit set */ { 0x70, 0x00 /* 0000111000, 4 5 6 */ } - }, - { /* transition number 1 with priority 1 - target: s1 - */ - /* name */ 6, - /* target */ { 0x80, 0x00 /* 0000000100, 7 */ }, - /* event */ NULL, - /* condition */ "Var1 == 1", - /* ontrans */ NULL, - /* type */ SCXML_TRANS_SPONTANEOUS, - /* conflicts */ { 0x0f /* 11110, 0 1 2 3 */ }, - /* exit set */ { 0xfe, 0x03 /* 0111111111, 1 2 3 4 5 6 7 8 9 */ } - }, - { /* transition number 2 with priority 2 - target: pass - */ - /* name */ 1, - /* target */ { 0x00, 0x01 /* 0000000010, 8 */ }, - /* event */ NULL, - /* condition */ "Var1 == 2", - /* ontrans */ NULL, - /* type */ SCXML_TRANS_SPONTANEOUS, - /* conflicts */ { 0x0f /* 11110, 0 1 2 3 */ }, - /* exit set */ { 0xfe, 0x03 /* 0111111111, 1 2 3 4 5 6 7 8 9 */ } - }, - { /* transition number 3 with priority 3 - target: fail + target: */ - /* name */ 1, - /* target */ { 0x00, 0x02 /* 0000000001, 9 */ }, + /* source */ 2, + /* target */ { NULL }, /* event */ NULL, /* condition */ NULL, /* ontrans */ NULL, - /* type */ SCXML_TRANS_SPONTANEOUS, - /* conflicts */ { 0x0f /* 11110, 0 1 2 3 */ }, - /* exit set */ { 0xfe, 0x03 /* 0111111111, 1 2 3 4 5 6 7 8 9 */ } - }, - { /* transition number 4 with priority 4 - target: h0 - */ - /* name */ 7, - /* target */ { 0x04, 0x00 /* 0010000000, 2 */ }, - /* event */ NULL, - /* condition */ "Var1 == 2", - /* ontrans */ NULL, - /* type */ SCXML_TRANS_SPONTANEOUS, - /* conflicts */ { 0x10 /* 00001, 4 */ }, - /* exit set */ { 0x00, 0x00 /* 0000000000, */ } + /* type */ SCXML_TRANS_TARGETLESS | SCXML_TRANS_SPONTANEOUS, + /* conflicts */ { 0x01 /* 1, 0 */ }, + /* exit set */ { 0x00 /* 00000, */ } } }; @@ -433,7 +289,7 @@ static const scxml_transition scxml_transitions[5] = { static void printStateNames(const char* a) { const char* seperator = ""; for (size_t i = 0; i < SCXML_NUMBER_STATES; i++) { - if (IS_SET(i, a)) { + if (BIT_HAS(i, a)) { printf("%s%s", seperator, (scxml_states[i].name != NULL ? scxml_states[i].name : "UNK")); seperator = ", "; } @@ -444,7 +300,7 @@ static void printStateNames(const char* a) { static void printBitsetIndices(const char* a, size_t length) { const char* seperator = ""; for (size_t i = 0; i < length; i++) { - if (IS_SET(i, a)) { + if (BIT_HAS(i, a)) { printf("%s%lu", seperator, i); seperator = ", "; } @@ -453,44 +309,44 @@ static void printBitsetIndices(const char* a, size_t length) { } #endif -static void bit_or(char* dest, const char* mask, size_t i) { +static int bit_has_and(const char* a, const char* b, size_t i) { do { - dest[i - 1] |= mask[i - 1]; + if (a[i - 1] & b[i - 1]) + return true; } while(--i); + return false; } -static void bit_copy(char* dest, const char* source, size_t i) { +static int bit_has_any(const char* a, size_t i) { do { - dest[i - 1] = source[i - 1]; + if (a[i - 1] > 0) + return true; } while(--i); + return false; } -static int bit_has_and(const char* a, const char* b, size_t i) { +static void bit_or(char* dest, const char* mask, size_t i) { do { - if (a[i - 1] & b[i - 1]) - return true; + dest[i - 1] |= mask[i - 1]; } while(--i); - return false; } -static void bit_and_not(char* dest, const char* mask, size_t i) { +static void bit_copy(char* dest, const char* source, size_t i) { do { - dest[i - 1] &= ~mask[i - 1]; + dest[i - 1] = source[i - 1]; } while(--i); } -static void bit_and(char* dest, const char* mask, size_t i) { +static void bit_and_not(char* dest, const char* mask, size_t i) { do { - dest[i - 1] &= mask[i - 1]; + dest[i - 1] &= ~mask[i - 1]; } while(--i); } -static int bit_any_set(const char* a, size_t i) { +static void bit_and(char* dest, const char* mask, size_t i) { do { - if (a[i - 1] > 0) - return true; + dest[i - 1] &= mask[i - 1]; } while(--i); - return false; } int scxml_step(scxml_ctx* ctx) { @@ -501,21 +357,21 @@ int scxml_step(scxml_ctx* ctx) { #endif // MACRO_STEP: - ctx->flags &= ~SCXML_CTX_TRANSITION_FOUND; if (ctx->flags & SCXML_CTX_TOP_LEVEL_FINAL) return SCXML_ERR_DONE; int err = SCXML_ERR_OK; char conflicts[1] = {0}; - char target_set[2] = {0, 0}; - char exit_set[2] = {0, 0}; + char target_set[1] = {0}; + char exit_set[1] = {0}; char trans_set[1] = {0}; - char entry_set[2] = {0, 0}; + char entry_set[1] = {0}; + char tmp_states[1] = {0}; if unlikely(ctx->flags == SCXML_CTX_PRISTINE) { global_script(ctx, &scxml_states[0], NULL); - bit_or(target_set, scxml_states[0].completion, 2); + bit_or(target_set, scxml_states[0].completion, 1); ctx->flags |= SCXML_CTX_SPONTANEOUS | SCXML_CTX_INITIALIZED; goto ESTABLISH_ENTRY_SET; } @@ -538,9 +394,9 @@ SELECT_TRANSITIONS: continue; // is the transition active? - if (IS_SET(scxml_transitions[i].source, ctx->config)) { + if (BIT_HAS(scxml_transitions[i].source, ctx->config)) { // is it non-conflicting? - if (!IS_SET(i, conflicts)) { + if (!BIT_HAS(i, conflicts)) { // is it enabled? if (ctx->is_enabled(ctx, &scxml_transitions[i], ctx->event) > 0) { // remember that we found a transition @@ -550,20 +406,21 @@ SELECT_TRANSITIONS: bit_or(conflicts, scxml_transitions[i].conflicts, 1); // states that are directly targeted (resolve as entry-set later) - bit_or(target_set, scxml_transitions[i].target, 2); + bit_or(target_set, scxml_transitions[i].target, 1); // states that will be left - bit_or(exit_set, scxml_transitions[i].exit_set, 2); + bit_or(exit_set, scxml_transitions[i].exit_set, 1); - SET_BIT(i, trans_set); + BIT_SET_AT(i, trans_set); } } } } - bit_and(exit_set, ctx->config, 2); + bit_and(exit_set, ctx->config, 1); if (ctx->flags & SCXML_CTX_TRANSITION_FOUND) { ctx->flags |= SCXML_CTX_SPONTANEOUS; + ctx->flags &= ~SCXML_CTX_TRANSITION_FOUND; } else { ctx->flags &= ~SCXML_CTX_SPONTANEOUS; } @@ -588,72 +445,79 @@ SELECT_TRANSITIONS: if unlikely(SCXML_STATE_MASK(scxml_states[i].type) == SCXML_STATE_HISTORY_SHALLOW || SCXML_STATE_MASK(scxml_states[i].type) == SCXML_STATE_HISTORY_DEEP) { // a history state whose parent is about to be exited - if unlikely(IS_SET(scxml_states[i].parent, exit_set)) { - char history[2] = {0, 0}; - bit_copy(history, scxml_states[i].completion, 2); + if unlikely(BIT_HAS(scxml_states[i].parent, exit_set)) { + bit_copy(tmp_states, scxml_states[i].completion, 1); // set those states who were enabled - bit_and(history, ctx->config, 2); + bit_and(tmp_states, ctx->config, 1); - // clear current history with completion mask - TODO: errornously clears nested history - bit_and_not(ctx->history, scxml_states[i].completion, 2); + // clear current history with completion mask + bit_and_not(ctx->history, scxml_states[i].completion, 1); // set history - bit_or(ctx->history, history, 2); + bit_or(ctx->history, tmp_states, 1); } } } ESTABLISH_ENTRY_SET: // calculate new entry set - bit_copy(entry_set, target_set, 2); + bit_copy(entry_set, target_set, 1); // iterate for ancestors for (size_t i = 0; i < SCXML_NUMBER_STATES; i++) { - if (IS_SET(i, entry_set)) { - bit_or(entry_set, scxml_states[i].ancestors, 2); + if (BIT_HAS(i, entry_set)) { + bit_or(entry_set, scxml_states[i].ancestors, 1); } } // iterate for descendants for (size_t i = 0; i < SCXML_NUMBER_STATES; i++) { - if (IS_SET(i, entry_set)) { + if (BIT_HAS(i, entry_set)) { switch (SCXML_STATE_MASK(scxml_states[i].type)) { case SCXML_STATE_PARALLEL: { - bit_or(entry_set, scxml_states[i].completion, 2); + bit_or(entry_set, scxml_states[i].completion, 1); break; } case SCXML_STATE_HISTORY_SHALLOW: case SCXML_STATE_HISTORY_DEEP: { - char history_targets[2] = {0, 0}; - if (!bit_has_and(scxml_states[i].completion, ctx->history, 2) && - !IS_SET(scxml_states[i].parent, ctx->config)) { - // nothing set for history, look for a default transition or enter parents completion + if (!bit_has_and(scxml_states[i].completion, ctx->history, 1) && + !BIT_HAS(scxml_states[i].parent, ctx->config)) { + // nothing set for history, look for a default transition for (size_t j = 0; j < SCXML_NUMBER_TRANSITIONS; j++) { if unlikely(scxml_transitions[j].source == i) { - bit_or(entry_set, scxml_transitions[j].target, 2); - SET_BIT(j, trans_set); + bit_or(entry_set, scxml_transitions[j].target, 1); + if(SCXML_STATE_MASK(scxml_states[i].type) == SCXML_STATE_HISTORY_DEEP && + !bit_has_and(scxml_transitions[j].target, scxml_states[i].children, 1)) { + for (size_t k = i + 1; k < SCXML_NUMBER_STATES; k++) { + if (BIT_HAS(k, scxml_transitions[j].target)) { + bit_or(entry_set, scxml_states[k].ancestors, 1); + break; + } + } + } + BIT_SET_AT(j, trans_set); break; } // Note: SCXML mandates every history to have a transition! } } else { - bit_copy(history_targets, scxml_states[i].completion, 2); - bit_and(history_targets, ctx->history, 2); - bit_or(entry_set, history_targets, 2); + bit_copy(tmp_states, scxml_states[i].completion, 1); + bit_and(tmp_states, ctx->history, 1); + bit_or(entry_set, tmp_states, 1); if (scxml_states[i].type == (SCXML_STATE_HAS_HISTORY | SCXML_STATE_HISTORY_DEEP)) { // a deep history state with nested histories -> more completion for (size_t j = i + 1; j < SCXML_NUMBER_STATES; j++) { - if (IS_SET(j, scxml_states[i].completion) && - IS_SET(j, entry_set) && + if (BIT_HAS(j, scxml_states[i].completion) && + BIT_HAS(j, entry_set) && (scxml_states[j].type & SCXML_STATE_HAS_HISTORY)) { for (size_t k = j + 1; k < SCXML_NUMBER_STATES; k++) { // add nested history to entry_set if ((SCXML_STATE_MASK(scxml_states[k].type) == SCXML_STATE_HISTORY_DEEP || SCXML_STATE_MASK(scxml_states[k].type) == SCXML_STATE_HISTORY_SHALLOW) && - IS_SET(k, scxml_states[j].children)) { + BIT_HAS(k, scxml_states[j].children)) { // a nested history state - SET_BIT(k, entry_set); + BIT_SET_AT(k, entry_set); } } } @@ -665,12 +529,12 @@ ESTABLISH_ENTRY_SET: case SCXML_STATE_INITIAL: { for (size_t j = 0; j < SCXML_NUMBER_TRANSITIONS; j++) { if (scxml_transitions[j].source == i) { - SET_BIT(j, trans_set); - CLEARBIT(i, entry_set); - bit_or(entry_set, scxml_transitions[j].target, 2); + BIT_SET_AT(j, trans_set); + BIT_CLEAR(i, entry_set); + bit_or(entry_set, scxml_transitions[j].target, 1); for (size_t k = i + 1; k < SCXML_NUMBER_STATES; k++) { - if (IS_SET(k, scxml_transitions[j].target)) { - bit_or(entry_set, scxml_states[k].ancestors, 2); + if (BIT_HAS(k, scxml_transitions[j].target)) { + bit_or(entry_set, scxml_states[k].ancestors, 1); } } } @@ -678,16 +542,16 @@ ESTABLISH_ENTRY_SET: break; } case SCXML_STATE_COMPOUND: { // we need to check whether one child is already in entry_set - if (!bit_has_and(entry_set, scxml_states[i].children, 2) && - (!bit_has_and(ctx->config, scxml_states[i].children, 2) || - bit_has_and(exit_set, scxml_states[i].children, 2))) + if (!bit_has_and(entry_set, scxml_states[i].children, 1) && + (!bit_has_and(ctx->config, scxml_states[i].children, 1) || + bit_has_and(exit_set, scxml_states[i].children, 1))) { - bit_or(entry_set, scxml_states[i].completion, 2); - if (!bit_has_and(scxml_states[i].completion, scxml_states[i].children, 2)) { + bit_or(entry_set, scxml_states[i].completion, 1); + if (!bit_has_and(scxml_states[i].completion, scxml_states[i].children, 1)) { // deep completion for (size_t j = i + 1; j < SCXML_NUMBER_STATES; j++) { - if (IS_SET(j, scxml_states[i].completion)) { - bit_or(entry_set, scxml_states[j].ancestors, 2); + if (BIT_HAS(j, scxml_states[i].completion)) { + bit_or(entry_set, scxml_states[j].ancestors, 1); break; // completion of compound is single state } } @@ -707,19 +571,19 @@ ESTABLISH_ENTRY_SET: // EXIT_STATES: size_t i = SCXML_NUMBER_STATES; while(i-- > 0) { - if (IS_SET(i, exit_set) && IS_SET(i, ctx->config)) { + if (BIT_HAS(i, exit_set) && BIT_HAS(i, ctx->config)) { // call all on exit handlers if (scxml_states[i].on_exit != NULL) { if unlikely((err = scxml_states[i].on_exit(ctx, &scxml_states[i], ctx->event)) != SCXML_ERR_OK) return err; } - CLEARBIT(i, ctx->config); + BIT_CLEAR(i, ctx->config); } } // TAKE_TRANSITIONS: for (size_t i = 0; i < SCXML_NUMBER_TRANSITIONS; i++) { - if (IS_SET(i, trans_set) && (scxml_transitions[i].type & (SCXML_TRANS_HISTORY | SCXML_TRANS_INITIAL)) == 0) { + if (BIT_HAS(i, trans_set) && (scxml_transitions[i].type & (SCXML_TRANS_HISTORY | SCXML_TRANS_INITIAL)) == 0) { // call executable content in transition if (scxml_transitions[i].on_transition != NULL) { if unlikely((err = scxml_transitions[i].on_transition(ctx, @@ -737,21 +601,21 @@ ESTABLISH_ENTRY_SET: // ENTER_STATES: for (size_t i = 0; i < SCXML_NUMBER_STATES; i++) { - if (IS_SET(i, entry_set) && !IS_SET(i, ctx->config)) { + if (BIT_HAS(i, entry_set) && !BIT_HAS(i, ctx->config)) { // these are no proper states if unlikely(SCXML_STATE_MASK(scxml_states[i].type) == SCXML_STATE_HISTORY_DEEP || SCXML_STATE_MASK(scxml_states[i].type) == SCXML_STATE_HISTORY_SHALLOW || SCXML_STATE_MASK(scxml_states[i].type) == SCXML_STATE_INITIAL) continue; - SET_BIT(i, ctx->config); + BIT_SET_AT(i, ctx->config); // initialize data - if (!IS_SET(i, ctx->initialized_data)) { + if (!BIT_HAS(i, ctx->initialized_data)) { if unlikely(scxml_states[i].data != NULL && ctx->exec_content_init != NULL) { ctx->exec_content_init(ctx, scxml_states[i].data); } - SET_BIT(i, ctx->initialized_data); + BIT_SET_AT(i, ctx->initialized_data); } if (scxml_states[i].on_entry != NULL) { @@ -761,7 +625,7 @@ ESTABLISH_ENTRY_SET: // take history and initial transitions for (size_t j = 0; j < SCXML_NUMBER_TRANSITIONS; j++) { - if unlikely(IS_SET(j, trans_set) && + if unlikely(BIT_HAS(j, trans_set) && (scxml_transitions[j].type & (SCXML_TRANS_HISTORY | SCXML_TRANS_INITIAL)) && scxml_states[scxml_transitions[j].source].parent == i) { // call executable content in transition @@ -797,20 +661,20 @@ ESTABLISH_ENTRY_SET: * 4. If a state remains, not all children of a parallel are final */ for (size_t j = 0; j < SCXML_NUMBER_STATES; j++) { - if unlikely(SCXML_STATE_MASK(scxml_states[j].type) == SCXML_STATE_PARALLEL) { - char parallel_children[2] = {0, 0}; - size_t parallel = j; + if unlikely(SCXML_STATE_MASK(scxml_states[j].type) == SCXML_STATE_PARALLEL && + BIT_HAS(j, scxml_states[i].ancestors)) { + bit_and_not(tmp_states, tmp_states, 1); for (size_t k = 0; k < SCXML_NUMBER_STATES; k++) { - if unlikely(IS_SET(parallel, scxml_states[k].ancestors) && IS_SET(k, ctx->config)) { + if unlikely(BIT_HAS(j, scxml_states[k].ancestors) && BIT_HAS(k, ctx->config)) { if (SCXML_STATE_MASK(scxml_states[k].type) == SCXML_STATE_FINAL) { - bit_and_not(parallel_children, scxml_states[k].ancestors, 2); + bit_and_not(tmp_states, scxml_states[k].ancestors, 1); } else { - SET_BIT(k, parallel_children); + BIT_SET_AT(k, tmp_states); } } } - if unlikely(!bit_any_set(parallel_children, 2)) { - ctx->raise_done_event(ctx, &scxml_states[parallel], NULL); + if unlikely(!bit_has_any(tmp_states, 1)) { + ctx->raise_done_event(ctx, &scxml_states[j], NULL); } } } diff --git a/test/uscxml/automated/ecma/uncompleted-history.scxml b/test/uscxml/automated/ecma/uncompleted-history.scxml deleted file mode 100644 index f6c3c04..0000000 --- a/test/uscxml/automated/ecma/uncompleted-history.scxml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file -- cgit v0.12