diff options
author | Stefan Radomski <sradomski@mintwerk.de> | 2015-12-04 08:00:18 (GMT) |
---|---|---|
committer | Stefan Radomski <sradomski@mintwerk.de> | 2015-12-04 08:00:18 (GMT) |
commit | b8ba0e7c31f397a66f9d509ff20a85b33619475a (patch) | |
tree | 9a5adb4f891cdc29eb80f597510e0cef8ee0a47f /src | |
parent | 57ba362eae6e8209cf560555fd4cc4bb76dbe2a1 (diff) | |
download | uscxml-b8ba0e7c31f397a66f9d509ff20a85b33619475a.zip uscxml-b8ba0e7c31f397a66f9d509ff20a85b33619475a.tar.gz uscxml-b8ba0e7c31f397a66f9d509ff20a85b33619475a.tar.bz2 |
All changes up to my dissertation
Diffstat (limited to 'src')
-rw-r--r-- | src/bindings/CMakeLists.txt | 13 | ||||
-rw-r--r-- | src/bindings/swig/php/uscxmlNativePHP.php | 27 | ||||
-rw-r--r-- | src/uscxml/Interpreter.cpp | 164 | ||||
-rw-r--r-- | src/uscxml/Interpreter.h | 13 | ||||
-rw-r--r-- | src/uscxml/debug/InterpreterIssue.cpp | 40 | ||||
-rw-r--r-- | src/uscxml/debug/InterpreterIssue.h | 5 | ||||
-rw-r--r-- | src/uscxml/interpreter/InterpreterRC.cpp | 15 | ||||
-rw-r--r-- | src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp | 2 | ||||
-rw-r--r-- | src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp | 6 | ||||
-rw-r--r-- | src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp | 2 | ||||
-rw-r--r-- | src/uscxml/plugins/element/fetch/FetchElement.cpp | 14 | ||||
-rw-r--r-- | src/uscxml/plugins/element/fetch/FetchElement.h | 2 | ||||
-rw-r--r-- | src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp | 12 | ||||
-rw-r--r-- | src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp | 33 | ||||
-rw-r--r-- | src/uscxml/transform/ChartToFSM.cpp | 170 | ||||
-rw-r--r-- | src/uscxml/transform/ChartToFSM.h | 4 | ||||
-rw-r--r-- | src/uscxml/transform/ChartToPromela.cpp | 83 |
17 files changed, 509 insertions, 96 deletions
diff --git a/src/bindings/CMakeLists.txt b/src/bindings/CMakeLists.txt index 0a258b8..89905ce 100644 --- a/src/bindings/CMakeLists.txt +++ b/src/bindings/CMakeLists.txt @@ -24,9 +24,16 @@ if (SWIG_FOUND) if(SWIG_VERSION VERSION_GREATER 2.0.4) MARK_AS_ADVANCED(SWIG_DIR SWIG_EXECUTABLE SWIG_VERSION) INCLUDE(${SWIG_USE_FILE}) - add_subdirectory(swig/java) - add_subdirectory(swig/csharp) - add_subdirectory(swig/php) + if (BUILD_BINDING_JAVA) + add_subdirectory(swig/java) + endif() + if (BUILD_BINDING_CSHARP) + add_subdirectory(swig/csharp) + endif() + if (BUILD_BINDING_PHP) + add_subdirectory(swig/php) + endif() + if(SWIG_VERSION VERSION_LESS 3.0.0) message(STATUS "SWIG version > 3.0 is recommended, found ${SWIG_VERSION}") endif() diff --git a/src/bindings/swig/php/uscxmlNativePHP.php b/src/bindings/swig/php/uscxmlNativePHP.php index 12757d3..eac292b 100644 --- a/src/bindings/swig/php/uscxmlNativePHP.php +++ b/src/bindings/swig/php/uscxmlNativePHP.php @@ -2,7 +2,7 @@ /* ---------------------------------------------------------------------------- * This file was automatically generated by SWIG (http://www.swig.org). - * Version 3.0.5 + * Version 3.0.7 * * This file is not intended to be easily readable and contains a number of * coding conventions designed to improve portability and efficiency. Do not make @@ -589,6 +589,14 @@ class NativeInterpreterMonitor { return array_key_exists($var, $this->_pData); } + function __construct($res=null) { + if (is_resource($res) && get_resource_type($res) === '_p_uscxml__InterpreterMonitor') { + $this->_cPtr=$res; + return; + } + $this->_cPtr=new_NativeInterpreterMonitor(); + } + function beforeProcessingEvent($interpreter,$event) { NativeInterpreterMonitor_beforeProcessingEvent($this->_cPtr,$interpreter,$event); } @@ -617,12 +625,12 @@ class NativeInterpreterMonitor { NativeInterpreterMonitor_reportIssue($this->_cPtr,$interpreter,$issue); } - function __construct($res=null) { - if (is_resource($res) && get_resource_type($res) === '_p_uscxml__InterpreterMonitor') { - $this->_cPtr=$res; - return; + function copyToInvokers($copy=null) { + switch (func_num_args()) { + case 0: $r=NativeInterpreterMonitor_copyToInvokers($this->_cPtr); break; + default: $r=NativeInterpreterMonitor_copyToInvokers($this->_cPtr,$copy); } - $this->_cPtr=new_NativeInterpreterMonitor(); + return $r; } } @@ -828,12 +836,15 @@ class InterpreterIssue { const USCXML_ISSUE_INFO = InterpreterIssue_USCXML_ISSUE_INFO; - function __construct($msg,$node,$severity) { + function __construct($msg,$node,$severity,$specRef=null) { if (is_resource($msg) && get_resource_type($msg) === '_p_uscxml__InterpreterIssue') { $this->_cPtr=$msg; return; } - $this->_cPtr=new_InterpreterIssue($msg,$node,$severity); + switch (func_num_args()) { + case 3: $this->_cPtr=new_InterpreterIssue($msg,$node,$severity); break; + default: $this->_cPtr=new_InterpreterIssue($msg,$node,$severity,$specRef); + } } function toString() { diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index 72232b8..169d9f6 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -330,16 +330,19 @@ void NameSpaceInfo::init(const std::map<std::string, std::string>& namespaceInfo } void StateTransitionMonitor::beforeTakingTransition(uscxml::Interpreter interpreter, const Arabica::DOM::Element<std::string>& transition, bool moreComing) { + tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); std::cerr << "Transition: " << uscxml::DOMUtils::xPathForNode(transition) << std::endl; } void StateTransitionMonitor::onStableConfiguration(uscxml::Interpreter interpreter) { + tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); std::cerr << "Config: {"; printNodeSet(interpreter.getConfiguration()); std::cerr << "}" << std::endl; } void StateTransitionMonitor::beforeProcessingEvent(uscxml::Interpreter interpreter, const uscxml::Event& event) { + tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); switch (event.eventType) { case uscxml::Event::INTERNAL: std::cerr << "Internal Event: " << event.name << std::endl; @@ -354,10 +357,12 @@ void StateTransitionMonitor::beforeProcessingEvent(uscxml::Interpreter interpret } void StateTransitionMonitor::beforeExecutingContent(Interpreter interpreter, const Arabica::DOM::Element<std::string>& element) { + tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); std::cerr << "Executable Content: " << DOMUtils::xPathForNode(element) << std::endl; } void StateTransitionMonitor::beforeExitingState(uscxml::Interpreter interpreter, const Arabica::DOM::Element<std::string>& state, bool moreComing) { + tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); exitingStates.push_back(state); if (!moreComing) { std::cerr << "Exiting: {"; @@ -368,6 +373,7 @@ void StateTransitionMonitor::beforeExitingState(uscxml::Interpreter interpreter, } void StateTransitionMonitor::beforeEnteringState(uscxml::Interpreter interpreter, const Arabica::DOM::Element<std::string>& state, bool moreComing) { + tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); enteringStates.push_back(state); if (!moreComing) { std::cerr << "Entering: {"; @@ -385,7 +391,8 @@ void StateTransitionMonitor::printNodeSet(const Arabica::XPath::NodeSet<std::str seperator = ", "; } } - +tthread::recursive_mutex StateTransitionMonitor::_mutex; + std::map<std::string, boost::weak_ptr<InterpreterImpl> > Interpreter::_instances; tthread::recursive_mutex Interpreter::_instanceMutex; @@ -740,7 +747,7 @@ NodeSet<std::string> InterpreterImpl::getDocumentInitialTransitions() { } else { // try to get initial transition from initial element - initialTransitions = _xpath.evaluate("/" + _nsInfo.xpathPrefix + "initial/" + _nsInfo.xpathPrefix + "transition", _scxml).asNodeSet(); + initialTransitions = _xpath.evaluate("/" + _nsInfo.xpathPrefix + "scxml/"+ _nsInfo.xpathPrefix + "initial/" + _nsInfo.xpathPrefix + "transition", _scxml).asNodeSet(); if (initialTransitions.size() == 0) { Arabica::XPath::NodeSet<std::string> initialStates; // fetch per draft @@ -791,6 +798,14 @@ InterpreterState InterpreterImpl::step(int waitForMS) { std::cerr << std::endl; #endif + // this is not mentionend in the standard, though it makes sense + for (int i = 0; i < initialTransitions.size(); i++) { + Element<std::string> transition(initialTransitions[i]); + USCXML_MONITOR_CALLBACK3(beforeTakingTransition, transition, (i + 1 < enabledTransitions.size())) + executeContent(transition); + USCXML_MONITOR_CALLBACK3(afterTakingTransition, transition, (i + 1 < enabledTransitions.size())) + } + enterStates(initialTransitions); setInterpreterState(USCXML_MICROSTEPPED); } @@ -1050,6 +1065,8 @@ void InterpreterImpl::stabilize() { _statesToInvoke = NodeSet<std::string>(); } +#if 0 + Arabica::XPath::NodeSet<std::string> InterpreterImpl::selectTransitions(const std::string& event) { Arabica::XPath::NodeSet<std::string> enabledTransitions; @@ -1128,6 +1145,104 @@ LOOP: return enabledTransitions; } +#else + +Arabica::XPath::NodeSet<std::string> InterpreterImpl::selectTransitions(const std::string& event) { + Arabica::XPath::NodeSet<std::string> enabledTransitions; + + NodeSet<std::string> atomicStates; + for (unsigned int i = 0; i < _configuration.size(); i++) { + if (isAtomic(Element<std::string>(_configuration[i]))) + atomicStates.push_back(_configuration[i]); + } + atomicStates.to_document_order(); + + for (unsigned int i = 0; i < atomicStates.size(); i++) { + Element<std::string> state(atomicStates[i]); + while(true) { + NodeSet<std::string> transitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", state); + for (unsigned int k = 0; k < transitions.size(); k++) { + if (isEnabledTransition(Element<std::string>(transitions[k]), event)) { + enabledTransitions.push_back(transitions[k]); + goto NEXT_ATOMIC; + } + } + if (state.getParentNode() && state.getParentNode().getNodeType() == Node_base::ELEMENT_NODE) { + state = Element<std::string>(state.getParentNode()); + } else { + goto NEXT_ATOMIC; + } + } + NEXT_ATOMIC:; + } + +#if 0 + std::cerr << "Enabled transitions for '" << event << "': " << std::endl; + for (int i = 0; i < enabledTransitions.size(); i++) { + std::cerr << enabledTransitions[i] << std::endl << "----" << std::endl; + } + std::cerr << std::endl; +#endif + + enabledTransitions = removeConflictingTransitions(enabledTransitions); + +#if 0 + std::cerr << "Non-conflicting transitions for '" << event << "': " << std::endl; + for (int i = 0; i < enabledTransitions.size(); i++) { + std::cerr << enabledTransitions[i] << std::endl << "----" << std::endl; + } + std::cerr << std::endl; +#endif + + return enabledTransitions; +} + + +Arabica::XPath::NodeSet<std::string> InterpreterImpl::selectEventlessTransitions() { + + Arabica::XPath::NodeSet<std::string> enabledTransitions; + + NodeSet<std::string> atomicStates; + for (unsigned int i = 0; i < _configuration.size(); i++) { + if (isAtomic(Element<std::string>(_configuration[i]))) + atomicStates.push_back(_configuration[i]); + } + atomicStates.to_document_order(); + + for (unsigned int i = 0; i < atomicStates.size(); i++) { + Element<std::string> state(atomicStates[i]); + while(true) { + NodeSet<std::string> transitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", state); + for (unsigned int k = 0; k < transitions.size(); k++) { + Element<std::string> transElem(transitions[k]); + if (!HAS_ATTR(transElem, "event") && hasConditionMatch(transElem)) { + enabledTransitions.push_back(transitions[k]); + goto NEXT_ATOMIC; + } + } + if (state.getParentNode() && state.getParentNode().getNodeType() == Node_base::ELEMENT_NODE) { + state = Element<std::string>(state.getParentNode()); + } else { + goto NEXT_ATOMIC; + } + } + NEXT_ATOMIC:; + } + +#if 0 + std::cerr << "Enabled eventless transitions: " << std::endl; + for (int i = 0; i < enabledTransitions.size(); i++) { + std::cerr << enabledTransitions[i] << std::endl << "----" << std::endl; + } + std::cerr << std::endl; +#endif + + enabledTransitions = removeConflictingTransitions(enabledTransitions); + return enabledTransitions; +} + + +#endif bool InterpreterImpl::isEnabledTransition(const Element<std::string>& transition, const std::string& event) { std::string eventName; @@ -2151,9 +2266,15 @@ void InterpreterImpl::invoke(const Arabica::DOM::Element<std::string>& element) USCXML_MONITOR_CALLBACK3(afterInvoking, Arabica::DOM::Element<std::string>(element), invokeReq.invokeid) // this is out of draft but so useful to know when an invoker started -// Event invSuccess; -// invSuccess.name = "invoke.success." + invokeReq.invokeid; -// receive(invSuccess); + if (HAS_ATTR(element, "callback")) { + std::string callback = ATTR(element, "callback"); + if (callback.size() > 0) { + Event invSuccess; + invSuccess.name = callback + "." + invokeReq.invokeid; + receive(invSuccess); + } + } + } catch(boost::bad_lexical_cast e) { LOG(ERROR) << "Exception caught while sending invoke request to invoker " << invokeReq.invokeid << ": " << e.what(); @@ -2594,7 +2715,8 @@ void InterpreterImpl::finalizeAndAutoForwardCurrentEvent() { // do not autoforward to invokers that send to #_parent from the SCXML IO Processor! // Yes do so, see test229! // if (!boost::equals(_currEvent.getOriginType(), "http://www.w3.org/TR/scxml/#SCXMLEventProcessor")) - invokeIter->second.send(_currEvent); +// LOG(ERROR) << _sessionId << " auto forwards " << _currEvent.name << " to " << invokeIter->first << std::endl; + invokeIter->second.send(_currEvent); } catch (const std::exception &e) { LOG(ERROR) << "Exception caught while sending event to invoker " << invokeIter->first << ": " << e.what(); } catch(...) { @@ -2696,6 +2818,7 @@ Arabica::DOM::Node<std::string> InterpreterImpl::getAncestorElement(const Arabic we are speaking of proper ancestor (parent or parent of a parent, etc.) the LCCA is never a member of stateList. */ +#define VERBOSE_FIND_LCCA 0 Arabica::DOM::Node<std::string> InterpreterImpl::findLCCA(const Arabica::XPath::NodeSet<std::string>& states) { #if VERBOSE_FIND_LCCA std::cerr << "findLCCA: "; @@ -2729,7 +2852,7 @@ NEXT_ANCESTOR: // take uppermost root as ancestor if (!ancestor) ancestor = _scxml; - assert(ancestor); + #if VERBOSE_FIND_LCCA std::cerr << " -> " << ATTR_CAST(ancestor, "id") << " " << ancestor.getLocalName() << std::endl; #endif @@ -2838,10 +2961,12 @@ Arabica::XPath::NodeSet<std::string> InterpreterImpl::getInitialStates(Arabica:: // initial element as child - but not the implicit generated one NodeSet<std::string> initElems = filterChildElements(_nsInfo.xmlNSPrefix + "initial", state); - if(initElems.size() == 1 && !iequals(ATTR_CAST(initElems[0], "generated"), "true")) { + if(initElems.size() > 0 && !iequals(ATTR_CAST(initElems[0], "generated"), "true")) { NodeSet<std::string> initTrans = filterChildElements(_nsInfo.xmlNSPrefix + "transition", initElems[0]); - return getTargetStates(Element<std::string>(initTrans[0])); - } + if (initTrans.size() > 0) { + return getTargetStates(Element<std::string>(initTrans[0])); + } + } // first child state Arabica::XPath::NodeSet<std::string> initStates; @@ -3096,6 +3221,14 @@ NodeSet<std::string> InterpreterImpl::filterChildType(const Node_base::Type type return filteredChildTypes; } +/* + * If state2 is null, returns the set of all ancestors of state1 in ancestry order + * (state1's parent followed by the parent's parent, etc. up to an including the <scxml> + * element). If state2 is non-null, returns in ancestry order the set of all ancestors + * of state1, up to but not including state2. (A "proper ancestor" of a state is its + * parent, or the parent's parent, or the parent's parent's parent, etc.))If state2 is + * state1's parent, or equal to state1, or a descendant of state1, this returns the empty set. + */ NodeSet<std::string> InterpreterImpl::getProperAncestors(const Arabica::DOM::Node<std::string>& s1, const Arabica::DOM::Node<std::string>& s2) { @@ -3109,13 +3242,13 @@ NodeSet<std::string> InterpreterImpl::getProperAncestors(const Arabica::DOM::Nod Arabica::DOM::Node<std::string> node = s1; while((node = node.getParentNode())) { if (node.getNodeType() != Node_base::ELEMENT_NODE) - continue; + break; Element<std::string> nodeElem(node); if (!isState(nodeElem)) break; - if (iequals(TAGNAME(nodeElem), _nsInfo.xmlNSPrefix + "scxml")) // do not return scxml root itself - this is somewhat ill-defined - break; +// if (iequals(TAGNAME(nodeElem), _nsInfo.xmlNSPrefix + "scxml")) // do not return scxml root itself - this is somewhat ill-defined +// break; if (!iequals(TAGNAME(nodeElem), _nsInfo.xmlNSPrefix + "parallel") && !iequals(TAGNAME(nodeElem), _nsInfo.xmlNSPrefix + "state") && !iequals(TAGNAME(nodeElem), _nsInfo.xmlNSPrefix + "scxml")) @@ -3131,7 +3264,10 @@ NodeSet<std::string> InterpreterImpl::getProperAncestors(const Arabica::DOM::Nod bool InterpreterImpl::isDescendant(const Arabica::DOM::Node<std::string>& s1, const Arabica::DOM::Node<std::string>& s2) { - Arabica::DOM::Node<std::string> parent = s1.getParentNode(); + if (!s1 || !s2) + return false; + + Arabica::DOM::Node<std::string> parent = s1.getParentNode(); while(parent) { if (s2 == parent) return true; diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h index b6719b5..4e450aa 100644 --- a/src/uscxml/Interpreter.h +++ b/src/uscxml/Interpreter.h @@ -859,6 +859,7 @@ protected: class USCXML_API InterpreterMonitor { public: + InterpreterMonitor() : _copyToInvokers(false) {} virtual ~InterpreterMonitor() {} virtual void beforeProcessingEvent(Interpreter interpreter, const Event& event) {} @@ -891,6 +892,17 @@ public: virtual void reportIssue(Interpreter interpreter, const InterpreterIssue& issue) {} + void copyToInvokers(bool copy) { + _copyToInvokers = copy; + } + + bool copyToInvokers() { + return _copyToInvokers; + } + +protected: + bool _copyToInvokers; + }; class StateTransitionMonitor : public uscxml::InterpreterMonitor { @@ -903,6 +915,7 @@ public: virtual void beforeEnteringState(uscxml::Interpreter interpreter, const Arabica::DOM::Element<std::string>& state, bool moreComing); protected: + static tthread::recursive_mutex _mutex; void printNodeSet(const Arabica::XPath::NodeSet<std::string>& config); Arabica::XPath::NodeSet<std::string> exitingStates; Arabica::XPath::NodeSet<std::string> enteringStates; diff --git a/src/uscxml/debug/InterpreterIssue.cpp b/src/uscxml/debug/InterpreterIssue.cpp index 103211b..49b595d 100644 --- a/src/uscxml/debug/InterpreterIssue.cpp +++ b/src/uscxml/debug/InterpreterIssue.cpp @@ -33,7 +33,7 @@ namespace uscxml { using namespace Arabica::XPath; using namespace Arabica::DOM; -InterpreterIssue::InterpreterIssue(const std::string& msg, Arabica::DOM::Node<std::string> node, IssueSeverity severity) : message(msg), node(node), severity(severity) { +InterpreterIssue::InterpreterIssue(const std::string& msg, Arabica::DOM::Node<std::string> node, IssueSeverity severity, const std::string& specRef) : message(msg), node(node), severity(severity), specRef(specRef) { if (node) xPath = DOMUtils::xPathForNode(node); } @@ -502,8 +502,17 @@ NEXT_TRANSITION: // check for valid initial transition { NodeSet<std::string> initTrans; - initTrans.push_back(InterpreterImpl::filterChildElements(_nsInfo.xmlNSPrefix + "transition", initials, true)); - initTrans.push_back(InterpreterImpl::filterChildElements(_nsInfo.xmlNSPrefix + "transition", histories, true)); +// initTrans.push_back(InterpreterImpl::filterChildElements(_nsInfo.xmlNSPrefix + "transition", histories, true)); + + for (int i = 0; i < initials.size(); i++) { + Element<std::string> initial = Element<std::string>(initials[i]); + NodeSet<std::string> initTransitions = InterpreterImpl::filterChildElements(_nsInfo.xmlNSPrefix + "transition", initial, true); + if (initTransitions.size() != 1) { + issues.push_back(InterpreterIssue("Initial element must define exactly one transition", initial, InterpreterIssue::USCXML_ISSUE_FATAL)); + } + initTrans.push_back(initTransitions); + + } for (int i = 0; i < initTrans.size(); i++) { Element<std::string> transition = Element<std::string>(initTrans[i]); @@ -616,6 +625,9 @@ NEXT_TRANSITION: if (!HAS_ATTR(element, *reqIter)) { issues.push_back(InterpreterIssue("Element " + localName + " is missing required attribute '" + *reqIter + "'", element, InterpreterIssue::USCXML_ISSUE_WARNING)); } + if (HAS_ATTR(element, *reqIter) && ATTR(element, *reqIter).size() == 0) { + issues.push_back(InterpreterIssue("Required attribute '" + *reqIter + "' of element " + localName + " is empty", element, InterpreterIssue::USCXML_ISSUE_WARNING)); + } } } @@ -706,9 +718,18 @@ NEXT_TRANSITION: if (HAS_ATTR(send, "delay") && HAS_ATTR(send, "target") && ATTR(send, "target")== "_internal") { issues.push_back(InterpreterIssue("Send element cannot have delay with target _internal", send, InterpreterIssue::USCXML_ISSUE_WARNING)); } - if (HAS_ATTR(send, "namelist") && InterpreterImpl::filterChildElements(_nsInfo.xmlNSPrefix + "content", send, false).size() > 0) { + + NodeSet<std::string> contentChilds = InterpreterImpl::filterChildElements(_nsInfo.xmlNSPrefix + "content", send, false); + NodeSet<std::string> paramChilds = InterpreterImpl::filterChildElements(_nsInfo.xmlNSPrefix + "param", send, false); + + if (HAS_ATTR(send, "namelist") && contentChilds.size() > 0) { issues.push_back(InterpreterIssue("Send element cannot have namelist attribute and content child", send, InterpreterIssue::USCXML_ISSUE_WARNING)); } + + if (paramChilds.size() > 0 && contentChilds.size() > 0) { + issues.push_back(InterpreterIssue("Send element cannot have param child and content child", send, InterpreterIssue::USCXML_ISSUE_WARNING)); + } + } for (int i = 0; i < cancels.size(); i++) { Element<std::string> cancel = Element<std::string>(cancels[i]); @@ -731,8 +752,19 @@ NEXT_TRANSITION: if (HAS_ATTR(invoke, "namelist") && InterpreterImpl::filterChildElements(_nsInfo.xmlNSPrefix + "param", invoke, false).size() > 0) { issues.push_back(InterpreterIssue("Invoke element cannot have namelist attribute and param child", invoke, InterpreterIssue::USCXML_ISSUE_WARNING)); } + if (HAS_ATTR(invoke, "src") && InterpreterImpl::filterChildElements(_nsInfo.xmlNSPrefix + "content", invoke, false).size() > 0) { + issues.push_back(InterpreterIssue("Invoke element cannot have src attribute and content child", invoke, InterpreterIssue::USCXML_ISSUE_WARNING)); + + } } + for (int i = 0; i < doneDatas.size(); i++) { + Element<std::string> donedata = Element<std::string>(doneDatas[i]); + if (InterpreterImpl::filterChildElements(_nsInfo.xmlNSPrefix + "content", donedata, false).size() > 0 && + InterpreterImpl::filterChildElements(_nsInfo.xmlNSPrefix + "param", donedata, false).size() > 0) { + issues.push_back(InterpreterIssue("Donedata element cannot have param child and content child", donedata, InterpreterIssue::USCXML_ISSUE_WARNING)); + } + } } // check that the datamodel is known if not already instantiated diff --git a/src/uscxml/debug/InterpreterIssue.h b/src/uscxml/debug/InterpreterIssue.h index c49233f..0e1f949 100644 --- a/src/uscxml/debug/InterpreterIssue.h +++ b/src/uscxml/debug/InterpreterIssue.h @@ -36,12 +36,13 @@ public: USCXML_ISSUE_INFO }; - InterpreterIssue(const std::string& msg, Arabica::DOM::Node<std::string> node, IssueSeverity severity); + InterpreterIssue(const std::string& msg, Arabica::DOM::Node<std::string> node, IssueSeverity severity, const std::string& specRef = ""); std::string xPath; - std::string message; + std::string message; Arabica::DOM::Node<std::string> node; IssueSeverity severity; + std::string specRef; private: static std::list<InterpreterIssue> forInterpreter(InterpreterImpl* interpreter); diff --git a/src/uscxml/interpreter/InterpreterRC.cpp b/src/uscxml/interpreter/InterpreterRC.cpp index b933993..879c771 100644 --- a/src/uscxml/interpreter/InterpreterRC.cpp +++ b/src/uscxml/interpreter/InterpreterRC.cpp @@ -209,15 +209,22 @@ Arabica::XPath::NodeSet<std::string> InterpreterRC::computeExitSet(const Arabica } Arabica::XPath::NodeSet<std::string> InterpreterRC::computeExitSet(const Arabica::DOM::Node<std::string>& transition) { - if (_exitSet.find(transition) != _exitSet.end()) // speed up removeConflicting - return _exitSet[transition]; +// if (_exitSet.find(transition) != _exitSet.end()) // speed up removeConflicting +// return _exitSet[transition]; Arabica::XPath::NodeSet<std::string> transitions; transitions.push_back(transition); Arabica::XPath::NodeSet<std::string> exitSet = computeExitSet(transitions); - _exitSet[transition] = exitSet; + //_exitSet[transition] = exitSet; +#if 0 + std::cerr << "Exit set for transition '" << transition << "': " << std::endl; + for (int i = 0; i < exitSet.size(); i++) { + std::cerr << ATTR_CAST(exitSet[i], "id") << std::endl << "----" << std::endl; + } + std::cerr << std::endl; +#endif return exitSet; } @@ -303,11 +310,11 @@ void InterpreterRC::enterStates(const Arabica::XPath::NodeSet<std::string>& enab // only process first donedata element doneData = Element<std::string>(doneDatas[0]); } - internalDoneSend(parent, doneData); if (parentIsScxmlState(s)) { _topLevelFinalReached = true; } else { + internalDoneSend(parent, doneData); Element<std::string> grandParent = (Element<std::string>)parent.getParentNode(); // internalDoneSend(parent, Arabica::DOM::Element<std::string>()); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp index 3c0b84b..dc0e281 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp @@ -556,7 +556,7 @@ void JSCDataModel::setForeach(const std::string& item, } bool JSCDataModel::isLocation(const std::string& expr) { - // location needs to be RHS and ++ is only valid for RHS + // location needs to be LHS and ++ is only valid for LHS return isValidSyntax(expr + "++"); } diff --git a/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp index 2621c66..2ca2bb3 100644 --- a/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp +++ b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp @@ -458,9 +458,9 @@ Data PromelaDataModel::evaluateExpr(void* ast) { case PML_CMPND: return getVariable(node); case PML_STRING: { -// std::string stripped = node->value.substr(1, node->value.size() - 2); -// return Data(stripped, Data::VERBATIM); - return Data(node->value, Data::INTERPRETED); + std::string stripped = node->value.substr(1, node->value.size() - 2); + return Data(stripped, Data::VERBATIM); +// return Data(node->value, Data::INTERPRETED); } case PML_PLUS: return dataToInt(evaluateExpr(*opIter++)) + dataToInt(evaluateExpr(*opIter++)); diff --git a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp index 06461aa..8822579 100644 --- a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp +++ b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp @@ -793,7 +793,7 @@ NodeSetVariableResolver::resolveVariable(const std::string& namepaceUri, const std::string& name) const { std::map<std::string, NodeSet<std::string> >::const_iterator n = _variables.find(name); if(n == _variables.end()) { - ERROR_EXECUTION_THROW("No varable named '" + name + "'"); + ERROR_EXECUTION_THROW("No variable named '" + name + "'"); } #if VERBOSE std::cout << std::endl << "Getting " << name << ":" << std::endl; diff --git a/src/uscxml/plugins/element/fetch/FetchElement.cpp b/src/uscxml/plugins/element/fetch/FetchElement.cpp index c042802..595c913 100644 --- a/src/uscxml/plugins/element/fetch/FetchElement.cpp +++ b/src/uscxml/plugins/element/fetch/FetchElement.cpp @@ -81,15 +81,15 @@ void FetchElement::downloadFailed(const URL& url, int errorCode) { } void FetchElement::enterElement(const Arabica::DOM::Element<std::string>& node) { - if (!HAS_ATTR(node, "target") && !HAS_ATTR(node, "targetexpr")) { - LOG(ERROR) << "Fetch element requires target or targetexpr"; + if (!HAS_ATTR(node, "src") && !HAS_ATTR(node, "srcexpr")) { + LOG(ERROR) << "Fetch element requires src or srcexpr"; return; } - if (HAS_ATTR(node, "targetexpr") && !_interpreter->getDataModel()) { - LOG(ERROR) << "Fetch element with targetexpr requires datamodel"; + if (HAS_ATTR(node, "srcexpr") && !_interpreter->getDataModel()) { + LOG(ERROR) << "Fetch element with srcexpr requires datamodel"; return; } - _target = (HAS_ATTR(node, "target") ? ATTR(node, "target") : _interpreter->getDataModel().evalAsString(ATTR(node, "targetexpr"))); + _source = (HAS_ATTR(node, "src") ? ATTR(node, "src") : _interpreter->getDataModel().evalAsString(ATTR(node, "srcexpr"))); if (!HAS_ATTR(node, "callback") && !HAS_ATTR(node, "callbackexpr")) { LOG(ERROR) << "Fetch element requires callback or callbackexpr"; @@ -110,10 +110,10 @@ void FetchElement::enterElement(const Arabica::DOM::Element<std::string>& node) return; } - _targetUrl = URL(_target); + _targetUrl = URL(_source); if (!_targetUrl.isAbsolute()) { if (!_targetUrl.toAbsolute(_interpreter->getBaseURL(node))) { - LOG(ERROR) << "Cannot transform " << _target << " into absolute URL"; + LOG(ERROR) << "Cannot transform " << _source << " into absolute URL"; return; } } diff --git a/src/uscxml/plugins/element/fetch/FetchElement.h b/src/uscxml/plugins/element/fetch/FetchElement.h index e3e5008..3b7628a 100644 --- a/src/uscxml/plugins/element/fetch/FetchElement.h +++ b/src/uscxml/plugins/element/fetch/FetchElement.h @@ -53,7 +53,7 @@ public: protected: URL _targetUrl; - std::string _target; + std::string _source; std::string _callback; std::string _type; }; diff --git a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp index 79b1829..d3aa35f 100644 --- a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp +++ b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp @@ -64,7 +64,8 @@ Data USCXMLInvoker::getDataModelVariables() { } void USCXMLInvoker::send(const SendRequest& req) { - _invokedInterpreter.receive(req); + if (_invokedInterpreter) + _invokedInterpreter.receive(req); } void USCXMLInvoker::cancel(const std::string sendId) { @@ -96,6 +97,15 @@ void USCXMLInvoker::invoke(const InvokeRequest& req) { DataModel dataModel(_invokedInterpreter.getImpl()->getDataModel()); _invokedInterpreter.getImpl()->setParentQueue(&_parentQueue); + // copy monitors + std::set<InterpreterMonitor*>::const_iterator monIter = _interpreter->_monitors.begin(); + while(monIter != _interpreter->_monitors.end()) { + if ((*monIter)->copyToInvokers()) { + _invokedInterpreter.getImpl()->_monitors.insert(*monIter); + } + monIter++; + } + // transfer namespace prefixes _invokedInterpreter.setNameSpaceInfo(_parentInterpreter->getNameSpaceInfo()); _invokedInterpreter.getImpl()->_sessionId = req.invokeid; diff --git a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp index cf7c8e7..19d109a 100644 --- a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp +++ b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp @@ -123,21 +123,22 @@ bool BasicHTTPIOProcessor::httpRecvRequest(const HTTPServer::Request& req) { * raises. */ - // this will call the const subscript operator -// if (req.data.at("content").hasKey("_scxmleventname")) { -// reqEvent.name = req.data.at("content").at("_scxmleventname").atom; -// } -// if (req.data.at("content").hasKey("content")) { -// reqEvent.content = req.data.at("content").at("content").atom; -// } - + { // if we sent ourself an event it will end up here + // this will call the const subscript operator + if (req.data.at("content").hasKey("_scxmleventname")) { + reqEvent.name = req.data.at("content").at("_scxmleventname").atom; + } + if (req.data.at("content").hasKey("content")) { + reqEvent.content = req.data.at("content").at("content").atom; + } + } + + // if we used wget, it will end up here - unify? if (req.data.hasKey("content")) { const Data& data = req.data["content"]; for(std::map<std::string, Data>::const_iterator compIter = data.compound.begin(); compIter!= data.compound.end(); compIter++) { - if (compIter->first == "_scxmleventname") { - reqEvent.name = compIter->second.atom; - } else if (compIter->first == "content") { + if (compIter->first == "content") { reqEvent.content = compIter->second.atom; } else { reqEvent.data[compIter->first] = compIter->second; @@ -145,6 +146,16 @@ bool BasicHTTPIOProcessor::httpRecvRequest(const HTTPServer::Request& req) { } } + if (req.data.hasKey("header")) { + const Data& data = req.data["header"]; + for(std::map<std::string, Data>::const_iterator compIter = data.compound.begin(); + compIter!= data.compound.end(); compIter++) { + if (compIter->first == "_scxmleventname") { + reqEvent.name = compIter->second.atom; + } + } + } + // check whether we can parse it as XML if (reqEvent.content.length() > 0) { NameSpacingParser parser = NameSpacingParser::fromXML(reqEvent.content); diff --git a/src/uscxml/transform/ChartToFSM.cpp b/src/uscxml/transform/ChartToFSM.cpp index fd7491c..d55ef24 100644 --- a/src/uscxml/transform/ChartToFSM.cpp +++ b/src/uscxml/transform/ChartToFSM.cpp @@ -416,6 +416,9 @@ void ChartToFSM::internalDoneSend(const Arabica::DOM::Element<std::string>& stat if (!isState(state)) return; +// if (LOCALNAME(state) == "scxml") +// return; + // if (parentIsScxmlState(state)) // return; @@ -596,19 +599,149 @@ void ChartToFSM::annotateRaiseAndSend(const Arabica::DOM::Element<std::string>& } } -void ChartToFSM::indexTransitions() { - indexTransitions(_scxml); +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"); + } + } +} + +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()); + } +} + +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()); - 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++; - } + } +} + +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 = ", "; + } + +// if (isDescendant(d1, d2) || isDescendant(d2, d1) || d1 == d2) { +// preemptionStr << seperator << ATTR(t2, "priority"); +// seperator = ", "; +// } - // reverse indices for most prior to be in front - std::reverse(indexedTransitions.begin(), indexedTransitions.end()); + } + if (preemptionStr.str().size() > 0) + t1.setAttribute("conflicts", preemptionStr.str()); + + } +} + +void ChartToFSM::indexTransitions() { + 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--; + } +#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++; + } +#endif + // reverse indices for most prior to be in front + //std::reverse(indexedTransitions.begin(), indexedTransitions.end()); } +#if 0 void ChartToFSM::indexTransitions(const Arabica::DOM::Element<std::string>& root) { // breadth first traversal of transitions Arabica::XPath::NodeSet<std::string> levelTransitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", root); @@ -624,7 +757,26 @@ 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])); + } +} + +#endif bool GlobalTransition::operator< (const GlobalTransition& other) const { const std::vector<Arabica::DOM::Element<std::string> >& indexedTransitions = interpreter->indexedTransitions; NodeSet<std::string> transitions = getTransitions(); diff --git a/src/uscxml/transform/ChartToFSM.h b/src/uscxml/transform/ChartToFSM.h index 64d1a0c..f7e00c5 100644 --- a/src/uscxml/transform/ChartToFSM.h +++ b/src/uscxml/transform/ChartToFSM.h @@ -242,6 +242,10 @@ public: virtual ~ChartToFSM(); void indexTransitions(); + void annotateDomain(); + void annotateExitSet(); + void annotateEntrySet(); + void annotateConflicts(); Arabica::DOM::Document<std::string> getDocument() const; // overwrite to return flat FSM protected: diff --git a/src/uscxml/transform/ChartToPromela.cpp b/src/uscxml/transform/ChartToPromela.cpp index 867092d..965eebc 100644 --- a/src/uscxml/transform/ChartToPromela.cpp +++ b/src/uscxml/transform/ChartToPromela.cpp @@ -384,7 +384,7 @@ 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::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(); @@ -1603,52 +1603,53 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica: } if (_analyzer->usesComplexEventStruct()) { stream << padding << "{" << std::endl; - stream << _analyzer->getTypeReset("tmpE", _analyzer->getType("_event"), padding + " "); - stream << 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")) { - stream << padding << " /* idlocation */" << std::endl; - stream << padding << " _lastSendId = _lastSendId + 1;" << std::endl; - stream << padding << " " << _prefix << ATTR(nodeElem, "idlocation") << " = _lastSendId;" << std::endl; - stream << padding << " tmpE.sendid = _lastSendId;" << std::endl; - stream << padding << " if" << std::endl; - stream << padding << " :: _lastSendId == 2147483647 -> _lastSendId = 0;" << std::endl; - stream << padding << " :: else -> skip;" << std::endl; - stream << padding << " fi;" << std::endl; + typeAssignSS << padding << " /* idlocation */" << std::endl; + typeAssignSS << padding << " _lastSendId = _lastSendId + 1;" << std::endl; + typeAssignSS << padding << " " << _prefix << ATTR(nodeElem, "idlocation") << " = _lastSendId;" << std::endl; + typeAssignSS << padding << " tmpE.sendid = _lastSendId;" << std::endl; + typeAssignSS << padding << " if" << std::endl; + typeAssignSS << padding << " :: _lastSendId == 2147483647 -> _lastSendId = 0;" << std::endl; + typeAssignSS << padding << " :: else -> skip;" << std::endl; + typeAssignSS << padding << " fi;" << std::endl; } else if (HAS_ATTR(nodeElem, "id")) { - stream << padding << " tmpE.sendid = " << _analyzer->macroForLiteral(ATTR(nodeElem, "id")) << ";" << std::endl; + 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 - stream << padding << " tmpE.invokeid = " << _analyzer->macroForLiteral(_invokerid) << ";" << std::endl; + typeAssignSS << padding << " tmpE.invokeid = " << _analyzer->macroForLiteral(_invokerid) << ";" << std::endl; } if (_analyzer->usesEventField("origintype") && !boost::ends_with(targetQueue, "iQ")) { - stream << padding << " tmpE.origintype = " << _analyzer->macroForLiteral("http://www.w3.org/TR/scxml/#SCXMLEventProcessor") << ";" << std::endl; + typeAssignSS << padding << " tmpE.origintype = " << _analyzer->macroForLiteral("http://www.w3.org/TR/scxml/#SCXMLEventProcessor") << ";" << std::endl; } if (_analyzer->usesEventField("delay")) { #if NEW_DELAY_RESHUFFLE #else insertOp += "!"; - stream << padding << " _lastSeqId = _lastSeqId + 1;" << std::endl; + typeAssignSS << padding << " _lastSeqId = _lastSeqId + 1;" << std::endl; #endif if (HAS_ATTR_CAST(nodeElem, "delay")) { - stream << padding << " tmpE.delay = " << ATTR_CAST(nodeElem, "delay") << ";" << std::endl; + typeAssignSS << padding << " tmpE.delay = " << ATTR_CAST(nodeElem, "delay") << ";" << std::endl; } else if (HAS_ATTR_CAST(nodeElem, "delayexpr")) { - stream << padding << " tmpE.delay = " << ADAPT_SRC(ATTR_CAST(nodeElem, "delayexpr")) << ";" << std::endl; + typeAssignSS << padding << " tmpE.delay = " << ADAPT_SRC(ATTR_CAST(nodeElem, "delayexpr")) << ";" << std::endl; } else { - stream << padding << " tmpE.delay = 0;" << std::endl; + typeAssignSS << padding << " tmpE.delay = 0;" << std::endl; } #if NEW_DELAY_RESHUFFLE #else - stream << padding << " tmpE.seqNr = _lastSeqId;" << std::endl; + typeAssignSS << padding << " tmpE.seqNr = _lastSeqId;" << std::endl; #endif } if (_analyzer->usesEventField("type")) { std::string eventType = (targetQueue.compare("iQ!") == 0 ? _analyzer->macroForLiteral("internal") : _analyzer->macroForLiteral("external")); - stream << padding << " tmpE.type = " << eventType << ";" << std::endl; + typeAssignSS << padding << " tmpE.type = " << eventType << ";" << std::endl; } NodeSet<std::string> sendParams = filterChildElements(_nsInfo.xmlNSPrefix + "param", nodeElem); @@ -1657,14 +1658,14 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica: if (sendParams.size() > 0) { for (int i = 0; i < sendParams.size(); i++) { Element<std::string> paramElem = Element<std::string>(sendParams[i]); - stream << padding << " tmpE.data." << ATTR(paramElem, "name") << " = " << ADAPT_SRC(ATTR(paramElem, "expr")) << ";" << std::endl; + typeAssignSS << padding << " tmpE.data." << ATTR(paramElem, "name") << " = " << ADAPT_SRC(ATTR(paramElem, "expr")) << ";" << std::endl; } } if (sendNameList.size() > 0) { std::list<std::string> nameListIds = tokenizeIdRefs(sendNameList); std::list<std::string>::iterator nameIter = nameListIds.begin(); while(nameIter != nameListIds.end()) { - stream << padding << " tmpE.data." << *nameIter << " = " << ADAPT_SRC(*nameIter) << ";" << std::endl; + typeAssignSS << padding << " tmpE.data." << *nameIter << " = " << ADAPT_SRC(*nameIter) << ";" << std::endl; nameIter++; } } @@ -1674,14 +1675,42 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica: if (contentElem.hasChildNodes() && contentElem.getFirstChild().getNodeType() == Node_base::TEXT_NODE) { std::string content = spaceNormalize(contentElem.getFirstChild().getNodeValue()); if (!isNumeric(content.c_str(), 10)) { - stream << padding << " tmpE.data = " << _analyzer->macroForLiteral(content) << ";" << std::endl; + typeAssignSS << padding << " tmpE.data = " << _analyzer->macroForLiteral(content) << ";" << std::endl; } else { - stream << padding << " tmpE.data = " << content << ";" << std::endl; + typeAssignSS << padding << " tmpE.data = " << content << ";" << std::endl; } } else if (HAS_ATTR(contentElem, "expr")) { - stream << padding << " tmpE.data = " << ADAPT_SRC(ATTR(contentElem, "expr")) << ";" << std::endl; + typeAssignSS << padding << " tmpE.data = " << ADAPT_SRC(ATTR(contentElem, "expr")) << ";" << std::endl; } } + + // 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('.')); +// std::istringstream typeResetSS (typeReset); +// for (std::string reset; std::getline(typeResetSS, reset); ) { +// if (!boost::find_first(reset, assigned)) { +// 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 @@ -2276,7 +2305,7 @@ void ChartToPromela::writeFSM(std::ostream& stream) { PromelaInline::PROMELA_EVENT_ONLY); stream << " atomic {" << std::endl; - stream << " /* pop an event */" << std::endl; + stream << "/* pop an event */" << std::endl; stream << " if" << std::endl; stream << " :: len(" << _prefix << "iQ) != 0 -> " << _prefix << "iQ ? " << _prefix << "_event /* from internal queue */" << std::endl; if (eventSources.size() > 0) { @@ -2363,7 +2392,7 @@ void ChartToPromela::writeFSM(std::ostream& stream) { stream << " fi;" << std::endl << std::endl; - stream << " /* terminate if we are stopped */" << std::endl; + stream << "/* terminate if we are stopped */" << std::endl; stream << " if" << std::endl; stream << " :: " << _prefix << "done -> goto " << _prefix << "terminate;" << std::endl; if (_parent != NULL) { |