From e0d6ac8097bfd148a9956128a48b7d1addf81e68 Mon Sep 17 00:00:00 2001 From: Stefan Radomski Date: Tue, 11 Jul 2017 10:02:26 +0200 Subject: Removed iostreams and PGO preparation --- CMakeLists.txt | 14 ++++++++++++++ src/uscxml/interpreter/FastMicroStep.cpp | 1 - 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f1fecb..8a4ff9e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -474,6 +474,20 @@ endif() add_subdirectory(src/uscxml) add_subdirectory(src/bindings) +# https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Optimize-Options.html#Optimize-Options +# https://clang.llvm.org/docs/UsersManual.html#profile-guided-optimization +if (${CMAKE_CXX_COMPILER_ID} STREQUAL Clang) + # add_definitions("-fprofile-instr-generate") + # add_definitions("-fprofile-generate=profiling") + # no measureable effect + # set_property(SOURCE src/uscxml/interpreter/FastMicroStep.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -fprofile-instr-generate=foo") + # set_property(SOURCE src/uscxml/interpreter/FastMicroStep.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Ofast") + # set_property(SOURCE src/uscxml/interpreter/LargeMicroStep.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Ofast") + # set_property(SOURCE src/uscxml/interpreter/FastMicroStep.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -fomit-frame-pointer") + # set_property(SOURCE src/uscxml/interpreter/LargeMicroStep.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -fomit-frame-pointer") +endif() + + if (BUILD_AS_PLUGINS) file(GLOB USCXML_PLUGINS ${CMAKE_SOURCE_DIR}/contrib/src/Pluma/*.cpp diff --git a/src/uscxml/interpreter/FastMicroStep.cpp b/src/uscxml/interpreter/FastMicroStep.cpp index 1345403..ab6b5f9 100644 --- a/src/uscxml/interpreter/FastMicroStep.cpp +++ b/src/uscxml/interpreter/FastMicroStep.cpp @@ -30,7 +30,6 @@ #include "uscxml/interpreter/Logging.h" #include // strtol -#include #undef USCXML_VERBOSE #undef WITH_CACHE_FILES -- cgit v0.12 From 04b04aa6624caf73ffe4fc33f918e7f48b27da37 Mon Sep 17 00:00:00 2001 From: Stefan Radomski Date: Thu, 13 Jul 2017 22:29:09 +0200 Subject: LambdaMonitors and prepared use-case examples --- CMakeLists.txt | 4 +- README.md | 40 +- apps/arduino/WaterPump.cxx | 170 -- apps/arduino/WaterPump.scxml | 70 - apps/arduino/stateMachine.c | 1291 ----------- apps/uscxml-browser.cpp | 132 -- apps/uscxml-browser.vbs | 177 -- apps/uscxml-debugger.html | 2839 ----------------------- apps/uscxml-transform.cpp | 385 --- contrib/cmake/CPackUSCXML.cmake | 5 + contrib/cmake/FindUSCXML.cmake | 84 + docs/BENCHMARKS.md | 26 + examples/cpp/library/lambdas/CMakeLists.txt | 10 + examples/cpp/library/lambdas/main.cpp | 17 + examples/cpp/library/simple/CMakeLists.txt | 10 + examples/cpp/library/simple/main.cpp | 17 + examples/cpp/transpiled/arduino/WaterPump.cxx | 170 ++ examples/cpp/transpiled/arduino/WaterPump.scxml | 70 + examples/cpp/transpiled/arduino/stateMachine.c | 1291 +++++++++++ src/apps/uscxml-browser.cpp | 132 ++ src/apps/uscxml-browser.vbs | 177 ++ src/apps/uscxml-debugger.html | 2839 +++++++++++++++++++++++ src/apps/uscxml-transform.cpp | 385 +++ src/uscxml/Interpreter.cpp | 4 + src/uscxml/Interpreter.h | 5 + src/uscxml/interpreter/InterpreterImpl.cpp | 13 +- src/uscxml/interpreter/InterpreterImpl.h | 6 +- src/uscxml/interpreter/InterpreterMonitor.h | 321 ++- src/uscxml/util/Predicates.cpp | 1 - test/src/test-snippets.cpp | 25 +- 30 files changed, 5597 insertions(+), 5119 deletions(-) delete mode 100644 apps/arduino/WaterPump.cxx delete mode 100644 apps/arduino/WaterPump.scxml delete mode 100644 apps/arduino/stateMachine.c delete mode 100644 apps/uscxml-browser.cpp delete mode 100644 apps/uscxml-browser.vbs delete mode 100644 apps/uscxml-debugger.html delete mode 100644 apps/uscxml-transform.cpp create mode 100644 contrib/cmake/FindUSCXML.cmake create mode 100644 docs/BENCHMARKS.md create mode 100644 examples/cpp/library/lambdas/CMakeLists.txt create mode 100644 examples/cpp/library/lambdas/main.cpp create mode 100644 examples/cpp/library/simple/CMakeLists.txt create mode 100644 examples/cpp/library/simple/main.cpp create mode 100644 examples/cpp/transpiled/arduino/WaterPump.cxx create mode 100644 examples/cpp/transpiled/arduino/WaterPump.scxml create mode 100644 examples/cpp/transpiled/arduino/stateMachine.c create mode 100644 src/apps/uscxml-browser.cpp create mode 100644 src/apps/uscxml-browser.vbs create mode 100644 src/apps/uscxml-debugger.html create mode 100644 src/apps/uscxml-transform.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a4ff9e..4c2e3dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -527,13 +527,13 @@ if (NOT CMAKE_CROSSCOMPILING) add_subdirectory(test) endif() -add_executable(uscxml-browser apps/uscxml-browser.cpp ${GETOPT_FILES}) +add_executable(uscxml-browser src/apps/uscxml-browser.cpp ${GETOPT_FILES}) set_property(TARGET uscxml-browser PROPERTY CXX_STANDARD 11) set_property(TARGET uscxml-browser PROPERTY CXX_STANDARD_REQUIRED ON) install_executable(TARGETS uscxml-browser COMPONENT tools) target_link_libraries(uscxml-browser uscxml) -add_executable(uscxml-transform apps/uscxml-transform.cpp ${GETOPT_FILES}) +add_executable(uscxml-transform src/apps/uscxml-transform.cpp ${GETOPT_FILES}) set_property(TARGET uscxml-transform PROPERTY CXX_STANDARD 11) set_property(TARGET uscxml-transform PROPERTY CXX_STANDARD_REQUIRED ON) install_executable(TARGETS uscxml-transform COMPONENT tools) diff --git a/README.md b/README.md index 7ba0406..c1f7ea7 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,11 @@ - [Changes](docs/CHANGES.md) - [Tests passed](test/w3c/TESTS.md) - [Publications](docs/PUBLICATIONS.md) +- [Benchmarks](docs/BENCHMARKS.md) ## What is it? -uSCXML is a platform to work with state-charts given as -[SCXML](http://www.w3.org/TR/scxml/) files. It consists of three principal components: +uSCXML is a platform to work with state-charts given as [SCXML](http://www.w3.org/TR/scxml/) files. It features the [fastest microstep](docs/BENCHMARKS.md) implementation available and consists of three principal components: 1. `libuscxml`: [C++ library](#embedded-as-a-library) containing an interpreter and accompanying functionality. @@ -20,9 +20,7 @@ uSCXML is a platform to work with state-charts given as 3. `uscxml-transform`: A collection of [transformation](#for-transformations) implementations to transpile SCXML, e.g. onto ANSI-C and VHDL. -The status of the various datamodels, bindings and generators with regard to the [W3C IRP -tests](https://www.w3.org/Voice/2013/scxml-irp/) can be checked in the [test -table](test/w3c/TESTS.md). +The status of the various datamodels, bindings and generators with regard to the [W3C IRPtests](https://www.w3.org/Voice/2013/scxml-irp/) can be checked in the [test table](test/w3c/TESTS.md). ## Installation @@ -58,15 +56,13 @@ For more detailled information, refer to the [documentation](http://tklab-tud.gi **Examples:** -* [uscxml-browser.cpp](https://github.com/tklab-tud/uscxml/blob/master/apps/uscxml-browser.cpp) (**C++**) +* [uscxml-browser.cpp](https://github.com/tklab-tud/uscxml/blob/master/src/apps/uscxml-browser.cpp) (**C++**) * [test-state-pass.cpp](https://github.com/tklab-tud/uscxml/blob/master/test/src/test-state-pass.cpp) (**C++**) * [TestStatePass.cs](https://github.com/tklab-tud/uscxml/blob/master/contrib/csharp/bindings/TestStatePass.cs) (**C#**) * [test-state-pass.py](https://github.com/tklab-tud/uscxml/blob/master/contrib/python/bindings/test-state-pass.py) (**Python**) * [JexlDataModelTest.java](https://github.com/tklab-tud/uscxml/blob/master/contrib/java/bindings/org/uscxml/tests/JexlDataModelTest.java) (**Java**) - - ### On the Command-line # interpret state-chart from url $ uscxml-browser https://raw.githubusercontent.com/tklab-tud/uscxml/master/test/w3c/null/test436.scxml @@ -78,34 +74,8 @@ For more detailled information, refer to the [documentation](http://tklab-tud.gi **Examples:** * [test-gen-c.cpp](https://github.com/tklab-tud/uscxml/blob/master/test/src/test-gen-c.cpp) (**C++**) -* [WaterPump.cxx](https://github.com/tklab-tud/uscxml/blob/master/apps/arduino/WaterPump.cxx) (**C++ on Arduino**) - -## Benchmarks - -We did conceive a [series of benchmark](https://github.com/tklab-tud/uscxml/tree/master/test/benchmarks) SCXML documents to evaluate the performance of the various SCXML implementations. The state-charts in the benchmarks are completely artificial and bear no resemblance to real-world state-charts. However, they may provide a general guidance to get an impression about the performance of the different implementations. - -The state-charts each stress a specific feature of any SCXML `microstep(T)` implementation. Each contains a state `mark` that is continuously entered and exited as part of a sequence of spontaneous microsteps and measures the entries per second. For every implementation, the [benchmark is run](https://github.com/tklab-tud/uscxml/blob/master/contrib/benchmarks/run.sh) for a number of seconds and the iterations per seconds are averaged. The benchmarks exist in increasing complexity from very simple with, e.g., 4 states nested in a depth of 4 compounds up until 512 for state-charts with > 250.000 states. - -**Note:** If you are the author / maintainer of one of the SCXML implementations being benchmarked below and feel that I misrepresent your implementation's performance, post an issue and I will set things straight. - -**Note:** There are two `microstep(T)` implementations in uSCXML, namely `fast` and `large` with the former being the default for transpilation and the latter for interpretation. Both are being employed on an interpreted state-chart here. For the `fast` microstep implementation we measured the case with pre-calculated predicates. - -**Note:** The numbers for scxmlcc are necessarily for the compiled case and N/A if we could not compile the state-chart within the time limit. - -### Transitions - -The Transitions benchmark measures transition selection with many conflicting transitions enabled as part of a microstep. - -![Transition Benchmark](https://user-images.githubusercontent.com/980655/27858834-004c9c78-6177-11e7-8519-2f73f0ff9fb4.png) - -### LCCA -When exiting a state via a transition, the least-common compound ancestor (LCCA) of the transition's targets and source state has to be identified. This is a common operation and its runtime is proportional to the nesting depth if implemented respectively. - -![LCCA Benchmark](https://user-images.githubusercontent.com/980655/27858835-00527ecc-6177-11e7-85d2-46c83ad5ed71.png) - -### Conclusion +* [WaterPump.cxx](https://github.com/tklab-tud/uscxml/blob/master/src/apps/arduino/WaterPump.cxx) (**C++ on Arduino**) -uSCXML with either microstep implementation is consistently the fastest with the exception of the Transitions benchmark, where the compiled `scxmlcc` is degenerating slower for more complex state-charts. This may be due to compiler optimizations (or an incomplete implementation) and it would be interesting to compare `scxmlcc` against the transpiled ANSI-C code from `uscxml-transform`. However, the limiting factor here becomes the time required to transpile the state-chart or to compile the generated source file into an executable binary respectively. With regard to huge state-charts, the large microstep implementation of `uSCXML` performs best and retains acceptable performance throughout the range of benchmarks, only surpassed by the fast implementation for smaller complexities. ## Changes diff --git a/apps/arduino/WaterPump.cxx b/apps/arduino/WaterPump.cxx deleted file mode 100644 index 01f4cfa..0000000 --- a/apps/arduino/WaterPump.cxx +++ /dev/null @@ -1,170 +0,0 @@ -// Resources: -// https://www.avrprogrammers.com/howto/atmega328-power -// https://github.com/PaulStoffregen/CapacitiveSensor -// https://de.wikipedia.org/wiki/Faustformelverfahren_%28Automatisierungstechnik%29 -// http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/ -// google://SCC3 for conformal coating - -#include -#include - - -#define USCXML_NO_HISTORY - -#define LED 13 // LED pin on the Arduino Nano -#define LIGHT A7 // 1:10 voltage divider soldered into the solar panel -#define LIGHT_THRES 300 // do not actuate beneath this brightness -#define MEASURE_INTERVAL SLEEP_1S // time between cycles -#define DARK_SLEEP_CYCLES 1 - -#define PUMP_ON LOW // Setting an output to LOW will trigger the relais -#define PUMP_OFF HIGH - -#define ROLLOFF 0.8 // exponential smoothing for sensor readings - -float soil[4] = { 0, 0, 0, 0 }; // smoothed sensor readings from the capacitive sensors -int pump[4] = { A0, A1, A2, A3 }; // we abuse analog pins as digital output -int activePump = -1; - -int thrs[4] = { 1400, 1400, 1400, 1400 }; // start pumping below these values - -CapacitiveSensor bed[4] = { // Pins where the capacitive sensors are connected - CapacitiveSensor(3, 2), - CapacitiveSensor(5, 4), - CapacitiveSensor(7, 6), - CapacitiveSensor(9, 8) -}; -char readCapSense = 0; // Whether the capsense invoker is active - -struct data_t { - int light; -}; -struct event_t { - const char* name; - struct data_t data; -}; - -// the various events -long pumpRemain = 0; -struct event_t _eventIdle = { - name: "idle" -}; -struct event_t _eventLight = { - name: "light" -}; -struct event_t _eventPump = { - name: "pump" -}; -struct event_t* _event; - -#include "stateMachine.c" - -uscxml_ctx ctx; - -/* state chart is invoking something */ -static int invoke(const uscxml_ctx* ctx, - const uscxml_state* s, - const uscxml_elem_invoke* invocation, - unsigned char uninvoke) { - if (strcmp(invocation->type, "pump") == 0) { - int pumpId = atoi(invocation->id); - digitalWrite(pump[pumpId], uninvoke == 0 ? PUMP_ON : PUMP_OFF); - } else if (strcmp(invocation->type, "capsense") == 0) { - readCapSense = uninvoke; - } -} - -/* is the event matching */ -static int matched(const uscxml_ctx* ctx, - const uscxml_transition* transition, - const void* event) { - // we ignore most event name matching rules here - return strcmp(transition->event, ((const struct event_t*)event)->name) == 0; -} - -static int send(const uscxml_ctx* ctx, const uscxml_elem_send* send) { - if (send->delay > 0) - pumpRemain = send->delay; - return USCXML_ERR_OK; -} - -static void* dequeueExternal(const uscxml_ctx* ctx) { - // we will only call step when we have an event - void* tmp = _event; - _event = NULL; - return tmp; -} - -static bool isInState(const char* stateId) { - for (size_t i = 0; i < ctx.machine->nr_states; i++) { - if (ctx.machine->states[i].name && - strcmp(ctx.machine->states[i].name, stateId) == 0 && - BIT_HAS(i, ctx.config)) { - return true; - } - } - - return false; -} - -void setup() { - // initilize the state chart - memset(&ctx, 0, sizeof(uscxml_ctx)); - ctx.machine = &USCXML_MACHINE; - ctx.invoke = invoke; - ctx.is_matched = matched; - ctx.dequeue_external = dequeueExternal; - ctx.exec_content_send = send; - - int err = USCXML_ERR_OK; - - // run until first stable config - while((err = uscxml_step(&ctx)) != USCXML_ERR_IDLE) {} -} - - -void loop() { - digitalWrite(LED, HIGH); - - int err = USCXML_ERR_OK; - - if (readCapSense) { - // capsense invoker is active - for (int i = 0; i < 4; ++i) { - int cap = bed[i].capacitiveSensor(50); - if (cap > 0) { - soil[i] = ROLLOFF * soil[i] + (1 - ROLLOFF) * (cap - thrs[i]); - } - } - } - - _eventLight.data.light = analogRead(LIGHT); - _event = &_eventLight; - while((err = uscxml_step(&ctx)) != USCXML_ERR_IDLE) {} - - if (isInState("dark")) { - LowPower.powerDown(MEASURE_INTERVAL, ADC_OFF, BOD_OFF); - return; - } - - if (isInState("light")) { - if (false) { - } else if (isInState("pumping")) { - // is time elapsed already? - if (pumpRemain == 0) { - _event = &_eventIdle; - while((err = uscxml_step(&ctx)) != USCXML_ERR_IDLE) {} - } - } else if (isInState("idle")) { - // check is we need to pump - _event = &_eventPump; - while((err = uscxml_step(&ctx)) != USCXML_ERR_IDLE) {} - } - } - - pumpRemain = (pumpRemain >= 8000) ? pumpRemain - 8000 : 0; - - digitalWrite(LED, LOW); - LowPower.powerDown(MEASURE_INTERVAL, ADC_OFF, BOD_OFF); - -} diff --git a/apps/arduino/WaterPump.scxml b/apps/arduino/WaterPump.scxml deleted file mode 100644 index a7d8bad..0000000 --- a/apps/arduino/WaterPump.scxml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/arduino/stateMachine.c b/apps/arduino/stateMachine.c deleted file mode 100644 index a74535b..0000000 --- a/apps/arduino/stateMachine.c +++ /dev/null @@ -1,1291 +0,0 @@ -/** - Generated from source: - file:///Users/sradomski/Documents/Electronics/WaterPump/WaterPump.scxml -*/ - -#ifndef USCXML_NO_STDTYPES_H -# include /* explicit types */ -#endif -#include /* 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 2 -#endif - -/** - * USCXML_MAX_NR_TRANS_BYTES - * same as above but for transitions. - */ - -#ifndef USCXML_MAX_NR_TRANS_BYTES -# define USCXML_MAX_NR_TRANS_BYTES 1 -#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_assign uscxml_elem_assign; -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); -typedef int (*is_matched_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 uscxml_elem_assign* assign); -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 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 an element - */ -struct uscxml_elem_assign { - const char* location; - 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 unsigned char children[USCXML_MAX_NR_STATES_BYTES]; /* all children */ - const unsigned char completion[USCXML_MAX_NR_STATES_BYTES]; /* default completion */ - const unsigned 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 element - */ -struct uscxml_transition { - const USCXML_NR_STATES_TYPE source; - const unsigned char target[USCXML_MAX_NR_STATES_BYTES]; - const char* event; - const char* condition; - const is_enabled_t is_enabled; - const exec_content_t on_transition; - const unsigned char type; - const unsigned char conflicts[USCXML_MAX_NR_TRANS_BYTES]; - const unsigned char exit_set[USCXML_MAX_NR_STATES_BYTES]; -}; - -/** - * All information pertaining to a element - */ -struct uscxml_elem_foreach { - const char* array; - const char* item; - const char* index; -}; - -/** - * All information pertaining to a 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 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 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 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; - unsigned long 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; - - unsigned char config[USCXML_MAX_NR_STATES_BYTES]; /* Make sure these macros specify a sufficient size */ - unsigned char history[USCXML_MAX_NR_STATES_BYTES]; - unsigned char invocations[USCXML_MAX_NR_STATES_BYTES]; - unsigned char initialized_data[USCXML_MAX_NR_STATES_BYTES]; - - void* user_data; - void* event; - - dequeue_internal_t dequeue_internal; - dequeue_external_t dequeue_external; - is_matched_t is_matched; - 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_4FC60039__machine; - -#ifndef USCXML_NO_ELEM_INFO - -static const uscxml_elem_send _uscxml_4FC60039__elem_sends[1] = { - { - /* event */ "idle", - /* eventexpr */ NULL, - /* target */ NULL, - /* targetexpr */ NULL, - /* type */ NULL, - /* typeexpr */ NULL, - /* id */ NULL, - /* idlocation */ NULL, - /* delay */ 8000, - /* delayexpr */ NULL, - /* namelist */ NULL, - /* content */ NULL, - /* contentexpr */ NULL, - /* params */ NULL - } -}; - -static const uscxml_elem_donedata _uscxml_4FC60039__elem_donedatas[1] = { - /* source, content, contentexpr, params */ - { 0, NULL, NULL, NULL } -}; - -#endif - -#ifndef USCXML_NO_ELEM_INFO - -static const uscxml_elem_invoke _uscxml_4FC60039__elem_invokes[5] = { - { - /* machine */ NULL, - /* type */ "capsense", - /* typeexpr */ NULL, - /* src */ NULL, - /* srcexpr */ NULL, - /* id */ "cap", - /* idlocation */ NULL, - /* sourcename */ "light", - /* namelist */ NULL, - /* autoforward */ 0, - /* params */ NULL, - /* finalize */ NULL, - /* content */ NULL, - /* contentexpr */ NULL, - }, - { - /* machine */ NULL, - /* type */ "pump", - /* typeexpr */ NULL, - /* src */ NULL, - /* srcexpr */ NULL, - /* id */ "1", - /* idlocation */ NULL, - /* sourcename */ "pump1", - /* namelist */ NULL, - /* autoforward */ 0, - /* params */ NULL, - /* finalize */ NULL, - /* content */ NULL, - /* contentexpr */ NULL, - }, - { - /* machine */ NULL, - /* type */ "pump", - /* typeexpr */ NULL, - /* src */ NULL, - /* srcexpr */ NULL, - /* id */ "2", - /* idlocation */ NULL, - /* sourcename */ "pump2", - /* namelist */ NULL, - /* autoforward */ 0, - /* params */ NULL, - /* finalize */ NULL, - /* content */ NULL, - /* contentexpr */ NULL, - }, - { - /* machine */ NULL, - /* type */ "pump", - /* typeexpr */ NULL, - /* src */ NULL, - /* srcexpr */ NULL, - /* id */ "3", - /* idlocation */ NULL, - /* sourcename */ "pump3", - /* namelist */ NULL, - /* autoforward */ 0, - /* params */ NULL, - /* finalize */ NULL, - /* content */ NULL, - /* contentexpr */ NULL, - }, - { - /* machine */ NULL, - /* type */ "pump", - /* typeexpr */ NULL, - /* src */ NULL, - /* srcexpr */ NULL, - /* id */ "4", - /* idlocation */ NULL, - /* sourcename */ "pump4", - /* namelist */ NULL, - /* autoforward */ 0, - /* params */ NULL, - /* finalize */ NULL, - /* content */ NULL, - /* contentexpr */ NULL, - } -}; - -#endif - -#ifndef USCXML_NO_EXEC_CONTENT - -static int _uscxml_4FC60039__global_script_0(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) { - int err = USCXML_ERR_OK; - - pinMode(LED, OUTPUT); - for (char i = 0; i < 4; ++i) { - pinMode(pump[i], OUTPUT); - digitalWrite(pump[i], PUMP_OFF); - bed[i].set_CS_AutocaL_Millis(0xFFFFFFFF); - } - return USCXML_ERR_OK; -} -static int _uscxml_4FC60039__global_script(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) { - _uscxml_4FC60039__global_script_0(ctx, state, event); - return USCXML_ERR_OK; -} - -static int _uscxml_4FC60039__dark_on_entry_0(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) { - int err = USCXML_ERR_OK; - - for (char i = 0; i < 4; ++i) { - digitalWrite(pump[i], PUMP_OFF); - } - return USCXML_ERR_OK; -} - -static int _uscxml_4FC60039__dark_on_entry(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) { - _uscxml_4FC60039__dark_on_entry_0(ctx, state, event); - return USCXML_ERR_OK; -} - -static int _uscxml_4FC60039__light_invoke(const uscxml_ctx* ctx, const uscxml_state* s, const uscxml_elem_invoke* invocation, unsigned char uninvoke) { - ctx->invoke(ctx, s, &_uscxml_4FC60039__elem_invokes[0], uninvoke); - - return USCXML_ERR_OK; -} -static int _uscxml_4FC60039__pumping_on_entry_0(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) { - int err = USCXML_ERR_OK; - if likely(ctx->exec_content_send != NULL) { - if ((ctx->exec_content_send(ctx, &_uscxml_4FC60039__elem_sends[0])) != USCXML_ERR_OK) return err; - } else { - return USCXML_ERR_MISSING_CALLBACK; - } - return USCXML_ERR_OK; -} - -static int _uscxml_4FC60039__pumping_on_entry(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) { - _uscxml_4FC60039__pumping_on_entry_0(ctx, state, event); - return USCXML_ERR_OK; -} - -static int _uscxml_4FC60039__pump1_invoke(const uscxml_ctx* ctx, const uscxml_state* s, const uscxml_elem_invoke* invocation, unsigned char uninvoke) { - ctx->invoke(ctx, s, &_uscxml_4FC60039__elem_invokes[1], uninvoke); - - return USCXML_ERR_OK; -} -static int _uscxml_4FC60039__pump2_invoke(const uscxml_ctx* ctx, const uscxml_state* s, const uscxml_elem_invoke* invocation, unsigned char uninvoke) { - ctx->invoke(ctx, s, &_uscxml_4FC60039__elem_invokes[2], uninvoke); - - return USCXML_ERR_OK; -} -static int _uscxml_4FC60039__pump3_invoke(const uscxml_ctx* ctx, const uscxml_state* s, const uscxml_elem_invoke* invocation, unsigned char uninvoke) { - ctx->invoke(ctx, s, &_uscxml_4FC60039__elem_invokes[3], uninvoke); - - return USCXML_ERR_OK; -} -static int _uscxml_4FC60039__pump4_invoke(const uscxml_ctx* ctx, const uscxml_state* s, const uscxml_elem_invoke* invocation, unsigned char uninvoke) { - ctx->invoke(ctx, s, &_uscxml_4FC60039__elem_invokes[4], uninvoke); - - return USCXML_ERR_OK; -} -static int _uscxml_4FC60039__dark_transition0_is_enabled(const uscxml_ctx* ctx, const uscxml_transition* transition) { - return (_event->data.light > LIGHT_THRES); -} -static int _uscxml_4FC60039__idle_transition0_is_enabled(const uscxml_ctx* ctx, const uscxml_transition* transition) { - return (soil[0] < 0 && soil[0] <= soil[1]); -} -static int _uscxml_4FC60039__idle_transition1_is_enabled(const uscxml_ctx* ctx, const uscxml_transition* transition) { - return (soil[1] < 0 && soil[1] <= soil[0]); -} -static int _uscxml_4FC60039__light_transition0_is_enabled(const uscxml_ctx* ctx, const uscxml_transition* transition) { - return (_event->data.light < LIGHT_THRES); -} -#endif - -#ifndef USCXML_NO_ELEM_INFO - -static const uscxml_state _uscxml_4FC60039__states[9] = { - { /* state number 0 */ - /* name */ NULL, - /* parent */ 0, - /* onentry */ NULL, - /* onexit */ NULL, - /* invoke */ NULL, - /* children */ { 0x06, 0x00 /* 011000000 */ }, - /* completion */ { 0x02, 0x00 /* 010000000 */ }, - /* ancestors */ { 0x00, 0x00 /* 000000000 */ }, - /* data */ NULL, - /* type */ USCXML_STATE_COMPOUND, - }, - { /* state number 1 */ - /* name */ "dark", - /* parent */ 0, - /* onentry */ _uscxml_4FC60039__dark_on_entry, - /* onexit */ NULL, - /* invoke */ NULL, - /* children */ { 0x00, 0x00 /* 000000000 */ }, - /* completion */ { 0x00, 0x00 /* 000000000 */ }, - /* ancestors */ { 0x01, 0x00 /* 100000000 */ }, - /* data */ NULL, - /* type */ USCXML_STATE_ATOMIC, - }, - { /* state number 2 */ - /* name */ "light", - /* parent */ 0, - /* onentry */ NULL, - /* onexit */ NULL, - /* invoke */ _uscxml_4FC60039__light_invoke, - /* children */ { 0x18, 0x00 /* 000110000 */ }, - /* completion */ { 0x08, 0x00 /* 000100000 */ }, - /* ancestors */ { 0x01, 0x00 /* 100000000 */ }, - /* data */ NULL, - /* type */ USCXML_STATE_COMPOUND, - }, - { /* state number 3 */ - /* name */ "idle", - /* parent */ 2, - /* onentry */ NULL, - /* onexit */ NULL, - /* invoke */ NULL, - /* children */ { 0x00, 0x00 /* 000000000 */ }, - /* completion */ { 0x00, 0x00 /* 000000000 */ }, - /* ancestors */ { 0x05, 0x00 /* 101000000 */ }, - /* data */ NULL, - /* type */ USCXML_STATE_ATOMIC, - }, - { /* state number 4 */ - /* name */ "pumping", - /* parent */ 2, - /* onentry */ _uscxml_4FC60039__pumping_on_entry, - /* onexit */ NULL, - /* invoke */ NULL, - /* children */ { 0xe0, 0x01 /* 000001111 */ }, - /* completion */ { 0x20, 0x00 /* 000001000 */ }, - /* ancestors */ { 0x05, 0x00 /* 101000000 */ }, - /* data */ NULL, - /* type */ USCXML_STATE_COMPOUND, - }, - { /* state number 5 */ - /* name */ "pump1", - /* parent */ 4, - /* onentry */ NULL, - /* onexit */ NULL, - /* invoke */ _uscxml_4FC60039__pump1_invoke, - /* children */ { 0x00, 0x00 /* 000000000 */ }, - /* completion */ { 0x00, 0x00 /* 000000000 */ }, - /* ancestors */ { 0x15, 0x00 /* 101010000 */ }, - /* data */ NULL, - /* type */ USCXML_STATE_ATOMIC, - }, - { /* state number 6 */ - /* name */ "pump2", - /* parent */ 4, - /* onentry */ NULL, - /* onexit */ NULL, - /* invoke */ _uscxml_4FC60039__pump2_invoke, - /* children */ { 0x00, 0x00 /* 000000000 */ }, - /* completion */ { 0x00, 0x00 /* 000000000 */ }, - /* ancestors */ { 0x15, 0x00 /* 101010000 */ }, - /* data */ NULL, - /* type */ USCXML_STATE_ATOMIC, - }, - { /* state number 7 */ - /* name */ "pump3", - /* parent */ 4, - /* onentry */ NULL, - /* onexit */ NULL, - /* invoke */ _uscxml_4FC60039__pump3_invoke, - /* children */ { 0x00, 0x00 /* 000000000 */ }, - /* completion */ { 0x00, 0x00 /* 000000000 */ }, - /* ancestors */ { 0x15, 0x00 /* 101010000 */ }, - /* data */ NULL, - /* type */ USCXML_STATE_ATOMIC, - }, - { /* state number 8 */ - /* name */ "pump4", - /* parent */ 4, - /* onentry */ NULL, - /* onexit */ NULL, - /* invoke */ _uscxml_4FC60039__pump4_invoke, - /* children */ { 0x00, 0x00 /* 000000000 */ }, - /* completion */ { 0x00, 0x00 /* 000000000 */ }, - /* ancestors */ { 0x15, 0x00 /* 101010000 */ }, - /* data */ NULL, - /* type */ USCXML_STATE_ATOMIC, - } -}; - -#endif - -#ifndef USCXML_NO_ELEM_INFO - -static const uscxml_transition _uscxml_4FC60039__transitions[5] = { - { /* transition number 0 with priority 0 - target: light - */ - /* source */ 1, - /* target */ { 0x04, 0x00 /* 001000000 */ }, - /* event */ "light", - /* condition */ NULL, - /* is_enabled */ _uscxml_4FC60039__dark_transition0_is_enabled, - /* ontrans */ NULL, - /* type */ 0, - /* conflicts */ { 0x1f /* 11111 */ }, - /* exit set */ { 0xfe, 0x01 /* 011111111 */ } - }, - { /* transition number 2 with priority 1 - target: pump1 - */ - /* source */ 3, - /* target */ { 0x20, 0x00 /* 000001000 */ }, - /* event */ "pump", - /* condition */ NULL, - /* is_enabled */ _uscxml_4FC60039__idle_transition0_is_enabled, - /* ontrans */ NULL, - /* type */ 0, - /* conflicts */ { 0x1f /* 11111 */ }, - /* exit set */ { 0xf8, 0x01 /* 000111111 */ } - }, - { /* transition number 3 with priority 2 - target: pump2 - */ - /* source */ 3, - /* target */ { 0x40, 0x00 /* 000000100 */ }, - /* event */ "pump", - /* condition */ NULL, - /* is_enabled */ _uscxml_4FC60039__idle_transition1_is_enabled, - /* ontrans */ NULL, - /* type */ 0, - /* conflicts */ { 0x1f /* 11111 */ }, - /* exit set */ { 0xf8, 0x01 /* 000111111 */ } - }, - { /* transition number 4 with priority 3 - target: idle - */ - /* source */ 4, - /* target */ { 0x08, 0x00 /* 000100000 */ }, - /* event */ "idle", - /* condition */ NULL, - /* is_enabled */ NULL, - /* ontrans */ NULL, - /* type */ 0, - /* conflicts */ { 0x1f /* 11111 */ }, - /* exit set */ { 0xf8, 0x01 /* 000111111 */ } - }, - { /* transition number 1 with priority 4 - target: dark - */ - /* source */ 2, - /* target */ { 0x02, 0x00 /* 010000000 */ }, - /* event */ "light", - /* condition */ NULL, - /* is_enabled */ _uscxml_4FC60039__light_transition0_is_enabled, - /* ontrans */ NULL, - /* type */ 0, - /* conflicts */ { 0x1f /* 11111 */ }, - /* exit set */ { 0xfe, 0x01 /* 011111111 */ } - } -}; - -#endif - -#ifndef USCXML_NO_ELEM_INFO - -#ifndef USCXML_MACHINE -# define USCXML_MACHINE _uscxml_4FC60039__machine -#endif -#define USCXML_MACHINE_0 _uscxml_4FC60039__machine -#define USCXML_MACHINE_WATERPUMP_SCXML _uscxml_4FC60039__machine - -const uscxml_machine _uscxml_4FC60039__machine = { - /* flags */ 0, - /* nr_states */ 9, - /* nr_transitions */ 5, - /* name */ "WaterPump.scxml", - /* datamodel */ "native", - /* uuid */ "4FC600390B3422E11879652D26725E30", - /* states */ &_uscxml_4FC60039__states[0], - /* transitions */ &_uscxml_4FC60039__transitions[0], - /* parent */ NULL, - /* donedata */ &_uscxml_4FC60039__elem_donedatas[0], - /* script */ _uscxml_4FC60039__global_script - -}; - -#endif - -#ifdef USCXML_VERBOSE -/** - * Print name of states contained in a (debugging). - */ -static void printStateNames(const uscxml_ctx* ctx, const unsigned 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 unsigned char* a, size_t length) { - size_t i; - const char* seperator = ""; - for (i = 0; i < length; i++) { - if (BIT_HAS(i, a)) { - printf("%s%zu", 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 unsigned char* a, const unsigned 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(unsigned 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(unsigned 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(unsigned char* dest, const unsigned 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(unsigned char* dest, const unsigned char* source, size_t i) { - while(i--) { - dest[i] = source[i]; - } -} - -/** - * Unset bits from mask in dest. - */ -static void bit_and_not(unsigned char* dest, const unsigned char* mask, size_t i) { - while(i--) { - dest[i] &= ~mask[i]; - } -} - -/** - * Set bits from mask in dest. - */ -static void bit_and(unsigned char* dest, const unsigned 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; - unsigned char conflicts [USCXML_MAX_NR_TRANS_BYTES]; - unsigned char trans_set [USCXML_MAX_NR_TRANS_BYTES]; - unsigned char target_set [USCXML_MAX_NR_STATES_BYTES]; - unsigned char exit_set [USCXML_MAX_NR_STATES_BYTES]; - unsigned char entry_set [USCXML_MAX_NR_STATES_BYTES]; - unsigned 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; - } - -DEQUEUE_EVENT: - 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->event == NULL || ctx->is_matched(ctx, &USCXML_GET_TRANS(i), ctx->event) > 0) && - (USCXML_GET_TRANS(i).condition == NULL || - USCXML_GET_TRANS(i).is_enabled(ctx, &USCXML_GET_TRANS(i)) > 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; - goto DEQUEUE_EVENT; - } - -#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; - } -#ifndef USCXML_NO_HISTORY - 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; - } -#endif - 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/apps/uscxml-browser.cpp b/apps/uscxml-browser.cpp deleted file mode 100644 index dd0633b..0000000 --- a/apps/uscxml-browser.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include "uscxml/config.h" -#include "uscxml/Interpreter.h" -#include "uscxml/InterpreterOptions.h" -#include "uscxml/debug/InterpreterIssue.h" -#include "uscxml/debug/DebuggerServlet.h" -#include "uscxml/interpreter/InterpreterMonitor.h" -#include "uscxml/util/DOM.h" - -#include "uscxml/interpreter/Logging.h" - -#include "uscxml/plugins/Factory.h" -#include "uscxml/server/HTTPServer.h" - - -int main(int argc, char** argv) { - using namespace uscxml; - -#if defined(HAS_SIGNAL_H) && !defined(WIN32) - signal(SIGPIPE, SIG_IGN); -#endif - - InterpreterOptions options = InterpreterOptions::fromCmdLine(argc, argv); - - if (!options) { - InterpreterOptions::printUsageAndExit(argv[0]); - } - - if (!options.validate) { - // setup HTTP server - HTTPServer::SSLConfig* sslConf = NULL; - if (options.certificate.length() > 0) { - sslConf = new HTTPServer::SSLConfig(); - sslConf->privateKey = options.certificate; - sslConf->publicKey = options.certificate; - sslConf->port = options.httpsPort; - - } else if (options.privateKey.length() > 0 && options.publicKey.length() > 0) { - sslConf = new HTTPServer::SSLConfig(); - sslConf->privateKey = options.privateKey; - sslConf->publicKey = options.publicKey; - sslConf->port = options.httpsPort; - - } - HTTPServer::getInstance(options.httpPort, options.wsPort, sslConf); - } - - if (options.pluginPath.length() > 0) { - Factory::setDefaultPluginPath(options.pluginPath); - } - - if (options.verbose) { - Factory::getInstance()->listComponents(); - } - - // instantiate and configure interpreters - std::list interpreters; - for(size_t i = 0; i < options.interpreters.size(); i++) { - -// InterpreterOptions* currOptions = options.interpreters[0].second; - std::string documentURL = options.interpreters[i].first; - - LOGD(USCXML_INFO) << "Processing " << documentURL << std::endl; - - try { - Interpreter interpreter = Interpreter::fromURL(documentURL); - if (interpreter) { - - if (options.validate) { - std::list issues = interpreter.validate(); - for (std::list::iterator issueIter = issues.begin(); issueIter != issues.end(); issueIter++) { - LOGD(USCXML_DEBUG) << "" << *issueIter << std::endl; - } - if (issues.size() == 0) { - LOGD(USCXML_DEBUG) << "No issues found" << std::endl; - } - - } - - if (options.verbose) { - StateTransitionMonitor* vm = new StateTransitionMonitor(); - vm->copyToInvokers(true); - interpreter.addMonitor(vm); - } - - interpreters.push_back(interpreter); - - } else { - LOGD(USCXML_ERROR) << "Cannot create interpreter from " << documentURL << std::endl; - } - } catch (Event e) { - LOGD(USCXML_ERROR) << e << std::endl; - } - } - - if (options.validate) { - return EXIT_SUCCESS; - } - - if (options.withDebugger) { - DebuggerServlet* debugger; - debugger = new DebuggerServlet(); - debugger->copyToInvokers(true); - HTTPServer::getInstance()->registerServlet("/debug", debugger); - for (auto interpreter : interpreters) { - interpreter.addMonitor(debugger); - } - } - - // run interpreters - if (interpreters.size() > 0) { - try { - std::list::iterator interpreterIter = interpreters.begin(); - while (interpreters.size() > 0) { - while(interpreterIter != interpreters.end()) { - InterpreterState state = interpreterIter->step(); - if (state == USCXML_FINISHED) { - interpreterIter = interpreters.erase(interpreterIter); - } else { - interpreterIter++; - } - } - interpreterIter = interpreters.begin(); - } - } catch (Event e) { - LOGD(USCXML_ERROR) << e << std::endl; - } - } else if (options.withDebugger) { - while(true) - std::this_thread::sleep_for(std::chrono::seconds(1)); - } - return EXIT_SUCCESS; -} diff --git a/apps/uscxml-browser.vbs b/apps/uscxml-browser.vbs deleted file mode 100644 index fc8ea9a..0000000 --- a/apps/uscxml-browser.vbs +++ /dev/null @@ -1,177 +0,0 @@ -' -' Description: VBScript/VBS open file dialog -' Compatible with most Windows platforms -' Author: wangye -' Website: http://wangye.org -' -' dir is the initial directory; if no directory is -' specified "Desktop" is used. -' filter is the file type filter; format "File type description|*.ext" -' -Public Function GetOpenFileName(dir, filter) - Const msoFileDialogFilePicker = 3 - - If VarType(dir) <> vbString Or dir="" Then - dir = CreateObject( "WScript.Shell" ).SpecialFolders( "Desktop" ) - End If - - If VarType(filter) <> vbString Or filter="" Then - filter = "All files|*.*" - End If - - Dim i,j, objDialog, TryObjectNames - TryObjectNames = Array( _ - "UserAccounts.CommonDialog", _ - "MSComDlg.CommonDialog", _ - "MSComDlg.CommonDialog.1", _ - "Word.Application", _ - "SAFRCFileDlg.FileOpen", _ - "InternetExplorer.Application" _ - ) - - On Error Resume Next - Err.Clear - - For i=0 To UBound(TryObjectNames) - Set objDialog = WSH.CreateObject(TryObjectNames(i)) - If Err.Number<>0 Then - Err.Clear - Else - Exit For - End If - Next - - Select Case i - Case 0,1,2 - ' 0. UserAccounts.CommonDialog XP Only. - ' 1.2. MSComDlg.CommonDialog MSCOMDLG32.OCX must registered. - If i=0 Then - objDialog.InitialDir = dir - Else - objDialog.InitDir = dir - End If - objDialog.Filter = filter - If objDialog.ShowOpen Then - GetOpenFileName = objDialog.FileName - End If - Case 3 - ' 3. Word.Application Microsoft Office must installed. - objDialog.Visible = False - Dim objOpenDialog, filtersInArray - filtersInArray = Split(filter, "|") - Set objOpenDialog = _ - objDialog.Application.FileDialog( _ - msoFileDialogFilePicker) - With objOpenDialog - .Title = "Open File(s):" - .AllowMultiSelect = False - .InitialFileName = dir - .Filters.Clear - For j=0 To UBound(filtersInArray) Step 2 - .Filters.Add filtersInArray(j), _ - filtersInArray(j+1), 1 - Next - If .Show And .SelectedItems.Count>0 Then - GetOpenFileName = .SelectedItems(1) - End If - End With - objDialog.Visible = True - objDialog.Quit - Set objOpenDialog = Nothing - Case 4 - ' 4. SAFRCFileDlg.FileOpen xp 2003 only - ' See http://www.robvanderwoude.com/vbstech_ui_fileopen.php - If objDialog.OpenFileOpenDlg Then - GetOpenFileName = objDialog.FileName - End If - Case 5 - - Dim IEVersion,IEMajorVersion, hasCompleted - hasCompleted = False - Dim shell - Set shell = CreateObject("WScript.Shell") - ' 下面获取IE版本 - IEVersion = shell.RegRead( _ - "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Version") - If InStr(IEVersion,".")>0 Then - ' 获取主版本号 - IEMajorVersion = CInt(Left(IEVersion, InStr(IEVersion,".")-1)) - If IEMajorVersion>7 Then - ' 如果版本号大于7,也就是大于IE7,则采取MSHTA方案 - ' Bypasses c:\fakepath\file.txt problem - ' http://pastebin.com/txVgnLBV - Dim fso - Set fso = CreateObject("Scripting.FileSystemObject") - - Dim tempFolder : Set tempFolder = fso.GetSpecialFolder(2) - Dim tempName : tempName = fso.GetTempName() - Dim tempFile : Set tempFile = tempFolder.CreateTextFile(tempName & ".hta") - Dim tempBaseName - tempBaseName = tempFolder & "\" & tempName - tempFile.Write _ - "" & _ - " " & _ - " Browse" & _ - " " & _ - " " & _ - " " & _ - " " & _ - " " & _ - "" - tempFile.Close - Set tempFile = Nothing - Set tempFolder = Nothing - shell.Run tempBaseName & ".hta", 1, True - Set tempFile = fso.OpenTextFile(tempBaseName & ".txt", 1) - GetOpenFileName = tempFile.ReadLine - tempFile.Close - fso.DeleteFile tempBaseName & ".hta" - fso.DeleteFile tempBaseName & ".txt" - Set tempFile = Nothing - Set fso = Nothing - hasCompleted = True ' 标记为已完成 - End If - End If - If Not hasCompleted Then - ' 5. InternetExplorer.Application IE must installed - objDialog.Navigate "about:blank" - Dim objBody, objFileDialog - Set objBody = _ - objDialog.document.getElementsByTagName("body")(0) - objBody.innerHTML = "" - while objDialog.Busy Or objDialog.ReadyState <> 4 - WScript.sleep 10 - Wend - Set objFileDialog = objDialog.document.all.fileDialog - objFileDialog.click - GetOpenFileName = objFileDialog.value - End If - objDialog.Quit - Set objFileDialog = Nothing - Set objBody = Nothing - Set shell = Nothing - Case Else - ' Sorry I cannot do that! - End Select - - Set objDialog = Nothing -End Function - -scxmlFile = GetOpenFileName(CreateObject("WScript.Shell").SpecialFolders("MyDocuments"), "All Files|*.*|SCXML Files|*.scxml") - -if scxmlFile <> "" then - set wshShell = WScript.CreateObject("WScript.Shell") - set objFs = WScript.CreateObject("Scripting.FileSystemObject") - wshShell.CurrentDirectory = objFs.GetParentFolderName(Wscript.ScriptFullName) -' WScript.Echo scxmlFile - wshShell.Run("mmi-browser.exe """ & scxmlFile & """") -end if \ No newline at end of file diff --git a/apps/uscxml-debugger.html b/apps/uscxml-debugger.html deleted file mode 100644 index fa49554..0000000 --- a/apps/uscxml-debugger.html +++ /dev/null @@ -1,2839 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- - diff --git a/apps/uscxml-transform.cpp b/apps/uscxml-transform.cpp deleted file mode 100644 index e99ed68..0000000 --- a/apps/uscxml-transform.cpp +++ /dev/null @@ -1,385 +0,0 @@ -#include "uscxml/config.h" -#include "uscxml/Interpreter.h" -#include "uscxml/util/String.h" -#include "uscxml/transform/ChartToC.h" -#include "uscxml/transform/ChartToJava.h" -#include "uscxml/transform/ChartToVHDL.h" -#include "uscxml/transform/ChartToPromela.h" - -#include - -#include -#include -#include - -#include "uscxml/plugins/Factory.h" -#include "uscxml/server/HTTPServer.h" -#include "getopt.h" - -#include "uscxml/interpreter/Logging.h" - -#define ANNOTATE(envKey, annotationParam) \ -envVarIsTrue(envKey) || std::find(options.begin(), options.end(), annotationParam) != options.end() - -void printUsageAndExit(const char* progName) { - // remove path from program name - std::string progStr(progName); - if (progStr.find_last_of(PATH_SEPERATOR) != std::string::npos) { - progStr = progStr.substr(progStr.find_last_of(PATH_SEPERATOR) + 1, progStr.length() - (progStr.find_last_of(PATH_SEPERATOR) + 1)); - } - - printf("%s version " USCXML_VERSION " (" CMAKE_BUILD_TYPE " build - " CMAKE_COMPILER_STRING ")\n", progStr.c_str()); - printf("Usage\n"); - printf("\t%s", progStr.c_str()); - printf(" [-t c|pml|flat|min] [-a {OPTIONS}] [-v] [-lN]"); -#ifdef BUILD_AS_PLUGINS - printf(" [-p pluginPath]"); -#endif - printf(" [-i URL] [-o FILE]"); - printf("\n"); - printf("Options\n"); - printf("\t-t c : convert to C program\n"); - printf("\t-t pml : convert to spin/promela program\n"); - printf("\t-t vhdl : convert to VHDL hardware description\n"); - printf("\t-t java : convert to Java classes\n"); - printf("\t-t flat : flatten to SCXML state-machine\n"); - printf("\t-a FILE : write annotated SCXML document for transformation\n"); - printf("\t-X {PARAMETER} : pass additional parameters to the transformation\n"); - printf("\t prefix=ID - prefix all symbols and identifiers with ID (-tc)\n"); - printf("\t-v : be verbose\n"); - printf("\t-lN : Set loglevel to N\n"); - printf("\t-i URL : Input file (defaults to STDIN)\n"); - printf("\t-o FILE : Output file (defaults to STDOUT)\n"); - printf("\n"); - exit(1); -} - -int main(int argc, char** argv) { - using namespace uscxml; - - bool verbose = false; - std::string outType; - std::string pluginPath; - std::string inputFile; - std::string annotatedFile; - std::string outputFile; - std::list options; - std::multimap extensions; - -#if defined(HAS_SIGNAL_H) && !defined(WIN32) - signal(SIGPIPE, SIG_IGN); -#endif - - optind = 0; - opterr = 0; - - struct option longOptions[] = { - {"verbose", no_argument, 0, 'v'}, - {"type", required_argument, 0, 't'}, - {"annotate", required_argument, 0, 'a'}, - {"param", required_argument, 0, 'X'}, - {"plugin-path", required_argument, 0, 'p'}, - {"input-file", required_argument, 0, 'i'}, - {"output-file", required_argument, 0, 'o'}, - {"loglevel", required_argument, 0, 'l'}, - {0, 0, 0, 0} - }; - - // parse global options - int optionInd = 0; - int option; - for (;;) { - option = getopt_long_only(argc, argv, "+vp:X:t:i:o:l:a:", longOptions, &optionInd); - if (option == -1) { - break; - } - switch(option) { - // cases without short option - case 0: { - break; - } - // cases with short-hand options - case 'v': - verbose = true; - break; - case 't': - outType = optarg; - break; - case 'p': - pluginPath = optarg; - break; - case 'i': - inputFile = optarg; - break; - case 'a': - annotatedFile = optarg; - break; - case 'X': { - std::list extension = tokenize(optarg, '='); - if (extension.size() != 2) - printUsageAndExit(argv[0]); - std::string key = boost::trim_copy(*(extension.begin())); - std::string value = boost::trim_copy(*(++extension.begin())); - extensions.insert(std::pair(key, value)); - } - break; - case 'o': - outputFile = optarg; - extensions.insert(std::pair("outputFile", outputFile)); - break; - case 'l': - break; - case '?': { - break; - } - default: - break; - } - } - - // make sure given annotation options are available in the environment - if(ANNOTATE("USCXML_ANNOTATE_GLOBAL_STATE_STEP", "step")) - setenv("USCXML_ANNOTATE_GLOBAL_STATE_STEP", "YES", 1); - - if (ANNOTATE("USCXML_ANNOTATE_GLOBAL_TRANS_PRIO", "priority")) - setenv("USCXML_ANNOTATE_GLOBAL_TRANS_PRIO", "YES", 1); - - if (ANNOTATE("USCXML_ANNOTATE_VERBOSE_COMMENTS", "verbose")) - setenv("USCXML_ANNOTATE_VERBOSE_COMMENTS", "YES", 1); - - if (ANNOTATE("USCXML_ANNOTATE_TRANS_EXITSET", "exitset")) - setenv("USCXML_ANNOTATE_TRANS_EXITSET", "YES", 1); - - if (ANNOTATE("USCXML_ANNOTATE_TRANS_DOMAIN", "domain")) - setenv("USCXML_ANNOTATE_TRANS_DOMAIN", "YES", 1); - - if (ANNOTATE("USCXML_ANNOTATE_TRANS_CONFLICTS", "conflicts")) - setenv("USCXML_ANNOTATE_TRANS_CONFLICTS", "YES", 1); - - if (ANNOTATE("USCXML_ANNOTATE_TRANS_ENTRYSET", "entryset")) - setenv("USCXML_ANNOTATE_TRANS_ENTRYSET", "YES", 1); - - if(ANNOTATE("USCXML_ANNOTATE_GLOBAL_TRANS_MEMBERS", "members")) - setenv("USCXML_ANNOTATE_GLOBAL_TRANS_MEMBERS", "YES", 1); - - if(ANNOTATE("USCXML_ANNOTATE_GLOBAL_TRANS_SENDS", "sends")) - setenv("USCXML_ANNOTATE_GLOBAL_TRANS_SENDS", "YES", 1); - - if(ANNOTATE("USCXML_ANNOTATE_GLOBAL_TRANS_RAISES", "raises")) - setenv("USCXML_ANNOTATE_GLOBAL_TRANS_RAISES", "YES", 1); - - if(ANNOTATE("USCXML_ANNOTATE_PROGRESS", "progress")) - setenv("USCXML_ANNOTATE_PROGRESS", "YES", 1); - - if(ANNOTATE("USCXML_ANNOTATE_NOCOMMENT", "nocomment")) - setenv("USCXML_ANNOTATE_NOCOMMENT", "YES", 1); - - -// if (outType.length() == 0 && outputFile.length() > 0) { -// // try to get type from outfile extension -// size_t dotPos = outputFile.find_last_of("."); -// if (dotPos != std::string::npos) { -// outType= outputFile.substr(dotPos + 1); -// } -// } - -// if (outType.length() == 0) -// printUsageAndExit(argv[0]); - - if (outType != "flat" && - outType != "scxml" && - outType != "pml" && - outType != "c" && - outType != "vhdl" && - outType != "java" && - outType != "min" && - std::find(options.begin(), options.end(), "priority") == options.end() && - std::find(options.begin(), options.end(), "domain") == options.end() && - std::find(options.begin(), options.end(), "conflicts") == options.end() && - std::find(options.begin(), options.end(), "exitset") == options.end() && - std::find(options.begin(), options.end(), "entryset") == options.end()) - printUsageAndExit(argv[0]); - - // register plugins - if (pluginPath.length() > 0) { - Factory::setDefaultPluginPath(pluginPath); - } - - // start HTTP server - HTTPServer::getInstance(30444, 30445, NULL); - - Interpreter interpreter; - try { - if (inputFile.size() == 0 || inputFile == "-") { - LOGD(USCXML_INFO) << "Reading SCXML from STDIN" << std::endl; - std::stringstream ss; - std::string line; - while (std::getline(std::cin, line)) { - ss << line; - } - URL tmp("anonymous.scxml"); - tmp = URL::resolveWithCWD(tmp); - interpreter = Interpreter::fromXML(ss.str(), tmp); - } else { - interpreter = Interpreter::fromURL(inputFile); - } - } 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 = URL::resolveWithCWD(tmp); - std::string content = tmp.getInContent(); - - std::string inlineBeginMarker = "INLINE SCXML BEGIN\n"; - std::string inlineEndMarker = "\nINLINE SCXML END"; - - size_t inlineSCXMLBegin = content.find(inlineBeginMarker); - if (inlineSCXMLBegin != std::string::npos) { - inlineSCXMLBegin += inlineBeginMarker.size(); - size_t inlineSCXMLEnd = content.find(inlineEndMarker); - std::string inlineSCXMLContent = content.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) { - LOGD(USCXML_ERROR) << "Cannot create interpreter from " << inputFile << std::endl; - exit(EXIT_FAILURE); - - } - - try { - if (verbose) { - std::list issues = interpreter.validate(); - for (std::list::iterator issueIter = issues.begin(); issueIter != issues.end(); issueIter++) { - std::cerr << *issueIter << std::endl; - } - } - - Transformer transformer; - if (outType == "c") { - transformer = ChartToC::transform(interpreter); - transformer.setExtensions(extensions); - transformer.setOptions(options); - - if (outputFile.size() == 0 || outputFile == "-") { - transformer.writeTo(std::cout); - } else { - std::ofstream outStream; - outStream.open(outputFile.c_str()); - transformer.writeTo(outStream); - outStream.close(); - } - } - - if (outType == "java") { - transformer = ChartToJava::transform(interpreter); - transformer.setExtensions(extensions); - transformer.setOptions(options); - - if (outputFile.size() == 0 || outputFile == "-") { - transformer.writeTo(std::cout); - } else { - std::ofstream outStream; - outStream.open(outputFile.c_str()); - transformer.writeTo(outStream); - outStream.close(); - } - } - - if (outType == "vhdl") { - transformer = ChartToVHDL::transform(interpreter); - transformer.setExtensions(extensions); - transformer.setOptions(options); - - if (outputFile.size() == 0 || outputFile == "-") { - transformer.writeTo(std::cout); - } else { - std::ofstream outStream; - outStream.open(outputFile.c_str()); - transformer.writeTo(outStream); - outStream.close(); - } - } - - if (outType == "pml") { - transformer = ChartToPromela::transform(interpreter); - transformer.setExtensions(extensions); - transformer.setOptions(options); - - if (outputFile.size() == 0 || outputFile == "-") { - transformer.writeTo(std::cout); - } else { - std::ofstream outStream; - outStream.open(outputFile.c_str()); - transformer.writeTo(outStream); - outStream.close(); - } - } - -// if (outType == "tex") { -// if (outputFile.size() == 0 || outputFile == "-") { -// ChartToTex::transform(interpreter).writeTo(std::cout); -// } else { -// std::ofstream outStream; -// outStream.open(outputFile.c_str()); -// ChartToTex::transform(interpreter).writeTo(outStream); -// outStream.close(); -// } -// exit(EXIT_SUCCESS); -// } - -// if (outType == "flat") { -// if (outputFile.size() == 0 || outputFile == "-") { -// ChartToFlatSCXML::transform(interpreter).writeTo(std::cout); -// } else { -// std::ofstream outStream; -// outStream.open(outputFile.c_str()); -// ChartToFlatSCXML::transform(interpreter).writeTo(outStream); -// outStream.close(); -// } -// exit(EXIT_SUCCESS); -// } - -// if (outType == "min") { -// if (outputFile.size() == 0 || outputFile == "-") { -// ChartToMinimalSCXML::transform(interpreter).writeTo(std::cout); -// } else { -// std::ofstream outStream; -// outStream.open(outputFile.c_str()); -// ChartToMinimalSCXML::transform(interpreter).writeTo(outStream); -// outStream.close(); -// } -// exit(EXIT_SUCCESS); -// } - - if (annotatedFile.size() > 0) { - std::ofstream outStream; - outStream.open(annotatedFile.c_str()); - outStream << (*transformer.getImpl()->getDocument()); - outStream.close(); - - } - - - } catch (Event e) { - std::cout << e << std::endl; - return EXIT_FAILURE; - } catch (const std::exception &e) { - std::cout << e.what() << std::endl; - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} diff --git a/contrib/cmake/CPackUSCXML.cmake b/contrib/cmake/CPackUSCXML.cmake index 2a6f88b..e9bc5ec 100644 --- a/contrib/cmake/CPackUSCXML.cmake +++ b/contrib/cmake/CPackUSCXML.cmake @@ -146,6 +146,11 @@ set(CPACK_DEBIAN_PACKAGE_NAME "uscxml") set(CPACK_RPM_PACKAGE_NAME "uscxml") set(CPACK_RPM_PACKAGE_LICENSE "Simplified BSD") +######################################## +# CMake Modules for clients +######################################## + +install(FILES ${PROJECT_SOURCE_DIR}/contrib/cmake/FindUSCXML.cmake DESTINATION share/uscxml/cmake COMPONENT library) ######################################## # Describe layout of package diff --git a/contrib/cmake/FindUSCXML.cmake b/contrib/cmake/FindUSCXML.cmake new file mode 100644 index 0000000..bf3605d --- /dev/null +++ b/contrib/cmake/FindUSCXML.cmake @@ -0,0 +1,84 @@ +# - Find USCXML +# This module checks if uSCXML is installed and determines where the +# include files and libraries are. This code sets the following +# variables: +# +# USCXML_INCLUDE_DIR = The full path to the uscxml headers +# USCXML_LIBRARIES = All uscxml libraries for release and debug builds +# +# Example: +# find_package(USCXML REQUIRED) +# include_directories(${USCXML_INCLUDE_DIR}) +# + +################################################### +# where to search for uscxml headers and libraries +################################################### +set(_USCXML_LIB_SEARCHPATH + ${USCXML_LIBRARY_ROOT} + "/usr/local" + "/opt/local" + "C:/Program Files (x86)/uSCXML" + "C:/Program Files/uSCXML" +) + +################################################### +# find the uSCXML header files +################################################### +FIND_PATH(USCXML_INCLUDE_DIR uscxml/uscxml.h + PATH_SUFFIXES include + PATHS ${_USCXML_LIB_SEARCHPATH} ${USCXML_HEADER_ROOT} + ENV USCXML_INCLUDE_DIR +) + + +set(USCXML_LIBRARIES) +# prefer MinSizeRel libraries +FIND_LIBRARY(USCXML_LIBRARY_RELEASE + PATH_SUFFIXES lib + NAMES uscxml_s + PATHS ${_USCXML_LIB_SEARCHPATH} + ENV USCXML_LIB_DIR +) +if (USCXML_LIBRARY_RELEASE) + list(APPEND USCXML_LIBRARIES optimized ${USCXML_LIBRARY_RELEASE}) +else() + # if no minsize libraries were found try normal release + FIND_LIBRARY(USCXML_LIBRARY_RELEASE + PATH_SUFFIXES lib + NAMES uscxml + PATHS ${_USCXML_LIB_SEARCHPATH} + ENV USCXML_LIB_DIR + ) + if (USCXML_LIBRARY_RELEASE) + list(APPEND USCXML_LIBRARIES optimized USCXML_LIBRARY_RELEASE) + endif() +endif() + +# prefer release with debug libraries +FIND_LIBRARY(USCXML_LIBRARY_DEBUG + PATH_SUFFIXES lib + NAMES uscxml_rd + PATHS ${_USCXML_LIB_SEARCHPATH} + ENV USCXML_LIB_DIR +) +if ("${USCXML_LIBRARY_DEBUG}") + list(APPEND USCXML_LIBRARIES debug ${USCXML_LIBRARY_DEBUG}) +else() + # go for normal debug libraries insteaf + FIND_LIBRARY(USCXML_LIBRARY_DEBUG + PATH_SUFFIXES lib + NAMES uscxml_d + PATHS ${_USCXML_LIB_SEARCHPATH} + ENV USCXML_LIB_DIR + ) + if ("${USCXML_LIBRARY_DEBUG}") + list(APPEND USCXML_LIBRARIES debug USCXML_LIBRARY_DEBUG) + endif() +endif() + + + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(USCXML DEFAULT_MSG USCXML_LIBRARIES USCXML_INCLUDE_DIR) +MARK_AS_ADVANCED(USCXML_INCLUDE_DIR USCXML_LIBRARIES) diff --git a/docs/BENCHMARKS.md b/docs/BENCHMARKS.md new file mode 100644 index 0000000..685c287 --- /dev/null +++ b/docs/BENCHMARKS.md @@ -0,0 +1,26 @@ +# Benchmarks + +We did conceive a [series of benchmark](https://github.com/tklab-tud/uscxml/tree/master/test/benchmarks) SCXML documents to evaluate the performance of the various SCXML implementations. The state-charts in the benchmarks are completely artificial and bear no resemblance to real-world state-charts. However, they may provide a general guidance to get an impression about the performance of the different implementations. + +The state-charts each stress a specific feature of any SCXML `microstep(T)` implementation. Each contains a state `mark` that is continuously entered and exited as part of a sequence of spontaneous microsteps and measures the entries per second. For every implementation, the [benchmark is run](https://github.com/tklab-tud/uscxml/blob/master/contrib/benchmarks/run.sh) for a number of seconds and the iterations per seconds are averaged. The benchmarks exist in increasing complexity from very simple with, e.g., 4 states nested in a depth of 4 compounds up until 512 for state-charts with > 250.000 states. + +**Note:** If you are the author / maintainer of one of the SCXML implementations being benchmarked below and feel that I misrepresent your implementation's performance, post an issue and I will set things straight. + +**Note:** There are two `microstep(T)` implementations in uSCXML, namely `fast` and `large` with the former being the default for transpilation and the latter for interpretation. Both are being employed on an interpreted state-chart here. For the `fast` microstep implementation we measured the case with pre-calculated predicates. + +**Note:** The numbers for scxmlcc are necessarily for the compiled case and N/A if we could not compile the state-chart within the time limit. + +## Transitions + +The Transitions benchmark measures transition selection with many conflicting transitions enabled as part of a microstep. + +![Transition Benchmark](https://user-images.githubusercontent.com/980655/27858834-004c9c78-6177-11e7-8519-2f73f0ff9fb4.png) + +## LCCA +When exiting a state via a transition, the least-common compound ancestor (LCCA) of the transition's targets and source state has to be identified. This is a common operation and its runtime is proportional to the nesting depth if implemented respectively. + +![LCCA Benchmark](https://user-images.githubusercontent.com/980655/27858835-00527ecc-6177-11e7-85d2-46c83ad5ed71.png) + +## Conclusion + +uSCXML with either microstep implementation is consistently the fastest with the exception of the Transitions benchmark, where the compiled `scxmlcc` is degenerating slower for more complex state-charts. This may be due to compiler optimizations (or an incomplete implementation) and it would be interesting to compare `scxmlcc` against the transpiled ANSI-C code from `uscxml-transform`. However, the limiting factor here becomes the time required to transpile the state-chart or to compile the generated source file into an executable binary respectively. With regard to huge state-charts, the large microstep implementation of `uSCXML` performs best and retains acceptable performance throughout the range of benchmarks, only surpassed by the fast implementation for smaller complexities. diff --git a/examples/cpp/library/lambdas/CMakeLists.txt b/examples/cpp/library/lambdas/CMakeLists.txt new file mode 100644 index 0000000..c062e64 --- /dev/null +++ b/examples/cpp/library/lambdas/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 2.8.6) +project(simple-scxml) + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "/usr/local/share/uscxml/cmake/") +find_package(USCXML REQUIRED) + + +include_directories(${USCXML_INCLUDE_DIR}) +add_executable(simple main.cpp) +target_link_libraries(simple ${USCXML_LIBRARIES}) \ No newline at end of file diff --git a/examples/cpp/library/lambdas/main.cpp b/examples/cpp/library/lambdas/main.cpp new file mode 100644 index 0000000..316576b --- /dev/null +++ b/examples/cpp/library/lambdas/main.cpp @@ -0,0 +1,17 @@ +#include +#include "uscxml/uscxml.h" + +int main(int argc, char *argv[]) +{ + if (argc < 2) { + std::cerr << "Expected URL with SCXML document as first argument" << std::endl; + return -1; + } + + uscxml::Interpreter sc = uscxml::Interpreter::fromURL(argv[1]); + uscxml::InterpreterState state; + while ((state = sc.step()) != uscxml::USCXML_FINISHED) { + } + + return 0; +} diff --git a/examples/cpp/library/simple/CMakeLists.txt b/examples/cpp/library/simple/CMakeLists.txt new file mode 100644 index 0000000..c062e64 --- /dev/null +++ b/examples/cpp/library/simple/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 2.8.6) +project(simple-scxml) + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "/usr/local/share/uscxml/cmake/") +find_package(USCXML REQUIRED) + + +include_directories(${USCXML_INCLUDE_DIR}) +add_executable(simple main.cpp) +target_link_libraries(simple ${USCXML_LIBRARIES}) \ No newline at end of file diff --git a/examples/cpp/library/simple/main.cpp b/examples/cpp/library/simple/main.cpp new file mode 100644 index 0000000..316576b --- /dev/null +++ b/examples/cpp/library/simple/main.cpp @@ -0,0 +1,17 @@ +#include +#include "uscxml/uscxml.h" + +int main(int argc, char *argv[]) +{ + if (argc < 2) { + std::cerr << "Expected URL with SCXML document as first argument" << std::endl; + return -1; + } + + uscxml::Interpreter sc = uscxml::Interpreter::fromURL(argv[1]); + uscxml::InterpreterState state; + while ((state = sc.step()) != uscxml::USCXML_FINISHED) { + } + + return 0; +} diff --git a/examples/cpp/transpiled/arduino/WaterPump.cxx b/examples/cpp/transpiled/arduino/WaterPump.cxx new file mode 100644 index 0000000..01f4cfa --- /dev/null +++ b/examples/cpp/transpiled/arduino/WaterPump.cxx @@ -0,0 +1,170 @@ +// Resources: +// https://www.avrprogrammers.com/howto/atmega328-power +// https://github.com/PaulStoffregen/CapacitiveSensor +// https://de.wikipedia.org/wiki/Faustformelverfahren_%28Automatisierungstechnik%29 +// http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/ +// google://SCC3 for conformal coating + +#include +#include + + +#define USCXML_NO_HISTORY + +#define LED 13 // LED pin on the Arduino Nano +#define LIGHT A7 // 1:10 voltage divider soldered into the solar panel +#define LIGHT_THRES 300 // do not actuate beneath this brightness +#define MEASURE_INTERVAL SLEEP_1S // time between cycles +#define DARK_SLEEP_CYCLES 1 + +#define PUMP_ON LOW // Setting an output to LOW will trigger the relais +#define PUMP_OFF HIGH + +#define ROLLOFF 0.8 // exponential smoothing for sensor readings + +float soil[4] = { 0, 0, 0, 0 }; // smoothed sensor readings from the capacitive sensors +int pump[4] = { A0, A1, A2, A3 }; // we abuse analog pins as digital output +int activePump = -1; + +int thrs[4] = { 1400, 1400, 1400, 1400 }; // start pumping below these values + +CapacitiveSensor bed[4] = { // Pins where the capacitive sensors are connected + CapacitiveSensor(3, 2), + CapacitiveSensor(5, 4), + CapacitiveSensor(7, 6), + CapacitiveSensor(9, 8) +}; +char readCapSense = 0; // Whether the capsense invoker is active + +struct data_t { + int light; +}; +struct event_t { + const char* name; + struct data_t data; +}; + +// the various events +long pumpRemain = 0; +struct event_t _eventIdle = { + name: "idle" +}; +struct event_t _eventLight = { + name: "light" +}; +struct event_t _eventPump = { + name: "pump" +}; +struct event_t* _event; + +#include "stateMachine.c" + +uscxml_ctx ctx; + +/* state chart is invoking something */ +static int invoke(const uscxml_ctx* ctx, + const uscxml_state* s, + const uscxml_elem_invoke* invocation, + unsigned char uninvoke) { + if (strcmp(invocation->type, "pump") == 0) { + int pumpId = atoi(invocation->id); + digitalWrite(pump[pumpId], uninvoke == 0 ? PUMP_ON : PUMP_OFF); + } else if (strcmp(invocation->type, "capsense") == 0) { + readCapSense = uninvoke; + } +} + +/* is the event matching */ +static int matched(const uscxml_ctx* ctx, + const uscxml_transition* transition, + const void* event) { + // we ignore most event name matching rules here + return strcmp(transition->event, ((const struct event_t*)event)->name) == 0; +} + +static int send(const uscxml_ctx* ctx, const uscxml_elem_send* send) { + if (send->delay > 0) + pumpRemain = send->delay; + return USCXML_ERR_OK; +} + +static void* dequeueExternal(const uscxml_ctx* ctx) { + // we will only call step when we have an event + void* tmp = _event; + _event = NULL; + return tmp; +} + +static bool isInState(const char* stateId) { + for (size_t i = 0; i < ctx.machine->nr_states; i++) { + if (ctx.machine->states[i].name && + strcmp(ctx.machine->states[i].name, stateId) == 0 && + BIT_HAS(i, ctx.config)) { + return true; + } + } + + return false; +} + +void setup() { + // initilize the state chart + memset(&ctx, 0, sizeof(uscxml_ctx)); + ctx.machine = &USCXML_MACHINE; + ctx.invoke = invoke; + ctx.is_matched = matched; + ctx.dequeue_external = dequeueExternal; + ctx.exec_content_send = send; + + int err = USCXML_ERR_OK; + + // run until first stable config + while((err = uscxml_step(&ctx)) != USCXML_ERR_IDLE) {} +} + + +void loop() { + digitalWrite(LED, HIGH); + + int err = USCXML_ERR_OK; + + if (readCapSense) { + // capsense invoker is active + for (int i = 0; i < 4; ++i) { + int cap = bed[i].capacitiveSensor(50); + if (cap > 0) { + soil[i] = ROLLOFF * soil[i] + (1 - ROLLOFF) * (cap - thrs[i]); + } + } + } + + _eventLight.data.light = analogRead(LIGHT); + _event = &_eventLight; + while((err = uscxml_step(&ctx)) != USCXML_ERR_IDLE) {} + + if (isInState("dark")) { + LowPower.powerDown(MEASURE_INTERVAL, ADC_OFF, BOD_OFF); + return; + } + + if (isInState("light")) { + if (false) { + } else if (isInState("pumping")) { + // is time elapsed already? + if (pumpRemain == 0) { + _event = &_eventIdle; + while((err = uscxml_step(&ctx)) != USCXML_ERR_IDLE) {} + } + } else if (isInState("idle")) { + // check is we need to pump + _event = &_eventPump; + while((err = uscxml_step(&ctx)) != USCXML_ERR_IDLE) {} + } + } + + pumpRemain = (pumpRemain >= 8000) ? pumpRemain - 8000 : 0; + + digitalWrite(LED, LOW); + LowPower.powerDown(MEASURE_INTERVAL, ADC_OFF, BOD_OFF); + +} diff --git a/examples/cpp/transpiled/arduino/WaterPump.scxml b/examples/cpp/transpiled/arduino/WaterPump.scxml new file mode 100644 index 0000000..a7d8bad --- /dev/null +++ b/examples/cpp/transpiled/arduino/WaterPump.scxml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/cpp/transpiled/arduino/stateMachine.c b/examples/cpp/transpiled/arduino/stateMachine.c new file mode 100644 index 0000000..a74535b --- /dev/null +++ b/examples/cpp/transpiled/arduino/stateMachine.c @@ -0,0 +1,1291 @@ +/** + Generated from source: + file:///Users/sradomski/Documents/Electronics/WaterPump/WaterPump.scxml +*/ + +#ifndef USCXML_NO_STDTYPES_H +# include /* explicit types */ +#endif +#include /* 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 2 +#endif + +/** + * USCXML_MAX_NR_TRANS_BYTES + * same as above but for transitions. + */ + +#ifndef USCXML_MAX_NR_TRANS_BYTES +# define USCXML_MAX_NR_TRANS_BYTES 1 +#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_assign uscxml_elem_assign; +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); +typedef int (*is_matched_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 uscxml_elem_assign* assign); +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 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 an element + */ +struct uscxml_elem_assign { + const char* location; + 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 unsigned char children[USCXML_MAX_NR_STATES_BYTES]; /* all children */ + const unsigned char completion[USCXML_MAX_NR_STATES_BYTES]; /* default completion */ + const unsigned 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 element + */ +struct uscxml_transition { + const USCXML_NR_STATES_TYPE source; + const unsigned char target[USCXML_MAX_NR_STATES_BYTES]; + const char* event; + const char* condition; + const is_enabled_t is_enabled; + const exec_content_t on_transition; + const unsigned char type; + const unsigned char conflicts[USCXML_MAX_NR_TRANS_BYTES]; + const unsigned char exit_set[USCXML_MAX_NR_STATES_BYTES]; +}; + +/** + * All information pertaining to a element + */ +struct uscxml_elem_foreach { + const char* array; + const char* item; + const char* index; +}; + +/** + * All information pertaining to a 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 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 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 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; + unsigned long 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; + + unsigned char config[USCXML_MAX_NR_STATES_BYTES]; /* Make sure these macros specify a sufficient size */ + unsigned char history[USCXML_MAX_NR_STATES_BYTES]; + unsigned char invocations[USCXML_MAX_NR_STATES_BYTES]; + unsigned char initialized_data[USCXML_MAX_NR_STATES_BYTES]; + + void* user_data; + void* event; + + dequeue_internal_t dequeue_internal; + dequeue_external_t dequeue_external; + is_matched_t is_matched; + 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_4FC60039__machine; + +#ifndef USCXML_NO_ELEM_INFO + +static const uscxml_elem_send _uscxml_4FC60039__elem_sends[1] = { + { + /* event */ "idle", + /* eventexpr */ NULL, + /* target */ NULL, + /* targetexpr */ NULL, + /* type */ NULL, + /* typeexpr */ NULL, + /* id */ NULL, + /* idlocation */ NULL, + /* delay */ 8000, + /* delayexpr */ NULL, + /* namelist */ NULL, + /* content */ NULL, + /* contentexpr */ NULL, + /* params */ NULL + } +}; + +static const uscxml_elem_donedata _uscxml_4FC60039__elem_donedatas[1] = { + /* source, content, contentexpr, params */ + { 0, NULL, NULL, NULL } +}; + +#endif + +#ifndef USCXML_NO_ELEM_INFO + +static const uscxml_elem_invoke _uscxml_4FC60039__elem_invokes[5] = { + { + /* machine */ NULL, + /* type */ "capsense", + /* typeexpr */ NULL, + /* src */ NULL, + /* srcexpr */ NULL, + /* id */ "cap", + /* idlocation */ NULL, + /* sourcename */ "light", + /* namelist */ NULL, + /* autoforward */ 0, + /* params */ NULL, + /* finalize */ NULL, + /* content */ NULL, + /* contentexpr */ NULL, + }, + { + /* machine */ NULL, + /* type */ "pump", + /* typeexpr */ NULL, + /* src */ NULL, + /* srcexpr */ NULL, + /* id */ "1", + /* idlocation */ NULL, + /* sourcename */ "pump1", + /* namelist */ NULL, + /* autoforward */ 0, + /* params */ NULL, + /* finalize */ NULL, + /* content */ NULL, + /* contentexpr */ NULL, + }, + { + /* machine */ NULL, + /* type */ "pump", + /* typeexpr */ NULL, + /* src */ NULL, + /* srcexpr */ NULL, + /* id */ "2", + /* idlocation */ NULL, + /* sourcename */ "pump2", + /* namelist */ NULL, + /* autoforward */ 0, + /* params */ NULL, + /* finalize */ NULL, + /* content */ NULL, + /* contentexpr */ NULL, + }, + { + /* machine */ NULL, + /* type */ "pump", + /* typeexpr */ NULL, + /* src */ NULL, + /* srcexpr */ NULL, + /* id */ "3", + /* idlocation */ NULL, + /* sourcename */ "pump3", + /* namelist */ NULL, + /* autoforward */ 0, + /* params */ NULL, + /* finalize */ NULL, + /* content */ NULL, + /* contentexpr */ NULL, + }, + { + /* machine */ NULL, + /* type */ "pump", + /* typeexpr */ NULL, + /* src */ NULL, + /* srcexpr */ NULL, + /* id */ "4", + /* idlocation */ NULL, + /* sourcename */ "pump4", + /* namelist */ NULL, + /* autoforward */ 0, + /* params */ NULL, + /* finalize */ NULL, + /* content */ NULL, + /* contentexpr */ NULL, + } +}; + +#endif + +#ifndef USCXML_NO_EXEC_CONTENT + +static int _uscxml_4FC60039__global_script_0(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) { + int err = USCXML_ERR_OK; + + pinMode(LED, OUTPUT); + for (char i = 0; i < 4; ++i) { + pinMode(pump[i], OUTPUT); + digitalWrite(pump[i], PUMP_OFF); + bed[i].set_CS_AutocaL_Millis(0xFFFFFFFF); + } + return USCXML_ERR_OK; +} +static int _uscxml_4FC60039__global_script(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) { + _uscxml_4FC60039__global_script_0(ctx, state, event); + return USCXML_ERR_OK; +} + +static int _uscxml_4FC60039__dark_on_entry_0(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) { + int err = USCXML_ERR_OK; + + for (char i = 0; i < 4; ++i) { + digitalWrite(pump[i], PUMP_OFF); + } + return USCXML_ERR_OK; +} + +static int _uscxml_4FC60039__dark_on_entry(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) { + _uscxml_4FC60039__dark_on_entry_0(ctx, state, event); + return USCXML_ERR_OK; +} + +static int _uscxml_4FC60039__light_invoke(const uscxml_ctx* ctx, const uscxml_state* s, const uscxml_elem_invoke* invocation, unsigned char uninvoke) { + ctx->invoke(ctx, s, &_uscxml_4FC60039__elem_invokes[0], uninvoke); + + return USCXML_ERR_OK; +} +static int _uscxml_4FC60039__pumping_on_entry_0(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) { + int err = USCXML_ERR_OK; + if likely(ctx->exec_content_send != NULL) { + if ((ctx->exec_content_send(ctx, &_uscxml_4FC60039__elem_sends[0])) != USCXML_ERR_OK) return err; + } else { + return USCXML_ERR_MISSING_CALLBACK; + } + return USCXML_ERR_OK; +} + +static int _uscxml_4FC60039__pumping_on_entry(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) { + _uscxml_4FC60039__pumping_on_entry_0(ctx, state, event); + return USCXML_ERR_OK; +} + +static int _uscxml_4FC60039__pump1_invoke(const uscxml_ctx* ctx, const uscxml_state* s, const uscxml_elem_invoke* invocation, unsigned char uninvoke) { + ctx->invoke(ctx, s, &_uscxml_4FC60039__elem_invokes[1], uninvoke); + + return USCXML_ERR_OK; +} +static int _uscxml_4FC60039__pump2_invoke(const uscxml_ctx* ctx, const uscxml_state* s, const uscxml_elem_invoke* invocation, unsigned char uninvoke) { + ctx->invoke(ctx, s, &_uscxml_4FC60039__elem_invokes[2], uninvoke); + + return USCXML_ERR_OK; +} +static int _uscxml_4FC60039__pump3_invoke(const uscxml_ctx* ctx, const uscxml_state* s, const uscxml_elem_invoke* invocation, unsigned char uninvoke) { + ctx->invoke(ctx, s, &_uscxml_4FC60039__elem_invokes[3], uninvoke); + + return USCXML_ERR_OK; +} +static int _uscxml_4FC60039__pump4_invoke(const uscxml_ctx* ctx, const uscxml_state* s, const uscxml_elem_invoke* invocation, unsigned char uninvoke) { + ctx->invoke(ctx, s, &_uscxml_4FC60039__elem_invokes[4], uninvoke); + + return USCXML_ERR_OK; +} +static int _uscxml_4FC60039__dark_transition0_is_enabled(const uscxml_ctx* ctx, const uscxml_transition* transition) { + return (_event->data.light > LIGHT_THRES); +} +static int _uscxml_4FC60039__idle_transition0_is_enabled(const uscxml_ctx* ctx, const uscxml_transition* transition) { + return (soil[0] < 0 && soil[0] <= soil[1]); +} +static int _uscxml_4FC60039__idle_transition1_is_enabled(const uscxml_ctx* ctx, const uscxml_transition* transition) { + return (soil[1] < 0 && soil[1] <= soil[0]); +} +static int _uscxml_4FC60039__light_transition0_is_enabled(const uscxml_ctx* ctx, const uscxml_transition* transition) { + return (_event->data.light < LIGHT_THRES); +} +#endif + +#ifndef USCXML_NO_ELEM_INFO + +static const uscxml_state _uscxml_4FC60039__states[9] = { + { /* state number 0 */ + /* name */ NULL, + /* parent */ 0, + /* onentry */ NULL, + /* onexit */ NULL, + /* invoke */ NULL, + /* children */ { 0x06, 0x00 /* 011000000 */ }, + /* completion */ { 0x02, 0x00 /* 010000000 */ }, + /* ancestors */ { 0x00, 0x00 /* 000000000 */ }, + /* data */ NULL, + /* type */ USCXML_STATE_COMPOUND, + }, + { /* state number 1 */ + /* name */ "dark", + /* parent */ 0, + /* onentry */ _uscxml_4FC60039__dark_on_entry, + /* onexit */ NULL, + /* invoke */ NULL, + /* children */ { 0x00, 0x00 /* 000000000 */ }, + /* completion */ { 0x00, 0x00 /* 000000000 */ }, + /* ancestors */ { 0x01, 0x00 /* 100000000 */ }, + /* data */ NULL, + /* type */ USCXML_STATE_ATOMIC, + }, + { /* state number 2 */ + /* name */ "light", + /* parent */ 0, + /* onentry */ NULL, + /* onexit */ NULL, + /* invoke */ _uscxml_4FC60039__light_invoke, + /* children */ { 0x18, 0x00 /* 000110000 */ }, + /* completion */ { 0x08, 0x00 /* 000100000 */ }, + /* ancestors */ { 0x01, 0x00 /* 100000000 */ }, + /* data */ NULL, + /* type */ USCXML_STATE_COMPOUND, + }, + { /* state number 3 */ + /* name */ "idle", + /* parent */ 2, + /* onentry */ NULL, + /* onexit */ NULL, + /* invoke */ NULL, + /* children */ { 0x00, 0x00 /* 000000000 */ }, + /* completion */ { 0x00, 0x00 /* 000000000 */ }, + /* ancestors */ { 0x05, 0x00 /* 101000000 */ }, + /* data */ NULL, + /* type */ USCXML_STATE_ATOMIC, + }, + { /* state number 4 */ + /* name */ "pumping", + /* parent */ 2, + /* onentry */ _uscxml_4FC60039__pumping_on_entry, + /* onexit */ NULL, + /* invoke */ NULL, + /* children */ { 0xe0, 0x01 /* 000001111 */ }, + /* completion */ { 0x20, 0x00 /* 000001000 */ }, + /* ancestors */ { 0x05, 0x00 /* 101000000 */ }, + /* data */ NULL, + /* type */ USCXML_STATE_COMPOUND, + }, + { /* state number 5 */ + /* name */ "pump1", + /* parent */ 4, + /* onentry */ NULL, + /* onexit */ NULL, + /* invoke */ _uscxml_4FC60039__pump1_invoke, + /* children */ { 0x00, 0x00 /* 000000000 */ }, + /* completion */ { 0x00, 0x00 /* 000000000 */ }, + /* ancestors */ { 0x15, 0x00 /* 101010000 */ }, + /* data */ NULL, + /* type */ USCXML_STATE_ATOMIC, + }, + { /* state number 6 */ + /* name */ "pump2", + /* parent */ 4, + /* onentry */ NULL, + /* onexit */ NULL, + /* invoke */ _uscxml_4FC60039__pump2_invoke, + /* children */ { 0x00, 0x00 /* 000000000 */ }, + /* completion */ { 0x00, 0x00 /* 000000000 */ }, + /* ancestors */ { 0x15, 0x00 /* 101010000 */ }, + /* data */ NULL, + /* type */ USCXML_STATE_ATOMIC, + }, + { /* state number 7 */ + /* name */ "pump3", + /* parent */ 4, + /* onentry */ NULL, + /* onexit */ NULL, + /* invoke */ _uscxml_4FC60039__pump3_invoke, + /* children */ { 0x00, 0x00 /* 000000000 */ }, + /* completion */ { 0x00, 0x00 /* 000000000 */ }, + /* ancestors */ { 0x15, 0x00 /* 101010000 */ }, + /* data */ NULL, + /* type */ USCXML_STATE_ATOMIC, + }, + { /* state number 8 */ + /* name */ "pump4", + /* parent */ 4, + /* onentry */ NULL, + /* onexit */ NULL, + /* invoke */ _uscxml_4FC60039__pump4_invoke, + /* children */ { 0x00, 0x00 /* 000000000 */ }, + /* completion */ { 0x00, 0x00 /* 000000000 */ }, + /* ancestors */ { 0x15, 0x00 /* 101010000 */ }, + /* data */ NULL, + /* type */ USCXML_STATE_ATOMIC, + } +}; + +#endif + +#ifndef USCXML_NO_ELEM_INFO + +static const uscxml_transition _uscxml_4FC60039__transitions[5] = { + { /* transition number 0 with priority 0 + target: light + */ + /* source */ 1, + /* target */ { 0x04, 0x00 /* 001000000 */ }, + /* event */ "light", + /* condition */ NULL, + /* is_enabled */ _uscxml_4FC60039__dark_transition0_is_enabled, + /* ontrans */ NULL, + /* type */ 0, + /* conflicts */ { 0x1f /* 11111 */ }, + /* exit set */ { 0xfe, 0x01 /* 011111111 */ } + }, + { /* transition number 2 with priority 1 + target: pump1 + */ + /* source */ 3, + /* target */ { 0x20, 0x00 /* 000001000 */ }, + /* event */ "pump", + /* condition */ NULL, + /* is_enabled */ _uscxml_4FC60039__idle_transition0_is_enabled, + /* ontrans */ NULL, + /* type */ 0, + /* conflicts */ { 0x1f /* 11111 */ }, + /* exit set */ { 0xf8, 0x01 /* 000111111 */ } + }, + { /* transition number 3 with priority 2 + target: pump2 + */ + /* source */ 3, + /* target */ { 0x40, 0x00 /* 000000100 */ }, + /* event */ "pump", + /* condition */ NULL, + /* is_enabled */ _uscxml_4FC60039__idle_transition1_is_enabled, + /* ontrans */ NULL, + /* type */ 0, + /* conflicts */ { 0x1f /* 11111 */ }, + /* exit set */ { 0xf8, 0x01 /* 000111111 */ } + }, + { /* transition number 4 with priority 3 + target: idle + */ + /* source */ 4, + /* target */ { 0x08, 0x00 /* 000100000 */ }, + /* event */ "idle", + /* condition */ NULL, + /* is_enabled */ NULL, + /* ontrans */ NULL, + /* type */ 0, + /* conflicts */ { 0x1f /* 11111 */ }, + /* exit set */ { 0xf8, 0x01 /* 000111111 */ } + }, + { /* transition number 1 with priority 4 + target: dark + */ + /* source */ 2, + /* target */ { 0x02, 0x00 /* 010000000 */ }, + /* event */ "light", + /* condition */ NULL, + /* is_enabled */ _uscxml_4FC60039__light_transition0_is_enabled, + /* ontrans */ NULL, + /* type */ 0, + /* conflicts */ { 0x1f /* 11111 */ }, + /* exit set */ { 0xfe, 0x01 /* 011111111 */ } + } +}; + +#endif + +#ifndef USCXML_NO_ELEM_INFO + +#ifndef USCXML_MACHINE +# define USCXML_MACHINE _uscxml_4FC60039__machine +#endif +#define USCXML_MACHINE_0 _uscxml_4FC60039__machine +#define USCXML_MACHINE_WATERPUMP_SCXML _uscxml_4FC60039__machine + +const uscxml_machine _uscxml_4FC60039__machine = { + /* flags */ 0, + /* nr_states */ 9, + /* nr_transitions */ 5, + /* name */ "WaterPump.scxml", + /* datamodel */ "native", + /* uuid */ "4FC600390B3422E11879652D26725E30", + /* states */ &_uscxml_4FC60039__states[0], + /* transitions */ &_uscxml_4FC60039__transitions[0], + /* parent */ NULL, + /* donedata */ &_uscxml_4FC60039__elem_donedatas[0], + /* script */ _uscxml_4FC60039__global_script + +}; + +#endif + +#ifdef USCXML_VERBOSE +/** + * Print name of states contained in a (debugging). + */ +static void printStateNames(const uscxml_ctx* ctx, const unsigned 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 unsigned char* a, size_t length) { + size_t i; + const char* seperator = ""; + for (i = 0; i < length; i++) { + if (BIT_HAS(i, a)) { + printf("%s%zu", 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 unsigned char* a, const unsigned 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(unsigned 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(unsigned 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(unsigned char* dest, const unsigned 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(unsigned char* dest, const unsigned char* source, size_t i) { + while(i--) { + dest[i] = source[i]; + } +} + +/** + * Unset bits from mask in dest. + */ +static void bit_and_not(unsigned char* dest, const unsigned char* mask, size_t i) { + while(i--) { + dest[i] &= ~mask[i]; + } +} + +/** + * Set bits from mask in dest. + */ +static void bit_and(unsigned char* dest, const unsigned 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; + unsigned char conflicts [USCXML_MAX_NR_TRANS_BYTES]; + unsigned char trans_set [USCXML_MAX_NR_TRANS_BYTES]; + unsigned char target_set [USCXML_MAX_NR_STATES_BYTES]; + unsigned char exit_set [USCXML_MAX_NR_STATES_BYTES]; + unsigned char entry_set [USCXML_MAX_NR_STATES_BYTES]; + unsigned 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; + } + +DEQUEUE_EVENT: + 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->event == NULL || ctx->is_matched(ctx, &USCXML_GET_TRANS(i), ctx->event) > 0) && + (USCXML_GET_TRANS(i).condition == NULL || + USCXML_GET_TRANS(i).is_enabled(ctx, &USCXML_GET_TRANS(i)) > 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; + goto DEQUEUE_EVENT; + } + +#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; + } +#ifndef USCXML_NO_HISTORY + 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; + } +#endif + 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/src/apps/uscxml-browser.cpp b/src/apps/uscxml-browser.cpp new file mode 100644 index 0000000..dd0633b --- /dev/null +++ b/src/apps/uscxml-browser.cpp @@ -0,0 +1,132 @@ +#include "uscxml/config.h" +#include "uscxml/Interpreter.h" +#include "uscxml/InterpreterOptions.h" +#include "uscxml/debug/InterpreterIssue.h" +#include "uscxml/debug/DebuggerServlet.h" +#include "uscxml/interpreter/InterpreterMonitor.h" +#include "uscxml/util/DOM.h" + +#include "uscxml/interpreter/Logging.h" + +#include "uscxml/plugins/Factory.h" +#include "uscxml/server/HTTPServer.h" + + +int main(int argc, char** argv) { + using namespace uscxml; + +#if defined(HAS_SIGNAL_H) && !defined(WIN32) + signal(SIGPIPE, SIG_IGN); +#endif + + InterpreterOptions options = InterpreterOptions::fromCmdLine(argc, argv); + + if (!options) { + InterpreterOptions::printUsageAndExit(argv[0]); + } + + if (!options.validate) { + // setup HTTP server + HTTPServer::SSLConfig* sslConf = NULL; + if (options.certificate.length() > 0) { + sslConf = new HTTPServer::SSLConfig(); + sslConf->privateKey = options.certificate; + sslConf->publicKey = options.certificate; + sslConf->port = options.httpsPort; + + } else if (options.privateKey.length() > 0 && options.publicKey.length() > 0) { + sslConf = new HTTPServer::SSLConfig(); + sslConf->privateKey = options.privateKey; + sslConf->publicKey = options.publicKey; + sslConf->port = options.httpsPort; + + } + HTTPServer::getInstance(options.httpPort, options.wsPort, sslConf); + } + + if (options.pluginPath.length() > 0) { + Factory::setDefaultPluginPath(options.pluginPath); + } + + if (options.verbose) { + Factory::getInstance()->listComponents(); + } + + // instantiate and configure interpreters + std::list interpreters; + for(size_t i = 0; i < options.interpreters.size(); i++) { + +// InterpreterOptions* currOptions = options.interpreters[0].second; + std::string documentURL = options.interpreters[i].first; + + LOGD(USCXML_INFO) << "Processing " << documentURL << std::endl; + + try { + Interpreter interpreter = Interpreter::fromURL(documentURL); + if (interpreter) { + + if (options.validate) { + std::list issues = interpreter.validate(); + for (std::list::iterator issueIter = issues.begin(); issueIter != issues.end(); issueIter++) { + LOGD(USCXML_DEBUG) << "" << *issueIter << std::endl; + } + if (issues.size() == 0) { + LOGD(USCXML_DEBUG) << "No issues found" << std::endl; + } + + } + + if (options.verbose) { + StateTransitionMonitor* vm = new StateTransitionMonitor(); + vm->copyToInvokers(true); + interpreter.addMonitor(vm); + } + + interpreters.push_back(interpreter); + + } else { + LOGD(USCXML_ERROR) << "Cannot create interpreter from " << documentURL << std::endl; + } + } catch (Event e) { + LOGD(USCXML_ERROR) << e << std::endl; + } + } + + if (options.validate) { + return EXIT_SUCCESS; + } + + if (options.withDebugger) { + DebuggerServlet* debugger; + debugger = new DebuggerServlet(); + debugger->copyToInvokers(true); + HTTPServer::getInstance()->registerServlet("/debug", debugger); + for (auto interpreter : interpreters) { + interpreter.addMonitor(debugger); + } + } + + // run interpreters + if (interpreters.size() > 0) { + try { + std::list::iterator interpreterIter = interpreters.begin(); + while (interpreters.size() > 0) { + while(interpreterIter != interpreters.end()) { + InterpreterState state = interpreterIter->step(); + if (state == USCXML_FINISHED) { + interpreterIter = interpreters.erase(interpreterIter); + } else { + interpreterIter++; + } + } + interpreterIter = interpreters.begin(); + } + } catch (Event e) { + LOGD(USCXML_ERROR) << e << std::endl; + } + } else if (options.withDebugger) { + while(true) + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + return EXIT_SUCCESS; +} diff --git a/src/apps/uscxml-browser.vbs b/src/apps/uscxml-browser.vbs new file mode 100644 index 0000000..fc8ea9a --- /dev/null +++ b/src/apps/uscxml-browser.vbs @@ -0,0 +1,177 @@ +' +' Description: VBScript/VBS open file dialog +' Compatible with most Windows platforms +' Author: wangye +' Website: http://wangye.org +' +' dir is the initial directory; if no directory is +' specified "Desktop" is used. +' filter is the file type filter; format "File type description|*.ext" +' +Public Function GetOpenFileName(dir, filter) + Const msoFileDialogFilePicker = 3 + + If VarType(dir) <> vbString Or dir="" Then + dir = CreateObject( "WScript.Shell" ).SpecialFolders( "Desktop" ) + End If + + If VarType(filter) <> vbString Or filter="" Then + filter = "All files|*.*" + End If + + Dim i,j, objDialog, TryObjectNames + TryObjectNames = Array( _ + "UserAccounts.CommonDialog", _ + "MSComDlg.CommonDialog", _ + "MSComDlg.CommonDialog.1", _ + "Word.Application", _ + "SAFRCFileDlg.FileOpen", _ + "InternetExplorer.Application" _ + ) + + On Error Resume Next + Err.Clear + + For i=0 To UBound(TryObjectNames) + Set objDialog = WSH.CreateObject(TryObjectNames(i)) + If Err.Number<>0 Then + Err.Clear + Else + Exit For + End If + Next + + Select Case i + Case 0,1,2 + ' 0. UserAccounts.CommonDialog XP Only. + ' 1.2. MSComDlg.CommonDialog MSCOMDLG32.OCX must registered. + If i=0 Then + objDialog.InitialDir = dir + Else + objDialog.InitDir = dir + End If + objDialog.Filter = filter + If objDialog.ShowOpen Then + GetOpenFileName = objDialog.FileName + End If + Case 3 + ' 3. Word.Application Microsoft Office must installed. + objDialog.Visible = False + Dim objOpenDialog, filtersInArray + filtersInArray = Split(filter, "|") + Set objOpenDialog = _ + objDialog.Application.FileDialog( _ + msoFileDialogFilePicker) + With objOpenDialog + .Title = "Open File(s):" + .AllowMultiSelect = False + .InitialFileName = dir + .Filters.Clear + For j=0 To UBound(filtersInArray) Step 2 + .Filters.Add filtersInArray(j), _ + filtersInArray(j+1), 1 + Next + If .Show And .SelectedItems.Count>0 Then + GetOpenFileName = .SelectedItems(1) + End If + End With + objDialog.Visible = True + objDialog.Quit + Set objOpenDialog = Nothing + Case 4 + ' 4. SAFRCFileDlg.FileOpen xp 2003 only + ' See http://www.robvanderwoude.com/vbstech_ui_fileopen.php + If objDialog.OpenFileOpenDlg Then + GetOpenFileName = objDialog.FileName + End If + Case 5 + + Dim IEVersion,IEMajorVersion, hasCompleted + hasCompleted = False + Dim shell + Set shell = CreateObject("WScript.Shell") + ' 下面获取IE版本 + IEVersion = shell.RegRead( _ + "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Version") + If InStr(IEVersion,".")>0 Then + ' 获取主版本号 + IEMajorVersion = CInt(Left(IEVersion, InStr(IEVersion,".")-1)) + If IEMajorVersion>7 Then + ' 如果版本号大于7,也就是大于IE7,则采取MSHTA方案 + ' Bypasses c:\fakepath\file.txt problem + ' http://pastebin.com/txVgnLBV + Dim fso + Set fso = CreateObject("Scripting.FileSystemObject") + + Dim tempFolder : Set tempFolder = fso.GetSpecialFolder(2) + Dim tempName : tempName = fso.GetTempName() + Dim tempFile : Set tempFile = tempFolder.CreateTextFile(tempName & ".hta") + Dim tempBaseName + tempBaseName = tempFolder & "\" & tempName + tempFile.Write _ + "" & _ + " " & _ + " Browse" & _ + " " & _ + " " & _ + " " & _ + " " & _ + " " & _ + "" + tempFile.Close + Set tempFile = Nothing + Set tempFolder = Nothing + shell.Run tempBaseName & ".hta", 1, True + Set tempFile = fso.OpenTextFile(tempBaseName & ".txt", 1) + GetOpenFileName = tempFile.ReadLine + tempFile.Close + fso.DeleteFile tempBaseName & ".hta" + fso.DeleteFile tempBaseName & ".txt" + Set tempFile = Nothing + Set fso = Nothing + hasCompleted = True ' 标记为已完成 + End If + End If + If Not hasCompleted Then + ' 5. InternetExplorer.Application IE must installed + objDialog.Navigate "about:blank" + Dim objBody, objFileDialog + Set objBody = _ + objDialog.document.getElementsByTagName("body")(0) + objBody.innerHTML = "" + while objDialog.Busy Or objDialog.ReadyState <> 4 + WScript.sleep 10 + Wend + Set objFileDialog = objDialog.document.all.fileDialog + objFileDialog.click + GetOpenFileName = objFileDialog.value + End If + objDialog.Quit + Set objFileDialog = Nothing + Set objBody = Nothing + Set shell = Nothing + Case Else + ' Sorry I cannot do that! + End Select + + Set objDialog = Nothing +End Function + +scxmlFile = GetOpenFileName(CreateObject("WScript.Shell").SpecialFolders("MyDocuments"), "All Files|*.*|SCXML Files|*.scxml") + +if scxmlFile <> "" then + set wshShell = WScript.CreateObject("WScript.Shell") + set objFs = WScript.CreateObject("Scripting.FileSystemObject") + wshShell.CurrentDirectory = objFs.GetParentFolderName(Wscript.ScriptFullName) +' WScript.Echo scxmlFile + wshShell.Run("mmi-browser.exe """ & scxmlFile & """") +end if \ No newline at end of file diff --git a/src/apps/uscxml-debugger.html b/src/apps/uscxml-debugger.html new file mode 100644 index 0000000..fa49554 --- /dev/null +++ b/src/apps/uscxml-debugger.html @@ -0,0 +1,2839 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + diff --git a/src/apps/uscxml-transform.cpp b/src/apps/uscxml-transform.cpp new file mode 100644 index 0000000..e99ed68 --- /dev/null +++ b/src/apps/uscxml-transform.cpp @@ -0,0 +1,385 @@ +#include "uscxml/config.h" +#include "uscxml/Interpreter.h" +#include "uscxml/util/String.h" +#include "uscxml/transform/ChartToC.h" +#include "uscxml/transform/ChartToJava.h" +#include "uscxml/transform/ChartToVHDL.h" +#include "uscxml/transform/ChartToPromela.h" + +#include + +#include +#include +#include + +#include "uscxml/plugins/Factory.h" +#include "uscxml/server/HTTPServer.h" +#include "getopt.h" + +#include "uscxml/interpreter/Logging.h" + +#define ANNOTATE(envKey, annotationParam) \ +envVarIsTrue(envKey) || std::find(options.begin(), options.end(), annotationParam) != options.end() + +void printUsageAndExit(const char* progName) { + // remove path from program name + std::string progStr(progName); + if (progStr.find_last_of(PATH_SEPERATOR) != std::string::npos) { + progStr = progStr.substr(progStr.find_last_of(PATH_SEPERATOR) + 1, progStr.length() - (progStr.find_last_of(PATH_SEPERATOR) + 1)); + } + + printf("%s version " USCXML_VERSION " (" CMAKE_BUILD_TYPE " build - " CMAKE_COMPILER_STRING ")\n", progStr.c_str()); + printf("Usage\n"); + printf("\t%s", progStr.c_str()); + printf(" [-t c|pml|flat|min] [-a {OPTIONS}] [-v] [-lN]"); +#ifdef BUILD_AS_PLUGINS + printf(" [-p pluginPath]"); +#endif + printf(" [-i URL] [-o FILE]"); + printf("\n"); + printf("Options\n"); + printf("\t-t c : convert to C program\n"); + printf("\t-t pml : convert to spin/promela program\n"); + printf("\t-t vhdl : convert to VHDL hardware description\n"); + printf("\t-t java : convert to Java classes\n"); + printf("\t-t flat : flatten to SCXML state-machine\n"); + printf("\t-a FILE : write annotated SCXML document for transformation\n"); + printf("\t-X {PARAMETER} : pass additional parameters to the transformation\n"); + printf("\t prefix=ID - prefix all symbols and identifiers with ID (-tc)\n"); + printf("\t-v : be verbose\n"); + printf("\t-lN : Set loglevel to N\n"); + printf("\t-i URL : Input file (defaults to STDIN)\n"); + printf("\t-o FILE : Output file (defaults to STDOUT)\n"); + printf("\n"); + exit(1); +} + +int main(int argc, char** argv) { + using namespace uscxml; + + bool verbose = false; + std::string outType; + std::string pluginPath; + std::string inputFile; + std::string annotatedFile; + std::string outputFile; + std::list options; + std::multimap extensions; + +#if defined(HAS_SIGNAL_H) && !defined(WIN32) + signal(SIGPIPE, SIG_IGN); +#endif + + optind = 0; + opterr = 0; + + struct option longOptions[] = { + {"verbose", no_argument, 0, 'v'}, + {"type", required_argument, 0, 't'}, + {"annotate", required_argument, 0, 'a'}, + {"param", required_argument, 0, 'X'}, + {"plugin-path", required_argument, 0, 'p'}, + {"input-file", required_argument, 0, 'i'}, + {"output-file", required_argument, 0, 'o'}, + {"loglevel", required_argument, 0, 'l'}, + {0, 0, 0, 0} + }; + + // parse global options + int optionInd = 0; + int option; + for (;;) { + option = getopt_long_only(argc, argv, "+vp:X:t:i:o:l:a:", longOptions, &optionInd); + if (option == -1) { + break; + } + switch(option) { + // cases without short option + case 0: { + break; + } + // cases with short-hand options + case 'v': + verbose = true; + break; + case 't': + outType = optarg; + break; + case 'p': + pluginPath = optarg; + break; + case 'i': + inputFile = optarg; + break; + case 'a': + annotatedFile = optarg; + break; + case 'X': { + std::list extension = tokenize(optarg, '='); + if (extension.size() != 2) + printUsageAndExit(argv[0]); + std::string key = boost::trim_copy(*(extension.begin())); + std::string value = boost::trim_copy(*(++extension.begin())); + extensions.insert(std::pair(key, value)); + } + break; + case 'o': + outputFile = optarg; + extensions.insert(std::pair("outputFile", outputFile)); + break; + case 'l': + break; + case '?': { + break; + } + default: + break; + } + } + + // make sure given annotation options are available in the environment + if(ANNOTATE("USCXML_ANNOTATE_GLOBAL_STATE_STEP", "step")) + setenv("USCXML_ANNOTATE_GLOBAL_STATE_STEP", "YES", 1); + + if (ANNOTATE("USCXML_ANNOTATE_GLOBAL_TRANS_PRIO", "priority")) + setenv("USCXML_ANNOTATE_GLOBAL_TRANS_PRIO", "YES", 1); + + if (ANNOTATE("USCXML_ANNOTATE_VERBOSE_COMMENTS", "verbose")) + setenv("USCXML_ANNOTATE_VERBOSE_COMMENTS", "YES", 1); + + if (ANNOTATE("USCXML_ANNOTATE_TRANS_EXITSET", "exitset")) + setenv("USCXML_ANNOTATE_TRANS_EXITSET", "YES", 1); + + if (ANNOTATE("USCXML_ANNOTATE_TRANS_DOMAIN", "domain")) + setenv("USCXML_ANNOTATE_TRANS_DOMAIN", "YES", 1); + + if (ANNOTATE("USCXML_ANNOTATE_TRANS_CONFLICTS", "conflicts")) + setenv("USCXML_ANNOTATE_TRANS_CONFLICTS", "YES", 1); + + if (ANNOTATE("USCXML_ANNOTATE_TRANS_ENTRYSET", "entryset")) + setenv("USCXML_ANNOTATE_TRANS_ENTRYSET", "YES", 1); + + if(ANNOTATE("USCXML_ANNOTATE_GLOBAL_TRANS_MEMBERS", "members")) + setenv("USCXML_ANNOTATE_GLOBAL_TRANS_MEMBERS", "YES", 1); + + if(ANNOTATE("USCXML_ANNOTATE_GLOBAL_TRANS_SENDS", "sends")) + setenv("USCXML_ANNOTATE_GLOBAL_TRANS_SENDS", "YES", 1); + + if(ANNOTATE("USCXML_ANNOTATE_GLOBAL_TRANS_RAISES", "raises")) + setenv("USCXML_ANNOTATE_GLOBAL_TRANS_RAISES", "YES", 1); + + if(ANNOTATE("USCXML_ANNOTATE_PROGRESS", "progress")) + setenv("USCXML_ANNOTATE_PROGRESS", "YES", 1); + + if(ANNOTATE("USCXML_ANNOTATE_NOCOMMENT", "nocomment")) + setenv("USCXML_ANNOTATE_NOCOMMENT", "YES", 1); + + +// if (outType.length() == 0 && outputFile.length() > 0) { +// // try to get type from outfile extension +// size_t dotPos = outputFile.find_last_of("."); +// if (dotPos != std::string::npos) { +// outType= outputFile.substr(dotPos + 1); +// } +// } + +// if (outType.length() == 0) +// printUsageAndExit(argv[0]); + + if (outType != "flat" && + outType != "scxml" && + outType != "pml" && + outType != "c" && + outType != "vhdl" && + outType != "java" && + outType != "min" && + std::find(options.begin(), options.end(), "priority") == options.end() && + std::find(options.begin(), options.end(), "domain") == options.end() && + std::find(options.begin(), options.end(), "conflicts") == options.end() && + std::find(options.begin(), options.end(), "exitset") == options.end() && + std::find(options.begin(), options.end(), "entryset") == options.end()) + printUsageAndExit(argv[0]); + + // register plugins + if (pluginPath.length() > 0) { + Factory::setDefaultPluginPath(pluginPath); + } + + // start HTTP server + HTTPServer::getInstance(30444, 30445, NULL); + + Interpreter interpreter; + try { + if (inputFile.size() == 0 || inputFile == "-") { + LOGD(USCXML_INFO) << "Reading SCXML from STDIN" << std::endl; + std::stringstream ss; + std::string line; + while (std::getline(std::cin, line)) { + ss << line; + } + URL tmp("anonymous.scxml"); + tmp = URL::resolveWithCWD(tmp); + interpreter = Interpreter::fromXML(ss.str(), tmp); + } else { + interpreter = Interpreter::fromURL(inputFile); + } + } 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 = URL::resolveWithCWD(tmp); + std::string content = tmp.getInContent(); + + std::string inlineBeginMarker = "INLINE SCXML BEGIN\n"; + std::string inlineEndMarker = "\nINLINE SCXML END"; + + size_t inlineSCXMLBegin = content.find(inlineBeginMarker); + if (inlineSCXMLBegin != std::string::npos) { + inlineSCXMLBegin += inlineBeginMarker.size(); + size_t inlineSCXMLEnd = content.find(inlineEndMarker); + std::string inlineSCXMLContent = content.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) { + LOGD(USCXML_ERROR) << "Cannot create interpreter from " << inputFile << std::endl; + exit(EXIT_FAILURE); + + } + + try { + if (verbose) { + std::list issues = interpreter.validate(); + for (std::list::iterator issueIter = issues.begin(); issueIter != issues.end(); issueIter++) { + std::cerr << *issueIter << std::endl; + } + } + + Transformer transformer; + if (outType == "c") { + transformer = ChartToC::transform(interpreter); + transformer.setExtensions(extensions); + transformer.setOptions(options); + + if (outputFile.size() == 0 || outputFile == "-") { + transformer.writeTo(std::cout); + } else { + std::ofstream outStream; + outStream.open(outputFile.c_str()); + transformer.writeTo(outStream); + outStream.close(); + } + } + + if (outType == "java") { + transformer = ChartToJava::transform(interpreter); + transformer.setExtensions(extensions); + transformer.setOptions(options); + + if (outputFile.size() == 0 || outputFile == "-") { + transformer.writeTo(std::cout); + } else { + std::ofstream outStream; + outStream.open(outputFile.c_str()); + transformer.writeTo(outStream); + outStream.close(); + } + } + + if (outType == "vhdl") { + transformer = ChartToVHDL::transform(interpreter); + transformer.setExtensions(extensions); + transformer.setOptions(options); + + if (outputFile.size() == 0 || outputFile == "-") { + transformer.writeTo(std::cout); + } else { + std::ofstream outStream; + outStream.open(outputFile.c_str()); + transformer.writeTo(outStream); + outStream.close(); + } + } + + if (outType == "pml") { + transformer = ChartToPromela::transform(interpreter); + transformer.setExtensions(extensions); + transformer.setOptions(options); + + if (outputFile.size() == 0 || outputFile == "-") { + transformer.writeTo(std::cout); + } else { + std::ofstream outStream; + outStream.open(outputFile.c_str()); + transformer.writeTo(outStream); + outStream.close(); + } + } + +// if (outType == "tex") { +// if (outputFile.size() == 0 || outputFile == "-") { +// ChartToTex::transform(interpreter).writeTo(std::cout); +// } else { +// std::ofstream outStream; +// outStream.open(outputFile.c_str()); +// ChartToTex::transform(interpreter).writeTo(outStream); +// outStream.close(); +// } +// exit(EXIT_SUCCESS); +// } + +// if (outType == "flat") { +// if (outputFile.size() == 0 || outputFile == "-") { +// ChartToFlatSCXML::transform(interpreter).writeTo(std::cout); +// } else { +// std::ofstream outStream; +// outStream.open(outputFile.c_str()); +// ChartToFlatSCXML::transform(interpreter).writeTo(outStream); +// outStream.close(); +// } +// exit(EXIT_SUCCESS); +// } + +// if (outType == "min") { +// if (outputFile.size() == 0 || outputFile == "-") { +// ChartToMinimalSCXML::transform(interpreter).writeTo(std::cout); +// } else { +// std::ofstream outStream; +// outStream.open(outputFile.c_str()); +// ChartToMinimalSCXML::transform(interpreter).writeTo(outStream); +// outStream.close(); +// } +// exit(EXIT_SUCCESS); +// } + + if (annotatedFile.size() > 0) { + std::ofstream outStream; + outStream.open(annotatedFile.c_str()); + outStream << (*transformer.getImpl()->getDocument()); + outStream.close(); + + } + + + } catch (Event e) { + std::cout << e << std::endl; + return EXIT_FAILURE; + } catch (const std::exception &e) { + std::cout << e.what() << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index c4025ba..f3aedee 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -271,6 +271,10 @@ std::list Interpreter::validate() { return InterpreterIssue::forInterpreter(_impl.get()); } +LambdaMonitor& Interpreter::on() { + return _impl->on(); +} + #if 1 static void printNodeSet(Logger& logger, const std::list nodes) { std::string seperator; diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h index 3c44400..aff77a2 100644 --- a/src/uscxml/Interpreter.h +++ b/src/uscxml/Interpreter.h @@ -34,6 +34,7 @@ #include "uscxml/interpreter/ContentExecutor.h" #include "uscxml/interpreter/EventQueue.h" #include "uscxml/interpreter/InterpreterState.h" +#include "uscxml/interpreter/InterpreterMonitor.h" #ifdef max #error define NOMINMAX or undefine the max macro please (https://support.microsoft.com/en-us/kb/143208) @@ -42,6 +43,7 @@ namespace uscxml { class InterpreterMonitor; +class LambdaMonitor; class InterpreterImpl; class InterpreterIssue; @@ -234,6 +236,9 @@ public: std::shared_ptr getImpl() const { return _impl; } + + LambdaMonitor& on(); + #if 0 // "Ambiguous user-defined-conversion" with operator bool() on MSVC from Visual Studio 12 explicit operator MicroStepCallbacks*() { diff --git a/src/uscxml/interpreter/InterpreterImpl.cpp b/src/uscxml/interpreter/InterpreterImpl.cpp index 414dba2..1caa3f0 100644 --- a/src/uscxml/interpreter/InterpreterImpl.cpp +++ b/src/uscxml/interpreter/InterpreterImpl.cpp @@ -103,6 +103,9 @@ InterpreterImpl::~InterpreterImpl() { if (_document) delete _document; + if (_lambdaMonitor) + delete _lambdaMonitor; + { std::lock_guard lock(_instanceMutex); _instances.erase(getSessionId()); @@ -139,7 +142,7 @@ void InterpreterImpl::reset() { if (_microStepper) _microStepper.reset(); - _isInitialized = false; +// _isInitialized = false; _state = USCXML_INSTANTIATED; // _dataModel.reset(); if (_delayQueue) @@ -622,4 +625,12 @@ void InterpreterImpl::enqueueAtParent(const Event& event) { } +LambdaMonitor& InterpreterImpl::on() { + if (_lambdaMonitor == NULL) { + _lambdaMonitor = new LambdaMonitor(); + addMonitor(_lambdaMonitor); + } + return *_lambdaMonitor; +} + } diff --git a/src/uscxml/interpreter/InterpreterImpl.h b/src/uscxml/interpreter/InterpreterImpl.h index 42d61f2..2f5fb07 100644 --- a/src/uscxml/interpreter/InterpreterImpl.h +++ b/src/uscxml/interpreter/InterpreterImpl.h @@ -269,9 +269,13 @@ public: return _document; } + LambdaMonitor& on(); + protected: static void addInstance(std::shared_ptr instance); - + + LambdaMonitor* _lambdaMonitor = NULL; + Binding _binding; ActionLanguage _al; diff --git a/src/uscxml/interpreter/InterpreterMonitor.h b/src/uscxml/interpreter/InterpreterMonitor.h index 43b7f53..ed62675 100644 --- a/src/uscxml/interpreter/InterpreterMonitor.h +++ b/src/uscxml/interpreter/InterpreterMonitor.h @@ -65,26 +65,47 @@ public: InterpreterMonitor(Logger logger) : _copyToInvokers(false), _logger(logger) {} virtual ~InterpreterMonitor() {} - virtual void beforeProcessingEvent(const std::string& sessionId, const Event& event) {} + virtual void beforeProcessingEvent(const std::string& sessionId, + const Event& event) {} virtual void beforeMicroStep(const std::string& sessionId) {} - virtual void beforeExitingState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) {} - virtual void afterExitingState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) {} + virtual void beforeExitingState(const std::string& sessionId, + const std::string& stateName, + const XERCESC_NS::DOMElement* state) {} + virtual void afterExitingState(const std::string& sessionId, + const std::string& stateName, + const XERCESC_NS::DOMElement* state) {} - virtual void beforeExecutingContent(const std::string& sessionId, const XERCESC_NS::DOMElement* execContent) {} - virtual void afterExecutingContent(const std::string& sessionId, const XERCESC_NS::DOMElement* execContent) {} + virtual void beforeExecutingContent(const std::string& sessionId, + const XERCESC_NS::DOMElement* execContent) {} + virtual void afterExecutingContent(const std::string& sessionId, + const XERCESC_NS::DOMElement* execContent) {} - virtual void beforeUninvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {} - virtual void afterUninvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {} + virtual void beforeUninvoking(const std::string& sessionId, + const XERCESC_NS::DOMElement* invokeElem, + const std::string& invokeid) {} + virtual void afterUninvoking(const std::string& sessionId, + const XERCESC_NS::DOMElement* invokeElem, + const std::string& invokeid) {} - virtual void beforeTakingTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition) {} - virtual void afterTakingTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition) {} + virtual void beforeTakingTransition(const std::string& sessionId, + const XERCESC_NS::DOMElement* transition) {} + virtual void afterTakingTransition(const std::string& sessionId, + const XERCESC_NS::DOMElement* transition) {} - virtual void beforeEnteringState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) {} - virtual void afterEnteringState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) {} + virtual void beforeEnteringState(const std::string& sessionId, + const std::string& stateName, + const XERCESC_NS::DOMElement* state) {} + virtual void afterEnteringState(const std::string& sessionId, + const std::string& stateName, + const XERCESC_NS::DOMElement* state) {} - virtual void beforeInvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {} - virtual void afterInvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {} + virtual void beforeInvoking(const std::string& sessionId, + const XERCESC_NS::DOMElement* invokeElem, + const std::string& invokeid) {} + virtual void afterInvoking(const std::string& sessionId, + const XERCESC_NS::DOMElement* invokeElem, + const std::string& invokeid) {} virtual void afterMicroStep(const std::string& sessionId) {} virtual void onStableConfiguration(const std::string& sessionId) {} @@ -92,7 +113,8 @@ public: virtual void beforeCompletion(const std::string& sessionId) {} virtual void afterCompletion(const std::string& sessionId) {} - virtual void reportIssue(const std::string& sessionId, const InterpreterIssue& issue) {} + virtual void reportIssue(const std::string& sessionId, + const InterpreterIssue& issue) {} void copyToInvokers(bool copy) { _copyToInvokers = copy; @@ -125,6 +147,277 @@ protected: std::string _logPrefix; }; +class USCXML_API LambdaMonitor : public InterpreterMonitor { +public: + void processEvent(std::function callback) { + _beforeProcessingEvent = callback; + } + + + void microStep(std::function callback, + bool after = false) { + if (after) { + _afterMicroStep = callback; + } else { + _beforeMicroStep = callback; + } + + } + + void exitState(std::function callback, + bool after = false) { + if (after) { + _afterExitingState = callback; + } else { + _beforeExitingState = callback; + } + } + + void executeContent(std::function callback, + bool after = false) { + if (after) { + _afterExecutingContent = callback; + } else { + _beforeExecutingContent = callback; + } + } + + void uninvoke(std::function callback, + bool after = false) { + if (after) { + _afterUninvoking = callback; + } else { + _beforeUninvoking = callback; + } + } + + void transition(std::function callback, + bool after = false) { + if (after) { + _afterTakingTransition = callback; + } else { + _beforeTakingTransition = callback; + } + } + + void enterState(std::function callback, + bool after = false) { + _beforeEnteringState = callback; + if (after) { + _afterEnteringState = callback; + } else { + _beforeEnteringState = callback; + } + + } + + void invoke(std::function callback, + bool after = false) { + if (after) { + _afterInvoking = callback; + } else { + _beforeInvoking = callback; + } + } + + void stableConfiguration(std::function callback) { + _onStableConfiguration = callback; + } + + void completion(std::function callback, + bool after = false) { + if (after) { + _afterCompletion = callback; + } else { + _beforeCompletion = callback; + } + + } + + void reportIssue(std::function callback) { + _reportIssue = callback; + } + +protected: + + std::function _beforeProcessingEvent; + + std::function _beforeMicroStep; + + std::function _beforeExitingState; + + std::function _afterExitingState; + + std::function _beforeExecutingContent; + std::function _afterExecutingContent; + + std::function _beforeUninvoking; + std::function _afterUninvoking; + + std::function _beforeTakingTransition; + std::function _afterTakingTransition; + + std::function _beforeEnteringState; + std::function _afterEnteringState; + + std::function _beforeInvoking; + std::function _afterInvoking; + + std::function _afterMicroStep; + std::function _onStableConfiguration; + + std::function _beforeCompletion; + std::function _afterCompletion; + + std::function _reportIssue; + + + + void beforeProcessingEvent(const std::string& sessionId, + const Event& event) { + if (_beforeProcessingEvent) + _beforeProcessingEvent(sessionId, event); + } + void beforeMicroStep(const std::string& sessionId) { + if (_beforeMicroStep) + _beforeMicroStep(sessionId); + } + + void beforeExitingState(const std::string& sessionId, + const std::string& stateName, + const XERCESC_NS::DOMElement* state) { + if (_beforeExitingState) + _beforeExitingState(sessionId, stateName, state); + } + + void afterExitingState(const std::string& sessionId, + const std::string& stateName, + const XERCESC_NS::DOMElement* state) { + if (_afterExitingState) + _afterExitingState(sessionId, stateName, state); + } + + void beforeExecutingContent(const std::string& sessionId, + const XERCESC_NS::DOMElement* execContent) { + if (_beforeExecutingContent) + _beforeExecutingContent(sessionId, execContent); + } + void afterExecutingContent(const std::string& sessionId, + const XERCESC_NS::DOMElement* execContent) { + if (_afterExecutingContent) + _afterExecutingContent(sessionId, execContent); + + } + + void beforeUninvoking(const std::string& sessionId, + const XERCESC_NS::DOMElement* invokeElem, + const std::string& invokeid) { + if (_beforeUninvoking) + _beforeUninvoking(sessionId, invokeElem, invokeid); + } + void afterUninvoking(const std::string& sessionId, + const XERCESC_NS::DOMElement* invokeElem, + const std::string& invokeid) { + if (_afterUninvoking) + _afterUninvoking(sessionId, invokeElem, invokeid); + } + + void beforeTakingTransition(const std::string& sessionId, + const XERCESC_NS::DOMElement* transition) { + if (_beforeTakingTransition) + _beforeTakingTransition(sessionId, transition); + } + void afterTakingTransition(const std::string& sessionId, + const XERCESC_NS::DOMElement* transition) { + if (_afterTakingTransition) + _afterTakingTransition(sessionId, transition); + } + + void beforeEnteringState(const std::string& sessionId, + const std::string& stateName, + const XERCESC_NS::DOMElement* state) { + if (_beforeEnteringState) + _beforeEnteringState(sessionId, stateName, state); + } + void afterEnteringState(const std::string& sessionId, + const std::string& stateName, + const XERCESC_NS::DOMElement* state) { + if (_afterEnteringState) + _afterEnteringState(sessionId, stateName, state); + } + + void beforeInvoking(const std::string& sessionId, + const XERCESC_NS::DOMElement* invokeElem, + const std::string& invokeid) { + if (_beforeInvoking) + _beforeInvoking(sessionId, invokeElem, invokeid); + } + void afterInvoking(const std::string& sessionId, + const XERCESC_NS::DOMElement* invokeElem, + const std::string& invokeid) { + if (_afterInvoking) + _afterInvoking(sessionId, invokeElem, invokeid); + } + + void afterMicroStep(const std::string& sessionId) { + if (_afterMicroStep) + _afterMicroStep(sessionId); + } + void onStableConfiguration(const std::string& sessionId) { + if (_onStableConfiguration) + _onStableConfiguration(sessionId); + } + + void beforeCompletion(const std::string& sessionId) { + if (_beforeCompletion) + _beforeCompletion(sessionId); + } + void afterCompletion(const std::string& sessionId) { + if (_afterCompletion) + _afterCompletion(sessionId); + } + + void reportIssue(const std::string& sessionId, + const InterpreterIssue& issue) { + if (_reportIssue) + _reportIssue(sessionId, issue); + } +}; + } #endif /* end of include guard: INTERPRETERMONITOR_H_D3F21429 */ diff --git a/src/uscxml/util/Predicates.cpp b/src/uscxml/util/Predicates.cpp index 6649907..1f95a52 100644 --- a/src/uscxml/util/Predicates.cpp +++ b/src/uscxml/util/Predicates.cpp @@ -328,7 +328,6 @@ DOMElement* getState(const std::string& stateId, const DOMElement* root) { } // no state with such an id in document! - assert(false); return NULL; } diff --git a/test/src/test-snippets.cpp b/test/src/test-snippets.cpp index f26b730..5eb680f 100644 --- a/test/src/test-snippets.cpp +++ b/test/src/test-snippets.cpp @@ -9,6 +9,8 @@ #include "uscxml/Interpreter.h" #include "uscxml/interpreter/LoggingImpl.h" +#include + using namespace uscxml; void microstep_snippet() { @@ -31,9 +33,30 @@ void microstep_snippet() { } +void lambda_snippet() { + InterpreterState state = uscxml::USCXML_UNDEF; + Interpreter scxml = Interpreter::fromURL("https://raw.githubusercontent.com/tklab-tud/uscxml/master/test/w3c/null/test436.scxml"); + + scxml.on().enterState([](const std::string& sessionId, + const std::string& stateName, + const xercesc_3_1::DOMElement* state) { + std::cout << "Entered " << stateName << std::endl; + }); + + scxml.on().exitState([](const std::string& sessionId, + const std::string& stateName, + const xercesc_3_1::DOMElement* state) { + std::cout << "Exited " << stateName << std::endl; + }); + + + while((state = scxml.step()) != uscxml::USCXML_FINISHED) {} + +} + int main(int argc, char** argv) { try { - Logger::getDefault().log(USCXML_FATAL) << "Foo!" << " BAR?" << std::endl; + lambda_snippet(); microstep_snippet(); } catch (...) { exit(EXIT_FAILURE); -- cgit v0.12