diff options
author | Stefan Radomski <sradomski@mintwerk.de> | 2016-01-10 02:40:12 (GMT) |
---|---|---|
committer | Stefan Radomski <sradomski@mintwerk.de> | 2016-01-10 02:40:12 (GMT) |
commit | 613cf9fb6fe4b24bc7852d5a31953f6ff419e43c (patch) | |
tree | 8459365c5a6a00503063b0bf1d516fce5ea4d891 /src/uscxml/transform | |
parent | c699a4057a65a9a09f78310d8e12588f2dc072cd (diff) | |
download | uscxml-613cf9fb6fe4b24bc7852d5a31953f6ff419e43c.zip uscxml-613cf9fb6fe4b24bc7852d5a31953f6ff419e43c.tar.gz uscxml-613cf9fb6fe4b24bc7852d5a31953f6ff419e43c.tar.bz2 |
Beautified code
Diffstat (limited to 'src/uscxml/transform')
-rw-r--r-- | src/uscxml/transform/ChartToC.cpp | 3051 | ||||
-rw-r--r-- | src/uscxml/transform/ChartToC.h | 100 | ||||
-rw-r--r-- | src/uscxml/transform/ChartToFSM.cpp | 674 | ||||
-rw-r--r-- | src/uscxml/transform/ChartToFSM.h | 66 | ||||
-rw-r--r-- | src/uscxml/transform/ChartToFlatSCXML.cpp | 134 | ||||
-rw-r--r-- | src/uscxml/transform/ChartToFlatSCXML.h | 10 | ||||
-rw-r--r-- | src/uscxml/transform/ChartToMinimalSCXML.cpp | 48 | ||||
-rw-r--r-- | src/uscxml/transform/ChartToMinimalSCXML.h | 18 | ||||
-rw-r--r-- | src/uscxml/transform/ChartToPromela.cpp | 976 | ||||
-rw-r--r-- | src/uscxml/transform/ChartToPromela.h | 126 | ||||
-rw-r--r-- | src/uscxml/transform/ChartToTex.cpp | 65 | ||||
-rw-r--r-- | src/uscxml/transform/ChartToTex.h | 10 | ||||
-rw-r--r-- | src/uscxml/transform/FlatStateIdentifier.h | 4 | ||||
-rw-r--r-- | src/uscxml/transform/Transformer.h | 14 |
14 files changed, 2655 insertions, 2641 deletions
diff --git a/src/uscxml/transform/ChartToC.cpp b/src/uscxml/transform/ChartToC.cpp index 3944b92..2d3f6ba 100644 --- a/src/uscxml/transform/ChartToC.cpp +++ b/src/uscxml/transform/ChartToC.cpp @@ -35,1592 +35,1593 @@ namespace uscxml { using namespace Arabica::DOM; using namespace Arabica::XPath; - + Transformer ChartToC::transform(const Interpreter& other) { - ChartToC* c2c = new ChartToC(other); - - return boost::shared_ptr<TransformerImpl>(c2c); + ChartToC* c2c = new ChartToC(other); + + return boost::shared_ptr<TransformerImpl>(c2c); } ChartToC::ChartToC(const Interpreter& other) : TransformerImpl() { - cloneFrom(other.getImpl()); + cloneFrom(other.getImpl()); } 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") : ""); - - std::set<std::string> elements; - elements.insert(_nsInfo.xmlNSPrefix + "scxml"); - elements.insert(_nsInfo.xmlNSPrefix + "state"); - elements.insert(_nsInfo.xmlNSPrefix + "final"); - elements.insert(_nsInfo.xmlNSPrefix + "parallel"); - elements.insert(_nsInfo.xmlNSPrefix + "history"); - elements.insert(_nsInfo.xmlNSPrefix + "initial"); - elements.insert(_nsInfo.xmlNSPrefix + "parallel"); - _states = inDocumentOrder(elements, _scxml); - - for (int i = 0; i < _states.size(); i++) { - Element<std::string> state(_states[i]); - state.setAttribute("documentOrder", toStr(i)); - if (HAS_ATTR(state, "id")) { - _stateNames[ATTR(state, "id")] = state; - } - } - - elements.clear(); - elements.insert(_nsInfo.xmlNSPrefix + "transition"); - _transitions = inPostFixOrder(elements, _scxml); - - for (int i = 0; i < _transitions.size(); i++) { - Element<std::string> transition(_transitions[i]); - transition.setAttribute("postFixOrder", toStr(i)); - } - - // how many bits do we need to represent the state array? - std::string seperator; - _stateCharArraySize = ceil((float)_states.size() / (float)8); - _stateCharArrayInit = "{"; - for (int i = 0; i < _stateCharArraySize; i++) { - _stateCharArrayInit += seperator + "0"; - seperator = ", "; - } - _stateCharArrayInit += "}"; - - seperator = ""; - _transCharArraySize = ceil((float)_transitions.size() / (float)8); - _transCharArrayInit = "{"; - for (int i = 0; i < _transCharArraySize; i++) { - _transCharArrayInit += seperator + "0"; - seperator = ", "; - } - _transCharArrayInit += "}"; - - writeIncludes(stream); - writeMacros(stream); - writeTypes(stream); - writeElementInfo(stream); - writeExecContent(stream); - writeStates(stream); - writeTransitions(stream); - writeHelpers(stream); - writeFSM(stream); - - // http://stackoverflow.com/questions/2525310/how-to-define-and-work-with-an-array-of-bits-in-c - + _binding = (HAS_ATTR(_scxml, "binding") && iequals(ATTR(_scxml, "binding"), "late") ? LATE : EARLY); + _name = (HAS_ATTR(_scxml, "name") ? ATTR(_scxml, "name") : ""); + + std::set<std::string> elements; + elements.insert(_nsInfo.xmlNSPrefix + "scxml"); + elements.insert(_nsInfo.xmlNSPrefix + "state"); + elements.insert(_nsInfo.xmlNSPrefix + "final"); + elements.insert(_nsInfo.xmlNSPrefix + "parallel"); + elements.insert(_nsInfo.xmlNSPrefix + "history"); + elements.insert(_nsInfo.xmlNSPrefix + "initial"); + elements.insert(_nsInfo.xmlNSPrefix + "parallel"); + _states = inDocumentOrder(elements, _scxml); + + for (int i = 0; i < _states.size(); i++) { + Element<std::string> state(_states[i]); + state.setAttribute("documentOrder", toStr(i)); + if (HAS_ATTR(state, "id")) { + _stateNames[ATTR(state, "id")] = state; + } + } + + elements.clear(); + elements.insert(_nsInfo.xmlNSPrefix + "transition"); + _transitions = inPostFixOrder(elements, _scxml); + + for (int i = 0; i < _transitions.size(); i++) { + Element<std::string> transition(_transitions[i]); + transition.setAttribute("postFixOrder", toStr(i)); + } + + // how many bits do we need to represent the state array? + std::string seperator; + _stateCharArraySize = ceil((float)_states.size() / (float)8); + _stateCharArrayInit = "{"; + for (int i = 0; i < _stateCharArraySize; i++) { + _stateCharArrayInit += seperator + "0"; + seperator = ", "; + } + _stateCharArrayInit += "}"; + + seperator = ""; + _transCharArraySize = ceil((float)_transitions.size() / (float)8); + _transCharArrayInit = "{"; + for (int i = 0; i < _transCharArraySize; i++) { + _transCharArrayInit += seperator + "0"; + seperator = ", "; + } + _transCharArrayInit += "}"; + + writeIncludes(stream); + writeMacros(stream); + writeTypes(stream); + writeElementInfo(stream); + writeExecContent(stream); + writeStates(stream); + writeTransitions(stream); + writeHelpers(stream); + writeFSM(stream); + + // http://stackoverflow.com/questions/2525310/how-to-define-and-work-with-an-array-of-bits-in-c + } void ChartToC::writeIncludes(std::ostream& stream) { - stream << "#include <stdint.h> // explicit types" << std::endl; - stream << "#include <stddef.h> // NULL" << std::endl; - stream << std::endl; + stream << "#include <stdint.h> // explicit types" << std::endl; + stream << "#include <stddef.h> // NULL" << std::endl; + stream << std::endl; } 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 << std::endl; - - stream << "#ifdef __GNUC__" << std::endl; - stream << "#define likely(x) __builtin_expect(!!(x), 1)" << std::endl; - stream << "#define unlikely(x) __builtin_expect(!!(x), 0)" << std::endl; - stream << "#else" << std::endl; - stream << "#define likely(x) (x)" << std::endl; - stream << "#define unlikely(x) (x)" << std::endl; - stream << "#endif" << std::endl; - stream << std::endl; - - stream << "// error return codes" << std::endl; - stream << "#define SCXML_ERR_OK 0" << std::endl; - stream << "#define SCXML_ERR_IDLE 1" << std::endl; - stream << "#define SCXML_ERR_DONE 2" << std::endl; - stream << "#define SCXML_ERR_MISSING_CALLBACK 3" << std::endl; - stream << "#define SCXML_ERR_FOREACH_DONE 4" << std::endl; - stream << "#define SCXML_ERR_EXEC_CONTENT 5" << std::endl; - stream << "#define SCXML_ERR_INVALID_TARGET 6" << std::endl; - stream << "#define SCXML_ERR_INVALID_TYPE 7" << std::endl; - stream << "#define SCXML_ERR_UNSUPPORTED 8" << std::endl; - stream << std::endl; - - stream << "#define SCXML_MACHINE_NAME \"" << _name << "\"" << std::endl; - stream << "#define SCXML_NUMBER_STATES " << _states.size() << std::endl; - stream << "#define SCXML_NUMBER_TRANSITIONS " << _transitions.size() << std::endl; - stream << std::endl; - - stream << "#define SCXML_TRANS_SPONTANEOUS 0x01" << std::endl; - stream << "#define SCXML_TRANS_TARGETLESS 0x02" << std::endl; - stream << "#define SCXML_TRANS_INTERNAL 0x04" << std::endl; - stream << "#define SCXML_TRANS_HISTORY 0x08" << std::endl; - stream << std::endl; - - stream << "#define SCXML_STATE_ATOMIC 0x01" << std::endl; - stream << "#define SCXML_STATE_PARALLEL 0x02" << std::endl; - stream << "#define SCXML_STATE_COMPOUND 0x03" << std::endl; - stream << "#define SCXML_STATE_FINAL 0x04" << std::endl; - stream << "#define SCXML_STATE_HISTORY_DEEP 0x05" << std::endl; - stream << "#define SCXML_STATE_HISTORY_SHALLOW 0x06" << std::endl; - stream << "#define SCXML_STATE_INITIAL 0x07" << std::endl; - - stream << "" << std::endl; - stream << "#define SCXML_CTX_PRISTINE 0x00" << std::endl; - 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 << std::endl; - - stream << "#define ELEM_DATA_IS_SET(data) (data->id != NULL)" << std::endl; - stream << "#define ELEM_DONEDATA_IS_SET(donedata) (donedata->content != NULL || donedata->contentexpr != NULL || donedata->params != NULL)" << std::endl; - stream << "#define ELEM_PARAM_IS_SET(param) (param->name != NULL)" << std::endl; - stream << std::endl; + 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 << std::endl; + + stream << "#ifdef __GNUC__" << std::endl; + stream << "#define likely(x) __builtin_expect(!!(x), 1)" << std::endl; + stream << "#define unlikely(x) __builtin_expect(!!(x), 0)" << std::endl; + stream << "#else" << std::endl; + stream << "#define likely(x) (x)" << std::endl; + stream << "#define unlikely(x) (x)" << std::endl; + stream << "#endif" << std::endl; + stream << std::endl; + + stream << "// error return codes" << std::endl; + stream << "#define SCXML_ERR_OK 0" << std::endl; + stream << "#define SCXML_ERR_IDLE 1" << std::endl; + stream << "#define SCXML_ERR_DONE 2" << std::endl; + stream << "#define SCXML_ERR_MISSING_CALLBACK 3" << std::endl; + stream << "#define SCXML_ERR_FOREACH_DONE 4" << std::endl; + stream << "#define SCXML_ERR_EXEC_CONTENT 5" << std::endl; + stream << "#define SCXML_ERR_INVALID_TARGET 6" << std::endl; + stream << "#define SCXML_ERR_INVALID_TYPE 7" << std::endl; + stream << "#define SCXML_ERR_UNSUPPORTED 8" << std::endl; + stream << std::endl; + + stream << "#define SCXML_MACHINE_NAME \"" << _name << "\"" << std::endl; + stream << "#define SCXML_NUMBER_STATES " << _states.size() << std::endl; + stream << "#define SCXML_NUMBER_TRANSITIONS " << _transitions.size() << std::endl; + stream << std::endl; + + stream << "#define SCXML_TRANS_SPONTANEOUS 0x01" << std::endl; + stream << "#define SCXML_TRANS_TARGETLESS 0x02" << std::endl; + stream << "#define SCXML_TRANS_INTERNAL 0x04" << std::endl; + stream << "#define SCXML_TRANS_HISTORY 0x08" << std::endl; + stream << std::endl; + + stream << "#define SCXML_STATE_ATOMIC 0x01" << std::endl; + stream << "#define SCXML_STATE_PARALLEL 0x02" << std::endl; + stream << "#define SCXML_STATE_COMPOUND 0x03" << std::endl; + stream << "#define SCXML_STATE_FINAL 0x04" << std::endl; + stream << "#define SCXML_STATE_HISTORY_DEEP 0x05" << std::endl; + stream << "#define SCXML_STATE_HISTORY_SHALLOW 0x06" << std::endl; + stream << "#define SCXML_STATE_INITIAL 0x07" << std::endl; + + stream << "" << std::endl; + stream << "#define SCXML_CTX_PRISTINE 0x00" << std::endl; + 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 << std::endl; + + stream << "#define ELEM_DATA_IS_SET(data) (data->id != NULL)" << std::endl; + stream << "#define ELEM_DONEDATA_IS_SET(donedata) (donedata->content != NULL || donedata->contentexpr != NULL || donedata->params != NULL)" << std::endl; + stream << "#define ELEM_PARAM_IS_SET(param) (param->name != NULL)" << std::endl; + stream << std::endl; } void ChartToC::writeTypes(std::ostream& stream) { - - stream << std::endl; - stream << "typedef struct scxml_transition scxml_transition;" << std::endl; - stream << "typedef struct scxml_state scxml_state;" << std::endl; - stream << "typedef struct scxml_ctx scxml_ctx;" << std::endl; - stream << "typedef struct scxml_invoke scxml_invoke;" << std::endl; - - stream << std::endl; - - stream << "typedef struct scxml_elem_send scxml_elem_send;" << std::endl; - stream << "typedef struct scxml_elem_param scxml_elem_param;" << std::endl; - stream << "typedef struct scxml_elem_data scxml_elem_data;" << std::endl; - stream << "typedef struct scxml_elem_donedata scxml_elem_donedata;" << std::endl; - stream << "typedef struct scxml_elem_foreach scxml_elem_foreach;" << std::endl; - stream << std::endl; - - stream << "typedef void* (*dequeue_internal_cb_t)(const scxml_ctx* ctx);" << std::endl; - stream << "typedef void* (*dequeue_external_cb_t)(const scxml_ctx* ctx);" << std::endl; - stream << "typedef int (*is_enabled_cb_t)(const scxml_ctx* ctx, const scxml_transition* transition, const void* event);" << std::endl; - stream << "typedef int (*is_true_cb_t)(const scxml_ctx* ctx, const char* expr);" << std::endl; - stream << "typedef int (*exec_content_t)(const scxml_ctx* ctx, const scxml_state* state, const void* event);" << std::endl; - stream << "typedef int (*raise_done_event_t)(const scxml_ctx* ctx, const scxml_state* state, const scxml_elem_donedata* donedata);" << std::endl; - stream << "typedef int (*invoke_t)(const scxml_ctx* ctx, const scxml_state* s, const scxml_invoke* x);" << std::endl; - stream << std::endl; - - stream << "typedef int (*exec_content_log_t)(const scxml_ctx* ctx, const char* label, const char* expr);" << std::endl; - stream << "typedef int (*exec_content_raise_t)(const scxml_ctx* ctx, const char* event);" << std::endl; - stream << "typedef int (*exec_content_send_t)(const scxml_ctx* ctx, const scxml_elem_send* send);" << std::endl; - stream << "typedef int (*exec_content_foreach_init_t)(const scxml_ctx* ctx, const scxml_elem_foreach* foreach);" << std::endl; - stream << "typedef int (*exec_content_foreach_next_t)(const scxml_ctx* ctx, const scxml_elem_foreach* foreach);" << std::endl; - stream << "typedef int (*exec_content_foreach_done_t)(const scxml_ctx* ctx, const scxml_elem_foreach* foreach);" << std::endl; - stream << "typedef int (*exec_content_assign_t)(const scxml_ctx* ctx, const char* location, const char* expr);" << std::endl; - stream << "typedef int (*exec_content_init_t)(const scxml_ctx* ctx, const scxml_elem_data* data);" << std::endl; - stream << "typedef int (*exec_content_cancel_t)(const scxml_ctx* ctx, const char* sendid, const char* sendidexpr);" << std::endl; - stream << "typedef int (*exec_content_finalize_t)(const scxml_ctx* ctx, const scxml_invoke* invoker, const void* event);" << std::endl; - stream << "typedef int (*exec_content_script_t)(const scxml_ctx* ctx, const char* src, const char* content);" << std::endl; - stream << std::endl; - - stream << "struct scxml_elem_data {" << std::endl; - stream << " const char* id;" << std::endl; - stream << " const char* src;" << std::endl; - stream << " const char* expr;" << std::endl; - stream << " const char* content;" << std::endl; - stream << "};" << std::endl; - stream << std::endl; - - stream << "struct scxml_state {" << std::endl; - stream << " const char* name; // eventual name" << std::endl; - stream << " uint16_t source; // parent" << std::endl; - stream << " exec_content_t on_entry; // on entry handlers" << std::endl; - stream << " exec_content_t on_exit; // on exit handlers" << std::endl; - stream << " invoke_t invoke; // invocations" << std::endl; - stream << " char children[" << _stateCharArraySize << "]; // all children" << std::endl; - stream << " char completion[" << _stateCharArraySize << "]; // default completion" << std::endl; - stream << " char ancestors[" << _stateCharArraySize << "]; // all ancestors" << std::endl; - stream << " const scxml_elem_data* data;" << std::endl; - stream << " uint8_t type; // atomic, parallel, compound, final, history" << std::endl; - stream << "};" << std::endl; - stream << std::endl; - - stream << "struct scxml_transition {" << std::endl; - stream << " uint16_t source;" << std::endl; - stream << " char target[" << _stateCharArraySize << "];" << std::endl; - stream << " const char* event;" << std::endl; - stream << " const char* condition;" << std::endl; - stream << " exec_content_t on_transition;" << std::endl; - stream << " uint8_t type;" << std::endl; - stream << " char conflicts[" << _transCharArraySize << "];" << std::endl; - stream << " char exit_set[" << _stateCharArraySize << "];" << std::endl; - stream << "};" << std::endl; - stream << std::endl; - - stream << "struct scxml_elem_foreach {" << std::endl; - stream << " const char* array;" << std::endl; - stream << " const char* item;" << std::endl; - stream << " const char* index;" << std::endl; - stream << "};" << std::endl; - stream << std::endl; - - stream << "struct scxml_elem_param {" << std::endl; - stream << " const char* name;" << std::endl; - stream << " const char* expr;" << std::endl; - stream << " const char* location;" << std::endl; - stream << "};" << std::endl; - stream << std::endl; - - stream << "struct scxml_elem_donedata {" << std::endl; - stream << " uint16_t source;" << std::endl; - stream << " const char* content;" << std::endl; - stream << " const char* contentexpr;" << std::endl; - stream << " const scxml_elem_param* params;" << std::endl; - stream << "};" << std::endl; - stream << std::endl; - - stream << "struct scxml_elem_invoke {" << std::endl; - stream << " const char* type;" << std::endl; - stream << " const char* typeexpr;" << std::endl; - 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* namelist;" << std::endl; - stream << " uint8_t autoforward;" << std::endl; - stream << " const scxml_elem_param* params;" << std::endl; - stream << " const exec_content_finalize_t* finalize;" << std::endl; - stream << " const char* content;" << std::endl; - stream << " const char* contentexpr;" << std::endl; - stream << " void* user_data;" << std::endl; - stream << "};" << std::endl; - stream << std::endl; - - stream << "struct scxml_elem_send {" << std::endl; - stream << " const char* event;" << std::endl; - stream << " const char* eventexpr;" << std::endl; - stream << " const char* target;" << std::endl; - stream << " const char* targetexpr;" << std::endl; - stream << " const char* type;" << std::endl; - stream << " const char* typeexpr;" << std::endl; - stream << " const char* id;" << std::endl; - stream << " const char* idlocation;" << std::endl; - stream << " const char* delay;" << std::endl; - stream << " const char* delayexpr;" << std::endl; - stream << " const char* namelist;" << std::endl; - stream << " const char* content;" << std::endl; - stream << " const char* contentexpr;" << std::endl; - stream << " const scxml_elem_param* params;" << std::endl; - stream << " void* user_data;" << std::endl; - stream << "};" << std::endl; - stream << std::endl; - - stream << "struct scxml_ctx {" << std::endl; - stream << " uint8_t flags;" << std::endl; - stream << std::endl; - stream << " char config[" << _stateCharArraySize << "];" << std::endl; - stream << " char history[" << _stateCharArraySize << "];" << std::endl; - stream << " char pending_invokes[" << _stateCharArraySize << "];" << std::endl; - stream << " char initialized_data[" << _stateCharArraySize << "];" << std::endl; - stream << std::endl; - stream << " void* user_data;" << std::endl; - stream << std::endl; - stream << " dequeue_internal_cb_t dequeue_internal;" << std::endl; - stream << " dequeue_external_cb_t dequeue_external;" << std::endl; - stream << " is_enabled_cb_t is_enabled;" << std::endl; - stream << " is_true_cb_t is_true;" << std::endl; - stream << " raise_done_event_t raise_done_event;" << std::endl; - stream << std::endl; - stream << " exec_content_log_t exec_content_log;" << std::endl; - stream << " exec_content_raise_t exec_content_raise;" << std::endl; - stream << " exec_content_send_t exec_content_send;" << std::endl; - stream << " exec_content_foreach_init_t exec_content_foreach_init;" << std::endl; - stream << " exec_content_foreach_next_t exec_content_foreach_next;" << std::endl; - stream << " exec_content_foreach_done_t exec_content_foreach_done;" << std::endl; - stream << " exec_content_assign_t exec_content_assign;" << std::endl; - stream << " exec_content_init_t exec_content_init;" << std::endl; - stream << " exec_content_cancel_t exec_content_cancel;" << std::endl; - stream << " exec_content_script_t exec_content_script;" << std::endl; - stream << " invoke_t invoke;" << std::endl; - stream << "};" << std::endl; - stream << std::endl; + + stream << std::endl; + stream << "typedef struct scxml_transition scxml_transition;" << std::endl; + stream << "typedef struct scxml_state scxml_state;" << std::endl; + stream << "typedef struct scxml_ctx scxml_ctx;" << std::endl; + stream << "typedef struct scxml_invoke scxml_invoke;" << std::endl; + + stream << std::endl; + + stream << "typedef struct scxml_elem_send scxml_elem_send;" << std::endl; + stream << "typedef struct scxml_elem_param scxml_elem_param;" << std::endl; + stream << "typedef struct scxml_elem_data scxml_elem_data;" << std::endl; + stream << "typedef struct scxml_elem_donedata scxml_elem_donedata;" << std::endl; + stream << "typedef struct scxml_elem_foreach scxml_elem_foreach;" << std::endl; + stream << std::endl; + + stream << "typedef void* (*dequeue_internal_cb_t)(const scxml_ctx* ctx);" << std::endl; + stream << "typedef void* (*dequeue_external_cb_t)(const scxml_ctx* ctx);" << std::endl; + stream << "typedef int (*is_enabled_cb_t)(const scxml_ctx* ctx, const scxml_transition* transition, const void* event);" << std::endl; + stream << "typedef int (*is_true_cb_t)(const scxml_ctx* ctx, const char* expr);" << std::endl; + stream << "typedef int (*exec_content_t)(const scxml_ctx* ctx, const scxml_state* state, const void* event);" << std::endl; + stream << "typedef int (*raise_done_event_t)(const scxml_ctx* ctx, const scxml_state* state, const scxml_elem_donedata* donedata);" << std::endl; + stream << "typedef int (*invoke_t)(const scxml_ctx* ctx, const scxml_state* s, const scxml_invoke* x);" << std::endl; + stream << std::endl; + + stream << "typedef int (*exec_content_log_t)(const scxml_ctx* ctx, const char* label, const char* expr);" << std::endl; + stream << "typedef int (*exec_content_raise_t)(const scxml_ctx* ctx, const char* event);" << std::endl; + stream << "typedef int (*exec_content_send_t)(const scxml_ctx* ctx, const scxml_elem_send* send);" << std::endl; + stream << "typedef int (*exec_content_foreach_init_t)(const scxml_ctx* ctx, const scxml_elem_foreach* foreach);" << std::endl; + stream << "typedef int (*exec_content_foreach_next_t)(const scxml_ctx* ctx, const scxml_elem_foreach* foreach);" << std::endl; + stream << "typedef int (*exec_content_foreach_done_t)(const scxml_ctx* ctx, const scxml_elem_foreach* foreach);" << std::endl; + stream << "typedef int (*exec_content_assign_t)(const scxml_ctx* ctx, const char* location, const char* expr);" << std::endl; + stream << "typedef int (*exec_content_init_t)(const scxml_ctx* ctx, const scxml_elem_data* data);" << std::endl; + stream << "typedef int (*exec_content_cancel_t)(const scxml_ctx* ctx, const char* sendid, const char* sendidexpr);" << std::endl; + stream << "typedef int (*exec_content_finalize_t)(const scxml_ctx* ctx, const scxml_invoke* invoker, const void* event);" << std::endl; + stream << "typedef int (*exec_content_script_t)(const scxml_ctx* ctx, const char* src, const char* content);" << std::endl; + stream << std::endl; + + stream << "struct scxml_elem_data {" << std::endl; + stream << " const char* id;" << std::endl; + stream << " const char* src;" << std::endl; + stream << " const char* expr;" << std::endl; + stream << " const char* content;" << std::endl; + stream << "};" << std::endl; + stream << std::endl; + + stream << "struct scxml_state {" << std::endl; + stream << " const char* name; // eventual name" << std::endl; + stream << " uint16_t source; // parent" << std::endl; + stream << " exec_content_t on_entry; // on entry handlers" << std::endl; + stream << " exec_content_t on_exit; // on exit handlers" << std::endl; + stream << " invoke_t invoke; // invocations" << std::endl; + stream << " char children[" << _stateCharArraySize << "]; // all children" << std::endl; + stream << " char completion[" << _stateCharArraySize << "]; // default completion" << std::endl; + stream << " char ancestors[" << _stateCharArraySize << "]; // all ancestors" << std::endl; + stream << " const scxml_elem_data* data;" << std::endl; + stream << " uint8_t type; // atomic, parallel, compound, final, history" << std::endl; + stream << "};" << std::endl; + stream << std::endl; + + stream << "struct scxml_transition {" << std::endl; + stream << " uint16_t source;" << std::endl; + stream << " char target[" << _stateCharArraySize << "];" << std::endl; + stream << " const char* event;" << std::endl; + stream << " const char* condition;" << std::endl; + stream << " exec_content_t on_transition;" << std::endl; + stream << " uint8_t type;" << std::endl; + stream << " char conflicts[" << _transCharArraySize << "];" << std::endl; + stream << " char exit_set[" << _stateCharArraySize << "];" << std::endl; + stream << "};" << std::endl; + stream << std::endl; + + stream << "struct scxml_elem_foreach {" << std::endl; + stream << " const char* array;" << std::endl; + stream << " const char* item;" << std::endl; + stream << " const char* index;" << std::endl; + stream << "};" << std::endl; + stream << std::endl; + + stream << "struct scxml_elem_param {" << std::endl; + stream << " const char* name;" << std::endl; + stream << " const char* expr;" << std::endl; + stream << " const char* location;" << std::endl; + stream << "};" << std::endl; + stream << std::endl; + + stream << "struct scxml_elem_donedata {" << std::endl; + stream << " uint16_t source;" << std::endl; + stream << " const char* content;" << std::endl; + stream << " const char* contentexpr;" << std::endl; + stream << " const scxml_elem_param* params;" << std::endl; + stream << "};" << std::endl; + stream << std::endl; + + stream << "struct scxml_elem_invoke {" << std::endl; + stream << " const char* type;" << std::endl; + stream << " const char* typeexpr;" << std::endl; + 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* namelist;" << std::endl; + stream << " uint8_t autoforward;" << std::endl; + stream << " const scxml_elem_param* params;" << std::endl; + stream << " const exec_content_finalize_t* finalize;" << std::endl; + stream << " const char* content;" << std::endl; + stream << " const char* contentexpr;" << std::endl; + stream << " void* user_data;" << std::endl; + stream << "};" << std::endl; + stream << std::endl; + + stream << "struct scxml_elem_send {" << std::endl; + stream << " const char* event;" << std::endl; + stream << " const char* eventexpr;" << std::endl; + stream << " const char* target;" << std::endl; + stream << " const char* targetexpr;" << std::endl; + stream << " const char* type;" << std::endl; + stream << " const char* typeexpr;" << std::endl; + stream << " const char* id;" << std::endl; + stream << " const char* idlocation;" << std::endl; + stream << " const char* delay;" << std::endl; + stream << " const char* delayexpr;" << std::endl; + stream << " const char* namelist;" << std::endl; + stream << " const char* content;" << std::endl; + stream << " const char* contentexpr;" << std::endl; + stream << " const scxml_elem_param* params;" << std::endl; + stream << " void* user_data;" << std::endl; + stream << "};" << std::endl; + stream << std::endl; + + stream << "struct scxml_ctx {" << std::endl; + stream << " uint8_t flags;" << std::endl; + stream << std::endl; + stream << " char config[" << _stateCharArraySize << "];" << std::endl; + stream << " char history[" << _stateCharArraySize << "];" << std::endl; + stream << " char pending_invokes[" << _stateCharArraySize << "];" << std::endl; + stream << " char initialized_data[" << _stateCharArraySize << "];" << std::endl; + stream << std::endl; + stream << " void* user_data;" << std::endl; + stream << std::endl; + stream << " dequeue_internal_cb_t dequeue_internal;" << std::endl; + stream << " dequeue_external_cb_t dequeue_external;" << std::endl; + stream << " is_enabled_cb_t is_enabled;" << std::endl; + stream << " is_true_cb_t is_true;" << std::endl; + stream << " raise_done_event_t raise_done_event;" << std::endl; + stream << std::endl; + stream << " exec_content_log_t exec_content_log;" << std::endl; + stream << " exec_content_raise_t exec_content_raise;" << std::endl; + stream << " exec_content_send_t exec_content_send;" << std::endl; + stream << " exec_content_foreach_init_t exec_content_foreach_init;" << std::endl; + stream << " exec_content_foreach_next_t exec_content_foreach_next;" << std::endl; + stream << " exec_content_foreach_done_t exec_content_foreach_done;" << std::endl; + stream << " exec_content_assign_t exec_content_assign;" << std::endl; + stream << " exec_content_init_t exec_content_init;" << std::endl; + stream << " exec_content_cancel_t exec_content_cancel;" << std::endl; + stream << " exec_content_script_t exec_content_script;" << std::endl; + stream << " invoke_t invoke;" << std::endl; + stream << "};" << std::endl; + stream << std::endl; } void ChartToC::writeHelpers(std::ostream& stream) { - stream << "#ifdef SCXML_VERBOSE" << std::endl; - stream << "static void printStateNames(const char* a) {" << std::endl; - stream << " const char* seperator = \"\";" << std::endl; - stream << " for (int i = 0; i < SCXML_NUMBER_STATES; i++) {" << std::endl; - stream << " if (IS_SET(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; - stream << " }" << std::endl; - stream << " printf(\"\\n\");" << std::endl; - stream << "}" << std::endl; - stream << std::endl; - - stream << "static void printBitsetIndices(const char* a, size_t length) {" << std::endl; - stream << " const char* seperator = \"\";" << std::endl; - stream << " for (int i = 0; i < length; i++) {" << std::endl; - stream << " if (IS_SET(i, a)) {" << std::endl; - stream << " printf(\"%s%d\", seperator, i);" << std::endl; - stream << " seperator = \", \";" << std::endl; - stream << " }" << std::endl; - stream << " }" << std::endl; - stream << " printf(\"\\n\");" << std::endl; - stream << "}" << std::endl; - - stream << "#endif" << std::endl; - stream << std::endl; - - stream << "static void bit_or(char* dest, const char* mask, size_t i) {" << std::endl; - stream << " do {" << std::endl; - stream << " dest[i - 1] |= mask[i - 1];" << std::endl; - stream << " } while(--i);" << std::endl; - stream << "}" << std::endl; - stream << 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] = source[i - 1];" << std::endl; - stream << " } while(--i);" << 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 << " do {" << 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_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 << " } 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 << " do {" << 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 << " do {" << 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 << "#ifdef SCXML_VERBOSE" << std::endl; + stream << "static void printStateNames(const char* a) {" << std::endl; + stream << " const char* seperator = \"\";" << std::endl; + stream << " for (int i = 0; i < SCXML_NUMBER_STATES; i++) {" << std::endl; + stream << " if (IS_SET(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; + stream << " }" << std::endl; + stream << " printf(\"\\n\");" << std::endl; + stream << "}" << std::endl; + stream << std::endl; + + stream << "static void printBitsetIndices(const char* a, size_t length) {" << std::endl; + stream << " const char* seperator = \"\";" << std::endl; + stream << " for (int i = 0; i < length; i++) {" << std::endl; + stream << " if (IS_SET(i, a)) {" << std::endl; + stream << " printf(\"%s%d\", seperator, i);" << std::endl; + stream << " seperator = \", \";" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " printf(\"\\n\");" << std::endl; + stream << "}" << std::endl; + + stream << "#endif" << std::endl; + stream << std::endl; + + stream << "static void bit_or(char* dest, const char* mask, size_t i) {" << std::endl; + stream << " do {" << std::endl; + stream << " dest[i - 1] |= mask[i - 1];" << std::endl; + stream << " } while(--i);" << std::endl; + stream << "}" << std::endl; + stream << 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] = source[i - 1];" << std::endl; + stream << " } while(--i);" << 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 << " do {" << 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_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 << " } 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 << " do {" << 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 << " do {" << 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; } - + void ChartToC::writeExecContent(std::ostream& stream) { - for (int i = 0; i < _states.size(); i++) { - Element<std::string> state(_states[i]); - - if (i == 0) { - // root state - we need to perform some initialization here - NodeSet<std::string> globalScripts = filterChildElements(_nsInfo.xmlNSPrefix + "script", state); - if (globalScripts.size() > 0) { - _hasGlobalScripts = true; - for (int j = 0; j < globalScripts.size(); j++) { - stream << "static int global_script_" << toStr(j) << "(const scxml_ctx* ctx, const scxml_state* state, const void* event) {" << std::endl; - stream << " int err = SCXML_ERR_OK;" << std::endl; - writeExecContent(stream, globalScripts[j], 1); - stream << " return SCXML_ERR_OK;" << std::endl; - stream << "}" << std::endl; - } - - stream << "static int global_script(const scxml_ctx* ctx, const scxml_state* state, const void* event) {" << std::endl; - for (int j = 0; j < globalScripts.size(); j++) { - stream << " global_script_" << toStr(j) << "(ctx, state, event);" << std::endl; - } - stream << " return SCXML_ERR_OK;" << std::endl; - stream << "}" << std::endl; - stream << std::endl; - } else { - _hasGlobalScripts = false; - } - } - - NodeSet<std::string> onexit = filterChildElements(_nsInfo.xmlNSPrefix + "onexit", state); - for (int j = 0; j < onexit.size(); j++) { - stream << "static int " << DOMUtils::idForNode(state) << "_on_exit_" << toStr(j) << "(const scxml_ctx* ctx, const scxml_state* state, const void* event) {" << std::endl; - stream << " int err = SCXML_ERR_OK;" << std::endl; - writeExecContent(stream, onexit[j], 1); - stream << " return SCXML_ERR_OK;" << std::endl; - stream << "}" << std::endl; - stream << std::endl; - } - - if (onexit.size() > 0) { - stream << "static int " << DOMUtils::idForNode(state) << "_on_exit(const scxml_ctx* ctx, const scxml_state* state, const void* event) {" << std::endl; - for (int j = 0; j < onexit.size(); j++) { - stream << " " << DOMUtils::idForNode(state) << "_on_exit_" << toStr(j) << "(ctx, state, event);" << std::endl; - } - stream << " return SCXML_ERR_OK;" << std::endl; - stream << "}" << std::endl; - stream << std::endl; - } - - - NodeSet<std::string> onentry = filterChildElements(_nsInfo.xmlNSPrefix + "onentry", state); - for (int j = 0; j < onentry.size(); j++) { - stream << "static int " << DOMUtils::idForNode(state) << "_on_entry_" << toStr(j) << "(const scxml_ctx* ctx, const scxml_state* state, const void* event) {" << std::endl; - stream << " int err = SCXML_ERR_OK;" << std::endl; - writeExecContent(stream, onentry[j], 1); - stream << " return SCXML_ERR_OK;" << std::endl; - stream << "}" << std::endl; - stream << std::endl; - } - - bool hasInitialState = false; - NodeSet<std::string> initial = filterChildElements(_nsInfo.xmlNSPrefix + "initial", state); - if (initial.size() > 0) { - NodeSet<std::string> initialTransition = filterChildElements(_nsInfo.xmlNSPrefix + "transition", initial); - if (initialTransition.size() > 0) { - hasInitialState = true; - stream << "static int " << DOMUtils::idForNode(state) << "_initial" << "(const scxml_ctx* ctx, const scxml_state* state, const void* event) {" << std::endl; - stream << " int err = SCXML_ERR_OK;" << std::endl; - writeExecContent(stream, initialTransition[0], 1); - stream << " return SCXML_ERR_OK;" << std::endl; - stream << "}" << std::endl; - stream << std::endl; - } - } - - - if (onentry.size() > 0) { - stream << "static int " << DOMUtils::idForNode(state) << "_on_entry(const scxml_ctx* ctx, const scxml_state* state, const void* event) {" << std::endl; - for (int j = 0; j < onentry.size(); j++) { - stream << " " << DOMUtils::idForNode(state) << "_on_entry_" << toStr(j) << "(ctx, state, event);" << std::endl; - } - if (hasInitialState) { - stream << " " << DOMUtils::idForNode(state) << "_initial" << "(ctx, state, event);" << std::endl; - } - - stream << " return SCXML_ERR_OK;" << std::endl; - stream << "}" << std::endl; - stream << std::endl; - } - - - NodeSet<std::string> invoke = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", state); - if (invoke.size() > 0) { - stream << "static int " << DOMUtils::idForNode(state) << "_invoke(const scxml_ctx* ctx, const scxml_state* s, const scxml_invoke* x) {" << std::endl; - for (int j = 0; j < invoke.size(); j++) { - stream << " ctx->invoke(ctx, s, x);" << std::endl; - stream << " return SCXML_ERR_OK;" << std::endl; - stream << std::endl; - } - stream << "}" << std::endl; - } - } - - for (int i = 0; i < _transitions.size(); i++) { - Element<std::string> transition(_transitions[i]); - if (iequals(TAGNAME_CAST(transition.getParentNode()), "initial")) - continue; - - NodeSet<std::string> execContent = filterChildType(Node_base::ELEMENT_NODE, transition); - - if (execContent.size() > 0) { - stream << "static int " << DOMUtils::idForNode(transition) << "_on_trans(const scxml_ctx* ctx, const scxml_state* state, const void* event) {" << std::endl; - stream << " int err = SCXML_ERR_OK;" << std::endl; - for (int j = 0; j < execContent.size(); j++) { - writeExecContent(stream, Element<std::string>(execContent[j]), 1); - } - stream << " return SCXML_ERR_OK;" << std::endl; - stream << "}" << std::endl; - stream << std::endl; - } - } + for (int i = 0; i < _states.size(); i++) { + Element<std::string> state(_states[i]); + + if (i == 0) { + // root state - we need to perform some initialization here + NodeSet<std::string> globalScripts = filterChildElements(_nsInfo.xmlNSPrefix + "script", state); + if (globalScripts.size() > 0) { + _hasGlobalScripts = true; + for (int j = 0; j < globalScripts.size(); j++) { + stream << "static int global_script_" << toStr(j) << "(const scxml_ctx* ctx, const scxml_state* state, const void* event) {" << std::endl; + stream << " int err = SCXML_ERR_OK;" << std::endl; + writeExecContent(stream, globalScripts[j], 1); + stream << " return SCXML_ERR_OK;" << std::endl; + stream << "}" << std::endl; + } + + stream << "static int global_script(const scxml_ctx* ctx, const scxml_state* state, const void* event) {" << std::endl; + for (int j = 0; j < globalScripts.size(); j++) { + stream << " global_script_" << toStr(j) << "(ctx, state, event);" << std::endl; + } + stream << " return SCXML_ERR_OK;" << std::endl; + stream << "}" << std::endl; + stream << std::endl; + } else { + _hasGlobalScripts = false; + } + } + + NodeSet<std::string> onexit = filterChildElements(_nsInfo.xmlNSPrefix + "onexit", state); + for (int j = 0; j < onexit.size(); j++) { + stream << "static int " << DOMUtils::idForNode(state) << "_on_exit_" << toStr(j) << "(const scxml_ctx* ctx, const scxml_state* state, const void* event) {" << std::endl; + stream << " int err = SCXML_ERR_OK;" << std::endl; + writeExecContent(stream, onexit[j], 1); + stream << " return SCXML_ERR_OK;" << std::endl; + stream << "}" << std::endl; + stream << std::endl; + } + + if (onexit.size() > 0) { + stream << "static int " << DOMUtils::idForNode(state) << "_on_exit(const scxml_ctx* ctx, const scxml_state* state, const void* event) {" << std::endl; + for (int j = 0; j < onexit.size(); j++) { + stream << " " << DOMUtils::idForNode(state) << "_on_exit_" << toStr(j) << "(ctx, state, event);" << std::endl; + } + stream << " return SCXML_ERR_OK;" << std::endl; + stream << "}" << std::endl; + stream << std::endl; + } + + + NodeSet<std::string> onentry = filterChildElements(_nsInfo.xmlNSPrefix + "onentry", state); + for (int j = 0; j < onentry.size(); j++) { + stream << "static int " << DOMUtils::idForNode(state) << "_on_entry_" << toStr(j) << "(const scxml_ctx* ctx, const scxml_state* state, const void* event) {" << std::endl; + stream << " int err = SCXML_ERR_OK;" << std::endl; + writeExecContent(stream, onentry[j], 1); + stream << " return SCXML_ERR_OK;" << std::endl; + stream << "}" << std::endl; + stream << std::endl; + } + + bool hasInitialState = false; + NodeSet<std::string> initial = filterChildElements(_nsInfo.xmlNSPrefix + "initial", state); + if (initial.size() > 0) { + NodeSet<std::string> initialTransition = filterChildElements(_nsInfo.xmlNSPrefix + "transition", initial); + if (initialTransition.size() > 0) { + hasInitialState = true; + stream << "static int " << DOMUtils::idForNode(state) << "_initial" << "(const scxml_ctx* ctx, const scxml_state* state, const void* event) {" << std::endl; + stream << " int err = SCXML_ERR_OK;" << std::endl; + writeExecContent(stream, initialTransition[0], 1); + stream << " return SCXML_ERR_OK;" << std::endl; + stream << "}" << std::endl; + stream << std::endl; + } + } + + + if (onentry.size() > 0) { + stream << "static int " << DOMUtils::idForNode(state) << "_on_entry(const scxml_ctx* ctx, const scxml_state* state, const void* event) {" << std::endl; + for (int j = 0; j < onentry.size(); j++) { + stream << " " << DOMUtils::idForNode(state) << "_on_entry_" << toStr(j) << "(ctx, state, event);" << std::endl; + } + if (hasInitialState) { + stream << " " << DOMUtils::idForNode(state) << "_initial" << "(ctx, state, event);" << std::endl; + } + + stream << " return SCXML_ERR_OK;" << std::endl; + stream << "}" << std::endl; + stream << std::endl; + } + + + NodeSet<std::string> invoke = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", state); + if (invoke.size() > 0) { + stream << "static int " << DOMUtils::idForNode(state) << "_invoke(const scxml_ctx* ctx, const scxml_state* s, const scxml_invoke* x) {" << std::endl; + for (int j = 0; j < invoke.size(); j++) { + stream << " ctx->invoke(ctx, s, x);" << std::endl; + stream << " return SCXML_ERR_OK;" << std::endl; + stream << std::endl; + } + stream << "}" << std::endl; + } + } + + for (int i = 0; i < _transitions.size(); i++) { + Element<std::string> transition(_transitions[i]); + if (iequals(TAGNAME_CAST(transition.getParentNode()), "initial")) + continue; + + NodeSet<std::string> execContent = filterChildType(Node_base::ELEMENT_NODE, transition); + + if (execContent.size() > 0) { + stream << "static int " << DOMUtils::idForNode(transition) << "_on_trans(const scxml_ctx* ctx, const scxml_state* state, const void* event) {" << std::endl; + stream << " int err = SCXML_ERR_OK;" << std::endl; + for (int j = 0; j < execContent.size(); j++) { + writeExecContent(stream, Element<std::string>(execContent[j]), 1); + } + stream << " return SCXML_ERR_OK;" << std::endl; + stream << "}" << std::endl; + stream << std::endl; + } + } } void ChartToC::writeExecContent(std::ostream& stream, const Arabica::DOM::Node<std::string>& node, int indent) { - if (!node) - return; - - if (node.getNodeType() == Node_base::TEXT_NODE) { - if (boost::trim_copy(node.getNodeValue()).length() > 0) { - std::string escaped = escape(node.getNodeValue()); - stream << escaped; - } - return; - } - - std::string padding; - for (int i = 0; i < indent; i++) { - padding += " "; - } - - - if (node.getNodeType() != Node_base::ELEMENT_NODE) - return; // skip anything not an element - - Arabica::DOM::Element<std::string> elem = Arabica::DOM::Element<std::string>(node); - - if (false) { - } else if(TAGNAME(elem) == "onentry" || TAGNAME(elem) == "onexit" || TAGNAME(elem) == "transition" || TAGNAME(elem) == "finalize") { - // descent into childs and write their contents - Arabica::DOM::Node<std::string> child = node.getFirstChild(); - while(child) { - writeExecContent(stream, child, indent); - child = child.getNextSibling(); - } - } else if(TAGNAME(elem) == "script") { - stream << padding; - stream << "if likely(ctx->exec_content_script != NULL) {" << std::endl; - stream << padding; - stream << " if unlikely((err = ctx->exec_content_script(ctx, "; - stream << (HAS_ATTR(elem, "src") ? "\"" + escape(ATTR(elem, "src")) + "\"" : "NULL") << ", "; - - NodeSet<std::string> scriptTexts = filterChildType(Node_base::TEXT_NODE, elem); - if (scriptTexts.size() > 0) { - stream << "\""; - writeExecContent(stream, scriptTexts[0], 0); - stream << "\""; - } else { - stream << "NULL"; - } - - stream << ")) != SCXML_ERR_OK) return err;" << std::endl; - stream << padding << "} else {" << std::endl; - stream << padding << " return SCXML_ERR_MISSING_CALLBACK;" << std::endl; - stream << padding << "}" << std::endl; - - } else if(TAGNAME(elem) == "log") { - stream << padding; - stream << "if likely(ctx->exec_content_log != NULL) {" << std::endl; - stream << padding; - stream << " if unlikely((ctx->exec_content_log(ctx, "; - stream << (HAS_ATTR(elem, "label") ? "\"" + escape(ATTR(elem, "label")) + "\"" : "NULL") << ", "; - stream << (HAS_ATTR(elem, "expr") ? "\"" + escape(ATTR(elem, "expr")) + "\"" : "NULL"); - stream << ")) != SCXML_ERR_OK) return err;" << std::endl; - stream << padding << "} else {" << std::endl; - stream << padding << " return SCXML_ERR_MISSING_CALLBACK;" << std::endl; - stream << padding << "}" << std::endl; - - } else if(TAGNAME(elem) == "foreach") { - stream << padding << "if likely(ctx->exec_content_foreach_init != NULL &&" << std::endl; - stream << padding << " ctx->exec_content_foreach_next != NULL &&" << std::endl; - stream << padding << " ctx->exec_content_foreach_done != NULL) {" << std::endl; - stream << std::endl; - - stream << padding << " if unlikely((ctx->exec_content_foreach_init(ctx, &scxml_elem_foreachs[" << ATTR(elem, "documentOrder") << "])) != SCXML_ERR_OK) return err;" << std::endl; - stream << padding << " while (ctx->exec_content_foreach_next(ctx, &scxml_elem_foreachs[" << ATTR(elem, "documentOrder") << "]) == SCXML_ERR_OK) {" << std::endl; - Arabica::DOM::Node<std::string> child = node.getFirstChild(); - while(child) { - writeExecContent(stream, child, indent + 2); - child = child.getNextSibling(); - } - stream << padding << " }" << std::endl; - stream << padding << " if ((ctx->exec_content_foreach_done(ctx, &scxml_elem_foreachs[" << ATTR(elem, "documentOrder") << "])) != SCXML_ERR_OK) return err;" << std::endl; - stream << padding << "} else {" << std::endl; - stream << padding << " return SCXML_ERR_MISSING_CALLBACK;" << std::endl; - stream << padding << "}" << std::endl; - - } else if(TAGNAME(elem) == "if") { - stream << padding; - stream << "if likely(ctx->is_true != NULL) {" << std::endl; - stream << padding; - stream << " if (ctx->is_true(ctx, " << (HAS_ATTR(elem, "cond") ? "\"" + escape(ATTR(elem, "cond")) + "\"" : "NULL") << ")) {" << std::endl; - Arabica::DOM::Node<std::string> child = elem.getFirstChild(); - while(child) { - if (child.getNodeType() == Node_base::ELEMENT_NODE && TAGNAME_CAST(child) == "elseif") { - stream << padding; - stream << " } else if (ctx->is_true(ctx, " << (HAS_ATTR_CAST(child, "cond") ? "\"" + escape(ATTR_CAST(child, "cond")) + "\"" : "NULL") << ")) {" << std::endl; - } else if (child.getNodeType() == Node_base::ELEMENT_NODE && TAGNAME_CAST(child) == "else") { - stream << padding; - stream << " } else {" << std::endl; - } else { - writeExecContent(stream, child, indent + 2); - } - child = child.getNextSibling(); - } - stream << padding << " }" << std::endl; - stream << padding << "} else {" << std::endl; - stream << padding << " return SCXML_ERR_MISSING_CALLBACK;" << std::endl; - stream << padding << "}" << std::endl; - - } else if(TAGNAME(elem) == "assign") { - stream << padding; - stream << "if likely(ctx->exec_content_assign != NULL) {" << std::endl; - stream << padding; - stream << " if ((ctx->exec_content_assign(ctx, "; - stream << (HAS_ATTR(elem, "location") ? "\"" + escape(ATTR(elem, "location")) + "\"" : "NULL") << ", "; - if (HAS_ATTR(elem, "expr")) { - stream << "\"" + escape(ATTR(elem, "expr")) + "\""; - } else { - NodeSet<std::string> assignTexts = filterChildType(Node_base::TEXT_NODE, elem); - if (assignTexts.size() > 0) { - stream << "\""; - writeExecContent(stream, assignTexts[0], 0); - stream << "\""; - } else { - stream << "NULL"; - } - } - stream << ")) != SCXML_ERR_OK) return err;" << std::endl; - stream << padding << "} else {" << std::endl; - stream << padding << " return SCXML_ERR_MISSING_CALLBACK;" << std::endl; - stream << padding << "}" << std::endl; - - - } else if(TAGNAME(elem) == "raise") { - stream << padding; - stream << "if likely(ctx->exec_content_raise != NULL) {" << std::endl; - stream << padding; - stream << " if unlikely((ctx->exec_content_raise(ctx, "; - stream << (HAS_ATTR(elem, "event") ? "\"" + escape(ATTR(elem, "event")) + "\"" : "NULL"); - stream << ")) != SCXML_ERR_OK) return err;" << std::endl; - stream << padding << "} else {" << std::endl; - stream << padding << " return SCXML_ERR_MISSING_CALLBACK;" << std::endl; - stream << padding << "}" << std::endl; - - } else if(TAGNAME(elem) == "send") { - stream << padding; - stream << "if likely(ctx->exec_content_send != NULL) {" << std::endl; - stream << padding; - stream << " if ((ctx->exec_content_send(ctx, &scxml_elem_sends[" << ATTR(elem, "documentOrder") << "]"; - stream << ")) != SCXML_ERR_OK) return err;" << std::endl; - stream << padding << "} else {" << std::endl; - stream << padding << " return SCXML_ERR_MISSING_CALLBACK;" << std::endl; - stream << padding << "}" << std::endl; - - } else if(TAGNAME(elem) == "cancel") { - stream << padding; - stream << "if likely(ctx->exec_content_cancel != NULL) {" << std::endl; - stream << padding; - stream << " if ((ctx->exec_content_cancel(ctx, "; - stream << (HAS_ATTR(elem, "sendid") ? "\"" + escape(ATTR(elem, "sendid")) + "\"" : "NULL") << ", "; - stream << (HAS_ATTR(elem, "sendidexpr") ? "\"" + escape(ATTR(elem, "sendidexpr")) + "\"" : "NULL"); - stream << ")) != SCXML_ERR_OK) return err;" << std::endl; - stream << padding << "} else {" << std::endl; - stream << padding << " return SCXML_ERR_MISSING_CALLBACK;" << std::endl; - stream << padding << "}" << std::endl; - - } else { - std::cerr << "'" << TAGNAME(elem) << "'" << std::endl << elem << std::endl; - assert(false); - } + if (!node) + return; + + if (node.getNodeType() == Node_base::TEXT_NODE) { + if (boost::trim_copy(node.getNodeValue()).length() > 0) { + std::string escaped = escape(node.getNodeValue()); + stream << escaped; + } + return; + } + + std::string padding; + for (int i = 0; i < indent; i++) { + padding += " "; + } + + + if (node.getNodeType() != Node_base::ELEMENT_NODE) + return; // skip anything not an element + + Arabica::DOM::Element<std::string> elem = Arabica::DOM::Element<std::string>(node); + + if (false) { + } else if(TAGNAME(elem) == "onentry" || TAGNAME(elem) == "onexit" || TAGNAME(elem) == "transition" || TAGNAME(elem) == "finalize") { + // descent into childs and write their contents + Arabica::DOM::Node<std::string> child = node.getFirstChild(); + while(child) { + writeExecContent(stream, child, indent); + child = child.getNextSibling(); + } + } else if(TAGNAME(elem) == "script") { + stream << padding; + stream << "if likely(ctx->exec_content_script != NULL) {" << std::endl; + stream << padding; + stream << " if unlikely((err = ctx->exec_content_script(ctx, "; + stream << (HAS_ATTR(elem, "src") ? "\"" + escape(ATTR(elem, "src")) + "\"" : "NULL") << ", "; + + NodeSet<std::string> scriptTexts = filterChildType(Node_base::TEXT_NODE, elem); + if (scriptTexts.size() > 0) { + stream << "\""; + writeExecContent(stream, scriptTexts[0], 0); + stream << "\""; + } else { + stream << "NULL"; + } + + stream << ")) != SCXML_ERR_OK) return err;" << std::endl; + stream << padding << "} else {" << std::endl; + stream << padding << " return SCXML_ERR_MISSING_CALLBACK;" << std::endl; + stream << padding << "}" << std::endl; + + } else if(TAGNAME(elem) == "log") { + stream << padding; + stream << "if likely(ctx->exec_content_log != NULL) {" << std::endl; + stream << padding; + stream << " if unlikely((ctx->exec_content_log(ctx, "; + stream << (HAS_ATTR(elem, "label") ? "\"" + escape(ATTR(elem, "label")) + "\"" : "NULL") << ", "; + stream << (HAS_ATTR(elem, "expr") ? "\"" + escape(ATTR(elem, "expr")) + "\"" : "NULL"); + stream << ")) != SCXML_ERR_OK) return err;" << std::endl; + stream << padding << "} else {" << std::endl; + stream << padding << " return SCXML_ERR_MISSING_CALLBACK;" << std::endl; + stream << padding << "}" << std::endl; + + } else if(TAGNAME(elem) == "foreach") { + stream << padding << "if likely(ctx->exec_content_foreach_init != NULL &&" << std::endl; + stream << padding << " ctx->exec_content_foreach_next != NULL &&" << std::endl; + stream << padding << " ctx->exec_content_foreach_done != NULL) {" << std::endl; + stream << std::endl; + + stream << padding << " if unlikely((ctx->exec_content_foreach_init(ctx, &scxml_elem_foreachs[" << ATTR(elem, "documentOrder") << "])) != SCXML_ERR_OK) return err;" << std::endl; + stream << padding << " while (ctx->exec_content_foreach_next(ctx, &scxml_elem_foreachs[" << ATTR(elem, "documentOrder") << "]) == SCXML_ERR_OK) {" << std::endl; + Arabica::DOM::Node<std::string> child = node.getFirstChild(); + while(child) { + writeExecContent(stream, child, indent + 2); + child = child.getNextSibling(); + } + stream << padding << " }" << std::endl; + stream << padding << " if ((ctx->exec_content_foreach_done(ctx, &scxml_elem_foreachs[" << ATTR(elem, "documentOrder") << "])) != SCXML_ERR_OK) return err;" << std::endl; + stream << padding << "} else {" << std::endl; + stream << padding << " return SCXML_ERR_MISSING_CALLBACK;" << std::endl; + stream << padding << "}" << std::endl; + + } else if(TAGNAME(elem) == "if") { + stream << padding; + stream << "if likely(ctx->is_true != NULL) {" << std::endl; + stream << padding; + stream << " if (ctx->is_true(ctx, " << (HAS_ATTR(elem, "cond") ? "\"" + escape(ATTR(elem, "cond")) + "\"" : "NULL") << ")) {" << std::endl; + Arabica::DOM::Node<std::string> child = elem.getFirstChild(); + while(child) { + if (child.getNodeType() == Node_base::ELEMENT_NODE && TAGNAME_CAST(child) == "elseif") { + stream << padding; + stream << " } else if (ctx->is_true(ctx, " << (HAS_ATTR_CAST(child, "cond") ? "\"" + escape(ATTR_CAST(child, "cond")) + "\"" : "NULL") << ")) {" << std::endl; + } else if (child.getNodeType() == Node_base::ELEMENT_NODE && TAGNAME_CAST(child) == "else") { + stream << padding; + stream << " } else {" << std::endl; + } else { + writeExecContent(stream, child, indent + 2); + } + child = child.getNextSibling(); + } + stream << padding << " }" << std::endl; + stream << padding << "} else {" << std::endl; + stream << padding << " return SCXML_ERR_MISSING_CALLBACK;" << std::endl; + stream << padding << "}" << std::endl; + + } else if(TAGNAME(elem) == "assign") { + stream << padding; + stream << "if likely(ctx->exec_content_assign != NULL) {" << std::endl; + stream << padding; + stream << " if ((ctx->exec_content_assign(ctx, "; + stream << (HAS_ATTR(elem, "location") ? "\"" + escape(ATTR(elem, "location")) + "\"" : "NULL") << ", "; + if (HAS_ATTR(elem, "expr")) { + stream << "\"" + escape(ATTR(elem, "expr")) + "\""; + } else { + NodeSet<std::string> assignTexts = filterChildType(Node_base::TEXT_NODE, elem); + if (assignTexts.size() > 0) { + stream << "\""; + writeExecContent(stream, assignTexts[0], 0); + stream << "\""; + } else { + stream << "NULL"; + } + } + stream << ")) != SCXML_ERR_OK) return err;" << std::endl; + stream << padding << "} else {" << std::endl; + stream << padding << " return SCXML_ERR_MISSING_CALLBACK;" << std::endl; + stream << padding << "}" << std::endl; + + + } else if(TAGNAME(elem) == "raise") { + stream << padding; + stream << "if likely(ctx->exec_content_raise != NULL) {" << std::endl; + stream << padding; + stream << " if unlikely((ctx->exec_content_raise(ctx, "; + stream << (HAS_ATTR(elem, "event") ? "\"" + escape(ATTR(elem, "event")) + "\"" : "NULL"); + stream << ")) != SCXML_ERR_OK) return err;" << std::endl; + stream << padding << "} else {" << std::endl; + stream << padding << " return SCXML_ERR_MISSING_CALLBACK;" << std::endl; + stream << padding << "}" << std::endl; + + } else if(TAGNAME(elem) == "send") { + stream << padding; + stream << "if likely(ctx->exec_content_send != NULL) {" << std::endl; + stream << padding; + stream << " if ((ctx->exec_content_send(ctx, &scxml_elem_sends[" << ATTR(elem, "documentOrder") << "]"; + stream << ")) != SCXML_ERR_OK) return err;" << std::endl; + stream << padding << "} else {" << std::endl; + stream << padding << " return SCXML_ERR_MISSING_CALLBACK;" << std::endl; + stream << padding << "}" << std::endl; + + } else if(TAGNAME(elem) == "cancel") { + stream << padding; + stream << "if likely(ctx->exec_content_cancel != NULL) {" << std::endl; + stream << padding; + stream << " if ((ctx->exec_content_cancel(ctx, "; + stream << (HAS_ATTR(elem, "sendid") ? "\"" + escape(ATTR(elem, "sendid")) + "\"" : "NULL") << ", "; + stream << (HAS_ATTR(elem, "sendidexpr") ? "\"" + escape(ATTR(elem, "sendidexpr")) + "\"" : "NULL"); + stream << ")) != SCXML_ERR_OK) return err;" << std::endl; + stream << padding << "} else {" << std::endl; + stream << padding << " return SCXML_ERR_MISSING_CALLBACK;" << std::endl; + stream << padding << "}" << std::endl; + + } else { + std::cerr << "'" << TAGNAME(elem) << "'" << std::endl << elem << std::endl; + assert(false); + } } void ChartToC::writeElementInfo(std::ostream& stream) { - NodeSet<std::string> foreachs = filterChildElements(_nsInfo.xmlNSPrefix + "foreach", _scxml, true); - if (foreachs.size() > 0) { - stream << "static scxml_elem_foreach scxml_elem_foreachs[" << foreachs.size() << "] = {" << std::endl; - for (int i = 0; i < foreachs.size(); i++) { - Element<std::string> foreach(foreachs[i]); - stream << " { "; - stream << (HAS_ATTR(foreach, "array") ? "\"" + escape(ATTR(foreach, "array")) + "\"" : "NULL") << ", "; - stream << (HAS_ATTR(foreach, "item") ? "\"" + escape(ATTR(foreach, "item")) + "\"" : "NULL") << ", "; - stream << (HAS_ATTR(foreach, "index") ? "\"" + escape(ATTR(foreach, "index")) + "\"" : "NULL"); - stream << " }" << (i + 1 < foreachs.size() ? ",": "") << std::endl; - foreach.setAttribute("documentOrder", toStr(i)); - } - stream << "};" << std::endl; - stream << std::endl; - } - - NodeSet<std::string> datas = filterChildElements(_nsInfo.xmlNSPrefix + "data", _scxml, true); - if (datas.size() > 0) { - size_t dataIndexOffset = 0; - Node<std::string> parent; - size_t distinctParents = 0; - - if (_binding == InterpreterImpl::EARLY) { - Element<std::string>(_states[0]).setAttribute("dataIndex", "0"); - distinctParents = 1; - } else { - for (int i = 0; i < datas.size(); i++) { - Element<std::string> data(datas[i]); - if (data.getParentNode() != parent) { - distinctParents++; - } - } - } - - parent = Node<std::string>(); - - stream << "static scxml_elem_data scxml_elem_datas[" << datas.size() + distinctParents << "] = {" << std::endl; - for (int i = 0; i < datas.size(); i++) { - Element<std::string> data(datas[i]); - if (data.getParentNode().getParentNode() != parent) { - if (_binding == InterpreterImpl::LATE) { - if (i > 0) { - stream << " { NULL, NULL, NULL, NULL }," << std::endl; - dataIndexOffset++; - } - Element<std::string>(data.getParentNode().getParentNode()).setAttribute("dataIndex", toStr(i + dataIndexOffset)); - } - parent = data.getParentNode().getParentNode(); - } - stream << " { "; - stream << (HAS_ATTR(data, "id") ? "\"" + escape(ATTR(data, "id")) + "\"" : "NULL") << ", "; - stream << (HAS_ATTR(data, "src") ? "\"" + escape(ATTR(data, "src")) + "\"" : "NULL") << ", "; - stream << (HAS_ATTR(data, "expr") ? "\"" + escape(ATTR(data, "expr")) + "\"" : "NULL") << ", "; - - NodeSet<std::string> dataTexts = filterChildType(Node_base::TEXT_NODE, data); - if (dataTexts.size() > 0) { - if (boost::trim_copy(dataTexts[0].getNodeValue()).length() > 0) { - std::string escaped = escape(dataTexts[0].getNodeValue()); - stream << "\"" << escaped << "\"" << std::endl; - } - } else { - stream << "NULL"; - } - stream << " }," << std::endl; - - } - stream << " { NULL, NULL, NULL, NULL }" << std::endl; - stream << "};" << std::endl; - stream << std::endl; - } - - NodeSet<std::string> params = filterChildElements(_nsInfo.xmlNSPrefix + "param", _scxml, true); - if (params.size() > 0) { - Node<std::string> parent; - size_t distinctParents = 0; - for (int i = 0; i < params.size(); i++) { - Element<std::string> param(params[i]); - if (param.getParentNode() != parent) { - distinctParents++; - } - } - parent = Node<std::string>(); - - stream << "static scxml_elem_param scxml_elem_params[" << params.size() + distinctParents << "] = {" << std::endl; - for (int i = 0; i < params.size(); i++) { - Element<std::string> param(params[i]); - if (param.getParentNode() != parent) { - Element<std::string>(param.getParentNode()).setAttribute("paramIndex", toStr(i)); - if (i > 0) { - stream << " { NULL, NULL, NULL }," << std::endl; - } - parent = param.getParentNode(); - } - stream << " { "; - stream << (HAS_ATTR(param, "name") ? "\"" + escape(ATTR(param, "name")) + "\"" : "NULL") << ", "; - stream << (HAS_ATTR(param, "expr") ? "\"" + escape(ATTR(param, "expr")) + "\"" : "NULL") << ", "; - stream << (HAS_ATTR(param, "location") ? "\"" + escape(ATTR(param, "location")) + "\"" : "NULL"); - stream << " }," << std::endl; - - } - stream << " { NULL, NULL, NULL }" << std::endl; - stream << "};" << std::endl; - stream << std::endl; - } - - NodeSet<std::string> sends = filterChildElements(_nsInfo.xmlNSPrefix + "send", _scxml, true); - if (sends.size() > 0) { - stream << "static scxml_elem_send scxml_elem_sends[" << sends.size() << "] = {" << std::endl; - for (int i = 0; i < sends.size(); i++) { - Element<std::string> send(sends[i]); - stream << " { "; - stream << (HAS_ATTR(send, "event") ? "\"" + escape(ATTR(send, "event")) + "\"" : "NULL") << ", "; - stream << (HAS_ATTR(send, "eventexpr") ? "\"" + escape(ATTR(send, "eventexpr")) + "\"" : "NULL") << ", "; - stream << (HAS_ATTR(send, "target") ? "\"" + escape(ATTR(send, "target")) + "\"" : "NULL") << ", "; - stream << (HAS_ATTR(send, "targetexpr") ? "\"" + escape(ATTR(send, "targetexpr")) + "\"" : "NULL") << ", "; - stream << (HAS_ATTR(send, "type") ? "\"" + escape(ATTR(send, "type")) + "\"" : "NULL") << ", "; - stream << (HAS_ATTR(send, "typeexpr") ? "\"" + escape(ATTR(send, "typeexpr")) + "\"" : "NULL") << ", "; - stream << (HAS_ATTR(send, "id") ? "\"" + escape(ATTR(send, "id")) + "\"" : "NULL") << ", "; - stream << (HAS_ATTR(send, "idlocation") ? "\"" + escape(ATTR(send, "idlocation")) + "\"" : "NULL") << ", "; - stream << (HAS_ATTR(send, "delay") ? "\"" + escape(ATTR(send, "delay")) + "\"" : "NULL") << ", "; - stream << (HAS_ATTR(send, "delayexpr") ? "\"" + escape(ATTR(send, "delayexpr")) + "\"" : "NULL") << ", "; - stream << (HAS_ATTR(send, "namelist") ? "\"" + escape(ATTR(send, "namelist")) + "\"" : "NULL") << ", "; - - NodeSet<std::string> contents = filterChildElements(_nsInfo.xmlNSPrefix + "content", send); - if (contents.size() > 0) { - std::stringstream ss; - NodeList<std::string> cChilds = contents[0].getChildNodes(); - for (int j = 0; j < cChilds.getLength(); j++) { - ss << cChilds.item(j); - } - stream << (ss.str().size() > 0 ? "\"" + escape(ss.str()) + "\", " : "NULL, "); - stream << (HAS_ATTR_CAST(contents[0], "expr") ? "\"" + ATTR_CAST(contents[0], "expr") + "\", " : "NULL, "); - } else { - stream << "NULL, NULL, "; - } - - - if (HAS_ATTR(send, "paramIndex")) { - stream << "(const scxml_elem_param*)&scxml_elem_params[" << escape(ATTR(send, "paramIndex")) << "], "; - } else { - stream << "NULL, "; - } - stream << "NULL"; - - stream << " }" << (i + 1 < sends.size() ? ",": "") << std::endl; - send.setAttribute("documentOrder", toStr(i)); - } - stream << "};" << std::endl; - stream << std::endl; - } - - NodeSet<std::string> donedatas = filterChildElements(_nsInfo.xmlNSPrefix + "donedata", _scxml, true); - if (donedatas.size() > 0) { - _hasDoneData = true; - stream << "static scxml_elem_donedata scxml_elem_donedatas[" << donedatas.size() + 1 << "] = {" << std::endl; - for (int i = 0; i < donedatas.size(); i++) { - Element<std::string> donedata(donedatas[i]); - stream << " { "; - - // parent - stream << ATTR_CAST(donedata.getParentNode(), "documentOrder") << ", "; - - NodeSet<std::string> contents = filterChildElements(_nsInfo.xmlNSPrefix + "content", donedata); - if (contents.size() > 0) { - std::stringstream ss; - NodeList<std::string> cChilds = contents[0].getChildNodes(); - for (int j = 0; j < cChilds.getLength(); j++) { - ss << cChilds.item(j); - } - stream << (ss.str().size() > 0 ? "\"" + escape(ss.str()) + "\", " : "NULL, "); - stream << (HAS_ATTR_CAST(contents[0], "expr") ? "\"" + ATTR_CAST(contents[0], "expr") + "\", " : "NULL, "); - } else { - stream << "NULL, NULL, "; - } - - if (HAS_ATTR(donedata, "paramIndex")) { - stream << "(const scxml_elem_param*)&scxml_elem_params[" << escape(ATTR(donedata, "paramIndex")) << "]"; - } else { - stream << "NULL"; - } - - stream << " }," << std::endl; - donedata.setAttribute("documentOrder", toStr(i)); - } - stream << " { 0, NULL, NULL }" << std::endl; - stream << "};" << std::endl; - stream << std::endl; - } else { - _hasDoneData = false; - } + NodeSet<std::string> foreachs = filterChildElements(_nsInfo.xmlNSPrefix + "foreach", _scxml, true); + if (foreachs.size() > 0) { + stream << "static scxml_elem_foreach scxml_elem_foreachs[" << foreachs.size() << "] = {" << std::endl; + for (int i = 0; i < foreachs.size(); i++) { + Element<std::string> foreach(foreachs[i]); + stream << " { "; + stream << (HAS_ATTR(foreach, "array") ? "\"" + escape(ATTR(foreach, "array")) + "\"" : "NULL") << ", "; + stream << (HAS_ATTR(foreach, "item") ? "\"" + escape(ATTR(foreach, "item")) + "\"" : "NULL") << ", "; + stream << (HAS_ATTR(foreach, "index") ? "\"" + escape(ATTR(foreach, "index")) + "\"" : "NULL"); + stream << " }" << (i + 1 < foreachs.size() ? ",": "") << std::endl; + foreach.setAttribute("documentOrder", toStr(i)); + } + stream << "};" << std::endl; + stream << std::endl; + } + + NodeSet<std::string> datas = filterChildElements(_nsInfo.xmlNSPrefix + "data", _scxml, true); + if (datas.size() > 0) { + size_t dataIndexOffset = 0; + Node<std::string> parent; + size_t distinctParents = 0; + + if (_binding == InterpreterImpl::EARLY) { + Element<std::string>(_states[0]).setAttribute("dataIndex", "0"); + distinctParents = 1; + } else { + for (int i = 0; i < datas.size(); i++) { + Element<std::string> data(datas[i]); + if (data.getParentNode() != parent) { + distinctParents++; + } + } + } + + parent = Node<std::string>(); + + stream << "static scxml_elem_data scxml_elem_datas[" << datas.size() + distinctParents << "] = {" << std::endl; + for (int i = 0; i < datas.size(); i++) { + Element<std::string> data(datas[i]); + if (data.getParentNode().getParentNode() != parent) { + if (_binding == InterpreterImpl::LATE) { + if (i > 0) { + stream << " { NULL, NULL, NULL, NULL }," << std::endl; + dataIndexOffset++; + } + Element<std::string>(data.getParentNode().getParentNode()).setAttribute("dataIndex", toStr(i + dataIndexOffset)); + } + parent = data.getParentNode().getParentNode(); + } + stream << " { "; + stream << (HAS_ATTR(data, "id") ? "\"" + escape(ATTR(data, "id")) + "\"" : "NULL") << ", "; + stream << (HAS_ATTR(data, "src") ? "\"" + escape(ATTR(data, "src")) + "\"" : "NULL") << ", "; + stream << (HAS_ATTR(data, "expr") ? "\"" + escape(ATTR(data, "expr")) + "\"" : "NULL") << ", "; + + NodeSet<std::string> dataTexts = filterChildType(Node_base::TEXT_NODE, data); + if (dataTexts.size() > 0) { + if (boost::trim_copy(dataTexts[0].getNodeValue()).length() > 0) { + std::string escaped = escape(dataTexts[0].getNodeValue()); + stream << "\"" << escaped << "\"" << std::endl; + } + } else { + stream << "NULL"; + } + stream << " }," << std::endl; + + } + stream << " { NULL, NULL, NULL, NULL }" << std::endl; + stream << "};" << std::endl; + stream << std::endl; + } + + NodeSet<std::string> params = filterChildElements(_nsInfo.xmlNSPrefix + "param", _scxml, true); + if (params.size() > 0) { + Node<std::string> parent; + size_t distinctParents = 0; + for (int i = 0; i < params.size(); i++) { + Element<std::string> param(params[i]); + if (param.getParentNode() != parent) { + distinctParents++; + } + } + parent = Node<std::string>(); + + stream << "static scxml_elem_param scxml_elem_params[" << params.size() + distinctParents << "] = {" << std::endl; + for (int i = 0; i < params.size(); i++) { + Element<std::string> param(params[i]); + if (param.getParentNode() != parent) { + Element<std::string>(param.getParentNode()).setAttribute("paramIndex", toStr(i)); + if (i > 0) { + stream << " { NULL, NULL, NULL }," << std::endl; + } + parent = param.getParentNode(); + } + stream << " { "; + stream << (HAS_ATTR(param, "name") ? "\"" + escape(ATTR(param, "name")) + "\"" : "NULL") << ", "; + stream << (HAS_ATTR(param, "expr") ? "\"" + escape(ATTR(param, "expr")) + "\"" : "NULL") << ", "; + stream << (HAS_ATTR(param, "location") ? "\"" + escape(ATTR(param, "location")) + "\"" : "NULL"); + stream << " }," << std::endl; + + } + stream << " { NULL, NULL, NULL }" << std::endl; + stream << "};" << std::endl; + stream << std::endl; + } + + NodeSet<std::string> sends = filterChildElements(_nsInfo.xmlNSPrefix + "send", _scxml, true); + if (sends.size() > 0) { + stream << "static scxml_elem_send scxml_elem_sends[" << sends.size() << "] = {" << std::endl; + for (int i = 0; i < sends.size(); i++) { + Element<std::string> send(sends[i]); + stream << " { "; + stream << (HAS_ATTR(send, "event") ? "\"" + escape(ATTR(send, "event")) + "\"" : "NULL") << ", "; + stream << (HAS_ATTR(send, "eventexpr") ? "\"" + escape(ATTR(send, "eventexpr")) + "\"" : "NULL") << ", "; + stream << (HAS_ATTR(send, "target") ? "\"" + escape(ATTR(send, "target")) + "\"" : "NULL") << ", "; + stream << (HAS_ATTR(send, "targetexpr") ? "\"" + escape(ATTR(send, "targetexpr")) + "\"" : "NULL") << ", "; + stream << (HAS_ATTR(send, "type") ? "\"" + escape(ATTR(send, "type")) + "\"" : "NULL") << ", "; + stream << (HAS_ATTR(send, "typeexpr") ? "\"" + escape(ATTR(send, "typeexpr")) + "\"" : "NULL") << ", "; + stream << (HAS_ATTR(send, "id") ? "\"" + escape(ATTR(send, "id")) + "\"" : "NULL") << ", "; + stream << (HAS_ATTR(send, "idlocation") ? "\"" + escape(ATTR(send, "idlocation")) + "\"" : "NULL") << ", "; + stream << (HAS_ATTR(send, "delay") ? "\"" + escape(ATTR(send, "delay")) + "\"" : "NULL") << ", "; + stream << (HAS_ATTR(send, "delayexpr") ? "\"" + escape(ATTR(send, "delayexpr")) + "\"" : "NULL") << ", "; + stream << (HAS_ATTR(send, "namelist") ? "\"" + escape(ATTR(send, "namelist")) + "\"" : "NULL") << ", "; + + NodeSet<std::string> contents = filterChildElements(_nsInfo.xmlNSPrefix + "content", send); + if (contents.size() > 0) { + std::stringstream ss; + NodeList<std::string> cChilds = contents[0].getChildNodes(); + for (int j = 0; j < cChilds.getLength(); j++) { + ss << cChilds.item(j); + } + stream << (ss.str().size() > 0 ? "\"" + escape(ss.str()) + "\", " : "NULL, "); + stream << (HAS_ATTR_CAST(contents[0], "expr") ? "\"" + ATTR_CAST(contents[0], "expr") + "\", " : "NULL, "); + } else { + stream << "NULL, NULL, "; + } + + + if (HAS_ATTR(send, "paramIndex")) { + stream << "(const scxml_elem_param*)&scxml_elem_params[" << escape(ATTR(send, "paramIndex")) << "], "; + } else { + stream << "NULL, "; + } + stream << "NULL"; + + stream << " }" << (i + 1 < sends.size() ? ",": "") << std::endl; + send.setAttribute("documentOrder", toStr(i)); + } + stream << "};" << std::endl; + stream << std::endl; + } + + NodeSet<std::string> donedatas = filterChildElements(_nsInfo.xmlNSPrefix + "donedata", _scxml, true); + if (donedatas.size() > 0) { + _hasDoneData = true; + stream << "static scxml_elem_donedata scxml_elem_donedatas[" << donedatas.size() + 1 << "] = {" << std::endl; + for (int i = 0; i < donedatas.size(); i++) { + Element<std::string> donedata(donedatas[i]); + stream << " { "; + + // parent + stream << ATTR_CAST(donedata.getParentNode(), "documentOrder") << ", "; + + NodeSet<std::string> contents = filterChildElements(_nsInfo.xmlNSPrefix + "content", donedata); + if (contents.size() > 0) { + std::stringstream ss; + NodeList<std::string> cChilds = contents[0].getChildNodes(); + for (int j = 0; j < cChilds.getLength(); j++) { + ss << cChilds.item(j); + } + stream << (ss.str().size() > 0 ? "\"" + escape(ss.str()) + "\", " : "NULL, "); + stream << (HAS_ATTR_CAST(contents[0], "expr") ? "\"" + ATTR_CAST(contents[0], "expr") + "\", " : "NULL, "); + } else { + stream << "NULL, NULL, "; + } + + if (HAS_ATTR(donedata, "paramIndex")) { + stream << "(const scxml_elem_param*)&scxml_elem_params[" << escape(ATTR(donedata, "paramIndex")) << "]"; + } else { + stream << "NULL"; + } + + stream << " }," << std::endl; + donedata.setAttribute("documentOrder", toStr(i)); + } + stream << " { 0, NULL, NULL }" << std::endl; + stream << "};" << std::endl; + stream << std::endl; + } else { + _hasDoneData = false; + } } void ChartToC::writeStates(std::ostream& stream) { - stream << "static scxml_state scxml_states[" << toStr(_states.size()) << "] = {" << std::endl; - for (int i = 0; i < _states.size(); i++) { - Element<std::string> state(_states[i]); - stream << " { "; - - // name - stream << (HAS_ATTR(state, "id") ? "\"" + escape(ATTR(state, "id")) + "\"" : "NULL") << ", "; - - // parent - stream << (i == 0 ? "0" : ATTR_CAST(state.getParentNode(), "documentOrder")) << ", "; - - // onentry - stream << (filterChildElements(_nsInfo.xmlNSPrefix + "onentry", state).size() > 0 ? DOMUtils::idForNode(state) + "_on_entry" : "NULL") << ", "; - - // onexit - stream << (filterChildElements(_nsInfo.xmlNSPrefix + "onexit", state).size() > 0 ? DOMUtils::idForNode(state) + "_on_exit" : "NULL") << ", "; - - // invokers - stream << (filterChildElements(_nsInfo.xmlNSPrefix + "invoke", state).size() > 0 ? DOMUtils::idForNode(state) + "_invoke" : "NULL") << ", "; - - // children - std::string childBools; - std::string childBoolsIdx; - for (int j = 0; j < _states.size(); j++) { - if (_states[j].getParentNode() == state) { - childBools += "1"; - childBoolsIdx += " " + toStr(j); - } else { - childBools += "0"; - } - } - stream << "{ "; - writeCharArrayInitList(stream, childBools); - stream << " /* " << childBools << "," << childBoolsIdx << " */"; - stream << " }, "; - - // default completion - NodeSet<std::string> completion; - if (isHistory(state)) { - bool deep = (HAS_ATTR(state, "type") && iequals(ATTR(state, "type"), "deep")); - for (int j = 0; j < _states.size(); j++) { - if (deep) { - if (isDescendant(_states[j], state.getParentNode()) && !isHistory(Element<std::string>(_states[j]))) { - completion.push_back(_states[j]); - } - } else { - if (_states[j].getParentNode() == state.getParentNode() && !isHistory(Element<std::string>(_states[j]))) { - completion.push_back(_states[j]); - } - } - } - } if (isParallel(state)) { - completion = getChildStates(state); - } else if (state.hasAttribute("initial")) { - completion = getStates(tokenizeIdRefs(state.getAttribute("initial"))); - } else { - NodeSet<std::string> initElems = filterChildElements(_nsInfo.xmlNSPrefix + "initial", state); - if(initElems.size() > 0 && !iequals(ATTR_CAST(initElems[0], "generated"), "true")) { - // initial element is first child - completion.push_back(initElems[0]); - } else { - // first child state - Arabica::XPath::NodeSet<std::string> initStates; - NodeList<std::string> childs = state.getChildNodes(); - for (int i = 0; i < childs.getLength(); i++) { - if (childs.item(i).getNodeType() != Node_base::ELEMENT_NODE) - continue; - if (isState(Element<std::string>(childs.item(i)))) { - completion.push_back(childs.item(i)); - break; - } - } - } - } - - std::string descBools; - std::string descBoolsIdx; - for (int j = 0; j < _states.size(); j++) { - if (isMember(_states[j], completion)) { - descBools += "1"; - descBoolsIdx += " " + toStr(j); - } else { - descBools += "0"; - } - } - stream << "{ "; - writeCharArrayInitList(stream, descBools); - stream << " /* " << descBools << "," << descBoolsIdx << " */"; - stream << " }, "; - - // ancestors - std::string ancBools; - std::string ancBoolsIdx; - for (int j = 0; j < _states.size(); j++) { - if (isDescendant(state, _states[j])) { - ancBools += "1"; - ancBoolsIdx += " " + toStr(j); - } else { - ancBools += "0"; - } - } - stream << "{ "; - writeCharArrayInitList(stream, ancBools); - stream << " /* " << ancBools << "," << ancBoolsIdx << " */"; - stream << " }, "; - - if (HAS_ATTR(state, "dataIndex")) { - stream << "(const scxml_elem_data*)&scxml_elem_datas[" << escape(ATTR(state, "dataIndex")) << "], "; - } else { - stream << "NULL, "; - } - - if (false) { - } else if (iequals(TAGNAME(state), "initial")) { - stream << "SCXML_STATE_INITIAL"; - } else if (isFinal(state)) { - stream << "SCXML_STATE_FINAL"; - } else if (isHistory(state)) { - if (HAS_ATTR(state, "type") && iequals(ATTR(state, "type"), "deep")) { - stream << "SCXML_STATE_HISTORY_DEEP"; - } else { - stream << "SCXML_STATE_HISTORY_SHALLOW"; - } - } else if (isAtomic(state)) { - stream << "SCXML_STATE_ATOMIC"; - } else if (isParallel(state)) { - stream << "SCXML_STATE_PARALLEL"; - } else if (isCompound(state)) { - stream << "SCXML_STATE_COMPOUND"; - } else { // <scxml> - stream << "SCXML_STATE_COMPOUND"; - } - - stream << " }" << (i + 1 < _states.size() ? ",": "") << std::endl; - } - stream << "};" << std::endl; - stream << std::endl; + stream << "static scxml_state scxml_states[" << toStr(_states.size()) << "] = {" << std::endl; + for (int i = 0; i < _states.size(); i++) { + Element<std::string> state(_states[i]); + stream << " { "; + + // name + stream << (HAS_ATTR(state, "id") ? "\"" + escape(ATTR(state, "id")) + "\"" : "NULL") << ", "; + + // parent + stream << (i == 0 ? "0" : ATTR_CAST(state.getParentNode(), "documentOrder")) << ", "; + + // onentry + stream << (filterChildElements(_nsInfo.xmlNSPrefix + "onentry", state).size() > 0 ? DOMUtils::idForNode(state) + "_on_entry" : "NULL") << ", "; + + // onexit + stream << (filterChildElements(_nsInfo.xmlNSPrefix + "onexit", state).size() > 0 ? DOMUtils::idForNode(state) + "_on_exit" : "NULL") << ", "; + + // invokers + stream << (filterChildElements(_nsInfo.xmlNSPrefix + "invoke", state).size() > 0 ? DOMUtils::idForNode(state) + "_invoke" : "NULL") << ", "; + + // children + std::string childBools; + std::string childBoolsIdx; + for (int j = 0; j < _states.size(); j++) { + if (_states[j].getParentNode() == state) { + childBools += "1"; + childBoolsIdx += " " + toStr(j); + } else { + childBools += "0"; + } + } + stream << "{ "; + writeCharArrayInitList(stream, childBools); + stream << " /* " << childBools << "," << childBoolsIdx << " */"; + stream << " }, "; + + // default completion + NodeSet<std::string> completion; + if (isHistory(state)) { + bool deep = (HAS_ATTR(state, "type") && iequals(ATTR(state, "type"), "deep")); + for (int j = 0; j < _states.size(); j++) { + if (deep) { + if (isDescendant(_states[j], state.getParentNode()) && !isHistory(Element<std::string>(_states[j]))) { + completion.push_back(_states[j]); + } + } else { + if (_states[j].getParentNode() == state.getParentNode() && !isHistory(Element<std::string>(_states[j]))) { + completion.push_back(_states[j]); + } + } + } + } + if (isParallel(state)) { + completion = getChildStates(state); + } else if (state.hasAttribute("initial")) { + completion = getStates(tokenizeIdRefs(state.getAttribute("initial"))); + } else { + NodeSet<std::string> initElems = filterChildElements(_nsInfo.xmlNSPrefix + "initial", state); + if(initElems.size() > 0 && !iequals(ATTR_CAST(initElems[0], "generated"), "true")) { + // initial element is first child + completion.push_back(initElems[0]); + } else { + // first child state + Arabica::XPath::NodeSet<std::string> initStates; + NodeList<std::string> childs = state.getChildNodes(); + for (int i = 0; i < childs.getLength(); i++) { + if (childs.item(i).getNodeType() != Node_base::ELEMENT_NODE) + continue; + if (isState(Element<std::string>(childs.item(i)))) { + completion.push_back(childs.item(i)); + break; + } + } + } + } + + std::string descBools; + std::string descBoolsIdx; + for (int j = 0; j < _states.size(); j++) { + if (isMember(_states[j], completion)) { + descBools += "1"; + descBoolsIdx += " " + toStr(j); + } else { + descBools += "0"; + } + } + stream << "{ "; + writeCharArrayInitList(stream, descBools); + stream << " /* " << descBools << "," << descBoolsIdx << " */"; + stream << " }, "; + + // ancestors + std::string ancBools; + std::string ancBoolsIdx; + for (int j = 0; j < _states.size(); j++) { + if (isDescendant(state, _states[j])) { + ancBools += "1"; + ancBoolsIdx += " " + toStr(j); + } else { + ancBools += "0"; + } + } + stream << "{ "; + writeCharArrayInitList(stream, ancBools); + stream << " /* " << ancBools << "," << ancBoolsIdx << " */"; + stream << " }, "; + + if (HAS_ATTR(state, "dataIndex")) { + stream << "(const scxml_elem_data*)&scxml_elem_datas[" << escape(ATTR(state, "dataIndex")) << "], "; + } else { + stream << "NULL, "; + } + + if (false) { + } else if (iequals(TAGNAME(state), "initial")) { + stream << "SCXML_STATE_INITIAL"; + } else if (isFinal(state)) { + stream << "SCXML_STATE_FINAL"; + } else if (isHistory(state)) { + if (HAS_ATTR(state, "type") && iequals(ATTR(state, "type"), "deep")) { + stream << "SCXML_STATE_HISTORY_DEEP"; + } else { + stream << "SCXML_STATE_HISTORY_SHALLOW"; + } + } else if (isAtomic(state)) { + stream << "SCXML_STATE_ATOMIC"; + } else if (isParallel(state)) { + stream << "SCXML_STATE_PARALLEL"; + } else if (isCompound(state)) { + stream << "SCXML_STATE_COMPOUND"; + } else { // <scxml> + stream << "SCXML_STATE_COMPOUND"; + } + + stream << " }" << (i + 1 < _states.size() ? ",": "") << std::endl; + } + stream << "};" << std::endl; + stream << std::endl; } - - + + void ChartToC::writeTransitions(std::ostream& stream) { - stream << "static scxml_transition scxml_transitions[" << toStr(_transitions.size()) << "] = {" << std::endl; - for (int i = 0; i < _transitions.size(); i++) { - Element<std::string> transition(_transitions[i]); - stream << " { "; - - /** - uint16_t source; - target[SCXML_NUMBER_STATES / 8 + 1]; - const char* event; - const char* condition; - exec_content_t on_transition; - uint8_t type; - char conflicts[SCXML_NUMBER_STATES / 8 + 1]; - char exit_set[SCXML_NUMBER_STATES / 8 + 1]; - */ - - // source - stream << ATTR_CAST(transition.getParentNode(), "documentOrder") << ", "; - - // targets - if (HAS_ATTR(transition, "target")) { - std::list<std::string> targets = tokenize(ATTR(transition, "target")); - - std::string targetBools; - for (int j = 0; j < _states.size(); j++) { - Element<std::string> state(_states[j]); - - if (HAS_ATTR(state, "id") && - std::find(targets.begin(), targets.end(), escape(ATTR(state, "id"))) != targets.end()) { - targetBools += "1"; - } else { - targetBools += "0"; - } - } - - stream << "{ "; - writeCharArrayInitList(stream, targetBools); - stream << " /* " << targetBools << " */"; - stream << " }, "; - - } else { - stream << "{ NULL }, "; - } - - // event - stream << (HAS_ATTR(transition, "event") ? "\"" + escape(ATTR(transition, "event")) + "\"" : "NULL") << ", "; - - // condition - stream << (HAS_ATTR(transition, "cond") ? "\"" + escape(ATTR(transition, "cond")) + "\"" : "NULL") << ", "; - - // on transition handlers - if (filterChildType(Arabica::DOM::Node_base::ELEMENT_NODE, transition).size() > 0 && - !iequals(TAGNAME_CAST(transition.getParentNode()), "initial")) { - stream << DOMUtils::idForNode(transition) + "_on_trans, "; - } else { - stream << "NULL, "; - } - - // type - std::string seperator = ""; - if (!HAS_ATTR(transition, "target")) { - stream << seperator << "SCXML_TRANS_TARGETLESS"; - seperator = " | "; - } - - if (HAS_ATTR(transition, "type") && iequals(ATTR(transition, "type"), "internal")) { - stream << seperator << "SCXML_TRANS_INTERNAL"; - seperator = " | "; - } - - if (!HAS_ATTR(transition, "event")) { - stream << seperator << "SCXML_TRANS_SPONTANEOUS"; - seperator = " | "; - } - - if (iequals(TAGNAME_CAST(transition.getParentNode()), "history")) { - stream << seperator << "SCXML_TRANS_HISTORY"; - seperator = " | "; - } - - if (seperator.size() == 0) { - stream << "0"; - } - stream << ", "; - - // conflicts - std::string conflictBools; - for (unsigned int j = 0; j < _transitions.size(); j++) { - Element<std::string> t2(_transitions[j]); - if (hasIntersection(computeExitSet(transition), computeExitSet(t2)) || - (getSourceState(transition) == getSourceState(t2)) || - (isDescendant(getSourceState(transition), getSourceState(t2))) || - (isDescendant(getSourceState(t2), getSourceState(transition)))) { - conflictBools += "1"; - } else { - conflictBools += "0"; - } - } - stream << "{ "; - writeCharArrayInitList(stream, conflictBools); - stream << " /* " << conflictBools << " */"; - stream << " }, "; - - // exit set - std::string exitSetBools; - NodeSet<std::string> exitSet = computeExitSet(transition); - for (unsigned int j = 0; j < _states.size(); j++) { - Element<std::string> state(_states[j]); - if (isMember(state, exitSet)) { - exitSetBools += "1"; - } else { - exitSetBools += "0"; - } - } - stream << "{ "; - writeCharArrayInitList(stream, exitSetBools); - stream << " /* " << exitSetBools << " */"; - stream << " }"; - - stream << " }" << (i + 1 < _transitions.size() ? ",": "") << std::endl; - } - stream << "};" << std::endl; - stream << std::endl; + stream << "static scxml_transition scxml_transitions[" << toStr(_transitions.size()) << "] = {" << std::endl; + for (int i = 0; i < _transitions.size(); i++) { + Element<std::string> transition(_transitions[i]); + stream << " { "; + + /** + uint16_t source; + target[SCXML_NUMBER_STATES / 8 + 1]; + const char* event; + const char* condition; + exec_content_t on_transition; + uint8_t type; + char conflicts[SCXML_NUMBER_STATES / 8 + 1]; + char exit_set[SCXML_NUMBER_STATES / 8 + 1]; + */ + + // source + stream << ATTR_CAST(transition.getParentNode(), "documentOrder") << ", "; + + // targets + if (HAS_ATTR(transition, "target")) { + std::list<std::string> targets = tokenize(ATTR(transition, "target")); + + std::string targetBools; + for (int j = 0; j < _states.size(); j++) { + Element<std::string> state(_states[j]); + + if (HAS_ATTR(state, "id") && + std::find(targets.begin(), targets.end(), escape(ATTR(state, "id"))) != targets.end()) { + targetBools += "1"; + } else { + targetBools += "0"; + } + } + + stream << "{ "; + writeCharArrayInitList(stream, targetBools); + stream << " /* " << targetBools << " */"; + stream << " }, "; + + } else { + stream << "{ NULL }, "; + } + + // event + stream << (HAS_ATTR(transition, "event") ? "\"" + escape(ATTR(transition, "event")) + "\"" : "NULL") << ", "; + + // condition + stream << (HAS_ATTR(transition, "cond") ? "\"" + escape(ATTR(transition, "cond")) + "\"" : "NULL") << ", "; + + // on transition handlers + if (filterChildType(Arabica::DOM::Node_base::ELEMENT_NODE, transition).size() > 0 && + !iequals(TAGNAME_CAST(transition.getParentNode()), "initial")) { + stream << DOMUtils::idForNode(transition) + "_on_trans, "; + } else { + stream << "NULL, "; + } + + // type + std::string seperator = ""; + if (!HAS_ATTR(transition, "target")) { + stream << seperator << "SCXML_TRANS_TARGETLESS"; + seperator = " | "; + } + + if (HAS_ATTR(transition, "type") && iequals(ATTR(transition, "type"), "internal")) { + stream << seperator << "SCXML_TRANS_INTERNAL"; + seperator = " | "; + } + + if (!HAS_ATTR(transition, "event")) { + stream << seperator << "SCXML_TRANS_SPONTANEOUS"; + seperator = " | "; + } + + if (iequals(TAGNAME_CAST(transition.getParentNode()), "history")) { + stream << seperator << "SCXML_TRANS_HISTORY"; + seperator = " | "; + } + + if (seperator.size() == 0) { + stream << "0"; + } + stream << ", "; + + // conflicts + std::string conflictBools; + for (unsigned int j = 0; j < _transitions.size(); j++) { + Element<std::string> t2(_transitions[j]); + if (hasIntersection(computeExitSet(transition), computeExitSet(t2)) || + (getSourceState(transition) == getSourceState(t2)) || + (isDescendant(getSourceState(transition), getSourceState(t2))) || + (isDescendant(getSourceState(t2), getSourceState(transition)))) { + conflictBools += "1"; + } else { + conflictBools += "0"; + } + } + stream << "{ "; + writeCharArrayInitList(stream, conflictBools); + stream << " /* " << conflictBools << " */"; + stream << " }, "; + + // exit set + std::string exitSetBools; + NodeSet<std::string> exitSet = computeExitSet(transition); + for (unsigned int j = 0; j < _states.size(); j++) { + Element<std::string> state(_states[j]); + if (isMember(state, exitSet)) { + exitSetBools += "1"; + } else { + exitSetBools += "0"; + } + } + stream << "{ "; + writeCharArrayInitList(stream, exitSetBools); + stream << " /* " << exitSetBools << " */"; + stream << " }"; + + stream << " }" << (i + 1 < _transitions.size() ? ",": "") << std::endl; + } + stream << "};" << std::endl; + stream << std::endl; } Arabica::XPath::NodeSet<std::string> ChartToC::computeExitSet(const Arabica::DOM::Element<std::string>& transition) { - - NodeSet<std::string> statesToExit; - if (!isTargetless(transition)) { - Arabica::DOM::Node<std::string> domain = getTransitionDomain(transition); - if (!domain) - return statesToExit; - for (unsigned int j = 0; j < _states.size(); j++) { - const Node<std::string>& s = _states[j]; - if (isDescendant(s, domain)) { - statesToExit.push_back(s); - } - } - } - - return statesToExit; + + NodeSet<std::string> statesToExit; + if (!isTargetless(transition)) { + Arabica::DOM::Node<std::string> domain = getTransitionDomain(transition); + if (!domain) + return statesToExit; + for (unsigned int j = 0; j < _states.size(); j++) { + const Node<std::string>& s = _states[j]; + if (isDescendant(s, domain)) { + statesToExit.push_back(s); + } + } + } + + return statesToExit; } void ChartToC::writeCharArrayInitList(std::ostream& stream, const std::string& boolString) { - /** - * 0111 -> 0x08 - * 1111 -> 0x0f - * 1111 1111 -> 0xff - * 1111 1111 1110 -> 0x0f, 0xfd - * - * 76543210 fedcba98 ... - */ - - std::string charArray; - size_t index = 0; - char currChar = 0; - - for (std::string::const_iterator bIter = boolString.begin(); bIter != boolString.end(); bIter++) { - - if (*bIter == '1') { - currChar |= 1 << index; - } - - index++; - if (index == 8) { - charArray += currChar; - currChar = 0; - index = 0; - } - } - - if (index != 0) { - charArray += currChar; - } - - std::string seperator = ""; - for (std::string::const_iterator cIter = charArray.begin(); cIter != charArray.end(); cIter++) { - stream << seperator << "0x" << std::setw(2) << std::setfill('0') << std::hex << int(*cIter & 0xFF); - seperator = ", "; - } + /** + * 0111 -> 0x08 + * 1111 -> 0x0f + * 1111 1111 -> 0xff + * 1111 1111 1110 -> 0x0f, 0xfd + * + * 76543210 fedcba98 ... + */ + + std::string charArray; + size_t index = 0; + char currChar = 0; + + for (std::string::const_iterator bIter = boolString.begin(); bIter != boolString.end(); bIter++) { + + if (*bIter == '1') { + currChar |= 1 << index; + } + + index++; + if (index == 8) { + charArray += currChar; + currChar = 0; + index = 0; + } + } + + if (index != 0) { + charArray += currChar; + } + + std::string seperator = ""; + for (std::string::const_iterator cIter = charArray.begin(); cIter != charArray.end(); cIter++) { + stream << seperator << "0x" << std::setw(2) << std::setfill('0') << std::hex << int(*cIter & 0xFF); + seperator = ", "; + } } void ChartToC::writeFSM(std::ostream& stream) { - stream << "static int scxml_step(scxml_ctx* ctx) {" << std::endl; - stream << std::endl; - - stream << "#ifdef SCXML_VERBOSE" << std::endl; - stream << " printf(\"Config: \");" << std::endl; - stream << " printStateNames(ctx->config);" << std::endl; - stream << "#endif" << std::endl; - stream << std::endl; - - stream << "// MACRO_STEP:" << 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; - stream << " return SCXML_ERR_DONE; " << std::endl; - stream << std::endl; - - stream << " int err = SCXML_ERR_OK;" << std::endl; - stream << " char conflicts[" << _transCharArraySize << "] = " << _transCharArrayInit << ";" << std::endl; - stream << " char target_set[" << _stateCharArraySize << "] = " << _stateCharArrayInit << ";" << std::endl; - 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 << std::endl; - - stream << " void* event;" << std::endl; - stream << " if unlikely(ctx->flags == SCXML_CTX_PRISTINE) {" << std::endl; - if (_hasGlobalScripts) { - stream << " global_script(ctx, &scxml_states[0], NULL);" << std::endl; - } - stream << " bit_or(target_set, scxml_states[0].completion, " << _stateCharArraySize << ");" << std::endl; - stream << " ctx->flags |= SCXML_CTX_SPONTANEOUS | SCXML_CTX_INITIALIZED;" << std::endl; - stream << " goto COMPLETE_CONFIG;" << std::endl; - stream << " }" << std::endl; - stream << std::endl; - - stream << " if (ctx->flags & SCXML_CTX_SPONTANEOUS) {" << std::endl; - stream << " event = NULL;" << std::endl; - stream << " goto SELECT_TRANSITIONS;" << std::endl; - stream << " }" << std::endl; - stream << " if ((event = ctx->dequeue_internal(ctx)) != NULL) {" << std::endl; - stream << " goto SELECT_TRANSITIONS;" << std::endl; - stream << " }" << std::endl; - stream << " if ((event = ctx->dequeue_external(ctx)) != NULL) {" << std::endl; - - stream << " goto SELECT_TRANSITIONS;" << std::endl; - stream << " }" << std::endl; - stream << std::endl; + stream << "static int scxml_step(scxml_ctx* ctx) {" << std::endl; + stream << std::endl; + + stream << "#ifdef SCXML_VERBOSE" << std::endl; + stream << " printf(\"Config: \");" << std::endl; + stream << " printStateNames(ctx->config);" << std::endl; + stream << "#endif" << std::endl; + stream << std::endl; + + stream << "// MACRO_STEP:" << 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; + stream << " return SCXML_ERR_DONE; " << std::endl; + stream << std::endl; + + stream << " int err = SCXML_ERR_OK;" << std::endl; + stream << " char conflicts[" << _transCharArraySize << "] = " << _transCharArrayInit << ";" << std::endl; + stream << " char target_set[" << _stateCharArraySize << "] = " << _stateCharArrayInit << ";" << std::endl; + 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 << std::endl; + + stream << " void* event;" << std::endl; + stream << " if unlikely(ctx->flags == SCXML_CTX_PRISTINE) {" << std::endl; + if (_hasGlobalScripts) { + stream << " global_script(ctx, &scxml_states[0], NULL);" << std::endl; + } + stream << " bit_or(target_set, scxml_states[0].completion, " << _stateCharArraySize << ");" << std::endl; + stream << " ctx->flags |= SCXML_CTX_SPONTANEOUS | SCXML_CTX_INITIALIZED;" << std::endl; + stream << " goto COMPLETE_CONFIG;" << std::endl; + stream << " }" << std::endl; + stream << std::endl; + + stream << " if (ctx->flags & SCXML_CTX_SPONTANEOUS) {" << std::endl; + stream << " event = NULL;" << std::endl; + stream << " goto SELECT_TRANSITIONS;" << std::endl; + stream << " }" << std::endl; + stream << " if ((event = ctx->dequeue_internal(ctx)) != NULL) {" << std::endl; + stream << " goto SELECT_TRANSITIONS;" << std::endl; + stream << " }" << std::endl; + stream << " if ((event = ctx->dequeue_external(ctx)) != NULL) {" << std::endl; + + stream << " goto SELECT_TRANSITIONS;" << std::endl; + stream << " }" << std::endl; + stream << std::endl; // HISTORY TRANSITION IS SELECTED BY ACCIDENT! - - stream << "SELECT_TRANSITIONS:" << std::endl; - stream << " for (int i = 0; i < SCXML_NUMBER_TRANSITIONS; i++) {" << std::endl; - stream << " // never select history or initial transitions automatically" << std::endl; - stream << " if unlikely(scxml_transitions[i].type & (SCXML_TRANS_HISTORY | SCXML_TRANS_HISTORY))" << std::endl; - 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 << " // is it non-conflicting?" << std::endl; - stream << " if (!IS_SET(i, conflicts)) {" << std::endl; - stream << " // is it enabled?" << std::endl; - stream << " if (ctx->is_enabled(ctx, &scxml_transitions[i], event) > 0) {" << std::endl; - stream << " // remember that we found a transition" << std::endl; - stream << " ctx->flags |= SCXML_CTX_TRANSITION_FOUND;" << std::endl; - stream << std::endl; - - stream << " // transitions that are pre-empted" << std::endl; - stream << " bit_or(conflicts, scxml_transitions[i].conflicts, " << _transCharArraySize << ");" << std::endl; - stream << std::endl; - stream << " // states that are directly targeted (resolve as entry-set later)" << std::endl; - stream << " bit_or(target_set, scxml_transitions[i].target, " << _stateCharArraySize << ");" << std::endl; - stream << std::endl; - 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 << " }" << std::endl; - stream << " }" << std::endl; - stream << " }" << std::endl; - stream << " }" << std::endl; - stream << " bit_and(exit_set, ctx->config, " << _stateCharArraySize << ");" << std::endl; - stream << std::endl; - - stream << " if (ctx->flags & SCXML_CTX_TRANSITION_FOUND) {" << std::endl; - stream << " ctx->flags |= SCXML_CTX_SPONTANEOUS;" << std::endl; - stream << " } else {" << std::endl; - stream << " ctx->flags &= ~SCXML_CTX_SPONTANEOUS;" << std::endl; - stream << " // goto MACRO_STEP;" << std::endl; - stream << " return SCXML_ERR_OK;" << std::endl; - stream << " }" << std::endl; - stream << std::endl; - - stream << "#ifdef SCXML_VERBOSE" << std::endl; - stream << " printf(\"Targets: \");" << std::endl; - stream << " printStateNames(target_set);" << std::endl; - stream << "#endif" << std::endl; - stream << std::endl; - - stream << "// REMEMBER_HISTORY:" << std::endl; - stream << " for (int i = 0; i < SCXML_NUMBER_STATES; i++) {" << std::endl; - stream << " if unlikely(scxml_states[i].type == SCXML_STATE_HISTORY_SHALLOW || 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].source, exit_set)) {" << std::endl; - stream << " char history[" << _stateCharArraySize << "] = " << _stateCharArrayInit << ";" << std::endl; - stream << " bit_copy(history, 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 << 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 << " }" << std::endl; - stream << " }" << std::endl; - stream << " }" << std::endl; - - stream << "#ifdef SCXML_VERBOSE" << std::endl; - stream << " printf(\"Exiting: \");" << std::endl; - stream << " printStateNames(exit_set);" << std::endl; - stream << "#endif" << std::endl; - stream << std::endl; - - stream << "#ifdef SCXML_VERBOSE" << std::endl; - stream << " printf(\"History: \");" << std::endl; - stream << " printStateNames(ctx->history);" << std::endl; - stream << "#endif" << std::endl; - stream << std::endl; - - stream << "// EXIT_STATES:" << std::endl; - stream << " for (int i = SCXML_NUMBER_STATES - 1; i >= 0; i--) {" << std::endl; - stream << " if (IS_SET(i, exit_set) && IS_SET(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], event)) != SCXML_ERR_OK)" << std::endl; - stream << " return err;" << std::endl; - stream << " }" << std::endl; - stream << " CLEARBIT(i, ctx->config);" << std::endl; - stream << " }" << std::endl; - stream << " }" << std::endl; - stream << std::endl; - - stream << "COMPLETE_CONFIG:" << std::endl; - stream << " // calculate new entry set" << std::endl; - stream << " bit_copy(entry_set, target_set, " << _stateCharArraySize << ");" << std::endl; - stream << std::endl; - stream << " // iterate for ancestors" << std::endl; - stream << " for (int i = 0; i < SCXML_NUMBER_STATES; i++) {" << std::endl; - stream << " if (IS_SET(i, entry_set)) {" << std::endl; - stream << " bit_or(entry_set, scxml_states[i].ancestors, " << _stateCharArraySize << ");" << std::endl; - stream << " }" << std::endl; - stream << " }" << std::endl; - stream << std::endl; - - stream << "// ADD_DESCENDANTS:" << std::endl; - stream << " // iterate for descendants" << std::endl; - stream << " for (int i = 0; i < SCXML_NUMBER_STATES; i++) {" << std::endl; - stream << " if (IS_SET(i, entry_set)) {" << std::endl; - stream << " switch (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; - stream << " break;" << std::endl; - 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 << " // nothing set for history, look for a default transition or enter parents completion" << std::endl; - stream << " for (int 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 << " break;" << std::endl; - stream << " }" << std::endl; - stream << " }" << std::endl; - stream << " // TODO: enter parents default completion here" << 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 << " }" << std::endl; - stream << " break;" << std::endl; - stream << " }" << std::endl; - stream << " case SCXML_STATE_INITIAL: {" << std::endl; - stream << " for (int 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_or(entry_set, scxml_transitions[j].target, " << _stateCharArraySize << ");" << std::endl; - stream << " // one target may have been above, reestablish completion" << std::endl; - stream << " // goto ADD_DESCENDANTS; // initial will have to be first!" << std::endl; - stream << " }" << std::endl; - stream << " }" << std::endl; - stream << " break;" << std::endl; - stream << " }" << std::endl; - stream << " case SCXML_STATE_COMPOUND: { // we need to check whether one child is already in entry_set" << std::endl; - stream << " if (!bit_has_and(entry_set, scxml_states[i].children, " << _stateCharArraySize << ") &&" << std::endl; - stream << " !bit_has_and(ctx->config, scxml_states[i].children, " << _stateCharArraySize << "))" << std::endl; - stream << " {" << std::endl; - stream << " bit_or(entry_set, scxml_states[i].completion, " << _stateCharArraySize << ");" << std::endl; - stream << " }" << std::endl; - stream << " break;" << std::endl; - stream << " }" << std::endl; - stream << " }" << std::endl; - stream << " }" << std::endl; - stream << " }" << std::endl; - stream << std::endl; - - stream << "#ifdef SCXML_VERBOSE" << std::endl; - stream << " printf(\"Transitions: \");" << std::endl; - stream << " printBitsetIndices(trans_set, sizeof(char) * 8 * " << _transCharArraySize << ");" << std::endl; - stream << "#endif" << std::endl; - stream << std::endl; - - stream << "// TAKE_TRANSITIONS:" << std::endl; - stream << " for (int i = 0; i < SCXML_NUMBER_TRANSITIONS; i++) {" << std::endl; - stream << " if (IS_SET(i, trans_set) && (scxml_transitions[i].type & SCXML_TRANS_HISTORY) == 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; - stream << " &scxml_states[scxml_transitions[i].source]," << std::endl; - stream << " event)) != SCXML_ERR_OK)" << std::endl; - stream << " return err;" << std::endl; - stream << " }" << std::endl; - stream << " }" << std::endl; - stream << " }" << std::endl; - stream << std::endl; - - stream << "#ifdef SCXML_VERBOSE" << std::endl; - stream << " printf(\"Entering: \");" << std::endl; - stream << " printStateNames(entry_set);" << std::endl; - stream << "#endif" << std::endl; - stream << std::endl; - - stream << "// ENTER_STATES:" << std::endl; - stream << " for (int i = 0; i < SCXML_NUMBER_STATES; i++) {" << std::endl; - stream << " if (IS_SET(i, entry_set) && !IS_SET(i, ctx->config)) {" << std::endl; - stream << " // these are no proper states" << std::endl; - stream << " if unlikely(scxml_states[i].type == SCXML_STATE_HISTORY_DEEP ||" << std::endl; - stream << " scxml_states[i].type == SCXML_STATE_HISTORY_SHALLOW ||" << std::endl; - stream << " scxml_states[i].type == SCXML_STATE_INITIAL)" << std::endl; - stream << " continue;" << std::endl; - stream << std::endl; - - stream << " SET_BIT(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 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 << " }" << std::endl; - stream << std::endl; - - stream << " if (scxml_states[i].on_entry != NULL) {" << std::endl; - stream << " if unlikely((err = scxml_states[i].on_entry(ctx, &scxml_states[i], event)) != SCXML_ERR_OK)" << std::endl; - stream << " return err;" << std::endl; - stream << " }" << std::endl; - stream << std::endl; - - stream << " // handle final states" << std::endl; - stream << " if unlikely(scxml_states[i].type == SCXML_STATE_FINAL) {" << std::endl; - stream << " if unlikely(scxml_states[i].ancestors[0] == 0x01) {" << std::endl; - stream << " ctx->flags |= SCXML_CTX_TOP_LEVEL_FINAL;" << std::endl; - stream << " } else {" << std::endl; - stream << " // raise done event" << std::endl; - stream << " size_t parent = 0;" << std::endl; - stream << " for (int j = SCXML_NUMBER_STATES - 1; j >= 0; j--) {" << std::endl; - stream << " // we could trade runtime for memory here by saving the parent index" << std::endl; - stream << " if unlikely(IS_SET(j, scxml_states[i].ancestors)) {" << std::endl; - stream << " parent = j;" << std::endl; - stream << " break;" << std::endl; - stream << " }" << std::endl; - stream << " }" << std::endl; - stream << " // is this raised for toplevel final as well?" << std::endl; - if (_hasDoneData) { - stream << " scxml_elem_donedata* donedata = &scxml_elem_donedatas[0];" << std::endl; - stream << " while(ELEM_DONEDATA_IS_SET(donedata)) {" << std::endl; - stream << " if unlikely(donedata->source == i)" << std::endl; - stream << " break;" << std::endl; - stream << " donedata++;" << std::endl; - stream << " }" << std::endl; - stream << " ctx->raise_done_event(ctx, &scxml_states[parent], (ELEM_DONEDATA_IS_SET(donedata) ? donedata : NULL));" << std::endl; - } else { - stream << " ctx->raise_done_event(ctx, &scxml_states[parent], NULL);" << std::endl; - } - stream << " }" << std::endl; - stream << std::endl; - - stream << " /**" << std::endl; - stream << " * are we the last final state to leave a parallel state?:" << std::endl; - stream << " * 1. Gather all parallel states in our ancestor chain" << std::endl; - stream << " * 2. Find all states for which these parallels are ancestors" << std::endl; - stream << " * 3. Iterate all active final states and remove their ancestors" << std::endl; - stream << " * 4. If a state remains, not all children of a parallel are final" << std::endl; - stream << " */" << std::endl; - stream << " for (int j = 0; j < SCXML_NUMBER_STATES; j++) {" << std::endl; - stream << " if unlikely(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 << " for (int 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 (scxml_states[k].type == SCXML_STATE_FINAL) {" << std::endl; - stream << " bit_and_not(parallel_children, scxml_states[k].ancestors, " << _stateCharArraySize << ");" << std::endl; - stream << " } else {" << std::endl; - stream << " SET_BIT(k, parallel_children);" << 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 << " }" << std::endl; - stream << " }" << std::endl; - stream << " }" << std::endl; - stream << std::endl; - - stream << " }" << std::endl; - stream << std::endl; - - stream << " }" << std::endl; - stream << " }" << std::endl; - stream << std::endl; - - stream << "// HISTORY_TRANSITIONS:" << std::endl; - stream << " for (int 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 << " 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; + + stream << "SELECT_TRANSITIONS:" << std::endl; + stream << " for (int i = 0; i < SCXML_NUMBER_TRANSITIONS; i++) {" << std::endl; + stream << " // never select history or initial transitions automatically" << std::endl; + stream << " if unlikely(scxml_transitions[i].type & (SCXML_TRANS_HISTORY | SCXML_TRANS_HISTORY))" << std::endl; + 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 << " // is it non-conflicting?" << std::endl; + stream << " if (!IS_SET(i, conflicts)) {" << std::endl; + stream << " // is it enabled?" << std::endl; + stream << " if (ctx->is_enabled(ctx, &scxml_transitions[i], event) > 0) {" << std::endl; + stream << " // remember that we found a transition" << std::endl; + stream << " ctx->flags |= SCXML_CTX_TRANSITION_FOUND;" << std::endl; + stream << std::endl; + + stream << " // transitions that are pre-empted" << std::endl; + stream << " bit_or(conflicts, scxml_transitions[i].conflicts, " << _transCharArraySize << ");" << std::endl; + stream << std::endl; + stream << " // states that are directly targeted (resolve as entry-set later)" << std::endl; + stream << " bit_or(target_set, scxml_transitions[i].target, " << _stateCharArraySize << ");" << std::endl; + stream << std::endl; + 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 << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " bit_and(exit_set, ctx->config, " << _stateCharArraySize << ");" << std::endl; + stream << std::endl; + + stream << " if (ctx->flags & SCXML_CTX_TRANSITION_FOUND) {" << std::endl; + stream << " ctx->flags |= SCXML_CTX_SPONTANEOUS;" << std::endl; + stream << " } else {" << std::endl; + stream << " ctx->flags &= ~SCXML_CTX_SPONTANEOUS;" << std::endl; + stream << " // goto MACRO_STEP;" << std::endl; + stream << " return SCXML_ERR_OK;" << std::endl; + stream << " }" << std::endl; + stream << std::endl; + + stream << "#ifdef SCXML_VERBOSE" << std::endl; + stream << " printf(\"Targets: \");" << std::endl; + stream << " printStateNames(target_set);" << std::endl; + stream << "#endif" << std::endl; + stream << std::endl; + + stream << "// REMEMBER_HISTORY:" << std::endl; + stream << " for (int i = 0; i < SCXML_NUMBER_STATES; i++) {" << std::endl; + stream << " if unlikely(scxml_states[i].type == SCXML_STATE_HISTORY_SHALLOW || 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].source, exit_set)) {" << std::endl; + stream << " char history[" << _stateCharArraySize << "] = " << _stateCharArrayInit << ";" << std::endl; + stream << " bit_copy(history, 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 << 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 << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + + stream << "#ifdef SCXML_VERBOSE" << std::endl; + stream << " printf(\"Exiting: \");" << std::endl; + stream << " printStateNames(exit_set);" << std::endl; + stream << "#endif" << std::endl; + stream << std::endl; + + stream << "#ifdef SCXML_VERBOSE" << std::endl; + stream << " printf(\"History: \");" << std::endl; + stream << " printStateNames(ctx->history);" << std::endl; + stream << "#endif" << std::endl; + stream << std::endl; + + stream << "// EXIT_STATES:" << std::endl; + stream << " for (int i = SCXML_NUMBER_STATES - 1; i >= 0; i--) {" << std::endl; + stream << " if (IS_SET(i, exit_set) && IS_SET(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], event)) != SCXML_ERR_OK)" << std::endl; + stream << " return err;" << std::endl; + stream << " }" << std::endl; + stream << " CLEARBIT(i, ctx->config);" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << std::endl; + + stream << "COMPLETE_CONFIG:" << std::endl; + stream << " // calculate new entry set" << std::endl; + stream << " bit_copy(entry_set, target_set, " << _stateCharArraySize << ");" << std::endl; + stream << std::endl; + stream << " // iterate for ancestors" << std::endl; + stream << " for (int i = 0; i < SCXML_NUMBER_STATES; i++) {" << std::endl; + stream << " if (IS_SET(i, entry_set)) {" << std::endl; + stream << " bit_or(entry_set, scxml_states[i].ancestors, " << _stateCharArraySize << ");" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << std::endl; + + stream << "// ADD_DESCENDANTS:" << std::endl; + stream << " // iterate for descendants" << std::endl; + stream << " for (int i = 0; i < SCXML_NUMBER_STATES; i++) {" << std::endl; + stream << " if (IS_SET(i, entry_set)) {" << std::endl; + stream << " switch (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; + stream << " break;" << std::endl; + 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 << " // nothing set for history, look for a default transition or enter parents completion" << std::endl; + stream << " for (int 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 << " break;" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " // TODO: enter parents default completion here" << 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 << " }" << std::endl; + stream << " break;" << std::endl; + stream << " }" << std::endl; + stream << " case SCXML_STATE_INITIAL: {" << std::endl; + stream << " for (int 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_or(entry_set, scxml_transitions[j].target, " << _stateCharArraySize << ");" << std::endl; + stream << " // one target may have been above, reestablish completion" << std::endl; + stream << " // goto ADD_DESCENDANTS; // initial will have to be first!" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " break;" << std::endl; + stream << " }" << std::endl; + stream << " case SCXML_STATE_COMPOUND: { // we need to check whether one child is already in entry_set" << std::endl; + stream << " if (!bit_has_and(entry_set, scxml_states[i].children, " << _stateCharArraySize << ") &&" << std::endl; + stream << " !bit_has_and(ctx->config, scxml_states[i].children, " << _stateCharArraySize << "))" << std::endl; + stream << " {" << std::endl; + stream << " bit_or(entry_set, scxml_states[i].completion, " << _stateCharArraySize << ");" << std::endl; + stream << " }" << std::endl; + stream << " break;" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << std::endl; + + stream << "#ifdef SCXML_VERBOSE" << std::endl; + stream << " printf(\"Transitions: \");" << std::endl; + stream << " printBitsetIndices(trans_set, sizeof(char) * 8 * " << _transCharArraySize << ");" << std::endl; + stream << "#endif" << std::endl; + stream << std::endl; + + stream << "// TAKE_TRANSITIONS:" << std::endl; + stream << " for (int i = 0; i < SCXML_NUMBER_TRANSITIONS; i++) {" << std::endl; + stream << " if (IS_SET(i, trans_set) && (scxml_transitions[i].type & SCXML_TRANS_HISTORY) == 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; + stream << " &scxml_states[scxml_transitions[i].source]," << std::endl; + stream << " event)) != SCXML_ERR_OK)" << std::endl; + stream << " return err;" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << std::endl; + + stream << "#ifdef SCXML_VERBOSE" << std::endl; + stream << " printf(\"Entering: \");" << std::endl; + stream << " printStateNames(entry_set);" << std::endl; + stream << "#endif" << std::endl; + stream << std::endl; + + stream << "// ENTER_STATES:" << std::endl; + stream << " for (int i = 0; i < SCXML_NUMBER_STATES; i++) {" << std::endl; + stream << " if (IS_SET(i, entry_set) && !IS_SET(i, ctx->config)) {" << std::endl; + stream << " // these are no proper states" << std::endl; + stream << " if unlikely(scxml_states[i].type == SCXML_STATE_HISTORY_DEEP ||" << std::endl; + stream << " scxml_states[i].type == SCXML_STATE_HISTORY_SHALLOW ||" << std::endl; + stream << " scxml_states[i].type == SCXML_STATE_INITIAL)" << std::endl; + stream << " continue;" << std::endl; + stream << std::endl; + + stream << " SET_BIT(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 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 << " }" << std::endl; + stream << std::endl; + + stream << " if (scxml_states[i].on_entry != NULL) {" << std::endl; + stream << " if unlikely((err = scxml_states[i].on_entry(ctx, &scxml_states[i], event)) != SCXML_ERR_OK)" << std::endl; + stream << " return err;" << std::endl; + stream << " }" << std::endl; + stream << std::endl; + + stream << " // handle final states" << std::endl; + stream << " if unlikely(scxml_states[i].type == SCXML_STATE_FINAL) {" << std::endl; + stream << " if unlikely(scxml_states[i].ancestors[0] == 0x01) {" << std::endl; + stream << " ctx->flags |= SCXML_CTX_TOP_LEVEL_FINAL;" << std::endl; + stream << " } else {" << std::endl; + stream << " // raise done event" << std::endl; + stream << " size_t parent = 0;" << std::endl; + stream << " for (int j = SCXML_NUMBER_STATES - 1; j >= 0; j--) {" << std::endl; + stream << " // we could trade runtime for memory here by saving the parent index" << std::endl; + stream << " if unlikely(IS_SET(j, scxml_states[i].ancestors)) {" << std::endl; + stream << " parent = j;" << std::endl; + stream << " break;" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " // is this raised for toplevel final as well?" << std::endl; + if (_hasDoneData) { + stream << " scxml_elem_donedata* donedata = &scxml_elem_donedatas[0];" << std::endl; + stream << " while(ELEM_DONEDATA_IS_SET(donedata)) {" << std::endl; + stream << " if unlikely(donedata->source == i)" << std::endl; + stream << " break;" << std::endl; + stream << " donedata++;" << std::endl; + stream << " }" << std::endl; + stream << " ctx->raise_done_event(ctx, &scxml_states[parent], (ELEM_DONEDATA_IS_SET(donedata) ? donedata : NULL));" << std::endl; + } else { + stream << " ctx->raise_done_event(ctx, &scxml_states[parent], NULL);" << std::endl; + } + stream << " }" << std::endl; + stream << std::endl; + + stream << " /**" << std::endl; + stream << " * are we the last final state to leave a parallel state?:" << std::endl; + stream << " * 1. Gather all parallel states in our ancestor chain" << std::endl; + stream << " * 2. Find all states for which these parallels are ancestors" << std::endl; + stream << " * 3. Iterate all active final states and remove their ancestors" << std::endl; + stream << " * 4. If a state remains, not all children of a parallel are final" << std::endl; + stream << " */" << std::endl; + stream << " for (int j = 0; j < SCXML_NUMBER_STATES; j++) {" << std::endl; + stream << " if unlikely(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 << " for (int 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 (scxml_states[k].type == SCXML_STATE_FINAL) {" << std::endl; + stream << " bit_and_not(parallel_children, scxml_states[k].ancestors, " << _stateCharArraySize << ");" << std::endl; + stream << " } else {" << std::endl; + stream << " SET_BIT(k, parallel_children);" << 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 << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << std::endl; + + stream << " }" << std::endl; + stream << std::endl; + + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << std::endl; + + stream << "// HISTORY_TRANSITIONS:" << std::endl; + stream << " for (int 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 << " 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; } NodeSet<std::string> ChartToC::inPostFixOrder(const std::set<std::string>& elements, const Element<std::string>& root) { - NodeSet<std::string> nodes; - inPostFixOrder(elements, root, nodes); - return nodes; + NodeSet<std::string> nodes; + inPostFixOrder(elements, root, nodes); + return nodes; } void ChartToC::inPostFixOrder(const std::set<std::string>& elements, const Element<std::string>& root, NodeSet<std::string>& nodes) { - NodeList<std::string> children = root.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - if (children.item(i).getNodeType() != Node_base::ELEMENT_NODE) - continue; - Arabica::DOM::Element<std::string> childElem(children.item(i)); - inPostFixOrder(elements, childElem, nodes); - - } - for (int i = 0; i < children.getLength(); i++) { - if (children.item(i).getNodeType() != Node_base::ELEMENT_NODE) - continue; - Arabica::DOM::Element<std::string> childElem(children.item(i)); - - if (elements.find(TAGNAME(childElem)) != elements.end()) { - nodes.push_back(childElem); - } - } + NodeList<std::string> children = root.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + if (children.item(i).getNodeType() != Node_base::ELEMENT_NODE) + continue; + Arabica::DOM::Element<std::string> childElem(children.item(i)); + inPostFixOrder(elements, childElem, nodes); + + } + for (int i = 0; i < children.getLength(); i++) { + if (children.item(i).getNodeType() != Node_base::ELEMENT_NODE) + continue; + Arabica::DOM::Element<std::string> childElem(children.item(i)); + + if (elements.find(TAGNAME(childElem)) != elements.end()) { + nodes.push_back(childElem); + } + } } NodeSet<std::string> ChartToC::inDocumentOrder(const std::set<std::string>& elements, const Element<std::string>& root) { - NodeSet<std::string> nodes; - inDocumentOrder(elements, root, nodes); - return nodes; + NodeSet<std::string> nodes; + inDocumentOrder(elements, root, nodes); + return nodes; } void ChartToC::inDocumentOrder(const std::set<std::string>& elements, const Element<std::string>& root, NodeSet<std::string>& nodes) { - if (elements.find(TAGNAME(root)) != elements.end()) { - nodes.push_back(root); - } - - NodeList<std::string> children = root.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - if (children.item(i).getNodeType() != Node_base::ELEMENT_NODE) - continue; - Arabica::DOM::Element<std::string> childElem(children.item(i)); - inDocumentOrder(elements, childElem, nodes); - } + if (elements.find(TAGNAME(root)) != elements.end()) { + nodes.push_back(root); + } + + NodeList<std::string> children = root.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + if (children.item(i).getNodeType() != Node_base::ELEMENT_NODE) + continue; + Arabica::DOM::Element<std::string> childElem(children.item(i)); + inDocumentOrder(elements, childElem, nodes); + } } ChartToC::~ChartToC() { } - + }
\ No newline at end of file diff --git a/src/uscxml/transform/ChartToC.h b/src/uscxml/transform/ChartToC.h index 0ee0d3c..6e6bac0 100644 --- a/src/uscxml/transform/ChartToC.h +++ b/src/uscxml/transform/ChartToC.h @@ -34,57 +34,57 @@ namespace uscxml { class USCXML_API ChartToC : public InterpreterRC, public TransformerImpl { public: - - virtual ~ChartToC(); - static Transformer transform(const Interpreter& other); - - void writeTo(std::ostream& stream); - - static Arabica::XPath::NodeSet<std::string> inPostFixOrder(const std::set<std::string>& elements, - const Arabica::DOM::Element<std::string>& root); - static Arabica::XPath::NodeSet<std::string> inDocumentOrder(const std::set<std::string>& elements, - const Arabica::DOM::Element<std::string>& root); + + virtual ~ChartToC(); + static Transformer transform(const Interpreter& other); + + void writeTo(std::ostream& stream); + + static Arabica::XPath::NodeSet<std::string> inPostFixOrder(const std::set<std::string>& elements, + const Arabica::DOM::Element<std::string>& root); + static Arabica::XPath::NodeSet<std::string> inDocumentOrder(const std::set<std::string>& elements, + const Arabica::DOM::Element<std::string>& root); protected: - ChartToC(const Interpreter& other); - - static void inPostFixOrder(const std::set<std::string>& elements, - const Arabica::DOM::Element<std::string>& root, - Arabica::XPath::NodeSet<std::string>& nodes); - - static void inDocumentOrder(const std::set<std::string>& elements, - const Arabica::DOM::Element<std::string>& root, - Arabica::XPath::NodeSet<std::string>& nodes); - - void writeIncludes(std::ostream& stream); - void writeMacros(std::ostream& stream); - void writeTypes(std::ostream& stream); - void writeHelpers(std::ostream& stream); - void writeExecContent(std::ostream& stream); - void writeElementInfo(std::ostream& stream); - - void writeStates(std::ostream& stream); - void writeTransitions(std::ostream& stream); - void writeFSM(std::ostream& stream); - void writeCharArrayInitList(std::ostream& stream, const std::string& boolString); - - void writeExecContent(std::ostream& stream, const Arabica::DOM::Node<std::string>& node, int indent = 0); - - Arabica::XPath::NodeSet<std::string> computeExitSet(const Arabica::DOM::Element<std::string>& transition); - - Interpreter interpreter; - - Arabica::XPath::NodeSet<std::string> _states; - std::map<std::string, Arabica::DOM::Element<std::string> > _stateNames; - Arabica::XPath::NodeSet<std::string> _transitions; - - bool _hasGlobalScripts; - bool _hasDoneData; - - size_t _transCharArraySize; - std::string _transCharArrayInit; - - size_t _stateCharArraySize; - std::string _stateCharArrayInit; + ChartToC(const Interpreter& other); + + static void inPostFixOrder(const std::set<std::string>& elements, + const Arabica::DOM::Element<std::string>& root, + Arabica::XPath::NodeSet<std::string>& nodes); + + static void inDocumentOrder(const std::set<std::string>& elements, + const Arabica::DOM::Element<std::string>& root, + Arabica::XPath::NodeSet<std::string>& nodes); + + void writeIncludes(std::ostream& stream); + void writeMacros(std::ostream& stream); + void writeTypes(std::ostream& stream); + void writeHelpers(std::ostream& stream); + void writeExecContent(std::ostream& stream); + void writeElementInfo(std::ostream& stream); + + void writeStates(std::ostream& stream); + void writeTransitions(std::ostream& stream); + void writeFSM(std::ostream& stream); + void writeCharArrayInitList(std::ostream& stream, const std::string& boolString); + + void writeExecContent(std::ostream& stream, const Arabica::DOM::Node<std::string>& node, int indent = 0); + + Arabica::XPath::NodeSet<std::string> computeExitSet(const Arabica::DOM::Element<std::string>& transition); + + Interpreter interpreter; + + Arabica::XPath::NodeSet<std::string> _states; + std::map<std::string, Arabica::DOM::Element<std::string> > _stateNames; + Arabica::XPath::NodeSet<std::string> _transitions; + + bool _hasGlobalScripts; + bool _hasDoneData; + + size_t _transCharArraySize; + std::string _transCharArrayInit; + + size_t _stateCharArraySize; + std::string _stateCharArrayInit; }; } diff --git a/src/uscxml/transform/ChartToFSM.cpp b/src/uscxml/transform/ChartToFSM.cpp index d55ef24..b78a2dd 100644 --- a/src/uscxml/transform/ChartToFSM.cpp +++ b/src/uscxml/transform/ChartToFSM.cpp @@ -97,7 +97,7 @@ std::cerr << ")"; ChartToFSM::ChartToFSM(const Interpreter& other) { cloneFrom(other.getImpl()); - + _transitionsFromTree = true; _keepInvalidTransitions = false; _lastTimeStamp = tthread::chrono::system_clock::now(); @@ -116,20 +116,20 @@ ChartToFSM::ChartToFSM(const Interpreter& other) { if (envVarIEquals("USCXML_TRANSFORM_TRANS_FROM", "powerset")) _transitionsFromTree = false; - + _start = NULL; _currGlobalTransition = NULL; _transTree = NULL; - + _lastStateIndex = 0; _lastActiveIndex = 0; _lastTransIndex = 0; - + _maxEventSentChain = 0; _maxEventRaisedChain = 0; _doneEventRaiseTolerance = 0; _skipEventChainCalculations = false; - + addMonitor(this); } @@ -144,7 +144,7 @@ ChartToFSM::~ChartToFSM() { delete confIter->second; confIter++; } - + // tear down caches Arabica::XPath::NodeSet<std::string> allTransitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", _scxml, true); for (int i = 0; i < allTransitions.size(); i++) { @@ -180,7 +180,7 @@ InterpreterState ChartToFSM::interpret() { } std::map<size_t, size_t> histoGramm = Complexity::getTransitionHistogramm(_scxml); // abort(); - + uint64_t complexity = Complexity::stateMachineComplexity(this) + 1; std::cerr << "Approximate Complexity: " << complexity << std::endl; std::cerr << "Approximate Active Complexity: " << Complexity::stateMachineComplexity(this, Complexity::IGNORE_HISTORY | Complexity::IGNORE_NESTED_DATA) + 1 << std::endl; @@ -224,7 +224,7 @@ InterpreterState ChartToFSM::interpret() { for (int i = 0; i < histories.size(); i++) { _historyTargets[ATTR_CAST(histories[i], "id")] = Element<std::string>(histories[i]); } - + _binding = (HAS_ATTR(_scxml, "binding") && iequals(ATTR(_scxml, "binding"), "late") ? LATE : EARLY); _alreadyFlat = (HAS_ATTR(_scxml, "flat") && stringIsTrue(ATTR(_scxml, "flat"))); @@ -232,7 +232,7 @@ InterpreterState ChartToFSM::interpret() { reassembleFromFlat(); return _state; } - + // set invokeid for all invokers to parent state if none given NodeSet<std::string> invokers = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", _scxml, true); for (int i = 0; i < invokers.size(); i++) { @@ -265,14 +265,14 @@ InterpreterState ChartToFSM::interpret() { _scxml.appendChild(initialElem); initialTransitions.push_back(transitionElem); } - + if (!_skipEventChainCalculations) annotateRaiseAndSend(_scxml); - + // std::cout << _scxml << std::endl; - + indexTransitions(); - + // add initial transitions as least prior for (int i = 0; i < initialTransitions.size() ; i++) { indexedTransitions.push_back(Element<std::string>(initialTransitions[i])); @@ -293,7 +293,7 @@ InterpreterState ChartToFSM::interpret() { // gather and set index attribute o states NodeSet<std::string> allStates = getAllStates(); allStates.to_document_order(); - + indexedStates.resize(allStates.size()); for (int i = 0; i < allStates.size(); i++) { Element<std::string> state = Element<std::string>(allStates[i]); @@ -309,9 +309,9 @@ InterpreterState ChartToFSM::interpret() { // std::cerr << _scxml << std::endl; - // create a _flatDoc for the FSM - DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation(); - _flatDoc = domFactory.createDocument(_document.getNamespaceURI(), "", 0); + // create a _flatDoc for the FSM + DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation(); + _flatDoc = domFactory.createDocument(_document.getNamespaceURI(), "", 0); GlobalTransition* globalTransition = new GlobalTransition(initialTransitions, _dataModel, this); globalTransition->index = _lastTransIndex++; @@ -323,7 +323,7 @@ InterpreterState ChartToFSM::interpret() { enterStates(initialTransitions); globalTransition->destination = FlatStateIdentifier::toStateId(_configuration); globalTransition->activeDestination = globalTransition->destination; - + explode(); DUMP_STATS(0, true); @@ -363,7 +363,7 @@ void ChartToFSM::executeContent(const Arabica::DOM::Element<std::string>& conten } } return; - + HAS_VALID_CHILDREN: if (false) { } else if (TAGNAME(content) == "transition") { @@ -379,21 +379,21 @@ HAS_VALID_CHILDREN: } if (!_skipEventChainCalculations && - (_maxEventRaisedChain != UNDECIDABLE || _maxEventSentChain != UNDECIDABLE)) { + (_maxEventRaisedChain != UNDECIDABLE || _maxEventSentChain != UNDECIDABLE)) { assert(content.hasAttribute("raise") && content.hasAttribute("send")); std::string raiseAttr = content.getAttribute("raise"); std::string sendAttr = content.getAttribute("send"); - + _currGlobalTransition->eventsRaised = (raiseAttr == "-1" ? UNDECIDABLE : _currGlobalTransition->eventsRaised + strTo<uint32_t>(raiseAttr)); _currGlobalTransition->eventsSent = (sendAttr == "-1" ? UNDECIDABLE : _currGlobalTransition->eventsSent + strTo<uint32_t>(sendAttr)); - + if (_currGlobalTransition->eventsRaised > _maxEventRaisedChain) _maxEventRaisedChain = _currGlobalTransition->eventsRaised; if (_currGlobalTransition->eventsSent > _maxEventSentChain) _maxEventSentChain = _currGlobalTransition->eventsSent; } - + _currGlobalTransition->actions.push_back(action); _currGlobalTransition->hasExecutableContent = true; } @@ -434,19 +434,19 @@ void ChartToFSM::internalDoneSend(const Arabica::DOM::Element<std::string>& stat onentry.appendChild(raise); - if (doneData) { - Arabica::XPath::NodeSet<std::string> contents = filterChildElements(_nsInfo.xmlNSPrefix + "content", doneData); - if (contents.size() > 0) { - Node<std::string> imported = _flatDoc.importNode(contents[0], true); - raise.appendChild(imported); - } - Arabica::XPath::NodeSet<std::string> params = filterChildElements(_nsInfo.xmlNSPrefix + "param", doneData); - if (params.size() > 0) { - Node<std::string> imported = _flatDoc.importNode(params[0], true); - raise.appendChild(imported); - } - } - + if (doneData) { + Arabica::XPath::NodeSet<std::string> contents = filterChildElements(_nsInfo.xmlNSPrefix + "content", doneData); + if (contents.size() > 0) { + Node<std::string> imported = _flatDoc.importNode(contents[0], true); + raise.appendChild(imported); + } + Arabica::XPath::NodeSet<std::string> params = filterChildElements(_nsInfo.xmlNSPrefix + "param", doneData); + if (params.size() > 0) { + Node<std::string> imported = _flatDoc.importNode(params[0], true); + raise.appendChild(imported); + } + } + raise.setAttribute("event", "done.state." + ATTR_CAST(state, "id")); // parent?! @@ -455,7 +455,7 @@ void ChartToFSM::internalDoneSend(const Arabica::DOM::Element<std::string>& stat _currGlobalTransition->actions.push_back(action); if (!_skipEventChainCalculations && - (_maxEventRaisedChain != UNDECIDABLE || _maxEventSentChain != UNDECIDABLE)) + (_maxEventRaisedChain != UNDECIDABLE || _maxEventSentChain != UNDECIDABLE)) _currGlobalTransition->eventsRaised++; _currGlobalTransition->hasExecutableContent = true; @@ -463,13 +463,13 @@ void ChartToFSM::internalDoneSend(const Arabica::DOM::Element<std::string>& stat static bool isSuperset(const GlobalTransition* t1, const GlobalTransition* t2) { bool isSuperset = true; - + if (t1->transitionRefs.size() >= t2->transitionRefs.size()) return false; - + NodeSet<std::string> t1Trans = t1->getTransitions(); NodeSet<std::string> t2Trans = t2->getTransitions(); - + for (int i = 0; i < t1Trans.size(); i++) { if (!InterpreterImpl::isMember(t1Trans[i], t2Trans)) { isSuperset = false; @@ -515,7 +515,7 @@ static bool filterSameHierarchy(const NodeSet<std::string>& transitions) { return true; } - + static bool filterChildEnabled(const NodeSet<std::string>& transitions) { // drop any transition that is already enabled by a child NodeSet<std::string> filteredTransitions; @@ -548,7 +548,7 @@ static bool filterChildEnabled(const NodeSet<std::string>& transitions) { bool ChartToFSM::hasForeachInBetween(const Arabica::DOM::Node<std::string>& ancestor, const Arabica::DOM::Node<std::string>& child) { if (!ancestor || !child) return false; - + Node<std::string> currChild = child; while(currChild != ancestor) { if (!currChild.getParentNode()) @@ -580,8 +580,8 @@ void ChartToFSM::annotateRaiseAndSend(const Arabica::DOM::Element<std::string>& } execContentElem.setAttribute("raise", toStr(nrRaise)); - DONE_COUNT_RAISE: - +DONE_COUNT_RAISE: + int nrSend = 0; NodeSet<std::string> sends = filterChildElements(_nsInfo.xmlNSPrefix + "send", execContent[i], true); for (int j = 0; j < sends.size(); j++) { @@ -594,151 +594,151 @@ void ChartToFSM::annotateRaiseAndSend(const Arabica::DOM::Element<std::string>& } execContentElem.setAttribute("send", toStr(nrSend)); - DONE_COUNT_SEND: +DONE_COUNT_SEND: ; } } void ChartToFSM::annotateDomain() { - Arabica::XPath::NodeSet<std::string> allTransitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", _scxml, true); - for (int i = 0; i < allTransitions.size(); i++) { - Element<std::string> transition(allTransitions[i]); - Arabica::DOM::Node<std::string> domain = getTransitionDomain(transition); - if (domain) { - transition.setAttribute("domain", (HAS_ATTR_CAST(domain, "id") ? ATTR_CAST(domain, "id") : DOMUtils::xPathForNode(domain))); - } else { - transition.setAttribute("domain", "#UNDEF"); - } - } + Arabica::XPath::NodeSet<std::string> allTransitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", _scxml, true); + for (int i = 0; i < allTransitions.size(); i++) { + Element<std::string> transition(allTransitions[i]); + Arabica::DOM::Node<std::string> domain = getTransitionDomain(transition); + if (domain) { + transition.setAttribute("domain", (HAS_ATTR_CAST(domain, "id") ? ATTR_CAST(domain, "id") : DOMUtils::xPathForNode(domain))); + } else { + transition.setAttribute("domain", "#UNDEF"); + } + } } - + void ChartToFSM::annotateExitSet() { - Arabica::XPath::NodeSet<std::string> allTransitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", _scxml, true); - for (int i = 0; i < allTransitions.size(); i++) { - Element<std::string> transition(allTransitions[i]); - Arabica::DOM::Node<std::string> domain = getTransitionDomain(transition); - - Arabica::XPath::NodeSet<std::string> allStates = getAllStates(); - std::ostringstream exitSetStr; - std::string seperator = ""; - for (int j = 0; j < allStates.size(); j++) { - Element<std::string> state(allStates[j]); - if (state.getParentNode() == domain) { - exitSetStr << seperator << (HAS_ATTR(state, "id") ? ATTR(state, "id") : DOMUtils::xPathForNode(state)); - seperator = ", "; - } - } - transition.setAttribute("exitset", exitSetStr.str()); - } + Arabica::XPath::NodeSet<std::string> allTransitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", _scxml, true); + for (int i = 0; i < allTransitions.size(); i++) { + Element<std::string> transition(allTransitions[i]); + Arabica::DOM::Node<std::string> domain = getTransitionDomain(transition); + + Arabica::XPath::NodeSet<std::string> allStates = getAllStates(); + std::ostringstream exitSetStr; + std::string seperator = ""; + for (int j = 0; j < allStates.size(); j++) { + Element<std::string> state(allStates[j]); + if (state.getParentNode() == domain) { + exitSetStr << seperator << (HAS_ATTR(state, "id") ? ATTR(state, "id") : DOMUtils::xPathForNode(state)); + seperator = ", "; + } + } + transition.setAttribute("exitset", exitSetStr.str()); + } } - + void ChartToFSM::annotateEntrySet() { - Arabica::XPath::NodeSet<std::string> allTransitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", _scxml, true); - for (int i = 0; i < allTransitions.size(); i++) { - Element<std::string> transition(allTransitions[i]); - - NodeSet<std::string> tmpTransitions; - NodeSet<std::string> tmpStatesToEnter; - NodeSet<std::string> tmpStatesForDefaultEntry; - std::map<std::string, Arabica::DOM::Node<std::string> > tmpDefaultHistoryContent; - - tmpTransitions.push_back(transition); - computeEntrySet(tmpTransitions, tmpStatesToEnter, tmpStatesForDefaultEntry, tmpDefaultHistoryContent); - - std::ostringstream entrySetStr; - std::string seperator = ""; - - for (int j = 0; j < tmpStatesToEnter.size(); j++) { - Element<std::string> state(tmpStatesToEnter[j]); - entrySetStr << seperator << (HAS_ATTR(state, "id") ? ATTR(state, "id") : DOMUtils::xPathForNode(state)); - seperator = ", "; - } - for (int j = 0; j < tmpStatesForDefaultEntry.size(); j++) { - Element<std::string> state(tmpStatesForDefaultEntry[j]); - entrySetStr << seperator << (HAS_ATTR(state, "id") ? ATTR(state, "id") : DOMUtils::xPathForNode(state)); - seperator = ", "; - } - transition.setAttribute("entryset", entrySetStr.str()); - - } + Arabica::XPath::NodeSet<std::string> allTransitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", _scxml, true); + for (int i = 0; i < allTransitions.size(); i++) { + Element<std::string> transition(allTransitions[i]); + + NodeSet<std::string> tmpTransitions; + NodeSet<std::string> tmpStatesToEnter; + NodeSet<std::string> tmpStatesForDefaultEntry; + std::map<std::string, Arabica::DOM::Node<std::string> > tmpDefaultHistoryContent; + + tmpTransitions.push_back(transition); + computeEntrySet(tmpTransitions, tmpStatesToEnter, tmpStatesForDefaultEntry, tmpDefaultHistoryContent); + + std::ostringstream entrySetStr; + std::string seperator = ""; + + for (int j = 0; j < tmpStatesToEnter.size(); j++) { + Element<std::string> state(tmpStatesToEnter[j]); + entrySetStr << seperator << (HAS_ATTR(state, "id") ? ATTR(state, "id") : DOMUtils::xPathForNode(state)); + seperator = ", "; + } + for (int j = 0; j < tmpStatesForDefaultEntry.size(); j++) { + Element<std::string> state(tmpStatesForDefaultEntry[j]); + entrySetStr << seperator << (HAS_ATTR(state, "id") ? ATTR(state, "id") : DOMUtils::xPathForNode(state)); + seperator = ", "; + } + transition.setAttribute("entryset", entrySetStr.str()); + + } } void ChartToFSM::annotateConflicts() { - Arabica::XPath::NodeSet<std::string> allTransitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", _scxml, true); - Arabica::XPath::NodeSet<std::string> allStates = getAllStates(); - - for (int i = 0; i < allTransitions.size(); i++) { - Element<std::string> t1(allTransitions[i]); - if (!isState(Element<std::string>(t1.getParentNode()))) - continue; - - Arabica::DOM::Node<std::string> d1 = getTransitionDomain(t1); - - Arabica::XPath::NodeSet<std::string> exitSet1; - for (int k = 0; k < allStates.size(); k++) { - Element<std::string> state(allStates[k]); - if (isDescendant(state, d1)) { - exitSet1.push_back(state); - } - } - - std::ostringstream preemptionStr; - std::string seperator = ""; - - for (int j = 0; j < allTransitions.size(); j++) { - if ( i == j) - continue; - - Element<std::string> t2(allTransitions[j]); - if (!isState(Element<std::string>(t2.getParentNode()))) - continue; - - Arabica::DOM::Node<std::string> d2 = getTransitionDomain(t2); - - Arabica::XPath::NodeSet<std::string> exitSet2; - for (int k = 0; k < allStates.size(); k++) { - Element<std::string> state(allStates[k]); - if (isDescendant(state, d2)) { - exitSet2.push_back(state); - } - } - - if (hasIntersection(exitSet1, exitSet2)) { - preemptionStr << seperator << (HAS_ATTR(t2, "priority") ? ATTR(t2, "priority") : DOMUtils::xPathForNode(t2)); - seperator = ", "; - } + Arabica::XPath::NodeSet<std::string> allTransitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", _scxml, true); + Arabica::XPath::NodeSet<std::string> allStates = getAllStates(); + + for (int i = 0; i < allTransitions.size(); i++) { + Element<std::string> t1(allTransitions[i]); + if (!isState(Element<std::string>(t1.getParentNode()))) + continue; + + Arabica::DOM::Node<std::string> d1 = getTransitionDomain(t1); + + Arabica::XPath::NodeSet<std::string> exitSet1; + for (int k = 0; k < allStates.size(); k++) { + Element<std::string> state(allStates[k]); + if (isDescendant(state, d1)) { + exitSet1.push_back(state); + } + } + + std::ostringstream preemptionStr; + std::string seperator = ""; + + for (int j = 0; j < allTransitions.size(); j++) { + if ( i == j) + continue; + + Element<std::string> t2(allTransitions[j]); + if (!isState(Element<std::string>(t2.getParentNode()))) + continue; + + Arabica::DOM::Node<std::string> d2 = getTransitionDomain(t2); + + Arabica::XPath::NodeSet<std::string> exitSet2; + for (int k = 0; k < allStates.size(); k++) { + Element<std::string> state(allStates[k]); + if (isDescendant(state, d2)) { + exitSet2.push_back(state); + } + } + + if (hasIntersection(exitSet1, exitSet2)) { + preemptionStr << seperator << (HAS_ATTR(t2, "priority") ? ATTR(t2, "priority") : DOMUtils::xPathForNode(t2)); + seperator = ", "; + } // if (isDescendant(d1, d2) || isDescendant(d2, d1) || d1 == d2) { // preemptionStr << seperator << ATTR(t2, "priority"); // seperator = ", "; // } - } - if (preemptionStr.str().size() > 0) - t1.setAttribute("conflicts", preemptionStr.str()); + } + if (preemptionStr.str().size() > 0) + t1.setAttribute("conflicts", preemptionStr.str()); - } + } } void ChartToFSM::indexTransitions() { - indexedTransitions.clear(); - indexTransitions(_scxml); - + indexedTransitions.clear(); + indexTransitions(_scxml); + #if 1 - size_t index = indexedTransitions.size() - 1; - for (std::vector<Arabica::DOM::Element<std::string> >::iterator transIter = indexedTransitions.begin(); transIter != indexedTransitions.end(); transIter++) { - transIter->setAttribute("priority", toStr(index)); - index--; - } + size_t index = indexedTransitions.size() - 1; + for (std::vector<Arabica::DOM::Element<std::string> >::iterator transIter = indexedTransitions.begin(); transIter != indexedTransitions.end(); transIter++) { + transIter->setAttribute("priority", toStr(index)); + index--; + } #else - size_t index = 0; - for (std::vector<Arabica::DOM::Element<std::string> >::iterator transIter = indexedTransitions.begin(); transIter != indexedTransitions.end(); transIter++) { - transIter->setAttribute("priority", toStr(index)); - index++; - } + size_t index = 0; + for (std::vector<Arabica::DOM::Element<std::string> >::iterator transIter = indexedTransitions.begin(); transIter != indexedTransitions.end(); transIter++) { + transIter->setAttribute("priority", toStr(index)); + index++; + } #endif - // reverse indices for most prior to be in front - //std::reverse(indexedTransitions.begin(), indexedTransitions.end()); + // reverse indices for most prior to be in front + //std::reverse(indexedTransitions.begin(), indexedTransitions.end()); } #if 0 @@ -757,30 +757,30 @@ void ChartToFSM::indexTransitions(const Arabica::DOM::Element<std::string>& root indexTransitions(stateElem); } } - + #else - + void ChartToFSM::indexTransitions(const Arabica::DOM::Element<std::string>& root) { - // Post-order traversal of transitions - Arabica::XPath::NodeSet<std::string> childStates = getChildStates(root); - for (int i = 0; i < childStates.size(); i++) { - Element<std::string> childElem(childStates[i]); - indexTransitions(childElem); - } - - Arabica::XPath::NodeSet<std::string> levelTransitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", root); - for (int i = 0; i < levelTransitions.size(); i++) { - // push into index starting with least prior - indexedTransitions.push_back(Element<std::string>(levelTransitions[i])); - } + // Post-order traversal of transitions + Arabica::XPath::NodeSet<std::string> childStates = getChildStates(root); + for (int i = 0; i < childStates.size(); i++) { + Element<std::string> childElem(childStates[i]); + indexTransitions(childElem); + } + + Arabica::XPath::NodeSet<std::string> levelTransitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", root); + for (int i = 0; i < levelTransitions.size(); i++) { + // push into index starting with least prior + indexedTransitions.push_back(Element<std::string>(levelTransitions[i])); + } } - + #endif bool GlobalTransition::operator< (const GlobalTransition& other) const { const std::vector<Arabica::DOM::Element<std::string> >& indexedTransitions = interpreter->indexedTransitions; NodeSet<std::string> transitions = getTransitions(); - + for (std::vector<Element<std::string> >::const_iterator transIter = indexedTransitions.begin(); transIter != indexedTransitions.end(); transIter++) { const Element<std::string>& refTrans = *transIter; NodeSet<std::string> otherTransitions = other.getTransitions(); @@ -807,10 +807,10 @@ bool hasUnconditionalSuperset(GlobalTransition* first, GlobalTransition* second) NodeSet<std::string> firstTransitions = first->getTransitions(); NodeSet<std::string> secondTransitions = second->getTransitions(); - + // if (first->condition.size() > 0) // return false; - + if (isSuperset(second, first)) { for (int i = 0; i < firstTransitions.size(); i++) { if (!InterpreterImpl::isMember(firstTransitions[i], secondTransitions)) { @@ -839,11 +839,11 @@ std::list<GlobalTransition*> redundantRemove(std::list<GlobalTransition*> list) #if 1 std::list<GlobalTransition*>::iterator outerIter; std::list<GlobalTransition*>::iterator innerIter; - + outerIter = list.begin(); while(outerIter != list.end()) { innerIter = outerIter; - + while(innerIter != list.end()) { if (innerIter == outerIter) { innerIter++; @@ -866,25 +866,25 @@ std::list<GlobalTransition*> redundantRemove(std::list<GlobalTransition*> list) } innerIter++; } - + outerIter++; } - + #else for (std::list<GlobalTransition*>::iterator outerIter = list.begin(); - outerIter != list.end(); - outerIter++) { + outerIter != list.end(); + outerIter++) { for (std::list<GlobalTransition*>::iterator innerIter = outerIter; - innerIter != list.end(); - innerIter++) { - + innerIter != list.end(); + innerIter++) { + if (innerIter == outerIter) continue; - + GlobalTransition* t1 = *outerIter; GlobalTransition* t2 = *innerIter; - + if (hasUnconditionalSuperset(t1, t2)) { innerIter = list.erase(innerIter); continue; @@ -906,20 +906,20 @@ std::list<GlobalTransition*> redundantMark(std::list<GlobalTransition*> list) { #if 1 std::list<GlobalTransition*>::iterator outerIter; std::list<GlobalTransition*>::iterator innerIter; - + outerIter = list.begin(); while(outerIter != list.end()) { innerIter = outerIter; - + while(innerIter != list.end()) { if (innerIter == outerIter) { innerIter++; continue; } - + GlobalTransition* t1 = *outerIter; GlobalTransition* t2 = *innerIter; - + if (!t1->isValid || !t2->isValid) { innerIter++; continue; @@ -947,28 +947,28 @@ std::list<GlobalTransition*> redundantMark(std::list<GlobalTransition*> list) { } innerIter++; } - + outerIter++; } - + #else for (std::list<GlobalTransition*>::iterator outerIter = list.begin(); - outerIter != list.end(); - outerIter++) { + outerIter != list.end(); + outerIter++) { for (std::list<GlobalTransition*>::iterator innerIter = outerIter; - innerIter != list.end(); - innerIter++) { - + innerIter != list.end(); + innerIter++) { + if (innerIter == outerIter) continue; - + GlobalTransition* t1 = *outerIter; GlobalTransition* t2 = *innerIter; - + if (!t1->isValid || !t2->isValid) continue; - + if (hasUnconditionalSuperset(t1, t2)) { t2->isValid = false; t2->invalidMsg = "Unconditional superset"; @@ -992,7 +992,7 @@ std::list<GlobalTransition*> redundantMark(std::list<GlobalTransition*> list) { return list; } - + void TransitionTreeNode::dump(int indent) { std::string padding; for (int i = 0; i + 1 < indent; i++) { @@ -1000,23 +1000,27 @@ void TransitionTreeNode::dump(int indent) { } if (indent > 0) padding += "|-"; - + std::string typeString; switch (type) { - case TYPE_NESTED: - typeString = "NESTED"; break; - case TYPE_PARALLEL: - typeString = "PARALLEL"; break; - case TYPE_TRANSITION: - typeString = "TRANSITION"; break; - case TYPE_UNDEFINED: - typeString = "UNDEFINED"; break; - break; - default: - break; + case TYPE_NESTED: + typeString = "NESTED"; + break; + case TYPE_PARALLEL: + typeString = "PARALLEL"; + break; + case TYPE_TRANSITION: + typeString = "TRANSITION"; + break; + case TYPE_UNDEFINED: + typeString = "UNDEFINED"; + break; + break; + default: + break; } - + if (transition) { std::cerr << padding << "t" << ATTR(transition, "index") << " " << typeString << ": "; // std::cerr << (prevTransition != NULL ? " (" + prevTransition->nodeId + ") <-" : ""); @@ -1028,7 +1032,7 @@ void TransitionTreeNode::dump(int indent) { // std::cerr << (firstTransition != NULL ? " -> " + firstTransition->nodeId : ""); std::cerr << std::endl; } - + for (std::list<TransitionTreeNode*>::iterator childIter = children.begin(); childIter != children.end(); childIter++) { (*childIter)->dump(indent + 1); } @@ -1047,27 +1051,27 @@ void ChartToFSM::getPotentialTransitionsForConfFromTree(const Arabica::XPath::No // recursion start std::set<TransitionTreeNode*> transLeafs; - for (int i = 0; i < conf.size(); i++) { - DUMP_STATS(conf.size(), false); - - Element<std::string> confElem(conf[i]); - assert(_stateToTransTreeNode.find(confElem) != _stateToTransTreeNode.end()); - TransitionTreeNode* node = _stateToTransTreeNode[confElem]; - if (node->firstState == NULL) { // a leaf - ignore intermediates - // ascend to the first parent with transitions but stop at parallel nodes - while(node != NULL && node->firstTransition == NULL) { - if (node->parent && node->parent->type == TransitionTreeNode::TYPE_PARALLEL) - break; - node = node->parent; - } - if (node != NULL) { - transLeafs.insert(node); - } else { - //std::cerr << ATTR(confElem, "id") << " does not cause transitions" << std::endl; - } + for (int i = 0; i < conf.size(); i++) { + DUMP_STATS(conf.size(), false); + + Element<std::string> confElem(conf[i]); + assert(_stateToTransTreeNode.find(confElem) != _stateToTransTreeNode.end()); + TransitionTreeNode* node = _stateToTransTreeNode[confElem]; + if (node->firstState == NULL) { // a leaf - ignore intermediates + // ascend to the first parent with transitions but stop at parallel nodes + while(node != NULL && node->firstTransition == NULL) { + if (node->parent && node->parent->type == TransitionTreeNode::TYPE_PARALLEL) + break; + node = node->parent; + } + if (node != NULL) { + transLeafs.insert(node); + } else { + //std::cerr << ATTR(confElem, "id") << " does not cause transitions" << std::endl; } } - + } + std::list<std::set<TransitionTreeNode*> > stack; stack.push_back(transLeafs); // push follow-up configurations onto stack @@ -1075,7 +1079,7 @@ void ChartToFSM::getPotentialTransitionsForConfFromTree(const Arabica::XPath::No // pop from front of stack std::set<TransitionTreeNode*> stateList = stack.front(); stack.pop_front(); - + DUMP_STATS(conf.size(), false); #if 0 @@ -1087,40 +1091,40 @@ void ChartToFSM::getPotentialTransitionsForConfFromTree(const Arabica::XPath::No } std::cerr << std::endl; #endif - + /* * TransNodes contains a set of lists of transitions. - * In the inner stack we build every possible combination + * In the inner stack we build every possible combination * of picking at-most one from each list. */ - + /* create global transitions for every n-tuple in current set of lists */ std::list<std::pair<std::set<TransitionTreeNode*>, std::set<TransitionTreeNode*> > > innerStack; innerStack.push_back(std::make_pair(std::set<TransitionTreeNode*>(), stateList)); - + while(innerStack.size() > 0) { // picking at-most one from each list std::set<TransitionTreeNode*> remainingStates = innerStack.front().second; std::set<TransitionTreeNode*> fixedTransitions = innerStack.front().first; innerStack.pop_front(); - + if (remainingStates.size() > 0) { // iterate for each first element fixed TransitionTreeNode* firstRemainingState = *remainingStates.begin(); remainingStates.erase(remainingStates.begin()); - + if (firstRemainingState->firstTransition == NULL) { // no transitions at this state - reenqueue with NULL selection from this innerStack.push_back(std::make_pair(fixedTransitions, remainingStates)); continue; } - + TransitionTreeNode* currTrans = firstRemainingState->firstTransition; - + // choose none from firstList innerStack.push_back(std::make_pair(fixedTransitions, remainingStates)); - + while(currTrans != NULL) { std::set<TransitionTreeNode*> fixedAndThis(fixedTransitions); fixedAndThis.insert(currTrans); @@ -1136,7 +1140,7 @@ void ChartToFSM::getPotentialTransitionsForConfFromTree(const Arabica::XPath::No _perfTransProcessed++; NodeSet<std::string> fixed; - + #if 0 seperator = ""; for (std::set<TransitionTreeNode*>::iterator itemIter = fixedTransitions.begin(); itemIter != fixedTransitions.end(); itemIter++) { @@ -1146,7 +1150,7 @@ void ChartToFSM::getPotentialTransitionsForConfFromTree(const Arabica::XPath::No } std::cerr << " ## "; #endif - + seperator = ""; for (std::set<TransitionTreeNode*>::iterator itemIter = fixedTransitions.begin(); itemIter != fixedTransitions.end(); itemIter++) { TransitionTreeNode* currItem = *itemIter; @@ -1165,7 +1169,7 @@ void ChartToFSM::getPotentialTransitionsForConfFromTree(const Arabica::XPath::No // std::cerr << " - PREEMPTS" << std::endl; continue; } - + GlobalTransition* transition = new GlobalTransition(fixed, _dataModel, this); transition->index = _lastTransIndex++; @@ -1176,7 +1180,7 @@ void ChartToFSM::getPotentialTransitionsForConfFromTree(const Arabica::XPath::No // std::cerr << " - INVALID" << std::endl; continue; } - + _perfTransUsed++; outMap[transition->transitionId] = transition; @@ -1184,31 +1188,31 @@ void ChartToFSM::getPotentialTransitionsForConfFromTree(const Arabica::XPath::No } } } - + // create new set of transition lists by moving to parent states for (std::set<TransitionTreeNode*>::iterator stateIter = stateList.begin(); stateIter != stateList.end(); stateIter++) { TransitionTreeNode* origState = *stateIter; TransitionTreeNode* currState = origState; TransitionTreeNode* parentState = currState->parent; - + /** * We ascend the current state via its parent and add the parent with transitions. - * However, we break if we reached the top or if we passed a parallel state for + * However, we break if we reached the top or if we passed a parallel state for * wich we are not the first child */ - + while(parentState != NULL) { if (parentState->type == TransitionTreeNode::TYPE_PARALLEL && parentState->firstState != currState) { // the first child of the parallel state will continue this transition - we made sure to keep them break; } - + if (parentState->firstTransition != NULL) { // std::cerr << "#### Adding new parent lists for " << origState->nodeId << std::endl; - + std::set<TransitionTreeNode*> newStateList; newStateList.insert(parentState); - + // add all other states that are not a child of the parent state for (std::set<TransitionTreeNode*>::iterator newlistIter = stateList.begin(); newlistIter != stateList.end(); newlistIter++) { TransitionTreeNode* otherState = *newlistIter; @@ -1234,7 +1238,7 @@ TransitionTreeNode* ChartToFSM::buildTransTree(const Arabica::DOM::Element<std:: TransitionTreeNode* stateNode = new TransitionTreeNode(); stateNode->nodeId = nodeId; stateNode->state = root; - + if (TAGNAME(root) == _nsInfo.xmlNSPrefix + "parallel") { stateNode->type = TransitionTreeNode::TYPE_PARALLEL; } else { @@ -1250,7 +1254,7 @@ TransitionTreeNode* ChartToFSM::buildTransTree(const Arabica::DOM::Element<std:: nested.to_document_order(); TransitionTreeNode* lastNode = NULL; - + for (int i = 0; i < nested.size(); i++) { Element<std::string> nestedElem(nested[i]); if (TAGNAME(nestedElem) == _nsInfo.xmlNSPrefix + "transition") { @@ -1259,20 +1263,20 @@ TransitionTreeNode* ChartToFSM::buildTransTree(const Arabica::DOM::Element<std:: transNode->parent = stateNode; transNode->nodeId = nodeId + "-" + toStr(i); transNode->type = TransitionTreeNode::TYPE_TRANSITION; - + if (stateNode->firstTransition == NULL) { stateNode->firstTransition = transNode; } stateNode->children.push_back(transNode); stateNode->lastTransition = transNode; - + if (lastNode != NULL) { lastNode->nextTransition = transNode; transNode->prevTransition = lastNode; } lastNode = transNode; - - + + } else { TransitionTreeNode* deeperNode = buildTransTree(nestedElem, nodeId + "-" + toStr(i)); if (stateNode->firstState == NULL) { @@ -1283,9 +1287,9 @@ TransitionTreeNode* ChartToFSM::buildTransTree(const Arabica::DOM::Element<std:: stateNode->children.push_back(deeperNode); } } - + _stateToTransTreeNode[root] = stateNode; - + return stateNode; } @@ -1301,42 +1305,42 @@ void ChartToFSM::getPotentialTransitionsForConfFromPowerSet(const Arabica::XPath } std::cerr << std::endl; } - + // if (true) { // outMap = _confToTransitions[""]; // } - + if (allTransitions.size() == 0) return; // no transitions - + int nrElements = allTransitions.size(); int k = 0; int* stack = (int*)malloc((nrElements + 1) * sizeof(int)); memset(stack, 0, (nrElements + 1) * sizeof(int)); - + /** * Powerset is too naive and takes too long! - * We have it up to 500k checks/sec and still 2**30 is + * We have it up to 500k checks/sec and still 2**30 is * 1G+ for 30minutes in a single state out of 50k+! */ - + while(1) { // create the power set of all potential transitions - this is expensive! // see: http://www.programminglogic.com/powerset-algorithm-in-c/ - + if (stack[k] < nrElements) { stack[k+1] = stack[k] + 1; k++; } - + else { stack[k-1]++; k--; } - + if (k==0) break; - + NodeSet<std::string> transitions; // std::cerr << globalState->stateId << " [" << nrElements << "]: " << std::endl; for (int i = 1; i <= k; i++) { @@ -1344,27 +1348,27 @@ void ChartToFSM::getPotentialTransitionsForConfFromPowerSet(const Arabica::XPath transitions.push_back(allTransitions[stack[i] - 1]); } // std::cerr << std::endl; - + // transitions.push_back(allTransitions[0]); // transitions.push_back(allTransitions[4]); // transitions.push_back(allTransitions[5]); // transitions.push_back(allTransitions[7]); - + bool dump = false; - + // if (k == 4 && stack[1] == 1 && stack[2] == 5 && stack[3] == 6 && stack[4] == 8) { // dump = true; // } - + if (dump) DUMP_TRANSSET("at start"); - + _perfTransTotal++; _perfTransProcessed++; - + DUMP_STATS(nrElements, false); - + GlobalTransition* transition = NULL; - + // reduce to conflict-free subset // transitions.to_document_order(); if (!_keepInvalidTransitions) { @@ -1372,18 +1376,18 @@ void ChartToFSM::getPotentialTransitionsForConfFromPowerSet(const Arabica::XPath if(!filterSameState(transitions)) continue; if (dump) DUMP_TRANSSET("after same state filtered"); - + // remove those transitions with a child transition // if(!filterChildEnabled(transitions)) if(!filterSameHierarchy(transitions)) continue; if (dump) DUMP_TRANSSET("after child enabled filtered"); - + transitions = removeConflictingTransitions(transitions); if (dump) DUMP_TRANSSET("after conflicting filtered"); // algorithm can never reduce to empty set assert(transitions.size() > 0); - + // create a GlobalTransition object from the set transition = new GlobalTransition(transitions, _dataModel, this); if (!transition->isValid) { @@ -1393,13 +1397,13 @@ void ChartToFSM::getPotentialTransitionsForConfFromPowerSet(const Arabica::XPath } } else { transition = new GlobalTransition(transitions, _dataModel, this); - + // remove transitions in the same state if(!filterSameState(transitions)) { transition->isValid = false; transition->invalidReason = GlobalTransition::SAME_SOURCE_STATE; transition->invalidMsg = "Same source state"; - + // } else if(!filterChildEnabled(transitions)) { } else if(!filterSameHierarchy(transitions)) { transition->isValid = false; @@ -1413,7 +1417,7 @@ void ChartToFSM::getPotentialTransitionsForConfFromPowerSet(const Arabica::XPath transition->invalidMsg = "Preempting members"; } } - + } // two combinations might have projected onto the same conflict-free set @@ -1425,7 +1429,7 @@ void ChartToFSM::getPotentialTransitionsForConfFromPowerSet(const Arabica::XPath transition->index = _lastTransIndex++; _perfTransUsed++; - + // remember this conflict-free set // std::cerr << "New conflict-free subset: " << transition->transitionId << ":" << transition->eventDesc << std::endl; outMap[transition->transitionId] = transition; @@ -1433,12 +1437,12 @@ void ChartToFSM::getPotentialTransitionsForConfFromPowerSet(const Arabica::XPath // _confToTransitions[""] = outMap; return; } - + void ChartToFSM::explode() { std::list<std::pair<GlobalTransition*, GlobalState*> > statesRemaining; statesRemaining.push_back(std::make_pair(_currGlobalTransition, new GlobalState(_configuration, _alreadyEntered, _historyValue, _nsInfo.xmlNSPrefix, this))); - + // add all invokers for initial transition for (unsigned int i = 0; i < _statesToInvoke.size(); i++) { NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", _statesToInvoke[i]); @@ -1451,7 +1455,7 @@ void ChartToFSM::explode() { /** We need this to be a recursion in order not to exhaust the stack */ - + // append new global states and pop from front while(statesRemaining.size() > 0) { _perfStackSize = statesRemaining.size(); @@ -1459,18 +1463,18 @@ void ChartToFSM::explode() { _perfStatesProcessed++; DUMP_STATS(0, false); - + GlobalState* globalState = statesRemaining.front().second; _currGlobalTransition = statesRemaining.front().first; statesRemaining.pop_front(); - + // used to be conditionalized, we will just assume assert(_currGlobalTransition); if (_globalConf.find(globalState->stateId) != _globalConf.end()) { if (_currGlobalTransition->isEventless && - !_skipEventChainCalculations && - (_maxEventRaisedChain != UNDECIDABLE || _maxEventSentChain != UNDECIDABLE)) { + !_skipEventChainCalculations && + (_maxEventRaisedChain != UNDECIDABLE || _maxEventSentChain != UNDECIDABLE)) { // we arrived via a spontaneaous transition, do we need to update? updateRaisedAndSendChains(_globalConf[globalState->stateId], _currGlobalTransition, std::set<GlobalTransition*>()); } @@ -1487,7 +1491,7 @@ void ChartToFSM::explode() { // remember as global configuration _globalConf[globalState->stateId] = globalState; _globalConf[globalState->stateId]->index = _lastStateIndex++; - + if(_globalConf[globalState->stateId]->isFinal) { if (_activeConf.find(globalState->activeId) == _activeConf.end()) { assert(globalState->activeIndex == -1); @@ -1522,11 +1526,11 @@ void ChartToFSM::explode() { // reduce and sort transition sets for(std::map<std::string, GlobalTransition*>::iterator transSetIter = transitionSets.begin(); - transSetIter != transitionSets.end(); - transSetIter++) { + transSetIter != transitionSets.end(); + transSetIter++) { globalState->sortedOutgoing.push_back(transSetIter->second); } - + globalState->sortedOutgoing.sort(PtrComp<GlobalTransition>); // globalState->sortedOutgoing.unique(hasUnconditionalSuperset); // globalState->sortedOutgoing.unique(hasEarlierUnconditionalMatch); @@ -1542,23 +1546,23 @@ void ChartToFSM::explode() { // globalState->sortedOutgoing = redundantRemove(globalState->sortedOutgoing); // // std::cout << globalState->sortedOutgoing.size() << std::endl; - + assert(_activeConf.find(globalState->activeId) == _activeConf.end()); assert(globalState->activeIndex == -1); globalState->activeIndex = _lastActiveIndex++; _activeConf[globalState->activeId] = globalState; } - + // take every transition set and append resulting new state for(std::list<GlobalTransition*>::iterator transIter = globalState->sortedOutgoing.begin(); - transIter != globalState->sortedOutgoing.end(); - transIter++) { - + transIter != globalState->sortedOutgoing.end(); + transIter++) { + GlobalTransition* incomingTrans = _currGlobalTransition; GlobalTransition* outgoingTrans = *transIter; - + outgoingTrans->source = globalState->stateId; - + if (_keepInvalidTransitions && !outgoingTrans->isValid) continue; @@ -1572,8 +1576,8 @@ void ChartToFSM::explode() { // if outgoing transition is spontaneous, add number of events to chain if (outgoingTrans->isEventless && - !_skipEventChainCalculations && - (_maxEventRaisedChain != UNDECIDABLE || _maxEventSentChain != UNDECIDABLE)) { + !_skipEventChainCalculations && + (_maxEventRaisedChain != UNDECIDABLE || _maxEventSentChain != UNDECIDABLE)) { outgoingTrans->eventsChainRaised = MIN(incomingTrans->eventsChainRaised + outgoingTrans->eventsRaised, UNDECIDABLE); outgoingTrans->eventsChainSent = MIN(incomingTrans->eventsChainSent + outgoingTrans->eventsSent, UNDECIDABLE); @@ -1585,7 +1589,7 @@ void ChartToFSM::explode() { } statesRemaining.push_back(std::make_pair(outgoingTrans, new GlobalState(_configuration, _alreadyEntered, _historyValue, _nsInfo.xmlNSPrefix, this))); - + // add all invokers for (unsigned int i = 0; i < _statesToInvoke.size(); i++) { NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", _statesToInvoke[i]); @@ -1610,13 +1614,13 @@ void ChartToFSM::explode() { void ChartToFSM::updateRaisedAndSendChains(GlobalState* state, GlobalTransition* source, std::set<GlobalTransition*> visited) { for (std::list<GlobalTransition*>::iterator transIter = state->sortedOutgoing.begin(); transIter != state->sortedOutgoing.end(); transIter++) { GlobalTransition* transition = *transIter; - + if (!transition->isEventless) continue; // we do not care for eventful transitions - + // source leads to spontaneous transition -> update event chains bool eventChainsNeedUpdated = false; - + if (visited.find(transition) != visited.end()) { // potential spontaneous transition cycle! if (transition->eventsChainRaised > 0) @@ -1625,32 +1629,32 @@ void ChartToFSM::updateRaisedAndSendChains(GlobalState* state, GlobalTransition* _maxEventSentChain = UNDECIDABLE; return; } - + // UNDECIDABLE means "undecidable / endless" - + // will source increase our event chain? if (transition->eventsChainRaised != UNDECIDABLE && - transition->eventsChainRaised < source->eventsChainRaised + transition->eventsRaised) { + transition->eventsChainRaised < source->eventsChainRaised + transition->eventsRaised) { // taking transition after source causes more events in chain transition->eventsChainRaised = MIN(source->eventsChainRaised + transition->eventsRaised, UNDECIDABLE); eventChainsNeedUpdated = true; } if (transition->eventsChainSent != UNDECIDABLE && - transition->eventsChainSent < source->eventsChainSent + transition->eventsSent) { + transition->eventsChainSent < source->eventsChainSent + transition->eventsSent) { // taking transition after source causes more events in chain transition->eventsChainSent = MIN(source->eventsChainSent + transition->eventsSent, UNDECIDABLE); eventChainsNeedUpdated = true; } if (eventChainsNeedUpdated && - transition->destination.length() > 0 && - _globalConf.find(transition->destination) != _globalConf.end()) { + transition->destination.length() > 0 && + _globalConf.find(transition->destination) != _globalConf.end()) { visited.insert(transition); // iterate all spontaneous transitions in destination and update event chains updateRaisedAndSendChains(_globalConf[transition->destination], transition, visited); } - + if (transition->eventsChainRaised > _maxEventRaisedChain) _maxEventRaisedChain = transition->eventsChainRaised; if (transition->eventsChainSent > _maxEventSentChain) @@ -1690,7 +1694,7 @@ Arabica::XPath::NodeSet<std::string> ChartToFSM::refsToTransitions(const std::se } return transitions; } - + void ChartToFSM::beforeMicroStep(Interpreter interpreter) { } void ChartToFSM::onStableConfiguration(Interpreter interpreter) { @@ -1732,7 +1736,7 @@ GlobalState::GlobalState(const Arabica::XPath::NodeSet<std::string>& activeState const Arabica::XPath::NodeSet<std::string>& alreadyEnteredStates_, // we need to remember for binding=late const std::map<std::string, Arabica::XPath::NodeSet<std::string> >& historyStates_, const std::string& xmlNSPrefix, - ChartToFSM* flattener) { + ChartToFSM* flattener) { interpreter = flattener; activeIndex = -1; @@ -1778,13 +1782,13 @@ GlobalTransition* GlobalTransition::copyWithoutExecContent(GlobalTransition* oth GlobalTransition::GlobalTransition(const Arabica::XPath::NodeSet<std::string>& transitionSet, DataModel dataModel, ChartToFSM* flattener) { interpreter = flattener; - + eventsRaised = 0; eventsSent = 0; eventsChainRaised = 0; eventsChainSent = 0; historyBase = NULL; - + for (int i = 0; i < transitionSet.size(); i++) { transitionRefs.insert(strTo<int>(ATTR_CAST(transitionSet[i], "index"))); } @@ -1800,7 +1804,7 @@ GlobalTransition::GlobalTransition(const Arabica::XPath::NodeSet<std::string>& t hasExecutableContent = false; isValid = true; isEventless = true; - + #if 0 std::cerr << "################" << std::endl; for (int i = 0; i < transitions.size(); i++) { @@ -1910,7 +1914,7 @@ GlobalTransition::GlobalTransition(const Arabica::XPath::NodeSet<std::string>& t if (HAS_ATTR(transElem, "cond")) { conditions.push_back(boost::trim_copy(ATTR(transElem, "cond"))); } - + std::list<std::string> targets = InterpreterImpl::tokenizeIdRefs(ATTR(transElem, "target")); std::list<std::string>::iterator targetIter = targets.begin(); while(targetIter != targets.end()) { @@ -1922,7 +1926,7 @@ GlobalTransition::GlobalTransition(const Arabica::XPath::NodeSet<std::string>& t } // std::cout << std::endl << std::endl; } - + seperator = ""; for (std::vector<Element<std::string> >::iterator transIter = interpreter->indexedTransitions.begin(); transIter != interpreter->indexedTransitions.end(); transIter++) { const Element<std::string>& refTrans = *transIter; @@ -1938,7 +1942,7 @@ GlobalTransition::GlobalTransition(const Arabica::XPath::NodeSet<std::string>& t } seperator = " "; } - + // if (members == " 4 6 7 ") // std::cout << "asdfadf"; @@ -1968,7 +1972,7 @@ std::map<std::string, Arabica::XPath::NodeSet<std::string> > GlobalState::getHis return historyValue; } - + Arabica::XPath::NodeSet<std::string> GlobalTransition::getTransitions() const { return interpreter->refsToTransitions(transitionRefs); } diff --git a/src/uscxml/transform/ChartToFSM.h b/src/uscxml/transform/ChartToFSM.h index f7e00c5..ab4aed4 100644 --- a/src/uscxml/transform/ChartToFSM.h +++ b/src/uscxml/transform/ChartToFSM.h @@ -43,12 +43,12 @@ public: const Arabica::XPath::NodeSet<std::string>& alreadyEnteredStates, // we need to remember for binding=late const std::map<std::string, Arabica::XPath::NodeSet<std::string> >& historyStates, const std::string& xmlNSPrefix, - ChartToFSM* flattener); + ChartToFSM* flattener); std::set<int> activeStatesRefs; std::set<int> alreadyEnteredStatesRefs; std::map<std::string, std::set<int> > historyStatesRefs; - + std::list<GlobalTransition*> sortedOutgoing; std::string stateId; std::string activeId; @@ -56,9 +56,9 @@ public: unsigned long activeIndex; unsigned long index; bool isFinal; - + ChartToFSM* interpreter; - + Arabica::XPath::NodeSet<std::string> getActiveStates(); Arabica::XPath::NodeSet<std::string> getAlreadyEnteredStates(); std::map<std::string, Arabica::XPath::NodeSet<std::string> > getHistoryStates(); @@ -98,7 +98,7 @@ public: return true; if ((uninvoke && !other.uninvoke) || (!uninvoke && other.uninvoke)) return true; - + if (onEntry < other.onEntry) return onEntry < other.onEntry; if (raiseDone < other.raiseDone) @@ -124,11 +124,11 @@ public: bool operator!=(const Action& other) const { return !operator==(other); } - + friend USCXML_API std::ostream& operator<< (std::ostream& os, const Action& action); typedef std::list<GlobalTransition::Action>::iterator iter_t; - + Arabica::DOM::Element<std::string> onEntry; Arabica::DOM::Element<std::string> onExit; Arabica::DOM::Element<std::string> transition; @@ -137,12 +137,12 @@ public: Arabica::DOM::Element<std::string> invoke; Arabica::DOM::Element<std::string> uninvoke; Arabica::DOM::Element<std::string> raiseDone; - + }; GlobalTransition(const Arabica::XPath::NodeSet<std::string>& transitions, DataModel dataModel, ChartToFSM* flattener); static GlobalTransition* copyWithoutExecContent(GlobalTransition* other); - + bool isValid; // constructor will determine, calling code will delete if not std::string invalidMsg; InvalidReason invalidReason; @@ -151,17 +151,17 @@ public: bool isTargetless; // whether or not all our transitions are eventless bool isSubset; // there is a superset to this set bool hasExecutableContent; - + uint32_t eventsRaised; // internal events this transition will raise uint32_t eventsSent; // external events this transition will send uint32_t eventsChainRaised; // maximum number of internal events raised when taking this transition in a chain uint32_t eventsChainSent; // maximum number of external events raised when taking this transition in a chain - + std::set<int> startTransitionRefs; // indices of eventful transitions that might trigger this transition - + std::set<int> transitionRefs; // indizes of constituting transitions Arabica::XPath::NodeSet<std::string> getTransitions() const; - + std::list<std::string> eventNames; // the list of longest event names that will enable this set std::string eventDesc; // space-seperated eventnames for convenience std::string condition; // conjunction of all the set's conditions @@ -198,15 +198,15 @@ public: TYPE_NESTED, TYPE_TRANSITION }; - + TransitionTreeNode() - : prevTransition(NULL), - nextTransition(NULL), - firstTransition(NULL), - firstState(NULL), - parent(NULL), - type(TYPE_UNDEFINED) {} - + : prevTransition(NULL), + nextTransition(NULL), + firstTransition(NULL), + firstState(NULL), + parent(NULL), + type(TYPE_UNDEFINED) {} + virtual ~TransitionTreeNode() { for (std::list<TransitionTreeNode*>::iterator childIter = children.begin(); childIter != children.end(); childIter++) { delete(*childIter); @@ -229,7 +229,7 @@ public: std::string nodeId; TransitionTreeNodeType type; - + bool operator<(const TransitionTreeNode& other) const { return nodeId < other.nodeId; } @@ -242,16 +242,16 @@ public: virtual ~ChartToFSM(); void indexTransitions(); - void annotateDomain(); - void annotateExitSet(); - void annotateEntrySet(); - void annotateConflicts(); + void annotateDomain(); + void annotateExitSet(); + void annotateEntrySet(); + void annotateConflicts(); Arabica::DOM::Document<std::string> getDocument() const; // overwrite to return flat FSM protected: InterpreterState interpret(); - + GlobalState* _start; Arabica::DOM::Document<std::string> _flatDoc; std::map<std::string, GlobalState*> _globalConf; @@ -270,7 +270,7 @@ protected: private: Arabica::XPath::NodeSet<std::string> refsToStates(const std::set<int>&); Arabica::XPath::NodeSet<std::string> refsToTransitions(const std::set<int>&); - + // gather executable content per microstep void executeContent(const Arabica::DOM::Element<std::string>& content, bool rethrow = false); @@ -301,12 +301,12 @@ private: void updateRaisedAndSendChains(GlobalState* state, GlobalTransition* source, std::set<GlobalTransition*> visited); void reassembleFromFlat(); - + std::list<GlobalTransition*> sortTransitions(std::list<GlobalTransition*> list); // we need this static as we use it in a sort function static std::map<Arabica::DOM::Node<std::string>, Arabica::DOM::Node<std::string> > _transParents; - + static bool filterSameState(const Arabica::XPath::NodeSet<std::string>& transitions); uint64_t _perfTransProcessed; @@ -334,13 +334,13 @@ private: size_t _maxEventSentChain; size_t _maxEventRaisedChain; size_t _doneEventRaiseTolerance; - + GlobalTransition* _currGlobalTransition; std::map<std::string, std::map<std::string, GlobalTransition*> > _confToTransitions; - + TransitionTreeNode* _transTree; std::map<Arabica::DOM::Element<std::string>, TransitionTreeNode*> _stateToTransTreeNode; - + friend class GlobalTransition; friend class GlobalState; }; diff --git a/src/uscxml/transform/ChartToFlatSCXML.cpp b/src/uscxml/transform/ChartToFlatSCXML.cpp index c554218..2905444 100644 --- a/src/uscxml/transform/ChartToFlatSCXML.cpp +++ b/src/uscxml/transform/ChartToFlatSCXML.cpp @@ -52,7 +52,7 @@ ChartToFlatSCXML::operator Interpreter() { return Interpreter::fromClone(shared_from_this()); } - + Transformer ChartToFlatSCXML::transform(const Interpreter& other) { return boost::shared_ptr<TransformerImpl>(new ChartToFlatSCXML(other)); } @@ -79,10 +79,10 @@ void ChartToFlatSCXML::writeTo(std::ostream& stream) { if (HAS_ATTR(element, "final-target")) element.removeAttribute("final-target"); } - + if (envVarIsTrue("USCXML_FLAT_FSM_METRICS_ONLY")) return; - + stream << _scxml; } @@ -90,7 +90,7 @@ void ChartToFlatSCXML::createDocument() { if (HAS_ATTR(_scxml, "flat") && stringIsTrue(ATTR(_scxml, "flat"))) return; - + { NodeSet<std::string> allElements = filterChildType(Node_base::ELEMENT_NODE, _scxml, true); size_t nrElements = 0; @@ -100,36 +100,36 @@ void ChartToFlatSCXML::createDocument() { } std::cerr << "Number of elements before flattening: " << nrElements + 1 << std::endl; } - + if (_start == NULL) interpret(); // only if not already flat! - + if (envVarIsTrue("USCXML_FLAT_FSM_METRICS_ONLY")) return; - + Element<std::string> _origSCXML = _scxml; - + _scxml = _flatDoc.createElementNS(_nsInfo.nsURL, "scxml"); _nsInfo.setPrefix(_scxml); - + _scxml.setAttribute("flat", "true"); _flatDoc.appendChild(_scxml); - + if (HAS_ATTR(_origSCXML, "datamodel")) { _scxml.setAttribute("datamodel", ATTR(_origSCXML, "datamodel")); } - + if (HAS_ATTR(_origSCXML, "name")) { _scxml.setAttribute("name", ATTR(_origSCXML, "name")); } - + if (HAS_ATTR(_origSCXML, "binding")) { _scxml.setAttribute("binding", ATTR(_origSCXML, "binding")); } - + _scxml.setAttribute("initial", _start->stateId); - + NodeSet<std::string> datas; if (_binding == InterpreterImpl::LATE) { // with late binding, just copy direct datamodel childs @@ -144,34 +144,34 @@ void ChartToFlatSCXML::createDocument() { Node<std::string> imported = _flatDoc.importNode(datas[i], true); _scxml.appendChild(imported); } - - + + NodeSet<std::string> scripts = filterChildElements(_nsInfo.xmlNSPrefix + "script", _origSCXML); for (int i = 0; i < scripts.size(); i++) { Node<std::string> imported = _flatDoc.importNode(scripts[i], true); _scxml.appendChild(imported); } - + NodeSet<std::string> comments = filterChildType(Node_base::COMMENT_NODE, _origSCXML); for (int i = 0; i < comments.size(); i++) { Node<std::string> imported = _flatDoc.importNode(comments[i], true); _scxml.appendChild(imported); } - + std::vector<std::pair<std::string,GlobalState*> > sortedStates; sortedStates.insert(sortedStates.begin(), _globalConf.begin(), _globalConf.end()); std::sort(sortedStates.begin(), sortedStates.end(), sortStatesByIndex); - + // int index = 0; // for (std::vector<Element<std::string> >::iterator transIter = indexedTransitions.begin(); transIter != indexedTransitions.end(); transIter++) { // const Element<std::string>& refTrans = *transIter; // std::cerr << index++ << ": " << refTrans << std::endl; // } // std::cerr << std::endl; - + for (std::vector<std::pair<std::string,GlobalState*> >::iterator confIter = sortedStates.begin(); - confIter != sortedStates.end(); - confIter++) { + confIter != sortedStates.end(); + confIter++) { appendGlobalStateNode(confIter->second); } @@ -181,7 +181,7 @@ void ChartToFlatSCXML::createDocument() { if (scxmls.size() > 0) { _scxml = Element<std::string>(scxmls[0]); } - + { NodeSet<std::string> allElements = filterChildType(Node_base::ELEMENT_NODE, _scxml, true); size_t nrElements = 0; @@ -191,29 +191,29 @@ void ChartToFlatSCXML::createDocument() { } std::cerr << "Number of elements after flattening: " << nrElements + 1 << std::endl; } - + } void ChartToFlatSCXML::appendGlobalStateNode(GlobalState* globalState) { Element<std::string> state = _flatDoc.createElementNS(_nsInfo.nsURL, "state"); _nsInfo.setPrefix(state); - + state.setAttribute("step", toStr(globalState->index)); state.setAttribute("id", globalState->stateId); - + if (globalState->isFinal) state.setAttribute("final", "true"); - + std::list<GlobalTransition*>& transitionList = globalState->sortedOutgoing; - + // apend here, for transient state chains to trail the state _scxml.appendChild(state); - + size_t index = 0; for (std::list<GlobalTransition*>::iterator outIter = transitionList.begin(); - outIter != transitionList.end(); - outIter++) { + outIter != transitionList.end(); + outIter++) { // (*outIter)->index = globalState->index + ":" + toStr(index); state.appendChild(globalTransitionToNode(*outIter)); index++; @@ -226,48 +226,48 @@ void ChartToFlatSCXML::appendGlobalStateNode(GlobalState* globalState) { Node<std::string> ChartToFlatSCXML::globalTransitionToNode(GlobalTransition* globalTransition) { Element<std::string> transition = _flatDoc.createElementNS(_nsInfo.nsURL, "transition"); _nsInfo.setPrefix(transition); - + // transition.setAttribute("ref", globalTransition->index); - + #if 1 transition.setAttribute("members", globalTransition->members); #endif // transition.setAttribute("priority", toStr(globalTransition->priority)); - + if (!globalTransition->isEventless) { transition.setAttribute("event", globalTransition->eventDesc); } - + if (globalTransition->condition.size() > 0) { transition.setAttribute("cond", globalTransition->condition); } - + if (globalTransition->destination.size() > 0) { transition.setAttribute("final-target", globalTransition->destination); } - + NodeSet<std::string> transientStateChain; - + // current active state set FlatStateIdentifier flatId(globalTransition->source); std::list<std::string> currActiveStates = flatId.getActive(); - + // std::cerr << "From " << globalTransition->source << " to " << globalTransition->destination << ":" << std::endl; - + // gather content for new transient state NodeSet<std::string> childs; - + // aggregated entering / exiting to avoid states without childs while still labeling std::list<Arabica::DOM::Comment<std::string> > pendingComments; - + // iterate all actions taken during the transition for (std::list<GlobalTransition::Action>::iterator actionIter = globalTransition->actions.begin(); - actionIter != globalTransition->actions.end(); - actionIter++) { - + actionIter != globalTransition->actions.end(); + actionIter++) { + if (actionIter->transition) { // DETAIL_EXEC_CONTENT(transition, actionIter); - + Element<std::string> onexit = _flatDoc.createElementNS(_nsInfo.nsURL, "onexit"); _nsInfo.setPrefix(onexit); Node<std::string> child = actionIter->transition.getFirstChild(); @@ -286,7 +286,7 @@ Node<std::string> ChartToFlatSCXML::globalTransitionToNode(GlobalTransition* glo if (HAS_ATTR(actionIter->transition, "target")) commentSS << " to target '" << ATTR(actionIter->transition, "target") << "'"; commentSS << " "; - + if (onexit.hasChildNodes()) { if (envVarIsTrue("USCXML_ANNOTATE_VERBOSE_COMMENTS")) childs.push_back(_flatDoc.createComment(commentSS.str())); @@ -295,16 +295,16 @@ Node<std::string> ChartToFlatSCXML::globalTransitionToNode(GlobalTransition* glo if (envVarIsTrue("USCXML_ANNOTATE_VERBOSE_COMMENTS")) pendingComments.push_back(_flatDoc.createComment(commentSS.str())); } - + continue; } - + if (actionIter->onExit) { // DETAIL_EXEC_CONTENT(onExit, actionIter); childs.push_back(actionIter->onExit); continue; } - + if (actionIter->onEntry) { // DETAIL_EXEC_CONTENT(onEntry, actionIter); childs.push_back(actionIter->onEntry); @@ -324,12 +324,12 @@ Node<std::string> ChartToFlatSCXML::globalTransitionToNode(GlobalTransition* glo childs.push_back(invokeElem); continue; } - + if (actionIter->uninvoke) { // DETAIL_EXEC_CONTENT(uninvoke, actionIter); Element<std::string> uninvokeElem = _flatDoc.createElementNS(_nsInfo.nsURL, "uninvoke"); _nsInfo.setPrefix(uninvokeElem); - + if (HAS_ATTR(actionIter->uninvoke, "type")) { uninvokeElem.setAttribute("type", ATTR(actionIter->uninvoke, "type")); } @@ -345,7 +345,7 @@ Node<std::string> ChartToFlatSCXML::globalTransitionToNode(GlobalTransition* glo childs.push_back(uninvokeElem); continue; } - + if (actionIter->exited) { currActiveStates.remove(ATTR_CAST(actionIter->exited, "id")); if (childs.size() > 0) { @@ -358,7 +358,7 @@ Node<std::string> ChartToFlatSCXML::globalTransitionToNode(GlobalTransition* glo pendingComments.push_back(_flatDoc.createComment(" Exiting " + ATTR_CAST(actionIter->exited, "id") + " ")); } } - + if (actionIter->entered) { if (childs.size() > 0) { if (envVarIsTrue("USCXML_ANNOTATE_VERBOSE_COMMENTS")) @@ -369,7 +369,7 @@ Node<std::string> ChartToFlatSCXML::globalTransitionToNode(GlobalTransition* glo pendingComments.push_back(_flatDoc.createComment(" Entering " + ATTR_CAST(actionIter->entered, "id") + " ")); } currActiveStates.push_back(ATTR_CAST(actionIter->entered, "id")); - + // we entered a new child - check if it has a datamodel and we entered for the first time if (_binding == InterpreterImpl::LATE) { NodeSet<std::string> datamodel = filterChildElements(_nsInfo.xmlNSPrefix + "datamodel", actionIter->entered); @@ -379,35 +379,35 @@ Node<std::string> ChartToFlatSCXML::globalTransitionToNode(GlobalTransition* glo } } } - + CREATE_TRANSIENT_STATE_WITH_CHILDS(FlatStateIdentifier::toStateId(currActiveStates)) - + if (transientStateChain.size() > 0) { Element<std::string> prevExitTransitionElem; - + for (int i = 0; i < transientStateChain.size(); i++) { Element<std::string> transientStateElem = Element<std::string>(transientStateChain[i]); transientStateElem.setAttribute("id", transientStateElem.getAttribute("id") + "-via-" + toStr(_lastTransientStateId++)); - + Element<std::string> exitTransition = _flatDoc.createElementNS(_nsInfo.nsURL, "transition"); _nsInfo.setPrefix(exitTransition); - + if (prevExitTransitionElem) { // point previous to this one prevExitTransitionElem.setAttribute("target", transientStateElem.getAttribute("id")); } else { // update globalTransition->source target } - + transientStateElem.appendChild(exitTransition); prevExitTransitionElem = exitTransition; - + if (i == 0) transition.setAttribute("target", transientStateElem.getAttribute("id")); - + _scxml.appendChild(transientStateElem); } - + // last one points to actual target assert(prevExitTransitionElem); prevExitTransitionElem.setAttribute("target", globalTransition->destination); @@ -415,11 +415,11 @@ Node<std::string> ChartToFlatSCXML::globalTransitionToNode(GlobalTransition* glo } else if (transientStateChain.size() == 1) { Element<std::string> transientStateElem = Element<std::string>(transientStateChain[0]); transientStateElem.setAttribute("onlyOne", "yes!"); - + Element<std::string> exitTransition = _flatDoc.createElementNS(_nsInfo.nsURL, "transition"); _nsInfo.setPrefix(exitTransition); exitTransition.setAttribute("target", globalTransition->destination); - + transientStateElem.appendChild(exitTransition); _scxml.appendChild(transientStateElem); @@ -428,7 +428,7 @@ Node<std::string> ChartToFlatSCXML::globalTransitionToNode(GlobalTransition* glo } else { transition.setAttribute("target", globalTransition->destination); } - + assert(HAS_ATTR_CAST(transition, "target")); return transition; } diff --git a/src/uscxml/transform/ChartToFlatSCXML.h b/src/uscxml/transform/ChartToFlatSCXML.h index 7afe3c5..a278721 100644 --- a/src/uscxml/transform/ChartToFlatSCXML.h +++ b/src/uscxml/transform/ChartToFlatSCXML.h @@ -33,17 +33,17 @@ public: operator Interpreter(); Arabica::DOM::Document<std::string> getDocument() const { - if (_flatDoc) - return _flatDoc; - return _document; + if (_flatDoc) + return _flatDoc; + return _document; } protected: void writeTo(std::ostream& stream); - + ChartToFlatSCXML(const Interpreter& other) : TransformerImpl(), ChartToFSM(other), _lastTransientStateId(0) {} void createDocument(); - + void appendGlobalStateNode(GlobalState* globalState); Arabica::DOM::Node<std::string> globalTransitionToNode(GlobalTransition* globalTransition); static bool sortStatesByIndex(const std::pair<std::string,GlobalState*>& s1, const std::pair<std::string,GlobalState*>& s2); diff --git a/src/uscxml/transform/ChartToMinimalSCXML.cpp b/src/uscxml/transform/ChartToMinimalSCXML.cpp index ecfa12b..69ac9cb 100644 --- a/src/uscxml/transform/ChartToMinimalSCXML.cpp +++ b/src/uscxml/transform/ChartToMinimalSCXML.cpp @@ -38,7 +38,7 @@ Transformer ChartToMinimalSCXML::transform(const Interpreter& other) { ChartToMinimalSCXML::ChartToMinimalSCXML(const Interpreter& other) : TransformerImpl(), _retainAsComments(false), _step(1) { cloneFrom(other.getImpl()); - + // a bit messy but needed for SCXML IO Processor with session id target _selfPtr = boost::shared_ptr<InterpreterImpl>(this, Deleter()); Interpreter::addInstance(_selfPtr); @@ -47,7 +47,7 @@ ChartToMinimalSCXML::ChartToMinimalSCXML(const Interpreter& other) : Transformer void ChartToMinimalSCXML::writeTo(std::ostream& stream) { addMonitor(this); - + { NodeSet<std::string> allElements = filterChildType(Node_base::ELEMENT_NODE, _scxml, true); size_t nrElements = 0; @@ -57,7 +57,7 @@ void ChartToMinimalSCXML::writeTo(std::ostream& stream) { } std::cerr << "Number of elements before reduction: " << nrElements + 1 << std::endl; } - + // test 278 - move embedded datas to topmost datamodel if (_binding == EARLY) { // move all data elements into topmost datamodel element @@ -75,7 +75,7 @@ void ChartToMinimalSCXML::writeTo(std::ostream& stream) { while(topMostDatamodel.hasChildNodes()) topMostDatamodel.removeChild(topMostDatamodel.getFirstChild()); - + for (int i = 0; i < datas.size(); i++) { if (!isInEmbeddedDocument(datas[i])) { topMostDatamodel.appendChild(datas[i]); @@ -83,10 +83,10 @@ void ChartToMinimalSCXML::writeTo(std::ostream& stream) { } } } - + char* waitForEnv = getenv("USCXML_MINIMIZE_WAIT_MS"); _retainAsComments = envVarIsTrue("USCXML_MINIMIZE_RETAIN_AS_COMMENTS"); - + long waitFor = -1; if (waitForEnv != NULL) { @@ -114,7 +114,7 @@ void ChartToMinimalSCXML::writeTo(std::ostream& stream) { } } stop(); - + removeUnvisited(_scxml); { @@ -140,11 +140,11 @@ void ChartToMinimalSCXML::removeUnvisited(Arabica::DOM::Node<std::string>& node) Element<std::string> elem(node); if (isInEmbeddedDocument(elem) || - (TAGNAME(elem) == _nsInfo.xmlNSPrefix + "param") || - (TAGNAME(elem) == _nsInfo.xmlNSPrefix + "donedata") || - (TAGNAME(elem) == _nsInfo.xmlNSPrefix + "datamodel") || - (TAGNAME(elem) == _nsInfo.xmlNSPrefix + "data") || - (TAGNAME(elem) == _nsInfo.xmlNSPrefix + "content")) { + (TAGNAME(elem) == _nsInfo.xmlNSPrefix + "param") || + (TAGNAME(elem) == _nsInfo.xmlNSPrefix + "donedata") || + (TAGNAME(elem) == _nsInfo.xmlNSPrefix + "datamodel") || + (TAGNAME(elem) == _nsInfo.xmlNSPrefix + "data") || + (TAGNAME(elem) == _nsInfo.xmlNSPrefix + "content")) { return; } @@ -168,14 +168,14 @@ void ChartToMinimalSCXML::removeUnvisited(Arabica::DOM::Node<std::string>& node) } } } - + // test344 if (_dmCopy && - TAGNAME(elem) == _nsInfo.xmlNSPrefix + "transition" && - HAS_ATTR(elem, "cond") && - !_dmCopy.isValidSyntax(ATTR(elem, "cond"))) + TAGNAME(elem) == _nsInfo.xmlNSPrefix + "transition" && + HAS_ATTR(elem, "cond") && + !_dmCopy.isValidSyntax(ATTR(elem, "cond"))) return; - + // detach unvisited nodes from DOM if (_visited.find(node) == _visited.end()) { std::cerr << DOMUtils::xPathForNode(node) << std::endl; @@ -198,13 +198,13 @@ void ChartToMinimalSCXML::removeUnvisited(Arabica::DOM::Node<std::string>& node) removeUnvisited(child); } } - + void ChartToMinimalSCXML::markAsVisited(const Arabica::DOM::Element<std::string>& element) { if (_visited.find(element) != _visited.end()) return; - + Arabica::DOM::Element<std::string> elem = const_cast<Arabica::DOM::Element<std::string>&>(element); - + _visited.insert(element); Node<std::string> parent = element.getParentNode(); if (parent && parent.getNodeType() == Node_base::ELEMENT_NODE) { @@ -212,7 +212,7 @@ void ChartToMinimalSCXML::markAsVisited(const Arabica::DOM::Element<std::string> markAsVisited(parentElem); } } - + void ChartToMinimalSCXML::beforeExecutingContent(Interpreter interpreter, const Arabica::DOM::Element<std::string>& element) { markAsVisited(element); StateTransitionMonitor::beforeExecutingContent(interpreter, element); @@ -229,7 +229,7 @@ void ChartToMinimalSCXML::beforeTakingTransition(Interpreter interpreter, const markAsVisited(Arabica::DOM::Element<std::string>(targets[i])); } markAsVisited(transition); - + std::stringstream commentSS; if (HAS_ATTR(transition, "event")) { commentSS << " Step #" << _step++ << " - transition taken for event '" << _currEvent.name << "' "; @@ -244,10 +244,10 @@ void ChartToMinimalSCXML::beforeTakingTransition(Interpreter interpreter, const void ChartToMinimalSCXML::beforeEnteringState(Interpreter interpreter, const Arabica::DOM::Element<std::string>& state, bool moreComing) { markAsVisited(state); - + std::stringstream commentSS; commentSS << " Step #" << _step++ << " - state entered "; - + Arabica::DOM::Element<std::string> ncState = const_cast<Arabica::DOM::Element<std::string>&>(state); if (envVarIsTrue("USCXML_ANNOTATE_PROGRESS")) ncState.insertBefore(_document.createComment(commentSS.str()), ncState.getFirstChild()); diff --git a/src/uscxml/transform/ChartToMinimalSCXML.h b/src/uscxml/transform/ChartToMinimalSCXML.h index 3cdab54..0260ee1 100644 --- a/src/uscxml/transform/ChartToMinimalSCXML.h +++ b/src/uscxml/transform/ChartToMinimalSCXML.h @@ -37,7 +37,7 @@ class USCXML_API ChartToMinimalSCXML : public InterpreterRC, public StateTransit public: virtual ~ChartToMinimalSCXML() {} static Transformer transform(const Interpreter& other); - + // InterpreterMonitor virtual void beforeExecutingContent(Interpreter interpreter, const Arabica::DOM::Element<std::string>& element); virtual void beforeUninvoking(Interpreter interpreter, const Arabica::DOM::Element<std::string>& invokeElem, const std::string& invokeid); @@ -49,33 +49,35 @@ public: // gather executable content per microstep void executeContent(const Arabica::DOM::Element<std::string>& content, bool rethrow = false); - + // invoke and uninvoke virtual void invoke(const Arabica::DOM::Element<std::string>& element); virtual void cancelInvoke(const Arabica::DOM::Element<std::string>& element); protected: void writeTo(std::ostream& stream); - + ChartToMinimalSCXML(const Interpreter& other); - + void markAsVisited(const Arabica::DOM::Element<std::string>& element); void removeUnvisited(Arabica::DOM::Node<std::string>& node); std::set<Arabica::DOM::Node<std::string> > _visited; DataModel _dmCopy; bool _retainAsComments; - + private: size_t _step; - + // we need this to register as an instance at Interpreter::_instances boost::shared_ptr<InterpreterImpl> _selfPtr; - + // prevent deletion from shared_ptr class Deleter { public: - void operator()(ChartToMinimalSCXML* p) { /* do nothing */ } + void operator()(ChartToMinimalSCXML* p) { + /* do nothing */ + } }; }; diff --git a/src/uscxml/transform/ChartToPromela.cpp b/src/uscxml/transform/ChartToPromela.cpp index 03178f0..4e3a990 100644 --- a/src/uscxml/transform/ChartToPromela.cpp +++ b/src/uscxml/transform/ChartToPromela.cpp @@ -109,7 +109,7 @@ for (std::set<int>::iterator transRefIter = transList->transitionRefs.begin(); \ stream << padding << _prefix << "transitions[" << *transRefIter << "] = "#value"; " << std::endl; \ } \ } \ - + #define DUMP_STATS(disregardTime) \ uint64_t now = tthread::chrono::system_clock::now(); \ @@ -142,11 +142,11 @@ void ChartToPromela::writeTo(std::ostream& stream) { writeProgram(stream); } - + void PromelaCodeAnalyzer::addCode(const std::string& code, ChartToPromela* interpreter) { PromelaParser parser(code); // parser.dump(); - + // find all strings std::list<PromelaParserNode*> astNodes; astNodes.push_back(parser.ast); @@ -160,7 +160,7 @@ void PromelaCodeAnalyzer::addCode(const std::string& code, ChartToPromela* inter bool hasValue = false; int assignedValue = 0; - + switch (node->type) { case PML_STRING: { std::string unquoted = node->value; @@ -193,8 +193,8 @@ void PromelaCodeAnalyzer::addCode(const std::string& code, ChartToPromela* inter std::list<PromelaParserNode*>::iterator opIter = node->operands.begin(); if ((*opIter)->type != PML_NAME) { node->dump(); - return; - assert(false); + return; + assert(false); } PromelaTypedef* td = &_typeDefs; @@ -249,14 +249,14 @@ void PromelaCodeAnalyzer::addCode(const std::string& code, ChartToPromela* inter } opIter++; } - + if (hasValue) { if (td->maxValue < assignedValue) td->maxValue = assignedValue; if (td->minValue > assignedValue) td->minValue = assignedValue; } - + continue; // skip processing nested AST nodes } case PML_NAME: { @@ -300,7 +300,7 @@ void PromelaCodeAnalyzer::addOrigState(const std::string& stateName) { createMacroName(stateName); } } - + void PromelaCodeAnalyzer::addState(const std::string& stateName) { if (_states.find(stateName) != _states.end()) return; @@ -367,7 +367,7 @@ std::string PromelaCodeAnalyzer::createMacroName(const std::string& literal) { macroName = "_EMPTY_STRING"; if(macroName.length() < 2 && macroName[0] == '_') macroName = "_WEIRD_CHARS"; - + unsigned int index = 2; while (_macroNameSet.find(macroName) != _macroNameSet.end()) { std::string suffix = toStr(index); @@ -384,45 +384,45 @@ std::string PromelaCodeAnalyzer::createMacroName(const std::string& literal) { return macroName; } - std::string PromelaCodeAnalyzer::getTypeReset(const std::string& var, const PromelaTypedef& type, const std::string padding) { - std::stringstream assignment; - - std::map<std::string, PromelaTypedef>::const_iterator typeIter = type.types.begin(); - while(typeIter != type.types.end()) { - const PromelaTypedef& innerType = typeIter->second; - if (innerType.arraySize > 0) { - for (int i = 0; i < innerType.arraySize; i++) { - assignment << padding << var << "." << typeIter->first << "[" << i << "] = 0;" << std::endl; - } - } else if (innerType.types.size() > 0) { - assignment << getTypeReset(var + "." + typeIter->first, typeIter->second, padding); - } else { - assignment << padding << var << "." << typeIter->first << " = 0;" << std::endl; - } - typeIter++; - } - return assignment.str(); +std::string PromelaCodeAnalyzer::getTypeReset(const std::string& var, const PromelaTypedef& type, const std::string padding) { + std::stringstream assignment; + + std::map<std::string, PromelaTypedef>::const_iterator typeIter = type.types.begin(); + while(typeIter != type.types.end()) { + const PromelaTypedef& innerType = typeIter->second; + if (innerType.arraySize > 0) { + for (int i = 0; i < innerType.arraySize; i++) { + assignment << padding << var << "." << typeIter->first << "[" << i << "] = 0;" << std::endl; + } + } else if (innerType.types.size() > 0) { + assignment << getTypeReset(var + "." + typeIter->first, typeIter->second, padding); + } else { + assignment << padding << var << "." << typeIter->first << " = 0;" << std::endl; + } + typeIter++; + } + return assignment.str(); } std::string PromelaCodeAnalyzer::getTypeAssignment(const std::string& varTo, const std::string& varFrom, const PromelaTypedef& type, const std::string padding) { - std::stringstream assignment; - - std::map<std::string, PromelaTypedef>::const_iterator typeIter = type.types.begin(); - while(typeIter != type.types.end()) { - const PromelaTypedef& innerType = typeIter->second; - if (innerType.arraySize > 0) { - for (int i = 0; i < innerType.arraySize; i++) { - assignment << padding << varTo << "." << typeIter->first << "[" << i << "] = " << varFrom << "." << typeIter->first << "[" << i << "];" << std::endl; - } - } else if (innerType.types.size() > 0) { - assignment << getTypeAssignment(varTo + "." + typeIter->first, varFrom + "." + typeIter->first, typeIter->second, padding); - } else { - assignment << padding << varTo << "." << typeIter->first << " = " << varFrom << "." << typeIter->first << ";" << std::endl; - } - typeIter++; - } - return assignment.str(); + std::stringstream assignment; + + std::map<std::string, PromelaTypedef>::const_iterator typeIter = type.types.begin(); + while(typeIter != type.types.end()) { + const PromelaTypedef& innerType = typeIter->second; + if (innerType.arraySize > 0) { + for (int i = 0; i < innerType.arraySize; i++) { + assignment << padding << varTo << "." << typeIter->first << "[" << i << "] = " << varFrom << "." << typeIter->first << "[" << i << "];" << std::endl; + } + } else if (innerType.types.size() > 0) { + assignment << getTypeAssignment(varTo + "." + typeIter->first, varFrom + "." + typeIter->first, typeIter->second, padding); + } else { + assignment << padding << varTo << "." << typeIter->first << " = " << varFrom << "." << typeIter->first << ";" << std::endl; + } + typeIter++; + } + return assignment.str(); } std::string PromelaCodeAnalyzer::macroForLiteral(const std::string& literal) { @@ -464,14 +464,14 @@ std::string PromelaCodeAnalyzer::adaptCode(const std::string& code, const std::s posList.sort(); posIter = posList.begin(); lastPos = 0; - + while (posIter != posList.end()) { processedStr << code.substr(lastPos, posIter->first - lastPos) << prefix; lastPos = posIter->first; posIter++; } processedStr << processed.substr(lastPos, processed.size() - lastPos); - + processed = processedStr.str(); processedStr.clear(); processedStr.str(""); @@ -494,12 +494,12 @@ std::string PromelaCodeAnalyzer::adaptCode(const std::string& code, const std::s posIter++; } processedStr << processed.substr(lastPos, processed.size() - lastPos); - + processed = processedStr.str(); processedStr.clear(); processedStr.str(""); } - + return processed; } @@ -507,7 +507,7 @@ std::string PromelaCodeAnalyzer::adaptCode(const std::string& code, const std::s // PromelaParser parsed(expr); // std::list<size_t> posList = getTokenPositions(expr, PML_NAME, parsed.ast); // posList.sort(); -// +// // std::stringstream prefixed; // std::list<size_t>::iterator posIter = posList.begin(); // size_t lastPos = 0; @@ -516,18 +516,18 @@ std::string PromelaCodeAnalyzer::adaptCode(const std::string& code, const std::s // lastPos = *posIter; // posIter++; // } -// +// // prefixed << expr.substr(lastPos, expr.size() - lastPos); // return prefixed.str(); //} - + std::list<std::pair<size_t, size_t> > PromelaCodeAnalyzer::getTokenPositions(const std::string& expr, int type, PromelaParserNode* ast) { std::list<std::pair<size_t, size_t> > posList; if (ast->type == type && ast->loc != NULL) { // ast->dump(); if (type == PML_NAME && ast->parent && - ((ast->parent->type == PML_CMPND && ast->parent->operands.front() != ast) || - (ast->parent->parent && ast->parent->type == PML_VAR_ARRAY && ast->parent->parent->type == PML_CMPND))) { + ((ast->parent->type == PML_CMPND && ast->parent->operands.front() != ast) || + (ast->parent->parent && ast->parent->type == PML_VAR_ARRAY && ast->parent->parent->type == PML_CMPND))) { // field in a compound } else { if (ast->loc->firstLine == 0) { @@ -549,7 +549,7 @@ std::list<std::pair<size_t, size_t> > PromelaCodeAnalyzer::getTokenPositions(con } return posList; } - + std::set<std::string> PromelaCodeAnalyzer::getEventsWithPrefix(const std::string& prefix) { std::set<std::string> eventNames; std::list<TrieNode*> trieNodes = _eventTrie.getWordsWithPrefix(prefix); @@ -588,14 +588,14 @@ void ChartToPromela::writeEvents(std::ostream& stream) { void ChartToPromela::writeStates(std::ostream& stream) { stream << "/* state name identifiers */" << std::endl; - + std::map<std::string, GlobalState*>::iterator stateIter = _activeConf.begin(); while(stateIter != _activeConf.end()) { stream << "#define " << "s" << stateIter->second->activeIndex << " " << stateIter->second->activeIndex; stream << " /* from \"" << stateIter->first << "\" */" << std::endl; stateIter++; } - + // for (int i = 0; i < _globalConf.size(); i++) { // stream << "#define " << "s" << i << " " << i; // stream << " /* from \"" << ATTR_CAST(_globalStates[i], "id") << "\" */" << std::endl; @@ -637,7 +637,7 @@ void ChartToPromela::writeHistoryArrays(std::ostream& stream) { histNameIter++; } } - + void ChartToPromela::writeTypeDefs(std::ostream& stream) { stream << "/* type definitions */" << std::endl; PromelaCodeAnalyzer::PromelaTypedef typeDefs = _analyzer->getTypes(); @@ -672,7 +672,7 @@ void ChartToPromela::writeTypeDefs(std::ostream& stream) { stream << " int delay;" << std::endl; #if NEW_DELAY_RESHUFFLE #else - stream << " int seqNr;" << std::endl; + stream << " int seqNr;" << std::endl; #endif } stream << " int name;" << std::endl; @@ -682,9 +682,9 @@ void ChartToPromela::writeTypeDefs(std::ostream& stream) { } for (std::map<std::string, PromelaCodeAnalyzer::PromelaTypedef>::iterator tIter = currDef.types.begin(); tIter != currDef.types.end(); tIter++) { if (currDef.name.compare("_event_t") == 0 && (tIter->first.compare("name") == 0 || - tIter->first.compare("seqNr") == 0 || - tIter->first.compare("invokeid") == 0 || - tIter->first.compare("delay") == 0)) { // special treatment for _event + tIter->first.compare("seqNr") == 0 || + tIter->first.compare("invokeid") == 0 || + tIter->first.compare("delay") == 0)) { // special treatment for _event continue; } if (currDef.name.compare("_x_t") == 0 && tIter->first.compare("states") == 0) { @@ -729,7 +729,7 @@ std::string ChartToPromela::declForRange(const std::string& identifier, long min return "int " + identifier; return "short " + identifier; } - + // type is definitely positive if (nativeOnly) { if (maxValue > 32767) @@ -768,7 +768,7 @@ std::string ChartToPromela::conditionForHistoryTransition(const GlobalTransition FlatStateIdentifier flatSource(transition->source); FlatStateIdentifier flatTarget(transition->destination); std::string condition; - + return condition; } @@ -777,22 +777,22 @@ std::string ChartToPromela::conditionalizeForHist(GlobalTransition* transition, transitions.insert(transition); return conditionalizeForHist(transitions); } - + std::string ChartToPromela::conditionalizeForHist(const std::set<GlobalTransition*>& transitions, int indent) { std::stringstream condition; std::string memberSep; - + std::set<std::map<std::string, std::list<std::string> > > histSeen; - + for (std::set<GlobalTransition*>::const_iterator transIter = transitions.begin(); transIter != transitions.end(); transIter++) { if ((*transIter)->histTargets.size() == 0) // there are no history transitions in here! continue; - + std::map<std::string, std::list<std::string> > relevantHist; std::map<std::string, std::list<std::string> > currentHist; FlatStateIdentifier flatSource((*transIter)->source); currentHist = flatSource.getHistory(); - + std::set<std::string>::iterator histTargetIter = (*transIter)->histTargets.begin(); while(histTargetIter != (*transIter)->histTargets.end()) { if (currentHist.find(*histTargetIter) != currentHist.end()) { @@ -802,17 +802,17 @@ std::string ChartToPromela::conditionalizeForHist(const std::set<GlobalTransitio } if (relevantHist.size() == 0) continue; - + if (histSeen.find(relevantHist) != histSeen.end()) continue; histSeen.insert(relevantHist); - + std::string itemSep; std::map<std::string, std::list<std::string> >::iterator relevanthistIter = relevantHist.begin(); if (relevantHist.size() > 0) condition << memberSep; - + while(relevanthistIter != relevantHist.end()) { std::list<std::string>::iterator histItemIter = relevanthistIter->second.begin(); while(histItemIter != relevanthistIter->second.end()) { @@ -849,7 +849,7 @@ std::string ChartToPromela::conditionalizeForHist(const std::set<GlobalTransitio // NodeSet<std::string> transitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", currState); // currState = _globalConf[ATTR_CAST(transitions[0], "target")]; // } -// +// // return content; //} @@ -859,53 +859,53 @@ void ChartToPromela::writeTransition(std::ostream& stream, GlobalTransition* tra padding += " "; } std::list<GlobalTransition*>::const_iterator histIter; - - if (envVarIsTrue("USCXML_ANNOTATE_NOCOMMENT")) { - stream << std::endl << _prefix << "t" << transition->index << ": /* ######################## */ " << std::endl; - - } else { - - stream << std::endl << _prefix << "t" << transition->index << ": /* ######################## " << std::endl; - FlatStateIdentifier flatActiveSource(transition->source); - stream << " from state: "; - PRETTY_PRINT_LIST(stream, flatActiveSource.getActive()); - stream << std::endl; - // stream << " with history: " << flatActiveSource.getFlatHistory() << std::endl; - stream << " ----- on event: " << (transition->eventDesc.size() > 0 ? transition->eventDesc : "SPONTANEOUS") << " --" << std::endl; - stream << " to state: "; - std::set<FlatStateIdentifier> destinations; - destinations.insert(FlatStateIdentifier(transition->destination)); - histIter = transition->historyTrans.begin(); - while(histIter != transition->historyTrans.end()) { - destinations.insert(FlatStateIdentifier((*histIter)->destination)); - histIter++; - } - std::string seperator = ""; - for (std::set<FlatStateIdentifier>::iterator destIter = destinations.begin(); destIter != destinations.end(); destIter++) { - stream << seperator; - PRETTY_PRINT_LIST(stream, destIter->getActive()); - stream << " with " << (destIter->getFlatHistory().size() > 0 ? destIter->getFlatHistory() : "no history"); - seperator = "\n "; - } - stream << std::endl; - - stream << "############################### */" << std::endl; - } - stream << std::endl; + + if (envVarIsTrue("USCXML_ANNOTATE_NOCOMMENT")) { + stream << std::endl << _prefix << "t" << transition->index << ": /* ######################## */ " << std::endl; + + } else { + + stream << std::endl << _prefix << "t" << transition->index << ": /* ######################## " << std::endl; + FlatStateIdentifier flatActiveSource(transition->source); + stream << " from state: "; + PRETTY_PRINT_LIST(stream, flatActiveSource.getActive()); + stream << std::endl; + // stream << " with history: " << flatActiveSource.getFlatHistory() << std::endl; + stream << " ----- on event: " << (transition->eventDesc.size() > 0 ? transition->eventDesc : "SPONTANEOUS") << " --" << std::endl; + stream << " to state: "; + std::set<FlatStateIdentifier> destinations; + destinations.insert(FlatStateIdentifier(transition->destination)); + histIter = transition->historyTrans.begin(); + while(histIter != transition->historyTrans.end()) { + destinations.insert(FlatStateIdentifier((*histIter)->destination)); + histIter++; + } + std::string seperator = ""; + for (std::set<FlatStateIdentifier>::iterator destIter = destinations.begin(); destIter != destinations.end(); destIter++) { + stream << seperator; + PRETTY_PRINT_LIST(stream, destIter->getActive()); + stream << " with " << (destIter->getFlatHistory().size() > 0 ? destIter->getFlatHistory() : "no history"); + seperator = "\n "; + } + stream << std::endl; + + stream << "############################### */" << std::endl; + } + stream << std::endl; stream << padding << "skip;" << std::endl; stream << padding << "d_step {" << std::endl; if (_writeTransitionPrintfs) stream << padding << " printf(\"Taking Transition " << _prefix << "t" << transition->index << "\\n\");" << std::endl; - + padding += " "; indent++; - + // iterators of history transitions executable content std::map<GlobalTransition*, std::pair<GlobalTransition::Action::iter_t, GlobalTransition::Action::iter_t> > actionIters; std::map<GlobalTransition*, std::set<GlobalTransition::Action> > actionsInTransition; typedef std::map<GlobalTransition*, std::pair<GlobalTransition::Action::iter_t, GlobalTransition::Action::iter_t> > actionIters_t; - + histIter = transition->historyTrans.begin(); while(histIter != transition->historyTrans.end()) { actionIters.insert(std::make_pair((*histIter), std::make_pair((*histIter)->actions.begin(), (*histIter)->actions.end()))); @@ -922,16 +922,16 @@ void ChartToPromela::writeTransition(std::ostream& stream, GlobalTransition* tra } // std::copy(transition->actions.begin(), transition->actions.end(), std::inserter(actionsInTransition[transition], actionsInTransition[transition].begin())); - + // GlobalTransition::Action action; std::set<GlobalTransition*> allBut; std::list<ExecContentSeqItem> ecSeq; - + for (std::list<GlobalTransition::Action>::const_iterator actionIter = transition->actions.begin(); actionIter != transition->actions.end(); actionIter++) { // for every executable content in base transition const GlobalTransition::Action& baseAction = *actionIter; allBut.clear(); - + for (actionIters_t::iterator histActionIter = actionIters.begin(); histActionIter != actionIters.end(); histActionIter++) { // iterate every history transition GlobalTransition* histTrans = histActionIter->first; @@ -945,7 +945,7 @@ void ChartToPromela::writeTransition(std::ostream& stream, GlobalTransition* tra if (baseAction != histAction && !baseAction.raiseDone) { // std::cout << baseAction << std::endl; // std::cout << histAction << std::endl; - + // executable content differs - will given executable content appear later in history? if (actionsInTransition[histTrans].find(baseAction) != actionsInTransition[histTrans].end()) { // yes -> write all exec content exclusive to this history transition until base executable content @@ -964,7 +964,7 @@ void ChartToPromela::writeTransition(std::ostream& stream, GlobalTransition* tra histActionIter->second.first++; } } - + if (allBut.empty()) { // everyone has the current actionIter one behind the base action ecSeq.push_back(ExecContentSeqItem(ExecContentSeqItem::EXEC_CONTENT_EVERY, NULL, baseAction)); @@ -973,7 +973,7 @@ void ChartToPromela::writeTransition(std::ostream& stream, GlobalTransition* tra ecSeq.push_back(ExecContentSeqItem(ExecContentSeqItem::EXEC_CONTENT_ALL_BUT, allBut, baseAction)); } } - + // see what remains in history transitions and add as exclusive for (actionIters_t::iterator histActionIter = actionIters.begin(); histActionIter != actionIters.end(); histActionIter++) { GlobalTransition* histTrans = histActionIter->first; @@ -987,7 +987,7 @@ void ChartToPromela::writeTransition(std::ostream& stream, GlobalTransition* tra bool isConditionalized = false; bool wroteHistoryAssignments = false; - + for (std::list<ExecContentSeqItem>::const_iterator ecIter = ecSeq.begin(); ecIter != ecSeq.end(); ecIter++) { const GlobalTransition::Action& action = ecIter->action; @@ -998,11 +998,11 @@ void ChartToPromela::writeTransition(std::ostream& stream, GlobalTransition* tra wroteHistoryAssignments = true; } } - + if (!_analyzer->usesInPredicate() && (action.entered || action.exited)) { continue; } - + if (!isConditionalized && ecIter->type == ExecContentSeqItem::EXEC_CONTENT_ONLY_FOR) { // assert(!wroteHistoryAssignments); // we need to move assignments after dispatching? stream << padding << "if" << std::endl; @@ -1031,18 +1031,18 @@ void ChartToPromela::writeTransition(std::ostream& stream, GlobalTransition* tra case ExecContentSeqItem::EXEC_CONTENT_ONLY_FOR: std::cout << "ONLY_FOR" << std::endl; break; - - default: - break; + + default: + break; } #endif - + if (action.exited) { // we left a state stream << padding << _prefix << "_x.states[" << _analyzer->macroForLiteral(ATTR(action.exited, "id")) << "] = false; " << std::endl; // continue; } - + if (action.entered) { // we entered a state stream << padding << _prefix << "_x.states[" << _analyzer->macroForLiteral(ATTR(action.entered, "id")) << "] = true; " << std::endl; @@ -1055,7 +1055,7 @@ void ChartToPromela::writeTransition(std::ostream& stream, GlobalTransition* tra writeExecutableContent(stream, action.transition, indent); // continue; } - + if (action.onExit) { // std::cout<< action.onExit << std::endl; // executable content from an onexit element @@ -1064,7 +1064,7 @@ void ChartToPromela::writeTransition(std::ostream& stream, GlobalTransition* tra writeExecutableContent(stream, action.onExit, indent); // continue; } - + if (action.onEntry) { // executable content from an onentry element if (action.onEntry.getParentNode()) // this should not be necessary? @@ -1083,7 +1083,7 @@ void ChartToPromela::writeTransition(std::ostream& stream, GlobalTransition* tra if (action.invoke) { // an invoke element - + if (_machines.find(action.invoke) != _machines.end()) { stream << padding << _prefix << "start!" << _analyzer->macroForLiteral(_machines[action.invoke]->_invokerid) << ";" << std::endl; } else { @@ -1093,7 +1093,7 @@ void ChartToPromela::writeTransition(std::ostream& stream, GlobalTransition* tra } } - + if (action.uninvoke) { if (_machines.find(action.uninvoke) != _machines.end()) { stream << padding << "do" << std::endl; @@ -1111,7 +1111,7 @@ void ChartToPromela::writeTransition(std::ostream& stream, GlobalTransition* tra } } } - + if (isConditionalized) { // peek into next content and see if same conditions apply -> keep conditionalization bool sameCondition = false; @@ -1120,7 +1120,7 @@ void ChartToPromela::writeTransition(std::ostream& stream, GlobalTransition* tra if (nextIter != ecSeq.end() && ecIter->type == nextIter->type && ecIter->transitions == nextIter->transitions) { sameCondition = true; } - + if (!sameCondition) { padding = padding.substr(2); indent--; @@ -1137,7 +1137,7 @@ void ChartToPromela::writeTransition(std::ostream& stream, GlobalTransition* tra } } } - + if (!wroteHistoryAssignments) { writeHistoryAssignments(stream, transition, indent); wroteHistoryAssignments = true; @@ -1158,42 +1158,42 @@ void ChartToPromela::writeTransition(std::ostream& stream, GlobalTransition* tra origNewState = _activeConf[transition->activeDestination]; bool hasHistoryTarget = false; - + for (std::map<GlobalState*, std::set<GlobalTransition*> >::const_iterator histTargetIter = histTargets.begin(); histTargetIter != histTargets.end(); histTargetIter++) { GlobalState* histNewState = histTargetIter->first; if (histNewState == origNewState) continue; stream << padding << "if" << std::endl; - if (!envVarIsTrue("USCXML_ANNOTATE_NOCOMMENT")) { - stream << "/* to state "; - FlatStateIdentifier flatActiveDest(histNewState->activeId); - PRETTY_PRINT_LIST(stream, flatActiveDest.getActive()); - stream << " via history */" << std::endl; - } + if (!envVarIsTrue("USCXML_ANNOTATE_NOCOMMENT")) { + stream << "/* to state "; + FlatStateIdentifier flatActiveDest(histNewState->activeId); + PRETTY_PRINT_LIST(stream, flatActiveDest.getActive()); + stream << " via history */" << std::endl; + } - stream << padding << ":: " << conditionalizeForHist(histTargetIter->second) << " -> " << _prefix << "s = s" << histNewState->activeIndex << ";" << std::endl; + stream << padding << ":: " << conditionalizeForHist(histTargetIter->second) << " -> " << _prefix << "s = s" << histNewState->activeIndex << ";" << std::endl; // writeTransitionClosure(stream, *histTargetIter->second.begin(), histNewState, indent + 1); // is this correct for everyone in set? hasHistoryTarget = true; } - + origNewState = _activeConf[transition->activeDestination]; FlatStateIdentifier flatActiveDest(transition->activeDestination); assert(origNewState != NULL); - - if (!envVarIsTrue("USCXML_ANNOTATE_NOCOMMENT")) { - stream << "/* to state "; - PRETTY_PRINT_LIST(stream, flatActiveDest.getActive()); - stream << " */" << std::endl; - } + + if (!envVarIsTrue("USCXML_ANNOTATE_NOCOMMENT")) { + stream << "/* to state "; + PRETTY_PRINT_LIST(stream, flatActiveDest.getActive()); + stream << " */" << std::endl; + } if (hasHistoryTarget) { stream << padding << ":: else -> "; padding += " "; indent++; } - + stream << padding << _prefix << "s = s" << origNewState->activeIndex << ";" << std::endl; @@ -1204,17 +1204,17 @@ void ChartToPromela::writeTransition(std::ostream& stream, GlobalTransition* tra stream << padding << "fi;" << std::endl; } - TRANSITION_TRACE(transition, false); - + TRANSITION_TRACE(transition, false); + padding = padding.substr(2); - stream << padding << "}" << std::endl; + stream << padding << "}" << std::endl; - // moved up here for goto from d_step + // moved up here for goto from d_step writeTransitionClosure(stream, transition, origNewState, indent-1); _perfTransProcessed++; _perfTransTotal++; - + DUMP_STATS(false); } @@ -1224,30 +1224,30 @@ void ChartToPromela::writeHistoryAssignments(std::ostream& stream, GlobalTransit for (int i = 0; i < indent; i++) { padding += " "; } - + if (transition->historyTrans.size() == 0) return; - + // GlobalState to *changed* history configuration std::list<HistoryTransitionClass> histClasses; std::set<GlobalTransition*> allTrans; allTrans.insert(transition); allTrans.insert(transition->historyTrans.begin(), transition->historyTrans.end()); - + // iterate all transitions std::set<GlobalTransition*>::iterator transIter = allTrans.begin(); while(transIter != allTrans.end()) { histClasses.push_back(HistoryTransitionClass(*transIter)); transIter++; } - + // nothing to do here if (histClasses.size() == 0) return; - + // std::cout << histClasses.size() << " / "; - + // now sort into equivalence classes std::list<HistoryTransitionClass>::iterator outerHistClassIter = histClasses.begin(); std::list<HistoryTransitionClass>::iterator innerHistClassIter = histClasses.begin(); @@ -1257,11 +1257,11 @@ void ChartToPromela::writeHistoryAssignments(std::ostream& stream, GlobalTransit // iterate inner iter for every outer iter and see if we can merge innerHistClassIter = outerHistClassIter; innerHistClassIter++; - + while(innerHistClassIter != histClasses.end()) { // can we merge the inner class into the outer one? HistoryTransitionClass& innerClass = *innerHistClassIter; - + if (outerClass.matches(innerClass)) { outerClass.merge(innerClass); histClasses.erase(innerHistClassIter++); @@ -1269,7 +1269,7 @@ void ChartToPromela::writeHistoryAssignments(std::ostream& stream, GlobalTransit innerHistClassIter++; } } - + _perfHistoryProcessed++; _perfHistoryTotal++; @@ -1316,7 +1316,7 @@ void ChartToPromela::writeHistoryAssignments(std::ostream& stream, GlobalTransit forgetIter++; } } - + { std::map<std::string, std::set<std::string> >::iterator rememberIter = histClassIter->toRemember.begin(); while(rememberIter != histClassIter->toRemember.end()) { @@ -1338,11 +1338,11 @@ void ChartToPromela::writeHistoryAssignments(std::ostream& stream, GlobalTransit if (histClassIter == defaultHistClassIter) { break; } - + histClassIter++; } assert(nrMembers == allTrans.size()); - + } HistoryTransitionClass::HistoryTransitionClass(GlobalTransition* transition) { @@ -1357,13 +1357,13 @@ HistoryTransitionClass::HistoryTransitionClass(const std::string& from, const st void HistoryTransitionClass::init(const std::string& from, const std::string& to) { if (from == to) return; - + FlatStateIdentifier flatSource(from); FlatStateIdentifier flatTarget(to); - + std::map<std::string, std::set<std::string> > activeBefore = flatSource.getHistorySets(); std::map<std::string, std::set<std::string> > activeAfter = flatTarget.getHistorySets(); - + std::map<std::string, std::set<std::string> >::const_iterator targetHistIter = activeAfter.begin(); while(targetHistIter != activeAfter.end()) { // for every history state in target, see if it existed in source @@ -1387,7 +1387,7 @@ void HistoryTransitionClass::init(const std::string& from, const std::string& to } sourceHistMemberIter++; } - + std::set<std::string>::const_iterator targetHistMemberIter = activeAfter.at(targetHistIter->first).begin(); while(targetHistMemberIter != activeAfter.at(targetHistIter->first).end()) { // iterate member of target history and see if it is new @@ -1401,7 +1401,7 @@ void HistoryTransitionClass::init(const std::string& from, const std::string& to targetHistIter++; } } - + bool HistoryTransitionClass::matches(const HistoryTransitionClass& other) { /* does the given transition match this one?: @@ -1409,12 +1409,12 @@ bool HistoryTransitionClass::matches(const HistoryTransitionClass& other) { 2. everything forgot has to be forgotten as well or already disabled and vice versa */ - + std::map<std::string, std::set<std::string> > tmp; - + typedef std::map<std::string, std::set<std::string> >::const_iterator histIter_t; typedef std::set<std::string>::const_iterator histMemberIter_t; - + // we will remember these - will the other try to forget them? INTERSECT_MAPS(toRemember, other.toForget, tmp); if (tmp.size() > 0) @@ -1438,9 +1438,9 @@ bool HistoryTransitionClass::matches(const HistoryTransitionClass& other) { void HistoryTransitionClass::merge(const HistoryTransitionClass& other) { members.insert(other.members.begin(), other.members.end()); - + std::map<std::string, std::set<std::string> >::const_iterator histIter; - + histIter = other.toRemember.begin(); while(histIter != other.toRemember.end()) { toRemember[histIter->first].insert(histIter->second.begin(), histIter->second.end()); @@ -1460,7 +1460,7 @@ void HistoryTransitionClass::merge(const HistoryTransitionClass& other) { } } - + void ChartToPromela::writeTransitionClosure(std::ostream& stream, GlobalTransition* transition, GlobalState* state, int indent) { std::string padding; for (int i = 0; i < indent; i++) { @@ -1491,12 +1491,12 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica: for (int i = 0; i < indent; i++) { padding += " "; } - + if (node.getNodeType() == Node_base::TEXT_NODE) { if (boost::trim_copy(node.getNodeValue()).length() > 0) stream << beautifyIndentation(ADAPT_SRC(node.getNodeValue()), indent) << std::endl; } - + if (node.getNodeType() != Node_base::ELEMENT_NODE) return; // skip anything not an element @@ -1515,17 +1515,17 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica: for (int i = 0; i < scriptText.size(); i++) { stream << ADAPT_SRC(beautifyIndentation(scriptText[i].getNodeValue(), indent)) << std::endl; } - + } else if(TAGNAME(nodeElem) == "log") { std::string label = (HAS_ATTR(nodeElem, "label") ? ATTR(nodeElem, "label") : ""); std::string expr = (HAS_ATTR(nodeElem, "expr") ? ADAPT_SRC(ATTR(nodeElem, "expr")) : ""); std::string trimmedExpr = boost::trim_copy(expr); bool isStringLiteral = (boost::starts_with(trimmedExpr, "\"") || boost::starts_with(trimmedExpr, "'")); - + std::string formatString; std::string varString; std::string seperator; - + if (label.size() > 0) { if (expr.size() > 0) { formatString += label + ": "; @@ -1533,20 +1533,20 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica: formatString += label; } } - + if (isStringLiteral) { formatString += expr; } else if (expr.size() > 0) { formatString += "%d"; varString += seperator + expr; } - + if (varString.length() > 0) { stream << padding << "printf(\"" + formatString + "\", " + varString + ");" << std::endl; } else { stream << padding << "printf(\"" + formatString + "\");" << std::endl; } - + } else if(TAGNAME(nodeElem) == "foreach") { stream << padding << "for (" << _prefix << (HAS_ATTR(nodeElem, "index") ? ATTR(nodeElem, "index") : "_index") << " in " << _prefix << ATTR(nodeElem, "array") << ") {" << std::endl; if (HAS_ATTR(nodeElem, "item")) { @@ -1560,23 +1560,23 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica: // if (HAS_ATTR(nodeElem, "index")) // stream << padding << " " << _prefix << ATTR(nodeElem, "index") << "++;" << std::endl; stream << padding << "}" << std::endl; - + } else if(TAGNAME(nodeElem) == "if") { NodeSet<std::string> condChain; condChain.push_back(node); condChain.push_back(filterChildElements(_nsInfo.xmlNSPrefix + "elseif", node)); condChain.push_back(filterChildElements(_nsInfo.xmlNSPrefix + "else", node)); - + writeIfBlock(stream, condChain, indent); - + } else if(TAGNAME(nodeElem) == "assign") { NodeSet<std::string> assignTexts = filterChildType(Node_base::TEXT_NODE, nodeElem, true); assert(assignTexts.size() > 0); stream << beautifyIndentation(ADAPT_SRC(boost::trim_copy(assignTexts[0].getNodeValue())), indent) << std::endl; - + } else if(TAGNAME(nodeElem) == "send" || TAGNAME(nodeElem) == "raise") { std::string targetQueue; - std::string insertOp = "!"; + std::string insertOp = "!"; if (TAGNAME(nodeElem) == "raise") { targetQueue = _prefix + "iQ"; } else if (!HAS_ATTR(nodeElem, "target")) { @@ -1595,7 +1595,7 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica: if (targetQueue.length() > 0) { // this is for our external queue std::string event; - + if (HAS_ATTR(nodeElem, "event")) { event = _analyzer->macroForLiteral(ATTR(nodeElem, "event")); } else if (HAS_ATTR(nodeElem, "eventexpr")) { @@ -1603,10 +1603,10 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica: } if (_analyzer->usesComplexEventStruct()) { stream << padding << "{" << std::endl; - std::string typeReset = _analyzer->getTypeReset("tmpE", _analyzer->getType("_event"), padding + " "); - std::stringstream typeAssignSS; - typeAssignSS << padding << " tmpE.name = " << event << ";" << std::endl; - + std::string typeReset = _analyzer->getTypeReset("tmpE", _analyzer->getType("_event"), padding + " "); + std::stringstream typeAssignSS; + typeAssignSS << padding << " tmpE.name = " << event << ";" << std::endl; + if (HAS_ATTR(nodeElem, "idlocation")) { typeAssignSS << padding << " /* idlocation */" << std::endl; typeAssignSS << padding << " _lastSendId = _lastSendId + 1;" << std::endl; @@ -1619,11 +1619,11 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica: } else if (HAS_ATTR(nodeElem, "id")) { typeAssignSS << padding << " tmpE.sendid = " << _analyzer->macroForLiteral(ATTR(nodeElem, "id")) << ";" << std::endl; } - + if (_invokerid.length() > 0) { // do not send invokeid if we send / raise to ourself typeAssignSS << padding << " tmpE.invokeid = " << _analyzer->macroForLiteral(_invokerid) << ";" << std::endl; } - + if (_analyzer->usesEventField("origintype") && !boost::ends_with(targetQueue, "iQ")) { typeAssignSS << padding << " tmpE.origintype = " << _analyzer->macroForLiteral("http://www.w3.org/TR/scxml/#SCXMLEventProcessor") << ";" << std::endl; } @@ -1631,7 +1631,7 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica: if (_analyzer->usesEventField("delay")) { #if NEW_DELAY_RESHUFFLE #else - insertOp += "!"; + insertOp += "!"; typeAssignSS << padding << " _lastSeqId = _lastSeqId + 1;" << std::endl; #endif if (HAS_ATTR_CAST(nodeElem, "delay")) { @@ -1643,7 +1643,7 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica: } #if NEW_DELAY_RESHUFFLE #else - typeAssignSS << padding << " tmpE.seqNr = _lastSeqId;" << std::endl; + typeAssignSS << padding << " tmpE.seqNr = _lastSeqId;" << std::endl; #endif } @@ -1651,7 +1651,7 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica: std::string eventType = (targetQueue.compare("iQ!") == 0 ? _analyzer->macroForLiteral("internal") : _analyzer->macroForLiteral("external")); typeAssignSS << padding << " tmpE.type = " << eventType << ";" << std::endl; } - + NodeSet<std::string> sendParams = filterChildElements(_nsInfo.xmlNSPrefix + "param", nodeElem); NodeSet<std::string> sendContents = filterChildElements(_nsInfo.xmlNSPrefix + "content", nodeElem); std::string sendNameList = ATTR(nodeElem, "namelist"); @@ -1669,7 +1669,7 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica: nameIter++; } } - + if (sendParams.size() == 0 && sendNameList.size() == 0 && sendContents.size() > 0) { Element<std::string> contentElem = Element<std::string>(sendContents[0]); if (contentElem.hasChildNodes() && contentElem.getFirstChild().getNodeType() == Node_base::TEXT_NODE) { @@ -1683,8 +1683,8 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica: typeAssignSS << padding << " tmpE.data = " << ADAPT_SRC(ATTR(contentElem, "expr")) << ";" << std::endl; } } - - // remove all fields from typeReset that are indeed set by typeAssign + + // remove all fields from typeReset that are indeed set by typeAssign // for (std::string assigned; std::getline(typeAssignSS, assigned); ) { // assigned = assigned.substr(0, assigned.find('=')); // assigned = assigned.substr(assigned.find('.')); @@ -1697,28 +1697,28 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica: // } // stream << typeAssignSS.str(); - std::istringstream typeResetSS (typeReset); - for (std::string reset; std::getline(typeResetSS, reset); ) { - std::string resetField = reset.substr(0, reset.find('=')); - resetField = resetField.substr(resetField.find('.')); - for (std::string assigned; std::getline(typeAssignSS, assigned); ) { - if (boost::find_first(resetField, assigned)) { - break; - } - } - stream << reset << std::endl; - } - stream << typeAssignSS.str(); - - + std::istringstream typeResetSS (typeReset); + for (std::string reset; std::getline(typeResetSS, reset); ) { + std::string resetField = reset.substr(0, reset.find('=')); + resetField = resetField.substr(resetField.find('.')); + for (std::string assigned; std::getline(typeAssignSS, assigned); ) { + if (boost::find_first(resetField, assigned)) { + break; + } + } + stream << reset << std::endl; + } + stream << typeAssignSS.str(); + + stream << padding << " " << targetQueue << insertOp <<"tmpE;" << std::endl; - + #if NEW_DELAY_RESHUFFLE - if (_analyzer->usesEventField("delay") && !boost::ends_with(targetQueue, "iQ")) { - stream << padding << " insertWithDelay(" << targetQueue << ");" << std::endl; - } + if (_analyzer->usesEventField("delay") && !boost::ends_with(targetQueue, "iQ")) { + stream << padding << " insertWithDelay(" << targetQueue << ");" << std::endl; + } #endif - + stream << padding << "}" << std::endl; } else { stream << padding << targetQueue << insertOp << event << ";" << std::endl; @@ -1742,7 +1742,7 @@ PromelaInlines::~PromelaInlines() { std::list<PromelaInline*> PromelaInlines::getRelatedTo(const Arabica::DOM::Node<std::string>& node, PromelaInline::PromelaInlineType type) { std::list<PromelaInline*> related; - + std::map<Arabica::DOM::Node<std::string>, std::list<PromelaInline*> >::iterator inlIter = inlines.begin(); while (inlIter != inlines.end()) { std::list<PromelaInline*>::iterator pmlIter = inlIter->second.begin(); @@ -1761,7 +1761,7 @@ std::list<PromelaInline*> PromelaInlines::getRelatedTo(const Arabica::DOM::Node< std::list<PromelaInline*> PromelaInlines::getAllOfType(uint32_t type) { std::list<PromelaInline*> related; - + std::map<Arabica::DOM::Node<std::string>, std::list<PromelaInline*> >::iterator inlIter = inlines.begin(); while (inlIter != inlines.end()) { std::list<PromelaInline*>::iterator pmlIter = inlIter->second.begin(); @@ -1782,7 +1782,7 @@ PromelaInline::PromelaInline(const Arabica::DOM::Node<std::string>& node) : prev std::stringstream ssLine(node.getNodeValue()); std::string line; - + while(std::getline(ssLine, line)) { // skip to first promela line boost::trim(line); @@ -1812,13 +1812,13 @@ PromelaInline::PromelaInline(const Arabica::DOM::Node<std::string>& node) : prev std::stringstream contentSS; size_t endType = line.find_first_of(": \n"); - + std::string seperator; if (endType != std::string::npos && endType + 1 < line.size()) { contentSS << line.substr(endType + 1, line.size() - endType + 1); seperator = "\n"; } - + while(std::getline(ssLine, line)) { boost::trim(line); if (boost::starts_with(line, "promela")) { @@ -1835,14 +1835,14 @@ PromelaInline::PromelaInline(const Arabica::DOM::Node<std::string>& node) : prev PromelaInlines::PromelaInlines(const Arabica::DOM::Node<std::string>& node) { NodeSet<std::string> levelNodes; levelNodes.push_back(node); - + size_t level = 0; while(levelNodes.size() > 0) { PromelaInline* predecessor = NULL; // iterate all nodes at given level for (int i = 0; i < levelNodes.size(); i++) { - + // get all comments NodeSet<std::string> comments = InterpreterImpl::filterChildType(Node_base::COMMENT_NODE, levelNodes[i]); for (int j = 0; j < comments.size(); j++) { @@ -1863,7 +1863,7 @@ PromelaInlines::PromelaInlines(const Arabica::DOM::Node<std::string>& node) { allInlines.push_back(tmp); } } - + levelNodes = InterpreterImpl::filterChildType(Node_base::ELEMENT_NODE, levelNodes); level++; } @@ -1872,32 +1872,32 @@ PromelaInlines::PromelaInlines(const Arabica::DOM::Node<std::string>& node) { void PromelaInline::dump() { #if 0 switch(type) { - case PROMELA_NIL: - std::cerr << "PROMELA_NIL" << std::endl; - break; - case PROMELA_CODE: - std::cerr << "PROMELA_CODE" << std::endl; - break; - case PROMELA_EVENT_SOURCE_ALL: - std::cerr << "PROMELA_EVENT_SOURCE" << std::endl; - break; - case PROMELA_INVOKER: - std::cerr << "PROMELA_INVOKER" << std::endl; - break; - case PROMELA_PROGRESS_LABEL: - std::cerr << "PROMELA_PROGRESS_LABEL" << std::endl; - break; - case PROMELA_ACCEPT_LABEL: - std::cerr << "PROMELA_ACCEPT_LABEL" << std::endl; - break; - case PROMELA_END_LABEL: - std::cerr << "PROMELA_END_LABEL" << std::endl; - break; + case PROMELA_NIL: + std::cerr << "PROMELA_NIL" << std::endl; + break; + case PROMELA_CODE: + std::cerr << "PROMELA_CODE" << std::endl; + break; + case PROMELA_EVENT_SOURCE_ALL: + std::cerr << "PROMELA_EVENT_SOURCE" << std::endl; + break; + case PROMELA_INVOKER: + std::cerr << "PROMELA_INVOKER" << std::endl; + break; + case PROMELA_PROGRESS_LABEL: + std::cerr << "PROMELA_PROGRESS_LABEL" << std::endl; + break; + case PROMELA_ACCEPT_LABEL: + std::cerr << "PROMELA_ACCEPT_LABEL" << std::endl; + break; + case PROMELA_END_LABEL: + std::cerr << "PROMELA_END_LABEL" << std::endl; + break; } #endif } - + void ChartToPromela::writeIfBlock(std::ostream& stream, const Arabica::XPath::NodeSet<std::string>& condChain, int indent) { if (condChain.size() == 0) return; @@ -2014,10 +2014,10 @@ void ChartToPromela::writeStrings(std::ostream& stream) { void ChartToPromela::writeDeclarations(std::ostream& stream) { stream << "/* global variables " << (_prefix.size() > 0 ? "for " + _prefix : "") << " */" << std::endl; - + // we cannot know our event queue with nested invokers? Adding some for test422 size_t tolerance = 6; - + if (_analyzer->usesComplexEventStruct()) { // event is defined with the typedefs stream << "_event_t " << _prefix << "_event; /* current event */" << std::endl; @@ -2038,7 +2038,7 @@ void ChartToPromela::writeDeclarations(std::ostream& stream) { if (_machines.size() > 0) { stream << "chan " << _prefix << "start = [" << _machines.size() << "] of {int} /* nested machines to start at next macrostep */" << std::endl; } - + if (_hasIndexLessLoops) stream << "hidden int " << _prefix << "_index; /* helper for indexless foreach loops */" << std::endl; @@ -2054,7 +2054,7 @@ void ChartToPromela::writeDeclarations(std::ostream& stream) { stream << "hidden _ioprocessors_t " << _prefix << "_ioprocessors;" << std::endl; _varInitializers.push_front("_ioprocessors.scxml.location = " + (_invokerid.size() > 0 ? _analyzer->macroForLiteral(_invokerid) : "1") + ";"); } - + if (_prefix.size() == 0 || _prefix == "MAIN_") { if (_analyzer->usesEventField("sendid")) { // stream << "chan sendIdQ = [" << MAX(_externalQueueLength + 1, 1) << "] of {_event_t} /* temporary queue to cancel events per sendidexpr */" << std::endl; @@ -2087,33 +2087,33 @@ void ChartToPromela::writeDeclarations(std::ostream& stream) { // get all data elements NodeSet<std::string> datas = _xpath.evaluate("//" + _nsInfo.xpathPrefix + "data", _scxml).asNodeSet(); - + // write their text content stream << "/* data model variables" << (_prefix.size() > 0 ? " for " + _prefix : "") << " */" << std::endl; std::set<std::string> processedIdentifiers; - + // automatic types PromelaCodeAnalyzer::PromelaTypedef allTypes = _analyzer->getTypes(); for (int i = 0; i < datas.size(); i++) { - + Node<std::string> data = datas[i]; if (isInEmbeddedDocument(data)) continue; - + std::string identifier = (HAS_ATTR_CAST(data, "id") ? ATTR_CAST(data, "id") : ""); std::string type = boost::trim_copy(HAS_ATTR_CAST(data, "type") ? ATTR_CAST(data, "type") : ""); - + _dataModelVars.insert(identifier); if (processedIdentifiers.find(identifier) != processedIdentifiers.end()) continue; - + processedIdentifiers.insert(identifier); - + if (boost::starts_with(type, "string")) { type = "int" + type.substr(6, type.length() - 6); } - + if (type.length() == 0 || type == "auto") { if (allTypes.types.find(identifier) != allTypes.types.end()) { type = allTypes.types[identifier].name; @@ -2122,7 +2122,7 @@ void ChartToPromela::writeDeclarations(std::ostream& stream) { continue; } } - + std::string arrSize; size_t bracketPos = type.find("["); if (bracketPos != std::string::npos) { @@ -2133,8 +2133,8 @@ void ChartToPromela::writeDeclarations(std::ostream& stream) { stream << decl << ";" << std::endl; } - - + + // implicit and dynamic types std::map<std::string, PromelaCodeAnalyzer::PromelaTypedef>::iterator typeIter = allTypes.types.begin(); while(typeIter != allTypes.types.end()) { @@ -2142,23 +2142,23 @@ void ChartToPromela::writeDeclarations(std::ostream& stream) { typeIter++; continue; } - + if (processedIdentifiers.find(typeIter->first) != processedIdentifiers.end()) { typeIter++; continue; } - + if (typeIter->first == "_event" || - typeIter->first == "_x" || - typeIter->first == "_ioprocessors" || - typeIter->first == "_SESSIONID" || - typeIter->first == "_NAME") { + typeIter->first == "_x" || + typeIter->first == "_ioprocessors" || + typeIter->first == "_SESSIONID" || + typeIter->first == "_NAME") { typeIter++; continue; } - + processedIdentifiers.insert(typeIter->first); - + if (typeIter->second.types.size() == 0) { stream << "hidden " << declForRange(_prefix + typeIter->first, typeIter->second.minValue, typeIter->second.maxValue) << ";" << std::endl; } else { @@ -2168,7 +2168,7 @@ void ChartToPromela::writeDeclarations(std::ostream& stream) { } stream << std::endl; - + } void ChartToPromela::writeEventSources(std::ostream& stream) { @@ -2189,7 +2189,7 @@ void ChartToPromela::writeStartInvoker(std::ostream& stream, const Arabica::DOM: } } } - + // set from params NodeSet<std::string> invokeParams = filterChildElements(_nsInfo.xmlNSPrefix + "param", node); for (int i = 0; i < invokeParams.size(); i++) { @@ -2199,7 +2199,7 @@ void ChartToPromela::writeStartInvoker(std::ostream& stream, const Arabica::DOM: stream << padding << invoker->_prefix << identifier << " = " << ADAPT_SRC(expression) << ";" << std::endl; } } - + stream << padding << "run " << invoker->_prefix << "run() priority 20;" << std::endl; if (HAS_ATTR_CAST(node, "idlocation")) { stream << padding << ADAPT_SRC(ATTR_CAST(node, "idlocation")) << " = " << _analyzer->macroForLiteral(invoker->_invokerid) << ";" << std::endl; @@ -2211,12 +2211,12 @@ void ChartToPromela::writeFSM(std::ostream& stream) { NodeSet<std::string> transitions; stream << "proctype " << (_prefix.size() == 0 ? "machine_" : _prefix) << "run() {" << std::endl; - stream << " d_step {" << std::endl; - stream << " " << _prefix << "done = false;" << std::endl; + stream << " d_step {" << std::endl; + stream << " " << _prefix << "done = false;" << std::endl; stream << " " << _prefix << "canceled = false;" << std::endl; stream << " " << _prefix << "spontaneous = true;" << std::endl; stream << " " << _prefix << "procid = _pid;" << std::endl; - stream << " }" << std::endl; + stream << " }" << std::endl; // write initial transition // transitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", _startState); // assert(transitions.size() == 1); @@ -2229,13 +2229,13 @@ void ChartToPromela::writeFSM(std::ostream& stream) { } stream << std::endl; } - + stream << std::endl << "/* transition to initial state */" << std::endl; assert(_start->sortedOutgoing.size() == 1); // initial transition has to be first one for control flow at start writeTransition(stream, _start->sortedOutgoing.front(), 1); stream << std::endl; - + // every other transition for (std::map<std::string, GlobalState*>::iterator stateIter = _activeConf.begin(); stateIter != _activeConf.end(); stateIter++) { for (std::list<GlobalTransition*>::iterator transIter = stateIter->second->sortedOutgoing.begin(); transIter != stateIter->second->sortedOutgoing.end(); transIter++) { @@ -2255,7 +2255,7 @@ void ChartToPromela::writeFSM(std::ostream& stream) { } _perfStatesProcessed++; _perfStatesTotal++; - + DUMP_STATS(false); } DUMP_STATS(true); @@ -2269,15 +2269,15 @@ void ChartToPromela::writeFSM(std::ostream& stream) { #if NEW_DELAY_RESHUFFLE stream << " :: len(" << _prefix << "tmpQ) != 0 -> { " << _prefix << "tmpQ?" << _prefix << "_event; " << _prefix << "eQ!" << _prefix << "_event; insertWithDelay(" << _prefix << "eQ); }" << std::endl; #else - stream << " :: len(" << _prefix << "tmpQ) != 0 -> { " << _prefix << "tmpQ?" << _prefix << "_event; " << _prefix << "eQ!!" << _prefix << "_event }" << std::endl; + stream << " :: len(" << _prefix << "tmpQ) != 0 -> { " << _prefix << "tmpQ?" << _prefix << "_event; " << _prefix << "eQ!!" << _prefix << "_event }" << std::endl; #endif - } else { + } else { stream << " :: len(" << _prefix << "tmpQ) != 0 -> { " << _prefix << "tmpQ?" << _prefix << "_event; " << _prefix << "eQ!" << _prefix << "_event }" << std::endl; } stream << " :: else -> break;" << std::endl; stream << " od;" << std::endl << std::endl; } - + if (_machines.size() > 0) { stream << " /* start pending invokers */" << std::endl; stream << " int invokerId;" << std::endl; @@ -2295,15 +2295,15 @@ void ChartToPromela::writeFSM(std::ostream& stream) { stream << " :: else -> break;" << std::endl; stream << " od" << std::endl << std::endl; } - + if (_analyzer->usesEventField("delay") && _machinesAll->size() > 1) { stream << "/* Determine machines with smallest delay and set their process priority */" << std::endl; stream << " scheduleMachines();" << std::endl << std::endl; } - + std::list<PromelaInline*> eventSources = pmlInlines.getAllOfType(PromelaInline::PROMELA_EVENT_ALL_BUT | - PromelaInline::PROMELA_EVENT_ONLY); - + PromelaInline::PROMELA_EVENT_ONLY); + stream << " atomic {" << std::endl; stream << "/* pop an event */" << std::endl; stream << " if" << std::endl; @@ -2318,7 +2318,7 @@ void ChartToPromela::writeFSM(std::ostream& stream) { PromelaEventSource es(**esIter); std::string condition = "true"; - + if (LOCALNAME(es.container) == "invoke") { if (HAS_ATTR_CAST(es.container, "id")) { condition = _prefix + ATTR_CAST(es.container, "id") + "Running"; @@ -2329,13 +2329,13 @@ void ChartToPromela::writeFSM(std::ostream& stream) { condition = _prefix + "_x.states[" + _analyzer->macroForLiteral(ATTR(es.container, "id")) + "]"; } stream << " :: " << condition << " -> {" << std::endl; - + if (es.type == PromelaInline::PROMELA_EVENT_ALL_BUT) { std::string excludeEventDescs; for (std::list<Data>::iterator evIter = es.events.array.begin(); evIter != es.events.array.end(); evIter++) { excludeEventDescs += " " + evIter->atom; } - + NodeSet<std::string> transitions = filterChildElements("transition", es.container, true); std::set<std::string> eventNames; for (int i = 0; i < transitions.size(); i++) { @@ -2365,7 +2365,7 @@ void ChartToPromela::writeFSM(std::ostream& stream) { } stream << " fi " << std::endl; } - + } else if (es.type == PromelaInline::PROMELA_EVENT_ONLY) { if (es.events.array.size() > 0) { stream << " if " << std::endl; @@ -2383,7 +2383,7 @@ void ChartToPromela::writeFSM(std::ostream& stream) { } stream << " }" << std::endl; } - + stream << " fi" << std::endl; stream << " }" << std::endl; } else { @@ -2391,7 +2391,7 @@ void ChartToPromela::writeFSM(std::ostream& stream) { } stream << " fi;" << std::endl << std::endl; - + stream << "/* terminate if we are stopped */" << std::endl; stream << " if" << std::endl; stream << " :: " << _prefix << "done -> goto " << _prefix << "terminate;" << std::endl; @@ -2425,7 +2425,7 @@ void ChartToPromela::writeFSM(std::ostream& stream) { stream << " fi;" << std::endl << std::endl; } } - + for (std::map<Arabica::DOM::Node<std::string>, ChartToPromela*>::iterator invIter = _machines.begin(); invIter != _machines.end(); invIter++) { if (invIter->second == this) { continue; @@ -2437,16 +2437,16 @@ void ChartToPromela::writeFSM(std::ostream& stream) { stream << " :: " << invIter->second->_prefix << "done -> skip;" << std::endl; stream << " :: " << invIter->second->_prefix << "canceled -> skip;" << std::endl; #if NEW_DELAY_RESHUFFLE - stream << " :: else -> { " << invIter->second->_prefix << "eQ!" << _prefix << "_event" << "; insertWithDelay(" << invIter->second->_prefix << "eQ" << "); }" << std::endl; + stream << " :: else -> { " << invIter->second->_prefix << "eQ!" << _prefix << "_event" << "; insertWithDelay(" << invIter->second->_prefix << "eQ" << "); }" << std::endl; #else - stream << " :: else -> { " << invIter->second->_prefix << "eQ!!" << _prefix << "_event" << " }" << std::endl; + stream << " :: else -> { " << invIter->second->_prefix << "eQ!!" << _prefix << "_event" << " }" << std::endl; #endif stream << " fi;" << std::endl << std::endl; } } stream << std::endl; - + stream << _prefix << "microStep:" << std::endl; stream << "/* event dispatching per state */" << std::endl; stream << " if" << std::endl; @@ -2461,22 +2461,22 @@ void ChartToPromela::writeFSM(std::ostream& stream) { if (_parent != NULL) { stream << " {" << std::endl; - stream << _analyzer->getTypeReset("tmpE", _analyzer->getType("_event"), " "); + stream << _analyzer->getTypeReset("tmpE", _analyzer->getType("_event"), " "); stream << " tmpE.name = " << _analyzer->macroForLiteral("done.invoke." + _invokerid) << ";" << std::endl; if (_invokerid.length() > 0) { stream << " tmpE.invokeid = " << _analyzer->macroForLiteral(_invokerid) << ";" << std::endl; } if (_analyzer->usesEventField("delay")) { #if NEW_DELAY_RESHUFFLE - stream << " " << _parent->_prefix << "eQ!tmpE;" << std::endl; - stream << " insertWithDelay(" << _parent->_prefix << "eQ);" << std::endl; - + stream << " " << _parent->_prefix << "eQ!tmpE;" << std::endl; + stream << " insertWithDelay(" << _parent->_prefix << "eQ);" << std::endl; + #else - stream << " _lastSeqId = _lastSeqId + 1;" << std::endl; - stream << " tmpE.seqNr = _lastSeqId;" << std::endl; - stream << " " << _parent->_prefix << "eQ!!tmpE;" << std::endl; + stream << " _lastSeqId = _lastSeqId + 1;" << std::endl; + stream << " tmpE.seqNr = _lastSeqId;" << std::endl; + stream << " " << _parent->_prefix << "eQ!!tmpE;" << std::endl; #endif - } else { + } else { stream << " " << _parent->_prefix << "eQ!tmpE;" << std::endl; } stream << " }" << std::endl; @@ -2484,7 +2484,7 @@ void ChartToPromela::writeFSM(std::ostream& stream) { if (_analyzer->usesEventField("delay")) stream << " removePendingEventsForInvoker(" << _analyzer->macroForLiteral(this->_invokerid) << ")" << std::endl; } - + stream << " }" << std::endl; stream << "}" << std::endl; } @@ -2525,7 +2525,7 @@ void ChartToPromela::writeRescheduleProcess(std::ostream& stream, int indent) { stream << padding << " fi;" << std::endl; stream << padding << " }" << std::endl; } - + stream << padding << " :: else -> skip;" << std::endl; stream << padding << " fi;" << std::endl; stream << padding << " }" << std::endl; @@ -2555,97 +2555,97 @@ void ChartToPromela::writeDetermineShortestDelay(std::ostream& stream, int inden } void ChartToPromela::writeInsertWithDelay(std::ostream& stream, int indent) { - std::string padding; - for (int i = 0; i < indent; i++) { - padding += " "; - } - - uint32_t maxExternalQueueLength = 1; - std::map<Arabica::DOM::Node<std::string>, ChartToPromela*>::iterator machineIter = _machinesAll->begin(); - while(machineIter != _machinesAll->end()) { - maxExternalQueueLength = MAX(maxExternalQueueLength, machineIter->second->_externalQueueLength); - machineIter++; - } - - maxExternalQueueLength += 6; - - if (maxExternalQueueLength <= 1) { - stream << padding << "/* noop for external queues with length <= 1 */" << std::endl; - stream << padding << "inline insertWithDelay(queue) {}" << std::endl; - } - - stream << padding << "hidden _event_t _iwdQ[" << maxExternalQueueLength - 1 << "];" << std::endl; - stream << padding << "hidden int _iwdQLength = 0;" << std::endl; - stream << padding << "hidden int _iwdIdx1 = 0;" << std::endl; - stream << padding << "hidden int _iwdIdx2 = 0;" << std::endl; - stream << padding << "hidden _event_t _iwdTmpE;" << std::endl; - stream << padding << "hidden _event_t _iwdLastE;" << std::endl; - stream << padding << "bool _iwdInserted = false;" << std::endl; - stream << padding << "" << std::endl; - stream << padding << "/* last event in given queue is potentially at wrong position */" << std::endl; - stream << padding << "inline insertWithDelay(queue) {" << std::endl; - stream << padding << " d_step {" << std::endl; - stream << padding << "" << std::endl; - stream << padding << " /* only process for non-trivial queues */" << std::endl; - stream << padding << " if" << std::endl; - stream << padding << " :: len(queue) > 1 -> {" << std::endl; - stream << padding << "" << std::endl; - stream << padding << " /* move all events but last over and remember the last one */" << std::endl; - stream << padding << " _iwdIdx1 = 0;" << std::endl; - stream << padding << " _iwdQLength = len(queue) - 1;" << std::endl; - stream << padding << "" << std::endl; - stream << padding << " do" << std::endl; - stream << padding << " :: _iwdIdx1 < _iwdQLength -> {" << std::endl; - stream << padding << " queue?_iwdTmpE;" << std::endl; - stream << padding << " _iwdQ[_iwdIdx1].name = _iwdTmpE.name;" << std::endl; - - stream << _analyzer->getTypeAssignment("_iwdQ[_iwdIdx1]", "_iwdTmpE", _analyzer->getType("_event"), padding + " "); - - stream << padding << " _iwdIdx1++;" << std::endl; - stream << padding << " }" << std::endl; - stream << padding << " :: else -> break;" << std::endl; - stream << padding << " od" << std::endl; - stream << padding << "" << std::endl; - stream << padding << " queue?_iwdLastE;" << std::endl; - stream << padding << "" << std::endl; - stream << padding << " /* _iwdQ now contains all but last item in _iwdLastE */" << std::endl; - stream << padding << " assert(len(queue) == 0);" << std::endl; - stream << padding << "" << std::endl; - stream << padding << " /* reinsert into queue and place _iwdLastE correctly */" << std::endl; - stream << padding << " _iwdInserted = false;" << std::endl; - stream << padding << " _iwdIdx2 = 0;" << std::endl; - stream << padding << "" << std::endl; - stream << padding << " do" << std::endl; - stream << padding << " :: _iwdIdx2 < _iwdIdx1 -> {" << std::endl; - stream << padding << " _iwdTmpE.name = _iwdQ[_iwdIdx2].name;" << std::endl; - - stream << _analyzer->getTypeAssignment("_iwdTmpE", "_iwdQ[_iwdIdx2]", _analyzer->getType("_event"), padding + " "); - - stream << padding << "" << std::endl; - stream << padding << " if" << std::endl; - stream << padding << " :: _iwdTmpE.delay > _iwdLastE.delay -> {" << std::endl; - stream << padding << " queue!_iwdLastE;" << std::endl; - stream << padding << " _iwdInserted = true;" << std::endl; - stream << padding << " }" << std::endl; - stream << padding << " :: else -> skip" << std::endl; - stream << padding << " fi;" << std::endl; - stream << padding << "" << std::endl; - stream << padding << " queue!_iwdTmpE;" << std::endl; - stream << padding << " _iwdIdx2++;" << std::endl; - stream << padding << " }" << std::endl; - stream << padding << " :: else -> break;" << std::endl; - stream << padding << " od" << std::endl; - stream << padding << "" << std::endl; - stream << padding << " if" << std::endl; - stream << padding << " :: !_iwdInserted -> queue!_iwdLastE;" << std::endl; - stream << padding << " :: else -> skip;" << std::endl; - stream << padding << " fi;" << std::endl; - stream << padding << "" << std::endl; - stream << padding << " }" << std::endl; - stream << padding << " :: else -> skip;" << std::endl; - stream << padding << " fi;" << std::endl; - stream << padding << " }" << std::endl; - stream << padding << "}" << std::endl; + std::string padding; + for (int i = 0; i < indent; i++) { + padding += " "; + } + + uint32_t maxExternalQueueLength = 1; + std::map<Arabica::DOM::Node<std::string>, ChartToPromela*>::iterator machineIter = _machinesAll->begin(); + while(machineIter != _machinesAll->end()) { + maxExternalQueueLength = MAX(maxExternalQueueLength, machineIter->second->_externalQueueLength); + machineIter++; + } + + maxExternalQueueLength += 6; + + if (maxExternalQueueLength <= 1) { + stream << padding << "/* noop for external queues with length <= 1 */" << std::endl; + stream << padding << "inline insertWithDelay(queue) {}" << std::endl; + } + + stream << padding << "hidden _event_t _iwdQ[" << maxExternalQueueLength - 1 << "];" << std::endl; + stream << padding << "hidden int _iwdQLength = 0;" << std::endl; + stream << padding << "hidden int _iwdIdx1 = 0;" << std::endl; + stream << padding << "hidden int _iwdIdx2 = 0;" << std::endl; + stream << padding << "hidden _event_t _iwdTmpE;" << std::endl; + stream << padding << "hidden _event_t _iwdLastE;" << std::endl; + stream << padding << "bool _iwdInserted = false;" << std::endl; + stream << padding << "" << std::endl; + stream << padding << "/* last event in given queue is potentially at wrong position */" << std::endl; + stream << padding << "inline insertWithDelay(queue) {" << std::endl; + stream << padding << " d_step {" << std::endl; + stream << padding << "" << std::endl; + stream << padding << " /* only process for non-trivial queues */" << std::endl; + stream << padding << " if" << std::endl; + stream << padding << " :: len(queue) > 1 -> {" << std::endl; + stream << padding << "" << std::endl; + stream << padding << " /* move all events but last over and remember the last one */" << std::endl; + stream << padding << " _iwdIdx1 = 0;" << std::endl; + stream << padding << " _iwdQLength = len(queue) - 1;" << std::endl; + stream << padding << "" << std::endl; + stream << padding << " do" << std::endl; + stream << padding << " :: _iwdIdx1 < _iwdQLength -> {" << std::endl; + stream << padding << " queue?_iwdTmpE;" << std::endl; + stream << padding << " _iwdQ[_iwdIdx1].name = _iwdTmpE.name;" << std::endl; + + stream << _analyzer->getTypeAssignment("_iwdQ[_iwdIdx1]", "_iwdTmpE", _analyzer->getType("_event"), padding + " "); + + stream << padding << " _iwdIdx1++;" << std::endl; + stream << padding << " }" << std::endl; + stream << padding << " :: else -> break;" << std::endl; + stream << padding << " od" << std::endl; + stream << padding << "" << std::endl; + stream << padding << " queue?_iwdLastE;" << std::endl; + stream << padding << "" << std::endl; + stream << padding << " /* _iwdQ now contains all but last item in _iwdLastE */" << std::endl; + stream << padding << " assert(len(queue) == 0);" << std::endl; + stream << padding << "" << std::endl; + stream << padding << " /* reinsert into queue and place _iwdLastE correctly */" << std::endl; + stream << padding << " _iwdInserted = false;" << std::endl; + stream << padding << " _iwdIdx2 = 0;" << std::endl; + stream << padding << "" << std::endl; + stream << padding << " do" << std::endl; + stream << padding << " :: _iwdIdx2 < _iwdIdx1 -> {" << std::endl; + stream << padding << " _iwdTmpE.name = _iwdQ[_iwdIdx2].name;" << std::endl; + + stream << _analyzer->getTypeAssignment("_iwdTmpE", "_iwdQ[_iwdIdx2]", _analyzer->getType("_event"), padding + " "); + + stream << padding << "" << std::endl; + stream << padding << " if" << std::endl; + stream << padding << " :: _iwdTmpE.delay > _iwdLastE.delay -> {" << std::endl; + stream << padding << " queue!_iwdLastE;" << std::endl; + stream << padding << " _iwdInserted = true;" << std::endl; + stream << padding << " }" << std::endl; + stream << padding << " :: else -> skip" << std::endl; + stream << padding << " fi;" << std::endl; + stream << padding << "" << std::endl; + stream << padding << " queue!_iwdTmpE;" << std::endl; + stream << padding << " _iwdIdx2++;" << std::endl; + stream << padding << " }" << std::endl; + stream << padding << " :: else -> break;" << std::endl; + stream << padding << " od" << std::endl; + stream << padding << "" << std::endl; + stream << padding << " if" << std::endl; + stream << padding << " :: !_iwdInserted -> queue!_iwdLastE;" << std::endl; + stream << padding << " :: else -> skip;" << std::endl; + stream << padding << " fi;" << std::endl; + stream << padding << "" << std::endl; + stream << padding << " }" << std::endl; + stream << padding << " :: else -> skip;" << std::endl; + stream << padding << " fi;" << std::endl; + stream << padding << " }" << std::endl; + stream << padding << "}" << std::endl; } void ChartToPromela::writeAdvanceTime(std::ostream& stream, int indent) { @@ -2653,7 +2653,7 @@ void ChartToPromela::writeAdvanceTime(std::ostream& stream, int indent) { for (int i = 0; i < indent; i++) { padding += " "; } - + stream << padding << "inline advanceTime(increment, queue) {" << std::endl; stream << padding << " tmpIndex = 0;" << std::endl; stream << padding << " do" << std::endl; @@ -2676,7 +2676,7 @@ void ChartToPromela::writeRemovePendingEventsFromInvoker(std::ostream& stream, i queues.push_back("eQ"); if (_allowEventInterleaving) queues.push_back("tmpQ"); - + stream << "inline removePendingEventsForInvoker(invokeIdentifier) {" << std::endl; for (std::map<Arabica::DOM::Node<std::string>, ChartToPromela*>::iterator queueIter = _machinesAll->begin(); queueIter != _machinesAll->end(); queueIter++) { for (std::list<std::string>::iterator qIter = queues.begin(); qIter != queues.end(); qIter++) { @@ -2741,42 +2741,42 @@ void ChartToPromela::writeScheduleMachines(std::ostream& stream, int indent) { for (int i = 0; i < indent; i++) { padding += " "; } - + stream << padding << "inline scheduleMachines() {" << std::endl; std::list<std::string> queues; queues.push_back("eQ"); if (_allowEventInterleaving) queues.push_back("tmpQ"); - + stream << " /* schedule state-machines with regard to their event's delay */" << std::endl; stream << " skip;" << std::endl; stream << " d_step {" << std::endl; - + stream << std::endl << "/* determine smallest delay */" << std::endl; stream << " int smallestDelay = 2147483647;" << std::endl; - + for (std::map<Arabica::DOM::Node<std::string>, ChartToPromela*>::iterator queueIter = _machinesAll->begin(); queueIter != _machinesAll->end(); queueIter++) { for (std::list<std::string>::iterator qIter = queues.begin(); qIter != queues.end(); qIter++) { stream << " determineSmallestDelay(smallestDelay, " << queueIter->second->_prefix << *qIter << ");" << std::endl; } } // stream << " printf(\"======= Lowest delay is %d\\n\", smallestDelay);" << std::endl; - + stream << std::endl << "/* prioritize processes with lowest delay or internal events */" << std::endl; - + for (std::map<Arabica::DOM::Node<std::string>, ChartToPromela*>::iterator queueIter = _machinesAll->begin(); queueIter != _machinesAll->end(); queueIter++) { stream << " rescheduleProcess(smallestDelay, " - << queueIter->second->_prefix << "procid, " - << queueIter->second->_prefix << "iQ, " - << queueIter->second->_prefix << "eQ"; + << queueIter->second->_prefix << "procid, " + << queueIter->second->_prefix << "iQ, " + << queueIter->second->_prefix << "eQ"; if (_allowEventInterleaving) { stream << ", " << queueIter->second->_prefix << "tmpQ);" << std::endl; } else { stream << ");" << std::endl; } } - + stream << std::endl << "/* advance time by subtracting the smallest delay from all event delays */" << std::endl; stream << " if" << std::endl; stream << " :: (smallestDelay > 0) -> {" << std::endl; @@ -2792,13 +2792,13 @@ void ChartToPromela::writeScheduleMachines(std::ostream& stream, int indent) { stream << " set_priority(_pid, 10);" << std::endl << std::endl; stream << padding << "}" << std::endl; } - + void ChartToPromela::writeEventDispatching(std::ostream& stream) { for (std::map<std::string, GlobalState*>::iterator stateIter = _activeConf.begin(); stateIter != _activeConf.end(); stateIter++) { - + const std::string& stateId = stateIter->first; const GlobalState* state = stateIter->second; - + stream << std::endl << "/* ### current state "; FlatStateIdentifier flatActiveSource(stateId); PRETTY_PRINT_LIST(stream, flatActiveSource.getActive()); @@ -2810,7 +2810,7 @@ void ChartToPromela::writeEventDispatching(std::ostream& stream) { stream << " }" << std::endl; } } - + void ChartToPromela::writeDispatchingBlock(std::ostream& stream, std::list<GlobalTransition*> transitions, int indent) { std::string padding; for (int i = 0; i < indent; i++) { @@ -2840,7 +2840,7 @@ void ChartToPromela::writeDispatchingBlock(std::ostream& stream, std::list<Globa stream << _prefix << "spontaneous"; } else { std::string eventDescs = currTrans->eventDesc; - + std::list<std::string> eventNames = tokenizeIdRefs(eventDescs); std::set<std::string> eventPrefixes; std::list<std::string>::iterator eventNameIter = eventNames.begin(); @@ -2868,7 +2868,7 @@ void ChartToPromela::writeDispatchingBlock(std::ostream& stream, std::list<Globa if (eventPrefixes.size() > 1) stream << " ("; - + std::string seperator; std::set<std::string>::iterator eventIter = eventPrefixes.begin(); while(eventIter != eventPrefixes.end()) { @@ -2892,37 +2892,37 @@ void ChartToPromela::writeDispatchingBlock(std::ostream& stream, std::list<Globa } if (currTrans->hasExecutableContent || currTrans->historyTrans.size() > 0) { stream << " -> { " << std::endl; - if (!envVarIsTrue("USCXML_ANNOTATE_NOCOMMENT")) { - stream << "/* transition to "; - FlatStateIdentifier flatActiveSource(currTrans->activeDestination); - PRETTY_PRINT_LIST(stream, flatActiveSource.getActive()); - stream << " */" << std::endl; - } - + if (!envVarIsTrue("USCXML_ANNOTATE_NOCOMMENT")) { + stream << "/* transition to "; + FlatStateIdentifier flatActiveSource(currTrans->activeDestination); + PRETTY_PRINT_LIST(stream, flatActiveSource.getActive()); + stream << " */" << std::endl; + } + if (_traceTransitions) { for (std::set<int>::iterator transRefIter = currTrans->transitionRefs.begin(); transRefIter != currTrans->transitionRefs.end(); transRefIter++) { stream << padding << " " << _prefix << "transitions[" << *transRefIter << "] = true; " << std::endl; } } - + stream << padding << " goto " << _prefix << "t" << currTrans->index << ";" << std::endl; stream << padding << "}" << std::endl; } else { - + stream << " -> {" << std::endl; GlobalState* newState = _activeConf[currTrans->activeDestination]; assert(newState != NULL); - if (!envVarIsTrue("USCXML_ANNOTATE_NOCOMMENT")) { - stream << "/* new state "; - FlatStateIdentifier flatActiveDest(currTrans->activeDestination); - PRETTY_PRINT_LIST(stream, flatActiveDest.getActive()); - stream << " */" << std::endl; - } + if (!envVarIsTrue("USCXML_ANNOTATE_NOCOMMENT")) { + stream << "/* new state "; + FlatStateIdentifier flatActiveDest(currTrans->activeDestination); + PRETTY_PRINT_LIST(stream, flatActiveDest.getActive()); + stream << " */" << std::endl; + } stream << padding << " " << _prefix << "s = s" << newState->activeIndex << ";" << std::endl; - TRANSITION_TRACE(currTrans, false); + TRANSITION_TRACE(currTrans, false); writeTransitionClosure(stream, currTrans, newState, indent + 1); stream << padding << "}" << std::endl; } @@ -2947,7 +2947,7 @@ void ChartToPromela::writeMain(std::ostream& stream) { } stream << std::endl; } - + stream << " run " << (_prefix.size() == 0 ? "machine_" : _prefix) << "run() priority 10;" << std::endl; stream << "}" << std::endl; @@ -2958,18 +2958,18 @@ void ChartToPromela::initNodes() { // some things we share with our invokers if (_analyzer == NULL) _analyzer = new PromelaCodeAnalyzer(); - + if (_machinesAll == NULL) { _machinesAll = new std::map<Arabica::DOM::Node<std::string>, ChartToPromela*>(); (*_machinesAll)[_scxml] = this; } - + if (_machinesAllPerId == NULL) _machinesAllPerId = new std::map<std::string, Arabica::DOM::Node<std::string> >(); if (_parentTopMost == NULL) _parentTopMost = this; - + _internalQueueLength = getMinInternalQueueLength(MSG_QUEUE_LENGTH); _externalQueueLength = getMinExternalQueueLength(MSG_QUEUE_LENGTH); @@ -2984,7 +2984,7 @@ void ChartToPromela::initNodes() { _analyzer->addEvent("done.state." + ATTR(stateElem, "id")); } } - + { // shorten UUID ids at invokers for readability NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", _scxml, true); @@ -3003,18 +3003,18 @@ void ChartToPromela::initNodes() { } } - + // are there nestes SCXML invokers? { NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", _scxml, true); for (int i = 0; i < invokes.size(); i++) { if (!HAS_ATTR_CAST(invokes[i], "type") || - ATTR_CAST(invokes[i], "type") == "scxml" || - ATTR_CAST(invokes[i], "type") == "http://www.w3.org/TR/scxml/#SCXMLEventProcessor" || - ATTR_CAST(invokes[i], "type") == "http://www.w3.org/TR/scxml/") { + ATTR_CAST(invokes[i], "type") == "scxml" || + ATTR_CAST(invokes[i], "type") == "http://www.w3.org/TR/scxml/#SCXMLEventProcessor" || + ATTR_CAST(invokes[i], "type") == "http://www.w3.org/TR/scxml/") { assert(HAS_ATTR_CAST(invokes[i], "id")); Element<std::string>(invokes[i]).setAttribute("name", ATTR_CAST(invokes[i], "id")); - + _prefix = "MAIN_"; Interpreter nested; if (HAS_ATTR_CAST(invokes[i], "src")) { @@ -3032,12 +3032,12 @@ void ChartToPromela::initNodes() { Document<std::string> nestedDoc = domFactory.createDocument(_scxml.getOwnerDocument().getNamespaceURI(), "", 0); Node<std::string> importRoot = nestedDoc.importNode(nestedRoot[0], true); nestedDoc.appendChild(importRoot); - + nested = Interpreter::fromDOM(nestedDoc, _nsInfo, _sourceURL); } - + // std::cout << invokes[i] << std::endl; - + // we found machines but have no prefix if (_prefix.length() == 0) _prefix = "MAIN_"; @@ -3048,13 +3048,13 @@ void ChartToPromela::initNodes() { _machines[invokes[i]]->_parentTopMost = _parentTopMost; _machines[invokes[i]]->_machinesAll = _machinesAll; (*_machinesAll)[invokes[i]] = _machines[invokes[i]]; - + _machines[invokes[i]]->_invokerid = ATTR_CAST(invokes[i], "id"); _machines[invokes[i]]->_prefix = ATTR_CAST(invokes[i], "id") + "_"; - + _analyzer->addLiteral(_machines[invokes[i]]->_invokerid); _analyzer->addEvent("done.invoke." + _machines[invokes[i]]->_invokerid); - + _machinesPerId[ATTR_CAST(invokes[i], "id")] = invokes[i]; (*_machinesAllPerId)[ATTR_CAST(invokes[i], "id")] = invokes[i]; } @@ -3064,7 +3064,7 @@ void ChartToPromela::initNodes() { if (_machines.size() > 0) { _analyzer->addCode("_event.invokeid", this); } - + // gather all potential members per history std::map<std::string, Arabica::DOM::Element<std::string> >::iterator histIter = _historyTargets.begin(); while(histIter != _historyTargets.end()) { @@ -3079,7 +3079,7 @@ void ChartToPromela::initNodes() { } histIter++; } - + // initialize event trie with all events that might occur NodeSet<std::string> internalEventNames; internalEventNames.push_back(_xpath.evaluate("//" + _nsInfo.xpathPrefix + "transition", _scxml).asNodeSet()); @@ -3105,7 +3105,7 @@ void ChartToPromela::initNodes() { // _analyzer->addCode("bumpDownArrow = 1; _event.foo = 3; forgetSelectedServer = 1;", this); // exit(0); - + // transform data / assign json into PROMELA statements { NodeSet<std::string> asgn; @@ -3115,19 +3115,19 @@ void ChartToPromela::initNodes() { for (int i = 0; i < asgn.size(); i++) { if (isInEmbeddedDocument(asgn[i])) continue; - + Element<std::string> asgnElem(asgn[i]); - + std::string key; if (HAS_ATTR(asgnElem, "id")) { key = ATTR(asgnElem, "id"); } else if (HAS_ATTR(asgnElem, "location")) { key = ATTR(asgnElem, "location"); } - + if (key.length() == 0) continue; - + std::string value; if (HAS_ATTR(asgnElem, "expr")) { value = ATTR(asgnElem, "expr"); @@ -3143,15 +3143,15 @@ void ChartToPromela::initNodes() { } } } - + boost::trim(value); if (value.size() == 0) continue; - + // remove all children, we will replae by suitable promela statements while(asgnElem.hasChildNodes()) asgnElem.removeChild(asgnElem.getFirstChild()); - + std::string newValue; Data json = Data::fromJSON(value); if (!json.empty()) { @@ -3161,24 +3161,24 @@ void ChartToPromela::initNodes() { } newValue = sanitizeCode(newValue); _analyzer->addCode(newValue, this); - + if (asgnElem.getLocalName() == "data") _varInitializers.push_back(newValue); Text<std::string> newText = _document.createTextNode(newValue); asgnElem.insertBefore(newText, Node<std::string>()); } } - + // do we need sendid / invokeid? { NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", _scxml, true); NodeSet<std::string> sends = filterChildElements(_nsInfo.xmlNSPrefix + "send", _scxml, true); NodeSet<std::string> cancels = filterChildElements(_nsInfo.xmlNSPrefix + "cancel", _scxml, true); - + if (cancels.size() > 0) { _analyzer->addCode("_event.invokeid", this); } - + for (int i = 0; i < sends.size(); i++) { if (HAS_ATTR_CAST(sends[i], "idlocation")) { _analyzer->addCode("_event.sendid", this); @@ -3195,12 +3195,12 @@ void ChartToPromela::initNodes() { _analyzer->addCode("_event.delay", this); #if NEW_DELAY_RESHUFFLE #else - _analyzer->addCode("_event.seqNr", this); + _analyzer->addCode("_event.seqNr", this); #endif } } } - + { // string literals for raise / send content NodeSet<std::string> withContent; @@ -3217,30 +3217,30 @@ void ChartToPromela::initNodes() { } } } - + { // gather all inline promela comments pmlInlines = PromelaInlines(_scxml); if (pmlInlines.getAllOfType(PromelaInline::PROMELA_EVENT_ONLY).size() > 0) _analyzer->addCode("_x.states", this); - + // register events and string literals for (std::list<PromelaInline*>::iterator inlIter = pmlInlines.allInlines.begin(); inlIter != pmlInlines.allInlines.end(); inlIter++) { if ((*inlIter)->type != (PromelaInline::PROMELA_EVENT_ONLY)) continue; - + Data json = Data::fromJSON((*inlIter)->content); if (!json.empty()) { std::list<std::string> eventNames = PromelaInlines::getEventNames(json); for (std::list<std::string>::iterator evIter = eventNames.begin(); evIter != eventNames.end(); evIter++) { _analyzer->addEvent(*evIter); } - + std::list<std::string> stringLiterals = PromelaInlines::getStringLiterals(json); for (std::list<std::string>::iterator strIter = stringLiterals.begin(); strIter != stringLiterals.end(); strIter++) { _analyzer->addLiteral(*strIter); } - + if (json.array.size() > 0) { for (int i = 0; i < json.array.size(); i++) { std::string expr = dataToAssignments("_event", json.item(i)); @@ -3249,7 +3249,7 @@ void ChartToPromela::initNodes() { } else { std::string expr = dataToAssignments("_event", json); _analyzer->addCode(expr, this); - + } } @@ -3449,7 +3449,7 @@ void ChartToPromela::writeProgram(std::ostream& stream) { _traceTransitions = envVarIsTrue("USCXML_PROMELA_TRANSITION_TRACE"); _writeTransitionPrintfs = envVarIsTrue("USCXML_PROMELA_TRANSITION_DEBUG"); - + if (!HAS_ATTR(_scxml, "datamodel") || ATTR(_scxml, "datamodel") != "promela") { LOG(ERROR) << "Can only convert SCXML documents with \"promela\" datamodel"; return; @@ -3470,7 +3470,7 @@ void ChartToPromela::writeProgram(std::ostream& stream) { stream << std::endl; initNodes(); - + for (std::map<Arabica::DOM::Node<std::string>, ChartToPromela*>::iterator nestedIter = _machines.begin(); nestedIter != _machines.end(); nestedIter++) { if (nestedIter->second->_start == NULL) { nestedIter->second->interpret(); @@ -3504,23 +3504,23 @@ void ChartToPromela::writeProgram(std::ostream& stream) { stream << std::endl << "/* global inline functions */" << std::endl; - if (_analyzer->usesComplexEventStruct()) { - stream << "hidden _event_t tmpE;" << std::endl; - } else { - stream << "hidden int tmpE;" << std::endl; - } - stream << "hidden int tmpIndex;" << std::endl; + if (_analyzer->usesComplexEventStruct()) { + stream << "hidden _event_t tmpE;" << std::endl; + } else { + stream << "hidden int tmpE;" << std::endl; + } + stream << "hidden int tmpIndex;" << std::endl; + - #if NEW_DELAY_RESHUFFLE - if (_analyzer->usesEventField("delay")) { - writeInsertWithDelay(stream); - stream << std::endl; - } + if (_analyzer->usesEventField("delay")) { + writeInsertWithDelay(stream); + stream << std::endl; + } #endif - + if (_analyzer->usesEventField("delay") && _machines.size() > 0) { - writeDetermineShortestDelay(stream); + writeDetermineShortestDelay(stream); stream << std::endl; writeAdvanceTime(stream); stream << std::endl; @@ -3557,11 +3557,11 @@ void ChartToPromela::writeProgram(std::ostream& stream) { nestedIter->second->writeFSM(stream); stream << std::endl; } - + // write ltl expression for success std::stringstream acceptingStates; std::string seperator; - + for (std::map<std::string, GlobalState*>::iterator stateIter = _activeConf.begin(); stateIter != _activeConf.end(); stateIter++) { FlatStateIdentifier flatId(stateIter->first); if (std::find(flatId.getActive().begin(), flatId.getActive().end(), "pass") != flatId.getActive().end()) { diff --git a/src/uscxml/transform/ChartToPromela.h b/src/uscxml/transform/ChartToPromela.h index 9c3c99b..d289436 100644 --- a/src/uscxml/transform/ChartToPromela.h +++ b/src/uscxml/transform/ChartToPromela.h @@ -52,7 +52,7 @@ public: PromelaInline(const Arabica::DOM::Node<std::string>& node); virtual ~PromelaInline() {} - + operator bool() { return (type != PROMELA_NIL); } @@ -60,13 +60,13 @@ public: std::list<PromelaInline*> children; PromelaInline* prevSibling; PromelaInline* nextSibling; - + virtual void dump(); virtual bool relatesTo(const Arabica::DOM::Node<std::string>& node) { return container == node; } - + size_t level; std::string content; Arabica::DOM::Element<std::string> container; @@ -78,22 +78,22 @@ protected: class USCXML_API PromelaInlines { public: - + PromelaInlines(const Arabica::DOM::Node<std::string>& node); PromelaInlines() {} virtual ~PromelaInlines(); - + std::list<PromelaInline*> getRelatedTo(const Arabica::DOM::Node<std::string>& node, PromelaInline::PromelaInlineType type); std::list<PromelaInline*> getAllOfType(uint32_t type); std::map<Arabica::DOM::Node<std::string>, std::list<PromelaInline*> > inlines; std::list<PromelaInline*> allInlines; - + static std::list<std::string> getStringLiterals(const Data& data); static std::list<std::string> getEventNames(const Data& data); - + }; class USCXML_API PromelaEventSource : public PromelaInline { @@ -104,7 +104,7 @@ public: content = pmlInline.content; events = Data::fromJSON(pmlInline.content); } - + virtual bool relatesTo(const Arabica::DOM::Node<std::string>& node) { return container == node || InterpreterImpl::isDescendant(node, container); } @@ -128,30 +128,30 @@ public: class USCXML_API PromelaEventSource { public: - + enum PromelaEventSourceType { PROMELA_EVENT_SOURCE_INVALID, PROMELA_EVENT_SOURCE_INVOKER, PROMELA_EVENT_SOURCE_GLOBAL, }; - + PromelaEventSource(); PromelaEventSource(const PromelaInline& source, PromelaCodeAnalyzer* analyzer = NULL, uint32_t externalQueueLength = 0); - + void writeStart(std::ostream& stream, int indent = 0); void writeStop(std::ostream& stream, int indent = 0); void writeDeclarations(std::ostream& stream, int indent = 0); void writeBody(std::ostream& stream); - + operator bool() { return type != PROMELA_EVENT_SOURCE_INVALID; } - + PromelaInline source; std::string name; uint32_t externalQueueLength; uint32_t longestSequence; - + Arabica::DOM::Node<std::string> container; std::list<std::list<std::string> > sequences; PromelaEventSourceType type; @@ -159,7 +159,7 @@ public: }; #endif - + class USCXML_API PromelaCodeAnalyzer { public: class PromelaTypedef { @@ -172,7 +172,7 @@ public: size_t maxValue; std::map<std::string, PromelaTypedef> types; std::set<ChartToPromela*> occurrences; - + bool operator==(const PromelaTypedef& other) const { return name == other.name; } @@ -199,15 +199,15 @@ public: bool usesEventDataField(const std::string& fieldName) { if (usesComplexEventStruct() && - _typeDefs.types["_event"].types.find("data") != _typeDefs.types["_event"].types.end() && - _typeDefs.types["_event"].types["data"].types.find(fieldName) != _typeDefs.types["_event"].types["data"].types.end()) + _typeDefs.types["_event"].types.find("data") != _typeDefs.types["_event"].types.end() && + _typeDefs.types["_event"].types["data"].types.find(fieldName) != _typeDefs.types["_event"].types["data"].types.end()) return true; return false; } - std::string getTypeAssignment(const std::string& varTo, const std::string& varFrom, const PromelaTypedef& type, const std::string padding = ""); - std::string getTypeReset(const std::string& var, const PromelaTypedef& type, const std::string padding = ""); - + std::string getTypeAssignment(const std::string& varTo, const std::string& varFrom, const PromelaTypedef& type, const std::string padding = ""); + std::string getTypeReset(const std::string& var, const PromelaTypedef& type, const std::string padding = ""); + bool usesInPredicate() { return _usesInPredicate; } @@ -251,9 +251,9 @@ public: return _typeDefs; } - PromelaTypedef& getType(const std::string& typeName) { - return _typeDefs.types.at(typeName); - } + PromelaTypedef& getType(const std::string& typeName) { + return _typeDefs.types.at(typeName); + } protected: std::string createMacroName(const std::string& literal); @@ -266,7 +266,7 @@ protected: std::map<std::string, int> _states; std::map<std::string, int> _events; - + PromelaTypedef _typeDefs; Trie _eventTrie; @@ -288,12 +288,12 @@ public: }; ExecContentSeqItem(ExecContentType type, const std::set<GlobalTransition*>& transitions, const GlobalTransition::Action& action) - : type(type), transitions(transitions), action(action) {} + : type(type), transitions(transitions), action(action) {} ExecContentSeqItem(ExecContentType type, GlobalTransition* transition, const GlobalTransition::Action& action) - : type(type), action(action) { + : type(type), action(action) { transitions.insert(transition); } - + ExecContentType type; std::set<GlobalTransition*> transitions; GlobalTransition::Action action; @@ -303,48 +303,48 @@ class HistoryTransitionClass { public: HistoryTransitionClass(GlobalTransition* transition); HistoryTransitionClass(const std::string& from, const std::string& to); - + void init(const std::string& from, const std::string& to); - + std::map<std::string, std::set<std::string> > toRemember; std::map<std::string, std::set<std::string> > toKeep; std::map<std::string, std::set<std::string> > toForget; - + std::set<GlobalTransition*> members; void merge(const HistoryTransitionClass& other); bool matches(const HistoryTransitionClass& other); }; - + class USCXML_API ChartToPromela : public TransformerImpl, public ChartToFSM { public: virtual ~ChartToPromela(); static Transformer transform(const Interpreter& other); - + void writeTo(std::ostream& stream); - + protected: ChartToPromela(const Interpreter& other) - : TransformerImpl(), - ChartToFSM(other), - _analyzer(NULL), - _allowEventInterleaving(false), - _hasIndexLessLoops(false), - _writeTransitionPrintfs(false), - _traceTransitions(false), - _machinesAll(NULL), - _parent(NULL), - _parentTopMost(NULL), - _machinesAllPerId(NULL), - _perfTransProcessed(0), - _perfTransTotal(0), - _perfHistoryProcessed(0), - _perfHistoryTotal(0), - _perfStatesProcessed(0), - _perfStatesTotal(0), - _lastTimeStamp(0) {} + : TransformerImpl(), + ChartToFSM(other), + _analyzer(NULL), + _allowEventInterleaving(false), + _hasIndexLessLoops(false), + _writeTransitionPrintfs(false), + _traceTransitions(false), + _machinesAll(NULL), + _parent(NULL), + _parentTopMost(NULL), + _machinesAllPerId(NULL), + _perfTransProcessed(0), + _perfTransTotal(0), + _perfHistoryProcessed(0), + _perfHistoryTotal(0), + _perfStatesProcessed(0), + _perfStatesTotal(0), + _lastTimeStamp(0) {} void initNodes(); @@ -377,10 +377,10 @@ protected: void writeStartInvoker(std::ostream& stream, const Arabica::DOM::Node<std::string>& node, ChartToPromela* invoker, int indent = 0); //void writeRemovePendingEventsFromInvoker(std::ostream& stream, ChartToPromela* invoker, int indent = 0, bool atomic = true); - + void writeDetermineShortestDelay(std::ostream& stream, int indent = 0); - void writeInsertWithDelay(std::ostream& stream, int indent = 0); - void writeAdvanceTime(std::ostream& stream, int indent = 0); + void writeInsertWithDelay(std::ostream& stream, int indent = 0); + void writeAdvanceTime(std::ostream& stream, int indent = 0); void writeRescheduleProcess(std::ostream& stream, int indent = 0); void writeScheduleMachines(std::ostream& stream, int indent = 0); void writeCancelEvents(std::ostream& stream, int indent = 0); @@ -388,7 +388,7 @@ protected: std::list<GlobalTransition::Action> getTransientContent(GlobalTransition* transition); //Arabica::DOM::Node<std::string> getUltimateTarget(const Arabica::DOM::Element<std::string>& transition); - + static std::string declForRange(const std::string& identifier, long minValue, long maxValue, bool nativeOnly = false); static std::string conditionForHistoryTransition(const GlobalTransition* transition); @@ -396,7 +396,7 @@ protected: std::string sanitizeCode(const std::string& code); std::string dataToAssignments(const std::string& prefix, const Data& data); - + // Arabica::XPath::NodeSet<std::string> _globalStates; // Arabica::DOM::Node<std::string> _startState; // std::map<std::string, Arabica::DOM::Element<std::string> > _states; @@ -409,28 +409,28 @@ protected: bool _hasIndexLessLoops; bool _writeTransitionPrintfs; bool _traceTransitions; - + uint32_t _externalQueueLength; uint32_t _internalQueueLength; - + PromelaInlines pmlInlines; // std::map<std::string, PromelaEventSource> _invokers; // PromelaEventSource _globalEventSource; - + std::map<std::string, std::map<std::string, size_t> > _historyMembers; // ids of all history states std::set<std::string> _dataModelVars; - + Arabica::DOM::Node<std::string> _finalize; std::map<Arabica::DOM::Node<std::string>, ChartToPromela*> _machines; std::map<Arabica::DOM::Node<std::string>, ChartToPromela*>* _machinesAll; ChartToPromela* _parent; // our invoking interpreter ChartToPromela* _parentTopMost; - + std::map<std::string, Arabica::DOM::Node<std::string> > _machinesPerId; std::map<std::string, Arabica::DOM::Node<std::string> >* _machinesAllPerId; std::string _prefix; // our prefix in case of nested SCXML documents std::string _invokerid; - + uint64_t _perfTransProcessed; uint64_t _perfTransTotal; uint64_t _perfHistoryProcessed; diff --git a/src/uscxml/transform/ChartToTex.cpp b/src/uscxml/transform/ChartToTex.cpp index 35731a1..f38740a 100644 --- a/src/uscxml/transform/ChartToTex.cpp +++ b/src/uscxml/transform/ChartToTex.cpp @@ -53,12 +53,12 @@ void ChartToTex::writeTex(std::ostream& stream) { bool wroteRowStart = false; std::string seperator; - + for (std::map<std::string, GlobalState*>::iterator stateIter = _globalConf.begin(); stateIter != _globalConf.end(); stateIter++) { assert(_indexToState.find(stateIter->second->index) == _indexToState.end()); _indexToState[stateIter->second->index] = stateIter->second; } - + stream << "% " << _sourceURL.asString() << std::endl; stream << "%<*provideCommand>" << std::endl; @@ -84,7 +84,7 @@ void ChartToTex::writeTex(std::ostream& stream) { stream << "%<*tableRows>" << std::endl; wroteRowStart = true; } - + stream << "%<*globalState" << currState->index << ">" << std::endl; // state index @@ -95,15 +95,15 @@ void ChartToTex::writeTex(std::ostream& stream) { stream << "\\globalStateListCell[t]{"; stream << "\\tikzmark{active_" << currState->index << "}"; stream << "$\\widetilde{s}_a(" << currState->index << ")$: " << stateListToTex(flatId.getFlatActive(), flatId.getActive().size() == 0) << "\\\\"; - + // already visited states stream << "\\tikzmark{visited_" << currState->index << "}"; stream << "$\\widetilde{s}_d(" << currState->index << ")$: " << stateListToTex(flatId.getFlatVisited(), flatId.getVisited().size() == 0) << "\\\\"; - + // history assignments stream << "\\tikzmark{history_" << currState->index << "}"; stream << "$\\widetilde{s}_h(" << currState->index << ")$: " << stateListToTex(flatId.getFlatHistory(), flatId.getHistory().size() == 0) << "} & "; - + // all transitions std::set<std::string> origTransitions; for (std::list<GlobalTransition*>::iterator transIter = stateIter->second->sortedOutgoing.begin(); transIter != stateIter->second->sortedOutgoing.end(); transIter++) { @@ -118,7 +118,7 @@ void ChartToTex::writeTex(std::ostream& stream) { } } } - + if (origTransitions.size() > 0) { stream << "$\\{ "; seperator = ""; @@ -144,7 +144,7 @@ void ChartToTex::writeTex(std::ostream& stream) { if (!currTrans->isValid) stream << "\\sout{"; - + Arabica::XPath::NodeSet<std::string> members = currTrans->getTransitions(); if (members.size() > 0) { stream << "$\\{ "; @@ -162,28 +162,35 @@ void ChartToTex::writeTex(std::ostream& stream) { } else { stream << "$\\emptyset$"; } - // stream << "& \\sout{$\\{ t_2, t_0 \\}$}, & \\emph{$Inv_4$: nested source states} \\\\" << std::endl; - // stream << "& $\\{ t_2 \\}$ & & $\\widetilde{s}(2)$ \\\\" << std::endl; - // stream << "& $\\{ t_0 \\}$ & & $\\widetilde{s}(4)$ \\\\" << std::endl; + // stream << "& \\sout{$\\{ t_2, t_0 \\}$}, & \\emph{$Inv_4$: nested source states} \\\\" << std::endl; + // stream << "& $\\{ t_2 \\}$ & & $\\widetilde{s}(2)$ \\\\" << std::endl; + // stream << "& $\\{ t_0 \\}$ & & $\\widetilde{s}(4)$ \\\\" << std::endl; if (!currTrans->isValid) { #if 1 stream << " } & \\emph{"; switch(currTrans->invalidReason) { - case GlobalTransition::NO_COMMON_EVENT: - stream << "$Inv_1$: "; break; - case GlobalTransition::MIXES_EVENT_SPONTANEOUS: - stream << "$Inv_2$: "; break; - case GlobalTransition::SAME_SOURCE_STATE: - stream << "$Inv_3$: "; break; - case GlobalTransition::CHILD_ENABLED: - stream << "$Inv_4$: "; break; - case GlobalTransition::PREEMPTING_MEMBERS: - stream << "$Inv_5$: "; break; - case GlobalTransition::UNCONDITIONAL_MATCH: - stream << "$Opt_1$: "; break; - case GlobalTransition::UNCONDITIONAL_SUPERSET: - stream << "$Opt_2$: "; break; + case GlobalTransition::NO_COMMON_EVENT: + stream << "$Inv_1$: "; + break; + case GlobalTransition::MIXES_EVENT_SPONTANEOUS: + stream << "$Inv_2$: "; + break; + case GlobalTransition::SAME_SOURCE_STATE: + stream << "$Inv_3$: "; + break; + case GlobalTransition::CHILD_ENABLED: + stream << "$Inv_4$: "; + break; + case GlobalTransition::PREEMPTING_MEMBERS: + stream << "$Inv_5$: "; + break; + case GlobalTransition::UNCONDITIONAL_MATCH: + stream << "$Opt_1$: "; + break; + case GlobalTransition::UNCONDITIONAL_SUPERSET: + stream << "$Opt_2$: "; + break; } stream << currTrans->invalidMsg << "} "; #endif @@ -192,7 +199,7 @@ void ChartToTex::writeTex(std::ostream& stream) { } else { stream << " & "; std::stringstream execContentSS; - + seperator = ""; for (std::list<GlobalTransition::Action>::iterator actionIter = currTrans->actions.begin(); actionIter != currTrans->actions.end(); actionIter++) { Element<std::string> execContent; @@ -224,7 +231,7 @@ void ChartToTex::writeTex(std::ostream& stream) { seperator = ", "; } } - + if (execContentSS.str().size() > 0) { stream << "$\\mathcal{X} := (" << execContentSS.str() << ")$"; } else { @@ -241,7 +248,7 @@ void ChartToTex::writeTex(std::ostream& stream) { if (stateIter->second->sortedOutgoing.size() == 0) { stream << " & & & \\\\" << std::endl; } - + stream << "\\hline" << std::endl; } stream << "%</globalState" << currState->index << ">" << std::endl; @@ -270,7 +277,7 @@ std::string ChartToTex::stateListToTex(const std::string& input, bool isEmpty) { } return statesTex; } - + std::string ChartToTex::texEscape(const std::string& input) { std::string texString(input); boost::replace_all(texString, "\\", "\\\\"); diff --git a/src/uscxml/transform/ChartToTex.h b/src/uscxml/transform/ChartToTex.h index b7542f4..037b55c 100644 --- a/src/uscxml/transform/ChartToTex.h +++ b/src/uscxml/transform/ChartToTex.h @@ -39,18 +39,18 @@ public: virtual ~ChartToTex(); static Transformer transform(const Interpreter& other); - + void writeTo(std::ostream& stream); - + protected: ChartToTex(const Interpreter& other) - : TransformerImpl(), - ChartToFSM(other) {} + : TransformerImpl(), + ChartToFSM(other) {} void writeTex(std::ostream& stream); std::map<unsigned long, GlobalState*> _indexToState; - + private: static std::string stateListToTex(const std::string& input, bool isEmpty); static std::string texEscape(const std::string& input); diff --git a/src/uscxml/transform/FlatStateIdentifier.h b/src/uscxml/transform/FlatStateIdentifier.h index f082b18..4afd956 100644 --- a/src/uscxml/transform/FlatStateIdentifier.h +++ b/src/uscxml/transform/FlatStateIdentifier.h @@ -93,8 +93,8 @@ public: } static std::string toStateId(const Arabica::XPath::NodeSet<std::string> activeStates, - const Arabica::XPath::NodeSet<std::string> alreadyEnteredStates = Arabica::XPath::NodeSet<std::string>(), - const std::map<std::string, Arabica::XPath::NodeSet<std::string> > historyStates = std::map<std::string, Arabica::XPath::NodeSet<std::string> >()) { + const Arabica::XPath::NodeSet<std::string> alreadyEnteredStates = Arabica::XPath::NodeSet<std::string>(), + const std::map<std::string, Arabica::XPath::NodeSet<std::string> > historyStates = std::map<std::string, Arabica::XPath::NodeSet<std::string> >()) { FlatStateIdentifier tmp(activeStates, alreadyEnteredStates, historyStates); return tmp.getStateId(); } diff --git a/src/uscxml/transform/Transformer.h b/src/uscxml/transform/Transformer.h index 9d31b71..16d0a94 100644 --- a/src/uscxml/transform/Transformer.h +++ b/src/uscxml/transform/Transformer.h @@ -39,12 +39,12 @@ public: class USCXML_API Transformer : public boost::enable_shared_from_this<Transformer> { public: // Transformer(const Interpreter& source) { _impl = new (source) } - + Transformer() : _impl() {} // the empty, invalid interpreter Transformer(boost::shared_ptr<TransformerImpl> const impl) : _impl(impl) { } Transformer(const Transformer& other) : _impl(other._impl) { } virtual ~Transformer() {}; - + operator bool() const { return (_impl); } @@ -68,11 +68,11 @@ public: operator Interpreter() { return _impl->operator Interpreter(); } - - boost::shared_ptr<TransformerImpl> getImpl() { - return _impl; - } - + + boost::shared_ptr<TransformerImpl> getImpl() { + return _impl; + } + protected: boost::shared_ptr<TransformerImpl> _impl; |