summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Radomski <sradomski@mintwerk.de>2016-02-11 09:40:02 (GMT)
committerStefan Radomski <sradomski@mintwerk.de>2016-02-11 09:40:02 (GMT)
commit7b428e5435f83a7e7db37094a9197afa2dd09bf5 (patch)
tree8e23dcc47322ddd79ada2bdbb5f0315266b1e1b4
parent179fe8cd5cf53893ad1783ff0ff41cf94e24a59b (diff)
downloaduscxml-7b428e5435f83a7e7db37094a9197afa2dd09bf5.zip
uscxml-7b428e5435f83a7e7db37094a9197afa2dd09bf5.tar.gz
uscxml-7b428e5435f83a7e7db37094a9197afa2dd09bf5.tar.bz2
Some tidying up of ANSI-C transformation
-rw-r--r--README.md21
-rw-r--r--apps/uscxml-transform.cpp39
-rw-r--r--docs/COMPARISON.md89
-rw-r--r--docs/GETTING_STARTED.md (renamed from docs/untitled.txt)0
-rw-r--r--docs/NATIVE_CODE.md142
-rw-r--r--src/uscxml/transform/ChartToC.cpp203
-rw-r--r--src/uscxml/transform/ChartToC.h2
-rw-r--r--src/uscxml/transform/ChartToVHDL.cpp112
-rw-r--r--src/uscxml/transform/ChartToVHDL.h6
-rw-r--r--test/CMakeLists.txt25
-rw-r--r--test/src/test-c-inline.c40
-rw-r--r--test/src/test-c-inline.c.scxml.c951
-rw-r--r--test/src/test-c-machine.cpp42
-rw-r--r--test/src/test-c-machine.scxml.c (renamed from test/src/test-c-machine.machine.c)228
14 files changed, 1727 insertions, 173 deletions
diff --git a/README.md b/README.md
index 3798be5..35ef803 100644
--- a/README.md
+++ b/README.md
@@ -55,7 +55,7 @@ frontend. It implements the following features:
* C# bindings
* PHP module for apache and cli interpreter (discontinued)
* <b>Interactive Debugger</b>
- * Accessible via a [web-frontend](http://htmlpreview.github.io/?https://github.com/tklab-tud/uscxml/blob/master/apps/uscxml-debugger.html)
+ * Accessible via a [web-frontend](http://htmlpreview.github.io/?apps/uscxml-debugger.html)
* Complete with user-defined breakpoints, data model inspection and stepping
### Transformer
@@ -65,21 +65,24 @@ made available via the <tt>uscxml-transform</tt> binary. It is a general tool
for SCXML documents and currently implements the following features:
* Transformations onto
- * [Flattened SCXML documents](https://github.com/tklab-tud/uscxml/blob/master/src/uscxml/transform/ChartToFlatSCXML.cpp) in which only a single state is ever active
+ * [Flattened SCXML documents](src/uscxml/transform/ChartToFlatSCXML.cpp) in which only a single state is ever active
* Resulting documents require slight adaptations to a compliant interpreter for donedata, the <tt>In</tt> predicate and invokers.
* Semantic equivalence is shown via IRP tests.
- * [ANSI C native code](https://github.com/tklab-tud/uscxml/blob/master/src/uscxml/transform/ChartToC.cpp) for easy embedding of SCXML state-charts in C and C++ programs
+ * [ANSI C native code](src/uscxml/transform/ChartToC.cpp) for easy embedding of SCXML state-charts in C and C++ programs
* No custom I/O processors implemented in scaffolding just yet.
- * [PROMELA programs](https://github.com/tklab-tud/uscxml/blob/master/src/uscxml/transform/ChartToPromela.cpp) for model-checking via linear temporal logic with the SPIN model-checker.
+ * To get started with transforming and embedding ANSI C code, read the [inline SCXML document](docs/NATIVE_CODE.md).
+ * [PROMELA programs](src/uscxml/transform/ChartToPromela.cpp) for model-checking via linear temporal logic with the SPIN model-checker.
* Only defined for the <tt>promela</tt> and <tt>null</tt> datamodel.
- * [Minimized SCXML documents](https://github.com/tklab-tud/uscxml/blob/master/src/uscxml/transform/ChartToMinimalSCXML.cpp) with dead states and executable content removed
+ * [Minimized SCXML documents](src/uscxml/transform/ChartToMinimalSCXML.cpp) with dead states and executable content removed
* Minimization is performed dynamically by marking elements as visited and removing unvisited elements.
* Annotations of the transitions exit set entry set, priority, conflicts, domain
+Currently, we support a transformation from SCXML onto ANSI C.
+
### Test Reports
* We continuously run the [W3C IRP tests](http://www.w3.org/Voice/2013/scxml-irp/) for SCXML.
-* Some tests are [excluded](https://github.com/tklab-tud/uscxml/blob/master/test/ctest/CTestCustom.ctest.in).
+* Some tests are [excluded](test/ctest/CTestCustom.ctest.in).
To run the tests yourself, you need to generate the build environment and pass <tt>-DBUILD_TESTS=ON</tt> via CMake:
@@ -100,14 +103,14 @@ so maybe restrict yourself to some subset.
uSCXML itself is distributed under the Simplified BSD license as in, do not sue us and do
not misrepresent authorship. Please have a look at the licenses of the [libraries we depend
-upon](https://github.com/tklab-tud/uscxml/blob/master/docs/BUILDING.md#build-dependencies) as well.
+upon](docs/BUILDING.md#build-dependencies) as well.
## Performance
We did some performance measurements in the scope of the C transformation. As
you can see in the figure below, for most IRP tests we average to a duration of
5-20us per microstep on an early 2015 MacBook Pro 13" with 3.1GHz in the case
-of [generated/compiled C](https://github.com/tklab-tud/uscxml/blob/master/test/src/test-c-machine.machine.c). For interpretation at runtime, we average at around 70-130us per
+of [generated/compiled C](test/src/test-c-machine.machine.c). For interpretation at runtime, we average at around 70-130us per
microstep. The generated C is rather optimized while the focus of the
interpreter is more on correctness, feature completeness and extensibility.
However, there are some lessons learned that are yet to be applied for the
@@ -116,7 +119,7 @@ interpreter.
<img src="https://raw.github.com/tklab-tud/uscxml/master/docs/Performance_Microstep.png" width="500px" />
For the tests, we took the
-[highest precision timer](https://github.com/tklab-tud/uscxml/blob/master/src/uscxml/concurrency/Timer.cpp)
+[highest precision timer](src/uscxml/concurrency/Timer.cpp)
we could attain and measured how long the execution of a given SCXML IRP test
took while subtracting initialization, tear-down and the time spent in the
data-model's routines. Time is averaged over 1.000 iterations.
diff --git a/apps/uscxml-transform.cpp b/apps/uscxml-transform.cpp
index 857a160..a5aa9ec 100644
--- a/apps/uscxml-transform.cpp
+++ b/apps/uscxml-transform.cpp
@@ -275,11 +275,44 @@ int main(int argc, char** argv) {
} else {
interpreter = Interpreter::fromURL(inputFile);
}
- if (!interpreter) {
- LOG(ERROR) << "Cannot create interpreter from " << inputFile;
- exit(EXIT_FAILURE);
+ } catch (Event e) {
+ // we will reattempt below, not yet a fatal error
+ } catch (const std::exception &e) {
+ std::cout << e.what() << std::endl;
+ }
+
+ if (!interpreter) {
+ URL tmp(inputFile);
+ tmp.toAbsoluteCwd();
+ std::stringstream contentSS;
+ contentSS << tmp;
+
+ std::string inlineBeginMarker = "INLINE SCXML BEGIN\n";
+ std::string inlineEndMarker = "\nINLINE SCXML END";
+
+ size_t inlineSCXMLBegin = contentSS.str().find(inlineBeginMarker);
+ if (inlineSCXMLBegin != std::string::npos) {
+ inlineSCXMLBegin += inlineBeginMarker.size();
+ size_t inlineSCXMLEnd = contentSS.str().find(inlineEndMarker);
+ std::string inlineSCXMLContent = contentSS.str().substr(inlineSCXMLBegin, inlineSCXMLEnd - inlineSCXMLBegin);
+ try {
+ interpreter = Interpreter::fromXML(inlineSCXMLContent, tmp);
+ } catch (Event e) {
+ std::cout << e << std::endl;
+ } catch (const std::exception &e) {
+ std::cout << e.what() << std::endl;
+ }
}
+ }
+
+ if (!interpreter) {
+ LOG(ERROR) << "Cannot create interpreter from " << inputFile;
+ exit(EXIT_FAILURE);
+
+ }
+
+ try {
if (verbose) {
std::list<InterpreterIssue> issues = interpreter.validate();
for (std::list<InterpreterIssue>::iterator issueIter = issues.begin(); issueIter != issues.end(); issueIter++) {
diff --git a/docs/COMPARISON.md b/docs/COMPARISON.md
new file mode 100644
index 0000000..94e8d3b
--- /dev/null
+++ b/docs/COMPARISON.md
@@ -0,0 +1,89 @@
+# Comparison of SCXML Interpreters
+
+In this document, I will make an attempt to compare and measure the performance
+of the various, freely available SCXML interpreters. If you are the author of
+one of these interpreters and feel that I misrepresented your work, please do
+not hesitate to contact me and I will reevaluate / correct any factual errors.
+
+This selection is based on the list of available implementations on the [SCXML
+wiki](https://en.wikipedia.org/wiki/SCXML) page, plus a few interpreters I know
+from the [W3C mailing list](https://lists.w3.org/Archives/Public/www-voice/)
+and the [SCXML workshops](http://scxmlworkshop.de). I will list all
+interpreters known to me, but only benchmark those that pass the W3C IRP tests
+as is required for an actual SCXML interpreter.
+
+# Methodology
+
+The benchmarks were performed with a [huge
+SCXML](https://github.com/tklab-tud/uscxml/tree/master/test/w3c/compound) file
+containing all of the automatic W3C IRP tests that do not rely on timeouts to
+pass.
+
+## scxmlcc
+
+| Platforms | Tested on | Tested | Website |
+|---------------|---------------------|------------------|---------------|
+| Linux only | Debian Jessie 64Bit | **No**: Subset of SCXML implemented is insufficient for SCXML IRP tests. | [http://scxmlcc.org](http://scxmlcc.org) |
+
+### How to build
+
+ $ sudo apt-get install build-essential libboost-all-dev autorevision
+ $ git clone https://github.com/jp-embedded/scxmlcc.git
+ $ cd scxmlcc/src
+ $ make
+
+### Evaluation
+
+ $ ./scxmlcc -i ./test-ecma-all.scxml |sort |uniq
+ warning: event asteriks not currently supported
+ warning: event tokens not currently supported
+ warning: parallel support is not fully implemented/tested
+ warning: unknown action type 'script'
+ warning: unknown item 'assign' in <onentry> or <onexit>
+ warning: unknown item 'assign' in <transition>
+ warning: unknown item 'cancel' in <transition>
+ warning: unknown item 'datamodel' in <state>
+ warning: unknown item 'donedata' in <state>
+ warning: unknown item 'foreach' in <onentry> or <onexit>
+ warning: unknown item 'if' in <onentry> or <onexit>
+ warning: unknown item 'invoke' in <state>
+ warning: unknown item 'send' in <onentry> or <onexit>
+ warning: unknown item 'send' in <transition>
+
+The subset of SCXML implemented in <tt>scxmlcc</tt> is insufficient to run the
+performance / compliance benchmarks.
+
+## SCXML Lab
+
+| Platforms | Tested on | Tested | Website |
+|---------------|---------------------|-----------|---------------|
+| HTML5 | Safari 9.0.3 | **No**: Subset of SCXML implemented is insufficient for SCXML IRP tests. | [http://www.ling.gu.se/~lager/Labs/SCXML-Lab/](http://www.ling.gu.se/~lager/Labs/SCXML-Lab/) |
+
+I pasted the file above into their web-frontend and got a <tt>validation-error</tt>
+
+ Unexpected attribute 'datamodel' in <scxml>. Hint:
+ Valid attributes are: 'id', 'initialstate', 'version', 'xmlns'.
+
+The <tt>datamodel</tt> is indeed not required for a compliant interpreter, but
+we will not be able to pass any meaningful subset of the SCXML IRP tests
+without support for a datamodel.
+
+## Legian
+
+| Platforms | Tested on | Tested | Website |
+|---------------|---------------------|-----------|---------------|
+| Java | Java(TM) SE (build 1.8.0_45-b14) | **No**: Subset of SCXML implemented is insufficient for SCXML IRP tests. | [https://github.com/pelatimtt/Legian](https://github.com/pelatimtt/Legian/) |
+
+Does not claim W3C compliance and will, therefore, not pass the compound IRP tests.
+
+## Qt SCXML Engine
+
+| Platforms | Tested on | Tested | Website |
+|---------------|---------------------|-----------|---------------|
+| Any | Mac OSX 10.11.3 with Macports 2.3.4 | **No**: Subset of SCXML implemented is insufficient for SCXML IRP tests. | [https://qt.gitorious.org/qt-labs/scxml](https://qt.gitorious.org/qt-labs/scxml/) |
+
+[No
+support](https://qt.gitorious.org/qt-labs/scxml?p=qt-labs:scxml.git;a=blob_plain;f=doc/scxml.qdoc;hb=HEAD)
+for <tt>&lt;donedata></tt>, <tt>&lt;finalize></tt>. Furthermore the
+<tt>profile</tt> (now <tt>datamodel</tt> with finalized SCXML recommendation)
+attribute is ignored.
diff --git a/docs/untitled.txt b/docs/GETTING_STARTED.md
index 8c585bf..8c585bf 100644
--- a/docs/untitled.txt
+++ b/docs/GETTING_STARTED.md
diff --git a/docs/NATIVE_CODE.md b/docs/NATIVE_CODE.md
new file mode 100644
index 0000000..91af599
--- /dev/null
+++ b/docs/NATIVE_CODE.md
@@ -0,0 +1,142 @@
+# Generating Native Code
+
+You can use the <tt>uscxml-transform</tt> tool to create native code from an
+SCXML document. In this case, you will not use an instance of the
+<tt>uscxml::Interpreter</tt> class, but instantiate an SCXML context from a
+native description of the state-chart.
+
+## Embedding ANSI C
+
+To embed the control flow described within an SCXML document in most variances
+of the C language, we provide a transformation onto ANSI C (C89) as a proper
+subset of virtually any more modern C/C++ dialect. There are two general
+approaches to achieve this. In any case, you need to transform your SCXML
+state-chart onto ANSI C by invoking <tt>uscxml-transform</tt>:
+
+ $ uscxml-transform -tc -i INPUT_FILE -o OUTPUT_FILE
+
+This transformation will create a single file that you can compile and link or
+include directly. I advice to include the file into another compilation unit
+and not to compile it directly, as it allows for more convenience and is
+generally a more flexible approach. The file will contain:
+
+1. A set of pre-processor **macros** for convenience and definitions, all starting
+with an <tt>USCXML_</tt> prefix. Of special note are the following macros that
+allow you to influence important characteristics of you state-machine.
+
+ * <tt>**USCXML_NR_STATES_TYPE** / **USCXML_NR_TRANS_TYPE**</tt>:
+
+ The type for unsigned integers that is of sufficient size to contain
+ the number of states / transitions of your largest state machine. The
+ transformation will automatically choose one of the <tt>uint*_t</tt>
+ types, though a popular extension, they are only available in C99
+ (<tt>stdint.h</tt>). Also, if you like to reuse parts of the file (e.g.
+ the types below) in another compilation unit, you might need to
+ predefine them explicitly to a sufficient size.
+
+ * <tt>**USCXML_MAX_NR_STATES_BYTES** / **USCXML_MAX_NR_TRANS_BYTES**</tt>:
+
+ The minimial size for the bit-arrays as <tt>char[N]</tt> containing the
+ states and transitions in the various types and on the stack during a
+ microstep. It has to be larger or equal to the smallest positive
+ integer that, when multiplied by 8 is larger or equal to the number of
+ states and transitions repsectively.
+
+ In other words, make sure that
+ <tt>states[USCXML_MAX_NR_STATES_BYTES]</tt> has room for one bit per
+ state and <tt>transitions[USCXML_MAX_NR_TRANS_BYTES]</tt> for one bit
+ per transition.
+
+ * There are some other macros defined, but they are rather for
+ micro-optimizations. Have a look at a generated file.
+
+2. All compound data **types** (<tt>struct</tt>) to encode an SCXML state-machine.
+These will refer to the macros above to require memory for a state-chart's
+states and transitions, so make sure that the macros are set if you
+conditionally include parts of the generated file and double-check that the
+type definitions are the same in every compilation unit if you want to access
+state-machines from other units (i.e. same value for macros above!).
+
+3. The actual **symbols** for one or many state-machines from the input SCXML
+file. Their identifiers are all prefixed by an identifier derived from the
+content of a given SCXML document. As such, if you transform any given SCXML
+document twice, you might end up with duplicate symbols, yet again, the
+state-chart's will be functionally identical as they contained the same content.
+
+ In order for not having to guess the prefix when referring to any machine
+ in application code, the tranformation will define three additional macros:
+
+ #ifndef USCXML_MACHINE
+ # define USCXML_MACHINE _uscxml_BC220711_machine
+ #endif
+ #define USCXML_MACHINE_0 _uscxml_BC220711_machine
+ #define USCXML_MACHINE_NAME_HERE _uscxml_BC220711_machine
+
+ The first macro is useful if you only transformed a single SCXML
+ state-chart as it will always refer to the very first state-chart
+ encountered. If there is more than one SCXML state-chart within a document
+ (i.e. an invocation of nested machines) you can also refer to them by index
+ or their eventual name.
+
+4. Some **helper functions**, most notably bit operations for arbitrary length
+bit arrays.
+
+5. The **micro-step function** <tt>uscxml_step</tt>, which will perform a
+micro-step on a given context and delegate control flow accordingly.
+
+These elements are always contained and you can, selectively, disable their
+inclusion by pre-defining respective macros (have a look at a generated source
+file).
+
+Now in order to actually use an SCXML document to manage the control flow among
+a set of functions, there are two general approaches. Both use the generated
+ANSI C source code above, but require more or less resources at runtime as
+detailled below.
+
+### Fully Compliant
+
+An SCXML interpreter does more than to perform a series of microsteps for event
+over a set of states and transitions and there are quite a few responsibilities
+not implemented in the generated ANSI C code:
+
+1. **Event Queues**:
+
+ A compliant interpreter is required to maintain two event queues, an
+ internal and an external one. With the generated ANSI C source, these are
+ integrated via four callbacks and will need to be implemented in
+ user-supplied code:
+
+ 1. <tt>**uscxml_ctx.dequeue_internal**</tt>: This callback is invoked
+ whenever the interpreter needs an event from the internal event queue. It
+ is passed an instance of a <tt>uscxml_ctx</tt> structure and is supposed to
+ return an opaque pointer to an event. If the internal queue is empty,
+ <tt>NULL</tt> is to be returned.
+
+ 2. <tt>**uscxml_ctx.dequeue_external**</tt>: This callback is functionally
+ equivalent to <tt>uscxml_ctx.dequeue_internal</tt> but invoked, when an
+ external event is to be dequeued.
+
+ 3. <tt>**uscxml_ctx.exec_content_send**</tt>: Whenever there is an
+ <tt>&lt;send></tt> element encountered in executable content, the generated
+ ANSI C code will invoke this callback with a context and an
+ <tt>uscxml_elem_send</tt> instance and the user code registered at the
+ callback is expected to handle the send request as per recommendation.
+
+ 4. <tt>**uscxml_ctx.exec_content_raise**</tt>: This callback is invoked for
+ any <tt>&lt;raise></tt> element processed as part of executable content and
+ is expected to deliver an event to the internal event queue.
+
+2. **Transition Matching / Enabling**
+
+ An event will match and enable a set of transitions. The generated ANSI C
+ source will already make sure that only valid sets of transitions can be
+ selected to constitute the optimal transition set for a microstep, but
+ user-supplied code will have to decide whether a transition is matched and
+ enabled. This is done via the <tt>**uscxml_ctx.is_enabled**</tt> callback.
+ It receives a context, a <tt>uscxml_transition</tt> structure and the
+ opaque event pointer and will have to return <tt>0</tt> for when the
+ transition is not matched and enabled by the given event and <tt>1</tt> if
+ it is.
+
+
+### Light-Weight
diff --git a/src/uscxml/transform/ChartToC.cpp b/src/uscxml/transform/ChartToC.cpp
index f9eba98..c6be393 100644
--- a/src/uscxml/transform/ChartToC.cpp
+++ b/src/uscxml/transform/ChartToC.cpp
@@ -56,6 +56,15 @@ ChartToC::ChartToC(const Interpreter& other) : TransformerImpl(), _topMostMachin
prepare();
findNestedMachines();
+ if (_extensions.find("prefix") != _extensions.end()) {
+ _prefixes = new std::list<std::string>();
+ std::pair<std::multimap<std::string, std::string>::iterator,
+ std::multimap<std::string, std::string>::iterator> keyRange = _extensions.equal_range("prefix");
+ for (std::multimap<std::string, std::string>::iterator iter = keyRange.first; iter != keyRange.second; ++iter) {
+ _prefixes->push_back(iter->second);
+ }
+ }
+
}
void ChartToC::setHistoryCompletion() {
@@ -423,8 +432,8 @@ void ChartToC::writeTo(std::ostream& stream) {
(*machIter)->writeExecContent(stream);
(*machIter)->writeStates(stream);
(*machIter)->writeTransitions(stream);
+ (*machIter)->writeMachineInfo(stream);
}
- writeMachineInfo(stream);
writeHelpers(stream);
writeFSM(stream);
@@ -434,7 +443,9 @@ void ChartToC::writeTo(std::ostream& stream) {
void ChartToC::writeForwardDeclarations(std::ostream& stream) {
stream << "/* forward declare machines to allow references */" << std::endl;
- stream << "extern const uscxml_machine uscxml_machines[" << toStr(_allMachines.size() + 1) << "];" << std::endl;
+ for (std::list<ChartToC*>::iterator machIter = _allMachines.begin(); machIter != _allMachines.end(); machIter++) {
+ stream << "extern const uscxml_machine " << (*machIter)->_prefix << "_machine;" << std::endl;
+ }
stream << std::endl;
}
@@ -488,13 +499,15 @@ void ChartToC::findNestedMachines() {
}
void ChartToC::writeIncludes(std::ostream& stream) {
- stream << "#include <stdint.h> /* explicit types */" << std::endl;
+ stream << "#ifndef USCXML_NO_STDTYPES_H" << std::endl;
+ stream << "# include <stdint.h> /* explicit types */" << std::endl;
+ stream << "#endif" << std::endl;
stream << "#include <stddef.h> /* NULL */" << std::endl;
stream << std::endl;
}
void ChartToC::writeMacros(std::ostream& stream) {
- stream << "#ifndef USCXML_GEN_C_MACROS" << std::endl;
+ stream << "#ifndef USCXML_NO_GEN_C_MACROS" << std::endl;
stream << std::endl;
stream << "/**" << std::endl;
stream << " * All macros used for the scxml types and functions" << std::endl;
@@ -651,7 +664,7 @@ void ChartToC::writeMacros(std::ostream& stream) {
stream << "#define USCXML_ELEM_PARAM_IS_SET(param) (param->name != NULL)" << std::endl;
stream << "#define USCXML_MACHINE_IS_SET(machine) (machine->nr_states > 0)" << std::endl;
stream << std::endl;
- stream << "#define USCXML_GEN_C_MACROS" << std::endl;
+ stream << "#define USCXML_NO_GEN_C_MACROS" << std::endl;
stream << "#endif" << std::endl;
stream << std::endl;
}
@@ -659,11 +672,11 @@ void ChartToC::writeMacros(std::ostream& stream) {
void ChartToC::writeTypes(std::ostream& stream) {
stream << std::endl;
- stream << "#ifndef USCXML_GEN_C_TYPES" << std::endl;
+ stream << "#ifndef USCXML_NO_GEN_C_TYPES" << std::endl;
stream << std::endl;
stream << "/**" << std::endl;
stream << " * All types required to represent an SCXML state chart." << std::endl;
- stream << " * Just predefine the USCXML_GEN_C_TYPES macro if you do not need them." << std::endl;
+ stream << " * Just predefine the USCXML_NO_GEN_C_TYPES macro if you do not need them." << std::endl;
stream << " */" << std::endl;
stream << std::endl;
@@ -876,7 +889,7 @@ void ChartToC::writeTypes(std::ostream& stream) {
stream << " invoke_t invoke;" << std::endl;
stream << "};" << std::endl;
stream << std::endl;
- stream << "#define USCXML_GEN_C_TYPES" << std::endl;
+ stream << "#define USCXML_NO_GEN_C_TYPES" << std::endl;
stream << "#endif" << std::endl;
stream << std::endl;
}
@@ -917,7 +930,7 @@ void ChartToC::writeHelpers(std::ostream& stream) {
stream << "#endif" << std::endl;
stream << std::endl;
- stream << "#ifndef USCXML_BIT_OPERATIONS" << std::endl;
+ stream << "#ifndef USCXML_NO_BIT_OPERATIONS" << std::endl;
stream << "/**" << std::endl;
stream << " * Return true if there is a common bit in a and b." << std::endl;
stream << " */" << std::endl;
@@ -993,15 +1006,22 @@ void ChartToC::writeHelpers(std::ostream& stream) {
stream << " };" << std::endl;
stream << "}" << std::endl;
stream << std::endl;
- stream << "#define USCXML_BIT_OPERATIONS" << std::endl;
+ stream << "#define USCXML_NO_BIT_OPERATIONS" << std::endl;
stream << "#endif" << std::endl;
stream << std::endl;
}
void ChartToC::writeExecContentFinalize(std::ostream& stream) {
+
// needs to be written prior to invocation elem info
NodeSet<std::string> finalizes = DOMUtils::inDocumentOrder(_nsInfo.xmlNSPrefix + "finalize", _scxml);
+
+ if (finalizes.size() > 0) {
+ stream << "#ifndef USCXML_NO_EXEC_CONTENT" << std::endl;
+ stream << std::endl;
+ }
+
for (size_t i = 0; i < finalizes.size(); i++) {
Element<std::string> finalize(finalizes[i]);
NodeSet<std::string> execContent = filterChildType(Node_base::ELEMENT_NODE, finalize);
@@ -1018,9 +1038,16 @@ void ChartToC::writeExecContentFinalize(std::ostream& stream) {
}
}
+ if (finalizes.size() > 0) {
+ stream << "#endif" << std::endl;
+ stream << std::endl;
+ }
}
void ChartToC::writeExecContent(std::ostream& stream) {
+ stream << "#ifndef USCXML_NO_EXEC_CONTENT" << std::endl;
+ stream << std::endl;
+
for (size_t i = 0; i < _states.size(); i++) {
Element<std::string> state(_states[i]);
@@ -1118,6 +1145,9 @@ void ChartToC::writeExecContent(std::ostream& stream) {
}
}
+ stream << "#endif" << std::endl;
+ stream << std::endl;
+
}
void ChartToC::writeExecContent(std::ostream& stream, const Arabica::DOM::Node<std::string>& node, int indent) {
@@ -1126,8 +1156,12 @@ void ChartToC::writeExecContent(std::ostream& stream, const Arabica::DOM::Node<s
if (node.getNodeType() == Node_base::TEXT_NODE) {
if (boost::trim_copy(node.getNodeValue()).length() > 0) {
- std::string escaped = escape(node.getNodeValue());
- stream << escaped;
+ if (HAS_ATTR(_scxml, "datamodel") && ATTR(_scxml, "datamodel") == "native") {
+ stream << node.getNodeValue();
+ } else {
+ std::string escaped = escape(node.getNodeValue());
+ stream << escaped;
+ }
}
return;
}
@@ -1291,6 +1325,10 @@ void ChartToC::writeExecContent(std::ostream& stream, const Arabica::DOM::Node<s
}
void ChartToC::writeElementInfoInvocation(std::ostream& stream) {
+
+ stream << "#ifndef USCXML_NO_ELEM_INFO" << std::endl;
+ stream << std::endl;
+
NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", _scxml, true);
if (invokes.size() > 0) {
_hasElement.insert("invoke");
@@ -1321,6 +1359,15 @@ void ChartToC::writeElementInfoInvocation(std::ostream& stream) {
stream << " /* machine */ ";
if (HAS_ATTR(invoke, "md5sum")) {
+#if 1
+ size_t machIdx = 0;
+ for (std::list<ChartToC*>::iterator machIter = _allMachines.begin(); machIter != _allMachines.end(); machIter++, machIdx++) {
+ if ((*machIter)->_md5 == ATTR(invoke, "md5sum")) {
+ stream << "&" << (*machIter)->_prefix << "_machine";
+ break;
+ }
+ }
+#else
size_t machIdx = 0;
for (std::list<ChartToC*>::iterator machIter = _allMachines.begin(); machIter != _allMachines.end(); machIter++, machIdx++) {
if ((*machIter)->_md5 == ATTR(invoke, "md5sum")) {
@@ -1328,6 +1375,7 @@ void ChartToC::writeElementInfoInvocation(std::ostream& stream) {
break;
}
}
+#endif
} else {
stream << "NULL";
}
@@ -1410,9 +1458,15 @@ void ChartToC::writeElementInfoInvocation(std::ostream& stream) {
stream << std::endl;
}
+ stream << "#endif" << std::endl;
+ stream << std::endl;
+
}
void ChartToC::writeElementInfo(std::ostream& stream) {
+ stream << "#ifndef USCXML_NO_ELEM_INFO" << std::endl;
+ stream << std::endl;
+
NodeSet<std::string> foreachs = DOMUtils::inDocumentOrder(_nsInfo.xmlNSPrefix + "foreach", _scxml);
if (foreachs.size() > 0) {
_hasElement.insert("foreach");
@@ -1624,9 +1678,76 @@ void ChartToC::writeElementInfo(std::ostream& stream) {
stream << "};" << std::endl;
stream << std::endl;
+ stream << "#endif" << std::endl;
+ stream << std::endl;
+
}
void ChartToC::writeMachineInfo(std::ostream& stream) {
+
+ stream << "#ifndef USCXML_NO_ELEM_INFO" << std::endl;
+ stream << std::endl;
+
+#if 1
+ size_t currIndex = 0;
+ char* currIndexStr = getenv("USCXML_CURRENT_MACHINE_INDEX");
+ if (currIndexStr != NULL) {
+ currIndex = strTo<size_t>(currIndexStr);
+ }
+
+ stream << "#ifndef USCXML_MACHINE" << std::endl;
+ stream << "# define USCXML_MACHINE " << _prefix << "_machine" << std::endl;
+ stream << "#endif" << std::endl;
+
+ stream << "#define USCXML_MACHINE_" << toStr(currIndex) << " " << _prefix << "_machine" << std::endl;
+
+ if (_name.size() > 0) {
+ std::string macroName = boost::to_upper_copy(escape(_name));
+ boost::replace_all(macroName, "-", "_");
+ stream << "#define USCXML_MACHINE_" << macroName << " " << _prefix << "_machine" << std::endl;
+ }
+ stream << std::endl;
+
+ currIndex++;
+ setenv("USCXML_CURRENT_MACHINE_INDEX", toStr(currIndex).c_str(), 1);
+
+ stream << "const uscxml_machine " << _prefix << "_machine = {" << std::endl;
+ stream << " /* flags */ 0," << std::endl;
+ stream << " /* nr_states */ " << _states.size() << "," << std::endl;
+ stream << " /* nr_transitions */ " << _transitions.size() << "," << std::endl;
+ stream << " /* name */ \"" << escape(_name) << "\"," << std::endl;
+ stream << " /* datamodel */ \"" << (HAS_ATTR(_scxml, "datamodel") ? ATTR(_scxml, "datamodel") : "null") << "\"," << std::endl;
+ stream << " /* uuid */ \"" << _md5 << "\"," << std::endl;
+ stream << " /* states */ " << "&" << _prefix << "_states[0], " << std::endl;
+ stream << " /* transitions */ " << "&" << _prefix << "_transitions[0], " << std::endl;
+ stream << " /* parent */ ";
+ if (_parentMachine != NULL) {
+ size_t parentIndex = 0;
+ for (std::list<ChartToC*>::iterator parentIter = _topMostMachine->_allMachines.begin();
+ parentIter != _topMostMachine->_allMachines.end();
+ parentIter++, parentIndex++) {
+ if (*parentIter == _parentMachine) {
+ stream << "&" << (*parentIter)->_prefix << "_machine";
+ }
+ }
+ } else {
+ stream << "NULL";
+ }
+ stream << "," << std::endl;
+
+ stream << " /* donedata */ " << "&" << _prefix << "_elem_donedatas[0], " << std::endl;
+ stream << " /* script */ ";
+ if (filterChildElements(_nsInfo.xmlNSPrefix + "script", _scxml).size() > 0) {
+ stream << _prefix << "_global_script" << std::endl;
+ } else {
+ stream << "NULL";
+ }
+ stream << std::endl;
+
+ stream << "};" << std::endl;
+ stream << std::endl;
+
+#else
if (_topMostMachine != NULL)
return;
@@ -1670,9 +1791,17 @@ void ChartToC::writeMachineInfo(std::ostream& stream) {
stream << " {0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }" << std::endl;
stream << "};" << std::endl;
stream << std::endl;
+#endif
+
+ stream << "#endif" << std::endl;
+ stream << std::endl;
+
}
void ChartToC::writeStates(std::ostream& stream) {
+ stream << "#ifndef USCXML_NO_ELEM_INFO" << std::endl;
+ stream << std::endl;
+
stream << "static const uscxml_state " << _prefix << "_states[" << toStr(_states.size()) << "] = {" << std::endl;
for (size_t i = 0; i < _states.size(); i++) {
Element<std::string> state(_states[i]);
@@ -1754,11 +1883,18 @@ void ChartToC::writeStates(std::ostream& stream) {
}
stream << "};" << std::endl;
stream << std::endl;
+
+ stream << "#endif" << std::endl;
+ stream << std::endl;
+
}
void ChartToC::writeTransitions(std::ostream& stream) {
+ stream << "#ifndef USCXML_NO_ELEM_INFO" << std::endl;
+ stream << std::endl;
+
// cross reference transition by document order - is this really needed?!
std::set<std::string> elements;
elements.insert(_nsInfo.xmlNSPrefix + "transition");
@@ -1853,6 +1989,10 @@ void ChartToC::writeTransitions(std::ostream& stream) {
}
stream << "};" << std::endl;
stream << std::endl;
+
+ stream << "#endif" << std::endl;
+ stream << std::endl;
+
}
Arabica::XPath::NodeSet<std::string> ChartToC::computeExitSet(const Arabica::DOM::Element<std::string>& transition) {
@@ -1916,7 +2056,7 @@ void ChartToC::writeCharArrayInitList(std::ostream& stream, const std::string& b
}
void ChartToC::writeFSM(std::ostream& stream) {
- stream << "#ifndef USCXML_STEP_FUNCTION" << std::endl;
+ stream << "#ifndef USCXML_NO_STEP_FUNCTION" << std::endl;
stream << "int uscxml_step(uscxml_ctx* ctx) {" << std::endl;
stream << std::endl;
@@ -1981,7 +2121,7 @@ void ChartToC::writeFSM(std::ostream& stream) {
stream << " ctx->event = NULL;" << std::endl;
stream << " goto SELECT_TRANSITIONS;" << std::endl;
stream << " }" << std::endl;
- stream << " if ((ctx->event = ctx->dequeue_internal(ctx)) != NULL) {" << std::endl;
+ stream << " if (ctx->dequeue_internal != NULL && (ctx->event = ctx->dequeue_internal(ctx)) != NULL) {" << std::endl;
stream << " goto SELECT_TRANSITIONS;" << std::endl;
stream << " }" << std::endl;
stream << std::endl;
@@ -2003,10 +2143,15 @@ void ChartToC::writeFSM(std::ostream& stream) {
stream << " }" << std::endl;
stream << std::endl;
- stream << " if ((ctx->event = ctx->dequeue_external(ctx)) != NULL) {" << std::endl;
+ stream << " if (ctx->dequeue_external != NULL && (ctx->event = ctx->dequeue_external(ctx)) != NULL) {" << std::endl;
stream << " goto SELECT_TRANSITIONS;" << std::endl;
stream << " }" << std::endl;
stream << std::endl;
+ stream << " if (ctx->dequeue_external == NULL) {" << std::endl;
+ stream << " return USCXML_ERR_DONE;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " return USCXML_ERR_IDLE;" << std::endl;
+ stream << std::endl;
stream << "SELECT_TRANSITIONS:" << std::endl;
stream << " bit_clear_all(conflicts, nr_trans_bytes);" << std::endl;
@@ -2020,22 +2165,26 @@ void ChartToC::writeFSM(std::ostream& stream) {
stream << " if (BIT_HAS(USCXML_GET_TRANS(i).source, ctx->config)) {" << std::endl;
stream << " /* is it non-conflicting? */" << std::endl;
stream << " if (!BIT_HAS(i, conflicts)) {" << std::endl;
- stream << " /* is it enabled? */" << std::endl;
- stream << " if (ctx->is_enabled(ctx, &USCXML_GET_TRANS(i), ctx->event) > 0) {" << std::endl;
- stream << " /* remember that we found a transition */" << std::endl;
- stream << " ctx->flags |= USCXML_CTX_TRANSITION_FOUND;" << std::endl;
+ stream << " /* is it spontaneous with an event or vice versa? */" << std::endl;
+ stream << " if ((USCXML_GET_TRANS(i).event == NULL && ctx->event == NULL) || " << std::endl;
+ stream << " (USCXML_GET_TRANS(i).event != NULL && ctx->event != NULL)) {" << std::endl;
+ stream << " /* is it enabled? */" << std::endl;
+ stream << " if (ctx->is_enabled(ctx, &USCXML_GET_TRANS(i), ctx->event) > 0) {" << std::endl;
+ stream << " /* remember that we found a transition */" << std::endl;
+ stream << " ctx->flags |= USCXML_CTX_TRANSITION_FOUND;" << std::endl;
stream << std::endl;
- stream << " /* transitions that are pre-empted */" << std::endl;
- stream << " bit_or(conflicts, USCXML_GET_TRANS(i).conflicts, nr_trans_bytes);" << std::endl;
+ stream << " /* transitions that are pre-empted */" << std::endl;
+ stream << " bit_or(conflicts, USCXML_GET_TRANS(i).conflicts, nr_trans_bytes);" << std::endl;
stream << std::endl;
- stream << " /* states that are directly targeted (resolve as entry-set later) */" << std::endl;
- stream << " bit_or(target_set, USCXML_GET_TRANS(i).target, nr_states_bytes);" << std::endl;
+ stream << " /* states that are directly targeted (resolve as entry-set later) */" << std::endl;
+ stream << " bit_or(target_set, USCXML_GET_TRANS(i).target, nr_states_bytes);" << std::endl;
stream << std::endl;
- stream << " /* states that will be left */" << std::endl;
- stream << " bit_or(exit_set, USCXML_GET_TRANS(i).exit_set, nr_states_bytes);" << std::endl;
+ stream << " /* states that will be left */" << std::endl;
+ stream << " bit_or(exit_set, USCXML_GET_TRANS(i).exit_set, nr_states_bytes);" << std::endl;
stream << std::endl;
- stream << " BIT_SET_AT(i, trans_set);" << std::endl;
+ stream << " BIT_SET_AT(i, trans_set);" << std::endl;
+ stream << " }" << std::endl;
stream << " }" << std::endl;
stream << " }" << std::endl;
stream << " }" << std::endl;
@@ -2334,7 +2483,7 @@ void ChartToC::writeFSM(std::ostream& stream) {
stream << "}" << std::endl;
stream << std::endl;
- stream << "#define USCXML_STEP_FUNCTION" << std::endl;
+ stream << "#define USCXML_NO_STEP_FUNCTION" << std::endl;
stream << "#endif" << std::endl;
stream << std::endl;
}
diff --git a/src/uscxml/transform/ChartToC.h b/src/uscxml/transform/ChartToC.h
index 4e1d14a..bb17102 100644
--- a/src/uscxml/transform/ChartToC.h
+++ b/src/uscxml/transform/ChartToC.h
@@ -93,6 +93,8 @@ protected:
ChartToC* _parentMachine;
std::list<ChartToC*> _nestedMachines;
std::list<ChartToC*> _allMachines;
+
+ std::list<std::string>* _prefixes;
};
}
diff --git a/src/uscxml/transform/ChartToVHDL.cpp b/src/uscxml/transform/ChartToVHDL.cpp
index 8e7f43f..f37ad7e 100644
--- a/src/uscxml/transform/ChartToVHDL.cpp
+++ b/src/uscxml/transform/ChartToVHDL.cpp
@@ -125,28 +125,14 @@ void ChartToVHDL::writeTo(std::ostream& stream) {
// _eventTrie.dump();
- writeOptimalTransitionSetSelection(stream);
writeTypes(stream);
writeFiFo(stream);
- writeTransitionSet(stream);
+ writeOptimalTransitionSetSelection(stream);
writeExitSet(stream);
writeEntrySet(stream);
writeFSM(stream);
}
-void ChartToVHDL::writeTransitionSet(std::ostream & stream) {
- for (size_t i = 0; i < _transitions.size(); i++) {
- Element<std::string> transition(_transitions[i]);
- std::string name = DOMUtils::idForNode(transition);
-
- }
-}
-
-void ChartToVHDL::writeExitSet(std::ostream & stream) {
-}
-
-void ChartToVHDL::writeEntrySet(std::ostream & stream) {
-}
void ChartToVHDL::writeFSM(std::ostream & stream) {
@@ -475,14 +461,14 @@ std::string ChartToVHDL::eventNameEscape(const std::string& eventName) {
}
void ChartToVHDL::writeOptimalTransitionSetSelection(std::ostream & stream) {
- stream << "-- write optimal transition set selection" << std::endl;
+ stream << "-- optimal transition set selection" << std::endl;
for (size_t i = 0; i < _transitions.size(); i++) {
Element<std::string> transition(_transitions[i]);
std::string conflicts = ATTR(transition, "conflictBools");
stream << "in_optimal_transition_set_" << ATTR(transition, "postFixOrder") << "_sig "
<< "<= " << (HAS_ATTR(transition, "event") ? "(not spontaneous_sig)" : "spontaneous_sig") << " and " << std::endl
- << " state_active_" << ATTR(transition, "source") << "_sig and not ( 0 " << std::endl;
+ << " state_active_" << ATTR(transition, "source") << "_sig and not ( '0' " << std::endl;
for (size_t j = 0; j < i; j++) {
if (conflicts[j] == '1') {
stream << " or in_optimal_transition_set_" << toStr(j) << "_sig" << std::endl;
@@ -490,7 +476,7 @@ void ChartToVHDL::writeOptimalTransitionSetSelection(std::ostream & stream) {
}
stream << " )";
if (HAS_ATTR(transition, "event")) {
- stream << " and ( 0 " << std::endl;;
+ stream << " and ( '0' " << std::endl;;
// find all matching event literals
std::list<std::string> eventDescs = tokenizeIdRefs(ATTR(transition, "event"));
@@ -508,6 +494,96 @@ void ChartToVHDL::writeOptimalTransitionSetSelection(std::ostream & stream) {
}
+void ChartToVHDL::writeExitSet(std::ostream & stream) {
+ stream << "-- exit set selection" << std::endl;
+
+ for (size_t i = 0; i < _states.size(); i++) {
+ Element<std::string> state(_states[i]);
+ std::string completion = ATTR(state, "completionBools");
+ std::string ancestors = ATTR(state, "ancBools");
+ std::string children = ATTR(state, "childBools");
+ std::string parent = ATTR(state, "parent");
+
+ stream << "in_exit_set_" << toStr(i) << "_sig "
+ << "<= state_active_ " << toStr(i) << "_sig and ('0'" << std::endl;
+ for (size_t j = 0; j < _transitions.size(); j++) {
+ Element<std::string> transition(_transitions[j]);
+ std::string exitSet = ATTR(transition, "exitSetBools");
+ if (exitSet[i] == '1') {
+ stream << " or in_optimal_transition_set_" << toStr(j) << "_sig " << std::endl;
+ }
+ }
+
+ stream << ")";
+ stream << ";" << std::endl;
+
+ }
+}
+
+void ChartToVHDL::writeEntrySet(std::ostream & stream) {
+ stream << "-- entry set selection" << std::endl;
+
+ for (size_t i = 0; i < _states.size(); i++) {
+ Element<std::string> state(_states[i]);
+ std::string completion = ATTR(state, "completionBools");
+ std::string ancestors = ATTR(state, "ancBools");
+ std::string children = ATTR(state, "childBools");
+ std::string parent = ATTR(state, "parent");
+
+ stream << "in_complete_entry_set_up_" << toStr(i) << "_sig <= ('0'" << std::endl;
+
+ for (size_t j = 0; j < _transitions.size(); j++) {
+ Element<std::string> transition(_transitions[j]);
+// std::cout << transition;
+ std::string targetSet = ATTR(transition, "targetBools");
+ if (targetSet[i] == '1') {
+ stream << " or in_optimal_transition_set_" << toStr(j) << std::endl;
+ }
+ }
+ if (isCompound(state)) {
+ for (size_t j = 0; j < _states.size(); j++) {
+ if (children[j] != '1')
+ continue;
+
+ stream << " or in_complete_entry_set_up_" << toStr(j) << "_sig" << std::endl;
+ }
+
+ }
+ stream << ");" << std::endl;
+
+ }
+
+ for (size_t i = 0; i < _states.size(); i++) {
+ Element<std::string> state(_states[i]);
+ std::string completion = ATTR(state, "completionBools");
+ std::string ancestors = ATTR(state, "ancBools");
+ std::string children = ATTR(state, "childBools");
+ std::string parent = ATTR(state, "parent");
+
+ if (parent.size() == 0) {
+ continue; // TODO: FixMe <scxml>
+ }
+
+ stream << "in_complete_entry_set_" << toStr(i) << "_sig <= (in_complete_entry_set_up_" << toStr(i) << "_sig or (" << std::endl;
+
+ if (isParallel(Element<std::string>(_states[strTo<size_t>(parent)]))) {
+ stream << " in_complete_entry_set_" << toStr(parent) << "_sig" << std::endl;
+ } else if (isCompound(Element<std::string>(_states[strTo<size_t>(parent)]))) {
+ stream << " default_completion_" << toStr(parent) << "_sig" << std::endl;
+
+ for (size_t j = 0; j < _states.size(); j++) {
+ if (children[j] != '1')
+ continue;
+ stream << " and not (is_active" << toStr(j) << "_sig and not in_exit_set_" << toStr(j) << "_sig)" << std::endl;
+
+ }
+ }
+
+ stream << ");" << std::endl;
+
+ }
+}
+
//TODO write event generator
// wie die letzten beiden states erkennen
// process bauen der bei fail 0 ausgibt und bei accept 1
diff --git a/src/uscxml/transform/ChartToVHDL.h b/src/uscxml/transform/ChartToVHDL.h
index 64cf444..abcb477 100644
--- a/src/uscxml/transform/ChartToVHDL.h
+++ b/src/uscxml/transform/ChartToVHDL.h
@@ -51,7 +51,11 @@ protected:
void writeTopDown(std::ostream& stream);
void writeTypes(std::ostream& stream);
+
void writeOptimalTransitionSetSelection(std::ostream& stream);
+ void writeExitSet(std::ostream & stream);
+ void writeEntrySet(std::ostream & stream);
+
void writeNextStateLogic(std::ostream& stream);
void writeOutputLogic(std::ostream& stream);
void writeSignals(std::ostream& stream);
@@ -61,8 +65,6 @@ protected:
void writeFSM(std::ostream& stream);
void writeTransitionSet(std::ostream & stream);
- void writeExitSet(std::ostream & stream);
- void writeEntrySet(std::ostream & stream);
Trie _eventTrie;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index d61abf7..1c1223e 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -82,7 +82,30 @@ add_test(test-execution ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/uscxml-browser ${CMAKE
add_test(test-communication ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/uscxml-browser -t5493 ${CMAKE_SOURCE_DIR}/test/uscxml/test-communication.scxml)
add_test(test-done-data ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/uscxml-browser ${CMAKE_SOURCE_DIR}/test/uscxml/test-donedata.scxml)
-# declare W#C tests
+# tests for inline SCXML with generated C
+
+add_executable(test-c-inline src/test-c-inline.c)
+set_target_properties(test-c-inline PROPERTIES FOLDER "Tests")
+
+add_test(NAME "gen/c/inline"
+ COMMAND ${CMAKE_COMMAND}
+ -DOUTDIR:FILEPATH=${CMAKE_CURRENT_BINARY_DIR}/gen/c
+ -DTESTFILE:FILEPATH=${CMAKE_CURRENT_SOURCE_DIR}/src/test-c-inline.c
+ -DTARGETLANG=c
+ -DUSCXML_TRANSFORM_BIN:FILEPATH=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/uscxml-transform
+ -DCC_BIN:FILEPATH=${CC}
+ -DCXX_BIN:FILEPATH=${CXX}
+ -DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}
+ -DUSCXML_PLATFORM_ID=${USCXML_PLATFORM_ID}
+ -DCMAKE_BINARY_DIR=${CMAKE_BINARY_DIR}
+ -DPROJECT_BINARY_DIR=${PROJECT_BINARY_DIR}
+ -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/w3c/run_generated_inline_test.cmake)
+set_tests_properties("gen/c/inline" PROPERTIES DEPENDS uscxml-transform)
+set_property(TEST "gen/c/inline" PROPERTY LABELS "gen/c/inline")
+
+
+# declare W3C tests
find_program(SPIN spin)
find_program(CC gcc)
diff --git a/test/src/test-c-inline.c b/test/src/test-c-inline.c
new file mode 100644
index 0000000..c12ac73
--- /dev/null
+++ b/test/src/test-c-inline.c
@@ -0,0 +1,40 @@
+#include <stdlib.h> // EXIT_SUCCESS
+#include <stdio.h> // printf
+#include <string.h> // memset
+
+/**
+ * Preprocess:
+ * uscxml-transform -tc -i ./test-c-inline.c -o ./test-c-inline.c.scxml.c
+ */
+
+/** INLINE SCXML BEGIN
+<scxml name="test-inline" datamodel="native">
+ <state id="foo">
+ <onentry>
+ enteredFoo();
+ </onentry>
+ </state>
+</scxml>
+INLINE SCXML END */
+
+/**
+ * These function can be called from within executable content
+ */
+void enteredFoo() {
+ printf("Entered Foo!\n");
+}
+
+#include "test-c-inline.c.scxml.c"
+
+int main(int argc, char** argv) {
+ uscxml_ctx ctx;
+ memset(&ctx, 0, sizeof(uscxml_ctx));
+ ctx.machine = &USCXML_MACHINE_TEST_INLINE;
+
+ int err = USCXML_ERR_OK;
+ while(err != USCXML_ERR_DONE) {
+ err = uscxml_step(&ctx);
+ }
+
+ return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/test/src/test-c-inline.c.scxml.c b/test/src/test-c-inline.c.scxml.c
new file mode 100644
index 0000000..d586bb3
--- /dev/null
+++ b/test/src/test-c-inline.c.scxml.c
@@ -0,0 +1,951 @@
+/**
+ Generated from source:
+ file:///Users/sradomski/Documents/TK/Code/uscxml/test/src/test-c-inline.c
+*/
+
+#ifndef USCXML_NO_STDTYPES_H
+# include <stdint.h> /* explicit types */
+#endif
+#include <stddef.h> /* NULL */
+
+#ifndef USCXML_NO_GEN_C_MACROS
+
+/**
+ * All macros used for the scxml types and functions
+ *
+ * ** IMPORTANT: Make sure to set the following macros prior to including. **
+ * They are used to represent the machine in the types to follow
+ * and to allocate stack memory during a micro-step function.
+ * When in doubt, overprovide.
+ *
+ * USCXML_NR_STATES_TYPE
+ * as the smallest type for positive integers that can contain the
+ * largest number of states from an individual state machine. E.g.:
+ * < 2^8 states => uint8_t
+ * < 2^16 states => uint16_t
+ * < 2^32 states => uint32_t
+ */
+
+#ifndef USCXML_NR_STATES_TYPE
+# define USCXML_NR_STATES_TYPE uint8_t
+#endif
+
+/**
+ * USCXML_NR_TRANS_TYPE
+ * the same as above but for the number of transitions.
+ */
+
+#ifndef USCXML_NR_TRANS_TYPE
+# define USCXML_NR_TRANS_TYPE uint8_t
+#endif
+
+/**
+ * USCXML_MAX_NR_STATES_BYTES
+ * the smallest multiple of 8 that, if multiplied by 8,
+ * is larger than USCXML_NR_STATES_TYPE, e.g:
+ * 1-8 states => 1
+ * 9-16 states => 2
+ * 17-24 states => 3
+ * 25-32 states => 4
+ * ...
+ */
+
+#ifndef USCXML_MAX_NR_STATES_BYTES
+# define USCXML_MAX_NR_STATES_BYTES 1
+#endif
+
+/**
+ * USCXML_MAX_NR_TRANS_BYTES
+ * same as above but for transitions.
+ */
+
+#ifndef USCXML_MAX_NR_TRANS_BYTES
+# define USCXML_MAX_NR_TRANS_BYTES 0
+#endif
+
+/**
+ * USCXML_NUMBER_STATES / USCXML_NUMBER_TRANS
+ * Per default the number of states / transitions is retrieved from the machine
+ * info in the uscxml_ctx struct, but you can also hard-code it per macro.
+ */
+
+#ifndef USCXML_NUMBER_STATES
+# define USCXML_NUMBER_STATES (ctx->machine->nr_states)
+#endif
+
+#ifndef USCXML_NUMBER_TRANS
+# define USCXML_NUMBER_TRANS (ctx->machine->nr_transitions)
+#endif
+
+/**
+ * USCXML_GET_STATE / USCXML_GET_TRANS
+ * Per default an individual state or transitions is retrieved from the machine
+ * info in the uscxml_ctx struct, but you can also hard-code it per macro.
+ */
+
+#ifndef USCXML_GET_STATE
+# define USCXML_GET_STATE(i) (ctx->machine->states[i])
+#endif
+
+#ifndef USCXML_GET_TRANS
+# define USCXML_GET_TRANS(i) (ctx->machine->transitions[i])
+#endif
+
+
+/* Common macros below */
+
+#define BIT_HAS(idx, bitset) ((bitset[idx >> 3] & (1 << (idx & 7))) != 0)
+#define BIT_SET_AT(idx, bitset) bitset[idx >> 3] |= (1 << (idx & 7));
+#define BIT_CLEAR(idx, bitset) bitset[idx >> 3] &= (1 << (idx & 7)) ^ 0xFF;
+
+#ifdef __GNUC__
+# define likely(x) (__builtin_expect(!!(x), 1))
+# define unlikely(x) (__builtin_expect(!!(x), 0))
+#else
+# define likely(x) (x)
+# define unlikely(x) (x)
+#endif
+
+/* error return codes */
+#define USCXML_ERR_OK 0
+#define USCXML_ERR_IDLE 1
+#define USCXML_ERR_DONE 2
+#define USCXML_ERR_MISSING_CALLBACK 3
+#define USCXML_ERR_FOREACH_DONE 4
+#define USCXML_ERR_EXEC_CONTENT 5
+#define USCXML_ERR_INVALID_TARGET 6
+#define USCXML_ERR_INVALID_TYPE 7
+#define USCXML_ERR_UNSUPPORTED 8
+
+#define USCXML_TRANS_SPONTANEOUS 0x01
+#define USCXML_TRANS_TARGETLESS 0x02
+#define USCXML_TRANS_INTERNAL 0x04
+#define USCXML_TRANS_HISTORY 0x08
+#define USCXML_TRANS_INITIAL 0x10
+
+#define USCXML_STATE_ATOMIC 0x01
+#define USCXML_STATE_PARALLEL 0x02
+#define USCXML_STATE_COMPOUND 0x03
+#define USCXML_STATE_FINAL 0x04
+#define USCXML_STATE_HISTORY_DEEP 0x05
+#define USCXML_STATE_HISTORY_SHALLOW 0x06
+#define USCXML_STATE_INITIAL 0x07
+#define USCXML_STATE_HAS_HISTORY 0x80 /* highest bit */
+#define USCXML_STATE_MASK(t) (t & 0x7F) /* mask highest bit */
+
+#define USCXML_CTX_PRISTINE 0x00
+#define USCXML_CTX_SPONTANEOUS 0x01
+#define USCXML_CTX_INITIALIZED 0x02
+#define USCXML_CTX_TOP_LEVEL_FINAL 0x04
+#define USCXML_CTX_TRANSITION_FOUND 0x08
+#define USCXML_CTX_FINISHED 0x10
+
+#define USCXML_ELEM_DATA_IS_SET(data) (data->id != NULL)
+#define USCXML_ELEM_DONEDATA_IS_SET(donedata) (donedata->content != NULL || donedata->contentexpr != NULL || donedata->params != NULL)
+#define USCXML_ELEM_PARAM_IS_SET(param) (param->name != NULL)
+#define USCXML_MACHINE_IS_SET(machine) (machine->nr_states > 0)
+
+#define USCXML_NO_GEN_C_MACROS
+#endif
+
+
+#ifndef USCXML_NO_GEN_C_TYPES
+
+/**
+ * All types required to represent an SCXML state chart.
+ * Just predefine the USCXML_NO_GEN_C_TYPES macro if you do not need them.
+ */
+
+typedef struct uscxml_machine uscxml_machine;
+typedef struct uscxml_transition uscxml_transition;
+typedef struct uscxml_state uscxml_state;
+typedef struct uscxml_ctx uscxml_ctx;
+typedef struct uscxml_elem_invoke uscxml_elem_invoke;
+
+typedef struct uscxml_elem_send uscxml_elem_send;
+typedef struct uscxml_elem_param uscxml_elem_param;
+typedef struct uscxml_elem_data uscxml_elem_data;
+typedef struct uscxml_elem_donedata uscxml_elem_donedata;
+typedef struct uscxml_elem_foreach uscxml_elem_foreach;
+
+typedef void* (*dequeue_internal_t)(const uscxml_ctx* ctx);
+typedef void* (*dequeue_external_t)(const uscxml_ctx* ctx);
+typedef int (*is_enabled_t)(const uscxml_ctx* ctx, const uscxml_transition* transition, const void* event);
+typedef int (*is_true_t)(const uscxml_ctx* ctx, const char* expr);
+typedef int (*exec_content_t)(const uscxml_ctx* ctx, const uscxml_state* state, const void* event);
+typedef int (*raise_done_event_t)(const uscxml_ctx* ctx, const uscxml_state* state, const uscxml_elem_donedata* donedata);
+typedef int (*invoke_t)(const uscxml_ctx* ctx, const uscxml_state* s, const uscxml_elem_invoke* invocation, unsigned char uninvoke);
+
+typedef int (*exec_content_log_t)(const uscxml_ctx* ctx, const char* label, const char* expr);
+typedef int (*exec_content_raise_t)(const uscxml_ctx* ctx, const char* event);
+typedef int (*exec_content_send_t)(const uscxml_ctx* ctx, const uscxml_elem_send* send);
+typedef int (*exec_content_foreach_init_t)(const uscxml_ctx* ctx, const uscxml_elem_foreach* foreach);
+typedef int (*exec_content_foreach_next_t)(const uscxml_ctx* ctx, const uscxml_elem_foreach* foreach);
+typedef int (*exec_content_foreach_done_t)(const uscxml_ctx* ctx, const uscxml_elem_foreach* foreach);
+typedef int (*exec_content_assign_t)(const uscxml_ctx* ctx, const char* location, const char* expr);
+typedef int (*exec_content_init_t)(const uscxml_ctx* ctx, const uscxml_elem_data* data);
+typedef int (*exec_content_cancel_t)(const uscxml_ctx* ctx, const char* sendid, const char* sendidexpr);
+typedef int (*exec_content_finalize_t)(const uscxml_ctx* ctx, const uscxml_elem_invoke* invoker, const void* event);
+typedef int (*exec_content_script_t)(const uscxml_ctx* ctx, const char* src, const char* content);
+
+/**
+ * A single SCXML state-machine.
+ */
+struct uscxml_machine {
+ unsigned char flags; /* Unused */
+ USCXML_NR_STATES_TYPE nr_states; /* Make sure to set type per macro! */
+ USCXML_NR_TRANS_TYPE nr_transitions; /* Make sure to set type per macro! */
+ const char* name;
+ const char* datamodel;
+ const char* uuid; /* currently MD5 sum */
+ const uscxml_state* states;
+ const uscxml_transition* transitions;
+ const uscxml_machine* parent;
+ const uscxml_elem_donedata* donedata;
+ const exec_content_t script; /* Global script elements */
+};
+
+/**
+ * All information pertaining to a <data> element.
+ * With late data binding, blocks of data elements are separated by NULL
+ * use USCXML_ELEM_DATA_IS_SET to test for end of a block.
+ */
+struct uscxml_elem_data {
+ const char* id;
+ const char* src;
+ const char* expr;
+ const char* content;
+};
+
+/**
+ * All information pertaining to any state element.
+ */
+struct uscxml_state {
+ const char* name; /* eventual name */
+ const USCXML_NR_STATES_TYPE parent; /* parent */
+ const exec_content_t on_entry; /* on entry handlers */
+ const exec_content_t on_exit; /* on exit handlers */
+ const invoke_t invoke; /* invocations */
+ const char children[USCXML_MAX_NR_STATES_BYTES]; /* all children */
+ const char completion[USCXML_MAX_NR_STATES_BYTES]; /* default completion */
+ const char ancestors[USCXML_MAX_NR_STATES_BYTES]; /* all ancestors */
+ const uscxml_elem_data* data; /* data with late binding */
+ const unsigned char type; /* One of USCXML_STATE_* */
+};
+
+/**
+ * All information pertaining to a <transitions> element.
+ */
+struct uscxml_transition {
+ const USCXML_NR_STATES_TYPE source;
+ const char target[USCXML_MAX_NR_STATES_BYTES];
+ const char* event;
+ const char* condition;
+ const exec_content_t on_transition;
+ const unsigned char type;
+ const char conflicts[USCXML_MAX_NR_TRANS_BYTES];
+ const char exit_set[USCXML_MAX_NR_STATES_BYTES];
+};
+
+/**
+ * All information pertaining to a <foreach> element.
+ */
+struct uscxml_elem_foreach {
+ const char* array;
+ const char* item;
+ const char* index;
+};
+
+/**
+ * All information pertaining to a <param> element.
+ * Blocks of params are separated by NULL params, use
+ * USCXML_ELEM_PARAM_IS_SET to test for end of a block.
+ */
+struct uscxml_elem_param {
+ const char* name;
+ const char* expr;
+ const char* location;
+};
+
+/**
+ * All information pertaining to a <donedata> element.
+ */
+struct uscxml_elem_donedata {
+ const USCXML_NR_STATES_TYPE source;
+ const char* content;
+ const char* contentexpr;
+ const uscxml_elem_param* params;
+};
+
+/**
+ * All information pertaining to an <invoke> element.
+ */
+struct uscxml_elem_invoke {
+ const uscxml_machine* machine;
+ const char* type;
+ const char* typeexpr;
+ const char* src;
+ const char* srcexpr;
+ const char* id;
+ const char* idlocation;
+ const char* sourcename;
+ const char* namelist;
+ const unsigned char autoforward;
+ const uscxml_elem_param* params;
+ exec_content_finalize_t finalize;
+ const char* content;
+ const char* contentexpr;
+};
+
+/**
+ * All information pertaining to a <send> element.
+ */
+struct uscxml_elem_send {
+ const char* event;
+ const char* eventexpr;
+ const char* target;
+ const char* targetexpr;
+ const char* type;
+ const char* typeexpr;
+ const char* id;
+ const char* idlocation;
+ const char* delay;
+ const char* delayexpr;
+ const char* namelist; /* not space-separated, still as in attribute value */
+ const char* content;
+ const char* contentexpr;
+ const uscxml_elem_param* params;
+};
+
+/**
+ * Represents an instance of a state-chart at runtime/
+ */
+struct uscxml_ctx {
+ unsigned char flags;
+ const uscxml_machine* machine;
+
+ char config[USCXML_MAX_NR_STATES_BYTES]; /* Make sure these macros specify a sufficient size */
+ char history[USCXML_MAX_NR_STATES_BYTES];
+ char invocations[USCXML_MAX_NR_STATES_BYTES];
+ char initialized_data[USCXML_MAX_NR_STATES_BYTES];
+
+ void* user_data;
+ void* event;
+
+ dequeue_internal_t dequeue_internal;
+ dequeue_external_t dequeue_external;
+ is_enabled_t is_enabled;
+ is_true_t is_true;
+ raise_done_event_t raise_done_event;
+
+ exec_content_log_t exec_content_log;
+ exec_content_raise_t exec_content_raise;
+ exec_content_send_t exec_content_send;
+ exec_content_foreach_init_t exec_content_foreach_init;
+ exec_content_foreach_next_t exec_content_foreach_next;
+ exec_content_foreach_done_t exec_content_foreach_done;
+ exec_content_assign_t exec_content_assign;
+ exec_content_init_t exec_content_init;
+ exec_content_cancel_t exec_content_cancel;
+ exec_content_script_t exec_content_script;
+
+ invoke_t invoke;
+};
+
+#define USCXML_NO_GEN_C_TYPES
+#endif
+
+/* forward declare machines to allow references */
+extern const uscxml_machine _uscxml_9FAC9BE9_machine;
+
+#ifndef USCXML_NO_ELEM_INFO
+
+static const uscxml_elem_donedata _uscxml_9FAC9BE9_elem_donedatas[1] = {
+ /* source, content, contentexpr, params */
+ { 0, NULL, NULL, NULL }
+};
+
+#endif
+
+#ifndef USCXML_NO_ELEM_INFO
+
+#endif
+
+#ifndef USCXML_NO_EXEC_CONTENT
+
+static int _uscxml_9FAC9BE9_foo_on_entry_0(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) {
+ int err = USCXML_ERR_OK;
+
+ enteredFoo();
+ return USCXML_ERR_OK;
+}
+
+static int _uscxml_9FAC9BE9_foo_on_entry(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) {
+ _uscxml_9FAC9BE9_foo_on_entry_0(ctx, state, event);
+ return USCXML_ERR_OK;
+}
+
+#endif
+
+#ifndef USCXML_NO_ELEM_INFO
+
+static const uscxml_state _uscxml_9FAC9BE9_states[2] = {
+ { /* state number 0 */
+ /* name */ NULL,
+ /* parent */ 0,
+ /* onentry */ NULL,
+ /* onexit */ NULL,
+ /* invoke */ NULL,
+ /* children */ { 0x02 /* 01 */ },
+ /* completion */ { 0x02 /* 01 */ },
+ /* ancestors */ { 0x00 /* 00 */ },
+ /* data */ NULL,
+ /* type */ USCXML_STATE_COMPOUND,
+ },
+ { /* state number 1 */
+ /* name */ "foo",
+ /* parent */ 0,
+ /* onentry */ _uscxml_9FAC9BE9_foo_on_entry,
+ /* onexit */ NULL,
+ /* invoke */ NULL,
+ /* children */ { 0x00 /* 00 */ },
+ /* completion */ { 0x00 /* 00 */ },
+ /* ancestors */ { 0x01 /* 10 */ },
+ /* data */ NULL,
+ /* type */ USCXML_STATE_ATOMIC,
+ }
+};
+
+#endif
+
+#ifndef USCXML_NO_ELEM_INFO
+
+static const uscxml_transition _uscxml_9FAC9BE9_transitions[0] = {
+};
+
+#endif
+
+#ifndef USCXML_NO_ELEM_INFO
+
+#ifndef USCXML_MACHINE
+# define USCXML_MACHINE _uscxml_9FAC9BE9_machine
+#endif
+#define USCXML_MACHINE_0 _uscxml_9FAC9BE9_machine
+#define USCXML_MACHINE_TEST_INLINE _uscxml_9FAC9BE9_machine
+
+const uscxml_machine _uscxml_9FAC9BE9_machine = {
+ /* flags */ 0,
+ /* nr_states */ 2,
+ /* nr_transitions */ 0,
+ /* name */ "test-inline",
+ /* datamodel */ "native",
+ /* uuid */ "9FAC9BE9A82F66AFD36A205557064B27",
+ /* states */ &_uscxml_9FAC9BE9_states[0],
+ /* transitions */ &_uscxml_9FAC9BE9_transitions[0],
+ /* parent */ NULL,
+ /* donedata */ &_uscxml_9FAC9BE9_elem_donedatas[0],
+ /* script */ NULL
+};
+
+#endif
+
+#ifdef USCXML_VERBOSE
+/**
+ * Print name of states contained in a (debugging).
+ */
+static void printStateNames(const uscxml_ctx* ctx, const char* a, size_t length) {
+ size_t i;
+ const char* seperator = "";
+ for (i = 0; i < length; i++) {
+ if (BIT_HAS(i, a)) {
+ printf("%s%s", seperator, (USCXML_GET_STATE(i).name != NULL ? USCXML_GET_STATE(i).name : "UNK"));
+ seperator = ", ";
+ }
+ }
+ printf("\n");
+}
+
+/**
+ * Print bits set in a in a binary representation (debugging).
+ */
+static void printBitsetIndices(const char* a, size_t length) {
+ size_t i;
+ const char* seperator = "";
+ for (i = 0; i < length; i++) {
+ if (BIT_HAS(i, a)) {
+ printf("%s%lu", seperator, i);
+ seperator = ", ";
+ }
+ }
+ printf("\n");
+}
+#endif
+
+#ifndef USCXML_NO_BIT_OPERATIONS
+/**
+ * Return true if there is a common bit in a and b.
+ */
+static int bit_has_and(const char* a, const char* b, size_t i) {
+ while(i--) {
+ if (a[i] & b[i])
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * Set all bits to 0, this corresponds to memset(a, 0, i),
+ * but does not require string.h or cstring.
+ */
+static void bit_clear_all(char* a, size_t i) {
+ while(i--) {
+ a[i] = 0;
+ }
+}
+
+/**
+ * Return true if there is any bit set in a.
+ */
+static int bit_has_any(const char* a, size_t i) {
+ while(i--) {
+ if (a[i] > 0)
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * Set all bits from given mask in dest, this is |= for bit arrays.
+ */
+static void bit_or(char* dest, const char* mask, size_t i) {
+ while(i--) {
+ dest[i] |= mask[i];
+ }
+}
+
+/**
+ * Copy all bits from source to dest, this corresponds to memcpy(a, b, i),
+ * but does not require string.h or cstring.
+ */
+static void bit_copy(char* dest, const char* source, size_t i) {
+ while(i--) {
+ dest[i] = source[i];
+ }
+}
+
+/**
+ * Unset bits from mask in dest.
+ */
+static void bit_and_not(char* dest, const char* mask, size_t i) {
+ while(i--) {
+ dest[i] &= ~mask[i];
+ }
+}
+
+/**
+ * Set bits from mask in dest.
+ */
+static void bit_and(char* dest, const char* mask, size_t i) {
+ while(i--) {
+ dest[i] &= mask[i];
+ };
+}
+
+#define USCXML_NO_BIT_OPERATIONS
+#endif
+
+#ifndef USCXML_NO_STEP_FUNCTION
+int uscxml_step(uscxml_ctx* ctx) {
+
+ USCXML_NR_STATES_TYPE i, j, k;
+ USCXML_NR_STATES_TYPE nr_states_bytes = ((USCXML_NUMBER_STATES + 7) & ~7) >> 3;
+ USCXML_NR_TRANS_TYPE nr_trans_bytes = ((USCXML_NUMBER_TRANS + 7) & ~7) >> 3;
+ int err = USCXML_ERR_OK;
+ char conflicts [USCXML_MAX_NR_TRANS_BYTES];
+ char trans_set [USCXML_MAX_NR_TRANS_BYTES];
+ char target_set [USCXML_MAX_NR_STATES_BYTES];
+ char exit_set [USCXML_MAX_NR_STATES_BYTES];
+ char entry_set [USCXML_MAX_NR_STATES_BYTES];
+ char tmp_states [USCXML_MAX_NR_STATES_BYTES];
+
+#ifdef USCXML_VERBOSE
+ printf("Config: ");
+ printStateNames(ctx, ctx->config, USCXML_NUMBER_STATES);
+#endif
+
+ if (ctx->flags & USCXML_CTX_FINISHED)
+ return USCXML_ERR_DONE;
+
+ if (ctx->flags & USCXML_CTX_TOP_LEVEL_FINAL) {
+ /* exit all remaining states */
+ i = USCXML_NUMBER_STATES;
+ while(i-- > 0) {
+ if (BIT_HAS(i, ctx->config)) {
+ /* call all on exit handlers */
+ if (USCXML_GET_STATE(i).on_exit != NULL) {
+ if unlikely((err = USCXML_GET_STATE(i).on_exit(ctx, &USCXML_GET_STATE(i), ctx->event)) != USCXML_ERR_OK)
+ return err;
+ }
+ }
+ if (BIT_HAS(i, ctx->invocations)) {
+ if (USCXML_GET_STATE(i).invoke != NULL)
+ USCXML_GET_STATE(i).invoke(ctx, &USCXML_GET_STATE(i), NULL, 1);
+ BIT_CLEAR(i, ctx->invocations);
+ }
+ }
+ ctx->flags |= USCXML_CTX_FINISHED;
+ return USCXML_ERR_DONE;
+ }
+
+ bit_clear_all(target_set, nr_states_bytes);
+ bit_clear_all(trans_set, nr_trans_bytes);
+ if unlikely(ctx->flags == USCXML_CTX_PRISTINE) {
+ if (ctx->machine->script != NULL)
+ ctx->machine->script(ctx, &ctx->machine->states[0], NULL);
+ bit_or(target_set, ctx->machine->states[0].completion, nr_states_bytes);
+ ctx->flags |= USCXML_CTX_SPONTANEOUS | USCXML_CTX_INITIALIZED;
+ goto ESTABLISH_ENTRY_SET;
+ }
+
+ if (ctx->flags & USCXML_CTX_SPONTANEOUS) {
+ ctx->event = NULL;
+ goto SELECT_TRANSITIONS;
+ }
+ if (ctx->dequeue_internal != NULL && (ctx->event = ctx->dequeue_internal(ctx)) != NULL) {
+ goto SELECT_TRANSITIONS;
+ }
+
+ /* manage invocations */
+ for (i = 0; i < USCXML_NUMBER_STATES; i++) {
+ /* uninvoke */
+ if (!BIT_HAS(i, ctx->config) && BIT_HAS(i, ctx->invocations)) {
+ if (USCXML_GET_STATE(i).invoke != NULL)
+ USCXML_GET_STATE(i).invoke(ctx, &USCXML_GET_STATE(i), NULL, 1);
+ BIT_CLEAR(i, ctx->invocations)
+ }
+ /* invoke */
+ if (BIT_HAS(i, ctx->config) && !BIT_HAS(i, ctx->invocations)) {
+ if (USCXML_GET_STATE(i).invoke != NULL)
+ USCXML_GET_STATE(i).invoke(ctx, &USCXML_GET_STATE(i), NULL, 0);
+ BIT_SET_AT(i, ctx->invocations)
+ }
+ }
+
+ if (ctx->dequeue_external != NULL && (ctx->event = ctx->dequeue_external(ctx)) != NULL) {
+ goto SELECT_TRANSITIONS;
+ }
+
+ if (ctx->dequeue_external == NULL) {
+ return USCXML_ERR_DONE;
+ }
+ return USCXML_ERR_IDLE;
+
+SELECT_TRANSITIONS:
+ bit_clear_all(conflicts, nr_trans_bytes);
+ bit_clear_all(exit_set, nr_states_bytes);
+ for (i = 0; i < USCXML_NUMBER_TRANS; i++) {
+ /* never select history or initial transitions automatically */
+ if unlikely(USCXML_GET_TRANS(i).type & (USCXML_TRANS_HISTORY | USCXML_TRANS_INITIAL))
+ continue;
+
+ /* is the transition active? */
+ if (BIT_HAS(USCXML_GET_TRANS(i).source, ctx->config)) {
+ /* is it non-conflicting? */
+ if (!BIT_HAS(i, conflicts)) {
+ /* is it spontaneous with an event or vice versa? */
+ if ((USCXML_GET_TRANS(i).event == NULL && ctx->event == NULL) ||
+ (USCXML_GET_TRANS(i).event != NULL && ctx->event != NULL)) {
+ /* is it enabled? */
+ if (ctx->is_enabled(ctx, &USCXML_GET_TRANS(i), ctx->event) > 0) {
+ /* remember that we found a transition */
+ ctx->flags |= USCXML_CTX_TRANSITION_FOUND;
+
+ /* transitions that are pre-empted */
+ bit_or(conflicts, USCXML_GET_TRANS(i).conflicts, nr_trans_bytes);
+
+ /* states that are directly targeted (resolve as entry-set later) */
+ bit_or(target_set, USCXML_GET_TRANS(i).target, nr_states_bytes);
+
+ /* states that will be left */
+ bit_or(exit_set, USCXML_GET_TRANS(i).exit_set, nr_states_bytes);
+
+ BIT_SET_AT(i, trans_set);
+ }
+ }
+ }
+ }
+ }
+ bit_and(exit_set, ctx->config, nr_states_bytes);
+
+ if (ctx->flags & USCXML_CTX_TRANSITION_FOUND) {
+ ctx->flags |= USCXML_CTX_SPONTANEOUS;
+ ctx->flags &= ~USCXML_CTX_TRANSITION_FOUND;
+ } else {
+ ctx->flags &= ~USCXML_CTX_SPONTANEOUS;
+ }
+
+#ifdef USCXML_VERBOSE
+ printf("Targets: ");
+ printStateNames(ctx, target_set, USCXML_NUMBER_STATES);
+#endif
+
+#ifdef USCXML_VERBOSE
+ printf("Exiting: ");
+ printStateNames(ctx, exit_set, USCXML_NUMBER_STATES);
+#endif
+
+#ifdef USCXML_VERBOSE
+ printf("History: ");
+ printStateNames(ctx, ctx->history, USCXML_NUMBER_STATES);
+#endif
+
+/* REMEMBER_HISTORY: */
+ for (i = 0; i < USCXML_NUMBER_STATES; i++) {
+ if unlikely(USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_HISTORY_SHALLOW ||
+ USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_HISTORY_DEEP) {
+ /* a history state whose parent is about to be exited */
+ if unlikely(BIT_HAS(USCXML_GET_STATE(i).parent, exit_set)) {
+ bit_copy(tmp_states, USCXML_GET_STATE(i).completion, nr_states_bytes);
+
+ /* set those states who were enabled */
+ bit_and(tmp_states, ctx->config, nr_states_bytes);
+
+ /* clear current history with completion mask */
+ bit_and_not(ctx->history, USCXML_GET_STATE(i).completion, nr_states_bytes);
+
+ /* set history */
+ bit_or(ctx->history, tmp_states, nr_states_bytes);
+ }
+ }
+ }
+
+ESTABLISH_ENTRY_SET:
+ /* calculate new entry set */
+ bit_copy(entry_set, target_set, nr_states_bytes);
+
+ /* iterate for ancestors */
+ for (i = 0; i < USCXML_NUMBER_STATES; i++) {
+ if (BIT_HAS(i, entry_set)) {
+ bit_or(entry_set, USCXML_GET_STATE(i).ancestors, nr_states_bytes);
+ }
+ }
+
+ /* iterate for descendants */
+ for (i = 0; i < USCXML_NUMBER_STATES; i++) {
+ if (BIT_HAS(i, entry_set)) {
+ switch (USCXML_STATE_MASK(USCXML_GET_STATE(i).type)) {
+ case USCXML_STATE_PARALLEL: {
+ bit_or(entry_set, USCXML_GET_STATE(i).completion, nr_states_bytes);
+ break;
+ }
+ case USCXML_STATE_HISTORY_SHALLOW:
+ case USCXML_STATE_HISTORY_DEEP: {
+ if (!bit_has_and(USCXML_GET_STATE(i).completion, ctx->history, nr_states_bytes) &&
+ !BIT_HAS(USCXML_GET_STATE(i).parent, ctx->config)) {
+ /* nothing set for history, look for a default transition */
+ for (j = 0; j < USCXML_NUMBER_TRANS; j++) {
+ if unlikely(ctx->machine->transitions[j].source == i) {
+ bit_or(entry_set, ctx->machine->transitions[j].target, nr_states_bytes);
+ if(USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_HISTORY_DEEP &&
+ !bit_has_and(ctx->machine->transitions[j].target, USCXML_GET_STATE(i).children, nr_states_bytes)) {
+ for (k = i + 1; k < USCXML_NUMBER_STATES; k++) {
+ if (BIT_HAS(k, ctx->machine->transitions[j].target)) {
+ bit_or(entry_set, ctx->machine->states[k].ancestors, nr_states_bytes);
+ break;
+ }
+ }
+ }
+ BIT_SET_AT(j, trans_set);
+ break;
+ }
+ /* Note: SCXML mandates every history to have a transition! */
+ }
+ } else {
+ bit_copy(tmp_states, USCXML_GET_STATE(i).completion, nr_states_bytes);
+ bit_and(tmp_states, ctx->history, nr_states_bytes);
+ bit_or(entry_set, tmp_states, nr_states_bytes);
+ if (USCXML_GET_STATE(i).type == (USCXML_STATE_HAS_HISTORY | USCXML_STATE_HISTORY_DEEP)) {
+ /* a deep history state with nested histories -> more completion */
+ for (j = i + 1; j < USCXML_NUMBER_STATES; j++) {
+ if (BIT_HAS(j, USCXML_GET_STATE(i).completion) &&
+ BIT_HAS(j, entry_set) &&
+ (ctx->machine->states[j].type & USCXML_STATE_HAS_HISTORY)) {
+ for (k = j + 1; k < USCXML_NUMBER_STATES; k++) {
+ /* add nested history to entry_set */
+ if ((USCXML_STATE_MASK(ctx->machine->states[k].type) == USCXML_STATE_HISTORY_DEEP ||
+ USCXML_STATE_MASK(ctx->machine->states[k].type) == USCXML_STATE_HISTORY_SHALLOW) &&
+ BIT_HAS(k, ctx->machine->states[j].children)) {
+ /* a nested history state */
+ BIT_SET_AT(k, entry_set);
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+ case USCXML_STATE_INITIAL: {
+ for (j = 0; j < USCXML_NUMBER_TRANS; j++) {
+ if (ctx->machine->transitions[j].source == i) {
+ BIT_SET_AT(j, trans_set);
+ BIT_CLEAR(i, entry_set);
+ bit_or(entry_set, ctx->machine->transitions[j].target, nr_states_bytes);
+ for (k = i + 1; k < USCXML_NUMBER_STATES; k++) {
+ if (BIT_HAS(k, ctx->machine->transitions[j].target)) {
+ bit_or(entry_set, ctx->machine->states[k].ancestors, nr_states_bytes);
+ }
+ }
+ }
+ }
+ break;
+ }
+ case USCXML_STATE_COMPOUND: { /* we need to check whether one child is already in entry_set */
+ if (!bit_has_and(entry_set, USCXML_GET_STATE(i).children, nr_states_bytes) &&
+ (!bit_has_and(ctx->config, USCXML_GET_STATE(i).children, nr_states_bytes) ||
+ bit_has_and(exit_set, USCXML_GET_STATE(i).children, nr_states_bytes)))
+ {
+ bit_or(entry_set, USCXML_GET_STATE(i).completion, nr_states_bytes);
+ if (!bit_has_and(USCXML_GET_STATE(i).completion, USCXML_GET_STATE(i).children, nr_states_bytes)) {
+ /* deep completion */
+ for (j = i + 1; j < USCXML_NUMBER_STATES; j++) {
+ if (BIT_HAS(j, USCXML_GET_STATE(i).completion)) {
+ bit_or(entry_set, ctx->machine->states[j].ancestors, nr_states_bytes);
+ break; /* completion of compound is single state */
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+#ifdef USCXML_VERBOSE
+ printf("Transitions: ");
+ printBitsetIndices(trans_set, sizeof(char) * 8 * nr_trans_bytes);
+#endif
+
+/* EXIT_STATES: */
+ i = USCXML_NUMBER_STATES;
+ while(i-- > 0) {
+ if (BIT_HAS(i, exit_set) && BIT_HAS(i, ctx->config)) {
+ /* call all on exit handlers */
+ if (USCXML_GET_STATE(i).on_exit != NULL) {
+ if unlikely((err = USCXML_GET_STATE(i).on_exit(ctx, &USCXML_GET_STATE(i), ctx->event)) != USCXML_ERR_OK)
+ return err;
+ }
+ BIT_CLEAR(i, ctx->config);
+ }
+ }
+
+/* TAKE_TRANSITIONS: */
+ for (i = 0; i < USCXML_NUMBER_TRANS; i++) {
+ if (BIT_HAS(i, trans_set) && (USCXML_GET_TRANS(i).type & (USCXML_TRANS_HISTORY | USCXML_TRANS_INITIAL)) == 0) {
+ /* call executable content in transition */
+ if (USCXML_GET_TRANS(i).on_transition != NULL) {
+ if unlikely((err = USCXML_GET_TRANS(i).on_transition(ctx,
+ &ctx->machine->states[USCXML_GET_TRANS(i).source],
+ ctx->event)) != USCXML_ERR_OK)
+ return err;
+ }
+ }
+ }
+
+#ifdef USCXML_VERBOSE
+ printf("Entering: ");
+ printStateNames(ctx, entry_set, USCXML_NUMBER_STATES);
+#endif
+
+/* ENTER_STATES: */
+ for (i = 0; i < USCXML_NUMBER_STATES; i++) {
+ if (BIT_HAS(i, entry_set) && !BIT_HAS(i, ctx->config)) {
+ /* these are no proper states */
+ if unlikely(USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_HISTORY_DEEP ||
+ USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_HISTORY_SHALLOW ||
+ USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_INITIAL)
+ continue;
+
+ BIT_SET_AT(i, ctx->config);
+
+ /* initialize data */
+ if (!BIT_HAS(i, ctx->initialized_data)) {
+ if unlikely(USCXML_GET_STATE(i).data != NULL && ctx->exec_content_init != NULL) {
+ ctx->exec_content_init(ctx, USCXML_GET_STATE(i).data);
+ }
+ BIT_SET_AT(i, ctx->initialized_data);
+ }
+
+ if (USCXML_GET_STATE(i).on_entry != NULL) {
+ if unlikely((err = USCXML_GET_STATE(i).on_entry(ctx, &USCXML_GET_STATE(i), ctx->event)) != USCXML_ERR_OK)
+ return err;
+ }
+
+ /* take history and initial transitions */
+ for (j = 0; j < USCXML_NUMBER_TRANS; j++) {
+ if unlikely(BIT_HAS(j, trans_set) &&
+ (ctx->machine->transitions[j].type & (USCXML_TRANS_HISTORY | USCXML_TRANS_INITIAL)) &&
+ ctx->machine->states[ctx->machine->transitions[j].source].parent == i) {
+ /* call executable content in transition */
+ if (ctx->machine->transitions[j].on_transition != NULL) {
+ if unlikely((err = ctx->machine->transitions[j].on_transition(ctx,
+ &USCXML_GET_STATE(i),
+ ctx->event)) != USCXML_ERR_OK)
+ return err;
+ }
+ }
+ }
+
+ /* handle final states */
+ if unlikely(USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_FINAL) {
+ if unlikely(USCXML_GET_STATE(i).ancestors[0] == 0x01) {
+ ctx->flags |= USCXML_CTX_TOP_LEVEL_FINAL;
+ } else {
+ /* raise done event */
+ const uscxml_elem_donedata* donedata = &ctx->machine->donedata[0];
+ while(USCXML_ELEM_DONEDATA_IS_SET(donedata)) {
+ if unlikely(donedata->source == i)
+ break;
+ donedata++;
+ }
+ ctx->raise_done_event(ctx, &ctx->machine->states[USCXML_GET_STATE(i).parent], (USCXML_ELEM_DONEDATA_IS_SET(donedata) ? donedata : NULL));
+ }
+
+ /**
+ * are we the last final state to leave a parallel state?:
+ * 1. Gather all parallel states in our ancestor chain
+ * 2. Find all states for which these parallels are ancestors
+ * 3. Iterate all active final states and remove their ancestors
+ * 4. If a state remains, not all children of a parallel are final
+ */
+ for (j = 0; j < USCXML_NUMBER_STATES; j++) {
+ if unlikely(USCXML_STATE_MASK(ctx->machine->states[j].type) == USCXML_STATE_PARALLEL &&
+ BIT_HAS(j, USCXML_GET_STATE(i).ancestors)) {
+ bit_clear_all(tmp_states, nr_states_bytes);
+ for (k = 0; k < USCXML_NUMBER_STATES; k++) {
+ if unlikely(BIT_HAS(j, ctx->machine->states[k].ancestors) && BIT_HAS(k, ctx->config)) {
+ if (USCXML_STATE_MASK(ctx->machine->states[k].type) == USCXML_STATE_FINAL) {
+ bit_and_not(tmp_states, ctx->machine->states[k].ancestors, nr_states_bytes);
+ } else {
+ BIT_SET_AT(k, tmp_states);
+ }
+ }
+ }
+ if unlikely(!bit_has_any(tmp_states, nr_states_bytes)) {
+ ctx->raise_done_event(ctx, &ctx->machine->states[j], NULL);
+ }
+ }
+ }
+
+ }
+
+ }
+ }
+
+ return USCXML_ERR_OK;
+}
+
+#define USCXML_NO_STEP_FUNCTION
+#endif
+
diff --git a/test/src/test-c-machine.cpp b/test/src/test-c-machine.cpp
index 3bd92aa..2879ef9 100644
--- a/test/src/test-c-machine.cpp
+++ b/test/src/test-c-machine.cpp
@@ -17,7 +17,7 @@
#endif
#ifndef AUTOINCLUDE_TEST
-#include "test-c-machine.machine.c"
+#include "test-c-machine.scxml.c"
#endif
#include "uscxml/Convenience.h"
@@ -637,27 +637,27 @@ public:
Data d;
std::stringstream content;
- if (data->expr != NULL) {
- d = USER_DATA(ctx)->dataModel.getStringAsData(data->expr);
-// d = Data(data->expr, Data::INTERPRETED);
- } else if (data->content != NULL) {
- content << data->content;
- d = USER_DATA(ctx)->dataModel.getStringAsData(content.str());
-// d = Data(content.str(), Data::INTERPRETED);
- } else if (data->src != NULL) {
- URL sourceURL(data->src);
- if (USER_DATA(ctx)->baseURL.size() > 0) {
- sourceURL.toAbsolute(USER_DATA(ctx)->baseURL);
+ try {
+ if (data->expr != NULL) {
+// d = USER_DATA(ctx)->dataModel.getStringAsData(data->expr);
+ d = Data(data->expr, Data::INTERPRETED);
+ } else if (data->content != NULL) {
+ content << data->content;
+ d = USER_DATA(ctx)->dataModel.getStringAsData(content.str());
+ // d = Data(content.str(), Data::INTERPRETED);
+ } else if (data->src != NULL) {
+ URL sourceURL(data->src);
+ if (USER_DATA(ctx)->baseURL.size() > 0) {
+ sourceURL.toAbsolute(USER_DATA(ctx)->baseURL);
+ } else {
+ sourceURL.toAbsoluteCwd();
+ }
+ content << sourceURL;
+ // d = Data(content.str(), Data::INTERPRETED);
+ d = USER_DATA(ctx)->dataModel.getStringAsData(content.str());
} else {
- sourceURL.toAbsoluteCwd();
+ d = Data("undefined", Data::INTERPRETED);
}
- content << sourceURL;
-// d = Data(content.str(), Data::INTERPRETED);
- d = USER_DATA(ctx)->dataModel.getStringAsData(content.str());
- } else {
- d = Data("undefined", Data::INTERPRETED);
- }
- try {
// this might fail with an unquoted string literal in content
USER_DATA(ctx)->dataModel.init(data->id, d);
} catch (Event e) {
@@ -930,7 +930,7 @@ int main(int argc, char** argv) {
double avgDm = 0;
#endif
- StateMachine rootMachine(&uscxml_machines[0]);
+ StateMachine rootMachine(&USCXML_MACHINE);
Timer tTotal;
tTotal.start();
diff --git a/test/src/test-c-machine.machine.c b/test/src/test-c-machine.scxml.c
index 5ac3994..cbbfbfe 100644
--- a/test/src/test-c-machine.machine.c
+++ b/test/src/test-c-machine.scxml.c
@@ -1,12 +1,14 @@
/**
Generated from source:
- file:///Users/sradomski/Documents/TK/Code/uscxml/test/w3c/lua/test150.scxml
+ file:///Users/sradomski/Documents/TK/Code/uscxml/test/w3c/ecma/test326.scxml
*/
-#include <stdint.h> /* explicit types */
+#ifndef USCXML_NO_STDTYPES_H
+# include <stdint.h> /* explicit types */
+#endif
#include <stddef.h> /* NULL */
-#ifndef USCXML_GEN_C_MACROS
+#ifndef USCXML_NO_GEN_C_MACROS
/**
* All macros used for the scxml types and functions
@@ -143,15 +145,15 @@
#define USCXML_ELEM_PARAM_IS_SET(param) (param->name != NULL)
#define USCXML_MACHINE_IS_SET(machine) (machine->nr_states > 0)
-#define USCXML_GEN_C_MACROS
+#define USCXML_NO_GEN_C_MACROS
#endif
-#ifndef USCXML_GEN_C_TYPES
+#ifndef USCXML_NO_GEN_C_TYPES
/**
* All types required to represent an SCXML state chart.
- * Just predefine the USCXML_GEN_C_TYPES macro if you do not need them.
+ * Just predefine the USCXML_NO_GEN_C_TYPES macro if you do not need them.
*/
typedef struct uscxml_machine uscxml_machine;
@@ -350,41 +352,38 @@ struct uscxml_ctx {
invoke_t invoke;
};
-#define USCXML_GEN_C_TYPES
+#define USCXML_NO_GEN_C_TYPES
#endif
/* forward declare machines to allow references */
-extern const uscxml_machine uscxml_machines[2];
+extern const uscxml_machine _uscxml_EC83C2A5_machine;
-static const uscxml_elem_foreach _uscxml_9FEEFF45_elem_foreachs[2] = {
- /* array, item, index */
- { "testvar3", "testvar1", "testvar2" },
- { "testvar3", "testvar4", "testvar5" }
-};
+#ifndef USCXML_NO_ELEM_INFO
-static const uscxml_elem_data _uscxml_9FEEFF45_elem_datas[4] = {
+static const uscxml_elem_data _uscxml_EC83C2A5_elem_datas[3] = {
/* id, src, expr, content */
- { "testvar1", NULL, NULL, NULL },
- { "testvar2", NULL, NULL, NULL },
- { "testvar3", NULL, NULL, "{1,2,3}" },
+ { "Var1", NULL, "_ioprocessors", NULL },
+ { "Var2", NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL }
};
-static const uscxml_elem_donedata _uscxml_9FEEFF45_elem_donedatas[1] = {
+static const uscxml_elem_donedata _uscxml_EC83C2A5_elem_donedatas[1] = {
/* source, content, contentexpr, params */
{ 0, NULL, NULL, NULL }
};
-static int _uscxml_9FEEFF45_s0_on_entry_0(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) {
- int err = USCXML_ERR_OK;
- if likely(ctx->exec_content_foreach_init != NULL &&
- ctx->exec_content_foreach_next != NULL &&
- ctx->exec_content_foreach_done != NULL) {
+#endif
- if unlikely((ctx->exec_content_foreach_init(ctx, &_uscxml_9FEEFF45_elem_foreachs[0])) != USCXML_ERR_OK) return err;
- while (ctx->exec_content_foreach_next(ctx, &_uscxml_9FEEFF45_elem_foreachs[0]) == USCXML_ERR_OK) {
- }
- if ((ctx->exec_content_foreach_done(ctx, &_uscxml_9FEEFF45_elem_foreachs[0])) != USCXML_ERR_OK) return err;
+#ifndef USCXML_NO_ELEM_INFO
+
+#endif
+
+#ifndef USCXML_NO_EXEC_CONTENT
+
+static int _uscxml_EC83C2A5_s1_on_entry_0(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) {
+ int err = USCXML_ERR_OK;
+ if likely(ctx->exec_content_assign != NULL) {
+ if ((ctx->exec_content_assign(ctx, "_ioprocessors", "'otherName'")) != USCXML_ERR_OK) return err;
} else {
return USCXML_ERR_MISSING_CALLBACK;
}
@@ -396,38 +395,61 @@ static int _uscxml_9FEEFF45_s0_on_entry_0(const uscxml_ctx* ctx, const uscxml_st
return USCXML_ERR_OK;
}
-static int _uscxml_9FEEFF45_s0_on_entry(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) {
- _uscxml_9FEEFF45_s0_on_entry_0(ctx, state, event);
+static int _uscxml_EC83C2A5_s1_on_entry(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) {
+ _uscxml_EC83C2A5_s1_on_entry_0(ctx, state, event);
return USCXML_ERR_OK;
}
-static int _uscxml_9FEEFF45_s1_on_entry_0(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) {
+static int _uscxml_EC83C2A5_s2_on_entry_0(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) {
int err = USCXML_ERR_OK;
- if likely(ctx->exec_content_foreach_init != NULL &&
- ctx->exec_content_foreach_next != NULL &&
- ctx->exec_content_foreach_done != NULL) {
+ if likely(ctx->exec_content_assign != NULL) {
+ if ((ctx->exec_content_assign(ctx, "Var2", "_ioprocessors")) != USCXML_ERR_OK) return err;
+ } else {
+ return USCXML_ERR_MISSING_CALLBACK;
+ }
+ return USCXML_ERR_OK;
+}
- if unlikely((ctx->exec_content_foreach_init(ctx, &_uscxml_9FEEFF45_elem_foreachs[1])) != USCXML_ERR_OK) return err;
- while (ctx->exec_content_foreach_next(ctx, &_uscxml_9FEEFF45_elem_foreachs[1]) == USCXML_ERR_OK) {
- }
- if ((ctx->exec_content_foreach_done(ctx, &_uscxml_9FEEFF45_elem_foreachs[1])) != USCXML_ERR_OK) return err;
+static int _uscxml_EC83C2A5_s2_on_entry(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) {
+ _uscxml_EC83C2A5_s2_on_entry_0(ctx, state, event);
+ return USCXML_ERR_OK;
+}
+
+static int _uscxml_EC83C2A5_pass_on_entry_0(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) {
+ int err = USCXML_ERR_OK;
+ if likely(ctx->exec_content_log != NULL) {
+ if unlikely((ctx->exec_content_log(ctx, "Outcome", "'pass'")) != USCXML_ERR_OK) return err;
} else {
return USCXML_ERR_MISSING_CALLBACK;
}
- if likely(ctx->exec_content_raise != NULL) {
- if unlikely((ctx->exec_content_raise(ctx, "bar")) != USCXML_ERR_OK) return err;
+ return USCXML_ERR_OK;
+}
+
+static int _uscxml_EC83C2A5_pass_on_entry(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) {
+ _uscxml_EC83C2A5_pass_on_entry_0(ctx, state, event);
+ return USCXML_ERR_OK;
+}
+
+static int _uscxml_EC83C2A5_fail_on_entry_0(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) {
+ int err = USCXML_ERR_OK;
+ if likely(ctx->exec_content_log != NULL) {
+ if unlikely((ctx->exec_content_log(ctx, "Outcome", "'fail'")) != USCXML_ERR_OK) return err;
} else {
return USCXML_ERR_MISSING_CALLBACK;
}
return USCXML_ERR_OK;
}
-static int _uscxml_9FEEFF45_s1_on_entry(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) {
- _uscxml_9FEEFF45_s1_on_entry_0(ctx, state, event);
+static int _uscxml_EC83C2A5_fail_on_entry(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) {
+ _uscxml_EC83C2A5_fail_on_entry_0(ctx, state, event);
return USCXML_ERR_OK;
}
-static const uscxml_state _uscxml_9FEEFF45_states[6] = {
+#endif
+
+#ifndef USCXML_NO_ELEM_INFO
+
+static const uscxml_state _uscxml_EC83C2A5_states[6] = {
{ /* state number 0 */
/* name */ NULL,
/* parent */ 0,
@@ -437,13 +459,13 @@ static const uscxml_state _uscxml_9FEEFF45_states[6] = {
/* children */ { 0x3e /* 011111 */ },
/* completion */ { 0x02 /* 010000 */ },
/* ancestors */ { 0x00 /* 000000 */ },
- /* data */ &_uscxml_9FEEFF45_elem_datas[0],
+ /* data */ &_uscxml_EC83C2A5_elem_datas[0],
/* type */ USCXML_STATE_COMPOUND,
},
{ /* state number 1 */
/* name */ "s0",
/* parent */ 0,
- /* onentry */ _uscxml_9FEEFF45_s0_on_entry,
+ /* onentry */ NULL,
/* onexit */ NULL,
/* invoke */ NULL,
/* children */ { 0x00 /* 000000 */ },
@@ -455,7 +477,7 @@ static const uscxml_state _uscxml_9FEEFF45_states[6] = {
{ /* state number 2 */
/* name */ "s1",
/* parent */ 0,
- /* onentry */ _uscxml_9FEEFF45_s1_on_entry,
+ /* onentry */ _uscxml_EC83C2A5_s1_on_entry,
/* onexit */ NULL,
/* invoke */ NULL,
/* children */ { 0x00 /* 000000 */ },
@@ -467,7 +489,7 @@ static const uscxml_state _uscxml_9FEEFF45_states[6] = {
{ /* state number 3 */
/* name */ "s2",
/* parent */ 0,
- /* onentry */ NULL,
+ /* onentry */ _uscxml_EC83C2A5_s2_on_entry,
/* onexit */ NULL,
/* invoke */ NULL,
/* children */ { 0x00 /* 000000 */ },
@@ -479,7 +501,7 @@ static const uscxml_state _uscxml_9FEEFF45_states[6] = {
{ /* state number 4 */
/* name */ "pass",
/* parent */ 0,
- /* onentry */ NULL,
+ /* onentry */ _uscxml_EC83C2A5_pass_on_entry,
/* onexit */ NULL,
/* invoke */ NULL,
/* children */ { 0x00 /* 000000 */ },
@@ -491,7 +513,7 @@ static const uscxml_state _uscxml_9FEEFF45_states[6] = {
{ /* state number 5 */
/* name */ "fail",
/* parent */ 0,
- /* onentry */ NULL,
+ /* onentry */ _uscxml_EC83C2A5_fail_on_entry,
/* onexit */ NULL,
/* invoke */ NULL,
/* children */ { 0x00 /* 000000 */ },
@@ -502,37 +524,41 @@ static const uscxml_state _uscxml_9FEEFF45_states[6] = {
}
};
-static const uscxml_transition _uscxml_9FEEFF45_transitions[6] = {
+#endif
+
+#ifndef USCXML_NO_ELEM_INFO
+
+static const uscxml_transition _uscxml_EC83C2A5_transitions[6] = {
{ /* transition number 0 with priority 0
- target: fail
+ target: s1
*/
/* source */ 1,
- /* target */ { 0x20 /* 000001 */ },
- /* event */ "error",
- /* condition */ NULL,
+ /* target */ { 0x04 /* 001000 */ },
+ /* event */ NULL,
+ /* condition */ "Var1",
/* ontrans */ NULL,
- /* type */ 0,
+ /* type */ USCXML_TRANS_SPONTANEOUS,
/* conflicts */ { 0x3f /* 111111 */ },
/* exit set */ { 0x3e /* 011111 */ }
},
{ /* transition number 1 with priority 1
- target: s1
+ target: fail
*/
/* source */ 1,
- /* target */ { 0x04 /* 001000 */ },
- /* event */ "*",
- /* condition */ NULL,
+ /* target */ { 0x20 /* 000001 */ },
+ /* event */ NULL,
+ /* condition */ "true",
/* ontrans */ NULL,
- /* type */ 0,
+ /* type */ USCXML_TRANS_SPONTANEOUS,
/* conflicts */ { 0x3f /* 111111 */ },
/* exit set */ { 0x3e /* 011111 */ }
},
{ /* transition number 2 with priority 2
- target: fail
+ target: s2
*/
/* source */ 2,
- /* target */ { 0x20 /* 000001 */ },
- /* event */ "error",
+ /* target */ { 0x08 /* 000100 */ },
+ /* event */ "error.execution",
/* condition */ NULL,
/* ontrans */ NULL,
/* type */ 0,
@@ -540,10 +566,10 @@ static const uscxml_transition _uscxml_9FEEFF45_transitions[6] = {
/* exit set */ { 0x3e /* 011111 */ }
},
{ /* transition number 3 with priority 3
- target: s2
+ target: fail
*/
/* source */ 2,
- /* target */ { 0x08 /* 000100 */ },
+ /* target */ { 0x20 /* 000001 */ },
/* event */ "*",
/* condition */ NULL,
/* ontrans */ NULL,
@@ -557,7 +583,7 @@ static const uscxml_transition _uscxml_9FEEFF45_transitions[6] = {
/* source */ 3,
/* target */ { 0x10 /* 000010 */ },
/* event */ NULL,
- /* condition */ "testvar4 ~= nil",
+ /* condition */ "Var1==Var2",
/* ontrans */ NULL,
/* type */ USCXML_TRANS_SPONTANEOUS,
/* conflicts */ { 0x3f /* 111111 */ },
@@ -577,23 +603,32 @@ static const uscxml_transition _uscxml_9FEEFF45_transitions[6] = {
}
};
-const uscxml_machine uscxml_machines[2] = {
- {
+#endif
+
+#ifndef USCXML_NO_ELEM_INFO
+
+#ifndef USCXML_MACHINE
+# define USCXML_MACHINE _uscxml_EC83C2A5_machine
+#endif
+#define USCXML_MACHINE_0 _uscxml_EC83C2A5_machine
+#define USCXML_MACHINE_MACHINENAME _uscxml_EC83C2A5_machine
+
+const uscxml_machine _uscxml_EC83C2A5_machine = {
/* flags */ 0,
/* nr_states */ 6,
/* nr_transitions */ 6,
- /* name */ "",
- /* datamodel */ "lua",
- /* uuid */ "9FEEFF45D10C557438897A21612B7382",
- /* states */ &_uscxml_9FEEFF45_states[0],
- /* transitions */ &_uscxml_9FEEFF45_transitions[0],
+ /* name */ "machineName",
+ /* datamodel */ "ecmascript",
+ /* uuid */ "EC83C2A5BDF05B11A1F7E2C35039F65D",
+ /* states */ &_uscxml_EC83C2A5_states[0],
+ /* transitions */ &_uscxml_EC83C2A5_transitions[0],
/* parent */ NULL,
- /* donedata */ &_uscxml_9FEEFF45_elem_donedatas[0],
+ /* donedata */ &_uscxml_EC83C2A5_elem_donedatas[0],
/* script */ NULL
- },
- {0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
+#endif
+
#ifdef USCXML_VERBOSE
/**
* Print name of states contained in a (debugging).
@@ -626,7 +661,7 @@ static void printBitsetIndices(const char* a, size_t length) {
}
#endif
-#ifndef USCXML_BIT_OPERATIONS
+#ifndef USCXML_NO_BIT_OPERATIONS
/**
* Return true if there is a common bit in a and b.
*/
@@ -696,10 +731,10 @@ static void bit_and(char* dest, const char* mask, size_t i) {
};
}
-#define USCXML_BIT_OPERATIONS
+#define USCXML_NO_BIT_OPERATIONS
#endif
-#ifndef USCXML_STEP_FUNCTION
+#ifndef USCXML_NO_STEP_FUNCTION
int uscxml_step(uscxml_ctx* ctx) {
USCXML_NR_TRANS_TYPE i, j, k;
@@ -756,7 +791,7 @@ int uscxml_step(uscxml_ctx* ctx) {
ctx->event = NULL;
goto SELECT_TRANSITIONS;
}
- if ((ctx->event = ctx->dequeue_internal(ctx)) != NULL) {
+ if (ctx->dequeue_internal != NULL && (ctx->event = ctx->dequeue_internal(ctx)) != NULL) {
goto SELECT_TRANSITIONS;
}
@@ -776,10 +811,15 @@ int uscxml_step(uscxml_ctx* ctx) {
}
}
- if ((ctx->event = ctx->dequeue_external(ctx)) != NULL) {
+ if (ctx->dequeue_external != NULL && (ctx->event = ctx->dequeue_external(ctx)) != NULL) {
goto SELECT_TRANSITIONS;
}
+ if (ctx->dequeue_external == NULL) {
+ return USCXML_ERR_DONE;
+ }
+ return USCXML_ERR_IDLE;
+
SELECT_TRANSITIONS:
bit_clear_all(conflicts, nr_trans_bytes);
bit_clear_all(exit_set, nr_states_bytes);
@@ -792,21 +832,25 @@ SELECT_TRANSITIONS:
if (BIT_HAS(USCXML_GET_TRANS(i).source, ctx->config)) {
/* is it non-conflicting? */
if (!BIT_HAS(i, conflicts)) {
- /* is it enabled? */
- if (ctx->is_enabled(ctx, &USCXML_GET_TRANS(i), ctx->event) > 0) {
- /* remember that we found a transition */
- ctx->flags |= USCXML_CTX_TRANSITION_FOUND;
+ /* is it spontaneous with an event or vice versa? */
+ if ((USCXML_GET_TRANS(i).event == NULL && ctx->event == NULL) ||
+ (USCXML_GET_TRANS(i).event != NULL && ctx->event != NULL)) {
+ /* is it enabled? */
+ if (ctx->is_enabled(ctx, &USCXML_GET_TRANS(i), ctx->event) > 0) {
+ /* remember that we found a transition */
+ ctx->flags |= USCXML_CTX_TRANSITION_FOUND;
- /* transitions that are pre-empted */
- bit_or(conflicts, USCXML_GET_TRANS(i).conflicts, nr_trans_bytes);
+ /* transitions that are pre-empted */
+ bit_or(conflicts, USCXML_GET_TRANS(i).conflicts, nr_trans_bytes);
- /* states that are directly targeted (resolve as entry-set later) */
- bit_or(target_set, USCXML_GET_TRANS(i).target, nr_states_bytes);
+ /* states that are directly targeted (resolve as entry-set later) */
+ bit_or(target_set, USCXML_GET_TRANS(i).target, nr_states_bytes);
- /* states that will be left */
- bit_or(exit_set, USCXML_GET_TRANS(i).exit_set, nr_states_bytes);
+ /* states that will be left */
+ bit_or(exit_set, USCXML_GET_TRANS(i).exit_set, nr_states_bytes);
- BIT_SET_AT(i, trans_set);
+ BIT_SET_AT(i, trans_set);
+ }
}
}
}
@@ -1082,6 +1126,6 @@ ESTABLISH_ENTRY_SET:
return USCXML_ERR_OK;
}
-#define USCXML_STEP_FUNCTION
+#define USCXML_NO_STEP_FUNCTION
#endif