summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bindings/CMakeLists.txt13
-rw-r--r--src/bindings/swig/php/uscxmlNativePHP.php27
-rw-r--r--src/uscxml/Interpreter.cpp164
-rw-r--r--src/uscxml/Interpreter.h13
-rw-r--r--src/uscxml/debug/InterpreterIssue.cpp40
-rw-r--r--src/uscxml/debug/InterpreterIssue.h5
-rw-r--r--src/uscxml/interpreter/InterpreterRC.cpp15
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp2
-rw-r--r--src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp6
-rw-r--r--src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp2
-rw-r--r--src/uscxml/plugins/element/fetch/FetchElement.cpp14
-rw-r--r--src/uscxml/plugins/element/fetch/FetchElement.h2
-rw-r--r--src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp12
-rw-r--r--src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp33
-rw-r--r--src/uscxml/transform/ChartToFSM.cpp170
-rw-r--r--src/uscxml/transform/ChartToFSM.h4
-rw-r--r--src/uscxml/transform/ChartToPromela.cpp83
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) {