diff options
author | juehv <juehv@tk-jh-frankenstein.tk.informatik.tu-darmstadt.de> | 2016-11-15 13:17:49 (GMT) |
---|---|---|
committer | juehv <juehv@tk-jh-frankenstein.tk.informatik.tu-darmstadt.de> | 2016-11-15 13:17:49 (GMT) |
commit | f10d0b4bf3aef14ab2a6e760633906410e7ca783 (patch) | |
tree | 5c50f3b0ba7caf19858dba540480c7e12801cdba | |
parent | d410a27cfe384fd292cf1fd30c56a6f08bc40b98 (diff) | |
parent | 13220a705ac1efda68c0a0aef0ed63fbc2bc27cd (diff) | |
download | uscxml-f10d0b4bf3aef14ab2a6e760633906410e7ca783.zip uscxml-f10d0b4bf3aef14ab2a6e760633906410e7ca783.tar.gz uscxml-f10d0b4bf3aef14ab2a6e760633906410e7ca783.tar.bz2 |
merge
293 files changed, 21116 insertions, 2318 deletions
diff --git a/.travis.yml b/.travis.yml index 07b9243..b4b7faf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,5 @@ +# Ubuntu 14.04 Trusty support +# dist: trusty sudo: required language: cpp @@ -10,16 +12,18 @@ compiler: - clang install: - - if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi + - if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi + - if [ "$CXX" = "clang++" ] && [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export CXX="clang++-3.6" CC="clang-3.6"; fi addons: apt: sources: - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.6 packages: - - gcc-4.8 - - g++-4.8 - - clang + - gcc-4.9 + - g++-4.9 + - clang-3.6 before_install: - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update -qq; fi diff --git a/CMakeLists.txt b/CMakeLists.txt index 1466df7..87fc2e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -385,6 +385,8 @@ if (WITH_DM_C89) endif() endif() +OPTION(WITH_DM_PROMELA "Do build with promela datamodel support" ON) + add_subdirectory(src/uscxml) add_subdirectory(src/bindings) diff --git a/apps/uscxml-transform.cpp b/apps/uscxml-transform.cpp index de0c594..e1c44c3 100644 --- a/apps/uscxml-transform.cpp +++ b/apps/uscxml-transform.cpp @@ -3,6 +3,7 @@ #include "uscxml/util/String.h" #include "uscxml/transform/ChartToC.h" #include "uscxml/transform/ChartToVHDL.h" +#include "uscxml/transform/ChartToPromela.h" #include <boost/algorithm/string.hpp> @@ -29,7 +30,7 @@ void printUsageAndExit(const char* progName) { 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|tex] [-a {OPTIONS}] [-v] [-lN]"); + printf(" [-t c|pml|flat|min] [-a {OPTIONS}] [-v] [-lN]"); #ifdef BUILD_AS_PLUGINS printf(" [-p pluginPath]"); #endif @@ -41,7 +42,6 @@ void printUsageAndExit(const char* progName) { printf("\t-t vhdl : convert to VHDL hardware description\n"); printf("\t-t flat : flatten to SCXML state-machine\n"); printf("\t-t min : minimize SCXML state-chart\n"); - printf("\t-t tex : write global state transition table as tex file\n"); printf("\t-a {OPTIONS} : annotate SCXML elements with comma seperated options\n"); printf("\t priority - transitions with their priority for transition selection\n"); printf("\t exitset - annotate all transitions with their exit sets\n"); @@ -201,7 +201,6 @@ int main(int argc, char** argv) { outType != "c" && outType != "vhdl" && outType != "min" && - outType != "tex" && 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() && @@ -303,17 +302,17 @@ int main(int argc, char** argv) { exit(EXIT_SUCCESS); } -// if (outType == "pml") { -// if (outputFile.size() == 0 || outputFile == "-") { -// ChartToPromela::transform(interpreter).writeTo(std::cout); -// } else { -// std::ofstream outStream; -// outStream.open(outputFile.c_str()); -// ChartToPromela::transform(interpreter).writeTo(outStream); -// outStream.close(); -// } -// exit(EXIT_SUCCESS); -// } + if (outType == "pml") { + if (outputFile.size() == 0 || outputFile == "-") { + ChartToPromela::transform(interpreter).writeTo(std::cout); + } else { + std::ofstream outStream; + outStream.open(outputFile.c_str()); + ChartToPromela::transform(interpreter).writeTo(outStream); + outStream.close(); + } + exit(EXIT_SUCCESS); + } // if (outType == "tex") { // if (outputFile.size() == 0 || outputFile == "-") { diff --git a/config.h.in b/config.h.in index 074b072..e8b69c1 100644 --- a/config.h.in +++ b/config.h.in @@ -69,6 +69,8 @@ #cmakedefine WITH_DM_ECMA_JSC #cmakedefine WITH_DM_LUA #cmakedefine WITH_DM_C89 +#cmakedefine WITH_DM_PROMELA + /** Optional libraries we found */ #cmakedefine UMUNDO_FOUND diff --git a/contrib/cmake/BuildLibEvent.cmake b/contrib/cmake/BuildLibEvent.cmake index 79fed51..4e4e7af 100644 --- a/contrib/cmake/BuildLibEvent.cmake +++ b/contrib/cmake/BuildLibEvent.cmake @@ -29,6 +29,8 @@ else () URL_MD5 c4c56f986aa985677ca1db89630a2e11 BUILD_IN_SOURCE 0 PREFIX ${CMAKE_BINARY_DIR}/deps/libevent + PATCH_COMMAND + ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/contrib/patches/libevent/sierra.kqueue.c" <SOURCE_DIR>/kqueue.c CONFIGURE_COMMAND ${FORCE_FPIC} <SOURCE_DIR>/configure --enable-static --enable-shared --disable-openssl --prefix=<INSTALL_DIR> ) diff --git a/contrib/patches/libevent/sierra.kqueue.c b/contrib/patches/libevent/sierra.kqueue.c new file mode 100644 index 0000000..f74dfe1 --- /dev/null +++ b/contrib/patches/libevent/sierra.kqueue.c @@ -0,0 +1,475 @@ +/* $OpenBSD: kqueue.c,v 1.5 2002/07/10 14:41:31 art Exp $ */ + +/* + * Copyright 2000-2007 Niels Provos <provos@citi.umich.edu> + * Copyright 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "event2/event-config.h" + +#define _GNU_SOURCE + +#include <sys/types.h> +#ifdef _EVENT_HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#include <sys/queue.h> +#include <sys/event.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#ifdef _EVENT_HAVE_INTTYPES_H +#include <inttypes.h> +#endif + +/* Some platforms apparently define the udata field of struct kevent as + * intptr_t, whereas others define it as void*. There doesn't seem to be an + * easy way to tell them apart via autoconf, so we need to use OS macros. */ +#if defined(_EVENT_HAVE_INTTYPES_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__darwin__) && !defined(__APPLE__) +#define PTR_TO_UDATA(x) ((intptr_t)(x)) +#define INT_TO_UDATA(x) ((intptr_t)(x)) +#else +#define PTR_TO_UDATA(x) (x) +#define INT_TO_UDATA(x) ((void*)(x)) +#endif + +#include "event-internal.h" +#include "log-internal.h" +#include "evmap-internal.h" +#include "event2/thread.h" +#include "evthread-internal.h" +#include "changelist-internal.h" + +#define NEVENT 64 + +struct kqop { + struct kevent *changes; + int changes_size; + + struct kevent *events; + int events_size; + int kq; + pid_t pid; +}; + +static void kqop_free(struct kqop *kqop); + +static void *kq_init(struct event_base *); +static int kq_sig_add(struct event_base *, int, short, short, void *); +static int kq_sig_del(struct event_base *, int, short, short, void *); +static int kq_dispatch(struct event_base *, struct timeval *); +static void kq_dealloc(struct event_base *); + +const struct eventop kqops = { + "kqueue", + kq_init, + event_changelist_add, + event_changelist_del, + kq_dispatch, + kq_dealloc, + 1 /* need reinit */, + EV_FEATURE_ET|EV_FEATURE_O1|EV_FEATURE_FDS, + EVENT_CHANGELIST_FDINFO_SIZE +}; + +static const struct eventop kqsigops = { + "kqueue_signal", + NULL, + kq_sig_add, + kq_sig_del, + NULL, + NULL, + 1 /* need reinit */, + 0, + 0 +}; + +static void * +kq_init(struct event_base *base) +{ + int kq = -1; + struct kqop *kqueueop = NULL; + + if (!(kqueueop = mm_calloc(1, sizeof(struct kqop)))) + return (NULL); + +/* Initialize the kernel queue */ + + if ((kq = kqueue()) == -1) { + event_warn("kqueue"); + goto err; + } + + kqueueop->kq = kq; + + kqueueop->pid = getpid(); + + /* Initialize fields */ + kqueueop->changes = mm_calloc(NEVENT, sizeof(struct kevent)); + if (kqueueop->changes == NULL) + goto err; + kqueueop->events = mm_calloc(NEVENT, sizeof(struct kevent)); + if (kqueueop->events == NULL) + goto err; + kqueueop->events_size = kqueueop->changes_size = NEVENT; + + /* Check for Mac OS X kqueue bug. */ + memset(&kqueueop->changes[0], 0, sizeof kqueueop->changes[0]); + kqueueop->changes[0].ident = -1; + kqueueop->changes[0].filter = EVFILT_READ; + kqueueop->changes[0].flags = EV_ADD; + /* + * If kqueue works, then kevent will succeed, and it will + * stick an error in events[0]. If kqueue is broken, then + * kevent will fail. + */ + if (kevent(kq, + kqueueop->changes, 1, kqueueop->events, NEVENT, NULL) != 1 || + (int)kqueueop->events[0].ident != -1 || + !(kqueueop->events[0].flags & EV_ERROR)) { + event_warn("%s: detected broken kqueue; not using.", __func__); + goto err; + } + + base->evsigsel = &kqsigops; + + return (kqueueop); +err: + if (kqueueop) + kqop_free(kqueueop); + + return (NULL); +} + +static void +kq_sighandler(int sig) +{ + /* Do nothing here */ +} + +#define ADD_UDATA 0x30303 + +static void +kq_setup_kevent(struct kevent *out, evutil_socket_t fd, int filter, short change) +{ + memset(out, 0, sizeof(struct kevent)); + out->ident = fd; + out->filter = filter; + + if (change & EV_CHANGE_ADD) { + out->flags = EV_ADD; + /* We set a magic number here so that we can tell 'add' + * errors from 'del' errors. */ + out->udata = INT_TO_UDATA(ADD_UDATA); + if (change & EV_ET) + out->flags |= EV_CLEAR; +#ifdef NOTE_EOF + /* Make it behave like select() and poll() */ + if (filter == EVFILT_READ) + out->fflags = NOTE_EOF; +#endif + } else { + EVUTIL_ASSERT(change & EV_CHANGE_DEL); + out->flags = EV_DELETE; + } +} + +static int +kq_build_changes_list(const struct event_changelist *changelist, + struct kqop *kqop) +{ + int i; + int n_changes = 0; + + for (i = 0; i < changelist->n_changes; ++i) { + struct event_change *in_ch = &changelist->changes[i]; + struct kevent *out_ch; + if (n_changes >= kqop->changes_size - 1) { + int newsize = kqop->changes_size * 2; + struct kevent *newchanges; + + newchanges = mm_realloc(kqop->changes, + newsize * sizeof(struct kevent)); + if (newchanges == NULL) { + event_warn("%s: realloc", __func__); + return (-1); + } + kqop->changes = newchanges; + kqop->changes_size = newsize; + } + if (in_ch->read_change) { + out_ch = &kqop->changes[n_changes++]; + kq_setup_kevent(out_ch, in_ch->fd, EVFILT_READ, + in_ch->read_change); + } + if (in_ch->write_change) { + out_ch = &kqop->changes[n_changes++]; + kq_setup_kevent(out_ch, in_ch->fd, EVFILT_WRITE, + in_ch->write_change); + } + } + return n_changes; +} + +static int +kq_grow_events(struct kqop *kqop, size_t new_size) +{ + struct kevent *newresult; + + newresult = mm_realloc(kqop->events, + new_size * sizeof(struct kevent)); + + if (newresult) { + kqop->events = newresult; + kqop->events_size = new_size; + return 0; + } else { + return -1; + } +} + +static int +kq_dispatch(struct event_base *base, struct timeval *tv) +{ + struct kqop *kqop = base->evbase; + struct kevent *events = kqop->events; + struct kevent *changes; + struct timespec ts, *ts_p = NULL; + int i, n_changes, res; + + if (tv != NULL) { + TIMEVAL_TO_TIMESPEC(tv, &ts); + ts_p = &ts; + } + + /* Build "changes" from "base->changes" */ + EVUTIL_ASSERT(kqop->changes); + n_changes = kq_build_changes_list(&base->changelist, kqop); + if (n_changes < 0) + return -1; + + event_changelist_remove_all(&base->changelist, base); + + /* steal the changes array in case some broken code tries to call + * dispatch twice at once. */ + changes = kqop->changes; + kqop->changes = NULL; + + /* Make sure that 'events' is at least as long as the list of changes: + * otherwise errors in the changes can get reported as a -1 return + * value from kevent() rather than as EV_ERROR events in the events + * array. + * + * (We could instead handle -1 return values from kevent() by + * retrying with a smaller changes array or a larger events array, + * but this approach seems less risky for now.) + */ + if (kqop->events_size < n_changes) { + int new_size = kqop->events_size; + do { + new_size *= 2; + } while (new_size < n_changes); + + kq_grow_events(kqop, new_size); + events = kqop->events; + } + + EVBASE_RELEASE_LOCK(base, th_base_lock); + + res = kevent(kqop->kq, changes, n_changes, + events, kqop->events_size, ts_p); + + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + + EVUTIL_ASSERT(kqop->changes == NULL); + kqop->changes = changes; + + if (res == -1) { + if (errno != EINTR) { + event_warn("kevent"); + return (-1); + } + + return (0); + } + + event_debug(("%s: kevent reports %d", __func__, res)); + + for (i = 0; i < res; i++) { + int which = 0; + + if (events[i].flags & EV_ERROR) { + switch (events[i].data) { + + /* Can occur on delete if we are not currently + * watching any events on this fd. That can + * happen when the fd was closed and another + * file was opened with that fd. */ + case ENOENT: + /* Can occur for reasons not fully understood + * on FreeBSD. */ + case EINVAL: + continue; + + /* Can occur on a delete if the fd is closed. */ + case EBADF: + /* XXXX On NetBSD, we can also get EBADF if we + * try to add the write side of a pipe, but + * the read side has already been closed. + * Other BSDs call this situation 'EPIPE'. It + * would be good if we had a way to report + * this situation. */ + continue; + /* These two can occur on an add if the fd was one side + * of a pipe, and the other side was closed. */ + case EPERM: + case EPIPE: + /* Report read events, if we're listening for + * them, so that the user can learn about any + * add errors. (If the operation was a + * delete, then udata should be cleared.) */ + if (events[i].udata) { + /* The operation was an add: + * report the error as a read. */ + which |= EV_READ; + break; + } else { + /* The operation was a del: + * report nothing. */ + continue; + } + + /* Other errors shouldn't occur. */ + default: + errno = events[i].data; + return (-1); + } + } else if (events[i].filter == EVFILT_READ) { + which |= EV_READ; + } else if (events[i].filter == EVFILT_WRITE) { + which |= EV_WRITE; + } else if (events[i].filter == EVFILT_SIGNAL) { + which |= EV_SIGNAL; + } + + if (!which) + continue; + + if (events[i].filter == EVFILT_SIGNAL) { + evmap_signal_active(base, events[i].ident, 1); + } else { + evmap_io_active(base, events[i].ident, which | EV_ET); + } + } + + if (res == kqop->events_size) { + /* We used all the events space that we have. Maybe we should + make it bigger. */ + kq_grow_events(kqop, kqop->events_size * 2); + } + + return (0); +} + +static void +kqop_free(struct kqop *kqop) +{ + if (kqop->changes) + mm_free(kqop->changes); + if (kqop->events) + mm_free(kqop->events); + if (kqop->kq >= 0 && kqop->pid == getpid()) + close(kqop->kq); + memset(kqop, 0, sizeof(struct kqop)); + mm_free(kqop); +} + +static void +kq_dealloc(struct event_base *base) +{ + struct kqop *kqop = base->evbase; + evsig_dealloc(base); + kqop_free(kqop); +} + +/* signal handling */ +static int +kq_sig_add(struct event_base *base, int nsignal, short old, short events, void *p) +{ + struct kqop *kqop = base->evbase; + struct kevent kev; + struct timespec timeout = { 0, 0 }; + (void)p; + + EVUTIL_ASSERT(nsignal >= 0 && nsignal < NSIG); + + memset(&kev, 0, sizeof(kev)); + kev.ident = nsignal; + kev.filter = EVFILT_SIGNAL; + kev.flags = EV_ADD; + + /* Be ready for the signal if it is sent any + * time between now and the next call to + * kq_dispatch. */ + if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1) + return (-1); + + /* XXXX The manpage suggest we could use SIG_IGN instead of a + * do-nothing handler */ + if (_evsig_set_handler(base, nsignal, kq_sighandler) == -1) + return (-1); + + return (0); +} + +static int +kq_sig_del(struct event_base *base, int nsignal, short old, short events, void *p) +{ + struct kqop *kqop = base->evbase; + struct kevent kev; + + struct timespec timeout = { 0, 0 }; + (void)p; + + EVUTIL_ASSERT(nsignal >= 0 && nsignal < NSIG); + + memset(&kev, 0, sizeof(kev)); + kev.ident = nsignal; + kev.filter = EVFILT_SIGNAL; + kev.flags = EV_DELETE; + + /* Because we insert signal events + * immediately, we need to delete them + * immediately, too */ + if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1) + return (-1); + + if (_evsig_restore_handler(base, nsignal) == -1) + return (-1); + + return (0); +} diff --git a/src/bindings/swig/uscxml_beautify.i b/src/bindings/swig/uscxml_beautify.i index 0c17e2a..159bcaa 100644 --- a/src/bindings/swig/uscxml_beautify.i +++ b/src/bindings/swig/uscxml_beautify.i @@ -2,8 +2,8 @@ %rename(ActionLanguage) WrappedActionLanguage; %rename(NativeDataModel) DataModel; %rename(DataModel) WrappedDataModel; -%rename(NativeDataModelExtension) DataModelExtension; -%rename(DataModelExtension) WrappedDataModelExtension; +//%rename(NativeDataModelExtension) DataModelExtension; +//%rename(DataModelExtension) WrappedDataModelExtension; %rename(NativeExecutableContent) ExecutableContent; %rename(ExecutableContent) WrappedExecutableContent; %rename(NativeInvoker) Invoker; diff --git a/src/bindings/swig/wrapped/WrappedActionLanguage.h b/src/bindings/swig/wrapped/WrappedActionLanguage.h index f26329e..55e009c 100644 --- a/src/bindings/swig/wrapped/WrappedActionLanguage.h +++ b/src/bindings/swig/wrapped/WrappedActionLanguage.h @@ -19,7 +19,7 @@ #ifndef WRAPPEDACTIONLANGUAGE_H_020AFC96 #define WRAPPEDACTIONLANGUAGE_H_020AFC96 - + #include <vector> #include <list> #include <ostream> @@ -37,10 +37,10 @@ class DataModelImpl; class WrappedActionLanguage : public ActionLanguage { public: - WrappedActionLanguage(); - virtual ~WrappedActionLanguage(); + WrappedActionLanguage(); + virtual ~WrappedActionLanguage(); - void setDataModel(DataModelImpl* dm); + void setDataModel(DataModelImpl* dm); }; } diff --git a/src/bindings/swig/wrapped/WrappedDataModel.h b/src/bindings/swig/wrapped/WrappedDataModel.h index 49a3482..1fefcbe 100644 --- a/src/bindings/swig/wrapped/WrappedDataModel.h +++ b/src/bindings/swig/wrapped/WrappedDataModel.h @@ -35,62 +35,65 @@ namespace uscxml { class WrappedDataModel : public DataModelImpl { public: - WrappedDataModel(); - virtual ~WrappedDataModel(); - - virtual std::shared_ptr<DataModelImpl> create(DataModelCallbacks* callbacks) { - std::shared_ptr<WrappedDataModel> dm(create()); - dm->callbacks = callbacks; - return dm; - } - - virtual std::list<std::string> getNames() { - return std::list<std::string>(); - } - - virtual WrappedDataModel* create() { - return new WrappedDataModel(); - } - - virtual bool isValidSyntax(const std::string& expr) { - return true; - } - - virtual void setEvent(const Event& event) {} - - // foreach - virtual uint32_t getLength(const std::string& expr) { - return 0; - } - - virtual void setForeach(const std::string& item, - const std::string& array, - const std::string& index, - uint32_t iteration) {} - - virtual Data getAsData(const std::string& content) { - return Data(); - } - virtual Data evalAsData(const std::string& expr) { - return Data(); - } - virtual bool evalAsBool(const std::string& expr) { - return true; - } - - virtual bool isDeclared(const std::string& expr) { - return true; - } - - virtual void assign(const std::string& location, const Data& data) {} - virtual void init(const std::string& location, const Data& data) {} - - virtual std::string andExpressions(std::list<std::string>) { - return ""; - } + WrappedDataModel(); + virtual ~WrappedDataModel(); + + virtual std::shared_ptr<DataModelImpl> create(DataModelCallbacks* callbacks) { + std::shared_ptr<WrappedDataModel> dm(create()); + dm->callbacks = callbacks; + return dm; + } + + virtual std::list<std::string> getNames() { + return std::list<std::string>(); + } + + virtual WrappedDataModel* create() { + return new WrappedDataModel(); + } + + virtual bool isValidSyntax(const std::string& expr) { + return true; + } + + virtual void setEvent(const Event& event) {} + + // foreach + virtual uint32_t getLength(const std::string& expr) { + return 0; + } + + virtual void setForeach(const std::string& item, + const std::string& array, + const std::string& index, + uint32_t iteration) {} + + virtual Data getAsData(const std::string& content) { + return Data(); + } + virtual Data evalAsData(const std::string& expr) { + return Data(); + } + virtual bool evalAsBool(const std::string& expr) { + return true; + } + + virtual bool isDeclared(const std::string& expr) { + return true; + } + + virtual void assign(const std::string& location, const Data& data) {} + virtual void init(const std::string& location, const Data& data) {} + + virtual void addExtension(DataModelExtension* ext) { + } + + virtual std::string andExpressions(std::list<std::string>) { + return ""; + } protected: - DataModelCallbacks* callbacks; + DataModelCallbacks* callbacks; }; } diff --git a/src/bindings/swig/wrapped/WrappedExecutableContent.cpp b/src/bindings/swig/wrapped/WrappedExecutableContent.cpp index 09aa6fd..3587cb5 100644 --- a/src/bindings/swig/wrapped/WrappedExecutableContent.cpp +++ b/src/bindings/swig/wrapped/WrappedExecutableContent.cpp @@ -28,16 +28,16 @@ WrappedExecutableContent::WrappedExecutableContent() {} WrappedExecutableContent::~WrappedExecutableContent() {} void WrappedExecutableContent::enterElement(XERCESC_NS::DOMElement* element) { - std::stringstream ss; - ss << *element; - enterElement(ss.str()); + std::stringstream ss; + ss << *element; + enterElement(ss.str()); } void WrappedExecutableContent::exitElement(XERCESC_NS::DOMElement* element) { - std::stringstream ss; - ss << *element; - exitElement(ss.str()); + std::stringstream ss; + ss << *element; + exitElement(ss.str()); } - + }
\ No newline at end of file diff --git a/src/bindings/swig/wrapped/WrappedExecutableContent.h b/src/bindings/swig/wrapped/WrappedExecutableContent.h index 0ba8d3e..6786b0a 100644 --- a/src/bindings/swig/wrapped/WrappedExecutableContent.h +++ b/src/bindings/swig/wrapped/WrappedExecutableContent.h @@ -35,9 +35,9 @@ public: virtual ~WrappedExecutableContent(); virtual std::shared_ptr<ExecutableContentImpl> create(InterpreterImpl* interpreter) { - std::shared_ptr<WrappedExecutableContent> ec(new WrappedExecutableContent()); - return ec; - } + std::shared_ptr<WrappedExecutableContent> ec(new WrappedExecutableContent()); + return ec; + } virtual std::string getLocalName() { return ""; @@ -47,16 +47,16 @@ public: return "http://www.w3.org/2005/07/scxml"; } - - void enterElement(XERCESC_NS::DOMElement* element); - virtual void enterElement(const std::string& elementXML) {} - - void exitElement(XERCESC_NS::DOMElement* element); - virtual void exitElement(const std::string& elementXML) {} - virtual bool processChildren() { - return true; - } + void enterElement(XERCESC_NS::DOMElement* element); + virtual void enterElement(const std::string& elementXML) {} + + void exitElement(XERCESC_NS::DOMElement* element); + virtual void exitElement(const std::string& elementXML) {} + + virtual bool processChildren() { + return true; + } }; diff --git a/src/bindings/swig/wrapped/WrappedIOProcessor.cpp b/src/bindings/swig/wrapped/WrappedIOProcessor.cpp index d034bc3..6c96840 100644 --- a/src/bindings/swig/wrapped/WrappedIOProcessor.cpp +++ b/src/bindings/swig/wrapped/WrappedIOProcessor.cpp @@ -22,7 +22,7 @@ namespace uscxml { WrappedIOProcessor::WrappedIOProcessor(InterpreterImpl* interpreter) { - _interpreter = interpreter; + _interpreter = interpreter; } WrappedIOProcessor::~WrappedIOProcessor() {} diff --git a/src/bindings/swig/wrapped/WrappedIOProcessor.h b/src/bindings/swig/wrapped/WrappedIOProcessor.h index aa5f967..f1820a4 100644 --- a/src/bindings/swig/wrapped/WrappedIOProcessor.h +++ b/src/bindings/swig/wrapped/WrappedIOProcessor.h @@ -39,23 +39,23 @@ public: WrappedIOProcessor(InterpreterImpl* interpreter); virtual ~WrappedIOProcessor(); - virtual std::list<std::string> getNames() { - return std::list<std::string>(); - }; + virtual std::list<std::string> getNames() { + return std::list<std::string>(); + }; - virtual std::shared_ptr<IOProcessorImpl> create(InterpreterImpl* interpreter) { - std::shared_ptr<IOProcessorImpl> ioProc = std::shared_ptr<IOProcessorImpl>(new WrappedIOProcessor(interpreter)); - return ioProc; - } - - virtual void eventFromSCXML(const std::string& target, const Event& event) {} - virtual bool isValidTarget(const std::string& target) { - return true; - } + virtual std::shared_ptr<IOProcessorImpl> create(InterpreterImpl* interpreter) { + std::shared_ptr<IOProcessorImpl> ioProc = std::shared_ptr<IOProcessorImpl>(new WrappedIOProcessor(interpreter)); + return ioProc; + } - virtual Data getDataModelVariables() { - return Data(); - } + virtual void eventFromSCXML(const std::string& target, const Event& event) {} + virtual bool isValidTarget(const std::string& target) { + return true; + } + + virtual Data getDataModelVariables() { + return Data(); + } }; } diff --git a/src/bindings/swig/wrapped/WrappedInterpreterMonitor.cpp b/src/bindings/swig/wrapped/WrappedInterpreterMonitor.cpp index cdb46de..f563539 100644 --- a/src/bindings/swig/wrapped/WrappedInterpreterMonitor.cpp +++ b/src/bindings/swig/wrapped/WrappedInterpreterMonitor.cpp @@ -26,122 +26,122 @@ namespace uscxml { using namespace XERCESC_NS; - + WrappedInterpreterMonitor::WrappedInterpreterMonitor() {} WrappedInterpreterMonitor::~WrappedInterpreterMonitor() {} void WrappedInterpreterMonitor::beforeExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) { - std::stringstream ss; - ss << *state; - beforeExitingState(ATTR(state, "id"), DOMUtils::xPathForNode(state), ss.str()); + std::stringstream ss; + ss << *state; + beforeExitingState(ATTR(state, "id"), DOMUtils::xPathForNode(state), ss.str()); } void WrappedInterpreterMonitor::afterExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) { - std::stringstream ss; - ss << *state; - afterExitingState(ATTR(state, "id"), DOMUtils::xPathForNode(state), ss.str()); + std::stringstream ss; + ss << *state; + afterExitingState(ATTR(state, "id"), DOMUtils::xPathForNode(state), ss.str()); } void WrappedInterpreterMonitor::beforeExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* content) { - std::stringstream ss; - ss << *content; - beforeExecutingContent(TAGNAME(content), DOMUtils::xPathForNode(content), ss.str()); + std::stringstream ss; + ss << *content; + beforeExecutingContent(TAGNAME(content), DOMUtils::xPathForNode(content), ss.str()); } void WrappedInterpreterMonitor::afterExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* content) { - std::stringstream ss; - ss << *content; - afterExecutingContent(TAGNAME(content), DOMUtils::xPathForNode(content), ss.str()); + std::stringstream ss; + ss << *content; + afterExecutingContent(TAGNAME(content), DOMUtils::xPathForNode(content), ss.str()); } void WrappedInterpreterMonitor::beforeUninvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invoker, const std::string& invokeid) { - std::stringstream ss; - ss << *invoker; - std::string invokeId; - if (invoker->getUserData(X("invokeid")) != NULL) { - invokeId = (char*)invoker->getUserData(X("invokeid")); - } - - beforeUninvoking(DOMUtils::xPathForNode(invoker), invokeId, ss.str()); + std::stringstream ss; + ss << *invoker; + std::string invokeId; + if (invoker->getUserData(X("invokeid")) != NULL) { + invokeId = (char*)invoker->getUserData(X("invokeid")); + } + + beforeUninvoking(DOMUtils::xPathForNode(invoker), invokeId, ss.str()); } void WrappedInterpreterMonitor::afterUninvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invoker, const std::string& invokeid) { - std::stringstream ss; - ss << *invoker; - std::string invokeId; - if (invoker->getUserData(X("invokeid")) != NULL) { - invokeId = (char*)invoker->getUserData(X("invokeid")); - } - - afterUninvoking(DOMUtils::xPathForNode(invoker), invokeId, ss.str()); + std::stringstream ss; + ss << *invoker; + std::string invokeId; + if (invoker->getUserData(X("invokeid")) != NULL) { + invokeId = (char*)invoker->getUserData(X("invokeid")); + } + + afterUninvoking(DOMUtils::xPathForNode(invoker), invokeId, ss.str()); } void WrappedInterpreterMonitor::beforeTakingTransition(Interpreter& interpreter, const XERCESC_NS::DOMElement* transition) { - XERCESC_NS::DOMElement* sourceState = getSourceState(transition); - const XERCESC_NS::DOMElement* root = DOMUtils::getNearestAncestor(transition, "scxml"); - - std::list<XERCESC_NS::DOMElement*> targetStates = getTargetStates(transition, root); - - std::stringstream ss; - ss << *transition; - - std::list<std::string> targets; - for (auto t : targetStates) { - targets.push_back(ATTR_CAST(t, "id")); - } - - beforeTakingTransition(DOMUtils::xPathForNode(transition), ATTR_CAST(sourceState, "id"), targets, ss.str()); + XERCESC_NS::DOMElement* sourceState = getSourceState(transition); + const XERCESC_NS::DOMElement* root = DOMUtils::getNearestAncestor(transition, "scxml"); + + std::list<XERCESC_NS::DOMElement*> targetStates = getTargetStates(transition, root); + + std::stringstream ss; + ss << *transition; + + std::list<std::string> targets; + for (auto t : targetStates) { + targets.push_back(ATTR_CAST(t, "id")); + } + + beforeTakingTransition(DOMUtils::xPathForNode(transition), ATTR_CAST(sourceState, "id"), targets, ss.str()); } void WrappedInterpreterMonitor::afterTakingTransition(Interpreter& interpreter, const XERCESC_NS::DOMElement* transition) { - XERCESC_NS::DOMElement* sourceState = getSourceState(transition); - const XERCESC_NS::DOMElement* root = DOMUtils::getNearestAncestor(transition, "scxml"); - - std::list<XERCESC_NS::DOMElement*> targetStates = getTargetStates(transition, root); - - std::stringstream ss; - ss << *transition; - - std::list<std::string> targets; - for (auto t : targetStates) { - targets.push_back(ATTR_CAST(t, "id")); - } - - afterTakingTransition(DOMUtils::xPathForNode(transition), ATTR_CAST(sourceState, "id"), targets, ss.str()); + XERCESC_NS::DOMElement* sourceState = getSourceState(transition); + const XERCESC_NS::DOMElement* root = DOMUtils::getNearestAncestor(transition, "scxml"); + + std::list<XERCESC_NS::DOMElement*> targetStates = getTargetStates(transition, root); + + std::stringstream ss; + ss << *transition; + + std::list<std::string> targets; + for (auto t : targetStates) { + targets.push_back(ATTR_CAST(t, "id")); + } + + afterTakingTransition(DOMUtils::xPathForNode(transition), ATTR_CAST(sourceState, "id"), targets, ss.str()); } void WrappedInterpreterMonitor::beforeEnteringState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) { - std::stringstream ss; - ss << *state; - beforeEnteringState(ATTR(state, "id"), DOMUtils::xPathForNode(state), ss.str()); + std::stringstream ss; + ss << *state; + beforeEnteringState(ATTR(state, "id"), DOMUtils::xPathForNode(state), ss.str()); } void WrappedInterpreterMonitor::afterEnteringState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) { - std::stringstream ss; - ss << *state; - afterEnteringState(ATTR(state, "id"), DOMUtils::xPathForNode(state), ss.str()); + std::stringstream ss; + ss << *state; + afterEnteringState(ATTR(state, "id"), DOMUtils::xPathForNode(state), ss.str()); } void WrappedInterpreterMonitor::beforeInvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invoker, const std::string& invokeid) { - std::stringstream ss; - ss << *invoker; - std::string invokeId; - if (invoker->getUserData(X("invokeid")) != NULL) { - invokeId = (char*)invoker->getUserData(X("invokeid")); - } - - beforeInvoking(DOMUtils::xPathForNode(invoker), invokeId, ss.str()); + std::stringstream ss; + ss << *invoker; + std::string invokeId; + if (invoker->getUserData(X("invokeid")) != NULL) { + invokeId = (char*)invoker->getUserData(X("invokeid")); + } + + beforeInvoking(DOMUtils::xPathForNode(invoker), invokeId, ss.str()); } void WrappedInterpreterMonitor::afterInvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invoker, const std::string& invokeid) { - std::stringstream ss; - ss << *invoker; - std::string invokeId; - if (invoker->getUserData(X("invokeid")) != NULL) { - invokeId = (char*)invoker->getUserData(X("invokeid")); - } - - afterInvoking(DOMUtils::xPathForNode(invoker), invokeId, ss.str()); + std::stringstream ss; + ss << *invoker; + std::string invokeId; + if (invoker->getUserData(X("invokeid")) != NULL) { + invokeId = (char*)invoker->getUserData(X("invokeid")); + } + + afterInvoking(DOMUtils::xPathForNode(invoker), invokeId, ss.str()); } }
\ No newline at end of file diff --git a/src/bindings/swig/wrapped/WrappedInterpreterMonitor.h b/src/bindings/swig/wrapped/WrappedInterpreterMonitor.h index e05dad2..697a420 100644 --- a/src/bindings/swig/wrapped/WrappedInterpreterMonitor.h +++ b/src/bindings/swig/wrapped/WrappedInterpreterMonitor.h @@ -34,7 +34,7 @@ // forward declare namespace XERCESC_NS { - class DOMElement; +class DOMElement; } namespace uscxml { @@ -44,100 +44,100 @@ public: WrappedInterpreterMonitor(); virtual ~WrappedInterpreterMonitor(); - virtual void beforeProcessingEvent(Interpreter& interpreter, const Event& event) {} - virtual void beforeMicroStep(Interpreter& interpreter) {} + virtual void beforeProcessingEvent(Interpreter& interpreter, const Event& event) {} + virtual void beforeMicroStep(Interpreter& interpreter) {} - void beforeExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state); - virtual void beforeExitingState(const std::string& stateId, + void beforeExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state); + virtual void beforeExitingState(const std::string& stateId, const std::string& xpath, const std::string& stateXML) {} - void afterExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state); - virtual void afterExitingState(const std::string& stateId, - const std::string& xpath, - const std::string& stateXML) {} + void afterExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state); + virtual void afterExitingState(const std::string& stateId, + const std::string& xpath, + const std::string& stateXML) {} - void beforeExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* content); - virtual void beforeExecutingContent(const std::string& tagName, + void beforeExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* content); + virtual void beforeExecutingContent(const std::string& tagName, const std::string& xpath, const std::string& contentXML) {} - void afterExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* content); - virtual void afterExecutingContent(const std::string& tagName, + void afterExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* content); + virtual void afterExecutingContent(const std::string& tagName, const std::string& xpath, const std::string& contentXML) {} void beforeUninvoking(Interpreter& interpreter, - const XERCESC_NS::DOMElement* invoker, - const std::string& invokeid); + const XERCESC_NS::DOMElement* invoker, + const std::string& invokeid); virtual void beforeUninvoking(const std::string& xpath, const std::string& invokeid, const std::string& invokerXML) {} void afterUninvoking(Interpreter& interpreter, - const XERCESC_NS::DOMElement* invoker, - const std::string& invokeid); - virtual void afterUninvoking(const std::string& xpath, + const XERCESC_NS::DOMElement* invoker, + const std::string& invokeid); + virtual void afterUninvoking(const std::string& xpath, const std::string& invokeid, const std::string& invokerXML) {} - void beforeTakingTransition(Interpreter& interpreter, - const XERCESC_NS::DOMElement* transition); + void beforeTakingTransition(Interpreter& interpreter, + const XERCESC_NS::DOMElement* transition); virtual void beforeTakingTransition(const std::string& xpath, const std::string& source, const std::list<std::string>& targets, const std::string& transitionXML) {} - void afterTakingTransition(Interpreter& interpreter, - const XERCESC_NS::DOMElement* transition); - virtual void afterTakingTransition(const std::string& xpath, + void afterTakingTransition(Interpreter& interpreter, + const XERCESC_NS::DOMElement* transition); + virtual void afterTakingTransition(const std::string& xpath, const std::string& source, const std::list<std::string>& targets, const std::string& transitionXML) {} - void beforeEnteringState(Interpreter& interpreter, - const XERCESC_NS::DOMElement* state); - virtual void beforeEnteringState(const std::string& stateId, + void beforeEnteringState(Interpreter& interpreter, + const XERCESC_NS::DOMElement* state); + virtual void beforeEnteringState(const std::string& stateId, const std::string& xpath, const std::string& stateXML) {} - void afterEnteringState(Interpreter& interpreter, - const XERCESC_NS::DOMElement* state); - virtual void afterEnteringState(const std::string& stateId, + void afterEnteringState(Interpreter& interpreter, + const XERCESC_NS::DOMElement* state); + virtual void afterEnteringState(const std::string& stateId, const std::string& xpath, const std::string& stateXML) {} void beforeInvoking(Interpreter& interpreter, - const XERCESC_NS::DOMElement* invoker, - const std::string& invokeid); - virtual void beforeInvoking(const std::string& xpath, + const XERCESC_NS::DOMElement* invoker, + const std::string& invokeid); + virtual void beforeInvoking(const std::string& xpath, const std::string& invokeid, const std::string& invokerXML) {} - void afterInvoking(Interpreter& interpreter, - const XERCESC_NS::DOMElement* invoker, - const std::string& invokeid); - virtual void afterInvoking(const std::string& xpath, + void afterInvoking(Interpreter& interpreter, + const XERCESC_NS::DOMElement* invoker, + const std::string& invokeid); + virtual void afterInvoking(const std::string& xpath, const std::string& invokeid, const std::string& invokerXML) {} - virtual void afterMicroStep(Interpreter& interpreter) {} - virtual void onStableConfiguration(Interpreter& interpreter) {} - - virtual void beforeCompletion(Interpreter& interpreter) {} - virtual void afterCompletion(Interpreter& interpreter) {} + virtual void afterMicroStep(Interpreter& interpreter) {} + virtual void onStableConfiguration(Interpreter& interpreter) {} + + virtual void beforeCompletion(Interpreter& interpreter) {} + virtual void afterCompletion(Interpreter& interpreter) {} virtual void reportIssue(Interpreter& interpreter, - const InterpreterIssue& issue) {} + const InterpreterIssue& issue) {} }; } diff --git a/src/bindings/swig/wrapped/WrappedInvoker.cpp b/src/bindings/swig/wrapped/WrappedInvoker.cpp index ba76420..407323d 100644 --- a/src/bindings/swig/wrapped/WrappedInvoker.cpp +++ b/src/bindings/swig/wrapped/WrappedInvoker.cpp @@ -22,7 +22,7 @@ namespace uscxml { WrappedInvoker::WrappedInvoker(InterpreterImpl* interpreter) { - _interpreter = interpreter; + _interpreter = interpreter; } WrappedInvoker::~WrappedInvoker() {} diff --git a/src/bindings/swig/wrapped/WrappedInvoker.h b/src/bindings/swig/wrapped/WrappedInvoker.h index 3eb4a22..bb5d1ba 100644 --- a/src/bindings/swig/wrapped/WrappedInvoker.h +++ b/src/bindings/swig/wrapped/WrappedInvoker.h @@ -33,7 +33,7 @@ // forward declare namespace XERCESC_NS { - class DOMElement; +class DOMElement; } namespace uscxml { @@ -42,37 +42,37 @@ class WrappedInvoker : public InvokerImpl { public: WrappedInvoker(InterpreterImpl* interpreter); virtual ~WrappedInvoker(); - - virtual std::list<std::string> getNames() { - return std::list<std::string>(); - }; - - virtual std::shared_ptr<InvokerImpl> create(InterpreterImpl* interpreter) { - std::shared_ptr<InvokerImpl> inv = std::shared_ptr<InvokerImpl>(new WrappedInvoker(interpreter)); - return inv; - } - virtual void invoke(const std::string& source, const Event& invokeEvent) {} - virtual void uninvoke() {} - - virtual void eventFromSCXML(const Event& event) {} - - virtual XERCESC_NS::DOMElement* getFinalize() { - return _finalize; - } - virtual void setFinalize(XERCESC_NS::DOMElement* finalize) { - _finalize = finalize; - } - virtual void setInvokeId(const std::string& invokeId) { - _invokeId = invokeId; - } - - virtual Data getDataModelVariables() { - return Data(); - } - - void eventToSCXML(Event& event, const std::string& type, const std::string& invokeId, bool internal = false) { - - } + + virtual std::list<std::string> getNames() { + return std::list<std::string>(); + }; + + virtual std::shared_ptr<InvokerImpl> create(InterpreterImpl* interpreter) { + std::shared_ptr<InvokerImpl> inv = std::shared_ptr<InvokerImpl>(new WrappedInvoker(interpreter)); + return inv; + } + virtual void invoke(const std::string& source, const Event& invokeEvent) {} + virtual void uninvoke() {} + + virtual void eventFromSCXML(const Event& event) {} + + virtual XERCESC_NS::DOMElement* getFinalize() { + return _finalize; + } + virtual void setFinalize(XERCESC_NS::DOMElement* finalize) { + _finalize = finalize; + } + virtual void setInvokeId(const std::string& invokeId) { + _invokeId = invokeId; + } + + virtual Data getDataModelVariables() { + return Data(); + } + + void eventToSCXML(Event& event, const std::string& type, const std::string& invokeId, bool internal = false) { + + } private: InterpreterImpl* _interpreter; diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index 1d348fd..1e8c931 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -219,7 +219,7 @@ void Interpreter::setActionLanguage(ActionLanguage actionLanguage) { } void Interpreter::setFactory(Factory* factory) { - return _impl->setFactory(factory); + return _impl->setFactory(factory); } void Interpreter::addMonitor(InterpreterMonitor* monitor) { @@ -227,7 +227,7 @@ void Interpreter::addMonitor(InterpreterMonitor* monitor) { } void Interpreter::removeMonitor(InterpreterMonitor* monitor) { - return _impl->removeMonitor(monitor); + return _impl->removeMonitor(monitor); } std::list<InterpreterIssue> Interpreter::validate() { diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h index f87053f..6c60350 100644 --- a/src/uscxml/Interpreter.h +++ b/src/uscxml/Interpreter.h @@ -118,7 +118,7 @@ public: */ PIMPL_OPERATORS(Interpreter); - /** + /** * Advance the state-machine by a single microstep and return. * * This is the central function to drive the state machine. Calling step() @@ -179,22 +179,22 @@ public: */ void setActionLanguage(ActionLanguage actionLanguage); - /** - * Provide a custom Factory to instantiate dynamic instances for this and invoked state-chart instances. - */ - void setFactory(Factory* factory); + /** + * Provide a custom Factory to instantiate dynamic instances for this and invoked state-chart instances. + */ + void setFactory(Factory* factory); /** * Attach a monitor to make more details of the interpreter observable. */ - void addMonitor(InterpreterMonitor* monitor); - - /** - * Remove a monitor that was attached previously. - */ - void removeMonitor(InterpreterMonitor* monitor); + void addMonitor(InterpreterMonitor* monitor); + + /** + * Remove a monitor that was attached previously. + */ + void removeMonitor(InterpreterMonitor* monitor); + - /** * Return the actual implementation of the Interperter. */ diff --git a/src/uscxml/debug/Breakpoint.cpp b/src/uscxml/debug/Breakpoint.cpp index 3287075..7b9d5c9 100644 --- a/src/uscxml/debug/Breakpoint.cpp +++ b/src/uscxml/debug/Breakpoint.cpp @@ -244,7 +244,7 @@ bool Breakpoint::matches(Interpreter interpreter, const Breakpoint& other) const return InterpreterImpl::isMember(other.element, nodes); } #endif - + if(transSourceId.length() > 0 && transSourceId != other.transSourceId) { return false; } @@ -255,7 +255,7 @@ bool Breakpoint::matches(Interpreter interpreter, const Breakpoint& other) const if (condition.length() > 0) { try { - interpreter.getImpl()->isTrue(condition); + interpreter.getImpl()->isTrue(condition); } catch (...) { return false; } diff --git a/src/uscxml/debug/Breakpoint.h b/src/uscxml/debug/Breakpoint.h index 3809663..feaf221 100644 --- a/src/uscxml/debug/Breakpoint.h +++ b/src/uscxml/debug/Breakpoint.h @@ -28,7 +28,7 @@ // forward declare namespace XERCESC_NS { - class DOMElement; +class DOMElement; } namespace uscxml { @@ -76,7 +76,7 @@ public: Subject subject; Action action; - const XERCESC_NS::DOMElement* element = NULL; + const XERCESC_NS::DOMElement* element = NULL; std::string invokeId; std::string invokeType; diff --git a/src/uscxml/debug/DebugSession.cpp b/src/uscxml/debug/DebugSession.cpp index 60dcdfb..4d64443 100644 --- a/src/uscxml/debug/DebugSession.cpp +++ b/src/uscxml/debug/DebugSession.cpp @@ -74,21 +74,21 @@ void DebugSession::checkBreakpoints(const std::list<Breakpoint> qualifiedBreakpo void DebugSession::breakExecution(Data replyData) { std::lock_guard<std::recursive_mutex> lock(_mutex); - std::list<XERCESC_NS::DOMElement*> configuration = _interpreter.getConfiguration(); - for (auto state : configuration) { - if (HAS_ATTR(state, "id")) { - replyData.compound["activeStates"].array.push_back(Data(ATTR(state, "id"), Data::VERBATIM)); - if (isAtomic(state)) { - replyData.compound["basicStates"].array.push_back(Data(ATTR(state, "id"), Data::VERBATIM)); - } - } - } + std::list<XERCESC_NS::DOMElement*> configuration = _interpreter.getConfiguration(); + for (auto state : configuration) { + if (HAS_ATTR(state, "id")) { + replyData.compound["activeStates"].array.push_back(Data(ATTR(state, "id"), Data::VERBATIM)); + if (isAtomic(state)) { + replyData.compound["basicStates"].array.push_back(Data(ATTR(state, "id"), Data::VERBATIM)); + } + } + } replyData.compound["replyType"] = Data("breakpoint", Data::VERBATIM); _debugger->pushData(shared_from_this(), replyData); - - // wait for resume from the client - _resumeCond.wait(_mutex); + + // wait for resume from the client + _resumeCond.wait(_mutex); } Data DebugSession::debugPrepare(const Data& data) { @@ -104,23 +104,23 @@ Data DebugSession::debugPrepare(const Data& data) { _isAttached = false; - try { - if (data.hasKey("xml")) { - _interpreter = Interpreter::fromXML(data.at("xml").atom, (data.hasKey("url") ? data.at("url").atom : "")); - } else if (data.hasKey("url")) { - _interpreter = Interpreter::fromURL(data.at("url").atom); - } else { - _interpreter = Interpreter(); - } - } catch(ErrorEvent e) { - std::cerr << e; - } catch(...) {} - + try { + if (data.hasKey("xml")) { + _interpreter = Interpreter::fromXML(data.at("xml").atom, (data.hasKey("url") ? data.at("url").atom : "")); + } else if (data.hasKey("url")) { + _interpreter = Interpreter::fromURL(data.at("url").atom); + } else { + _interpreter = Interpreter(); + } + } catch(ErrorEvent e) { + std::cerr << e; + } catch(...) {} + if (_interpreter) { // register ourself as a monitor _interpreter.addMonitor(_debugger); _debugger->attachSession(_interpreter.getImpl().get(), shared_from_this()); - + replyData.compound["status"] = Data("success", Data::VERBATIM); } else { replyData.compound["status"] = Data("failure", Data::VERBATIM); @@ -143,8 +143,8 @@ Data DebugSession::debugAttach(const Data& data) { bool interpreterFound = false; // find interpreter for sessionid - std::map<std::string, std::weak_ptr<InterpreterImpl> > instances = InterpreterImpl::getInstances(); - for (auto weakInstance : instances) { + std::map<std::string, std::weak_ptr<InterpreterImpl> > instances = InterpreterImpl::getInstances(); + for (auto weakInstance : instances) { std::shared_ptr<InterpreterImpl> instance = weakInstance.second.lock(); if (instance && instance->getSessionId() == interpreterId) { @@ -185,8 +185,8 @@ Data DebugSession::debugStart(const Data& data) { replyData.compound["reason"] = Data("No interpreter attached or loaded", Data::VERBATIM); replyData.compound["status"] = Data("failure", Data::VERBATIM); } else { - _isRunning = true; - _interpreterThread = new std::thread(DebugSession::run, this); + _isRunning = true; + _interpreterThread = new std::thread(DebugSession::run, this); replyData.compound["status"] = Data("success", Data::VERBATIM); } @@ -194,28 +194,28 @@ Data DebugSession::debugStart(const Data& data) { } void DebugSession::run(void* instance) { - DebugSession* INSTANCE = (DebugSession*)instance; - + DebugSession* INSTANCE = (DebugSession*)instance; + #ifdef APPLE - std::string threadName; - threadName += "uscxml::"; - threadName += (INSTANCE->_interpreter.getImpl()->_name.size() > 0 ? INSTANCE->_interpreter.getImpl()->_name : "anon"); - threadName += ".debug"; - - pthread_setname_np(threadName.c_str()); + std::string threadName; + threadName += "uscxml::"; + threadName += (INSTANCE->_interpreter.getImpl()->_name.size() > 0 ? INSTANCE->_interpreter.getImpl()->_name : "anon"); + threadName += ".debug"; + + pthread_setname_np(threadName.c_str()); #endif - - InterpreterState state = USCXML_UNDEF; - while(state != USCXML_FINISHED && INSTANCE->_isRunning) { - state = INSTANCE->_interpreter.step(); - - // if (!INSTANCE->_isStarted) { - // // we have been cancelled - // INSTANCE->_isActive = false; - // return; - // } - } - LOG(DEBUG) << "done"; + + InterpreterState state = USCXML_UNDEF; + while(state != USCXML_FINISHED && INSTANCE->_isRunning) { + state = INSTANCE->_interpreter.step(); + + // if (!INSTANCE->_isStarted) { + // // we have been cancelled + // INSTANCE->_isActive = false; + // return; + // } + } + LOG(DEBUG) << "done"; } Data DebugSession::debugStop(const Data& data) { @@ -226,11 +226,11 @@ Data DebugSession::debugStop(const Data& data) { _debugger->detachSession(_interpreter.getImpl().get()); } - if (_isRunning && _interpreterThread != NULL) { - _isRunning = false; - _interpreterThread->join(); - delete(_interpreterThread); - } + if (_isRunning && _interpreterThread != NULL) { + _isRunning = false; + _interpreterThread->join(); + delete(_interpreterThread); + } // unblock _resumeCond.notify_all(); @@ -252,11 +252,11 @@ Data DebugSession::debugStep(const Data& data) { Data replyData; if (_interpreter) { // register ourself as a monitor - if (!_isRunning) { - _isRunning = true; - _interpreterThread = new std::thread(DebugSession::run, this); + if (!_isRunning) { + _isRunning = true; + _interpreterThread = new std::thread(DebugSession::run, this); - } + } replyData.compound["status"] = Data("success", Data::VERBATIM); } else { @@ -294,19 +294,19 @@ Data DebugSession::skipToBreakPoint(const Data& data) { std::lock_guard<std::recursive_mutex> lock(_mutex); _skipTo = Breakpoint(data); - Data replyData; - - if (_interpreter) { - // register ourself as a monitor - if (!_isRunning) { - _isRunning = true; - _interpreterThread = new std::thread(DebugSession::run, this); - } - - replyData.compound["status"] = Data("success", Data::VERBATIM); - } else { - replyData.compound["status"] = Data("failure", Data::VERBATIM); - } + Data replyData; + + if (_interpreter) { + // register ourself as a monitor + if (!_isRunning) { + _isRunning = true; + _interpreterThread = new std::thread(DebugSession::run, this); + } + + replyData.compound["status"] = Data("success", Data::VERBATIM); + } else { + replyData.compound["status"] = Data("failure", Data::VERBATIM); + } _resumeCond.notify_one(); return replyData; diff --git a/src/uscxml/debug/DebugSession.h b/src/uscxml/debug/DebugSession.h index c4f2564..fbfd065 100644 --- a/src/uscxml/debug/DebugSession.h +++ b/src/uscxml/debug/DebugSession.h @@ -34,8 +34,8 @@ class Debugger; class USCXML_API DebugSession : public std::enable_shared_from_this<DebugSession> { public: DebugSession() { - _isRunning = false; - _isStepping = false; + _isRunning = false; + _isStepping = false; _isAttached = false; _breakpointsEnabled = true; _markedForDeletion = false; @@ -88,9 +88,9 @@ protected: std::recursive_mutex _runMutex; std::recursive_mutex _mutex; - std::thread* _interpreterThread = NULL; - bool _isRunning; - static void run(void* instance); + std::thread* _interpreterThread = NULL; + bool _isRunning; + static void run(void* instance); bool _markedForDeletion; Debugger* _debugger; @@ -98,7 +98,7 @@ protected: std::set<Breakpoint> _breakPoints; Breakpoint _skipTo; - friend class Debugger; + friend class Debugger; }; diff --git a/src/uscxml/debug/Debugger.cpp b/src/uscxml/debug/Debugger.cpp index 1f13e40..9478927 100644 --- a/src/uscxml/debug/Debugger.cpp +++ b/src/uscxml/debug/Debugger.cpp @@ -25,7 +25,7 @@ namespace uscxml { void Debugger::afterCompletion(Interpreter& interpreter) { - InterpreterImpl* impl = interpreter.getImpl().get(); + InterpreterImpl* impl = interpreter.getImpl().get(); std::shared_ptr<DebugSession> session = getSession(impl); if (!session) return; @@ -72,9 +72,9 @@ std::list<Breakpoint> Debugger::getQualifiedTransBreakpoints(InterpreterImpl* im std::list<Breakpoint> breakpoints; XERCESC_NS::DOMElement* source = getSourceState(transition); - std::list<XERCESC_NS::DOMElement*> targets = getTargetStates(transition, impl->_scxml); + std::list<XERCESC_NS::DOMElement*> targets = getTargetStates(transition, impl->_scxml); - for (auto target : targets) { + for (auto target : targets) { Breakpoint bp = breakpointTemplate; // copy base as template bp.element = transition; @@ -143,9 +143,9 @@ void Debugger::handleExecutable(Interpreter& interpreter, std::shared_ptr<DebugSession> session = getSession(interpreter.getImpl().get()); if (!session) return; - if (!session->_isRunning) - return; - + if (!session->_isRunning) + return; + std::list<Breakpoint> breakpoints; Breakpoint breakpoint; @@ -160,12 +160,12 @@ void Debugger::handleExecutable(Interpreter& interpreter, } void Debugger::handleEvent(Interpreter& interpreter, const Event& event, Breakpoint::When when) { - InterpreterImpl* impl = interpreter.getImpl().get(); - std::shared_ptr<DebugSession> session = getSession(impl); - if (!session) - return; - if (!session->_isRunning) - return; + InterpreterImpl* impl = interpreter.getImpl().get(); + std::shared_ptr<DebugSession> session = getSession(impl); + if (!session) + return; + if (!session->_isRunning) + return; std::list<Breakpoint> breakpoints; @@ -180,12 +180,12 @@ void Debugger::handleEvent(Interpreter& interpreter, const Event& event, Breakpo } void Debugger::handleStable(Interpreter& interpreter, Breakpoint::When when) { - InterpreterImpl* impl = interpreter.getImpl().get(); - std::shared_ptr<DebugSession> session = getSession(impl); - if (!session) - return; - if (!session->_isRunning) - return; + InterpreterImpl* impl = interpreter.getImpl().get(); + std::shared_ptr<DebugSession> session = getSession(impl); + if (!session) + return; + if (!session->_isRunning) + return; std::list<Breakpoint> breakpoints; @@ -198,12 +198,12 @@ void Debugger::handleStable(Interpreter& interpreter, Breakpoint::When when) { } void Debugger::handleMicrostep(Interpreter& interpreter, Breakpoint::When when) { - InterpreterImpl* impl = interpreter.getImpl().get(); - std::shared_ptr<DebugSession> session = getSession(impl); - if (!session) - return; - if (!session->_isRunning) - return; + InterpreterImpl* impl = interpreter.getImpl().get(); + std::shared_ptr<DebugSession> session = getSession(impl); + if (!session) + return; + if (!session->_isRunning) + return; std::list<Breakpoint> breakpoints; @@ -216,12 +216,12 @@ void Debugger::handleMicrostep(Interpreter& interpreter, Breakpoint::When when) } void Debugger::handleTransition(Interpreter& interpreter, const XERCESC_NS::DOMElement* transition, Breakpoint::When when) { - InterpreterImpl* impl = interpreter.getImpl().get(); - std::shared_ptr<DebugSession> session = getSession(impl); - if (!session) - return; - if (!session->_isRunning) - return; + InterpreterImpl* impl = interpreter.getImpl().get(); + std::shared_ptr<DebugSession> session = getSession(impl); + if (!session) + return; + if (!session->_isRunning) + return; Breakpoint breakpointTemplate; breakpointTemplate.when = when; @@ -230,12 +230,12 @@ void Debugger::handleTransition(Interpreter& interpreter, const XERCESC_NS::DOME } void Debugger::handleState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state, Breakpoint::When when, Breakpoint::Action action) { - InterpreterImpl* impl = interpreter.getImpl().get(); - std::shared_ptr<DebugSession> session = getSession(impl); - if (!session) - return; - if (!session->_isRunning) - return; + InterpreterImpl* impl = interpreter.getImpl().get(); + std::shared_ptr<DebugSession> session = getSession(impl); + if (!session) + return; + if (!session->_isRunning) + return; Breakpoint breakpointTemplate; breakpointTemplate.when = when; @@ -246,12 +246,12 @@ void Debugger::handleState(Interpreter& interpreter, const XERCESC_NS::DOMElemen } void Debugger::handleInvoke(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeId, Breakpoint::When when, Breakpoint::Action action) { - InterpreterImpl* impl = interpreter.getImpl().get(); - std::shared_ptr<DebugSession> session = getSession(impl); - if (!session) - return; - if (!session->_isRunning) - return; + InterpreterImpl* impl = interpreter.getImpl().get(); + std::shared_ptr<DebugSession> session = getSession(impl); + if (!session) + return; + if (!session->_isRunning) + return; Breakpoint breakpointTemplate; breakpointTemplate.when = when; diff --git a/src/uscxml/debug/Debugger.h b/src/uscxml/debug/Debugger.h index 4b564cb..d69e6f6 100644 --- a/src/uscxml/debug/Debugger.h +++ b/src/uscxml/debug/Debugger.h @@ -55,24 +55,24 @@ public: virtual void pushData(std::shared_ptr<DebugSession> session, Data pushData) = 0; // InterpreterMonitor - virtual void beforeProcessingEvent(Interpreter& interpreter, const Event& event); - virtual void beforeMicroStep(Interpreter& interpreter); - virtual void beforeExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state); - virtual void afterExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state); - virtual void beforeExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* execContent); - virtual void afterExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* execContent); - virtual void beforeUninvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid); - virtual void afterUninvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid); - virtual void beforeTakingTransition(Interpreter& interpreter, const XERCESC_NS::DOMElement* transition); - virtual void afterTakingTransition(Interpreter& interpreter, const XERCESC_NS::DOMElement* transition); - virtual void beforeEnteringState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state); - virtual void afterEnteringState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state); - virtual void beforeInvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid); - virtual void afterInvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid); - virtual void afterMicroStep(Interpreter& interpreter); - virtual void onStableConfiguration(Interpreter& interpreter); - virtual void beforeCompletion(Interpreter& interpreter); - virtual void afterCompletion(Interpreter& interpreter); + virtual void beforeProcessingEvent(Interpreter& interpreter, const Event& event); + virtual void beforeMicroStep(Interpreter& interpreter); + virtual void beforeExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state); + virtual void afterExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state); + virtual void beforeExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* execContent); + virtual void afterExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* execContent); + virtual void beforeUninvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid); + virtual void afterUninvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid); + virtual void beforeTakingTransition(Interpreter& interpreter, const XERCESC_NS::DOMElement* transition); + virtual void afterTakingTransition(Interpreter& interpreter, const XERCESC_NS::DOMElement* transition); + virtual void beforeEnteringState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state); + virtual void afterEnteringState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state); + virtual void beforeInvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid); + virtual void afterInvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid); + virtual void afterMicroStep(Interpreter& interpreter); + virtual void onStableConfiguration(Interpreter& interpreter); + virtual void beforeCompletion(Interpreter& interpreter); + virtual void afterCompletion(Interpreter& interpreter); protected: @@ -95,19 +95,19 @@ protected: void handleMicrostep(Interpreter& interpreter, Breakpoint::When when); void handleEvent(Interpreter& interpreter, const Event& event, Breakpoint::When when); - std::list<Breakpoint> getQualifiedTransBreakpoints(InterpreterImpl* impl, - const XERCESC_NS::DOMElement* transition, - Breakpoint breakpointTemplate); - std::list<Breakpoint> getQualifiedStateBreakpoints(InterpreterImpl* impl, - const XERCESC_NS::DOMElement* state, - Breakpoint breakpointTemplate); - std::list<Breakpoint> getQualifiedInvokeBreakpoints(InterpreterImpl* impl, - const XERCESC_NS::DOMElement* invokeElem, - const std::string invokeId, - Breakpoint breakpointTemplate); + std::list<Breakpoint> getQualifiedTransBreakpoints(InterpreterImpl* impl, + const XERCESC_NS::DOMElement* transition, + Breakpoint breakpointTemplate); + std::list<Breakpoint> getQualifiedStateBreakpoints(InterpreterImpl* impl, + const XERCESC_NS::DOMElement* state, + Breakpoint breakpointTemplate); + std::list<Breakpoint> getQualifiedInvokeBreakpoints(InterpreterImpl* impl, + const XERCESC_NS::DOMElement* invokeElem, + const std::string invokeId, + Breakpoint breakpointTemplate); std::recursive_mutex _sessionMutex; - /// @todo: We ought to change form InterpreterImpl to Interpreter everywhere + /// @todo: We ought to change form InterpreterImpl to Interpreter everywhere std::map<InterpreterImpl*, std::shared_ptr<DebugSession> > _sessionForInterpreter; }; diff --git a/src/uscxml/debug/DebuggerServlet.cpp b/src/uscxml/debug/DebuggerServlet.cpp index 25df9dd..34c1eca 100644 --- a/src/uscxml/debug/DebuggerServlet.cpp +++ b/src/uscxml/debug/DebuggerServlet.cpp @@ -219,10 +219,10 @@ void DebuggerServlet::processDisconnect(const HTTPServer::Request& request) { void DebuggerServlet::processListSessions(const HTTPServer::Request& request) { Data replyData; - std::map<std::string, std::weak_ptr<InterpreterImpl> > instances = InterpreterImpl::getInstances(); - for (auto weakInstance : instances) { + std::map<std::string, std::weak_ptr<InterpreterImpl> > instances = InterpreterImpl::getInstances(); + for (auto weakInstance : instances) { - std::shared_ptr<InterpreterImpl> instance = weakInstance.second.lock(); + std::shared_ptr<InterpreterImpl> instance = weakInstance.second.lock(); if (instance) { Data sessionData; sessionData.compound["name"] = Data(instance->getName(), Data::VERBATIM); diff --git a/src/uscxml/debug/DebuggerServlet.h b/src/uscxml/debug/DebuggerServlet.h index 2ed1879..a1f18e3 100644 --- a/src/uscxml/debug/DebuggerServlet.h +++ b/src/uscxml/debug/DebuggerServlet.h @@ -34,7 +34,7 @@ public: class LogMessage : public Data { public: #if 0 - LogMessage(google::LogSeverity severity, const char* full_filename, + LogMessage(google::LogSeverity severity, const char* full_filename, const char* base_filename, int line, const struct ::tm* tm_time, std::string message, std::string formatted) { @@ -86,13 +86,13 @@ public: // void processPoll(const HTTPServer::Request& request); // Logsink - /** + /** virtual void send(google::LogSeverity severity, const char* full_filename, const char* base_filename, int line, const struct ::tm* tm_time, const char* message, size_t message_len); -*/ - void handle(const el::LogDispatchData* data); + */ + void handle(const el::LogDispatchData* data); protected: void serverPushData(std::shared_ptr<DebugSession>); diff --git a/src/uscxml/debug/InterpreterIssue.cpp b/src/uscxml/debug/InterpreterIssue.cpp index df2d125..90e06b4 100644 --- a/src/uscxml/debug/InterpreterIssue.cpp +++ b/src/uscxml/debug/InterpreterIssue.cpp @@ -39,7 +39,7 @@ InterpreterIssue::InterpreterIssue(const std::string& msg, DOMNode* node, IssueS // find all elements in the SCXML namespace in one traversal void assembleNodeSets(const std::string nsPrefix, DOMElement* node, std::map<std::string, std::list<DOMElement*> >& sets) { - for (auto childElem = node->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { + for (auto childElem = node->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { if (TAGNAME(childElem).find(nsPrefix) == 0) { // correct namespace, insert via localname @@ -57,7 +57,7 @@ std::list<std::set<const DOMElement* > > getAllConfigurations(const DOMElement* std::cout << *root; - for (auto childElem = root->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { + for (auto childElem = root->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { std::cout << *childElem; if (XMLString::compareIString(childElem->getTagName(), X(nsPrefix + "state")) == 0 || diff --git a/src/uscxml/interpreter/BasicContentExecutor.cpp b/src/uscxml/interpreter/BasicContentExecutor.cpp index f85e2b8..9f58b46 100644 --- a/src/uscxml/interpreter/BasicContentExecutor.cpp +++ b/src/uscxml/interpreter/BasicContentExecutor.cpp @@ -210,7 +210,7 @@ void BasicContentExecutor::processCancel(XERCESC_NS::DOMElement* content) { void BasicContentExecutor::processIf(XERCESC_NS::DOMElement* content) { bool blockIsTrue = _callbacks->isTrue(ATTR(content, "cond")); - for (auto childElem = content->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { + for (auto childElem = content->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { if (iequals(TAGNAME(childElem), XML_PREFIX(content).str() + "elseif")) { if (blockIsTrue) { // last block was true, break here @@ -252,7 +252,7 @@ void BasicContentExecutor::processForeach(XERCESC_NS::DOMElement* content) { for (uint32_t iteration = 0; iteration < iterations; iteration++) { _callbacks->setForeach(item, array, index, iteration); - for (auto childElem = content->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { + for (auto childElem = content->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { process(childElem, XML_PREFIX(content)); } } @@ -285,7 +285,7 @@ void BasicContentExecutor::process(XERCESC_NS::DOMElement* block, const X& xmlPr iequals(tagName, xmlPrefix.str() + "transition")) { try { - for (auto childElem = block->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { + for (auto childElem = block->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { // process any child eleents process(childElem, xmlPrefix); } @@ -404,7 +404,7 @@ void BasicContentExecutor::invoke(XERCESC_NS::DOMElement* element) { _callbacks->assign(ATTR(element, "idlocation"), Data(invokeEvent.invokeid, Data::VERBATIM)); } } - + // we need the invokeid to uninvoke char* invokeId = (char*)malloc(invokeEvent.invokeid.size() + 1); memcpy(invokeId, invokeEvent.invokeid.c_str(), invokeEvent.invokeid.size()); @@ -477,7 +477,7 @@ void BasicContentExecutor::uninvoke(XERCESC_NS::DOMElement* invoke) { _callbacks->uninvoke(invokeId); USCXML_MONITOR_CALLBACK2(_callbacks->getMonitors(), afterUninvoking, invoke, invokeId); - invoke->setUserData(X("invokeid"), NULL, NULL); + invoke->setUserData(X("invokeid"), NULL, NULL); free(invokeId); } @@ -558,7 +558,7 @@ Data BasicContentExecutor::elementAsData(XERCESC_NS::DOMElement* element) { if (HAS_ATTR(element, "expr")) { // return _callbacks->evalAsData(ATTR(element, "expr")); #if 0 - if (LOCALNAME(element) == "content") { + if (LOCALNAME(element) == "content") { // test 528 return _callbacks->evalAsData(ATTR(element, "expr")); } else { @@ -566,7 +566,7 @@ Data BasicContentExecutor::elementAsData(XERCESC_NS::DOMElement* element) { return Data(ATTR(element, "expr"), Data::INTERPRETED); } #endif - return _callbacks->evalAsData(ATTR(element, "expr")); + return _callbacks->evalAsData(ATTR(element, "expr")); } if (HAS_ATTR(element, "src")) { @@ -582,7 +582,7 @@ Data BasicContentExecutor::elementAsData(XERCESC_NS::DOMElement* element) { std::string content = url.getInContent(); // make an attempt to parse as XML - try { + try { XERCESC_NS::XercesDOMParser parser; parser.setValidationScheme(XERCESC_NS::XercesDOMParser::Val_Never); parser.setDoNamespaces(true); @@ -600,8 +600,8 @@ Data BasicContentExecutor::elementAsData(XERCESC_NS::DOMElement* element) { XERCESC_NS::DOMDocument* doc = parser.adoptDocument(); d.adoptedDoc = std::shared_ptr<XERCESC_NS::DOMDocument>(doc); d.node = doc->getDocumentElement(); - - return d; + + return d; } catch (...) { // just ignore and return as an interpreted string below diff --git a/src/uscxml/interpreter/BasicEventQueue.cpp b/src/uscxml/interpreter/BasicEventQueue.cpp index 3cf4daf..cc5ff04 100644 --- a/src/uscxml/interpreter/BasicEventQueue.cpp +++ b/src/uscxml/interpreter/BasicEventQueue.cpp @@ -36,11 +36,11 @@ Event BasicEventQueue::dequeue(size_t blockMs) { if (blockMs > 0) { - // block for given milliseconds or until queue is filled - auto endTime = std::chrono::system_clock::now() + std::chrono::milliseconds(blockMs); - - while (_queue.empty()) { - _cond.wait_until(_mutex, endTime); + // block for given milliseconds or until queue is filled + auto endTime = std::chrono::system_clock::now() + std::chrono::milliseconds(blockMs); + + while (_queue.empty()) { + _cond.wait_until(_mutex, endTime); } } @@ -61,8 +61,8 @@ void BasicEventQueue::enqueue(const Event& event) { } void BasicEventQueue::reset() { - std::lock_guard<std::recursive_mutex> lock(_mutex); - _queue.clear(); + std::lock_guard<std::recursive_mutex> lock(_mutex); + _queue.clear(); } static void dummyCallback(evutil_socket_t fd, short what, void *arg) { @@ -198,9 +198,9 @@ void BasicDelayedEventQueue::stop() { } void BasicDelayedEventQueue::reset() { - std::lock_guard<std::recursive_mutex> lock(_mutex); - cancelAllDelayed(); - _queue.clear(); + std::lock_guard<std::recursive_mutex> lock(_mutex); + cancelAllDelayed(); + _queue.clear(); } }
\ No newline at end of file diff --git a/src/uscxml/interpreter/BasicEventQueue.h b/src/uscxml/interpreter/BasicEventQueue.h index 1542e30..2bc739e 100644 --- a/src/uscxml/interpreter/BasicEventQueue.h +++ b/src/uscxml/interpreter/BasicEventQueue.h @@ -43,8 +43,8 @@ public: virtual ~BasicEventQueue(); virtual Event dequeue(size_t blockMs); virtual void enqueue(const Event& event); - virtual void reset(); - + virtual void reset(); + protected: std::list<Event> _queue; std::recursive_mutex _mutex; @@ -68,7 +68,7 @@ public: virtual void enqueue(const Event& event) { return BasicEventQueue::enqueue(event); } - virtual void reset(); + virtual void reset(); protected: struct callbackData { diff --git a/src/uscxml/interpreter/ContentExecutorImpl.h b/src/uscxml/interpreter/ContentExecutorImpl.h index ad4d695..ca565f0 100644 --- a/src/uscxml/interpreter/ContentExecutorImpl.h +++ b/src/uscxml/interpreter/ContentExecutorImpl.h @@ -66,7 +66,7 @@ public: /** Monitoring */ virtual std::set<InterpreterMonitor*> getMonitors() = 0; - virtual Interpreter getInterpreter() = 0; + virtual Interpreter getInterpreter() = 0; }; diff --git a/src/uscxml/interpreter/EventQueue.cpp b/src/uscxml/interpreter/EventQueue.cpp index 7ff0bfb..dd83f38 100644 --- a/src/uscxml/interpreter/EventQueue.cpp +++ b/src/uscxml/interpreter/EventQueue.cpp @@ -39,7 +39,7 @@ void EventQueue::enqueue(const Event& event) { return _impl->enqueue(event); } void EventQueue::reset() { - return _impl->reset(); + return _impl->reset(); } PIMPL_OPERATORS_INHERIT_IMPL(DelayedEventQueue, EventQueue) diff --git a/src/uscxml/interpreter/EventQueue.h b/src/uscxml/interpreter/EventQueue.h index 37b90be..79d0c26 100644 --- a/src/uscxml/interpreter/EventQueue.h +++ b/src/uscxml/interpreter/EventQueue.h @@ -38,7 +38,7 @@ public: virtual Event dequeue(size_t blockMs); virtual void enqueue(const Event& event); - virtual void reset(); + virtual void reset(); protected: std::shared_ptr<EventQueueImpl> _impl; diff --git a/src/uscxml/interpreter/EventQueueImpl.h b/src/uscxml/interpreter/EventQueueImpl.h index befd684..1f99226 100644 --- a/src/uscxml/interpreter/EventQueueImpl.h +++ b/src/uscxml/interpreter/EventQueueImpl.h @@ -42,7 +42,7 @@ class USCXML_API EventQueueImpl { public: virtual Event dequeue(size_t blockMs) = 0; virtual void enqueue(const Event& event) = 0; - virtual void reset() = 0; + virtual void reset() = 0; }; /** diff --git a/src/uscxml/interpreter/FastMicroStep.cpp b/src/uscxml/interpreter/FastMicroStep.cpp index 826df93..b0fda1f 100644 --- a/src/uscxml/interpreter/FastMicroStep.cpp +++ b/src/uscxml/interpreter/FastMicroStep.cpp @@ -91,24 +91,24 @@ FastMicroStep::~FastMicroStep() { void FastMicroStep::resortStates(DOMElement* element, const X& xmlPrefix) { - /** + /** initials deep histories shallow histories everything else */ - DOMElement* child = element->getFirstElementChild(); - while(child) { - resortStates(child, xmlPrefix); - child = child->getNextElementSibling(); - } + DOMElement* child = element->getFirstElementChild(); + while(child) { + resortStates(child, xmlPrefix); + child = child->getNextElementSibling(); + } // shallow history states to top child = element->getFirstElementChild(); while(child) { if (TAGNAME_CAST(child) == xmlPrefix.str() + "history" && - (!HAS_ATTR(element, "type") || iequals(ATTR(element, "type"), "shallow"))) { + (!HAS_ATTR(element, "type") || iequals(ATTR(element, "type"), "shallow"))) { DOMElement* tmp = child->getNextElementSibling(); if (child != element->getFirstChild()) { @@ -154,34 +154,34 @@ void FastMicroStep::resortStates(DOMElement* element, const X& xmlPrefix) { } std::list<XERCESC_NS::DOMElement*> FastMicroStep::getExitSetCached(const XERCESC_NS::DOMElement* transition, - const XERCESC_NS::DOMElement* root) { - - if (_cache.exitSet.find(transition) == _cache.exitSet.end()) { - _cache.exitSet[transition] = getExitSet(transition, root); - } - - return _cache.exitSet[transition]; + const XERCESC_NS::DOMElement* root) { + + if (_cache.exitSet.find(transition) == _cache.exitSet.end()) { + _cache.exitSet[transition] = getExitSet(transition, root); + } + + return _cache.exitSet[transition]; } bool FastMicroStep::conflictsCached(const DOMElement* t1, const DOMElement* t2, const DOMElement* root) { - if (getSourceState(t1) == getSourceState(t2)) - return true; - - if (DOMUtils::isDescendant(getSourceState(t1), getSourceState(t2))) - return true; - - if (DOMUtils::isDescendant(getSourceState(t2), getSourceState(t1))) - return true; - - if (DOMUtils::hasIntersection(getExitSetCached(t1, root), getExitSetCached(t2, root))) - return true; - - return false; + if (getSourceState(t1) == getSourceState(t2)) + return true; + + if (DOMUtils::isDescendant(getSourceState(t1), getSourceState(t2))) + return true; + + if (DOMUtils::isDescendant(getSourceState(t2), getSourceState(t1))) + return true; + + if (DOMUtils::hasIntersection(getExitSetCached(t1, root), getExitSetCached(t2, root))) + return true; + + return false; } - + void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) { - + _scxml = scxml; _binding = (HAS_ATTR(_scxml, "binding") && iequals(ATTR(_scxml, "binding"), "late") ? LATE : EARLY); _xmlPrefix = _scxml->getPrefix(); @@ -193,7 +193,7 @@ void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) { resortStates(_scxml, _xmlPrefix); // assert(false); // throw NULL; - + /** -- All things states -- */ std::list<XERCESC_NS::DOMElement*> tmp; @@ -356,8 +356,8 @@ void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) { assert(_transitions[i]->element != NULL); // std::cout << "i: " << i << std::endl << std::flush; std::list<DOMElement*> exitList = getExitSetCached(_transitions[i]->element, _scxml); - _cache.exitSet[_transitions[i]->element] = exitList; - + _cache.exitSet[_transitions[i]->element] = exitList; + for (j = 0; j < _states.size(); j++) { if (!exitList.empty() && _states[j]->element == exitList.front()) { _transitions[i]->exitSet[j] = true; @@ -369,7 +369,7 @@ void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) { assert(exitList.size() == 0); // establish the transitions' conflict set - for (j = i; j < _transitions.size(); j++) { + for (j = i; j < _transitions.size(); j++) { if (conflictsCached(_transitions[i]->element, _transitions[j]->element, _scxml)) { _transitions[i]->conflicts[j] = true; } else { @@ -377,13 +377,13 @@ void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) { } // std::cout << "."; } - - // conflicts matrix is symmetric - for (j = 0; j < i; j++) { - _transitions[i]->conflicts[j] = _transitions[j]->conflicts[i]; - } - + // conflicts matrix is symmetric + for (j = 0; j < i; j++) { + _transitions[i]->conflicts[j] = _transitions[j]->conflicts[i]; + } + + // establish the transitions' target set std::list<std::string> targets = tokenize(ATTR(_transitions[i]->element, "target")); for (auto tIter = targets.begin(); tIter != targets.end(); tIter++) { @@ -421,9 +421,9 @@ void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) { // the transitions event and condition _transitions[i]->event = (HAS_ATTR(_transitions[i]->element, "event") ? - ATTR(_transitions[i]->element, "event") : ""); + ATTR(_transitions[i]->element, "event") : ""); _transitions[i]->cond = (HAS_ATTR(_transitions[i]->element, "cond") ? - ATTR(_transitions[i]->element, "cond") : ""); + ATTR(_transitions[i]->element, "cond") : ""); // is there executable content? if (_transitions[i]->element->getChildElementCount() > 0) { @@ -431,7 +431,7 @@ void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) { } } - _cache.exitSet.clear(); + _cache.exitSet.clear(); _isInitialized = true; } @@ -942,11 +942,11 @@ ESTABLISH_ENTRYSET: // are we running in circles? if (_microstepConfigurations.find(_configuration) != _microstepConfigurations.end()) { - InterpreterIssue issue("Reentering same configuration during microstep - possible endless loop", - NULL, - InterpreterIssue::USCXML_ISSUE_WARNING); - - USCXML_MONITOR_CALLBACK1(_callbacks->getMonitors(), + InterpreterIssue issue("Reentering same configuration during microstep - possible endless loop", + NULL, + InterpreterIssue::USCXML_ISSUE_WARNING); + + USCXML_MONITOR_CALLBACK1(_callbacks->getMonitors(), reportIssue, issue); } @@ -1068,7 +1068,7 @@ std::list<DOMElement*> FastMicroStep::getCompletion(const DOMElement* state) { completion.push_back(initElems.front()); } else { // first child state - for (auto childElem = state->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { + for (auto childElem = state->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { if (isState(childElem)) { completion.push_back(childElem); break; diff --git a/src/uscxml/interpreter/FastMicroStep.h b/src/uscxml/interpreter/FastMicroStep.h index dd58480..1fbc8f4 100644 --- a/src/uscxml/interpreter/FastMicroStep.h +++ b/src/uscxml/interpreter/FastMicroStep.h @@ -91,10 +91,10 @@ protected: unsigned char type; }; - class CachedPredicates { - public: - std::map<const XERCESC_NS::DOMElement*, std::list<XERCESC_NS::DOMElement*> > exitSet; - }; + class CachedPredicates { + public: + std::map<const XERCESC_NS::DOMElement*, std::list<XERCESC_NS::DOMElement*> > exitSet; + }; virtual void init(XERCESC_NS::DOMElement* scxml); @@ -127,12 +127,12 @@ private: std::list<XERCESC_NS::DOMElement*> getHistoryCompletion(const XERCESC_NS::DOMElement* state); void resortStates(XERCESC_NS::DOMElement* node, const X& xmlPrefix); - bool conflictsCached(const XERCESC_NS::DOMElement* t1, const XERCESC_NS::DOMElement* t2, const XERCESC_NS::DOMElement* root); ///< overrides implementation Predicates::conflicts for speed + bool conflictsCached(const XERCESC_NS::DOMElement* t1, const XERCESC_NS::DOMElement* t2, const XERCESC_NS::DOMElement* root); ///< overrides implementation Predicates::conflicts for speed - std::list<XERCESC_NS::DOMElement*> getExitSetCached(const XERCESC_NS::DOMElement* transition, - const XERCESC_NS::DOMElement* root); + std::list<XERCESC_NS::DOMElement*> getExitSetCached(const XERCESC_NS::DOMElement* transition, + const XERCESC_NS::DOMElement* root); - CachedPredicates _cache; + CachedPredicates _cache; #ifdef USCXML_VERBOSE void printStateNames(const boost::dynamic_bitset<>& bitset); diff --git a/src/uscxml/interpreter/InterpreterImpl.cpp b/src/uscxml/interpreter/InterpreterImpl.cpp index 5cbae3c..d3b044a 100644 --- a/src/uscxml/interpreter/InterpreterImpl.cpp +++ b/src/uscxml/interpreter/InterpreterImpl.cpp @@ -82,27 +82,27 @@ InterpreterImpl::InterpreterImpl() : _isInitialized(false), _document(NULL), _sc InterpreterImpl::~InterpreterImpl() { - - // make sure we deallocate all user-data in the DOM, - // this is neccesary if we were aborted early - std::list<DOMElement*> invokes = DOMUtils::filterChildElements(_xmlPrefix.str() + "invoke", _scxml, true); - for (auto invoke : invokes) { - char* invokeId = (char*)invoke->getUserData(X("invokeid")); - if (invokeId != NULL) { - free(invokeId); - invoke->setUserData(X("invokeid"), NULL, NULL); - } - } - - if (_delayQueue) - _delayQueue.cancelAllDelayed(); - if (_document) - delete _document; - - { - std::lock_guard<std::recursive_mutex> lock(_instanceMutex); - _instances.erase(getSessionId()); - } + + // make sure we deallocate all user-data in the DOM, + // this is neccesary if we were aborted early + std::list<DOMElement*> invokes = DOMUtils::filterChildElements(_xmlPrefix.str() + "invoke", _scxml, true); + for (auto invoke : invokes) { + char* invokeId = (char*)invoke->getUserData(X("invokeid")); + if (invokeId != NULL) { + free(invokeId); + invoke->setUserData(X("invokeid"), NULL, NULL); + } + } + + if (_delayQueue) + _delayQueue.cancelAllDelayed(); + if (_document) + delete _document; + + { + std::lock_guard<std::recursive_mutex> lock(_instanceMutex); + _instances.erase(getSessionId()); + } // assert(_invokers.size() == 0); // ::xercesc_3_1::XMLPlatformUtils::Terminate(); @@ -377,7 +377,7 @@ void InterpreterImpl::uninvoke(const std::string& invokeId) { if (_invokers.find(invokeId) != _invokers.end()) { _invokers[invokeId].uninvoke(); _autoForwarders.erase(invokeId); - _invokers.erase(invokeId); + _invokers.erase(invokeId); } } diff --git a/src/uscxml/interpreter/InterpreterImpl.h b/src/uscxml/interpreter/InterpreterImpl.h index d6dbd1a..9b784d3 100644 --- a/src/uscxml/interpreter/InterpreterImpl.h +++ b/src/uscxml/interpreter/InterpreterImpl.h @@ -50,9 +50,8 @@ class USCXML_API InterpreterImpl : public MicroStepCallbacks, public DataModelCallbacks, public ContentExecutorCallbacks, - public DelayedEventQueueCallbacks, - public std::enable_shared_from_this<InterpreterImpl> -{ + public DelayedEventQueueCallbacks, + public std::enable_shared_from_this<InterpreterImpl> { public: enum Binding { EARLY = 0, @@ -77,13 +76,13 @@ public: virtual void reset() {///< Reset state machine if (_microStepper) - _microStepper.reset(); - + _microStepper.reset(); + _isInitialized = false; _state = USCXML_INSTANTIATED; // _dataModel.reset(); - if (_delayQueue) - _delayQueue.reset(); + if (_delayQueue) + _delayQueue.reset(); // _contentExecutor.reset(); } @@ -101,9 +100,9 @@ public: _monitors.insert(monitor); } - void removeMonitor(InterpreterMonitor* monitor) { - _monitors.erase(monitor); - } + void removeMonitor(InterpreterMonitor* monitor) { + _monitors.erase(monitor); + } /** MicrostepCallbacks @@ -136,13 +135,13 @@ public: _execContent.uninvoke(invoke); } - virtual std::set<InterpreterMonitor*> getMonitors() { + virtual std::set<InterpreterMonitor*> getMonitors() { return _monitors; } - virtual Interpreter getInterpreter() { - return Interpreter(shared_from_this()); - } + virtual Interpreter getInterpreter() { + return Interpreter(shared_from_this()); + } /** DataModelCallbacks @@ -230,14 +229,14 @@ public: _execContent = al.execContent; _microStepper = al.microStepper; _dataModel = al.dataModel; - _internalQueue = al.internalQueue; - _externalQueue = al.externalQueue; - _delayQueue = al.delayedQueue; + _internalQueue = al.internalQueue; + _externalQueue = al.externalQueue; + _delayQueue = al.delayedQueue; } - void setFactory(Factory* factory) { - _factory = factory; - } + void setFactory(Factory* factory) { + _factory = factory; + } static std::map<std::string, std::weak_ptr<InterpreterImpl> > getInstances(); @@ -270,9 +269,9 @@ protected: friend class InterpreterIssue; friend class TransformerImpl; friend class USCXMLInvoker; - friend class SCXMLIOProcessor; - friend class DebugSession; - friend class Debugger; + friend class SCXMLIOProcessor; + friend class DebugSession; + friend class Debugger; X _xmlPrefix; X _xmlNS; @@ -297,7 +296,7 @@ protected: std::map<std::string, IOProcessor> _ioProcs; std::map<std::string, Invoker> _invokers; std::set<std::string> _autoForwarders; - std::set<InterpreterMonitor*> _monitors; + std::set<InterpreterMonitor*> _monitors; private: void setupDOM(); diff --git a/src/uscxml/interpreter/InterpreterMonitor.h b/src/uscxml/interpreter/InterpreterMonitor.h index 10cc6ac..2519cfd 100644 --- a/src/uscxml/interpreter/InterpreterMonitor.h +++ b/src/uscxml/interpreter/InterpreterMonitor.h @@ -47,13 +47,13 @@ for (auto callback : callbacks) { callback->function(inptr, arg1, arg2); } } // forward declare namespace XERCESC_NS { - class DOMElement; +class DOMElement; } namespace uscxml { class Interpreter; - + class USCXML_API InterpreterMonitor { public: InterpreterMonitor() : _copyToInvokers(false) {} diff --git a/src/uscxml/interpreter/MicroStepImpl.h b/src/uscxml/interpreter/MicroStepImpl.h index 40f065c..7d7c9b0 100644 --- a/src/uscxml/interpreter/MicroStepImpl.h +++ b/src/uscxml/interpreter/MicroStepImpl.h @@ -35,7 +35,7 @@ namespace uscxml { class InterpreterMonitor; - + /** * @ingroup microstep * @ingroup callback @@ -61,7 +61,7 @@ public: /** Monitoring */ virtual std::set<InterpreterMonitor*> getMonitors() = 0; - virtual Interpreter getInterpreter() = 0; + virtual Interpreter getInterpreter() = 0; }; /** diff --git a/src/uscxml/plugins/DataModelImpl.h b/src/uscxml/plugins/DataModelImpl.h index a151141..e21be9a 100644 --- a/src/uscxml/plugins/DataModelImpl.h +++ b/src/uscxml/plugins/DataModelImpl.h @@ -43,7 +43,7 @@ class DataModelImpl; */ class USCXML_API DataModelCallbacks { public: - virtual ~DataModelCallbacks() {} ///< silence virtual destructor warning from swig + virtual ~DataModelCallbacks() {} ///< silence virtual destructor warning from swig virtual const std::string& getName() = 0; virtual const std::string& getSessionId() = 0; virtual const std::map<std::string, IOProcessor>& getIOProcessors() = 0; @@ -57,6 +57,7 @@ public: DataModelExtension() : dm(NULL) {} virtual ~DataModelExtension() {} virtual std::string provides() = 0; + virtual Data invoke(const std::string& member, const Data& params) = 0; virtual Data getValueOf(const std::string& member) = 0; virtual void setValueOf(const std::string& member, const Data& data) = 0; DataModelImpl* dm; @@ -117,7 +118,7 @@ public: * @param expr Anything that possibly evaluates to an enumerable object. * @return The number of items in the enumerable object. */ - virtual uint32_t getLength(const std::string& expr) = 0; + virtual uint32_t getLength(const std::string& expr) = 0; /** * Set a given item to the object at a given index for one iteration. diff --git a/src/uscxml/plugins/Factory.cpp b/src/uscxml/plugins/Factory.cpp index 4dabab6..a60fe4c 100644 --- a/src/uscxml/plugins/Factory.cpp +++ b/src/uscxml/plugins/Factory.cpp @@ -56,6 +56,10 @@ # include "uscxml/plugins/datamodel/c89/C89DataModel.h" #endif +#ifdef WITH_DM_PROMELA +# include "uscxml/plugins/datamodel/promela/PromelaDataModel.h" +#endif + #ifdef WITH_INV_SCXML # include "uscxml/plugins/invoker/scxml/USCXMLInvoker.h" @@ -89,66 +93,73 @@ std::string Factory::getDefaultPluginPath() { void Factory::registerPlugins() { #ifdef WITH_IOPROC_SCXML - { - SCXMLIOProcessor* ioProcessor = new SCXMLIOProcessor(); - registerIOProcessor(ioProcessor); - } + { + SCXMLIOProcessor* ioProcessor = new SCXMLIOProcessor(); + registerIOProcessor(ioProcessor); + } #endif #ifdef WITH_IOPROC_BASICHTTP - { - BasicHTTPIOProcessor* ioProcessor = new BasicHTTPIOProcessor(); - registerIOProcessor(ioProcessor); - } + { + BasicHTTPIOProcessor* ioProcessor = new BasicHTTPIOProcessor(); + registerIOProcessor(ioProcessor); + } #endif - + #ifdef WITH_DM_ECMA_V8 - { - V8DataModel* dataModel = new V8DataModel(); - registerDataModel(dataModel); - } + { + V8DataModel* dataModel = new V8DataModel(); + registerDataModel(dataModel); + } #endif #ifdef WITH_DM_ECMA_JSC - { - JSCDataModel* dataModel = new JSCDataModel(); - registerDataModel(dataModel); - } + { + JSCDataModel* dataModel = new JSCDataModel(); + registerDataModel(dataModel); + } #endif - + #ifdef WITH_DM_LUA - { - LuaDataModel* dataModel = new LuaDataModel(); - registerDataModel(dataModel); - } + { + LuaDataModel* dataModel = new LuaDataModel(); + registerDataModel(dataModel); + } #endif #ifdef WITH_DM_C89 - { - C89DataModel* dataModel = new C89DataModel(); - registerDataModel(dataModel); - } + { + C89DataModel* dataModel = new C89DataModel(); + registerDataModel(dataModel); + } #endif - { - NULLDataModel* dataModel = new NULLDataModel(); - registerDataModel(dataModel); - } +#ifdef WITH_DM_PROMELA + { + PromelaDataModel* dataModel = new PromelaDataModel(); + registerDataModel(dataModel); + } +#endif + + { + NULLDataModel* dataModel = new NULLDataModel(); + registerDataModel(dataModel); + } + - #ifdef WITH_INV_SCXML - { - USCXMLInvoker* invoker = new USCXMLInvoker(); - registerInvoker(invoker); - } + { + USCXMLInvoker* invoker = new USCXMLInvoker(); + registerInvoker(invoker); + } #endif - + #ifdef WITH_INV_DIRMON - { - DirMonInvoker* inv = new DirMonInvoker(); - registerInvoker(inv); - } + { + DirMonInvoker* inv = new DirMonInvoker(); + registerInvoker(inv); + } #endif } diff --git a/src/uscxml/plugins/datamodel/CMakeLists.txt b/src/uscxml/plugins/datamodel/CMakeLists.txt index fd08ee0..6409a7a 100644 --- a/src/uscxml/plugins/datamodel/CMakeLists.txt +++ b/src/uscxml/plugins/datamodel/CMakeLists.txt @@ -58,6 +58,17 @@ if (WITH_DM_C89) list (APPEND USCXML_FILES ${C89_DATAMODEL}) endif() +if (WITH_DM_PROMELA) + set(USCXML_DATAMODELS "promela ${USCXML_DATAMODELS}") + # Lua ecmascript datamodel + file(GLOB_RECURSE PROMELA_DATAMODEL + promela/*.cpp + promela/*.c + promela/*.h + ) + list (APPEND USCXML_FILES ${PROMELA_DATAMODEL}) +endif() + if (NOT SWIG_FOUND) message(STATUS "No swig binary found, not generating DOM classes") elseif(SWIG_VERSION VERSION_LESS 3.0.8) diff --git a/src/uscxml/plugins/datamodel/c89/C89DataModel.cpp b/src/uscxml/plugins/datamodel/c89/C89DataModel.cpp index 804b71a..24b9bb1 100644 --- a/src/uscxml/plugins/datamodel/c89/C89DataModel.cpp +++ b/src/uscxml/plugins/datamodel/c89/C89DataModel.cpp @@ -34,13 +34,13 @@ C89DataModel::C89DataModel() { std::shared_ptr<DataModelImpl> C89DataModel::create(DataModelCallbacks* callbacks) { std::shared_ptr<C89DataModel> dm(new C89DataModel()); - PicocInitialise(&dm->_pc, PICOC_STACK_SIZE); - PicocIncludeAllSystemHeaders(&dm->_pc); - return dm; + PicocInitialise(&dm->_pc, PICOC_STACK_SIZE); + PicocIncludeAllSystemHeaders(&dm->_pc); + return dm; } C89DataModel::~C89DataModel() { - PicocCleanup(&_pc); + PicocCleanup(&_pc); } void C89DataModel::addExtension(DataModelExtension* ext) { @@ -60,7 +60,7 @@ bool C89DataModel::isValidSyntax(const std::string& expr) { } uint32_t C89DataModel::getLength(const std::string& expr) { - return 0; + return 0; } void C89DataModel::setForeach(const std::string& item, diff --git a/src/uscxml/plugins/datamodel/c89/C89DataModel.h b/src/uscxml/plugins/datamodel/c89/C89DataModel.h index 30116e1..4e9eef0 100644 --- a/src/uscxml/plugins/datamodel/c89/C89DataModel.h +++ b/src/uscxml/plugins/datamodel/c89/C89DataModel.h @@ -59,7 +59,7 @@ public: virtual std::list<std::string> getNames() { std::list<std::string> names; names.push_back("c89"); - names.push_back("ansi-c"); + names.push_back("ansi-c"); return names; } @@ -86,7 +86,7 @@ public: virtual std::string andExpressions(std::list<std::string>); protected: - Picoc _pc; + Picoc _pc; }; #ifdef BUILD_AS_PLUGINS diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp index 05d37d4..bdb8939 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp @@ -401,23 +401,23 @@ Data JSCDataModel::evalAsData(const std::string& content) { Data JSCDataModel::getAsData(const std::string& content) { // parse as JSON test 578 - Data d = Data::fromJSON(content); - if (!d.empty()) - return d; - - std::string trimmed = boost::trim_copy(content); - if (trimmed.length() > 0) { - if (isNumeric(trimmed.c_str(), 10)) { - d = Data(trimmed, Data::INTERPRETED); - } else if (trimmed.length() >= 2 && - ((trimmed[0] == '"' && trimmed[trimmed.length() - 1] == '"') || - (trimmed[0] == '\'' && trimmed[trimmed.length() - 1] == '\''))) { - d = Data(trimmed.substr(1, trimmed.length() - 2), Data::VERBATIM); - } else { - d = Data(trimmed, Data::INTERPRETED); - } - } - return d; + Data d = Data::fromJSON(content); + if (!d.empty()) + return d; + + std::string trimmed = boost::trim_copy(content); + if (trimmed.length() > 0) { + if (isNumeric(trimmed.c_str(), 10)) { + d = Data(trimmed, Data::INTERPRETED); + } else if (trimmed.length() >= 2 && + ((trimmed[0] == '"' && trimmed[trimmed.length() - 1] == '"') || + (trimmed[0] == '\'' && trimmed[trimmed.length() - 1] == '\''))) { + d = Data(trimmed.substr(1, trimmed.length() - 2), Data::VERBATIM); + } else { + d = Data(trimmed, Data::INTERPRETED); + } + } + return d; } JSValueRef JSCDataModel::getDataAsValue(const Data& data) { diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp index db65ebf..0205674 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp @@ -423,23 +423,23 @@ void V8DataModel::setEvent(const Event& event) { } Data V8DataModel::getAsData(const std::string& content) { - Data d = Data::fromJSON(content); - if (!d.empty()) - return d; - - std::string trimmed = boost::trim_copy(content); - if (trimmed.length() > 0) { - if (isNumeric(trimmed.c_str(), 10)) { - d = Data(trimmed, Data::INTERPRETED); - } else if (trimmed.length() >= 2 && - ((trimmed[0] == '"' && trimmed[trimmed.length() - 1] == '"') || - (trimmed[0] == '\'' && trimmed[trimmed.length() - 1] == '\''))) { - d = Data(trimmed.substr(1, trimmed.length() - 2), Data::VERBATIM); - } else { - d = Data(trimmed, Data::INTERPRETED); - } - } - return d; + Data d = Data::fromJSON(content); + if (!d.empty()) + return d; + + std::string trimmed = boost::trim_copy(content); + if (trimmed.length() > 0) { + if (isNumeric(trimmed.c_str(), 10)) { + d = Data(trimmed, Data::INTERPRETED); + } else if (trimmed.length() >= 2 && + ((trimmed[0] == '"' && trimmed[trimmed.length() - 1] == '"') || + (trimmed[0] == '\'' && trimmed[trimmed.length() - 1] == '\''))) { + d = Data(trimmed.substr(1, trimmed.length() - 2), Data::VERBATIM); + } else { + d = Data(trimmed, Data::INTERPRETED); + } + } + return d; } Data V8DataModel::evalAsData(const std::string& content) { diff --git a/src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp b/src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp index ca8cc60..4b7ed67 100644 --- a/src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp +++ b/src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp @@ -79,12 +79,12 @@ static Data getLuaAsData(lua_State* _luaState, const luabridge::LuaRef& lua) { bool isArray = false; bool isMap = false; for (luabridge::Iterator iter (lua); !iter.isNil(); ++iter) { - luabridge::LuaRef luaKey = iter.key(); + luabridge::LuaRef luaKey = iter.key(); luabridge::LuaRef luaVal = *iter; if (luaKey.isString()) { - assert(!isArray); + assert(!isArray); isMap = true; - // luaKey.tostring() is not working?! see issue84 + // luaKey.tostring() is not working?! see issue84 data.compound[luaKey.cast<std::string>()] = getLuaAsData(_luaState, luaVal); } else { assert(!isMap); @@ -335,23 +335,23 @@ Data LuaDataModel::evalAsData(const std::string& content) { data = getLuaAsData(_luaState, luabridge::LuaRef::fromStack(_luaState, -1)); } lua_pop(_luaState, retVals); - return data; + return data; } catch (ErrorEvent e) { - } - - try { + } + + try { // evaluate again without the return() - int retVals = luaEval(_luaState, trimmedExpr); - + int retVals = luaEval(_luaState, trimmedExpr); + if (retVals == 1) { data = getLuaAsData(_luaState, luabridge::LuaRef::fromStack(_luaState, -1)); - } - lua_pop(_luaState, retVals); - return data; + } + lua_pop(_luaState, retVals); + return data; - } catch (ErrorEvent e) { - throw e; // we will assume syntax error and throw - } + } catch (ErrorEvent e) { + throw e; // we will assume syntax error and throw + } return data; } @@ -470,59 +470,59 @@ void LuaDataModel::assign(const std::string& location, const Data& data) { int retVals = luaEval(_luaState, location + " = " + location); lua_pop(_luaState, retVals); - std::list<std::pair<std::string, bool> > idPath; - size_t start = 0; - for (size_t i = 0; i < location.size(); i++) { - if (location[i] == '.' || location[i] == '[') { - idPath.push_back(std::make_pair(location.substr(start, i - start), false)); - start = i + 1; - } else if (location[i] == ']') { - idPath.push_back(std::make_pair(location.substr(start, i - start), true)); - start = i + 1; - } - } - if (start < location.size()) - idPath.push_back(std::make_pair(location.substr(start, location.size() - start), false)); - - if (idPath.size() == 0) - return; - - luabridge::LuaRef lua = getDataAsLua(_luaState, data); - - if (idPath.size() == 1) { - // trivial case where we reference a simple toplevel identifier - luabridge::setGlobal(_luaState, lua, location.c_str()); - - } else { - auto globalId = idPath.front(); - idPath.pop_front(); - - auto field = idPath.back(); - idPath.pop_back(); - - luabridge::LuaRef topValue = luabridge::getGlobal(_luaState, globalId.first.c_str()); - luabridge::LuaRef value = topValue; - - for (auto ident : idPath) { - if (!value.isTable()) - value = luabridge::newTable(_luaState); - - if (ident.second) { - luabridge::LuaRef tmp = value[strTo<long>(ident.first)]; - } else { - luabridge::LuaRef tmp = value[ident]; - value = tmp; - } - } - if (field.second) { - value[strTo<long>(field.first)] = lua; - } else { - value[field.first] = lua; - } - - } - - + std::list<std::pair<std::string, bool> > idPath; + size_t start = 0; + for (size_t i = 0; i < location.size(); i++) { + if (location[i] == '.' || location[i] == '[') { + idPath.push_back(std::make_pair(location.substr(start, i - start), false)); + start = i + 1; + } else if (location[i] == ']') { + idPath.push_back(std::make_pair(location.substr(start, i - start), true)); + start = i + 1; + } + } + if (start < location.size()) + idPath.push_back(std::make_pair(location.substr(start, location.size() - start), false)); + + if (idPath.size() == 0) + return; + + luabridge::LuaRef lua = getDataAsLua(_luaState, data); + + if (idPath.size() == 1) { + // trivial case where we reference a simple toplevel identifier + luabridge::setGlobal(_luaState, lua, location.c_str()); + + } else { + auto globalId = idPath.front(); + idPath.pop_front(); + + auto field = idPath.back(); + idPath.pop_back(); + + luabridge::LuaRef topValue = luabridge::getGlobal(_luaState, globalId.first.c_str()); + luabridge::LuaRef value = topValue; + + for (auto ident : idPath) { + if (!value.isTable()) + value = luabridge::newTable(_luaState); + + if (ident.second) { + luabridge::LuaRef tmp = value[strTo<long>(ident.first)]; + } else { + luabridge::LuaRef tmp = value[ident]; + value = tmp; + } + } + if (field.second) { + value[strTo<long>(field.first)] = lua; + } else { + value[field.first] = lua; + } + + } + + // std::cout << Data::toJSON(evalAsData(location)) << std::endl; } } diff --git a/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp new file mode 100644 index 0000000..458e372 --- /dev/null +++ b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp @@ -0,0 +1,728 @@ +/** + * @file + * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see <http://www.opensource.org/licenses/bsd-license>. + * @endcond + */ + +#include <boost/algorithm/string.hpp> + +#include "uscxml/Common.h" +#include "uscxml/config.h" +#include "uscxml/util/String.h" +#include "PromelaDataModel.h" +#include "uscxml/util/DOM.h" + +#include <cctype> + +#include "PromelaParser.h" +#include "parser/promela.tab.hpp" +#include <easylogging++.h> + +#ifdef BUILD_AS_PLUGINS +#include <Pluma/Connector.hpp> +#endif + +#define INVALID_ASSIGNMENT(name) \ +name.compare("_sessionid") == 0 || \ +name.compare("_name") == 0 || \ +name.compare("_ioprocessors") == 0 || \ +name.compare("_event") == 0 + +namespace uscxml { + +#ifdef BUILD_AS_PLUGINS +PLUMA_CONNECTOR +bool pluginConnect(pluma::Host& host) { + host.add( new PromelaDataModelProvider() ); + return true; +} +#endif + +PromelaDataModel::PromelaDataModel() { +} + +PromelaDataModel::~PromelaDataModel() { +} + +std::shared_ptr<DataModelImpl> PromelaDataModel::create(DataModelCallbacks* callbacks) { + std::shared_ptr<PromelaDataModel> dm(new PromelaDataModel()); + + dm->_callbacks = callbacks; + + // session id + Data sessionId; + sessionId.compound["type"] = Data("string", Data::VERBATIM); + sessionId.compound["value"] = Data(callbacks->getSessionId(), Data::VERBATIM); + dm->_variables["_sessionid"] = sessionId; + + // name + Data name; + name.compound["type"] = Data("string", Data::VERBATIM); + name.compound["value"] = Data(callbacks->getName(), Data::VERBATIM); + dm->_variables["_name"] = name; + + // ioprocessors + Data ioProcs; + ioProcs.compound["type"] = Data("compound", Data::VERBATIM); + + std::map<std::string, IOProcessor> ioProcessors = callbacks->getIOProcessors(); + for (std::map<std::string, IOProcessor>::iterator iter = ioProcessors.begin(); iter != ioProcessors.end(); iter++) { + ioProcs.compound["value"].compound[iter->first] = iter->second.getDataModelVariables(); + } + dm->_variables["_ioprocessors"] = ioProcs; + + dm->_lastMType = 0; + return dm; +} + + +void PromelaDataModel::setEvent(const Event& event) { + Data variable; + variable.compound["type"] = Data("compound", Data::VERBATIM); + variable.compound["value"].compound["name"] = Data(event.name, Data::VERBATIM); + variable.compound["value"].compound["origin"] = Data(event.origin, Data::VERBATIM); + variable.compound["value"].compound["origintype"] = Data(event.origintype, Data::VERBATIM); + variable.compound["value"].compound["invokeid"] = Data(event.invokeid, Data::VERBATIM); + if (event.hideSendId) { + variable.compound["value"].compound["sendid"] = Data("", Data::VERBATIM); + } else { + variable.compound["value"].compound["sendid"] = Data(event.sendid, Data::VERBATIM); + } + switch (event.eventType) { + case Event::PLATFORM: + variable.compound["value"].compound["type"] = Data("platform", Data::VERBATIM); + break; + case Event::INTERNAL: + variable.compound["value"].compound["type"] = Data("internal", Data::VERBATIM); + break; + case Event::EXTERNAL: + variable.compound["value"].compound["type"] = Data("external", Data::VERBATIM); + break; + default: + variable.compound["value"].compound["type"] = Data("invalid", Data::VERBATIM); + break; + } + + if (false) { +#if 0 + else if (event.dom) { + // no support + } else if (event.content.length() > 0) { + // _event.data is a string or JSON + Data json = Data::fromJSON(event.content); + if (!json.empty()) { + variable.compound["value"].compound["data"] = json; + } else { + if (isNumeric(event.content.c_str(), 10)) { + variable.compound["value"].compound["data"] = Data(event.content, Data::INTERPRETED); + } else { + variable.compound["value"].compound["data"] = Data(spaceNormalize(event.content), Data::VERBATIM); + } + } +#endif + } else { + // _event.data is KVP + if (!event.data.empty()) { + variable.compound["value"].compound["data"] = event.data; + } else { + // test 343 / test 488 + variable.compound["value"].compound["data"]; + } + + for (Event::params_t::const_iterator start = event.params.begin(), end = event.params.end(); + start != end; start = event.params.upper_bound(start->first)) { + // only set first param key + if (isNumeric(start->second.atom.c_str(), 10)) { + variable.compound["value"].compound["data"].compound[start->first] = strTo<int>(start->second.atom); + } else { + variable.compound["value"].compound["data"].compound[start->first] = start->second; + } + } + + for (Event::namelist_t::const_iterator iter = event.namelist.begin(); iter != event.namelist.end(); iter++) { + if (isNumeric(iter->second.atom.c_str(), 10)) { + variable.compound["value"].compound["data"].compound[iter->first] = strTo<int>(iter->second.atom); + } else { + variable.compound["value"].compound["data"].compound[iter->first] = iter->second; + } + } + } + + // iterate all data elements and adapt type for int if atom is integer + adaptType(variable.compound["value"].compound["data"]); + + _variables["_event"] = variable; + } + + void PromelaDataModel::adaptType(Data& data) { + if (data.atom.length() > 0 && isInteger(data.atom.c_str(), 10)) { + data.type = Data::INTERPRETED; + return; + } + + if (data.array.size() > 0) { + for (std::list<Data>::iterator iter = data.array.begin(); iter != data.array.end(); iter++) { + adaptType(*iter); + } + return; + } + + if (data.compound.size() > 0) { + for (std::map<std::string, Data>::iterator iter = data.compound.begin(); iter != data.compound.end(); iter++) { + adaptType(iter->second); + } + return; + } + + } + + bool PromelaDataModel::isValidSyntax(const std::string& expr) { + try { + PromelaParser parser(expr); + } catch (Event e) { + LOG(ERROR) << e << std::endl; + return false; + } + return true; + } + + uint32_t PromelaDataModel::getLength(const std::string& expr) { + if (!isDeclared(expr)) { + ERROR_EXECUTION_THROW("Variable '" + expr + "' was not declared"); + } + + if (!_variables[expr].hasKey("size")) { + ERROR_EXECUTION_THROW("Variable '" + expr + "' is no array"); + } + + return strTo<int>(_variables[expr]["size"].atom); + } + + void PromelaDataModel::setForeach(const std::string& item, + const std::string& array, + const std::string& index, + uint32_t iteration) { + // assign array element to item + std::stringstream ss; + ss << array << "[" << iteration << "]"; + + PromelaParser itemParser(item, 1, PromelaParser::PROMELA_EXPR); + if (itemParser.ast->type != PML_NAME) + ERROR_EXECUTION_THROW("Expression '" + item + "' is no valid item"); + + PromelaParser arrayParser(ss.str(), 1, PromelaParser::PROMELA_EXPR); + + setVariable(itemParser.ast, getVariable(arrayParser.ast)); + + if (index.length() > 0) { + PromelaParser indexParser(index, 1, PromelaParser::PROMELA_EXPR); + setVariable(indexParser.ast, iteration); + } + + } + + bool PromelaDataModel::evalAsBool(const std::string& expr) { + PromelaParser parser(expr, 1, PromelaParser::PROMELA_EXPR); +// parser.dump(); + Data tmp = evaluateExpr(parser.ast); + + if (tmp.atom.compare("false") == 0) + return false; + if (tmp.atom.compare("0") == 0) + return false; + return true; + } + + Data PromelaDataModel::evalAsData(const std::string& expr) { + PromelaParser parser(expr); + return evaluateExpr(parser.ast); + } + + Data PromelaDataModel::getAsData(const std::string& content) { + return evalAsData(content); + } + + void PromelaDataModel::evaluateDecl(const std::string& expr) { + PromelaParser parser(expr, 1, PromelaParser::PROMELA_DECL); + evaluateDecl(parser.ast); + } + + Data PromelaDataModel::evaluateExpr(const std::string& expr) { + PromelaParser parser(expr, 1, PromelaParser::PROMELA_EXPR); + return evaluateExpr(parser.ast); + } + + void PromelaDataModel::evaluateStmnt(const std::string& expr) { + PromelaParser parser(expr, 1, PromelaParser::PROMELA_STMNT); + evaluateStmnt(parser.ast); + } + + void PromelaDataModel::evaluateDecl(void* ast) { + PromelaParserNode* node = (PromelaParserNode*)ast; +// node->dump(); + if (false) { + } else if (node->type == PML_DECL) { + std::list<PromelaParserNode*>::iterator opIter = node->operands.begin(); + PromelaParserNode* vis = *opIter++; + PromelaParserNode* type = *opIter++; + PromelaParserNode* varlist = *opIter++; + + for (std::list<PromelaParserNode*>::iterator nameIter = varlist->operands.begin(); + nameIter != varlist->operands.end(); + nameIter++) { + Data variable; + variable.compound["vis"] = Data(vis->value, Data::VERBATIM); + variable.compound["type"] = Data(type->value, Data::VERBATIM); + + if (false) { + } else if ((*nameIter)->type == PML_NAME) { + // plain variables without initial assignment + + if (type->value == "mtype") { + variable.compound["value"] = Data(_lastMType++, Data::INTERPRETED); + } else { + variable.compound["value"] = Data(0, Data::INTERPRETED); + } + _variables.compound[(*nameIter)->value] = variable; + + } else if ((*nameIter)->type == PML_ASGN) { + // initially assigned variables + + std::list<PromelaParserNode*>::iterator opIterAsgn = (*nameIter)->operands.begin(); + PromelaParserNode* name = *opIterAsgn++; + PromelaParserNode* expr = *opIterAsgn++; + + try { + variable.compound["value"] = evaluateExpr(expr); + } catch(uscxml::Event e) { + // test277, declare and throw + _variables.compound[name->value] = variable; + throw e; + } + + assert(opIterAsgn == (*nameIter)->operands.end()); + _variables.compound[name->value] = variable; + } else if ((*nameIter)->type == PML_VAR_ARRAY) { + // variable arrays + + std::list<PromelaParserNode*>::iterator opIterAsgn = (*nameIter)->operands.begin(); + PromelaParserNode* name = *opIterAsgn++; + int size = dataToInt(evaluateExpr(*opIterAsgn++)); + + variable.compound["size"] = size; + for (size_t i = 0; i < size; i++) { + variable.compound["value"].array.push_back(Data(0, Data::INTERPRETED)); + } + + assert(opIterAsgn == (*nameIter)->operands.end()); + _variables.compound[name->value] = variable; + + } else { + ERROR_EXECUTION_THROW("Declaring variables via " + PromelaParserNode::typeToDesc((*nameIter)->type) + " not implemented"); + } + } + assert(opIter == node->operands.end()); + } else if (node->type == PML_DECLLIST) { + for (std::list<PromelaParserNode*>::iterator declIter = node->operands.begin(); + declIter != node->operands.end(); + declIter++) { + evaluateDecl(*declIter); + } + } else { + node->dump(); + ERROR_EXECUTION_THROW("Declaring variables via " + PromelaParserNode::typeToDesc(node->type) + " not implemented"); + } + } + + int PromelaDataModel::dataToInt(const Data& data) { + if (data.type != Data::INTERPRETED) + ERROR_EXECUTION_THROW("Operand is not integer"); + int value = strTo<int>(data.atom); + if (data.atom.compare(toStr(value)) != 0) + ERROR_EXECUTION_THROW("Operand is not integer"); + return value; + } + + bool PromelaDataModel::dataToBool(const Data& data) { + if (data.atom.size() == 0) // empty string or undefined + return false; + + if (data.type == Data::VERBATIM) { + // non-empty string is true + return true; + } else { + if (data.atom.compare("true") == 0) { + // boolean true is true + return true; + } else if (data.atom.compare("false") == 0) { + return false; + } else if (dataToInt(data) != 0) { + return true; // non zero values are true + } + } + return false; + } + + Data PromelaDataModel::evaluateExpr(void* ast) { + PromelaParserNode* node = (PromelaParserNode*)ast; + std::list<PromelaParserNode*>::iterator opIter = node->operands.begin(); + switch (node->type) { + case PML_CONST: + if (iequals(node->value, "false")) + return Data(false); + if (iequals(node->value, "true")) + return Data(true); + return strTo<int>(node->value); + case PML_NAME: + case PML_VAR_ARRAY: + case PML_CMPND: + return getVariable(node); + case PML_STRING: { + std::string stripped = node->value.substr(1, node->value.size() - 2); + return Data(stripped, Data::VERBATIM); +// return Data(node->value, Data::INTERPRETED); + } + case PML_PLUS: + return dataToInt(evaluateExpr(*opIter++)) + dataToInt(evaluateExpr(*opIter++)); + case PML_MINUS: + return dataToInt(evaluateExpr(*opIter++)) - dataToInt(evaluateExpr(*opIter++)); + case PML_DIVIDE: + return dataToInt(evaluateExpr(*opIter++)) / dataToInt(evaluateExpr(*opIter++)); + case PML_MODULO: + return dataToInt(evaluateExpr(*opIter++)) % dataToInt(evaluateExpr(*opIter++)); + case PML_EQ: { + PromelaParserNode* lhs = *opIter++; + PromelaParserNode* rhs = *opIter++; + + Data left = evaluateExpr(lhs); + Data right = evaluateExpr(rhs); + + if (left == right) // overloaded operator== + return Data(true); + + // literal strings or strings in variables + if ((lhs->type == PML_STRING || rhs->type == PML_STRING) + || (left.type == Data::VERBATIM && right.type == Data::VERBATIM)) { + return (left.atom.compare(right.atom) == 0 ? Data(true) : Data(false)); + } + return dataToInt(left) == dataToInt(right); + } + case PML_NEG: + return !dataToBool(evaluateExpr(*opIter++)); + case PML_LT: + return dataToInt(evaluateExpr(*opIter++)) < dataToInt(evaluateExpr(*opIter++)); + case PML_LE: + return dataToInt(evaluateExpr(*opIter++)) <= dataToInt(evaluateExpr(*opIter++)); + case PML_GT: + return dataToInt(evaluateExpr(*opIter++)) > dataToInt(evaluateExpr(*opIter++)); + case PML_GE: + return dataToInt(evaluateExpr(*opIter++)) >= dataToInt(evaluateExpr(*opIter++)); + case PML_TIMES: + return dataToInt(evaluateExpr(*opIter++)) * dataToInt(evaluateExpr(*opIter++)); + case PML_LSHIFT: + return dataToInt(evaluateExpr(*opIter++)) << dataToInt(evaluateExpr(*opIter++)); + case PML_RSHIFT: + return dataToInt(evaluateExpr(*opIter++)) >> dataToInt(evaluateExpr(*opIter++)); + case PML_AND: + case PML_OR: { + PromelaParserNode* lhs = *opIter++; + PromelaParserNode* rhs = *opIter++; + +// std::cout << "-----" << std::endl; +// lhs->dump(); +// rhs->dump(); + + Data left = evaluateExpr(lhs); + Data right = evaluateExpr(rhs); + + bool truthLeft = dataToBool(left); + bool truthRight = dataToBool(right); + + if (node->type == PML_AND) { + return truthLeft && truthRight; + } else { + return truthLeft || truthRight; + } + } + default: + ERROR_EXECUTION_THROW("Support for " + PromelaParserNode::typeToDesc(node->type) + " expressions not implemented"); + } + return 0; + } + + void PromelaDataModel::evaluateStmnt(void* ast) { + PromelaParserNode* node = (PromelaParserNode*)ast; + std::list<PromelaParserNode*>::iterator opIter = node->operands.begin(); + switch (node->type) { + case PML_ASGN: { + PromelaParserNode* name = *opIter++; + PromelaParserNode* expr = *opIter++; + setVariable(name, evaluateExpr(expr)); + break; + } + case PML_STMNT: { + while(opIter != node->operands.end()) { + evaluateStmnt(*opIter++); + } + break; + } + case PML_INCR: { + PromelaParserNode* name = *opIter++; + setVariable(name, strTo<long>(getVariable(name)) + 1); + break; + } + case PML_DECR: { + PromelaParserNode* name = *opIter++; + setVariable(name, strTo<long>(getVariable(name)) - 1); + break; + } + default: + node->dump(); + ERROR_EXECUTION_THROW("No support for " + PromelaParserNode::typeToDesc(node->type) + " statement implemented"); + } + } + + + void PromelaDataModel::setVariable(void* ast, const Data& value) { + PromelaParserNode* node = (PromelaParserNode*)ast; + + if (INVALID_ASSIGNMENT(node->value)) { + ERROR_EXECUTION_THROW("Cannot assign to " + node->value); + } + +// if (_variables.compound.find(name->value) == _variables.compound.end()) { +// // declare implicitly / convenience +// evaluateDecl(ast); +// } + + switch (node->type) { + case PML_VAR_ARRAY: { + std::list<PromelaParserNode*>::iterator opIter = node->operands.begin(); + + PromelaParserNode* name = *opIter++; + PromelaParserNode* expr = *opIter++; + + // is the location an array? + if (!_variables[name->value].hasKey("size")) { + ERROR_EXECUTION_THROW("Variable " + name->value + " is no array"); + } + + // is the array large enough? + int index = dataToInt(evaluateExpr(expr)); + if (strTo<int>(_variables[name->value]["size"].atom) <= index) { + ERROR_EXECUTION_THROW("Index " + toStr(index) + " in array " + name->value + "[" + _variables[name->value]["size"].atom + "] is out of bounds"); + } + + _variables.compound[name->value].compound["value"][index] = value; + + break; + } + case PML_NAME: { + // location is an array, but no array was passed + if (_variables[node->value].hasKey("size")) { + if (value.compound.size() > 0 || value.atom.size() > 0) + ERROR_EXECUTION_THROW("Variable " + node->value + " is an array"); + + if (strTo<size_t>(_variables[node->value].compound["size"].atom) < value.array.size()) + ERROR_EXECUTION_THROW("Array assigned to " + node->value + " is too large"); + } + + _variables.compound[node->value].compound["value"] = value; + break; + } + case PML_CMPND: { + std::list<PromelaParserNode*>::iterator opIter = node->operands.begin(); + PromelaParserNode* name = *opIter++; + + // location is no array + if (_variables[name->value].hasKey("size")) { + ERROR_EXECUTION_THROW("Variable " + name->value + " is an array"); + } + +// std::cout << Data::toJSON(_variables) << std::endl;; + + Data* var = &_variables[name->value].compound["value"]; + var->compound["type"] = Data("compound", Data::VERBATIM); + var->compound["vis"] = Data("", Data::VERBATIM); + + while(opIter != node->operands.end()) { + name = *opIter; + opIter++; + var = &(var->compound[name->value]); + } + *var = value; + + break; + } + default: + node->dump(); + ERROR_EXECUTION_THROW("No support for " + PromelaParserNode::typeToDesc(node->type) + " variables implemented"); + break; + } + +// std::cout << Data::toJSON(_variables) << std::endl; + } + + Data PromelaDataModel::getVariable(void* ast) { + PromelaParserNode* node = (PromelaParserNode*)ast; +// node->dump(); + + std::list<PromelaParserNode*>::iterator opIter = node->operands.begin(); + switch(node->type) { + case PML_NAME: + if (_variables.compound.find(node->value) == _variables.compound.end()) { + ERROR_EXECUTION_THROW("No variable " + node->value + " was declared"); + } +// if (_variables[node->value].compound.find("size") != _variables[node->value].compound.end()) { +// ERROR_EXECUTION_THROW("Type error: Variable " + node->value + " is an array"); +// } + return _variables[node->value]["value"]; + case PML_VAR_ARRAY: { + PromelaParserNode* name = *opIter++; + PromelaParserNode* expr = *opIter++; + int index = dataToInt(evaluateExpr(expr)); + + if (_variables.compound.find(name->value) == _variables.compound.end()) { + ERROR_EXECUTION_THROW("No variable " + name->value + " was declared"); + } + + if (!_variables[name->value].hasKey("size")) { + ERROR_EXECUTION_THROW("Variable " + name->value + " is no array"); + } + + if (strTo<int>(_variables[name->value]["size"].atom) <= index) { + ERROR_EXECUTION_THROW("Index " + toStr(index) + " in array " + name->value + "[" + _variables[name->value]["size"].atom + "] is out of bounds"); + } + return _variables.compound[name->value].compound["value"][index]; + } + case PML_CMPND: { +// node->dump(); +// std::cout << Data::toJSON(_variables["_event"]); + std::stringstream idPath; + PromelaParserNode* name = *opIter++; + + // special case for _x variables + if (name->value.compare("_x") == 0) { + PromelaParserNode* what = *opIter++; + + if (what->type == PML_VAR_ARRAY) { + if (what->operands.size() == 2) { + std::string arrName = what->operands.front()->value; + std::string index = what->operands.back()->value; + + if (what->operands.back()->type == PML_STRING) { + index = index.substr(1, index.size() - 2); // remove quotes + } + + if (arrName.compare("states") == 0) { + return Data(_callbacks->isInState(index)); + } + } + } + ERROR_EXECUTION_THROW("No variable " + name->value + " was declared"); + } + + if (_variables.compound.find(name->value) == _variables.compound.end()) { + ERROR_EXECUTION_THROW("No variable " + name->value + " was declared"); + } + + Data currData = _variables.compound[name->value]["value"]; + idPath << name->value; + while(opIter != node->operands.end()) { + std::string key = (*opIter)->value; + idPath << "." << key; + if (currData.compound.find(key) == currData.compound.end()) { + ERROR_EXECUTION_THROW("No variable " + idPath.str() + " was declared"); + } + Data tmp = currData.compound[key]; + currData = tmp; + + opIter++; + } + return currData; + } + default: + ERROR_EXECUTION_THROW("Retrieving value of " + PromelaParserNode::typeToDesc(node->type) + " variable not implemented"); + } + return 0; + } + + std::string PromelaDataModel::andExpressions(std::list<std::string> expressions) { + + if (expressions.size() == 0) + return ""; + + if (expressions.size() == 1) + return *(expressions.begin()); + + std::ostringstream exprSS; + exprSS << "("; + std::string conjunction = ""; + for (std::list<std::string>::const_iterator exprIter = expressions.begin(); + exprIter != expressions.end(); + exprIter++) { + exprSS << conjunction << "(" << *exprIter << ")"; + conjunction = " && "; + } + exprSS << ")"; + return exprSS.str(); + } + + void PromelaDataModel::assign(const std::string& location, const Data& data) { + // used for e.g. to assign command line parameters and idlocation + PromelaParser parser(location); + setVariable(parser.ast, data); + } + + void PromelaDataModel::init(const std::string& location, const Data& data) { + assign(location, data); + } + + bool PromelaDataModel::isDeclared(const std::string& expr) { + PromelaParser parser(expr); +// parser.dump(); + if (parser.ast->type == PML_VAR_ARRAY) + return _variables.compound.find(parser.ast->operands.front()->value) != _variables.compound.end(); + + if (parser.ast->type == PML_CMPND) { + // JSON declaration + std::list<PromelaParserNode*>::iterator opIter = parser.ast->operands.begin(); + Data* var = &_variables; + + while(opIter != parser.ast->operands.end()) { + std::string name = (*opIter)->value; + opIter++; + if (var->compound.find(name) != var->compound.end()) { + var = &(var->compound.at(name)); + } else if (var->compound.find("value") != var->compound.end() && var->compound.at("value").compound.find(name) != var->compound.at("value").compound.end()) { + var = &(var->compound.at("value").compound.at(name)); + } else { + return false; + } + } + return true; + + } + + return _variables.compound.find(expr) != _variables.compound.end(); + } + + void PromelaDataModel::addExtension(DataModelExtension* ext) { + ERROR_EXECUTION_THROW("Extensions unimplemented in promela datamodel"); + } + + +} diff --git a/src/uscxml/plugins/datamodel/promela/PromelaDataModel.h b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.h new file mode 100644 index 0000000..2c1f58d --- /dev/null +++ b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.h @@ -0,0 +1,102 @@ +/** + * @file + * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see <http://www.opensource.org/licenses/bsd-license>. + * @endcond + */ + +#ifndef PROMELADATAMODEL_H_4VG0TDMU +#define PROMELADATAMODEL_H_4VG0TDMU + +#include "uscxml/plugins/DataModelImpl.h" +#include <list> + +#ifdef BUILD_AS_PLUGINS +#include "uscxml/plugins/Plugins.h" +#endif + +namespace uscxml { + +class PromelaDataModel : public DataModelImpl { +public: + PromelaDataModel(); + virtual ~PromelaDataModel(); + virtual std::shared_ptr<DataModelImpl> create(DataModelCallbacks* callbacks); + + virtual std::list<std::string> getNames() { + std::list<std::string> names; + names.push_back("promela"); + return names; + } + + virtual void addExtension(DataModelExtension* ext); + + virtual bool isValidSyntax(const std::string& expr); + + virtual void setEvent(const Event& event); + + // foreach + virtual uint32_t getLength(const std::string& expr); + virtual void setForeach(const std::string& item, + const std::string& array, + const std::string& index, + uint32_t iteration); + + virtual bool evalAsBool(const std::string& expr); + virtual Data evalAsData(const std::string& expr); + virtual Data getAsData(const std::string& content); + + virtual bool isDeclared(const std::string& expr); + + virtual void assign(const std::string& location, const Data& data); + virtual void init(const std::string& location, const Data& data); + + virtual std::string andExpressions(std::list<std::string>); + +protected: + + int dataToInt(const Data& data); + bool dataToBool(const Data& data); + + void evaluateDecl(void* ast); + Data evaluateExpr(void* ast); + void evaluateStmnt(void* ast); + + void evaluateDecl(const std::string& expr); + Data evaluateExpr(const std::string& expr); + void evaluateStmnt(const std::string& expr); + + void setVariable(void* ast, const Data& value); + Data getVariable(void* ast); + + void adaptType(Data& data); + + int _lastMType; + + Event _event; + std::string _name; + std::string _sessionId; + + Data _variables; + +}; + +#ifdef BUILD_AS_PLUGINS +PLUMA_INHERIT_PROVIDER(PromelaDataModel, DataModelImpl); +#endif + +} + +#endif /* end of include guard: PROMELADATAMODEL_H_4VG0TDMU */ diff --git a/src/uscxml/plugins/datamodel/promela/PromelaParser.cpp b/src/uscxml/plugins/datamodel/promela/PromelaParser.cpp new file mode 100644 index 0000000..32fbc13 --- /dev/null +++ b/src/uscxml/plugins/datamodel/promela/PromelaParser.cpp @@ -0,0 +1,299 @@ +/** + * @file + * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see <http://www.opensource.org/licenses/bsd-license>. + * @endcond + */ + +#include "PromelaParser.h" +#include "parser/promela.tab.hpp" +#include "uscxml/messages/Event.h" + +#include <iostream> +#include <string.h> // memcpy + +struct yy_buffer_state; +typedef yy_buffer_state *YY_BUFFER_STATE; +extern YY_BUFFER_STATE promela__scan_buffer(char *, size_t, void*); +void promela__delete_buffer(YY_BUFFER_STATE, void*); +YY_BUFFER_STATE promela__scan_string (const char * yystr , void*); + + +extern int promela_lex (PROMELA_STYPE* yylval_param, PROMELA_LTYPE* yylloc_param, void* yyscanner); +int promela_lex_init (void**); +int promela_lex_destroy (void*); + +void promela_error (void* yylloc_param, uscxml::PromelaParser* ctx, void* yyscanner, const char* err) { + PROMELA_LTYPE* yylloc = (PROMELA_LTYPE*)yylloc_param; + // mark as pending exception as we cannot throw from constructor and have the destructor called + ERROR_EXECUTION(excEvent, err); + excEvent.data.compound["line"] = uscxml::Data(yylloc->first_line, uscxml::Data::VERBATIM); + excEvent.data.compound["col"] = uscxml::Data(yylloc->first_column, uscxml::Data::VERBATIM); + + std::stringstream ssUnderline; + for (size_t i = 0; i < yylloc->first_column; i++) + ssUnderline << " "; + ssUnderline << "^"; + excEvent.data.compound["sourcemark"] = uscxml::Data(ssUnderline.str(), uscxml::Data::VERBATIM); + + ctx->pendingException = excEvent; +} + +namespace uscxml { + +PromelaParser::PromelaParser(const std::string& expr) { + init(expr); +} + +PromelaParser::PromelaParser(const std::string& expr, int nrArgs, ...) { + init(expr); + + if (nrArgs == 0) + return; + + std::stringstream errSS; + std::string seperator; + errSS << "Promela syntax type mismatch: Expected {"; + + va_list ap; + va_start(ap, nrArgs); + for(int i = 1; i <= nrArgs; i++) { + int expectedType = va_arg(ap, int); + if (type == expectedType) + return; + errSS << seperator << typeToDesc(expectedType); + seperator = ", "; + } + errSS << "} but got " << typeToDesc(type); + ERROR_EXECUTION_THROW(errSS.str()); +} + +void PromelaParser::init(const std::string& expr) { + ast = NULL; + parseInCompound = 0; + input_length = expr.length() + 2; // plus some zero terminators + input = (char*) calloc(1, input_length); + memcpy(input, expr.c_str(), expr.length()); + + promela_lex_init(&scanner); + // promela_assign_set_extra(ast, &scanner); + buffer = promela__scan_string(input, scanner); + // buffer = promela__scan_buffer(input, input_length, scanner); + promela_parse(this, scanner); + if (pendingException.name.size() > 0) { + // parsing failed in promela_error + destroy(); + pendingException.data.compound["sourceline"] = Data(expr, Data::VERBATIM); + throw pendingException; + } +} + +void PromelaParser::destroy() { + if (ast) + delete(ast); + free(input); + promela__delete_buffer((YY_BUFFER_STATE)buffer, scanner); + promela_lex_destroy(scanner); +} + +PromelaParser::~PromelaParser() { + destroy(); +} + +std::string PromelaParser::typeToDesc(int type) { + switch (type) { + case PROMELA_EXPR: + return "expression"; + case PROMELA_DECL: + return "declarations"; + case PROMELA_STMNT: + return "statements"; + default: + break; + } + return ""; +} + +PromelaParserNode::~PromelaParserNode() { + while(operands.size() > 0) { + delete operands.front(); + operands.pop_front(); + } + if (loc) + free(loc); +} + +PromelaParserNode* PromelaParser::node(int type, int nrArgs, ...) { + PromelaParserNode* newNode = new PromelaParserNode(); + + newNode->type = type; + va_list ap; + va_start(ap, nrArgs); + for(int i = 1; i <= nrArgs; i++) { + newNode->operands.push_back(va_arg(ap, PromelaParserNode*)); + newNode->operands.back()->parent = newNode; + } + return newNode; +} + +PromelaParserNode* PromelaParser::value(int type, void* location, const char* value) { + PromelaParserNode* newNode = new PromelaParserNode(); + + if (location) { + PROMELA_LTYPE* location_param = (PROMELA_LTYPE*)location; + newNode->loc = (PromelaParserNode::Location*)malloc(sizeof(PromelaParserNode::Location)); + newNode->loc->firstCol = location_param->first_column; + newNode->loc->firstLine = location_param->first_line; + newNode->loc->lastCol = location_param->last_column; + newNode->loc->lastLine = location_param->last_line; + } + + newNode->value = value; + newNode->type = type; + return newNode; +} + + +void PromelaParser::dump() { + switch (type) { + case PROMELA_EXPR: + std::cout << "Promela Expression" << std::endl; + break; + case PROMELA_DECL: + std::cout << "Promela Declarations" << std::endl; + break; + case PROMELA_STMNT: + std::cout << "Promela Statement" << std::endl; + break; + } + ast->dump(); +} + + +void PromelaParserNode::merge(PromelaParserNode* node) { + for (std::list<PromelaParserNode*>::iterator iter = node->operands.begin(); + iter != node->operands.end(); iter++) { + operands.push_back(*iter); + (*iter)->parent = this; + } + node->operands.clear(); +} + +void PromelaParserNode::push(PromelaParserNode* node) { + node->parent = this; + operands.push_back(node); +} + +void PromelaParserNode::dump(int indent) { + std::string padding; + for (size_t i = 0; i < indent; i++) { + padding += " "; + } + std::cout << padding << typeToDesc(type) << ": " << value; + if (loc != NULL) { + std::cout << " (" << loc->firstLine << ":" << loc->firstCol << ")-(" << loc->lastLine << ":" << loc->lastCol << ")"; + } + std::cout << std::endl; + for (std::list<PromelaParserNode*>::iterator iter = operands.begin(); + iter != operands.end(); iter++) { + (*iter)->dump(indent + 1); + } +} + +std::string PromelaParserNode::typeToDesc(int type) { + switch(type) { + case PML_PLUS: + return "PLUS"; + case PML_MINUS: + return "MINUS"; + case PML_TIMES: + return "TIMES"; + case PML_DIVIDE: + return "DIVIDE"; + case PML_MODULO: + return "MODULO"; + case PML_BITAND: + return "BITAND"; + case PML_BITXOR: + return "BITXOR"; + case PML_BITOR: + return "BITOR"; + case PML_GT: + return "GT"; + case PML_LT: + return "LT"; + case PML_GE: + return "GE"; + case PML_LE: + return "LE"; + case PML_EQ: + return "EQ"; + case PML_NE: + return "NE"; + case PML_AND: + return "AND"; + case PML_OR: + return "OR"; + case PML_LSHIFT: + return "LSHIFT"; + case PML_RSHIFT: + return "RSHIFT"; + case PML_NEG: + return "NEG"; + case PML_ASGN: + return "ASGN"; + case PML_INCR: + return "INCR"; + case PML_DECR: + return "DECR"; + case PML_VAR_ARRAY: + return "VAR_ARRAY"; + case PML_DECL: + return "DECL"; + case PML_STMNT: + return "STMNT"; + case PML_TYPE: + return "TYPE"; + case PML_NAME: + return "NAME"; + case PML_CONST: + return "CONST"; + case PML_PRINT: + return "PRINT"; + case PML_SHOW: + return "SHOW"; + case PML_EXPR: + return "EXPR"; + case PML_VARLIST: + return "VARLIST"; + case PML_DECLLIST: + return "DECLLIST"; + case PML_NAMELIST: + return "NAMELIST"; + case PML_STRING: + return "STRING"; + case PML_TYPEDEF: + return "TYPEDEF"; + case PML_CMPND: + return "CMPND"; + case PML_ASSERT: + return "ASSERT"; + + default: + return std::string("UNK(") + toStr(type) + ")"; + } +} + +} diff --git a/src/uscxml/plugins/datamodel/promela/PromelaParser.h b/src/uscxml/plugins/datamodel/promela/PromelaParser.h new file mode 100644 index 0000000..51a2111 --- /dev/null +++ b/src/uscxml/plugins/datamodel/promela/PromelaParser.h @@ -0,0 +1,106 @@ +/** + * @file + * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see <http://www.opensource.org/licenses/bsd-license>. + * @endcond + */ + +// bison -v promela.ypp && flex promela.l + +#ifndef PROMELA_H_9AB78YB1 +#define PROMELA_H_9AB78YB1 + +#include <stdlib.h> +//#include <stdarg.h> +#include <cstdarg> +#include <string> +#include <list> + +#include "uscxml/messages/Event.h" + +namespace uscxml { + +class PromelaParser; + +class PromelaParserNode { +public: + struct Location { + int firstLine; + int firstCol; + int lastLine; + int lastCol; + }; + + PromelaParserNode() : type(0), parent(NULL), loc(NULL) {} + virtual ~PromelaParserNode(); + + void merge(PromelaParserNode* node); + void push(PromelaParserNode* node); + void dump(int indent = 0); + + static std::string typeToDesc(int type); + + int type; + std::string value; + std::list<PromelaParserNode*> operands; + PromelaParserNode* parent; + Location* loc; +}; + +class PromelaParser { +public: + enum Type { + PROMELA_EXPR, + PROMELA_DECL, + PROMELA_STMNT + }; + + static std::string typeToDesc(int type); + + PromelaParser() : ast(NULL) {} + PromelaParser(const std::string& expr); + PromelaParser(const std::string& expr, int nrArgs, ...); + virtual ~PromelaParser(); + + virtual PromelaParserNode* node(int type, int nrArgs, ...); + virtual PromelaParserNode* value(int type, void* location, const char* value); + void dump(); + + int parseInCompound; + + PromelaParserNode* ast; + Type type; + + Event pendingException; + operator bool() const { + return ast != NULL; + } + +protected: + + void init(const std::string& expr); + void destroy(); + + void* buffer; + void* scanner; + char* input; + size_t input_length; +}; + +} + +void promela_error (void* yylloc_param, uscxml::PromelaParser* ctx, void* yyscanner, const char* err); + +#endif /* end of include guard: PROMELA_H_9AB78YB1 */ diff --git a/src/uscxml/plugins/datamodel/promela/parser/promela.l b/src/uscxml/plugins/datamodel/promela/parser/promela.l new file mode 100644 index 0000000..1edc625 --- /dev/null +++ b/src/uscxml/plugins/datamodel/promela/parser/promela.l @@ -0,0 +1,117 @@ +/* see: http://www.phpcompiler.org/articles/reentrantparser.html */ +/* see: http://spinroot.com/spin/Man/operators.html */ + + +%option yylineno +%option reentrant +%option bison-bridge +%option prefix="promela_" +%option outfile="promela.lex.yy.cpp" +%option noyywrap +%option debug +%option never-interactive nounistd +%option bison-locations + +%{ + +#include "../PromelaParser.h" +#include "promela.tab.hpp" +#define YYSTYPE PROMELA_STYPE +#define YYLTYPE PROMELA_LTYPE +#define YY_USER_INIT \ + yycolumn = yylloc->first_line = yylloc->first_column = 0; \ + yylineno = yylloc->last_line = yylloc->last_column = 0; \ + +//int yycolumn = 1; + +#define YY_USER_ACTION \ +{ \ + yylloc->first_line = yylineno; \ + yylloc->first_column = yycolumn; \ + yylloc->last_column = yycolumn + yyleng; \ + yylloc->last_line = yylineno; \ + yycolumn = yycolumn + yyleng; \ +} + +%} + +DIGIT [0-9] +ID [_a-zA-Z][_a-zA-Z0-9]* +L [a-zA-Z_] + +%% + +\/\*([^*]|\*[^/])*\*+\/ /* multiline comments */ + +bit|bool|byte|int|mtype|short|unsigned|string|auto { + yylval->value = strdup(yytext); + return PML_TYPE; +} + +len { return PML_LEN; } +false|skip|true { yylval->value = strdup(yytext); return PML_CONST; } +printf { return PML_PRINT; } +typedef { return PML_TYPEDEF; } +assert { return PML_ASSERT; } + +"!" { return PML_NEG; } +"~" { return PML_COMPL; } +"++" { return PML_INCR; } +"--" { return PML_DECR; } + +"*" { return PML_TIMES; } +"/" { return PML_DIVIDE; } +"%" { return PML_MODULO; } + +"+" { return PML_PLUS; } +"-" { return PML_MINUS; } + +"<<" { return PML_LSHIFT; } +">>" { return PML_RSHIFT; } + +"<=" { return PML_LE; } +">=" { return PML_GE; } +"<" { return PML_LT; } +">" { return PML_GT; } + +"!=" { return PML_NE; } +"==" { return PML_EQ; } + +"&" { return PML_BITAND; } +"^" { return PML_BITXOR; } +"|" { return PML_BITOR; } + + +"&&" { return PML_AND; } +"||" { return PML_OR; } + +"." { return PML_DOT; } +"," { return PML_COMMA; } +";" { return PML_SEMI; } + +"(" { return '('; } +")" { return ')'; } + +"[" { return '['; } +"]" { return ']'; } + +"{" { return '{'; } +"}" { return '}'; } + +"=" { return PML_ASGN; } + +L?\"(\\.|[^\\"])*\" { yylval->value = strdup(yytext); return(PML_STRING); } + + +L?'(\\.|[^\'])*\' { + /* Non PROMELA extension for single quoted string literals */ + yylval->value = strdup(yytext); return(PML_STRING); +} + +{DIGIT}+ { yylval->value = strdup(yytext); return PML_CONST; } +{ID} { yylval->value = strdup(yytext); return PML_NAME; } + +[ \t\n]+ /* eat up whitespace */ + + +. { /*printf( "Unrecognized character: %s\n", yytext ); */ } diff --git a/src/uscxml/plugins/datamodel/promela/parser/promela.lex.yy.cpp b/src/uscxml/plugins/datamodel/promela/parser/promela.lex.yy.cpp new file mode 100644 index 0000000..3a99921 --- /dev/null +++ b/src/uscxml/plugins/datamodel/promela/parser/promela.lex.yy.cpp @@ -0,0 +1,2598 @@ +#line 2 "promela.lex.yy.cpp" + +#line 4 "promela.lex.yy.cpp" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +/* %not-for-header */ + +/* %if-c-only */ +/* %if-not-reentrant */ +/* %endif */ +/* %endif */ +/* %ok-for-header */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* %if-c++-only */ +/* %endif */ + +/* %if-c-only */ + +/* %endif */ + +/* %if-c-only */ + +/* %endif */ + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +/* %if-c-only */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> +/* %endif */ + +/* %if-tables-serialization */ +/* %endif */ +/* end standard C headers. */ + +/* %if-c-or-c++ */ +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +typedef uint64_t flex_uint64_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +/* %endif */ + +/* %if-c++-only */ +/* %endif */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* %not-for-header */ + +/* Returned upon end-of-file. */ +#define YY_NULL 0 +/* %ok-for-header */ + +/* %not-for-header */ + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) +/* %ok-for-header */ + +/* %if-reentrant */ + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +/* %endif */ + +/* %if-not-reentrant */ +/* %endif */ + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yyg->yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yyg->yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE promela_restart(yyin ,yyscanner ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +/* %if-not-reentrant */ +/* %endif */ + +/* %if-c-only */ +/* %if-not-reentrant */ +/* %endif */ +/* %endif */ + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* Note: We specifically omit the test for yy_rule_can_match_eol because it requires + * access to the local variable yy_act. Since yyless() is a macro, it would break + * existing scanners that call yyless() from OUTSIDE promela_lex. + * One obvious solution it to make yy_act a global. I tried that, and saw + * a 5% performance hit in a non-yylineno scanner, because yy_act is + * normally declared as a register variable-- so it is not worth it. + */ +#define YY_LESS_LINENO(n) \ + do { \ + yy_size_t yyl;\ + for ( yyl = n; yyl < yyleng; ++yyl )\ + if ( yytext[yyl] == '\n' )\ + --yylineno;\ + }while(0) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = yyg->yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state { + /* %if-c-only */ + FILE *yy_input_file; + /* %endif */ + + /* %if-c++-only */ + /* %endif */ + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + yy_size_t yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via promela_restart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + +}; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* %if-c-only Standard (non-C++) definition */ +/* %not-for-header */ + +/* %if-not-reentrant */ +/* %endif */ +/* %ok-for-header */ + +/* %endif */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ + ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] + +/* %if-c-only Standard (non-C++) definition */ + +/* %if-not-reentrant */ +/* %not-for-header */ + +/* %ok-for-header */ + +/* %endif */ + +void promela_restart (FILE *input_file ,yyscan_t yyscanner ); +void promela__switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +YY_BUFFER_STATE promela__create_buffer (FILE *file,int size ,yyscan_t yyscanner ); +void promela__delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void promela__flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void promela_push_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +void promela_pop_buffer_state (yyscan_t yyscanner ); + +static void promela_ensure_buffer_stack (yyscan_t yyscanner ); +static void promela__load_buffer_state (yyscan_t yyscanner ); +static void promela__init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); + +#define YY_FLUSH_BUFFER promela__flush_buffer(YY_CURRENT_BUFFER ,yyscanner) + +YY_BUFFER_STATE promela__scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); +YY_BUFFER_STATE promela__scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); +YY_BUFFER_STATE promela__scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner ); + +/* %endif */ + +void *promela_alloc (yy_size_t ,yyscan_t yyscanner ); +void *promela_realloc (void *,yy_size_t ,yyscan_t yyscanner ); +void promela_free (void * ,yyscan_t yyscanner ); + +#define yy_new_buffer promela__create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + promela_ensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + promela__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + promela_ensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + promela__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* %% [1.0] yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here */ + +#define promela_wrap(n) 1 +#define YY_SKIP_YYWRAP + +#define FLEX_DEBUG + +typedef unsigned char YY_CHAR; + +typedef int yy_state_type; + +#define yytext_ptr yytext_r + +/* %if-c-only Standard (non-C++) definition */ + +static yy_state_type yy_get_previous_state (yyscan_t yyscanner ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner); +static int yy_get_next_buffer (yyscan_t yyscanner ); +static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); + +/* %endif */ + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yyg->yytext_ptr = yy_bp; \ +/* %% [2.0] code to fiddle yytext and yyleng for yymore() goes here \ */\ + yyleng = (yy_size_t) (yy_cp - yy_bp); \ + yyg->yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ +/* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */\ + yyg->yy_c_buf_p = yy_cp; + +/* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */ +#define YY_NUM_RULES 46 +#define YY_END_OF_BUFFER 47 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; +}; +static yyconst flex_int16_t yy_accept[126] = { + 0, + 0, 0, 47, 45, 44, 44, 8, 45, 14, 25, + 45, 33, 34, 12, 15, 31, 16, 30, 13, 42, + 32, 21, 39, 22, 43, 43, 35, 36, 26, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 37, + 27, 38, 9, 44, 23, 0, 40, 0, 28, 0, + 41, 0, 10, 11, 0, 42, 17, 19, 24, 20, + 18, 43, 0, 0, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 29, 0, 41, 0, 0, 0, 43, 43, 2, 43, + 43, 43, 3, 43, 43, 43, 43, 43, 43, 43, + + 43, 0, 1, 43, 43, 43, 43, 43, 4, 43, + 43, 43, 1, 43, 43, 43, 43, 43, 7, 5, + 43, 43, 6, 43, 0 +} ; + +static yyconst flex_int32_t yy_ec[256] = { + 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 5, 1, 1, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 1, 18, 19, + 20, 21, 1, 1, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 23, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 24, 25, 26, 27, 22, 1, 28, 29, 22, 30, + + 31, 32, 33, 34, 35, 22, 36, 37, 38, 39, + 40, 41, 22, 42, 43, 44, 45, 22, 22, 22, + 46, 22, 47, 48, 49, 50, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 +} ; + +static yyconst flex_int32_t yy_meta[51] = { + 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, + 1, 2, 2, 1, 1, 1, 1, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 1, 1, 1 +} ; + +static yyconst flex_int16_t yy_base[131] = { + 0, + 0, 0, 172, 173, 49, 51, 151, 50, 173, 163, + 48, 173, 173, 173, 157, 173, 154, 173, 156, 149, + 173, 38, 145, 39, 0, 56, 173, 173, 173, 20, + 31, 136, 124, 131, 117, 118, 34, 30, 120, 173, + 110, 173, 173, 77, 173, 57, 173, 154, 173, 59, + 173, 66, 173, 173, 145, 138, 173, 173, 173, 173, + 173, 0, 76, 75, 111, 109, 108, 111, 106, 112, + 104, 108, 100, 110, 104, 108, 100, 96, 99, 96, + 173, 77, 78, 84, 127, 77, 106, 96, 0, 98, + 103, 90, 0, 91, 92, 88, 88, 93, 96, 95, + + 90, 78, 173, 82, 92, 91, 77, 76, 0, 80, + 88, 75, 96, 62, 73, 71, 68, 59, 0, 0, + 65, 65, 0, 65, 173, 109, 111, 88, 113, 115 +} ; + +static yyconst flex_int16_t yy_def[131] = { + 0, + 125, 1, 125, 125, 125, 125, 125, 126, 125, 125, + 127, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 128, 128, 125, 125, 125, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 125, + 125, 125, 125, 125, 125, 126, 125, 126, 125, 127, + 125, 129, 125, 125, 130, 125, 125, 125, 125, 125, + 125, 128, 126, 127, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 125, 127, 127, 129, 130, 130, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + + 128, 130, 125, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 130, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 0, 125, 125, 125, 125, 125 +} ; + +static yyconst flex_int16_t yy_nxt[224] = { + 0, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 4, 28, 29, 30, 31, 25, + 25, 32, 25, 25, 33, 25, 34, 35, 25, 25, + 36, 25, 37, 38, 39, 25, 40, 41, 42, 43, + 44, 44, 44, 44, 47, 51, 57, 58, 60, 61, + 63, 47, 65, 64, 66, 67, 51, 75, 50, 76, + 68, 78, 52, 83, 48, 79, 69, 77, 44, 44, + 47, 48, 51, 52, 51, 51, 50, 102, 86, 62, + 84, 83, 103, 113, 89, 124, 123, 122, 121, 52, + + 48, 52, 52, 89, 120, 119, 86, 118, 84, 46, + 46, 50, 50, 82, 82, 85, 85, 117, 116, 89, + 115, 89, 109, 114, 112, 111, 109, 110, 109, 108, + 107, 106, 105, 89, 89, 89, 104, 86, 101, 100, + 99, 98, 97, 96, 95, 94, 93, 89, 92, 91, + 90, 89, 88, 87, 56, 86, 125, 81, 80, 74, + 73, 72, 71, 70, 59, 56, 55, 54, 53, 49, + 45, 125, 3, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125 +} ; + +static yyconst flex_int16_t yy_chk[224] = { + 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 5, 5, 6, 6, 8, 11, 22, 22, 24, 24, + 26, 46, 30, 26, 30, 31, 50, 37, 52, 37, + 31, 38, 11, 52, 8, 38, 31, 37, 44, 44, + 63, 46, 64, 50, 82, 83, 84, 86, 102, 128, + 52, 84, 86, 102, 124, 122, 121, 118, 117, 64, + + 63, 82, 83, 116, 115, 114, 113, 112, 84, 126, + 126, 127, 127, 129, 129, 130, 130, 111, 110, 108, + 107, 106, 105, 104, 101, 100, 99, 98, 97, 96, + 95, 94, 92, 91, 90, 88, 87, 85, 80, 79, + 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, + 68, 67, 66, 65, 56, 55, 48, 41, 39, 36, + 35, 34, 33, 32, 23, 20, 19, 17, 15, 10, + 7, 3, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125 +} ; + +/* Table of booleans, true if rule could match eol. */ +static yyconst flex_int32_t yy_rule_can_match_eol[47] = { + 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 0, 0, +}; + +static yyconst flex_int16_t yy_rule_linenum[46] = { + 0, + 44, 46, 51, 52, 53, 54, 55, 57, 58, 59, + 60, 62, 63, 64, 66, 67, 69, 70, 72, 73, + 74, 75, 77, 78, 80, 81, 82, 85, 86, 88, + 89, 90, 92, 93, 95, 96, 98, 99, 101, 103, + 106, 111, 112, 114, 117 +} ; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +#line 1 "promela.l" +/* see: http://www.phpcompiler.org/articles/reentrantparser.html */ +/* see: http://spinroot.com/spin/Man/operators.html */ +#define YY_NO_UNISTD_H 1 +#line 16 "promela.l" + +#include "../PromelaParser.h" +#include "promela.tab.hpp" +#define YYSTYPE PROMELA_STYPE +#define YYLTYPE PROMELA_LTYPE +#define YY_USER_INIT \ + yycolumn = yylloc->first_line = yylloc->first_column = 0; \ + yylineno = yylloc->last_line = yylloc->last_column = 0; \ + +//int yycolumn = 1; + +#define YY_USER_ACTION \ +{ \ + yylloc->first_line = yylineno; \ + yylloc->first_column = yycolumn; \ + yylloc->last_column = yycolumn + yyleng; \ + yylloc->last_line = yylineno; \ + yycolumn = yycolumn + yyleng; \ +} + +#line 661 "promela.lex.yy.cpp" + +#define INITIAL 0 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +/* %if-c-only */ +#include <unistd.h> +/* %endif */ +/* %if-c++-only */ +/* %endif */ +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* %if-c-only Reentrant structure and macros (non-C++). */ +/* %if-reentrant */ + +/* Holds the entire state of the reentrant scanner. */ +struct yyguts_t { + + /* User-defined. Not touched by flex. */ + YY_EXTRA_TYPE yyextra_r; + + /* The rest are the same as the globals declared in the non-reentrant scanner. */ + FILE *yyin_r, *yyout_r; + size_t yy_buffer_stack_top; /**< index of top of stack. */ + size_t yy_buffer_stack_max; /**< capacity of stack. */ + YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ + char yy_hold_char; + yy_size_t yy_n_chars; + yy_size_t yyleng_r; + char *yy_c_buf_p; + int yy_init; + int yy_start; + int yy_did_buffer_switch_on_eof; + int yy_start_stack_ptr; + int yy_start_stack_depth; + int *yy_start_stack; + yy_state_type yy_last_accepting_state; + char* yy_last_accepting_cpos; + + int yylineno_r; + int yy_flex_debug_r; + + char *yytext_r; + int yy_more_flag; + int yy_more_len; + + YYSTYPE * yylval_r; + + YYLTYPE * yylloc_r; + +}; /* end struct yyguts_t */ + +/* %if-c-only */ + +static int yy_init_globals (yyscan_t yyscanner ); + +/* %endif */ + +/* %if-reentrant */ + +/* This must go here because YYSTYPE and YYLTYPE are included + * from bison output in section 1.*/ +# define yylval yyg->yylval_r + +# define yylloc yyg->yylloc_r + +int promela_lex_init (yyscan_t* scanner); + +int promela_lex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); + +/* %endif */ + +/* %endif End reentrant structures and macros. */ + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int promela_lex_destroy (yyscan_t yyscanner ); + +int promela_get_debug (yyscan_t yyscanner ); + +void promela_set_debug (int debug_flag ,yyscan_t yyscanner ); + +YY_EXTRA_TYPE promela_get_extra (yyscan_t yyscanner ); + +void promela_set_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); + +FILE *promela_get_in (yyscan_t yyscanner ); + +void promela_set_in (FILE * in_str ,yyscan_t yyscanner ); + +FILE *promela_get_out (yyscan_t yyscanner ); + +void promela_set_out (FILE * out_str ,yyscan_t yyscanner ); + +yy_size_t promela_get_leng (yyscan_t yyscanner ); + +char *promela_get_text (yyscan_t yyscanner ); + +int promela_get_lineno (yyscan_t yyscanner ); + +void promela_set_lineno (int line_number ,yyscan_t yyscanner ); + +/* %if-bison-bridge */ + +YYSTYPE * promela_get_lval (yyscan_t yyscanner ); + +void promela_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); + +YYLTYPE *promela_get_lloc (yyscan_t yyscanner ); + +void promela_set_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner ); + +/* %endif */ + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int promela_wrap (yyscan_t yyscanner ); +#else +extern int promela_wrap (yyscan_t yyscanner ); +#endif +#endif + +/* %not-for-header */ + +static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner); + +/* %ok-for-header */ + +/* %endif */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT +/* %if-c-only Standard (non-C++) definition */ +/* %not-for-header */ + +#ifdef __cplusplus +static int yyinput (yyscan_t yyscanner ); +#else +static int input (yyscan_t yyscanner ); +#endif +/* %ok-for-header */ + +/* %endif */ +#endif + +/* %if-c-only */ + +/* %endif */ + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* %if-c-only Standard (non-C++) definition */ +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO fwrite( yytext, yyleng, 1, yyout ) +/* %endif */ +/* %if-c++-only C++ definition */ +/* %endif */ +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ +/* %% [5.0] fread()/read() definition of YY_INPUT goes here unless we're doing C++ \ */\ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + yy_size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ +/* %if-c++-only C++ definition \ */\ +/* %endif */ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +/* %if-c-only */ +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +#endif + +/* %if-tables-serialization structures and prototypes */ +/* %not-for-header */ + +/* %ok-for-header */ + +/* %not-for-header */ + +/* %tables-yydmap generated elements */ +/* %endif */ +/* end tables serialization structures and prototypes */ + +/* %ok-for-header */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 +/* %if-c-only Standard (non-C++) definition */ + +extern int promela_lex \ +(YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner); + +#define YY_DECL int promela_lex \ + (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only C++ definition */ +/* %endif */ +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +/* %% [6.0] YY_RULE_SETUP definition goes here */ +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/* %not-for-header */ + +/** The main scanner function which does all the work. + */ +YY_DECL { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* %% [7.0] user's declarations go here */ +#line 42 "promela.l" + + +#line 970 "promela.lex.yy.cpp" + + yylval = yylval_param; + + yylloc = yylloc_param; + + if ( !yyg->yy_init ) { + yyg->yy_init = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yyg->yy_start ) + yyg->yy_start = 1; /* first start state */ + + if ( ! yyin ) + /* %if-c-only */ + yyin = stdin; + /* %endif */ + /* %if-c++-only */ + /* %endif */ + + if ( ! yyout ) + /* %if-c-only */ + yyout = stdout; + /* %endif */ + /* %if-c++-only */ + /* %endif */ + + if ( ! YY_CURRENT_BUFFER ) { + promela_ensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + promela__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + } + + promela__load_buffer_state(yyscanner ); + } + + while ( 1 ) { /* loops until end-of-file is reached */ + /* %% [8.0] yymore()-related code goes here */ + yy_cp = yyg->yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yyg->yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + /* %% [9.0] code to set up and find next match goes here */ + yy_current_state = yyg->yy_start; +yy_match: + do { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 126 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } while ( yy_current_state != 125 ); + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + +yy_find_action: + /* %% [10.0] code to find the action number goes here */ + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + + /* %% [11.0] code for yylineno update goes here */ + + if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) { + yy_size_t yyl; + for ( yyl = 0; yyl < yyleng; ++yyl ) + if ( yytext[yyl] == '\n' ) + + do { + yylineno++; + yycolumn=0; + } while(0) + ; + } + +do_action: /* This label is used only to access EOF actions. */ + + /* %% [12.0] debug code goes here */ + if ( yy_flex_debug ) { + if ( yy_act == 0 ) + fprintf( stderr, "--scanner backing up\n" ); + else if ( yy_act < 46 ) + fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n", + (long)yy_rule_linenum[yy_act], yytext ); + else if ( yy_act == 46 ) + fprintf( stderr, "--accepting default rule (\"%s\")\n", + yytext ); + else if ( yy_act == 47 ) + fprintf( stderr, "--(end of buffer or a NUL)\n" ); + else + fprintf( stderr, "--EOF (start condition %d)\n", YY_START ); + } + + switch ( yy_act ) { + /* beginning of action switch */ + /* %% [13.0] actions go here */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yyg->yy_hold_char; + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + + case 1: + /* rule 1 can match eol */ + YY_RULE_SETUP +#line 44 "promela.l" + /* multiline comments */ + YY_BREAK + case 2: + YY_RULE_SETUP +#line 46 "promela.l" + { + yylval->value = strdup(yytext); + return PML_TYPE; + } + YY_BREAK + case 3: + YY_RULE_SETUP +#line 51 "promela.l" + { return PML_LEN; } + YY_BREAK + case 4: + YY_RULE_SETUP +#line 52 "promela.l" + { yylval->value = strdup(yytext); return PML_CONST; } + YY_BREAK + case 5: + YY_RULE_SETUP +#line 53 "promela.l" + { return PML_PRINT; } + YY_BREAK + case 6: + YY_RULE_SETUP +#line 54 "promela.l" + { return PML_TYPEDEF; } + YY_BREAK + case 7: + YY_RULE_SETUP +#line 55 "promela.l" + { return PML_ASSERT; } + YY_BREAK + case 8: + YY_RULE_SETUP +#line 57 "promela.l" + { return PML_NEG; } + YY_BREAK + case 9: + YY_RULE_SETUP +#line 58 "promela.l" + { return PML_COMPL; } + YY_BREAK + case 10: + YY_RULE_SETUP +#line 59 "promela.l" + { return PML_INCR; } + YY_BREAK + case 11: + YY_RULE_SETUP +#line 60 "promela.l" + { return PML_DECR; } + YY_BREAK + case 12: + YY_RULE_SETUP +#line 62 "promela.l" + { return PML_TIMES; } + YY_BREAK + case 13: + YY_RULE_SETUP +#line 63 "promela.l" + { return PML_DIVIDE; } + YY_BREAK + case 14: + YY_RULE_SETUP +#line 64 "promela.l" + { return PML_MODULO; } + YY_BREAK + case 15: + YY_RULE_SETUP +#line 66 "promela.l" + { return PML_PLUS; } + YY_BREAK + case 16: + YY_RULE_SETUP +#line 67 "promela.l" + { return PML_MINUS; } + YY_BREAK + case 17: + YY_RULE_SETUP +#line 69 "promela.l" + { return PML_LSHIFT; } + YY_BREAK + case 18: + YY_RULE_SETUP +#line 70 "promela.l" + { return PML_RSHIFT; } + YY_BREAK + case 19: + YY_RULE_SETUP +#line 72 "promela.l" + { return PML_LE; } + YY_BREAK + case 20: + YY_RULE_SETUP +#line 73 "promela.l" + { return PML_GE; } + YY_BREAK + case 21: + YY_RULE_SETUP +#line 74 "promela.l" + { return PML_LT; } + YY_BREAK + case 22: + YY_RULE_SETUP +#line 75 "promela.l" + { return PML_GT; } + YY_BREAK + case 23: + YY_RULE_SETUP +#line 77 "promela.l" + { return PML_NE; } + YY_BREAK + case 24: + YY_RULE_SETUP +#line 78 "promela.l" + { return PML_EQ; } + YY_BREAK + case 25: + YY_RULE_SETUP +#line 80 "promela.l" + { return PML_BITAND; } + YY_BREAK + case 26: + YY_RULE_SETUP +#line 81 "promela.l" + { return PML_BITXOR; } + YY_BREAK + case 27: + YY_RULE_SETUP +#line 82 "promela.l" + { return PML_BITOR; } + YY_BREAK + case 28: + YY_RULE_SETUP +#line 85 "promela.l" + { return PML_AND; } + YY_BREAK + case 29: + YY_RULE_SETUP +#line 86 "promela.l" + { return PML_OR; } + YY_BREAK + case 30: + YY_RULE_SETUP +#line 88 "promela.l" + { return PML_DOT; } + YY_BREAK + case 31: + YY_RULE_SETUP +#line 89 "promela.l" + { return PML_COMMA; } + YY_BREAK + case 32: + YY_RULE_SETUP +#line 90 "promela.l" + { return PML_SEMI; } + YY_BREAK + case 33: + YY_RULE_SETUP +#line 92 "promela.l" + { return '('; } + YY_BREAK + case 34: + YY_RULE_SETUP +#line 93 "promela.l" + { return ')'; } + YY_BREAK + case 35: + YY_RULE_SETUP +#line 95 "promela.l" + { return '['; } + YY_BREAK + case 36: + YY_RULE_SETUP +#line 96 "promela.l" + { return ']'; } + YY_BREAK + case 37: + YY_RULE_SETUP +#line 98 "promela.l" + { return '{'; } + YY_BREAK + case 38: + YY_RULE_SETUP +#line 99 "promela.l" + { return '}'; } + YY_BREAK + case 39: + YY_RULE_SETUP +#line 101 "promela.l" + { return PML_ASGN; } + YY_BREAK + case 40: + /* rule 40 can match eol */ + YY_RULE_SETUP +#line 103 "promela.l" + { yylval->value = strdup(yytext); return(PML_STRING); } + YY_BREAK + case 41: + /* rule 41 can match eol */ + YY_RULE_SETUP +#line 106 "promela.l" + { + /* Non PROMELA extension for single quoted string literals */ + yylval->value = strdup(yytext); + return(PML_STRING); + } + YY_BREAK + case 42: + YY_RULE_SETUP +#line 111 "promela.l" + { yylval->value = strdup(yytext); return PML_CONST; } + YY_BREAK + case 43: + YY_RULE_SETUP +#line 112 "promela.l" + { yylval->value = strdup(yytext); return PML_NAME; } + YY_BREAK + case 44: + /* rule 44 can match eol */ + YY_RULE_SETUP +#line 114 "promela.l" + /* eat up whitespace */ + YY_BREAK + case 45: + YY_RULE_SETUP +#line 117 "promela.l" + { /*printf( "Unrecognized character: %s\n", yytext ); */ } + YY_BREAK + case 46: + YY_RULE_SETUP +#line 118 "promela.l" + ECHO; + YY_BREAK +#line 1336 "promela.lex.yy.cpp" + case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yyg->yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * promela_lex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) { + /* This was really a NUL. */ + yy_state_type yy_next_state; + + yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); + + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) { + /* Consume the NUL. */ + yy_cp = ++yyg->yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else { + /* %% [14.0] code to do back-up for compressed tables and set up yy_cp goes here */ + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( yyscanner ) ) { + case EOB_ACT_END_OF_FILE: { + yyg->yy_did_buffer_switch_on_eof = 0; + + if ( promela_wrap(yyscanner ) ) { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else { + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = + yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yyg->yy_c_buf_p = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of promela_lex */ +/* %ok-for-header */ + +/* %if-c++-only */ +/* %not-for-header */ + +/* %ok-for-header */ + +/* %endif */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +/* %if-c-only */ +static int yy_get_next_buffer (yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = yyg->yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { + /* Don't try to fill the buffer, so this is an EOF. */ + if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; + + else { + yy_size_t num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) { + /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) (yyg->yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) { + yy_size_t new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + promela_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); + } else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + yyg->yy_n_chars, num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + if ( yyg->yy_n_chars == 0 ) { + if ( number_to_move == YY_MORE_ADJ ) { + ret_val = EOB_ACT_END_OF_FILE; + promela_restart(yyin ,yyscanner); + } + + else { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) promela_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + yyg->yy_n_chars += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +/* %if-c-only */ +/* %not-for-header */ + +static yy_state_type yy_get_previous_state (yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + register yy_state_type yy_current_state; + register char *yy_cp; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* %% [15.0] code to get the start state into yy_current_state goes here */ + yy_current_state = yyg->yy_start; + + for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) { + /* %% [16.0] code to find the next state goes here */ + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 126 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ +/* %if-c-only */ +static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + register int yy_is_jam; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ + /* %% [17.0] code to find the next state, and perhaps do backing up, goes here */ + register char *yy_cp = yyg->yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 126 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 125); + + return yy_is_jam ? 0 : yy_current_state; +} + +/* %if-c-only */ + +static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + register char *yy_cp; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_cp = yyg->yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yyg->yy_hold_char; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { + /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register yy_size_t number_to_move = yyg->yy_n_chars + 2; + register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + register char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + /* %% [18.0] update yylineno here */ + + if ( c == '\n' ) { + --yylineno; + } + + yyg->yytext_ptr = yy_bp; + yyg->yy_hold_char = *yy_cp; + yyg->yy_c_buf_p = yy_cp; +} +/* %if-c-only */ + +/* %endif */ + +/* %if-c-only */ +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput (yyscan_t yyscanner) +#else +static int input (yyscan_t yyscanner) +#endif + +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + int c; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + *yyg->yy_c_buf_p = yyg->yy_hold_char; + + if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + /* This was really a NUL. */ + *yyg->yy_c_buf_p = '\0'; + + else { + /* need more input */ + yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr; + ++yyg->yy_c_buf_p; + + switch ( yy_get_next_buffer( yyscanner ) ) { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + promela_restart(yyin ,yyscanner); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: { + if ( promela_wrap(yyscanner ) ) + return 0; + + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(yyscanner); +#else + return input(yyscanner); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = yyg->yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ + *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ + yyg->yy_hold_char = *++yyg->yy_c_buf_p; + + /* %% [19.0] update BOL and yylineno */ + if ( c == '\n' ) + + do { + yylineno++; + yycolumn=0; + } while(0) + ; + + return c; +} +/* %if-c-only */ +#endif /* ifndef YY_NO_INPUT */ +/* %endif */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * @param yyscanner The scanner object. + * @note This function does not reset the start condition to @c INITIAL . + */ +/* %if-c-only */ +void promela_restart (FILE * input_file , yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! YY_CURRENT_BUFFER ) { + promela_ensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + promela__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + } + + promela__init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner); + promela__load_buffer_state(yyscanner ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * @param yyscanner The scanner object. + */ +/* %if-c-only */ +void promela__switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* TODO. We should be able to replace this entire function body + * with + * promela_pop_buffer_state(); + * promela_push_buffer_state(new_buffer); + */ + promela_ensure_buffer_stack (yyscanner); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + promela__load_buffer_state(yyscanner ); + + /* We don't actually know whether we did this switch during + * EOF (promela_wrap()) processing, but the only time this flag + * is looked at is after promela_wrap() is called, so it's safe + * to go ahead and always set it. + */ + yyg->yy_did_buffer_switch_on_eof = 1; +} + +/* %if-c-only */ +static void promela__load_buffer_state (yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + yyg->yy_hold_char = *yyg->yy_c_buf_p; +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * @param yyscanner The scanner object. + * @return the allocated buffer state. + */ +/* %if-c-only */ +YY_BUFFER_STATE promela__create_buffer (FILE * file, int size , yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) promela_alloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in promela__create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) promela_alloc(b->yy_buf_size + 2 ,yyscanner ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in promela__create_buffer()" ); + + b->yy_is_our_buffer = 1; + + promela__init_buffer(b,file ,yyscanner); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with promela__create_buffer() + * @param yyscanner The scanner object. + */ +/* %if-c-only */ +void promela__delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + promela_free((void *) b->yy_ch_buf ,yyscanner ); + + promela_free((void *) b ,yyscanner ); +} + +/* %if-c-only */ + +/* %endif */ + +/* %if-c++-only */ +/* %endif */ + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a promela_restart() or at EOF. + */ +/* %if-c-only */ +static void promela__init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ + +{ + int oerrno = errno; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + promela__flush_buffer(b ,yyscanner); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then promela__init_buffer was _probably_ + * called from promela_restart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER) { + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + /* %if-c-only */ + + b->yy_is_interactive = 0; + + /* %endif */ + /* %if-c++-only */ + /* %endif */ + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * @param yyscanner The scanner object. + */ +/* %if-c-only */ +void promela__flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + promela__load_buffer_state(yyscanner ); +} + +/* %if-c-or-c++ */ +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * @param yyscanner The scanner object. + */ +/* %if-c-only */ +void promela_push_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (new_buffer == NULL) + return; + + promela_ensure_buffer_stack(yyscanner); + + /* This block is copied from promela__switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + yyg->yy_buffer_stack_top++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from promela__switch_to_buffer. */ + promela__load_buffer_state(yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; +} +/* %endif */ + +/* %if-c-or-c++ */ +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * @param yyscanner The scanner object. + */ +/* %if-c-only */ +void promela_pop_buffer_state (yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (!YY_CURRENT_BUFFER) + return; + + promela__delete_buffer(YY_CURRENT_BUFFER ,yyscanner); + YY_CURRENT_BUFFER_LVALUE = NULL; + if (yyg->yy_buffer_stack_top > 0) + --yyg->yy_buffer_stack_top; + + if (YY_CURRENT_BUFFER) { + promela__load_buffer_state(yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; + } +} +/* %endif */ + +/* %if-c-or-c++ */ +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +/* %if-c-only */ +static void promela_ensure_buffer_stack (yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + yy_size_t num_to_alloc; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (!yyg->yy_buffer_stack) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + yyg->yy_buffer_stack = (struct yy_buffer_state**)promela_alloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in promela_ensure_buffer_stack()" ); + + memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + yyg->yy_buffer_stack_max = num_to_alloc; + yyg->yy_buffer_stack_top = 0; + return; + } + + if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1) { + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = yyg->yy_buffer_stack_max + grow_size; + yyg->yy_buffer_stack = (struct yy_buffer_state**)promela_realloc + (yyg->yy_buffer_stack, + num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in promela_ensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); + yyg->yy_buffer_stack_max = num_to_alloc; + } +} +/* %endif */ + +/* %if-c-only */ +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE promela__scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) promela_alloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in promela__scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + promela__switch_to_buffer(b ,yyscanner ); + + return b; +} +/* %endif */ + +/* %if-c-only */ +/** Setup the input buffer state to scan a string. The next call to promela_lex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * promela__scan_bytes() instead. + */ +YY_BUFFER_STATE promela__scan_string (yyconst char * yystr , yyscan_t yyscanner) { + + return promela__scan_bytes(yystr,strlen(yystr) ,yyscanner); +} +/* %endif */ + +/* %if-c-only */ +/** Setup the input buffer state to scan the given bytes. The next call to promela_lex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE promela__scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len , yyscan_t yyscanner) { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n, i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) promela_alloc(n ,yyscanner ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in promela__scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = promela__scan_buffer(buf,n ,yyscanner); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in promela__scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} +/* %endif */ + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +/* %if-c-only */ +static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} +/* %endif */ +/* %if-c++-only */ +/* %endif */ + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = yyg->yy_hold_char; \ + yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ + yyg->yy_hold_char = *yyg->yy_c_buf_p; \ + *yyg->yy_c_buf_p = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/* %if-c-only */ +/* %if-reentrant */ + +/** Get the user-defined data for this scanner. + * @param yyscanner The scanner object. + */ +YY_EXTRA_TYPE promela_get_extra (yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyextra; +} + +/* %endif */ + +/** Get the current line number. + * @param yyscanner The scanner object. + */ +int promela_get_lineno (yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yylineno; +} + +/** Get the current column number. + * @param yyscanner The scanner object. + */ +int promela_get_column (yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yycolumn; +} + +/** Get the input stream. + * @param yyscanner The scanner object. + */ +FILE *promela_get_in (yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyin; +} + +/** Get the output stream. + * @param yyscanner The scanner object. + */ +FILE *promela_get_out (yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyout; +} + +/** Get the length of the current token. + * @param yyscanner The scanner object. + */ +yy_size_t promela_get_leng (yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyleng; +} + +/** Get the current token. + * @param yyscanner The scanner object. + */ + +char *promela_get_text (yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yytext; +} + +/* %if-reentrant */ + +/** Set the user-defined data. This data is never touched by the scanner. + * @param user_defined The data to be associated with this scanner. + * @param yyscanner The scanner object. + */ +void promela_set_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyextra = user_defined ; +} + +/* %endif */ + +/** Set the current line number. + * @param line_number + * @param yyscanner The scanner object. + */ +void promela_set_lineno (int line_number , yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* lineno is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + yy_fatal_error( "promela_set_lineno called with no buffer" , yyscanner); + + yylineno = line_number; +} + +/** Set the current column. + * @param line_number + * @param yyscanner The scanner object. + */ +void promela_set_column (int column_no , yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* column is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + yy_fatal_error( "promela_set_column called with no buffer" , yyscanner); + + yycolumn = column_no; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * @param yyscanner The scanner object. + * @see promela__switch_to_buffer + */ +void promela_set_in (FILE * in_str , yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyin = in_str ; +} + +void promela_set_out (FILE * out_str , yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyout = out_str ; +} + +int promela_get_debug (yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yy_flex_debug; +} + +void promela_set_debug (int bdebug , yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yy_flex_debug = bdebug ; +} + +/* %endif */ + +/* %if-reentrant */ +/* Accessor methods for yylval and yylloc */ + +/* %if-bison-bridge */ + +YYSTYPE * promela_get_lval (yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yylval; +} + +void promela_set_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yylval = yylval_param; +} + +YYLTYPE *promela_get_lloc (yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yylloc; +} + +void promela_set_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yylloc = yylloc_param; +} + +/* %endif */ + +/* User-visible API */ + +/* promela_lex_init is special because it creates the scanner itself, so it is + * the ONLY reentrant function that doesn't take the scanner as the last argument. + * That's why we explicitly handle the declaration, instead of using our macros. + */ + +int promela_lex_init(yyscan_t* ptr_yy_globals) + +{ + if (ptr_yy_globals == NULL) { + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) promela_alloc ( sizeof( struct yyguts_t ), NULL ); + + if (*ptr_yy_globals == NULL) { + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + return yy_init_globals ( *ptr_yy_globals ); +} + +/* promela_lex_init_extra has the same functionality as promela_lex_init, but follows the + * convention of taking the scanner as the last argument. Note however, that + * this is a *pointer* to a scanner, as it will be allocated by this call (and + * is the reason, too, why this function also must handle its own declaration). + * The user defined value in the first argument will be available to promela_alloc in + * the yyextra field. + */ + +int promela_lex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals ) + +{ + struct yyguts_t dummy_yyguts; + + promela_set_extra (yy_user_defined, &dummy_yyguts); + + if (ptr_yy_globals == NULL) { + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) promela_alloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); + + if (*ptr_yy_globals == NULL) { + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in + yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + promela_set_extra (yy_user_defined, *ptr_yy_globals); + + return yy_init_globals ( *ptr_yy_globals ); +} + +/* %endif if-c-only */ + +/* %if-c-only */ +static int yy_init_globals (yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from promela_lex_destroy(), so don't allocate here. + */ + + yyg->yy_buffer_stack = 0; + yyg->yy_buffer_stack_top = 0; + yyg->yy_buffer_stack_max = 0; + yyg->yy_c_buf_p = (char *) 0; + yyg->yy_init = 0; + yyg->yy_start = 0; + + yyg->yy_start_stack_ptr = 0; + yyg->yy_start_stack_depth = 0; + yyg->yy_start_stack = NULL; + + /* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * promela_lex_init() + */ + return 0; +} +/* %endif */ + +/* %if-c-only SNIP! this currently causes conflicts with the c++ scanner */ +/* promela_lex_destroy is for both reentrant and non-reentrant scanners. */ +int promela_lex_destroy (yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER) { + promela__delete_buffer(YY_CURRENT_BUFFER ,yyscanner ); + YY_CURRENT_BUFFER_LVALUE = NULL; + promela_pop_buffer_state(yyscanner); + } + + /* Destroy the stack itself. */ + promela_free(yyg->yy_buffer_stack ,yyscanner); + yyg->yy_buffer_stack = NULL; + + /* Destroy the start condition stack. */ + promela_free(yyg->yy_start_stack ,yyscanner ); + yyg->yy_start_stack = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * promela_lex() is called, initialization will occur. */ + yy_init_globals( yyscanner); + + /* %if-reentrant */ + /* Destroy the main struct (reentrant only). */ + promela_free ( yyscanner , yyscanner ); + yyscanner = NULL; + /* %endif */ + return 0; +} +/* %endif */ + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *promela_alloc (yy_size_t size , yyscan_t yyscanner) { + return (void *) malloc( size ); +} + +void *promela_realloc (void * ptr, yy_size_t size , yyscan_t yyscanner) { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void promela_free (void * ptr , yyscan_t yyscanner) { + free( (char *) ptr ); /* see promela_realloc() for (char *) cast */ +} + +/* %if-tables-serialization definitions */ +/* %define-yytables The name for this specific scanner's tables. */ +#define YYTABLES_NAME "yytables" +/* %endif */ + +/* %ok-for-header */ + +#line 118 "promela.l" diff --git a/src/uscxml/plugins/datamodel/promela/parser/promela.tab.cpp b/src/uscxml/plugins/datamodel/promela/parser/promela.tab.cpp new file mode 100644 index 0000000..098c890 --- /dev/null +++ b/src/uscxml/plugins/datamodel/promela/parser/promela.tab.cpp @@ -0,0 +1,2634 @@ +/* A Bison parser, made by GNU Bison 2.7.12-4996. */ + +/* Bison implementation for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.7.12-4996" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 1 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + +/* Substitute the type names. */ +#define YYSTYPE PROMELA_STYPE +#define YYLTYPE PROMELA_LTYPE +/* Substitute the variable and function names. */ +#define yyparse promela_parse +#define yylex promela_lex +#define yyerror promela_error +#define yylval promela_lval +#define yychar promela_char +#define yydebug promela_debug +#define yynerrs promela_nerrs +#define yylloc promela_lloc + +/* Copy the first part of user declarations. */ +/* Line 371 of yacc.c */ +#line 14 "promela.ypp" + +#include "../PromelaParser.h" +#include "promela.tab.hpp" +#include <sys/types.h> +#include <stdarg.h> + +#define YYMAXDEPTH 20000 // default is 10000 +#define YYDEBUG 1 +#define YYERROR_VERBOSE 1 + +extern int promela_lex (PROMELA_STYPE* yylval_param, PROMELA_LTYPE* yylloc_param, void* yyscanner); + +using namespace uscxml; + +/* Line 371 of yacc.c */ +#line 93 "promela.tab.cpp" + +# ifndef YY_NULL +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULL nullptr +# else +# define YY_NULL 0 +# endif +# endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 1 +#endif + +/* In a future release of Bison, this section will be replaced + by #include "promela.tab.hpp". */ +#ifndef YY_PROMELA_PROMELA_TAB_HPP_INCLUDED +# define YY_PROMELA_PROMELA_TAB_HPP_INCLUDED +/* Enabling traces. */ +#ifndef PROMELA_DEBUG +# if defined YYDEBUG +# if YYDEBUG +# define PROMELA_DEBUG 1 +# else +# define PROMELA_DEBUG 0 +# endif +# else /* ! defined YYDEBUG */ +# define PROMELA_DEBUG 1 +# endif /* ! defined YYDEBUG */ +#endif /* ! defined PROMELA_DEBUG */ +#if PROMELA_DEBUG +extern int promela_debug; +#endif + +/* Tokens. */ +#ifndef PROMELA_TOKENTYPE +# define PROMELA_TOKENTYPE +/* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ +enum promela_tokentype { + PML_VAR_ARRAY = 258, + PML_VARLIST = 259, + PML_DECL = 260, + PML_DECLLIST = 261, + PML_STMNT = 262, + PML_COLON = 263, + PML_EXPR = 264, + PML_NAMELIST = 265, + PML_ASSERT = 266, + PML_PRINT = 267, + PML_PRINTM = 268, + PML_LEN = 269, + PML_STRING = 270, + PML_TYPEDEF = 271, + PML_MTYPE = 272, + PML_INLINE = 273, + PML_RETURN = 274, + PML_LABEL = 275, + PML_OF = 276, + PML_GOTO = 277, + PML_BREAK = 278, + PML_ELSE = 279, + PML_SEMI = 280, + PML_ARROW = 281, + PML_IF = 282, + PML_FI = 283, + PML_DO = 284, + PML_OD = 285, + PML_FOR = 286, + PML_SELECT = 287, + PML_IN = 288, + PML_SEP = 289, + PML_DOTDOT = 290, + PML_HIDDEN = 291, + PML_SHOW = 292, + PML_ISLOCAL = 293, + PML_CONST = 294, + PML_TYPE = 295, + PML_XU = 296, + PML_NAME = 297, + PML_UNAME = 298, + PML_PNAME = 299, + PML_INAME = 300, + PML_CLAIM = 301, + PML_TRACE = 302, + PML_INIT = 303, + PML_LTL = 304, + PML_COMMA = 305, + PML_ASGN = 306, + PML_AND = 307, + PML_OR = 308, + PML_BITAND = 309, + PML_BITXOR = 310, + PML_BITOR = 311, + PML_NE = 312, + PML_EQ = 313, + PML_LE = 314, + PML_GE = 315, + PML_LT = 316, + PML_GT = 317, + PML_RSHIFT = 318, + PML_LSHIFT = 319, + PML_MINUS = 320, + PML_PLUS = 321, + PML_MODULO = 322, + PML_DIVIDE = 323, + PML_TIMES = 324, + PML_DECR = 325, + PML_INCR = 326, + PML_COMPL = 327, + PML_NEG = 328, + PML_CMPND = 329, + PML_DOT = 330 +}; +#endif + + +#if ! defined PROMELA_STYPE && ! defined PROMELA_STYPE_IS_DECLARED +typedef union PROMELA_STYPE { + /* Line 387 of yacc.c */ +#line 39 "promela.ypp" + + uscxml::PromelaParserNode* node; + char* value; + + + /* Line 387 of yacc.c */ +#line 225 "promela.tab.cpp" +} PROMELA_STYPE; +# define PROMELA_STYPE_IS_TRIVIAL 1 +# define promela_stype PROMELA_STYPE /* obsolescent; will be withdrawn */ +# define PROMELA_STYPE_IS_DECLARED 1 +#endif + +#if ! defined PROMELA_LTYPE && ! defined PROMELA_LTYPE_IS_DECLARED +typedef struct PROMELA_LTYPE { + int first_line; + int first_column; + int last_line; + int last_column; +} PROMELA_LTYPE; +# define promela_ltype PROMELA_LTYPE /* obsolescent; will be withdrawn */ +# define PROMELA_LTYPE_IS_DECLARED 1 +# define PROMELA_LTYPE_IS_TRIVIAL 1 +#endif + + +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int promela_parse (void *YYPARSE_PARAM); +#else +int promela_parse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int promela_parse (uscxml::PromelaParser* ctx, void * scanner); +#else +int promela_parse (); +#endif +#endif /* ! YYPARSE_PARAM */ + +#endif /* !YY_PROMELA_PROMELA_TAB_HPP_INCLUDED */ + +/* Copy the second part of user declarations. */ + +/* Line 390 of yacc.c */ +#line 265 "promela.tab.cpp" + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include <libintl.h> /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# endif +#endif + +#ifndef __attribute__ +/* This feature is available in gcc versions 2.5 and later. */ +# if (! defined __GNUC__ || __GNUC__ < 2 \ + || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)) +# define __attribute__(Spec) /* empty */ +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(E) ((void) (E)) +#else +# define YYUSE(E) /* empty */ +#endif + + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(N) (N) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int yyi) +#else +static int +YYID (yyi) +int yyi; +#endif +{ + return yyi; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include <alloca.h> /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include <malloc.h> /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +/* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC +/* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM +/* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined PROMELA_LTYPE_IS_TRIVIAL && PROMELA_LTYPE_IS_TRIVIAL \ + && defined PROMELA_STYPE_IS_TRIVIAL && PROMELA_STYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc { + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; + YYLTYPE yyls_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + + 2 * YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 32 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 285 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 82 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 21 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 81 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 143 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 330 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = { + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 11, 12, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 13, 2, 14, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 15, 2, 16, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81 +}; + +#if PROMELA_DEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint16 yyprhs[] = { + 0, 0, 3, 5, 7, 9, 11, 13, 18, 21, + 22, 25, 29, 33, 37, 41, 45, 49, 53, 57, + 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, + 101, 104, 107, 112, 114, 116, 118, 119, 121, 123, + 125, 129, 133, 140, 143, 149, 151, 154, 158, 160, + 164, 166, 170, 172, 176, 181, 183, 186, 190, 194, + 198, 202, 206, 210, 212, 215, 218, 220, 223, 227, + 229, 233, 236, 239, 245, 250, 255, 258, 260, 261, + 264, 266 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = { + 83, 0, -1, 92, -1, 88, -1, 98, -1, 86, + -1, 48, -1, 48, 13, 88, 14, -1, 85, 87, + -1, -1, 81, 86, -1, 11, 88, 12, -1, 88, + 72, 88, -1, 88, 71, 88, -1, 88, 75, 88, + -1, 88, 74, 88, -1, 88, 73, 88, -1, 88, + 60, 88, -1, 88, 61, 88, -1, 88, 62, 88, + -1, 88, 68, 88, -1, 88, 67, 88, -1, 88, + 66, 88, -1, 88, 65, 88, -1, 88, 64, 88, + -1, 88, 63, 88, -1, 88, 58, 88, -1, 88, + 59, 88, -1, 88, 70, 88, -1, 88, 69, 88, + -1, 79, 88, -1, 71, 88, -1, 20, 11, 84, + 12, -1, 84, -1, 45, -1, 21, -1, -1, 42, + -1, 43, -1, 44, -1, 89, 46, 93, -1, 89, + 49, 93, -1, 89, 46, 57, 15, 97, 16, -1, + 89, 91, -1, 22, 48, 15, 92, 16, -1, 90, + -1, 90, 31, -1, 90, 31, 92, -1, 94, -1, + 94, 56, 93, -1, 95, -1, 95, 57, 88, -1, + 48, -1, 48, 8, 45, -1, 48, 13, 96, 14, + -1, 45, -1, 71, 96, -1, 11, 96, 12, -1, + 96, 72, 96, -1, 96, 71, 96, -1, 96, 75, + 96, -1, 96, 74, 96, -1, 96, 73, 96, -1, + 48, -1, 97, 48, -1, 97, 56, -1, 99, -1, + 99, 31, -1, 99, 31, 98, -1, 100, -1, 84, + 57, 88, -1, 84, 77, -1, 84, 76, -1, 18, + 11, 21, 101, 12, -1, 18, 11, 84, 12, -1, + 18, 11, 45, 12, -1, 17, 88, -1, 88, -1, + -1, 56, 102, -1, 88, -1, 88, 56, 102, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint8 yyrline[] = { + 0, 85, 85, 89, 93, 99, 102, 103, 106, 121, + 122, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 151, 152, 154, 155, 156, 157, 163, 164, 165, 166, + 169, 170, 171, 172, 175, 178, 179, 180, 190, 191, + 194, 195, 198, 199, 200, 203, 204, 205, 206, 207, + 208, 209, 210, 213, 214, 223, 226, 227, 228, 231, + 234, 235, 236, 237, 238, 239, 240, 241, 244, 245, + 248, 249 +}; +#endif + +#if PROMELA_DEBUG || YYERROR_VERBOSE || 1 +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = { + "$end", "error", "$undefined", "PML_VAR_ARRAY", "PML_VARLIST", + "PML_DECL", "PML_DECLLIST", "PML_STMNT", "PML_COLON", "PML_EXPR", + "PML_NAMELIST", "'('", "')'", "'['", "']'", "'{'", "'}'", "PML_ASSERT", + "PML_PRINT", "PML_PRINTM", "PML_LEN", "PML_STRING", "PML_TYPEDEF", + "PML_MTYPE", "PML_INLINE", "PML_RETURN", "PML_LABEL", "PML_OF", + "PML_GOTO", "PML_BREAK", "PML_ELSE", "PML_SEMI", "PML_ARROW", "PML_IF", + "PML_FI", "PML_DO", "PML_OD", "PML_FOR", "PML_SELECT", "PML_IN", + "PML_SEP", "PML_DOTDOT", "PML_HIDDEN", "PML_SHOW", "PML_ISLOCAL", + "PML_CONST", "PML_TYPE", "PML_XU", "PML_NAME", "PML_UNAME", "PML_PNAME", + "PML_INAME", "PML_CLAIM", "PML_TRACE", "PML_INIT", "PML_LTL", + "PML_COMMA", "PML_ASGN", "PML_AND", "PML_OR", "PML_BITAND", "PML_BITXOR", + "PML_BITOR", "PML_NE", "PML_EQ", "PML_LE", "PML_GE", "PML_LT", "PML_GT", + "PML_RSHIFT", "PML_LSHIFT", "PML_MINUS", "PML_PLUS", "PML_MODULO", + "PML_DIVIDE", "PML_TIMES", "PML_DECR", "PML_INCR", "PML_COMPL", + "PML_NEG", "PML_CMPND", "PML_DOT", "$accept", "program", "varref", + "pfld", "cmpnd", "sfld", "expr", "vis", "one_decl", "utype", "decl_lst", + "var_list", "ivar", "vardcl", "const_expr", "nlst", "stmnt_lst", "stmnt", + "Stmnt", "prargs", "arg", YY_NULL +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = { + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 40, 41, 91, 93, 123, 125, 266, 267, 268, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, + 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, + 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, + 329, 330 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = { + 0, 82, 83, 83, 83, 84, 85, 85, 86, 87, + 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, + 90, 90, 90, 90, 91, 92, 92, 92, 93, 93, + 94, 94, 95, 95, 95, 96, 96, 96, 96, 96, + 96, 96, 96, 97, 97, 97, 98, 98, 98, 99, + 100, 100, 100, 100, 100, 100, 100, 100, 101, 101, + 102, 102 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = { + 0, 2, 1, 1, 1, 1, 1, 4, 2, 0, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 4, 1, 1, 1, 0, 1, 1, 1, + 3, 3, 6, 2, 5, 1, 2, 3, 1, 3, + 1, 3, 1, 3, 4, 1, 2, 3, 3, 3, + 3, 3, 3, 1, 2, 2, 1, 2, 3, 1, + 3, 2, 2, 5, 4, 4, 2, 1, 0, 2, + 1, 3 +}; + +/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = { + 36, 0, 0, 0, 0, 35, 37, 38, 39, 34, + 6, 0, 0, 0, 33, 9, 5, 3, 0, 45, + 2, 4, 66, 69, 33, 0, 76, 0, 0, 0, + 31, 30, 1, 0, 72, 71, 0, 8, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, + 36, 67, 11, 78, 0, 0, 0, 0, 70, 10, + 26, 27, 17, 18, 19, 25, 24, 23, 22, 21, + 20, 29, 28, 13, 12, 16, 15, 14, 0, 52, + 0, 40, 48, 50, 41, 47, 77, 68, 0, 0, + 75, 74, 32, 7, 36, 0, 0, 0, 0, 0, + 80, 79, 73, 0, 53, 0, 55, 0, 0, 63, + 0, 49, 51, 0, 44, 0, 56, 54, 0, 0, + 0, 0, 0, 42, 64, 65, 81, 57, 59, 58, + 62, 61, 60 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = { + -1, 13, 24, 15, 16, 37, 110, 18, 19, 59, + 20, 91, 92, 93, 118, 120, 21, 22, 23, 99, + 111 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -112 +static const yytype_int16 yypact[] = { + 14, 53, 53, 3, 13, -112, -112, -112, -112, -112, + 15, 53, 53, 26, 34, -51, -112, 138, 81, 5, + -112, -112, 58, -112, -112, 75, 160, 169, 42, 53, + -66, -112, -112, 53, -112, -112, 42, -112, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 44, -35, 51, -112, + 72, 49, -112, 46, 88, 96, 100, 93, 160, -112, + 176, 176, 189, 189, 189, 200, 200, 207, 207, 207, + 207, 120, 120, -66, -66, -112, -112, -112, 98, -3, + 102, -112, 63, 74, -112, -112, 160, -112, 53, 113, + -112, -112, -112, -112, 62, 126, -8, 167, 51, 53, + 114, -112, -112, 267, -112, -8, -112, -8, 9, -112, + 70, -112, 160, 53, -112, 4, 48, -112, -8, -8, + -8, -8, -8, -112, -112, -112, -112, -112, 48, 48, + -112, -112, -112 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = { + -112, -112, 68, -112, 180, -112, 0, -112, -112, -112, + -33, -43, -112, -112, -111, -112, 223, -112, -112, -112, + 162 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -78 +static const yytype_int16 yytable[] = { + 17, 25, 26, 115, 125, 105, 126, 53, 54, 55, + 106, 30, 31, 89, 27, 94, 137, 138, 139, 140, + 141, 142, 90, 127, 28, 1, 32, 95, 29, 67, + 36, 2, 3, 68, 4, 5, 60, 116, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 6, 7, 8, 9, + 1, 96, 10, 117, 1, 121, 2, 3, 14, 4, + 5, 113, -46, 4, 5, 128, 129, 130, 131, 132, + 128, 129, 130, 131, 132, 11, 133, 62, -46, 61, + 10, 33, 88, 12, 9, 65, 66, 10, 9, 89, + 100, 10, 98, 56, 6, 7, 8, 103, 101, 122, + 34, 35, 102, 104, 6, 7, 8, 107, 134, 108, + 11, 130, 131, 132, 11, 112, 135, 57, 12, 14, + 58, 109, 12, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, -77, + 123, 114, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 63, 51, 52, 53, 54, 55, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 64, 119, 69, 10, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 49, 50, 51, 52, + 53, 54, 55, 124, 97, 136 +}; + +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-112))) + +#define yytable_value_is_error(Yytable_value) \ + YYID (0) + +static const yytype_uint8 yycheck[] = { + 0, 1, 2, 11, 115, 8, 117, 73, 74, 75, + 13, 11, 12, 48, 11, 58, 12, 128, 129, 130, + 131, 132, 57, 14, 11, 11, 0, 60, 13, 29, + 81, 17, 18, 33, 20, 21, 31, 45, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 42, 43, 44, 45, + 11, 61, 48, 71, 11, 108, 17, 18, 0, 20, + 21, 104, 0, 20, 21, 71, 72, 73, 74, 75, + 71, 72, 73, 74, 75, 71, 16, 12, 16, 31, + 48, 57, 48, 79, 45, 27, 28, 48, 45, 48, + 12, 48, 56, 22, 42, 43, 44, 14, 12, 109, + 76, 77, 12, 15, 42, 43, 44, 15, 48, 56, + 71, 73, 74, 75, 71, 12, 56, 46, 79, 61, + 49, 57, 79, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 31, + 56, 45, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + 21, 71, 72, 73, 74, 75, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 45, 48, 36, 48, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 74, 75, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 69, 70, 71, 72, + 73, 74, 75, 16, 61, 123 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = { + 0, 11, 17, 18, 20, 21, 42, 43, 44, 45, + 48, 71, 79, 83, 84, 85, 86, 88, 89, 90, + 92, 98, 99, 100, 84, 88, 88, 11, 11, 13, + 88, 88, 0, 57, 76, 77, 81, 87, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 22, 46, 49, 91, + 31, 31, 12, 21, 45, 84, 84, 88, 88, 86, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 48, 48, + 57, 93, 94, 95, 93, 92, 88, 98, 56, 101, + 12, 12, 12, 14, 15, 8, 13, 15, 56, 57, + 88, 102, 12, 92, 45, 11, 45, 71, 96, 48, + 97, 93, 88, 56, 16, 96, 96, 14, 71, 72, + 73, 74, 75, 16, 48, 56, 102, 12, 96, 96, + 96, 96, 96 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. However, + YYFAIL appears to be in use. Nevertheless, it is formally deprecated + in Bison 2.4.2's NEWS entry, where a plan to phase it out is + discussed. */ + +#define YYFAIL goto yyerrlab +#if defined YYFAIL +/* This is here to suppress warnings from the GCC cpp's + -Wunused-macros. Normally we don't worry about that warning, but + some users do, and we want to make it easy for users to remove + YYFAIL uses, which will produce warnings from Bison 2.5. */ +#endif + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (&yylloc, ctx, scanner, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + +/* Error token number */ +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if defined PROMELA_LTYPE_IS_TRIVIAL && PROMELA_LTYPE_IS_TRIVIAL + +/* Print *YYLOCP on YYO. Private, do not rely on its existence. */ + +__attribute__((__unused__)) +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static unsigned +yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp) +#else +static unsigned +yy_location_print_ (yyo, yylocp) +FILE *yyo; +YYLTYPE const * const yylocp; +#endif +{ + unsigned res = 0; + int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0; + if (0 <= yylocp->first_line) { + res += fprintf (yyo, "%d", yylocp->first_line); + if (0 <= yylocp->first_column) + res += fprintf (yyo, ".%d", yylocp->first_column); + } + if (0 <= yylocp->last_line) { + if (yylocp->first_line < yylocp->last_line) { + res += fprintf (yyo, "-%d", yylocp->last_line); + if (0 <= end_col) + res += fprintf (yyo, ".%d", end_col); + } else if (0 <= end_col && yylocp->first_column < end_col) + res += fprintf (yyo, "-%d", end_col); + } + return res; +} + +# define YY_LOCATION_PRINT(File, Loc) \ + yy_location_print_ (File, &(Loc)) + +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ +#ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) +#else +# define YYLEX yylex (&yylval, &yylloc, scanner) +#endif + +/* Enable debugging if requested. */ +#if PROMELA_DEBUG + +# ifndef YYFPRINTF +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value, Location, ctx, scanner); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, uscxml::PromelaParser* ctx, void * scanner) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, ctx, scanner) +FILE *yyoutput; +int yytype; +YYSTYPE const * const yyvaluep; +YYLTYPE const * const yylocationp; +uscxml::PromelaParser* ctx; +void * scanner; +#endif +{ + FILE *yyo = yyoutput; + YYUSE (yyo); + if (!yyvaluep) + return; + YYUSE (yylocationp); + YYUSE (ctx); + YYUSE (scanner); +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + YYUSE (yytype); +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, uscxml::PromelaParser* ctx, void * scanner) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, ctx, scanner) +FILE *yyoutput; +int yytype; +YYSTYPE const * const yyvaluep; +YYLTYPE const * const yylocationp; +uscxml::PromelaParser* ctx; +void * scanner; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + YY_LOCATION_PRINT (yyoutput, *yylocationp); + YYFPRINTF (yyoutput, ": "); + yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, ctx, scanner); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +#else +static void +yy_stack_print (yybottom, yytop) +yytype_int16 *yybottom; +yytype_int16 *yytop; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, uscxml::PromelaParser* ctx, void * scanner) +#else +static void +yy_reduce_print (yyvsp, yylsp, yyrule, ctx, scanner) +YYSTYPE *yyvsp; +YYLTYPE *yylsp; +int yyrule; +uscxml::PromelaParser* ctx; +void * scanner; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + , &(yylsp[(yyi + 1) - (yynrhs)]) , ctx, scanner); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, yylsp, Rule, ctx, scanner); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !PROMELA_DEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !PROMELA_DEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) +const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) +char *yydest; +const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) { + if (*yystr == '"') { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } +do_not_strip_quotes: + ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) { + YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = YY_NULL; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; + + /* There are many possibilities here to consider: + - Assume YYFAIL is not used. It's too flawed to consider. See + <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html> + for details. YYERROR is fine as it does not invoke this + function. + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) { + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + { + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } + } + } + + switch (yycount) { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + + if (*yymsg_alloc < yysize) { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } else { + yyp++; + yyformat++; + } + } + return 0; +} +#endif /* YYERROR_VERBOSE */ + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, uscxml::PromelaParser* ctx, void * scanner) +#else +static void +yydestruct (yymsg, yytype, yyvaluep, yylocationp, ctx, scanner) +const char *yymsg; +int yytype; +YYSTYPE *yyvaluep; +YYLTYPE *yylocationp; +uscxml::PromelaParser* ctx; +void * scanner; +#endif +{ + YYUSE (yyvaluep); + YYUSE (yylocationp); + YYUSE (ctx); + YYUSE (scanner); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + YYUSE (yytype); +} + + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) +void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (uscxml::PromelaParser* ctx, void * scanner) +#else +int +yyparse (ctx, scanner) +uscxml::PromelaParser* ctx; +void * scanner; +#endif +#endif +{ + /* The lookahead symbol. */ + int yychar; + + +#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ + /* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else + /* Default value used for initialization, for pacifying older GCCs + or non-GCC compilers. */ + static YYSTYPE yyval_default; +# define YY_INITIAL_VALUE(Value) = Value +#endif + static YYLTYPE yyloc_default +# if defined PROMELA_LTYPE_IS_TRIVIAL && PROMELA_LTYPE_IS_TRIVIAL + = { 1, 1, 1, 1 } +# endif + ; +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + + /* The semantic value of the lookahead symbol. */ + YYSTYPE yylval YY_INITIAL_VALUE(yyval_default); + + /* Location data for the lookahead symbol. */ + YYLTYPE yylloc = yyloc_default; + + + /* Number of syntax errors so far. */ + int yynerrs; + + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + `yyss': related to states. + `yyvs': related to semantic values. + `yyls': related to locations. + + Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + /* The location stack. */ + YYLTYPE yylsa[YYINITDEPTH]; + YYLTYPE *yyls; + YYLTYPE *yylsp; + + /* The locations where the error started and ended. */ + YYLTYPE yyerror_range[3]; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + YYLTYPE yyloc; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; + yylsp = yyls = yylsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + yylsp[0] = yylloc; + goto yysetstate; + + /*------------------------------------------------------------. + | yynewstate -- Push a new state, which is found in yystate. | + `------------------------------------------------------------*/ +yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + +yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + YYLTYPE *yyls1 = yyls; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yyls1, yysize * sizeof (*yylsp), + &yystacksize); + + yyls = yyls1; + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); + YYSTACK_RELOCATE (yyls_alloc, yyls); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + yylsp = yyls + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + + /*-----------. + | yybackup. | + `-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } else { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) { + if (yytable_value_is_error (yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + *++yylsp = yylloc; + goto yynewstate; + + + /*-----------------------------------------------------------. + | yydefault -- do the default action for the current state. | + `-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + + /*-----------------------------. + | yyreduce -- Do a reduction. | + `-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + /* Default location. */ + YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); + YY_REDUCE_PRINT (yyn); + switch (yyn) { + case 2: + /* Line 1787 of yacc.c */ +#line 85 "promela.ypp" + { + ctx->ast = (yyvsp[(1) - (1)].node); + ctx->type = PromelaParser::PROMELA_DECL; + } + break; + + case 3: + /* Line 1787 of yacc.c */ +#line 89 "promela.ypp" + { + ctx->ast = (yyvsp[(1) - (1)].node); + ctx->type = PromelaParser::PROMELA_EXPR; + } + break; + + case 4: + /* Line 1787 of yacc.c */ +#line 93 "promela.ypp" + { + ctx->ast = (yyvsp[(1) - (1)].node); + ctx->type = PromelaParser::PROMELA_STMNT; + } + break; + + case 5: + /* Line 1787 of yacc.c */ +#line 99 "promela.ypp" + { + (yyval.node) = (yyvsp[(1) - (1)].node); + } + break; + + case 6: + /* Line 1787 of yacc.c */ +#line 102 "promela.ypp" + { + (yyval.node) = ctx->value(PML_NAME, (void*)&((yylsp[(1) - (1)])), (yyvsp[(1) - (1)].value)); + free((yyvsp[(1) - (1)].value)); + } + break; + + case 7: + /* Line 1787 of yacc.c */ +#line 103 "promela.ypp" + { + (yyval.node) = ctx->node(PML_VAR_ARRAY, 2, ctx->value(PML_NAME, (void*)&((yylsp[(1) - (4)])), (yyvsp[(1) - (4)].value)), (yyvsp[(3) - (4)].node)); + free((yyvsp[(1) - (4)].value)); + } + break; + + case 8: + /* Line 1787 of yacc.c */ +#line 107 "promela.ypp" + { + if ((yyvsp[(2) - (2)].node) != NULL) { + if ((yyvsp[(2) - (2)].node)->type == PML_CMPND) { + (yyval.node) = ctx->node(PML_CMPND, 1, (yyvsp[(1) - (2)].node)); + (yyval.node)->merge((yyvsp[(2) - (2)].node)); + delete (yyvsp[(2) - (2)].node); + } else { + (yyval.node) = ctx->node(PML_CMPND, 2, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node)); + } + } else { + (yyval.node) = (yyvsp[(1) - (2)].node); + } + } + break; + + case 9: + /* Line 1787 of yacc.c */ +#line 121 "promela.ypp" + { + (yyval.node) = NULL; + } + break; + + case 10: + /* Line 1787 of yacc.c */ +#line 122 "promela.ypp" + { + (yyval.node) = (yyvsp[(2) - (2)].node); + } + break; + + case 11: + /* Line 1787 of yacc.c */ +#line 132 "promela.ypp" + { + (yyval.node) = (yyvsp[(2) - (3)].node); + } + break; + + case 12: + /* Line 1787 of yacc.c */ +#line 133 "promela.ypp" + { + (yyval.node) = ctx->node(PML_PLUS, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 13: + /* Line 1787 of yacc.c */ +#line 134 "promela.ypp" + { + (yyval.node) = ctx->node(PML_MINUS, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 14: + /* Line 1787 of yacc.c */ +#line 135 "promela.ypp" + { + (yyval.node) = ctx->node(PML_TIMES, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 15: + /* Line 1787 of yacc.c */ +#line 136 "promela.ypp" + { + (yyval.node) = ctx->node(PML_DIVIDE, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 16: + /* Line 1787 of yacc.c */ +#line 137 "promela.ypp" + { + (yyval.node) = ctx->node(PML_MODULO, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 17: + /* Line 1787 of yacc.c */ +#line 138 "promela.ypp" + { + (yyval.node) = ctx->node(PML_BITAND, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 18: + /* Line 1787 of yacc.c */ +#line 139 "promela.ypp" + { + (yyval.node) = ctx->node(PML_BITXOR, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 19: + /* Line 1787 of yacc.c */ +#line 140 "promela.ypp" + { + (yyval.node) = ctx->node(PML_BITOR, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 20: + /* Line 1787 of yacc.c */ +#line 141 "promela.ypp" + { + (yyval.node) = ctx->node(PML_GT, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 21: + /* Line 1787 of yacc.c */ +#line 142 "promela.ypp" + { + (yyval.node) = ctx->node(PML_LT, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 22: + /* Line 1787 of yacc.c */ +#line 143 "promela.ypp" + { + (yyval.node) = ctx->node(PML_GE, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 23: + /* Line 1787 of yacc.c */ +#line 144 "promela.ypp" + { + (yyval.node) = ctx->node(PML_LE, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 24: + /* Line 1787 of yacc.c */ +#line 145 "promela.ypp" + { + (yyval.node) = ctx->node(PML_EQ, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 25: + /* Line 1787 of yacc.c */ +#line 146 "promela.ypp" + { + (yyval.node) = ctx->node(PML_NE, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 26: + /* Line 1787 of yacc.c */ +#line 147 "promela.ypp" + { + (yyval.node) = ctx->node(PML_AND, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 27: + /* Line 1787 of yacc.c */ +#line 148 "promela.ypp" + { + (yyval.node) = ctx->node(PML_OR, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 28: + /* Line 1787 of yacc.c */ +#line 149 "promela.ypp" + { + (yyval.node) = ctx->node(PML_LSHIFT, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 29: + /* Line 1787 of yacc.c */ +#line 150 "promela.ypp" + { + (yyval.node) = ctx->node(PML_RSHIFT, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 30: + /* Line 1787 of yacc.c */ +#line 151 "promela.ypp" + { + (yyval.node) = ctx->node(PML_NEG, 1, (yyvsp[(2) - (2)].node)); + } + break; + + case 31: + /* Line 1787 of yacc.c */ +#line 152 "promela.ypp" + { + (yyval.node) = ctx->node(PML_MINUS, 1, (yyvsp[(2) - (2)].node)); + } + break; + + case 32: + /* Line 1787 of yacc.c */ +#line 154 "promela.ypp" + { + (yyval.node) = ctx->node(PML_LEN, 1, (yyvsp[(3) - (4)].node)); + } + break; + + case 33: + /* Line 1787 of yacc.c */ +#line 155 "promela.ypp" + { + (yyval.node) = (yyvsp[(1) - (1)].node); + } + break; + + case 34: + /* Line 1787 of yacc.c */ +#line 156 "promela.ypp" + { + (yyval.node) = ctx->value(PML_CONST, (void*)&((yylsp[(1) - (1)])), (yyvsp[(1) - (1)].value)); + free((yyvsp[(1) - (1)].value)); + } + break; + + case 35: + /* Line 1787 of yacc.c */ +#line 157 "promela.ypp" + { + /* Non standard promela for string literals */ + (yyval.node) = ctx->value(PML_STRING, (void*)&((yylsp[(1) - (1)])), (yyvsp[(1) - (1)].value)); + free((yyvsp[(1) - (1)].value)); + } + break; + + case 36: + /* Line 1787 of yacc.c */ +#line 163 "promela.ypp" + { + (yyval.node) = ctx->node(PML_SHOW, 0); + } + break; + + case 37: + /* Line 1787 of yacc.c */ +#line 164 "promela.ypp" + { + (yyval.node) = ctx->node(PML_HIDDEN, 0); + } + break; + + case 38: + /* Line 1787 of yacc.c */ +#line 165 "promela.ypp" + { + (yyval.node) = ctx->node(PML_SHOW, 0); + } + break; + + case 39: + /* Line 1787 of yacc.c */ +#line 166 "promela.ypp" + { + (yyval.node) = ctx->node(PML_ISLOCAL, 0); + } + break; + + case 40: + /* Line 1787 of yacc.c */ +#line 169 "promela.ypp" + { + (yyval.node) = ctx->node(PML_DECL, 3, (yyvsp[(1) - (3)].node), ctx->value(PML_TYPE, (void*)&((yylsp[(2) - (3)])), (yyvsp[(2) - (3)].value)), (yyvsp[(3) - (3)].node)); + free((yyvsp[(2) - (3)].value)); + } + break; + + case 41: + /* Line 1787 of yacc.c */ +#line 170 "promela.ypp" + { + (yyval.node) = ctx->node(PML_UNAME, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 42: + /* Line 1787 of yacc.c */ +#line 171 "promela.ypp" + { + (yyval.node) = ctx->node(PML_DECL, 3, (yyvsp[(1) - (6)].node), ctx->value(PML_TYPE, (void*)&((yylsp[(2) - (6)])), (yyvsp[(2) - (6)].value)), (yyvsp[(5) - (6)].node)); + free((yyvsp[(2) - (6)].value)); + } + break; + + case 43: + /* Line 1787 of yacc.c */ +#line 172 "promela.ypp" + { + (yyval.node) = (yyvsp[(2) - (2)].node); + } + break; + + case 44: + /* Line 1787 of yacc.c */ +#line 175 "promela.ypp" + { + (yyval.node) = ctx->node(PML_TYPEDEF, 2, ctx->value(PML_NAME, (void*)&((yylsp[(2) - (5)])), (yyvsp[(2) - (5)].value)), (yyvsp[(4) - (5)].node)); + } + break; + + case 45: + /* Line 1787 of yacc.c */ +#line 178 "promela.ypp" + { + (yyval.node) = (yyvsp[(1) - (1)].node); + } + break; + + case 46: + /* Line 1787 of yacc.c */ +#line 179 "promela.ypp" + { + (yyval.node) = (yyvsp[(1) - (2)].node); + } + break; + + case 47: + /* Line 1787 of yacc.c */ +#line 180 "promela.ypp" + { + (yyval.node) = ctx->node(PML_DECLLIST, 1, (yyvsp[(1) - (3)].node)); + if((yyvsp[(3) - (3)].node)->type == PML_DECLLIST) { + (yyval.node)->merge((yyvsp[(3) - (3)].node)); + delete (yyvsp[(3) - (3)].node); + } else { + (yyval.node)->push((yyvsp[(3) - (3)].node)); + } + } + break; + + case 48: + /* Line 1787 of yacc.c */ +#line 190 "promela.ypp" + { + (yyval.node) = ctx->node(PML_VARLIST, 1, (yyvsp[(1) - (1)].node)); + } + break; + + case 49: + /* Line 1787 of yacc.c */ +#line 191 "promela.ypp" + { + (yyval.node) = ctx->node(PML_VARLIST, 1, (yyvsp[(1) - (3)].node)); + (yyval.node)->merge((yyvsp[(3) - (3)].node)); + delete (yyvsp[(3) - (3)].node); + } + break; + + case 50: + /* Line 1787 of yacc.c */ +#line 194 "promela.ypp" + { + (yyval.node) = (yyvsp[(1) - (1)].node); + } + break; + + case 51: + /* Line 1787 of yacc.c */ +#line 195 "promela.ypp" + { + (yyval.node) = ctx->node(PML_ASGN, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 52: + /* Line 1787 of yacc.c */ +#line 198 "promela.ypp" + { + (yyval.node) = ctx->value(PML_NAME, (void*)&((yylsp[(1) - (1)])), (yyvsp[(1) - (1)].value)); + free((yyvsp[(1) - (1)].value)); + } + break; + + case 53: + /* Line 1787 of yacc.c */ +#line 199 "promela.ypp" + { + (yyval.node) = ctx->node(PML_COLON, 2, ctx->value(PML_NAME, (void*)&((yylsp[(1) - (3)])), (yyvsp[(1) - (3)].value)), ctx->value(PML_CONST, (void*)&((yylsp[(3) - (3)])), (yyvsp[(3) - (3)].value))); + free((yyvsp[(1) - (3)].value)); + free((yyvsp[(3) - (3)].value)); + } + break; + + case 54: + /* Line 1787 of yacc.c */ +#line 200 "promela.ypp" + { + (yyval.node) = ctx->node(PML_VAR_ARRAY, 2, ctx->value(PML_NAME, (void*)&((yylsp[(1) - (4)])), (yyvsp[(1) - (4)].value)), (yyvsp[(3) - (4)].node)); + free((yyvsp[(1) - (4)].value)); + } + break; + + case 55: + /* Line 1787 of yacc.c */ +#line 203 "promela.ypp" + { + (yyval.node) = ctx->value(PML_CONST, (void*)&((yylsp[(1) - (1)])), (yyvsp[(1) - (1)].value)); + free((yyvsp[(1) - (1)].value)); + } + break; + + case 56: + /* Line 1787 of yacc.c */ +#line 204 "promela.ypp" + { + (yyval.node) = ctx->node(PML_MINUS, 1, (yyvsp[(2) - (2)].node)); + } + break; + + case 57: + /* Line 1787 of yacc.c */ +#line 205 "promela.ypp" + { + (yyval.node) = (yyvsp[(2) - (3)].node); + } + break; + + case 58: + /* Line 1787 of yacc.c */ +#line 206 "promela.ypp" + { + (yyval.node) = ctx->node(PML_PLUS, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 59: + /* Line 1787 of yacc.c */ +#line 207 "promela.ypp" + { + (yyval.node) = ctx->node(PML_MINUS, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 60: + /* Line 1787 of yacc.c */ +#line 208 "promela.ypp" + { + (yyval.node) = ctx->node(PML_TIMES, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 61: + /* Line 1787 of yacc.c */ +#line 209 "promela.ypp" + { + (yyval.node) = ctx->node(PML_DIVIDE, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 62: + /* Line 1787 of yacc.c */ +#line 210 "promela.ypp" + { + (yyval.node) = ctx->node(PML_MODULO, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 63: + /* Line 1787 of yacc.c */ +#line 213 "promela.ypp" + { + (yyval.node) = ctx->value(PML_NAME, (void*)&((yylsp[(1) - (1)])), (yyvsp[(1) - (1)].value)); + free((yyvsp[(1) - (1)].value)); + } + break; + + case 64: + /* Line 1787 of yacc.c */ +#line 214 "promela.ypp" + { + if ((yyvsp[(1) - (2)].node)->type == PML_NAME) { + (yyval.node) = ctx->node(PML_NAMELIST, 1, (yyvsp[(1) - (2)].node)); + (yyval.node)->push(ctx->value(PML_NAME, (void*)&((yylsp[(2) - (2)])), (yyvsp[(2) - (2)].value))); + } else { + (yyvsp[(1) - (2)].node)->push(ctx->value(PML_NAME, (void*)&((yylsp[(2) - (2)])), (yyvsp[(2) - (2)].value))); + } + free((yyvsp[(2) - (2)].value)); + } + break; + + case 65: + /* Line 1787 of yacc.c */ +#line 223 "promela.ypp" + { + (yyval.node) = (yyvsp[(1) - (2)].node); + } + break; + + case 66: + /* Line 1787 of yacc.c */ +#line 226 "promela.ypp" + { + (yyval.node) = (yyvsp[(1) - (1)].node); + } + break; + + case 67: + /* Line 1787 of yacc.c */ +#line 227 "promela.ypp" + { + (yyval.node) = (yyvsp[(1) - (2)].node); + } + break; + + case 68: + /* Line 1787 of yacc.c */ +#line 228 "promela.ypp" + { + (yyval.node) = ctx->node(PML_STMNT, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 69: + /* Line 1787 of yacc.c */ +#line 231 "promela.ypp" + { + (yyval.node) = (yyvsp[(1) - (1)].node); + } + break; + + case 70: + /* Line 1787 of yacc.c */ +#line 234 "promela.ypp" + { + (yyval.node) = ctx->node(PML_ASGN, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + case 71: + /* Line 1787 of yacc.c */ +#line 235 "promela.ypp" + { + (yyval.node) = ctx->node(PML_INCR, 1, (yyvsp[(1) - (2)].node)); + } + break; + + case 72: + /* Line 1787 of yacc.c */ +#line 236 "promela.ypp" + { + (yyval.node) = ctx->node(PML_DECR, 1, (yyvsp[(1) - (2)].node)); + } + break; + + case 73: + /* Line 1787 of yacc.c */ +#line 237 "promela.ypp" + { + (yyval.node) = ctx->node(PML_PRINT, 2, ctx->value(PML_STRING, (void*)&((yylsp[(3) - (5)])), (yyvsp[(3) - (5)].value)), (yyvsp[(4) - (5)].node)); + free((yyvsp[(3) - (5)].value)); + } + break; + + case 74: + /* Line 1787 of yacc.c */ +#line 238 "promela.ypp" + { + (yyval.node) = ctx->node(PML_PRINT, 1, (yyvsp[(3) - (4)].node)); + } + break; + + case 75: + /* Line 1787 of yacc.c */ +#line 239 "promela.ypp" + { + (yyval.node) = ctx->node(PML_PRINT, 1, ctx->value(PML_CONST, (void*)&((yylsp[(3) - (4)])), (yyvsp[(3) - (4)].value))); + free((yyvsp[(3) - (4)].value)); + } + break; + + case 76: + /* Line 1787 of yacc.c */ +#line 240 "promela.ypp" + { + (yyval.node) = ctx->node(PML_ASSERT, 1, (yyvsp[(2) - (2)].node)); + } + break; + + case 77: + /* Line 1787 of yacc.c */ +#line 241 "promela.ypp" + { + (yyval.node) = (yyvsp[(1) - (1)].node); + } + break; + + case 78: + /* Line 1787 of yacc.c */ +#line 244 "promela.ypp" + { + (yyval.node) = ctx->value(0, NULL, ""); + } + break; + + case 79: + /* Line 1787 of yacc.c */ +#line 245 "promela.ypp" + { + (yyval.node) = (yyvsp[(2) - (2)].node); + } + break; + + case 80: + /* Line 1787 of yacc.c */ +#line 248 "promela.ypp" + { + (yyval.node) = (yyvsp[(1) - (1)].node); + } + break; + + case 81: + /* Line 1787 of yacc.c */ +#line 249 "promela.ypp" + { + (yyval.node) = ctx->node(0, 2, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); + } + break; + + + /* Line 1787 of yacc.c */ +#line 2285 "promela.tab.cpp" + default: + break; + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + *++yylsp = yyloc; + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + + /*------------------------------------. + | yyerrlab -- here on detecting error | + `------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (&yylloc, ctx, scanner, YY_("syntax error")); +#else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) + { + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } else { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (&yylloc, ctx, scanner, yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; + } +# undef YYSYNTAX_ERROR +#endif + } + + yyerror_range[1] = yylloc; + + if (yyerrstatus == 3) { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } else { + yydestruct ("Error: discarding", + yytoken, &yylval, &yylloc, ctx, scanner); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + + /*---------------------------------------------------. + | yyerrorlab -- error raised explicitly by YYERROR. | + `---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + yyerror_range[1] = yylsp[1-yylen]; + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + + /*-------------------------------------------------------------. + | yyerrlab1 -- common code for both syntax error and YYERROR. | + `-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + yyerror_range[1] = *yylsp; + yydestruct ("Error: popping", + yystos[yystate], yyvsp, yylsp, ctx, scanner); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + yyerror_range[2] = yylloc; + /* Using YYLLOC is tempting, but would change the location of + the lookahead. YYLOC is available though. */ + YYLLOC_DEFAULT (yyloc, yyerror_range, 2); + *++yylsp = yyloc; + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + + /*-------------------------------------. + | yyacceptlab -- YYACCEPT comes here. | + `-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + + /*-----------------------------------. + | yyabortlab -- YYABORT comes here. | + `-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined yyoverflow || YYERROR_VERBOSE + /*-------------------------------------------------. + | yyexhaustedlab -- memory exhaustion comes here. | + `-------------------------------------------------*/ +yyexhaustedlab: + yyerror (&yylloc, ctx, scanner, YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, &yylloc, ctx, scanner); + } + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp, yylsp, ctx, scanner); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + +/* Line 2050 of yacc.c */ +#line 253 "promela.ypp" + + diff --git a/src/uscxml/plugins/datamodel/promela/parser/promela.tab.hpp b/src/uscxml/plugins/datamodel/promela/parser/promela.tab.hpp new file mode 100644 index 0000000..a48031a --- /dev/null +++ b/src/uscxml/plugins/datamodel/promela/parser/promela.tab.hpp @@ -0,0 +1,180 @@ +/* A Bison parser, made by GNU Bison 2.7.12-4996. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +#ifndef YY_PROMELA_PROMELA_TAB_HPP_INCLUDED +# define YY_PROMELA_PROMELA_TAB_HPP_INCLUDED +/* Enabling traces. */ +#ifndef PROMELA_DEBUG +# if defined YYDEBUG +# if YYDEBUG +# define PROMELA_DEBUG 1 +# else +# define PROMELA_DEBUG 0 +# endif +# else /* ! defined YYDEBUG */ +# define PROMELA_DEBUG 1 +# endif /* ! defined YYDEBUG */ +#endif /* ! defined PROMELA_DEBUG */ +#if PROMELA_DEBUG +extern int promela_debug; +#endif + +/* Tokens. */ +#ifndef PROMELA_TOKENTYPE +# define PROMELA_TOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum promela_tokentype { + PML_VAR_ARRAY = 258, + PML_VARLIST = 259, + PML_DECL = 260, + PML_DECLLIST = 261, + PML_STMNT = 262, + PML_COLON = 263, + PML_EXPR = 264, + PML_NAMELIST = 265, + PML_ASSERT = 266, + PML_PRINT = 267, + PML_PRINTM = 268, + PML_LEN = 269, + PML_STRING = 270, + PML_TYPEDEF = 271, + PML_MTYPE = 272, + PML_INLINE = 273, + PML_RETURN = 274, + PML_LABEL = 275, + PML_OF = 276, + PML_GOTO = 277, + PML_BREAK = 278, + PML_ELSE = 279, + PML_SEMI = 280, + PML_ARROW = 281, + PML_IF = 282, + PML_FI = 283, + PML_DO = 284, + PML_OD = 285, + PML_FOR = 286, + PML_SELECT = 287, + PML_IN = 288, + PML_SEP = 289, + PML_DOTDOT = 290, + PML_HIDDEN = 291, + PML_SHOW = 292, + PML_ISLOCAL = 293, + PML_CONST = 294, + PML_TYPE = 295, + PML_XU = 296, + PML_NAME = 297, + PML_UNAME = 298, + PML_PNAME = 299, + PML_INAME = 300, + PML_CLAIM = 301, + PML_TRACE = 302, + PML_INIT = 303, + PML_LTL = 304, + PML_COMMA = 305, + PML_ASGN = 306, + PML_AND = 307, + PML_OR = 308, + PML_BITAND = 309, + PML_BITXOR = 310, + PML_BITOR = 311, + PML_NE = 312, + PML_EQ = 313, + PML_LE = 314, + PML_GE = 315, + PML_LT = 316, + PML_GT = 317, + PML_RSHIFT = 318, + PML_LSHIFT = 319, + PML_MINUS = 320, + PML_PLUS = 321, + PML_MODULO = 322, + PML_DIVIDE = 323, + PML_TIMES = 324, + PML_DECR = 325, + PML_INCR = 326, + PML_COMPL = 327, + PML_NEG = 328, + PML_CMPND = 329, + PML_DOT = 330 + }; +#endif + + +#if ! defined PROMELA_STYPE && ! defined PROMELA_STYPE_IS_DECLARED +typedef union PROMELA_STYPE +{ +/* Line 2053 of yacc.c */ +#line 39 "promela.ypp" + + uscxml::PromelaParserNode* node; + char* value; + + +/* Line 2053 of yacc.c */ +#line 146 "promela.tab.hpp" +} PROMELA_STYPE; +# define PROMELA_STYPE_IS_TRIVIAL 1 +# define promela_stype PROMELA_STYPE /* obsolescent; will be withdrawn */ +# define PROMELA_STYPE_IS_DECLARED 1 +#endif + +#if ! defined PROMELA_LTYPE && ! defined PROMELA_LTYPE_IS_DECLARED +typedef struct PROMELA_LTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} PROMELA_LTYPE; +# define promela_ltype PROMELA_LTYPE /* obsolescent; will be withdrawn */ +# define PROMELA_LTYPE_IS_DECLARED 1 +# define PROMELA_LTYPE_IS_TRIVIAL 1 +#endif + + +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int promela_parse (void *YYPARSE_PARAM); +#else +int promela_parse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int promela_parse (uscxml::PromelaParser* ctx, void * scanner); +#else +int promela_parse (); +#endif +#endif /* ! YYPARSE_PARAM */ + +#endif /* !YY_PROMELA_PROMELA_TAB_HPP_INCLUDED */ diff --git a/src/uscxml/plugins/datamodel/promela/parser/promela.ypp b/src/uscxml/plugins/datamodel/promela/parser/promela.ypp new file mode 100644 index 0000000..d76b24a --- /dev/null +++ b/src/uscxml/plugins/datamodel/promela/parser/promela.ypp @@ -0,0 +1,254 @@ +/** Subset extracted from spin.y by Stefan Radomski 2014 */ + +/***** spin: spin.y *****/ + +/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */ +/* All Rights Reserved. This software is for educational purposes only. */ +/* No guarantee whatsoever is expressed or implied by the distribution of */ +/* this code. Permission is given to distribute this code provided that */ +/* this introductory message is not removed and no monies are exchanged. */ +/* Software written by Gerard J. Holzmann. For tool documentation see: */ +/* http://spinroot.com/ */ +/* Send all bug-reports and/or questions to: bugs@spinroot.com */ + +%{ +#include "../PromelaParser.h" +#include "promela.tab.hpp" +#include <sys/types.h> +#include <stdarg.h> + +#define YYMAXDEPTH 20000 // default is 10000 +#define YYDEBUG 1 +#define YYERROR_VERBOSE 1 + +extern int promela_lex (PROMELA_STYPE* yylval_param, PROMELA_LTYPE* yylloc_param, void* yyscanner); + +using namespace uscxml; +%} + +%pure-parser +%debug +%locations +%file-prefix "promela" +%parse-param { uscxml::PromelaParser* ctx } +%lex-param {void * scanner} +%parse-param {void * scanner} +%define api.prefix promela_ +%defines + +%union { + uscxml::PromelaParserNode* node; + char* value; +} + +%error-verbose + +/* %type <node> expr_lst */ +%type <node> expr pfld sfld varref decl_lst stmnt_lst vardcl ivar var_list one_decl prargs utype cmpnd +%type <node> stmnt Stmnt const_expr nlst vis arg + +%token PML_VAR_ARRAY PML_VARLIST PML_DECL PML_DECLLIST PML_STMNT PML_COLON PML_EXPR PML_NAMELIST + +%token '(' ')' +%token '[' ']' +%token '{' '}' +%token PML_ASSERT PML_PRINT PML_PRINTM +%token <value> PML_LEN PML_STRING +%token PML_TYPEDEF PML_MTYPE PML_INLINE PML_RETURN PML_LABEL PML_OF +%token PML_GOTO PML_BREAK PML_ELSE PML_SEMI PML_ARROW +%token PML_IF PML_FI PML_DO PML_OD PML_FOR PML_SELECT PML_IN PML_SEP PML_DOTDOT +%token PML_HIDDEN PML_SHOW PML_ISLOCAL +%token <value> PML_CONST PML_TYPE PML_XU /* val */ +%token <value> PML_NAME PML_UNAME PML_PNAME PML_INAME /* sym */ +%token PML_CLAIM PML_TRACE PML_INIT PML_LTL /* sym */ +%token PML_COMMA + +%right PML_ASGN +%left PML_OR PML_AND +%left PML_BITOR PML_BITXOR PML_BITAND +%left PML_EQ PML_NE +%left PML_GT PML_LT PML_GE PML_LE +%left PML_LSHIFT PML_RSHIFT +%left PML_PLUS PML_MINUS +%left PML_TIMES PML_DIVIDE PML_MODULO +%left PML_INCR PML_DECR +%left PML_COMPL +%right PML_NEG +%left PML_DOT PML_CMPND + +%% + + +/** PROMELA Grammar Rules **/ + +program : + decl_lst { + ctx->ast = $1; + ctx->type = PromelaParser::PROMELA_DECL; + } + | expr { + ctx->ast = $1; + ctx->type = PromelaParser::PROMELA_EXPR; + } + | stmnt_lst { + ctx->ast = $1; + ctx->type = PromelaParser::PROMELA_STMNT; + } + ; + +varref : cmpnd { $$ = $1; } + ; + +pfld : PML_NAME { $$ = ctx->value(PML_NAME, (void*)&(@1), $1); free($1); } + | PML_NAME '[' expr ']' { $$ = ctx->node(PML_VAR_ARRAY, 2, ctx->value(PML_NAME, (void*)&(@1), $1), $3); free($1); } + ; + +cmpnd : pfld + sfld { + if ($2 != NULL) { + if ($2->type == PML_CMPND) { + $$ = ctx->node(PML_CMPND, 1, $1); + $$->merge($2); delete $2; + } else { + $$ = ctx->node(PML_CMPND, 2, $1, $2); + } + } else { + $$ = $1; + } + } + ; + +sfld : /* empty */ { $$ = NULL; } + | PML_DOT cmpnd %prec PML_DOT { $$ = $2; } + ; + +/* +expr_lst: expr { $$ = ctx->node(PML_EXPR, 1, $1); } + | expr PML_SEMI { $$ = ctx->node(PML_EXPR, 1, $1); } + | expr PML_SEMI expr_lst { $$ = ctx->node(PML_EXPR, 2, $1, $3); } + ; +*/ + +expr : '(' expr ')' { $$ = $2; } + | expr PML_PLUS expr { $$ = ctx->node(PML_PLUS, 2, $1, $3); } + | expr PML_MINUS expr { $$ = ctx->node(PML_MINUS, 2, $1, $3); } + | expr PML_TIMES expr { $$ = ctx->node(PML_TIMES, 2, $1, $3); } + | expr PML_DIVIDE expr { $$ = ctx->node(PML_DIVIDE, 2, $1, $3); } + | expr PML_MODULO expr { $$ = ctx->node(PML_MODULO, 2, $1, $3); } + | expr PML_BITAND expr { $$ = ctx->node(PML_BITAND, 2, $1, $3); } + | expr PML_BITXOR expr { $$ = ctx->node(PML_BITXOR, 2, $1, $3); } + | expr PML_BITOR expr { $$ = ctx->node(PML_BITOR, 2, $1, $3); } + | expr PML_GT expr { $$ = ctx->node(PML_GT, 2, $1, $3); } + | expr PML_LT expr { $$ = ctx->node(PML_LT, 2, $1, $3); } + | expr PML_GE expr { $$ = ctx->node(PML_GE, 2, $1, $3); } + | expr PML_LE expr { $$ = ctx->node(PML_LE, 2, $1, $3); } + | expr PML_EQ expr { $$ = ctx->node(PML_EQ, 2, $1, $3); } + | expr PML_NE expr { $$ = ctx->node(PML_NE, 2, $1, $3); } + | expr PML_AND expr { $$ = ctx->node(PML_AND, 2, $1, $3); } + | expr PML_OR expr { $$ = ctx->node(PML_OR, 2, $1, $3); } + | expr PML_LSHIFT expr { $$ = ctx->node(PML_LSHIFT, 2, $1, $3); } + | expr PML_RSHIFT expr { $$ = ctx->node(PML_RSHIFT, 2, $1, $3); } + | PML_NEG expr { $$ = ctx->node(PML_NEG, 1, $2); } + | PML_MINUS expr %prec PML_MINUS { $$ = ctx->node(PML_MINUS, 1, $2); } + + | PML_LEN '(' varref ')' { $$ = ctx->node(PML_LEN, 1, $3); } + | varref { $$ = $1; } + | PML_CONST { $$ = ctx->value(PML_CONST, (void*)&(@1), $1); free($1); } + | PML_STRING { + /* Non standard promela for string literals */ + $$ = ctx->value(PML_STRING, (void*)&(@1), $1); free($1); } + ; + + +vis : /* empty */ { $$ = ctx->node(PML_SHOW, 0); } + | PML_HIDDEN { $$ = ctx->node(PML_HIDDEN, 0); } + | PML_SHOW { $$ = ctx->node(PML_SHOW, 0); } + | PML_ISLOCAL { $$ = ctx->node(PML_ISLOCAL, 0); } + ; + +one_decl: vis PML_TYPE var_list { $$ = ctx->node(PML_DECL, 3, $1, ctx->value(PML_TYPE, (void*)&(@2), $2), $3); free($2); } + | vis PML_UNAME var_list { $$ = ctx->node(PML_UNAME, 2, $1, $3); } + | vis PML_TYPE PML_ASGN '{' nlst '}' { $$ = ctx->node(PML_DECL, 3, $1, ctx->value(PML_TYPE, (void*)&(@2), $2), $5); free($2); } + | vis utype { $$ = $2; } + ; + +utype : PML_TYPEDEF PML_NAME '{' decl_lst '}' { $$ = ctx->node(PML_TYPEDEF, 2, ctx->value(PML_NAME, (void*)&(@2), $2), $4); } + ; + +decl_lst: one_decl { $$ = $1; } + | one_decl PML_SEMI { $$ = $1; } + | one_decl PML_SEMI decl_lst { + $$ = ctx->node(PML_DECLLIST, 1, $1); + if($3->type == PML_DECLLIST) { + $$->merge($3); delete $3; + } else { + $$->push($3); + } + } + ; + +var_list: ivar { $$ = ctx->node(PML_VARLIST, 1, $1); } + | ivar PML_COMMA var_list { $$ = ctx->node(PML_VARLIST, 1, $1); $$->merge($3); delete $3; } + ; + +ivar : vardcl { $$ = $1; } + | vardcl PML_ASGN expr { $$ = ctx->node(PML_ASGN, 2, $1, $3); } + ; + +vardcl : PML_NAME { $$ = ctx->value(PML_NAME, (void*)&(@1), $1); free($1); } + | PML_NAME PML_COLON PML_CONST { $$ = ctx->node(PML_COLON, 2, ctx->value(PML_NAME, (void*)&(@1), $1), ctx->value(PML_CONST, (void*)&(@3), $3)); free($1); free($3); } + | PML_NAME '[' const_expr ']' { $$ = ctx->node(PML_VAR_ARRAY, 2, ctx->value(PML_NAME, (void*)&(@1), $1), $3); free($1); } + ; + +const_expr: PML_CONST { $$ = ctx->value(PML_CONST, (void*)&(@1), $1); free($1); } + | PML_MINUS const_expr %prec PML_MINUS { $$ = ctx->node(PML_MINUS, 1, $2); } + | '(' const_expr ')' { $$ = $2; } + | const_expr PML_PLUS const_expr { $$ = ctx->node(PML_PLUS, 2, $1, $3); } + | const_expr PML_MINUS const_expr { $$ = ctx->node(PML_MINUS, 2, $1, $3); } + | const_expr PML_TIMES const_expr { $$ = ctx->node(PML_TIMES, 2, $1, $3); } + | const_expr PML_DIVIDE const_expr { $$ = ctx->node(PML_DIVIDE, 2, $1, $3); } + | const_expr PML_MODULO const_expr { $$ = ctx->node(PML_MODULO, 2, $1, $3); } + ; + +nlst : PML_NAME { $$ = ctx->value(PML_NAME, (void*)&(@1), $1); free($1); } + | nlst PML_NAME { + if ($1->type == PML_NAME) { + $$ = ctx->node(PML_NAMELIST, 1, $1); + $$->push(ctx->value(PML_NAME, (void*)&(@2), $2)); + } else { + $1->push(ctx->value(PML_NAME, (void*)&(@2), $2)); + } + free($2); + } + | nlst PML_COMMA { $$ = $1; } + ; + +stmnt_lst: stmnt { $$ = $1; } + | stmnt PML_SEMI { $$ = $1; } + | stmnt PML_SEMI stmnt_lst { $$ = ctx->node(PML_STMNT, 2, $1, $3); } + ; + +stmnt : Stmnt { $$ = $1; } + ; + +Stmnt : varref PML_ASGN expr { $$ = ctx->node(PML_ASGN, 2, $1, $3); } + | varref PML_INCR { $$ = ctx->node(PML_INCR, 1, $1); } + | varref PML_DECR { $$ = ctx->node(PML_DECR, 1, $1); } + | PML_PRINT '(' PML_STRING prargs ')' { $$ = ctx->node(PML_PRINT, 2, ctx->value(PML_STRING, (void*)&(@3), $3), $4); free($3); } + | PML_PRINT '(' varref ')' { $$ = ctx->node(PML_PRINT, 1, $3); } + | PML_PRINT '(' PML_CONST ')' { $$ = ctx->node(PML_PRINT, 1, ctx->value(PML_CONST, (void*)&(@3), $3)); free($3); } + | PML_ASSERT expr { $$ = ctx->node(PML_ASSERT, 1, $2); } + | expr { $$ = $1; } + ; + +prargs : /* empty */ { $$ = ctx->value(0, NULL, ""); } + | PML_COMMA arg { $$ = $2; } + ; + +arg : expr { $$ = $1; } + | expr PML_COMMA arg { $$ = ctx->node(0, 2, $1, $3); } + ; + + +%% + diff --git a/src/uscxml/plugins/invoker/dirmon/DirMonInvoker.cpp b/src/uscxml/plugins/invoker/dirmon/DirMonInvoker.cpp index f3b429f..08a0be8 100644 --- a/src/uscxml/plugins/invoker/dirmon/DirMonInvoker.cpp +++ b/src/uscxml/plugins/invoker/dirmon/DirMonInvoker.cpp @@ -134,8 +134,8 @@ void DirMonInvoker::invoke(const std::string& source, const Event& req) { std::multimap<std::string, Data>::const_iterator dirIter = req.params.find("dir"); while(dirIter != req.params.upper_bound("dir")) { // this is simplified - Data might be more elaborate than a simple string atom - URL url = URL::resolve(dirIter->second.atom, _interpreter->getBaseURL()); - + URL url = URL::resolve(dirIter->second.atom, _interpreter->getBaseURL()); + if (!url.isAbsolute()) { LOG(ERROR) << "Given directory '" << dirIter->second << "' cannot be transformed to absolute path"; } else { @@ -153,13 +153,13 @@ void DirMonInvoker::invoke(const std::string& source, const Event& req) { } void DirMonInvoker::uninvoke() { - _isRunning = false; - if (_thread) { - _thread->join(); - delete _thread; - } + _isRunning = false; + if (_thread) { + _thread->join(); + delete _thread; + } } - + void DirMonInvoker::run(void* instance) { while(((DirMonInvoker*)instance)->_isRunning) { { diff --git a/src/uscxml/plugins/invoker/dirmon/DirMonInvoker.h b/src/uscxml/plugins/invoker/dirmon/DirMonInvoker.h index be510d9..6e13864 100644 --- a/src/uscxml/plugins/invoker/dirmon/DirMonInvoker.h +++ b/src/uscxml/plugins/invoker/dirmon/DirMonInvoker.h @@ -107,9 +107,9 @@ public: } virtual Data getDataModelVariables(); - virtual void eventFromSCXML(const Event& event); - virtual void invoke(const std::string& source, const Event& invokeEvent); - virtual void uninvoke(); + virtual void eventFromSCXML(const Event& event); + virtual void invoke(const std::string& source, const Event& invokeEvent); + virtual void uninvoke(); virtual void handleChanges(DirectoryWatch::Action action, const std::string dir, const std::string file, struct stat fileStat); diff --git a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp index 317b94c..564977d 100644 --- a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp +++ b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp @@ -200,8 +200,8 @@ void BasicHTTPIOProcessor::eventFromSCXML(const std::string& target, const Event kvps << kvpSeperator << eventNameCStr << "=" << eventValueCStr; kvpSeperator = "&"; targetURL.addOutHeader("_scxmleventname", eventValueCStr); - free(eventNameCStr); - free(eventValueCStr); + free(eventNameCStr); + free(eventValueCStr); } // event namelist diff --git a/src/uscxml/server/HTTPServer.cpp b/src/uscxml/server/HTTPServer.cpp index 071846c..679ab67 100644 --- a/src/uscxml/server/HTTPServer.cpp +++ b/src/uscxml/server/HTTPServer.cpp @@ -386,14 +386,14 @@ void HTTPServer::httpRecvReqCallback(struct evhttp_request *req, void *callbackD key = item.substr(0, equalPos); value = item.substr(equalPos + 1, item.length() - (equalPos + 1)); - size_t keyCStrLen = 0; - size_t valueCStrLen = 0; - char* keyCStr = evhttp_uridecode(key.c_str(), 1, &keyCStrLen); + size_t keyCStrLen = 0; + size_t valueCStrLen = 0; + char* keyCStr = evhttp_uridecode(key.c_str(), 1, &keyCStrLen); char* valueCStr = evhttp_uridecode(value.c_str(), 1, &valueCStrLen); - std::string decKey = std::string(keyCStr, keyCStrLen); - std::string decValue = std::string(valueCStr, valueCStrLen); - - request.data.compound["content"].compound[decKey] = Data(decValue, Data::VERBATIM); + std::string decKey = std::string(keyCStr, keyCStrLen); + std::string decValue = std::string(valueCStr, valueCStrLen); + + request.data.compound["content"].compound[decKey] = Data(decValue, Data::VERBATIM); free(keyCStr); free(valueCStr); key.clear(); @@ -418,11 +418,11 @@ void HTTPServer::httpRecvReqCallback(struct evhttp_request *req, void *callbackD request.raw = raw.str(); #if 0 - std::cout << "====" << std::endl; - std::cout << request.raw << std::endl; - std::cout << "====" << std::endl; + std::cout << "====" << std::endl; + std::cout << request.raw << std::endl; + std::cout << "====" << std::endl; #endif - + // try with the handler registered for path first bool answered = false; if (callbackData != NULL) diff --git a/src/uscxml/transform/ChartToC.cpp b/src/uscxml/transform/ChartToC.cpp index 04f0378..10eee0c 100644 --- a/src/uscxml/transform/ChartToC.cpp +++ b/src/uscxml/transform/ChartToC.cpp @@ -50,7 +50,7 @@ ChartToC::ChartToC(const Interpreter& other) : TransformerImpl(other), _topMostM ss << _document; _md5 = md5(ss.str()); - _prefix = "_uscxml_" + _md5.substr(0, 8); + _prefix = "_uscxml_" + _md5.substr(0, 8) + "_"; _allMachines.push_back(this); prepare(); @@ -1189,7 +1189,7 @@ void ChartToC::writeExecContent(std::ostream& stream) { } -void ChartToC::writeExecContent(std::ostream& stream, const DOMNode* node, int indent) { +void ChartToC::writeExecContent(std::ostream& stream, const DOMNode* node, size_t indent) { if (!node) return; @@ -2560,4 +2560,4 @@ void ChartToC::writeFSM(std::ostream& stream) { ChartToC::~ChartToC() { } -}
\ No newline at end of file +} diff --git a/src/uscxml/transform/ChartToC.h b/src/uscxml/transform/ChartToC.h index 43ffc45..9fe6a9f 100644 --- a/src/uscxml/transform/ChartToC.h +++ b/src/uscxml/transform/ChartToC.h @@ -58,7 +58,7 @@ protected: void writeFSM(std::ostream& stream); void writeCharArrayInitList(std::ostream& stream, const std::string& boolString); - void writeExecContent(std::ostream& stream, const XERCESC_NS::DOMNode* node, int indent = 0); + void writeExecContent(std::ostream& stream, const XERCESC_NS::DOMNode* node, size_t indent = 0); void resortStates(XERCESC_NS::DOMNode* node); void setHistoryCompletion(); diff --git a/src/uscxml/transform/ChartToPromela.cpp b/src/uscxml/transform/ChartToPromela.cpp new file mode 100644 index 0000000..a697d99 --- /dev/null +++ b/src/uscxml/transform/ChartToPromela.cpp @@ -0,0 +1,2625 @@ +/** + * @file + * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see <http://www.opensource.org/licenses/bsd-license>. + * @endcond + */ + +#include "uscxml/transform/ChartToPromela.h" +#include "uscxml/util/Predicates.h" +#include "uscxml/util/String.h" +#include "uscxml/plugins/datamodel/promela/PromelaParser.h" +#include "uscxml/plugins/datamodel/promela/parser/promela.tab.hpp" + +#include <boost/algorithm/string.hpp> +#include <easylogging++.h> + +#include <algorithm> + +#define ADAPT_SRC(code) _analyzer.adaptCode(code, _prefix) +#define BIT_WIDTH(number) (number > 1 ? (int)ceil(log((double)number) / log((double)2.0)) : 1) +#define EVENT_NAME (_analyzer.usesComplexEventStruct() ? "_event.name" : "_event") + +namespace uscxml { + +using namespace XERCESC_NS; + + +Transformer ChartToPromela::transform(const Interpreter& other) { + return std::shared_ptr<TransformerImpl>(new ChartToPromela(other)); +} + +ChartToPromela::~ChartToPromela() { +} + +/** + The following tests FAILED: + 1740 - w3c/spin/promela/test150.scxml (Failed) + 1741 - w3c/spin/promela/test151.scxml (Failed) + 1742 - w3c/spin/promela/test152.scxml (Failed) + 1743 - w3c/spin/promela/test153.scxml (Failed) + 1744 - w3c/spin/promela/test155.scxml (Failed) + 1745 - w3c/spin/promela/test156.scxml (Failed) + 1749 - w3c/spin/promela/test173.scxml (Failed) + 1750 - w3c/spin/promela/test174.scxml (Failed) + 1752 - w3c/spin/promela/test176.scxml (Failed) + 1753 - w3c/spin/promela/test178.scxml (Failed) + 1754 - w3c/spin/promela/test179.scxml (Failed) + 1757 - w3c/spin/promela/test186.scxml (Failed) + 1762 - w3c/spin/promela/test192.scxml (Failed) + 1763 - w3c/spin/promela/test193.scxml (Failed) + 1765 - w3c/spin/promela/test198.scxml (Failed) + 1769 - w3c/spin/promela/test205.scxml (Failed) + 1770 - w3c/spin/promela/test207.scxml (Failed) + 1771 - w3c/spin/promela/test208.scxml (Failed) + 1772 - w3c/spin/promela/test210.scxml (Failed) + 1773 - w3c/spin/promela/test215.scxml (Failed) + 1774 - w3c/spin/promela/test216.scxml (Failed) + 1776 - w3c/spin/promela/test223.scxml (Failed) + 1777 - w3c/spin/promela/test224.scxml (Failed) + 1778 - w3c/spin/promela/test225.scxml (Failed) + 1780 - w3c/spin/promela/test228.scxml (Failed) + 1782 - w3c/spin/promela/test230.scxml (Failed) + 1783 - w3c/spin/promela/test232.scxml (Failed) + 1785 - w3c/spin/promela/test234.scxml (Failed) + 1787 - w3c/spin/promela/test236.scxml (Failed) + 1788 - w3c/spin/promela/test237.scxml (Failed) + 1789 - w3c/spin/promela/test239.scxml (Failed) + 1790 - w3c/spin/promela/test240.scxml (Failed) + 1791 - w3c/spin/promela/test241.scxml (Failed) + 1792 - w3c/spin/promela/test242.scxml (Failed) + 1797 - w3c/spin/promela/test250.scxml (Failed) + 1798 - w3c/spin/promela/test252.scxml (Failed) + 1799 - w3c/spin/promela/test253.scxml (Failed) + 1802 - w3c/spin/promela/test278.scxml (Failed) + 1803 - w3c/spin/promela/test279.scxml (Failed) + 1805 - w3c/spin/promela/test286.scxml (Failed) + 1808 - w3c/spin/promela/test294.scxml (Failed) + 1809 - w3c/spin/promela/test298.scxml (Failed) + 1811 - w3c/spin/promela/test302.scxml (Failed) + 1813 - w3c/spin/promela/test304.scxml (Failed) + 1814 - w3c/spin/promela/test309.scxml (Failed) + 1815 - w3c/spin/promela/test310.scxml (Failed) + 1816 - w3c/spin/promela/test311.scxml (Failed) + 1817 - w3c/spin/promela/test312.scxml (Failed) + 1818 - w3c/spin/promela/test313.scxml (Failed) + 1819 - w3c/spin/promela/test314.scxml (Failed) + 1820 - w3c/spin/promela/test318.scxml (Failed) + 1823 - w3c/spin/promela/test322.scxml (Failed) + 1825 - w3c/spin/promela/test324.scxml (Failed) + 1827 - w3c/spin/promela/test326.scxml (Failed) + 1828 - w3c/spin/promela/test329.scxml (Failed) + 1829 - w3c/spin/promela/test330.scxml (Failed) + 1830 - w3c/spin/promela/test331.scxml (Failed) + 1831 - w3c/spin/promela/test332.scxml (Failed) + 1832 - w3c/spin/promela/test333.scxml (Failed) + 1833 - w3c/spin/promela/test335.scxml (Failed) + 1835 - w3c/spin/promela/test337.scxml (Failed) + 1837 - w3c/spin/promela/test339.scxml (Failed) + 1838 - w3c/spin/promela/test342.scxml (Failed) + 1839 - w3c/spin/promela/test343.scxml (Failed) + 1840 - w3c/spin/promela/test344.scxml (Failed) + 1841 - w3c/spin/promela/test346.scxml (Failed) + 1842 - w3c/spin/promela/test347.scxml (Failed) + 1846 - w3c/spin/promela/test351.scxml (Failed) + 1847 - w3c/spin/promela/test352.scxml (Failed) + 1848 - w3c/spin/promela/test354.scxml (Failed) + 1849 - w3c/spin/promela/test355.scxml (Failed) + 1850 - w3c/spin/promela/test364.scxml (Failed) + 1851 - w3c/spin/promela/test372.scxml (Failed) + 1854 - w3c/spin/promela/test377.scxml (Failed) + 1855 - w3c/spin/promela/test378.scxml (Failed) + 1856 - w3c/spin/promela/test387.scxml (Failed) + 1857 - w3c/spin/promela/test388.scxml (Failed) + 1858 - w3c/spin/promela/test396.scxml (Failed) + 1859 - w3c/spin/promela/test399.scxml (Failed) + 1860 - w3c/spin/promela/test401.scxml (Failed) + 1861 - w3c/spin/promela/test402.scxml (Failed) + 1862 - w3c/spin/promela/test403a.scxml (Failed) + 1863 - w3c/spin/promela/test403b.scxml (Failed) + 1864 - w3c/spin/promela/test403c.scxml (Failed) + 1865 - w3c/spin/promela/test404.scxml (Failed) + 1866 - w3c/spin/promela/test405.scxml (Failed) + 1867 - w3c/spin/promela/test406.scxml (Failed) + 1868 - w3c/spin/promela/test407.scxml (Failed) + 1869 - w3c/spin/promela/test409.scxml (Failed) + 1870 - w3c/spin/promela/test411.scxml (Failed) + 1871 - w3c/spin/promela/test412.scxml (Failed) + 1872 - w3c/spin/promela/test413.scxml (Failed) + 1873 - w3c/spin/promela/test415.scxml (Failed) + 1874 - w3c/spin/promela/test416.scxml (Failed) + 1875 - w3c/spin/promela/test417.scxml (Failed) + 1877 - w3c/spin/promela/test421.scxml (Failed) + 1878 - w3c/spin/promela/test422.scxml (Failed) + 1880 - w3c/spin/promela/test487.scxml (Failed) + 1881 - w3c/spin/promela/test488.scxml (Failed) + 1882 - w3c/spin/promela/test495.scxml (Failed) + 1886 - w3c/spin/promela/test503.scxml (Failed) + 1887 - w3c/spin/promela/test504.scxml (Failed) + 1888 - w3c/spin/promela/test505.scxml (Failed) + 1890 - w3c/spin/promela/test509.scxml (Failed) + 1892 - w3c/spin/promela/test518.scxml (Failed) + 1893 - w3c/spin/promela/test519.scxml (Failed) + 1894 - w3c/spin/promela/test520.scxml (Failed) + 1897 - w3c/spin/promela/test525.scxml (Failed) + 1898 - w3c/spin/promela/test527.scxml (Failed) + 1899 - w3c/spin/promela/test528.scxml (Failed) + 1900 - w3c/spin/promela/test529.scxml (Failed) + 1901 - w3c/spin/promela/test530.scxml (Failed) + 1902 - w3c/spin/promela/test531.scxml (Failed) + 1903 - w3c/spin/promela/test532.scxml (Failed) + 1904 - w3c/spin/promela/test533.scxml (Failed) + 1905 - w3c/spin/promela/test534.scxml (Failed) + 1906 - w3c/spin/promela/test550.scxml (Failed) + 1907 - w3c/spin/promela/test551.scxml (Failed) + 1911 - w3c/spin/promela/test567.scxml (Failed) + 1912 - w3c/spin/promela/test570.scxml (Failed) + 1913 - w3c/spin/promela/test576.scxml (Failed) + 1915 - w3c/spin/promela/test579.scxml (Failed) + 1916 - w3c/spin/promela/test580.scxml (Failed) +*/ + +void ChartToPromela::prepare() { + if (_machinesAll == NULL) { + _machinesAll = new std::map<DOMNode*, ChartToPromela*>(); + (*_machinesAll)[_scxml] = this; + } + + if (_machinesAllPerId == NULL) + _machinesAllPerId = new std::map<std::string, XERCESC_NS::DOMNode* >(); + + if (_parentTopMost == NULL) + _parentTopMost = this; + + // transform data / assign json into PROMELA statements + std::list<DOMElement*> values; + + values.splice(values.end(), DOMUtils::inDocumentOrder({XML_PREFIX(_scxml).str() + "assign"}, _scxml)); + values.splice(values.end(), DOMUtils::inDocumentOrder({XML_PREFIX(_scxml).str() + "data"}, _scxml)); + + for (auto element : values) { + std::string key; + if (HAS_ATTR(element, "id")) { + key = ATTR(element, "id"); + } else if (HAS_ATTR(element, "location")) { + key = ATTR(element, "location"); + } + + if (key.length() == 0) + continue; + + std::string value; + if (HAS_ATTR(element, "expr")) { + value = ATTR(element, "expr"); + } else if (HAS_ATTR(element, "src")) { + URL absUrl = URL::resolve(ATTR_CAST(element, "src"), _baseURL); + value = absUrl.getInContent(); + } else { + std::list<DOMNode*> assignTexts = DOMUtils::filterChildType(DOMNode::TEXT_NODE, element, true); + if (assignTexts.size() > 0) { + for (auto assignText : assignTexts) { + value += X(assignText->getNodeValue()).str(); + } + } + } + + boost::trim(value); + if (value.size() == 0) + continue; + + // remove all children, we will replae by suitable promela statements + while(element->hasChildNodes()) + element->removeChild(element->getFirstChild()); + + std::string newValue; + Data json = Data::fromJSON(value); + if (!json.empty()) { + newValue = dataToAssignments(key, json); + } else { + newValue = key + " = " + value + ";"; + } + + if (LOCALNAME(element) == "data") + _varInitializers.push_back(newValue); + + DOMText* newText = _document->createTextNode(X(newValue)); + element->insertBefore(newText, NULL); + + _analyzer.addCode(newValue, this); + + } +} + +void ChartToPromela::writeTo(std::ostream& stream) { + + _analyzer.analyze(this); + // same preparations as the C transformation + prepare(); + + stream << "/** generated from " << std::endl; + stream << " " << std::string(_baseURL) << std::endl; + stream << " Use as:" << std::endl; + stream << " $ spin -a this.pml" << std::endl; + stream << " $ gcc pan.c -o pan" << std::endl; + stream << " $ ./pan -a -n -N w3c" << std::endl; + stream << " */" << std::endl; + stream << std::endl; + + + writeMacros(stream); + stream << std::endl; + writeTypeDefs(stream); + stream << std::endl; + writeTypes(stream); + stream << std::endl; + writeStrings(stream); + stream << std::endl; + writeCancelEvents(stream); + stream << std::endl; + writeFSM(stream); + stream << std::endl; + + + stream << "init {" << std::endl; + + stream << "/* initialize state and transition information */" << std::endl; + writeTransitions(stream); + stream << std::endl; + writeStates(stream); + stream << std::endl; + + stream << "/* initialize data model variables */" << std::endl; + stream << " " << _prefix << "flags[USCXML_CTX_PRISTINE] = true;" << std::endl; + stream << " " << _prefix << "flags[USCXML_CTX_SPONTANEOUS] = true;" << std::endl; + + for (auto initializer : _varInitializers) { + stream << ADAPT_SRC(beautifyIndentation(initializer, 1)) << std::endl; + } + + stream << std::endl; + + stream << " run " << _prefix << "step() priority 10;" << std::endl; + stream << "}" << std::endl; + stream << std::endl; + stream << "ltl w3c { eventually (" << _prefix << "config[" << _prefix << "PASS]) }" << std::endl; + +} + +void ChartToPromela::bit_clear_all(std::ostream& stream, + const std::string& identifier, + size_t length, + size_t indent) { + std::string padding; + while (indent--) + padding += " "; + stream << std::endl; + stream << padding << "/** clearing all bits of " << identifier << " */" << std::endl; + for (size_t i = 0; i < length; i++) { + stream << padding << identifier << "[" << i << "] = false;" << std::endl; + } +} + +void ChartToPromela::bit_copy(std::ostream& stream, + const std::string& from, + const std::string& to, + size_t length, + size_t indent) { + std::string padding; + while (indent--) + padding += " "; + stream << std::endl; + stream << padding << "/** copy bits from " << from << " to " << to << " */" << std::endl; + for (size_t i = 0; i < length; i++) { + stream << padding << to << "[" << i << "] = "<< from << "[" << i << "];" << std::endl; + } +} + +void ChartToPromela::bit_or(std::ostream& stream, + const std::string& to, + const std::string& mask, + size_t length, + size_t indent) { + std::string padding; + while (indent--) + padding += " "; + stream << std::endl; + stream << padding << "/** or'ing bits in " << to << " with mask " << mask << " */" << std::endl; + for (size_t i = 0; i < length; i++) { + stream << padding << to << "[" << i << "] = "<< to << "[" << i << "] | " << mask << "[" << i << "];" << std::endl; + } +} + +void ChartToPromela::bit_and(std::ostream& stream, + const std::string& to, + const std::string& mask, + size_t length, + size_t indent) { + std::string padding; + while (indent--) + padding += " "; + stream << std::endl; + stream << padding << "/** and'ing bits in " << to << " with mask " << mask << " */" << std::endl; + for (size_t i = 0; i < length; i++) { + stream << padding << to << "[" << i << "] = "<< to << "[" << i << "] & " << mask << "[" << i << "];" << std::endl; + } +} + +void ChartToPromela::bit_and_not(std::ostream& stream, + const std::string& to, + const std::string& mask, + size_t length, + size_t indent) { + std::string padding; + while (indent--) + padding += " "; + stream << std::endl; + stream << padding << "/** not and'ing bits in " << to << " with mask " << mask << " */" << std::endl; + for (size_t i = 0; i < length; i++) { + stream << padding << to << "[" << i << "] = "<< to << "[" << i << "] & !" << mask << "[" << i << "];" << std::endl; + } +} + +void ChartToPromela::bit_has_and(std::ostream& stream, + const std::string& a, + const std::string& b, + size_t length, + size_t indent) { + std::string padding; + while (indent--) + padding += " "; + stream << "(false /** is there a common bit in " << a << " and " << b << " */" << std::endl; + for (size_t i = 0; i < length; i++) { + stream << padding << " || " << a << "[" << i << "] & "<< b << "[" << i << "]" << std::endl; + } + stream << padding << ")"; + +} + +void ChartToPromela::printBitArray(std::ostream& stream, + const std::string& array, + size_t length, + size_t indent) { + std::string padding; + while (indent--) + padding += " "; + + stream << padding << "printf(\""; + for (size_t i = 0; i < length; i++) { + stream << "%d"; + } + stream << "\", " << std::endl; + for (size_t i = 0; i < length; i++) { + stream << padding << " " << array << "[" << toStr(i) << "]"; + if (i + 1 < length) { + stream << ", " << std::endl; + } + } + stream << ");" << std::endl; +} + +void ChartToPromela::writeMacros(std::ostream& stream) { + stream << "/* machine state flags */" << std::endl; + stream << "#define USCXML_CTX_PRISTINE 0" << std::endl; + stream << "#define USCXML_CTX_SPONTANEOUS 1" << std::endl; + stream << "#define USCXML_CTX_INITIALIZED 2" << std::endl; + stream << "#define USCXML_CTX_TOP_LEVEL_FINAL 3" << std::endl; + stream << "#define USCXML_CTX_TRANSITION_FOUND 4" << std::endl; + stream << "#define USCXML_CTX_FINISHED 5" << std::endl; + stream << std::endl; + + stream << "#define USCXML_TRANS_SPONTANEOUS 0" << std::endl; + stream << "#define USCXML_TRANS_TARGETLESS 1" << std::endl; + stream << "#define USCXML_TRANS_INTERNAL 2" << std::endl; + stream << "#define USCXML_TRANS_HISTORY 3" << std::endl; + stream << "#define USCXML_TRANS_INITIAL 4" << std::endl; + stream << std::endl; + + stream << "#define USCXML_STATE_ATOMIC 0" << std::endl; + stream << "#define USCXML_STATE_PARALLEL 1" << std::endl; + stream << "#define USCXML_STATE_COMPOUND 2" << std::endl; + stream << "#define USCXML_STATE_FINAL 3" << std::endl; + stream << "#define USCXML_STATE_HISTORY_DEEP 4" << std::endl; + stream << "#define USCXML_STATE_HISTORY_SHALLOW 5" << std::endl; + stream << "#define USCXML_STATE_INITIAL 6" << std::endl; + stream << "#define USCXML_STATE_HAS_HISTORY 7" << std::endl; + stream << std::endl; + + stream << "#define USCXML_ERR_OK 0" << std::endl; + stream << "#define USCXML_ERR_DONE 1" << std::endl; + stream << std::endl; + + stream << "#define USCXML_EVENT_SPONTANEOUS 0" << std::endl; + stream << std::endl; + stream << "#define TRACE_EXECUTION 1" << std::endl; + stream << std::endl; + + +} + +void ChartToPromela::writeTypeDefs(std::ostream& stream) { + stream << "/* type definitions */" << std::endl; + PromelaCodeAnalyzer::PromelaTypedef typeDefs = _analyzer.getTypes(); + if (typeDefs.types.size() == 0) + return; + + std::list<PromelaCodeAnalyzer::PromelaTypedef> individualDefs; + std::list<PromelaCodeAnalyzer::PromelaTypedef> currDefs; + currDefs.push_back(typeDefs); + + while(currDefs.size() > 0) { + if (std::find(individualDefs.begin(), individualDefs.end(), currDefs.front()) == individualDefs.end()) { + individualDefs.push_back(currDefs.front()); + for (std::map<std::string, PromelaCodeAnalyzer::PromelaTypedef>::iterator typeIter = currDefs.front().types.begin(); typeIter != currDefs.front().types.end(); typeIter++) { + currDefs.push_back(typeIter->second); + } + } + currDefs.pop_front(); + } + individualDefs.pop_front(); + + for (std::list<PromelaCodeAnalyzer::PromelaTypedef>::reverse_iterator rIter = individualDefs.rbegin(); rIter != individualDefs.rend(); rIter++) { + PromelaCodeAnalyzer::PromelaTypedef currDef = *rIter; + + if (currDef.types.size() == 0 || currDef.name.size() == 0) + continue; + + stream << "typedef " << currDef.name << " {" << std::endl; + if (currDef.name.compare("_event_t") ==0) { + if (_analyzer.usesEventField("delay")) { + // make sure delay is the first member for sorted enqueuing to work + stream << " int delay;" << std::endl; +#if NEW_DELAY_RESHUFFLE +#else + stream << " int seqNr;" << std::endl; +#endif + } + stream << " int name;" << std::endl; + if (_analyzer.usesEventField("invokeid")) { + stream << " int invokeid;" << std::endl; + } + } + for (std::map<std::string, PromelaCodeAnalyzer::PromelaTypedef>::iterator tIter = currDef.types.begin(); tIter != currDef.types.end(); tIter++) { + if (currDef.name.compare("_event_t") == 0 && (tIter->first.compare("name") == 0 || + tIter->first.compare("seqNr") == 0 || + tIter->first.compare("invokeid") == 0 || + tIter->first.compare("delay") == 0)) { // special treatment for _event + continue; + } + if (tIter->second.types.size() == 0) { + stream << " " << declForRange(tIter->first, tIter->second.minValue, tIter->second.maxValue, true) << ";" << std::endl; // not further nested + // stream << " int " << tIter->first << ";" << std::endl; // not further nested + } else { + stream << " " << tIter->second.name << " " << tIter->first << ";" << std::endl; + } + } + stream << "};" << std::endl << std::endl; + } + + // stream << "/* typedef instances */" << std::endl; + // PromelaCodeAnalyzer::PromelaTypedef allTypes = _analyzer->getTypes(); + // std::map<std::string, PromelaCodeAnalyzer::PromelaTypedef>::iterator typeIter = allTypes.types.begin(); + // while(typeIter != allTypes.types.end()) { + // if (typeIter->second.types.size() > 0) { + // // an actual typedef + // stream << "hidden " << typeIter->second.name << " " << typeIter->first << ";" << std::endl; + // } else { + // stream << "hidden " << declForRange(typeIter->first, typeIter->second.minValue, typeIter->second.maxValue) << ";" << std::endl; + // } + // typeIter++; + // } + +} + + +void ChartToPromela::writeTypes(std::ostream& stream) { + stream << "/* type definitions and global variables */" << std::endl; + stream << "bool " << _prefix << "flags[6];" << std::endl; + stream << "bool " << _prefix << "config[" << _states.size() << "];" << std::endl; + stream << "bool " << _prefix << "history[" << _states.size() << "];" << std::endl; + stream << "bool " << _prefix << "invocations[" << _states.size() << "];" << std::endl; + stream << "bool " << _prefix << "initialized_data[" << _states.size() << "];" << std::endl; + + size_t tolerance = 6; + + if (_analyzer.usesComplexEventStruct()) { + // event is defined with the typedefs + stream << "_event_t " << _prefix << "_event; /* current event */" << std::endl; + stream << "chan " << _prefix << "iQ = [" << (std::max)(_internalQueueLength, (size_t)1) << "] of {_event_t} /* internal queue */" << std::endl; + stream << "chan " << _prefix << "eQ = [" << _externalQueueLength + tolerance << "] of {_event_t} /* external queue */" << std::endl; + if (_allowEventInterleaving) + stream << "chan " << _prefix << "tmpQ = [" << (std::max)(_externalQueueLength + tolerance, (size_t)1) << "] of {_event_t} /* temporary queue for external events in transitions */" << std::endl; + } else { + stream << "unsigned " << _prefix << "_event : " << BIT_WIDTH(_analyzer.getLiterals().size() + 1) << "; /* current event */" << std::endl; + stream << "chan " << _prefix << "iQ = [" << (std::max)(_internalQueueLength, (size_t)1) << "] of {int} /* internal queue */" << std::endl; + stream << "chan " << _prefix << "eQ = [" << _externalQueueLength + tolerance << "] of {int} /* external queue */" << std::endl; + if (_allowEventInterleaving) + stream << "chan " << _prefix << "tmpQ = [" << (std::max)(_externalQueueLength + tolerance, (size_t)1) << "] of {int} /* temporary queue for external events in transitions */" << std::endl; + } + + stream << std::endl; + stream << "typedef transition {" << std::endl; + stream << " unsigned source : " << BIT_WIDTH(_states.size()) << ";" << std::endl; + stream << " bool target[" << _states.size() << "];" << std::endl; + stream << " bool type[5];" << std::endl; + stream << " bool conflicts[" << _transitions.size() << "];" << std::endl; + stream << " bool exit_set[" << _states.size() << "];" << std::endl; + stream << "}" << std::endl; + if (_transitions.size() > 0) { + stream << "hidden transition " << _prefix << "transitions[" << toStr(_transitions.size()) << "];" << std::endl; + } + stream << std::endl; + + stream << "typedef state {" << std::endl; + stream << " unsigned parent : " << BIT_WIDTH(_states.size()) << ";" << std::endl; + stream << " bool children[" << _states.size() << "];" << std::endl; + stream << " bool completion[" << _states.size() << "];" << std::endl; + stream << " bool ancestors[" << _states.size() << "];" << std::endl; + stream << " bool type[8];" << std::endl; + stream << "}" << std::endl; + if (_states.size() > 0) { + stream << "hidden state " << _prefix << "states[" << toStr(_states.size()) << "];" << std::endl; + } + stream << std::endl; + + stream << "hidden int tmpIndex;" << std::endl; + if (_analyzer.usesComplexEventStruct()) { + stream << "hidden _event_t tmpE;" << std::endl; + } else { + stream << "hidden int tmpE;" << std::endl; + } + + if (_analyzer.hasIndexLessLoops()) + stream << "hidden int " << _prefix << "_index; /* helper for indexless foreach loops */" << std::endl; + + if (_analyzer.usesEventField("sendid")) + stream << "hidden int _lastSendId = 0; /* sequential counter for send ids */" << std::endl; + + if (_analyzer.usesEventField("delay")) + stream << "hidden int _lastSeqId = 0; /* sequential counter for delayed events */" << std::endl; + + stream << std::endl; + + std::set<std::string> processedIdentifiers; + + // automatic types + std::list<DOMElement*> datas = DOMUtils::inDocumentOrder({ XML_PREFIX(_scxml).str() + "data" }, _scxml, false); + PromelaCodeAnalyzer::PromelaTypedef allTypes = _analyzer.getTypes(); + + for (auto data : datas) { + std::string identifier = (HAS_ATTR_CAST(data, "id") ? ATTR_CAST(data, "id") : ""); + std::string type = boost::trim_copy(HAS_ATTR_CAST(data, "type") ? ATTR_CAST(data, "type") : ""); + + _dataModelVars.insert(identifier); + if (processedIdentifiers.find(identifier) != processedIdentifiers.end()) + continue; + + processedIdentifiers.insert(identifier); + + if (boost::starts_with(type, "string")) { + type = "int" + type.substr(6, type.length() - 6); + } + + if (type.length() == 0 || type == "auto") { + if (allTypes.types.find(identifier) != allTypes.types.end()) { + type = allTypes.types[identifier].name; + } else { + LOG(ERROR) << "Automatic or no type for '" << identifier << "' but no type resolved"; + continue; + } + } + + std::string arrSize; + size_t bracketPos = type.find("["); + if (bracketPos != std::string::npos) { + arrSize = type.substr(bracketPos, type.length() - bracketPos); + type = type.substr(0, bracketPos); + } + std::string decl = type + " " + _prefix + identifier + arrSize; + stream << decl << ";" << std::endl; + + } + + // implicit and dynamic types + std::map<std::string, PromelaCodeAnalyzer::PromelaTypedef>::iterator typeIter = allTypes.types.begin(); + while(typeIter != allTypes.types.end()) { + if (typeIter->second.occurrences.find(this) == typeIter->second.occurrences.end()) { + typeIter++; + continue; + } + + if (processedIdentifiers.find(typeIter->first) != processedIdentifiers.end()) { + typeIter++; + continue; + } + + if (typeIter->first == "_event" + || typeIter->first == "config" + || typeIter->first == "_ioprocessors" + || typeIter->first == "_SESSIONID" + || typeIter->first == "_NAME" + || !std::any_of(typeIter->first.begin(), typeIter->first.end(), ::islower) + ) { + typeIter++; + continue; + } + + processedIdentifiers.insert(typeIter->first); + + if (typeIter->second.types.size() == 0) { + stream << "hidden " << declForRange(_prefix + typeIter->first, typeIter->second.minValue, typeIter->second.maxValue) << ";" << std::endl; + } else { + stream << "hidden " << _prefix << typeIter->second.name << " " << typeIter->first << ";" << std::endl; + } + typeIter++; + } + +} + +void ChartToPromela::writeStrings(std::ostream& stream) { + stream << "/* states, events and string literals */" << std::endl; + std::set<std::string> literals = _analyzer.getLiterals(); + + { + for (size_t i = 0; i < _states.size(); i++) { + if (HAS_ATTR(_states[i], "id")) { + stream << "#define " << _prefix << _analyzer.macroForLiteral(ATTR(_states[i], "id")) << " " << toStr(i); + stream << " /* index for state " << ATTR(_states[i], "id") << " */" << std::endl; + } + } + } + + + for (auto literal : literals) { + stream << "#define " << _analyzer.macroForLiteral(literal) << " " << _analyzer.indexForLiteral(literal) << " /* " << literal << " */" << std::endl; + } +} + +void ChartToPromela::writeTransitions(std::ostream& stream) { + for (size_t i = 0; i < _transitions.size(); i++) { + DOMElement* transition(_transitions[i]); + + /** source */ + stream << " " << _prefix << "transitions[" << toStr(i) << "].source = "; + stream << ATTR_CAST(transition->getParentNode(), "documentOrder") ; + stream << ";" << std::endl; + + /** target */ + if (HAS_ATTR(transition, "targetBools")) { + std::string targetBools = ATTR(transition, "targetBools"); + for (size_t j = 0; j < _states.size(); j++) { + if (targetBools[j] == '1') + stream << " " << _prefix << "transitions[" << toStr(i) << "].target[" << toStr(j) << "] = 1;" << std::endl; + } + } + +#if 0 + /** events */ + if (HAS_ATTR(transition, "event")) { + std::list<std::string> events = tokenize(ATTR(transition, "event"), ' ', true); + for(auto& event : events) { + auto trieNodes = _analyzer.getTrie().getWordsWithPrefix(event); + for(auto trieNode : trieNodes) { + stream << " " << _prefix << "transitions[" << toStr(i) << "].event[" << _analyzer.macroForLiteral(trieNode->value) << "] = 1;" << std::endl; + } + } + } +#endif + + if (!HAS_ATTR(transition, "event")) + stream << " " << _prefix << "transitions[" << toStr(i) << "].type[USCXML_TRANS_SPONTANEOUS] = 1;" << std::endl; + + if (!HAS_ATTR(transition, "target")) + stream << " " << _prefix << "transitions[" << toStr(i) << "].type[USCXML_TRANS_TARGETLESS] = 1;" << std::endl; + + if (HAS_ATTR(transition, "type") && ATTR(transition, "type") == "internal") + stream << " " << _prefix << "transitions[" << toStr(i) << "].type[USCXML_TRANS_INTERNAL] = 1;" << std::endl; + + if (TAGNAME_CAST(transition->getParentNode()) == XML_PREFIX(transition).str() + "history") + stream << " " << _prefix << "transitions[" << toStr(i) << "].type[USCXML_TRANS_HISTORY] = 1;" << std::endl; + + if (TAGNAME_CAST(transition->getParentNode()) == XML_PREFIX(transition).str() + "initial") + stream << " " << _prefix << "transitions[" << toStr(i) << "].type[USCXML_TRANS_INITIAL] = 1;" << std::endl; + + if (HAS_ATTR(transition, "conflictBools")) { + std::string conflicts = ATTR(transition, "conflictBools"); + for (auto j = 0; j < conflicts.size(); j++) { + if (conflicts[j] == '1') + stream << " " << _prefix << "transitions[" << toStr(i) << "].conflicts[" << toStr(j) << "] = 1;" << std::endl; + } + } + + if (HAS_ATTR(transition, "exitSetBools")) { + std::string exitSet = ATTR(transition, "exitSetBools"); + for (auto j = 0; j < exitSet.size(); j++) { + if (exitSet[j] == '1') + stream << " " << _prefix << "transitions[" << toStr(i) << "].exit_set[" << toStr(j) << "] = 1;" << std::endl; + } + } + + stream << std::endl; + + } +} + + + +void ChartToPromela::writeStates(std::ostream& stream) { + for (size_t i = 0; i < _states.size(); i++) { + DOMElement* state(_states[i]); + + stream << " " << _prefix << "states[" << toStr(i) << "].parent = "; + stream << (i == 0 ? "0" : ATTR_CAST(state->getParentNode(), "documentOrder")); + stream << ";" << std::endl; + + + if (HAS_ATTR(state, "childBools")) { + std::string childs = ATTR(state, "childBools"); + for (auto j = 0; j < childs.size(); j++) { + if (childs[j] == '1') + stream << " " << _prefix << "states[" << toStr(i) << "].children[" << toStr(j) << "] = 1;" << std::endl; + } + } + + if (HAS_ATTR(state, "completionBools")) { + std::string completions = ATTR(state, "completionBools"); + for (auto j = 0; j < completions.size(); j++) { + if (completions[j] == '1') + stream << " " << _prefix << "states[" << toStr(i) << "].completion[" << toStr(j) << "] = 1;" << std::endl; + } + } + + if (HAS_ATTR(state, "ancBools")) { + std::string ancestors = ATTR(state, "ancBools"); + for (auto j = 0; j < ancestors.size(); j++) { + if (ancestors[j] == '1') + stream << " " << _prefix << "states[" << toStr(i) << "].ancestors[" << toStr(j) << "] = 1;" << std::endl; + } + } + if (false) { + } else if (iequals(TAGNAME(state), "initial")) { + stream << " " << _prefix << "states[" << toStr(i) << "].type[USCXML_STATE_INITIAL] = 1;" << std::endl; + } else if (isFinal(state)) { + stream << " " << _prefix << "states[" << toStr(i) << "].type[USCXML_STATE_FINAL] = 1;" << std::endl; + } else if (isHistory(state)) { + if (HAS_ATTR(state, "type") && iequals(ATTR(state, "type"), "deep")) { + stream << " " << _prefix << "states[" << toStr(i) << "].type[USCXML_STATE_HISTORY_DEEP] = 1;" << std::endl; + } else { + stream << " " << _prefix << "states[" << toStr(i) << "].type[USCXML_STATE_HISTORY_SHALLOW] = 1;" << std::endl; + } + } else if (isAtomic(state)) { + stream << " " << _prefix << "states[" << toStr(i) << "].type[USCXML_STATE_ATOMIC] = 1;" << std::endl; + } else if (isParallel(state)) { + stream << " " << _prefix << "states[" << toStr(i) << "].type[USCXML_STATE_PARALLEL] = 1;" << std::endl; + } else if (isCompound(state)) { + stream << " " << _prefix << "states[" << toStr(i) << "].type[USCXML_STATE_COMPOUND] = 1;" << std::endl; + } else { // <scxml> + stream << " " << _prefix << "states[" << toStr(i) << "].type[USCXML_STATE_COMPOUND] = 1;" << std::endl; + } + if (HAS_ATTR(state, "hasHistoryChild")) { + stream << " " << _prefix << "states[" << toStr(i) << "].type[USCXML_STATE_HAS_HISTORY] = 1;" << std::endl; + } + + stream << std::endl; + + } +} + + +void ChartToPromela::writeHelpers(std::ostream& stream) { + + +} + +void ChartToPromela::writeExecContent(std::ostream& stream, const XERCESC_NS::DOMNode* node, size_t indent) { + if (!node) + return; + + std::string padding; + for (size_t i = 0; i < indent; i++) { + padding += " "; + } + + if (node->getNodeType() == DOMNode::TEXT_NODE) { + if (boost::trim_copy(X(node->getNodeValue()).str()).length() > 0) + stream << beautifyIndentation(ADAPT_SRC(X(node->getNodeValue()).str()), indent) << std::endl; + } + + if (node->getNodeType() != DOMNode::ELEMENT_NODE) + return; // skip anything not an element + + const XERCESC_NS::DOMElement* element = static_cast<const XERCESC_NS::DOMElement*>(node); + + if (false) { + } else if(TAGNAME(element) == "onentry" || + TAGNAME(element) == "onexit" || + TAGNAME(element) == "transition" || + TAGNAME(element) == "finalize") { + // descent into childs and write their contents + const XERCESC_NS::DOMNode* child = node->getFirstChild(); + while(child) { + writeExecContent(stream, child, indent); + child = child->getNextSibling(); + } + } else if(TAGNAME(element) == "script") { + std::list<DOMNode*> scriptTexts = DOMUtils::filterChildType(DOMNode::TEXT_NODE, node, true); + for (auto scriptText : scriptTexts) { + stream << ADAPT_SRC(beautifyIndentation(X(scriptText->getNodeValue()).str(), indent)) << std::endl; + } + + } else if(TAGNAME(element) == "log") { + std::string label = (HAS_ATTR(element, "label") ? ATTR(element, "label") : ""); + std::string expr = (HAS_ATTR(element, "expr") ? ADAPT_SRC(ATTR(element, "expr")) : ""); + std::string trimmedExpr = boost::trim_copy(expr); + bool isStringLiteral = (boost::starts_with(trimmedExpr, "\"") || boost::starts_with(trimmedExpr, "'")); + + std::string formatString; + std::string varString; + std::string seperator; + + if (label.size() > 0) { + if (expr.size() > 0) { + formatString += label + ": "; + } else { + formatString += label; + } + } + + if (isStringLiteral) { + formatString += expr; + } else if (expr.size() > 0) { + formatString += "%d"; + varString += seperator + expr; + } + + if (varString.length() > 0) { + stream << padding << "printf(\"" + formatString + "\", " + varString + ");" << std::endl; + } else { + stream << padding << "printf(\"" + formatString + "\");" << std::endl; + } + + } else if(TAGNAME(element) == "foreach") { + stream << padding << "for (" << _prefix << (HAS_ATTR(element, "index") ? ATTR(element, "index") : "_index") << " in " << _prefix << ATTR(element, "array") << ") {" << std::endl; + if (HAS_ATTR(element, "item")) { + stream << padding << " " << _prefix << ATTR(element, "item") << " = " << _prefix << ATTR(element, "array") << "[" << _prefix << (HAS_ATTR(element, "index") ? ATTR(element, "index") : "_index") << "];" << std::endl; + } + const XERCESC_NS::DOMNode* child = element->getFirstChild(); + while(child) { + writeExecContent(stream, child, indent + 1); + child = child->getNextSibling(); + } + // if (HAS_ATTR(nodeElem, "index")) + // stream << padding << " " << _prefix << ATTR(nodeElem, "index") << "++;" << std::endl; + stream << padding << "}" << std::endl; + + } else if(TAGNAME(element) == "if") { + std::list<DOMElement*> condChain; + condChain.push_back(const_cast<DOMElement*>(element)); + + condChain.splice(condChain.end(), DOMUtils::filterChildElements(XML_PREFIX(element).str() + "elseif", element)); + condChain.splice(condChain.end(), DOMUtils::filterChildElements(XML_PREFIX(element).str() + "else", element)); + + writeIfBlock(stream, condChain, indent); + + } else if(TAGNAME(element) == "assign") { + + std::list<DOMNode*> assignTexts = DOMUtils::filterChildType(DOMNode::TEXT_NODE, element, true); + assert(assignTexts.size() > 0); + stream << beautifyIndentation(ADAPT_SRC(boost::trim_copy(X(assignTexts.front()->getNodeValue()).str())), indent) << std::endl; + + } else if(TAGNAME(element) == "send" || TAGNAME(element) == "raise") { + std::string targetQueue; + std::string insertOp = "!"; + if (TAGNAME(element) == "raise") { + targetQueue = _prefix + "iQ"; + } else if (!HAS_ATTR(element, "target")) { +// if (_allowEventInterleaving) { +// targetQueue = _prefix + "tmpQ"; +// } else { + targetQueue = _prefix + "eQ"; +// } + } else if (ATTR(element, "target").compare("#_internal") == 0) { + targetQueue = _prefix + "iQ"; + } else if (ATTR(element, "target").compare("#_parent") == 0) { + targetQueue = _parent->_prefix + "eQ"; + } else if (boost::starts_with(ATTR(element, "target"), "#_") && _machinesPerId.find(ATTR(element, "target").substr(2)) != _machinesPerId.end()) { + targetQueue = _machines[_machinesPerId[ATTR(element, "target").substr(2)]]->_prefix + "eQ"; + } + if (targetQueue.length() > 0) { + // this is for our external queue + std::string event; + + if (HAS_ATTR(element, "event")) { + event = _analyzer.macroForLiteral(ATTR(element, "event")); + } else if (HAS_ATTR(element, "eventexpr")) { + event = ADAPT_SRC(ATTR(element, "eventexpr")); + } + if (_analyzer.usesComplexEventStruct()) { + stream << padding << "{" << std::endl; + std::string typeReset = _analyzer.getTypeReset(_prefix + "_event", _analyzer.getType("_event"), padding + " "); + std::stringstream typeAssignSS; + typeAssignSS << padding << " " << _prefix << EVENT_NAME << " = " << event << ";" << std::endl; + + if (HAS_ATTR(element, "idlocation")) { + typeAssignSS << padding << " /* idlocation */" << std::endl; + typeAssignSS << padding << " _lastSendId = _lastSendId + 1;" << std::endl; + typeAssignSS << padding << " " << _prefix << ATTR(element, "idlocation") << " = _lastSendId;" << std::endl; + typeAssignSS << padding << " " << _prefix << "_event.sendid = _lastSendId;" << std::endl; + typeAssignSS << padding << " if" << std::endl; + typeAssignSS << padding << " :: _lastSendId == 2147483647 -> _lastSendId = 0;" << std::endl; + typeAssignSS << padding << " :: else -> skip;" << std::endl; + typeAssignSS << padding << " fi;" << std::endl; + } else if (HAS_ATTR(element, "id")) { + typeAssignSS << padding << " " << _prefix << "_event.sendid = " << _analyzer.macroForLiteral(ATTR(element, "id")) << ";" << std::endl; + } + + if (_invokerid.length() > 0) { // do not send invokeid if we send / raise to ourself + typeAssignSS << padding << " " << _prefix << "_event.invokeid = " << _analyzer.macroForLiteral(_invokerid) << ";" << std::endl; + } + + if (_analyzer.usesEventField("origintype") && !boost::ends_with(targetQueue, "iQ")) { + typeAssignSS << padding << " " << _prefix << "_event.origintype = " << _analyzer.macroForLiteral("http://www.w3.org/TR/scxml/#SCXMLEventProcessor") << ";" << std::endl; + } + + if (_analyzer.usesEventField("delay")) { +#if NEW_DELAY_RESHUFFLE +#else + insertOp += "!"; + typeAssignSS << padding << " _lastSeqId = _lastSeqId + 1;" << std::endl; +#endif + if (HAS_ATTR_CAST(element, "delay")) { + typeAssignSS << padding << " " << _prefix << "_event.delay = " << ATTR_CAST(element, "delay") << ";" << std::endl; + } else if (HAS_ATTR_CAST(element, "delayexpr")) { + typeAssignSS << padding << " " << _prefix << "_event.delay = " << ADAPT_SRC(ATTR_CAST(element, "delayexpr")) << ";" << std::endl; + } else { + typeAssignSS << padding << " " << _prefix << "_event.delay = 0;" << std::endl; + } +#if NEW_DELAY_RESHUFFLE +#else + typeAssignSS << padding << " " << _prefix << "_event.seqNr = _lastSeqId;" << std::endl; +#endif + } + + if (_analyzer.usesEventField("type")) { + std::string eventType = (targetQueue.compare("iQ!") == 0 ? _analyzer.macroForLiteral("internal") : _analyzer.macroForLiteral("external")); + typeAssignSS << padding << " " << _prefix << "_event.type = " << eventType << ";" << std::endl; + } + + std::list<DOMElement*> sendParams = DOMUtils::filterChildElements(XML_PREFIX(element).str() + "param", element); + std::list<DOMElement*> sendContents = DOMUtils::filterChildElements(XML_PREFIX(element).str() + "content", element); + std::string sendNameList = ATTR(element, "namelist"); + if (sendParams.size() > 0) { + for (auto sendParam : sendParams) { + typeAssignSS << padding << " " << _prefix << "_event.data." << ATTR(sendParam, "name") << " = " << ADAPT_SRC(ATTR(sendParam, "expr")) << ";" << std::endl; + } + } + if (sendNameList.size() > 0) { + std::list<std::string> nameListIds = tokenize(sendNameList); + std::list<std::string>::iterator nameIter = nameListIds.begin(); + while(nameIter != nameListIds.end()) { + typeAssignSS << padding << " " << _prefix << "_event.data." << *nameIter << " = " << ADAPT_SRC(*nameIter) << ";" << std::endl; + nameIter++; + } + } + + if (sendParams.size() == 0 && sendNameList.size() == 0 && sendContents.size() > 0) { + DOMElement* contentElem = sendContents.front(); + if (contentElem->hasChildNodes() && contentElem->getFirstChild()->getNodeType() == DOMNode::TEXT_NODE) { + std::string content = spaceNormalize(X(contentElem->getFirstChild()->getNodeValue()).str()); + if (!isNumeric(content.c_str(), 10)) { + typeAssignSS << padding << " " << _prefix << "_event.data = " << _analyzer.macroForLiteral(content) << ";" << std::endl; + } else { + typeAssignSS << padding << " " << _prefix << "_event.data = " << content << ";" << std::endl; + } + } else if (HAS_ATTR(contentElem, "expr")) { + typeAssignSS << padding << " " << _prefix << "_event.data = " << ADAPT_SRC(ATTR(contentElem, "expr")) << ";" << std::endl; + } + } + + // remove all fields from typeReset that are indeed set by typeAssign + // for (std::string assigned; std::getline(typeAssignSS, assigned); ) { + // assigned = assigned.substr(0, assigned.find('=')); + // assigned = assigned.substr(assigned.find('.')); + // std::istringstream typeResetSS (typeReset); + // for (std::string reset; std::getline(typeResetSS, reset); ) { + // if (!boost::find_first(reset, assigned)) { + // stream << reset << std::endl; + // } + // } + // } + // stream << typeAssignSS.str(); + + std::istringstream typeResetSS (typeReset); + for (std::string reset; std::getline(typeResetSS, reset); ) { + std::string resetField = reset.substr(0, reset.find('=')); + resetField = resetField.substr(resetField.find('.')); + for (std::string assigned; std::getline(typeAssignSS, assigned); ) { + if (boost::find_first(resetField, assigned)) { + break; + } + } + stream << reset << std::endl; + } + stream << typeAssignSS.str(); + + + stream << padding << " " << targetQueue << insertOp << _prefix <<"_event;" << std::endl; + +#if NEW_DELAY_RESHUFFLE + if (_analyzer->usesEventField("delay") && !boost::ends_with(targetQueue, "iQ")) { + stream << padding << " insertWithDelay(" << targetQueue << ");" << std::endl; + } +#endif + + stream << padding << "}" << std::endl; + } else { + stream << padding << targetQueue << insertOp << event << ";" << std::endl; + } + } + } else if(TAGNAME(element) == "cancel") { + if (HAS_ATTR(element, "sendid")) { + stream << padding << "cancelSendId(" << _analyzer.macroForLiteral(ATTR(element, "sendid")) << ", " << (_invokerid.size() > 0 ? _analyzer.macroForLiteral(_invokerid) : "0") << ");" << std::endl; + } else if (HAS_ATTR(element, "sendidexpr")) { + stream << padding << "cancelSendId(" << ADAPT_SRC(ATTR(element, "sendidexpr")) << ", " << (_invokerid.size() > 0 ? _analyzer.macroForLiteral(_invokerid) : "0") << ");" << std::endl; + } + } else { + std::cerr << "'" << TAGNAME(element) << "' not supported" << std::endl << element << std::endl; + assert(false); + } + + +} + + + +void ChartToPromela::writeFSM(std::ostream& stream) { + stream << "/* machine microstep function */" << std::endl; + stream << "#define USCXML_NUMBER_STATES " << _states.size() << std::endl; + stream << "#define USCXML_NUMBER_TRANS " << _transitions.size() << std::endl; + + stream << "proctype " << _prefix << "step() { atomic {" << std::endl; + stream << std::endl; + stream << "/* ---------------------------- */" << std::endl; + stream << "MICROSTEP:" << std::endl; + + stream << "do" << std::endl; + stream << ":: !" << _prefix << "flags[USCXML_CTX_FINISHED] -> {" << std::endl; + stream << std::endl; + + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Taking a step\\n\");" << std::endl; + stream << "#endif" << std::endl; + + + size_t largestBitWidth = (_states.size() > _transitions.size() ? + BIT_WIDTH(_states.size() + 1) : + BIT_WIDTH(_transitions.size() + 1)); + + stream << " unsigned"; + stream << " i : " << largestBitWidth << ", "; + stream << " j : " << largestBitWidth << ", "; + stream << " k : " << largestBitWidth << ";" << std::endl; + + stream << " int err = USCXML_ERR_OK;" << std::endl; + + stream << " bool conflicts[" << _transitions.size() << "];" << std::endl; + stream << " bool trans_set[" << _transitions.size() << "];" << std::endl; + + stream << " bool target_set[" << _states.size() << "];" << std::endl; + stream << " bool exit_set[" << _states.size() << "];" << std::endl; + stream << " bool entry_set[" << _states.size() << "];" << std::endl; + stream << " bool tmp_states[" << _states.size() << "];" << std::endl; + stream << std::endl; + +#if 0 + stream << " if" << std::endl; + stream << " :: " << _prefix << "flags[USCXML_CTX_FINISHED]" << std::endl; + stream << " ACCEPT: {" << std::endl; + stream << " false;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi;" << std::endl; + stream << std::endl; + + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Machine not finished\\n\");" << std::endl; + stream << "#endif" << std::endl; +#endif + +#if 0 + stream << " if (ctx->flags & USCXML_CTX_TOP_LEVEL_FINAL) -> {" << std::endl; + stream << " /* exit all remaining states */" << std::endl; + stream << " i = USCXML_NUMBER_STATES;" << std::endl; + stream << " while(i-- > 0) {" << std::endl; + stream << " if (BIT_HAS(i, ctx->config)) {" << std::endl; + stream << " /* call all on exit handlers */" << std::endl; + stream << " if (USCXML_GET_STATE(i).on_exit != NULL) {" << std::endl; + stream << " if unlikely((err = USCXML_GET_STATE(i).on_exit(ctx, &USCXML_GET_STATE(i), ctx->event)) != USCXML_ERR_OK)" << std::endl; + stream << " return err;" << std::endl; + stream << " }" << std::endl; + // stream << " BIT_CLEAR(i, ctx->config);" << std::endl; + stream << " }" << std::endl; + stream << " if (BIT_HAS(i, ctx->invocations)) {" << std::endl; + stream << " if (USCXML_GET_STATE(i).invoke != NULL)" << std::endl; + stream << " USCXML_GET_STATE(i).invoke(ctx, &USCXML_GET_STATE(i), NULL, 1);" << std::endl; + stream << " BIT_CLEAR(i, ctx->invocations);" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " ctx->flags |= USCXML_CTX_FINISHED;" << std::endl; + stream << " return USCXML_ERR_DONE;" << std::endl; + stream << " }" << std::endl; + stream << std::endl; + +#endif + + stream << " if" << std::endl; + stream << " ::" << _prefix << "flags[USCXML_CTX_TOP_LEVEL_FINAL] -> {" << std::endl; + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Top level final state reached\\n\");" << std::endl; + stream << "#endif" << std::endl; + stream << " /* exit all remaining states */" << std::endl; + stream << " i = USCXML_NUMBER_STATES;" << std::endl; + stream << " do" << std::endl; + stream << " :: i > 0 -> {" << std::endl; + stream << " i = i - 1;" << std::endl; + stream << " if" << std::endl; + stream << " :: " << _prefix << "config[i] -> {" << std::endl; + stream << " /* TODO: call all on exit handlers */" << std::endl; + stream << " skip;" << std::endl; + stream << " " << std::endl; + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi;" << std::endl; + stream << std::endl; + + stream << " if" << std::endl; + stream << " :: " << _prefix << "invocations[i] -> {" << std::endl; + stream << " /* TODO: cancel invocations */" << std::endl; + stream << " skip;" << std::endl; + stream << " " << std::endl; + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> break;" << std::endl; + stream << " od;" << std::endl; + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Ending machine!\\n\");" << std::endl; + stream << "#endif" << std::endl; + stream << " " << _prefix << "flags[USCXML_CTX_FINISHED] = true;" << std::endl; + stream << " goto MICROSTEP;" << std::endl; + + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi;" << std::endl; + stream << std::endl; + +#if 0 + stream << " bit_clear_all(target_set, nr_states_bytes);" << std::endl; + stream << " bit_clear_all(trans_set, nr_trans_bytes);" << std::endl; + stream << " if unlikely(ctx->flags == USCXML_CTX_PRISTINE) {" << std::endl; + stream << " if (ctx->machine->script != NULL)" << std::endl; + stream << " ctx->machine->script(ctx, &ctx->machine->states[0], NULL);" << std::endl; + stream << " bit_or(target_set, ctx->machine->states[0].completion, nr_states_bytes);" << std::endl; + stream << " ctx->flags |= USCXML_CTX_SPONTANEOUS | USCXML_CTX_INITIALIZED;" << std::endl; + stream << " goto ESTABLISH_ENTRY_SET;" << std::endl; + stream << " }" << std::endl; + stream << std::endl; +#endif + + stream << " if" << std::endl; + stream << " ::" << _prefix << "flags[USCXML_CTX_PRISTINE] -> {" << std::endl; + stream << " /* run global scripts */" << std::endl; + + std::list<DOMElement*> globalScripts = DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "script", _scxml, false); + for (auto globalScript : globalScripts) { + writeExecContent(stream, globalScript); + } + stream << std::endl; + + stream << " /* Enter initial configuration */" << std::endl; + bit_copy(stream, _prefix + "states[0].completion", "target_set", _states.size(), 2); + stream << " " << _prefix << "flags[USCXML_CTX_SPONTANEOUS] = true;" << std::endl; + stream << " " << _prefix << "flags[USCXML_CTX_PRISTINE] = false;" << std::endl; + + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Entering initial default completion\\n\");" << std::endl; + stream << "#endif" << std::endl; + + stream << " goto ESTABLISH_ENTRY_SET;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi;" << std::endl; + stream << std::endl; + + +#if 0 + stream << "DEQUEUE_EVENT:" << std::endl; + stream << " if (ctx->flags & USCXML_CTX_SPONTANEOUS) {" << std::endl; + stream << " ctx->event = NULL;" << std::endl; + stream << " goto SELECT_TRANSITIONS;" << std::endl; + stream << " }" << std::endl; + stream << " if (ctx->dequeue_internal != NULL && (ctx->event = ctx->dequeue_internal(ctx)) != NULL) {" << std::endl; + stream << " goto SELECT_TRANSITIONS;" << std::endl; + stream << " }" << std::endl; + stream << std::endl; +#endif + + + stream << "/* ---------------------------- */" << std::endl; + stream << "DEQUEUE_EVENT:" << std::endl; + stream << " if" << std::endl; + stream << " ::" << _prefix << "flags[USCXML_CTX_SPONTANEOUS] -> {" << std::endl; + stream << " " << _prefix << EVENT_NAME << " = USCXML_EVENT_SPONTANEOUS;" << std::endl; + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Trying with a spontaneuous event\\n\");" << std::endl; + stream << "#endif" << std::endl; + stream << " goto SELECT_TRANSITIONS;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi;" << std::endl; + stream << std::endl; + + stream << " if" << std::endl; + stream << " :: len(" << _prefix << "iQ) != 0 -> {" << std::endl; + stream << " " << _prefix << "iQ ? " << _prefix << "_event;" << std::endl; + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Deqeued an internal event\\n\");" << std::endl; + stream << "#endif" << std::endl; + stream << " goto SELECT_TRANSITIONS;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi;" << std::endl; + + +#if 0 + stream << " /* manage invocations */" << std::endl; + stream << " for (i = 0; i < USCXML_NUMBER_STATES; i++) {" << std::endl; + stream << " /* uninvoke */" << std::endl; + stream << " if (!BIT_HAS(i, ctx->config) && BIT_HAS(i, ctx->invocations)) {" << std::endl; + stream << " if (USCXML_GET_STATE(i).invoke != NULL)" << std::endl; + stream << " USCXML_GET_STATE(i).invoke(ctx, &USCXML_GET_STATE(i), NULL, 1);" << std::endl; + stream << " BIT_CLEAR(i, ctx->invocations)" << std::endl; + stream << " }" << std::endl; + stream << " /* invoke */" << std::endl; + stream << " if (BIT_HAS(i, ctx->config) && !BIT_HAS(i, ctx->invocations)) {" << std::endl; + stream << " if (USCXML_GET_STATE(i).invoke != NULL)" << std::endl; + stream << " USCXML_GET_STATE(i).invoke(ctx, &USCXML_GET_STATE(i), NULL, 0);" << std::endl; + stream << " BIT_SET_AT(i, ctx->invocations)" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << std::endl; +#endif + + stream << " /* manage invocations */" << std::endl; + stream << " i = 0;" << std::endl; + stream << " do" << std::endl; + stream << " :: i < USCXML_NUMBER_STATES -> {" << std::endl; + stream << " /* uninvoke */" << std::endl; + stream << " if" << std::endl; + stream << " :: !" << _prefix << "config[i] && " << _prefix << "invocations[i] -> {" << std::endl; + stream << " skip;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi;" << std::endl; + stream << std::endl; + + stream << " /* invoke */" << std::endl; + stream << " if" << std::endl; + stream << " :: " << _prefix << "config[i] && !" << _prefix << "invocations[i] -> {" << std::endl; + stream << " skip;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi;" << std::endl; + stream << " i = i + 1;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> break;" << std::endl; + stream << " od;" << std::endl; + stream << std::endl; + +#if 0 + stream << " if (ctx->dequeue_external != NULL && (ctx->event = ctx->dequeue_external(ctx)) != NULL) {" << std::endl; + stream << " goto SELECT_TRANSITIONS;" << std::endl; + stream << " }" << std::endl; + stream << std::endl; + stream << " if (ctx->dequeue_external == NULL) {" << std::endl; + stream << " return USCXML_ERR_DONE;" << std::endl; + stream << " }" << std::endl; + stream << " return USCXML_ERR_IDLE;" << std::endl; + stream << std::endl; +#endif + + stream << " if" << std::endl; + stream << " :: len(" << _prefix << "eQ) != 0 -> {" << std::endl; + stream << " " << _prefix << "eQ ? " << _prefix << "_event;" << std::endl; + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Deqeued an external event\\n\");" << std::endl; + stream << "#endif" << std::endl; + stream << " goto SELECT_TRANSITIONS;" << std::endl; + stream << " }" << std::endl; +// stream << " :: else -> quit;" << std::endl; + stream << " fi;" << std::endl; + stream << std::endl; + +#if 0 + stream << "SELECT_TRANSITIONS:" << std::endl; + stream << " bit_clear_all(conflicts, nr_trans_bytes);" << std::endl; + stream << " bit_clear_all(exit_set, nr_states_bytes);" << std::endl; + stream << " for (i = 0; i < USCXML_NUMBER_TRANS; i++) {" << std::endl; + stream << " /* never select history or initial transitions automatically */" << std::endl; + stream << " if unlikely(USCXML_GET_TRANS(i).type & (USCXML_TRANS_HISTORY | USCXML_TRANS_INITIAL))" << std::endl; + stream << " continue;" << std::endl; + stream << std::endl; + stream << " /* is the transition active? */" << std::endl; + stream << " if (BIT_HAS(USCXML_GET_TRANS(i).source, ctx->config)) {" << std::endl; + stream << " /* is it non-conflicting? */" << std::endl; + stream << " if (!BIT_HAS(i, conflicts)) {" << std::endl; + stream << " /* is it spontaneous with an event or vice versa? */" << std::endl; + stream << " if ((USCXML_GET_TRANS(i).event == NULL && ctx->event == NULL) || " << std::endl; + stream << " (USCXML_GET_TRANS(i).event != NULL && ctx->event != NULL)) {" << std::endl; + stream << " /* is it enabled? */" << std::endl; + stream << " if ((ctx->event == NULL || ctx->is_matched(ctx, &USCXML_GET_TRANS(i), ctx->event) > 0) &&" << std::endl; + stream << " (USCXML_GET_TRANS(i).condition == NULL || " << std::endl; + stream << " USCXML_GET_TRANS(i).is_enabled(ctx, &USCXML_GET_TRANS(i)) > 0)) {" << std::endl; + stream << " /* remember that we found a transition */" << std::endl; + stream << " ctx->flags |= USCXML_CTX_TRANSITION_FOUND;" << std::endl; + stream << std::endl; + + stream << " /* transitions that are pre-empted */" << std::endl; + stream << " bit_or(conflicts, USCXML_GET_TRANS(i).conflicts, nr_trans_bytes);" << std::endl; + stream << std::endl; + stream << " /* states that are directly targeted (resolve as entry-set later) */" << std::endl; + stream << " bit_or(target_set, USCXML_GET_TRANS(i).target, nr_states_bytes);" << std::endl; + stream << std::endl; + stream << " /* states that will be left */" << std::endl; + stream << " bit_or(exit_set, USCXML_GET_TRANS(i).exit_set, nr_states_bytes);" << std::endl; + stream << std::endl; + stream << " BIT_SET_AT(i, trans_set);" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " bit_and(exit_set, ctx->config, nr_states_bytes);" << std::endl; + stream << std::endl; +#endif + + stream << "/* ---------------------------- */" << std::endl; + stream << "SELECT_TRANSITIONS:" << std::endl; + bit_clear_all(stream, "conflicts", _transitions.size(), 1); + bit_clear_all(stream, "trans_set", _transitions.size(), 1); + bit_clear_all(stream, "target_set", _states.size(), 1); + bit_clear_all(stream, "exit_set", _states.size(), 1); + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Establishing optimal transition set for event %d\\n\", " << _prefix << EVENT_NAME << ");" << std::endl; + stream << "#endif" << std::endl; + stream << " " << _prefix << "flags[USCXML_CTX_TRANSITION_FOUND] = false;" << std::endl; + stream << " i = 0;" << std::endl; + stream << " do" << std::endl; + stream << " :: i < USCXML_NUMBER_TRANS -> {" << std::endl; + + stream << " /* only select non-history, non-initial transitions */" << std::endl; + stream << " if" << std::endl; + stream << " :: !" << _prefix << "transitions[i].type[USCXML_TRANS_HISTORY] &&" << std::endl; + stream << " !" << _prefix << "transitions[i].type[USCXML_TRANS_INITIAL] -> {" << std::endl; + + stream << " if" << std::endl; + stream << " :: /* is the transition active? */" << std::endl; + stream << " " << _prefix << "config[" << _prefix << "transitions[i].source] && " << std::endl; + stream << std::endl; + stream << " /* is it non-conflicting? */" << std::endl; + stream << " !conflicts[i] && " << std::endl; + stream << std::endl; + stream << " /* is it spontaneous with an event or vice versa? */" << std::endl; + stream << " ((" << _prefix << EVENT_NAME << " == USCXML_EVENT_SPONTANEOUS && " << std::endl; + stream << " " << _prefix << "transitions[i].type[USCXML_TRANS_SPONTANEOUS]) || " << std::endl; + stream << " (" << _prefix << EVENT_NAME << " != USCXML_EVENT_SPONTANEOUS && " << std::endl; + stream << " !" << _prefix << "transitions[i].type[USCXML_TRANS_SPONTANEOUS])) &&" << std::endl; + stream << std::endl; + stream << " /* is it matching and enabled? */" << std::endl; + stream << " (false " << std::endl; + + + for (auto i = 0; i < _transitions.size(); i++) { + stream << " || (i == " << toStr(i); + if (HAS_ATTR(_transitions[i], "event") && ATTR(_transitions[i], "event") != "*") { + stream << " && (false"; + std::list<TrieNode*> events =_analyzer.getTrie().getWordsWithPrefix(ATTR(_transitions[i], "event")); + for (auto event : events) { + stream << " || " << _prefix << EVENT_NAME << " == " << _analyzer.macroForLiteral(event->value); + } + stream << ")"; + } + if (HAS_ATTR(_transitions[i], "cond")) { + stream << " && " << ADAPT_SRC(ATTR(_transitions[i], "cond")); + } + stream << ")" << std::endl; + } + + stream << " ) -> {" << std::endl; + + stream << " /* remember that we found a transition */" << std::endl; + stream << " " << _prefix << "flags[USCXML_CTX_TRANSITION_FOUND] = true;" << std::endl; + stream << std::endl; + + stream << " /* transitions that are pre-empted */" << std::endl; + bit_or(stream, "conflicts", _prefix + "transitions[i].conflicts", _transitions.size(), 4); + stream << std::endl; + + stream << " /* states that are directly targeted (resolve as entry-set later) */" << std::endl; + bit_or(stream, "target_set", _prefix + "transitions[i].target", _states.size(), 4); + stream << std::endl; + + stream << " /* states that will be left */" << std::endl; + bit_or(stream, "exit_set", _prefix + "transitions[i].exit_set", _states.size(), 4); + stream << std::endl; + + stream << " trans_set[i] = true;" << std::endl; + + + stream << " }" << std::endl; + stream << " :: else {" << std::endl; + stream << " skip;" << std::endl; + stream << " }" << std::endl; + stream << " fi" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> break;" << std::endl; + stream << " fi" << std::endl; + + stream << " i = i + 1;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> break;" << std::endl; + stream << " od;" << std::endl; + + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Selected Transitions: \");" << std::endl; + printBitArray(stream, "trans_set", _transitions.size()); + stream << "printf(\"\\n\");" << std::endl; + stream << "#endif" << std::endl; + + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Target Set: \");" << std::endl; + printBitArray(stream, "target_set", _states.size()); + stream << "printf(\"\\n\");" << std::endl; + stream << "#endif" << std::endl; + +#if 0 + stream << " if (ctx->flags & USCXML_CTX_TRANSITION_FOUND) {" << std::endl; + stream << " ctx->flags |= USCXML_CTX_SPONTANEOUS;" << std::endl; + stream << " ctx->flags &= ~USCXML_CTX_TRANSITION_FOUND;" << std::endl; + stream << " } else {" << std::endl; + stream << " ctx->flags &= ~USCXML_CTX_SPONTANEOUS;" << std::endl; + stream << " goto DEQUEUE_EVENT;" << std::endl; + stream << " }" << std::endl; + stream << std::endl; +#endif + + stream << " if" << std::endl; + stream << " :: " << _prefix << "flags[USCXML_CTX_TRANSITION_FOUND] -> {" << std::endl; + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Found transitions\\n\");" << std::endl; + stream << "#endif" << std::endl; + stream << " " << _prefix << "flags[USCXML_CTX_SPONTANEOUS] = true;" << std::endl; + stream << " " << _prefix << "flags[USCXML_CTX_TRANSITION_FOUND] = false;" << std::endl; + stream << " }" << std::endl; + stream << " :: else {" << std::endl; + stream << " " << _prefix << "flags[USCXML_CTX_SPONTANEOUS] = false;" << std::endl; + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Found NO transitions\\n\");" << std::endl; + stream << "#endif" << std::endl; + stream << " goto DEQUEUE_EVENT;" << std::endl; + stream << " }" << std::endl; + stream << " fi" << std::endl; + stream << std::endl; + +#if 0 + stream << "/* REMEMBER_HISTORY: */" << std::endl; + stream << " for (i = 0; i < USCXML_NUMBER_STATES; i++) {" << std::endl; + stream << " if unlikely(USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_HISTORY_SHALLOW ||" << std::endl; + stream << " USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_HISTORY_DEEP) {" << std::endl; + stream << " /* a history state whose parent is about to be exited */" << std::endl; + stream << " if unlikely(BIT_HAS(USCXML_GET_STATE(i).parent, exit_set)) {" << std::endl; + stream << " bit_copy(tmp_states, USCXML_GET_STATE(i).completion, nr_states_bytes);" << std::endl; + stream << std::endl; + stream << " /* set those states who were enabled */" << std::endl; + stream << " bit_and(tmp_states, ctx->config, nr_states_bytes);" << std::endl; + stream << std::endl; + stream << " /* clear current history with completion mask */" << std::endl; + stream << " bit_and_not(ctx->history, USCXML_GET_STATE(i).completion, nr_states_bytes);" << std::endl; + stream << std::endl; + stream << " /* set history */" << std::endl; + stream << " bit_or(ctx->history, tmp_states, nr_states_bytes);" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << std::endl; +#endif + + stream << "/* ---------------------------- */" << std::endl; + stream << "/* REMEMBER_HISTORY: */" << std::endl; + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Save history configurations\\n\");" << std::endl; + stream << "#endif" << std::endl; + stream << " i = 0;" << std::endl; + stream << " do" << std::endl; + stream << " :: i < USCXML_NUMBER_STATES -> {" << std::endl; + + stream << " if" << std::endl; + stream << " :: " << _prefix << "states[i].type[USCXML_STATE_HISTORY_SHALLOW] ||" << std::endl; + stream << " " << _prefix << "states[i].type[USCXML_STATE_HISTORY_DEEP] -> {" << std::endl; + stream << " if" << std::endl; + stream << " :: exit_set[" << _prefix << "states[i].parent] -> {" << std::endl; + stream << " /* a history state whose parent is about to be exited */" << std::endl; + + bit_copy(stream, _prefix + "states[i].completion", "tmp_states", _states.size(), 3); + bit_and(stream, "tmp_states", _prefix + "config", _states.size(), 3); + bit_and_not(stream, "tmp_states", _prefix + "states[i].completion", _states.size(), 3); + bit_or(stream, _prefix + "history", "tmp_states", _states.size(), 3); + stream << std::endl; + + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi;" << std::endl; + + + stream << " i = i + 1;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> break;" << std::endl; + stream << " od;" << std::endl; + stream << std::endl; + +#if 0 + stream << "ESTABLISH_ENTRY_SET:" << std::endl; + stream << " /* calculate new entry set */" << std::endl; + stream << " bit_copy(entry_set, target_set, nr_states_bytes);" << std::endl; + stream << std::endl; + stream << " /* iterate for ancestors */" << std::endl; + stream << " for (i = 0; i < USCXML_NUMBER_STATES; i++) {" << std::endl; + stream << " if (BIT_HAS(i, entry_set)) {" << std::endl; + stream << " bit_or(entry_set, USCXML_GET_STATE(i).ancestors, nr_states_bytes);" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << std::endl; +#endif + + stream << "/* ---------------------------- */" << std::endl; + stream << "ESTABLISH_ENTRY_SET:" << std::endl; + stream << " /* calculate new entry set */" << std::endl; + bit_copy(stream, "target_set", "entry_set", _states.size(), 1); + stream << std::endl; + + stream << " i = 0;" << std::endl; + stream << " do" << std::endl; + stream << " :: i < USCXML_NUMBER_STATES -> {" << std::endl; + + stream << " if" << std::endl; + stream << " :: entry_set[i] -> {" << std::endl; + stream << " /* ancestor completion */" << std::endl; + bit_or(stream, "entry_set", _prefix + "states[i].ancestors", _states.size(), 3); + + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi;" << std::endl; + + stream << " i = i + 1;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> break;" << std::endl; + stream << " od;" << std::endl; + stream << std::endl; + + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Entry Set (after ancestor completion)\");" << std::endl; + printBitArray(stream, "entry_set", _states.size()); + stream << "printf(\"\\n\");" << std::endl; + stream << "#endif" << std::endl; + +#if 0 + stream << " /* iterate for descendants */" << std::endl; + stream << " for (i = 0; i < USCXML_NUMBER_STATES; i++) {" << std::endl; + stream << " if (BIT_HAS(i, entry_set)) {" << std::endl; + stream << " switch (USCXML_STATE_MASK(USCXML_GET_STATE(i).type)) {" << std::endl; +#endif + + stream << " /* iterate for descendants */" << std::endl; + stream << " i = 0;" << std::endl; + stream << " do" << std::endl; + stream << " :: i < USCXML_NUMBER_STATES -> {" << std::endl; + stream << " if" << std::endl; + stream << " :: entry_set[i] -> {" << std::endl; + stream << " if" << std::endl; + +#if 0 + stream << " case USCXML_STATE_PARALLEL: {" << std::endl; + stream << " bit_or(entry_set, USCXML_GET_STATE(i).completion, nr_states_bytes);" << std::endl; + stream << " break;" << std::endl; + stream << " }" << std::endl; +#endif + + stream << " :: " << _prefix << "states[i].type[USCXML_STATE_PARALLEL] -> {" << std::endl; + bit_or(stream, "entry_set", _prefix + "states[i].completion", _states.size(), 4); + stream << " }" << std::endl; + + +#if 0 + stream << " case USCXML_STATE_HISTORY_SHALLOW:" << std::endl; + stream << " case USCXML_STATE_HISTORY_DEEP: {" << std::endl; + stream << " if (!bit_has_and(USCXML_GET_STATE(i).completion, ctx->history, nr_states_bytes) &&" << std::endl; + stream << " !BIT_HAS(USCXML_GET_STATE(i).parent, ctx->config)) {" << std::endl; + stream << " /* nothing set for history, look for a default transition */" << std::endl; + stream << " for (j = 0; j < USCXML_NUMBER_TRANS; j++) {" << std::endl; + stream << " if unlikely(ctx->machine->transitions[j].source == i) {" << std::endl; + stream << " bit_or(entry_set, ctx->machine->transitions[j].target, nr_states_bytes);" << std::endl; + stream << " if(USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_HISTORY_DEEP &&" << std::endl; + stream << " !bit_has_and(ctx->machine->transitions[j].target, USCXML_GET_STATE(i).children, nr_states_bytes)) {" << std::endl; + stream << " for (k = i + 1; k < USCXML_NUMBER_STATES; k++) {" << std::endl; + stream << " if (BIT_HAS(k, ctx->machine->transitions[j].target)) {" << std::endl; + stream << " bit_or(entry_set, ctx->machine->states[k].ancestors, nr_states_bytes);" << std::endl; + stream << " break;" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " BIT_SET_AT(j, trans_set);" << std::endl; + stream << " break;" << std::endl; + stream << " }" << std::endl; + stream << " /* Note: SCXML mandates every history to have a transition! */" << std::endl; + stream << " }" << std::endl; + stream << " } else {" << std::endl; + stream << " bit_copy(tmp_states, USCXML_GET_STATE(i).completion, nr_states_bytes);" << std::endl; + stream << " bit_and(tmp_states, ctx->history, nr_states_bytes);" << std::endl; + stream << " bit_or(entry_set, tmp_states, nr_states_bytes);" << std::endl; + stream << " if (USCXML_GET_STATE(i).type == (USCXML_STATE_HAS_HISTORY | USCXML_STATE_HISTORY_DEEP)) {" << std::endl; + stream << " /* a deep history state with nested histories -> more completion */" << std::endl; + stream << " for (j = i + 1; j < USCXML_NUMBER_STATES; j++) {" << std::endl; + stream << " if (BIT_HAS(j, USCXML_GET_STATE(i).completion) &&" << std::endl; + stream << " BIT_HAS(j, entry_set) &&" << std::endl; + stream << " (ctx->machine->states[j].type & USCXML_STATE_HAS_HISTORY)) {" << std::endl; + stream << " for (k = j + 1; k < USCXML_NUMBER_STATES; k++) {" << std::endl; + stream << " /* add nested history to entry_set */" << std::endl; + stream << " if ((USCXML_STATE_MASK(ctx->machine->states[k].type) == USCXML_STATE_HISTORY_DEEP ||" << std::endl; + stream << " USCXML_STATE_MASK(ctx->machine->states[k].type) == USCXML_STATE_HISTORY_SHALLOW) &&" << std::endl; + stream << " BIT_HAS(k, ctx->machine->states[j].children)) {" << std::endl; + stream << " /* a nested history state */" << std::endl; + stream << " BIT_SET_AT(k, entry_set);" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " break;" << std::endl; + stream << " }" << std::endl; +#endif + + + stream << " :: " << _prefix << "states[i].type[USCXML_STATE_HISTORY_SHALLOW] ||" << std::endl; + stream << " " << _prefix << "states[i].type[USCXML_STATE_HISTORY_DEEP] -> {" << std::endl; + stream << " if" << std::endl; + stream << " :: !"; + bit_has_and(stream, _prefix + "states[i].completion", _prefix + "history", _states.size(), 5); + stream << " && !" << _prefix << "config[" << _prefix << "states[i].parent]" << " -> {" << std::endl; + stream << " /* nothing set for history, look for a default transition */" << std::endl; + stream << " j = 0;" << std::endl; + stream << " do" << std::endl; + stream << " :: j < USCXML_NUMBER_TRANS -> {" << std::endl; + stream << " if" << std::endl; + stream << " :: " << _prefix << "transitions[j].source == i -> {" << std::endl; + + bit_or(stream, "entry_set", _prefix + "transitions[j].target", _states.size(), 8); + stream << std::endl; + stream << " if" << std::endl; + stream << " :: (" << _prefix << "states[i].type[USCXML_STATE_HISTORY_DEEP] &&" << std::endl; + stream << " !"; + bit_has_and(stream, _prefix + "transitions[j].target", _prefix + "states[i].children", _states.size(), 10); + stream << " ) -> {" << std::endl; + stream << " k = i + 1" << std::endl; + stream << " do" << std::endl; + stream << " :: k < USCXML_NUMBER_STATES -> {" << std::endl; + stream << " if" << std::endl; + stream << " :: " << _prefix << "transitions[j].target[k] -> {" << std::endl; + bit_or(stream, "entry_set", _prefix + "states[k].ancestors", _states.size(), 11); + stream << " break;" << std::endl; + stream << std::endl; + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> break;" << std::endl; + stream << " od" << std::endl; + stream << " trans_set[j] = true;" << std::endl; + stream << " break;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi" << std::endl; + + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi" << std::endl; + stream << " j = j + 1;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> break" << std::endl; + stream << " od" << std::endl; + stream << " skip;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> {" << std::endl; + bit_copy(stream, "tmp_states", _prefix + "states[i].completion", _states.size(), 5); + bit_and(stream, "tmp_states", _prefix + "history", _states.size(), 5); + bit_or(stream, "entry_set", "tmp_states", _states.size(), 5); + stream << " if" << std::endl; + stream << " :: " << _prefix << "states[i].type[USCXML_STATE_HAS_HISTORY] ||" << std::endl; + stream << " " << _prefix << "states[i].type[USCXML_STATE_HISTORY_DEEP] -> { " << std::endl; + stream << " /* a deep history state with nested histories -> more completion */" << std::endl; + stream << " j = i + 1;" << std::endl; + stream << " do" << std::endl; + stream << " :: j < USCXML_NUMBER_STATES -> {" << std::endl; + stream << " if" << std::endl; + stream << " :: (" << _prefix << "states[i].completion[j] &&" << std::endl; + stream << " entry_set[j] && " << std::endl; + stream << " " << _prefix << "states[j].type[USCXML_STATE_HAS_HISTORY]) -> {" << std::endl; + stream << " k = j + 1;" << std::endl; + stream << " do" << std::endl; + stream << " :: k < USCXML_NUMBER_STATES -> {" << std::endl; + stream << " /* add nested history to entry_set */" << std::endl; + stream << " k = k + 1;" << std::endl; + stream << " if" << std::endl; + stream << " :: (" << _prefix << "states[k].type[USCXML_STATE_HISTORY_DEEP] ||" << std::endl; + stream << " " << _prefix << "states[k].type[USCXML_STATE_HISTORY_SHALLOW]) &&" << std::endl; + stream << " " << _prefix << "states[j].children[k] -> {" << std::endl; + stream << " /* a nested history state */" << std::endl; + stream << " entry_set[k] = true;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> break;" << std::endl; + stream << " od" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> break;" << std::endl; + stream << " od" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi" << std::endl; + + stream << " }" << std::endl; + stream << " fi;" << std::endl; + + stream << " }" << std::endl; + +#if 0 + stream << " case USCXML_STATE_INITIAL: {" << std::endl; + stream << " for (j = 0; j < USCXML_NUMBER_TRANS; j++) {" << std::endl; + stream << " if (ctx->machine->transitions[j].source == i) {" << std::endl; + stream << " BIT_SET_AT(j, trans_set);" << std::endl; + stream << " BIT_CLEAR(i, entry_set);" << std::endl; + stream << " bit_or(entry_set, ctx->machine->transitions[j].target, nr_states_bytes);" << std::endl; + stream << " for (k = i + 1; k < USCXML_NUMBER_STATES; k++) {" << std::endl; + stream << " if (BIT_HAS(k, ctx->machine->transitions[j].target)) {" << std::endl; + stream << " bit_or(entry_set, ctx->machine->states[k].ancestors, nr_states_bytes);" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " break;" << std::endl; + stream << " }" << std::endl; +#endif + + stream << " :: " << _prefix << "states[i].type[USCXML_STATE_INITIAL] -> {" << std::endl; + stream << " j = 0" << std::endl; + stream << " do" << std::endl; + stream << " :: j < USCXML_NUMBER_TRANS -> {" << std::endl; + stream << " if" << std::endl; + stream << " :: " << _prefix << "transitions[j].source == i -> {" << std::endl; + stream << " trans_set[j] = true;" << std::endl; + stream << " entry_set[i] = false;" << std::endl; + + bit_or(stream, "entry_set", _prefix + "transitions[j].target", _states.size(), 6); + stream << std::endl; + + stream << " k = i + 1;" << std::endl; + stream << " do" << std::endl; + stream << " :: k < USCXML_NUMBER_STATES -> {" << std::endl; + stream << " if" << std::endl; + stream << " :: " << _prefix << "transitions[j].target[k] -> {" << std::endl; + + bit_or(stream, "entry_set", _prefix + "states[k].ancestors", _states.size(), 8); + stream << std::endl; + + stream << " }" << std::endl; + stream << " :: else -> break;" << std::endl; + stream << " fi" << std::endl; + stream << " k = k + 1;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> break" << std::endl; + stream << " od" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> break;" << std::endl; + stream << " fi" << std::endl; + stream << " j = j + 1;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> break" << std::endl; + stream << " od;" << std::endl; + + stream << " }" << std::endl; + + +#if 0 + stream << " case USCXML_STATE_COMPOUND: { /* we need to check whether one child is already in entry_set */" << std::endl; + stream << " if (!bit_has_and(entry_set, USCXML_GET_STATE(i).children, nr_states_bytes) &&" << std::endl; + stream << " (!bit_has_and(ctx->config, USCXML_GET_STATE(i).children, nr_states_bytes) ||" << std::endl; + stream << " bit_has_and(exit_set, USCXML_GET_STATE(i).children, nr_states_bytes)))" << std::endl; + stream << " {" << std::endl; + stream << " bit_or(entry_set, USCXML_GET_STATE(i).completion, nr_states_bytes);" << std::endl; + stream << " if (!bit_has_and(USCXML_GET_STATE(i).completion, USCXML_GET_STATE(i).children, nr_states_bytes)) {" << std::endl; + stream << " /* deep completion */" << std::endl; + stream << " for (j = i + 1; j < USCXML_NUMBER_STATES; j++) {" << std::endl; + stream << " if (BIT_HAS(j, USCXML_GET_STATE(i).completion)) {" << std::endl; + stream << " bit_or(entry_set, ctx->machine->states[j].ancestors, nr_states_bytes);" << std::endl; + stream << " break; /* completion of compound is single state */" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " break;" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << std::endl; +#endif + + stream << " :: " << _prefix << "states[i].type[USCXML_STATE_COMPOUND] -> {" << std::endl; + + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Descendant completion for compound state %d\\n\", i);" << std::endl; + stream << "#endif" << std::endl; + + stream << " /* we need to check whether one child is already in entry_set */" << std::endl; + stream << " if" << std::endl; + stream << " :: (" << std::endl; + stream << " !"; + bit_has_and(stream, "entry_set", _prefix + "states[i].children", _states.size(), 5); + stream << " && " << std::endl; + stream << " (!"; + bit_has_and(stream, _prefix + "config", _prefix + "states[i].children", _states.size(), 5); + stream << " || " << std::endl; + bit_has_and(stream, "exit_set", _prefix + "states[i].children", _states.size(), 5); + stream << ")) "<< std::endl; + stream << " -> {" << std::endl; + + bit_or(stream, "entry_set", _prefix + "states[i].completion", _states.size(), 5); + + stream << " if" << std::endl; + stream << " :: ("; + bit_has_and(stream, _prefix + "states[i].completion", _prefix + "states[i].children", _states.size(), 5); + stream << std::endl; + stream << " ) -> {" << std::endl; + stream << " /* deep completion */" << std::endl; + stream << " j = i + 1;" << std::endl; + stream << " do" << std::endl; + stream << " :: j < USCXML_NUMBER_STATES - 1 -> {" << std::endl; + stream << " j = j + 1;" << std::endl; + stream << " if" << std::endl; + stream << " :: " << _prefix << "states[i].completion[j] -> {" << std::endl; + + bit_or(stream, "entry_set", _prefix + "states[j].ancestors", _states.size(), 9); + stream << std::endl; + + stream << " /* completion of compound is single state */" << std::endl; + stream << " break;" << std::endl; + stream << " } " << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> break;" << std::endl; + stream << " od" << std::endl; + + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi" << std::endl; + + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi" << std::endl; + stream << " }" << std::endl; + + stream << " :: else -> skip;" << std::endl; + stream << " fi;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi;" << std::endl; + stream << " i = i + 1;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> break;" << std::endl; + stream << " od;" << std::endl; + stream << std::endl; + +#if 0 + stream << "/* EXIT_STATES: */" << std::endl; + stream << " i = USCXML_NUMBER_STATES;" << std::endl; + stream << " while(i-- > 0) {" << std::endl; + stream << " if (BIT_HAS(i, exit_set) && BIT_HAS(i, ctx->config)) {" << std::endl; + stream << " /* call all on exit handlers */" << std::endl; + stream << " if (USCXML_GET_STATE(i).on_exit != NULL) {" << std::endl; + stream << " if unlikely((err = USCXML_GET_STATE(i).on_exit(ctx, &USCXML_GET_STATE(i), ctx->event)) != USCXML_ERR_OK)" << std::endl; + stream << " return err;" << std::endl; + stream << " }" << std::endl; + stream << " BIT_CLEAR(i, ctx->config);" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << std::endl; +#endif + + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Entry Set (after descendant completion)\");" << std::endl; + printBitArray(stream, "entry_set", _states.size()); + stream << "printf(\"\\n\");" << std::endl; + stream << "#endif" << std::endl; + + stream << "/* ---------------------------- */" << std::endl; + stream << "/* EXIT_STATES: */" << std::endl; + stream << " i = USCXML_NUMBER_STATES;" << std::endl; + stream << " do" << std::endl; + stream << " :: i > 0 -> {" << std::endl; + stream << " i = i - 1;" << std::endl; + stream << " if" << std::endl; + stream << " :: exit_set[i] && " << _prefix << "config[i] -> {" << std::endl; + stream << " /* call all on-exit handlers */" << std::endl; + + stream << " if" << std::endl; + for (auto i = 0; i < _states.size(); i++) { + std::list<DOMElement*> onentries = DOMUtils::filterChildElements(XML_PREFIX(_states[i]).str() + "onexit" , _states[i]); + if (onentries.size() > 0) { + stream << " :: i == " << toStr(i) << " -> {" << std::endl; + for (auto onentry : onentries) + writeExecContent(stream, onentry, 3); + stream << " }" << std::endl; + } + } + stream << " :: else ->skip;" << std::endl; + stream << " fi" << std::endl; + stream << std::endl; + + + stream << " " << _prefix << "config[i] = false;" << std::endl; + stream << " skip;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> break;" << std::endl; + stream << " od;" << std::endl; + stream << std::endl; + + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Exited States\\n\");" << std::endl; + stream << "#endif" << std::endl; + +#if 0 + stream << "/* TAKE_TRANSITIONS: */" << std::endl; + stream << " for (i = 0; i < USCXML_NUMBER_TRANS; i++) {" << std::endl; + stream << " if (BIT_HAS(i, trans_set) && (USCXML_GET_TRANS(i).type & (USCXML_TRANS_HISTORY | USCXML_TRANS_INITIAL)) == 0) {" << std::endl; + stream << " /* call executable content in transition */" << std::endl; + stream << " if (USCXML_GET_TRANS(i).on_transition != NULL) {" << std::endl; + stream << " if unlikely((err = USCXML_GET_TRANS(i).on_transition(ctx," << std::endl; + stream << " &ctx->machine->states[USCXML_GET_TRANS(i).source]," << std::endl; + stream << " ctx->event)) != USCXML_ERR_OK)" << std::endl; + stream << " return err;" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << std::endl; +#endif + + stream << "/* ---------------------------- */" << std::endl; + stream << "/* TAKE_TRANSITIONS: */" << std::endl; + stream << " i = 0;" << std::endl; + stream << " do" << std::endl; + stream << " :: i < USCXML_NUMBER_TRANS -> {" << std::endl; + stream << " if" << std::endl; + stream << " :: trans_set[i] && " << std::endl; + stream << " !" << _prefix << "transitions[i].type[USCXML_TRANS_HISTORY] && " << std::endl; + stream << " !" << _prefix << "transitions[i].type[USCXML_TRANS_INITIAL] -> {" << std::endl; + stream << " /* Call executable content in normal transition */" << std::endl; + stream << " if" << std::endl; + for (auto i = 0; i < _transitions.size(); i++) { + stream << " :: i == " << toStr(i) << " -> {" << std::endl; + writeExecContent(stream, _transitions[i], 4); + stream << " skip;" << std::endl; + stream << " }" << std::endl; + } + stream << " :: else ->skip;" << std::endl; + stream << " fi" << std::endl; + stream << std::endl; + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi;" << std::endl; + stream << " i = i + 1;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> break;" << std::endl; + stream << " od;" << std::endl; + stream << std::endl; + + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Took Transitions\\n\");" << std::endl; + stream << "#endif" << std::endl; + +#if 0 + stream << "/* ENTER_STATES: */" << std::endl; + stream << " for (i = 0; i < USCXML_NUMBER_STATES; i++) {" << std::endl; + stream << " if (BIT_HAS(i, entry_set) && !BIT_HAS(i, ctx->config)) {" << std::endl; + stream << " /* these are no proper states */" << std::endl; + stream << " if unlikely(USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_HISTORY_DEEP ||" << std::endl; + stream << " USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_HISTORY_SHALLOW ||" << std::endl; + stream << " USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_INITIAL)" << std::endl; + stream << " continue;" << std::endl; + stream << std::endl; +#endif + + stream << "/* ---------------------------- */" << std::endl; + stream << "/* ENTER_STATES: */" << std::endl; + stream << " i = 0;" << std::endl; + stream << " do" << std::endl; + stream << " :: i < USCXML_NUMBER_STATES -> {" << std::endl; + stream << " if" << std::endl; + stream << " :: (entry_set[i] &&" << std::endl; + stream << " !" << _prefix << "config[i] && " << std::endl; + stream << " /* these are no proper states */" << std::endl; + stream << " !" << _prefix << "states[i].type[USCXML_STATE_HISTORY_DEEP] && " << std::endl; + stream << " !" << _prefix << "states[i].type[USCXML_STATE_HISTORY_SHALLOW] && " << std::endl; + stream << " !" << _prefix << "states[i].type[USCXML_STATE_INITIAL]" << std::endl; + stream << " ) -> {" << std::endl; + +#if 0 + stream << " BIT_SET_AT(i, ctx->config);" << std::endl; + stream << std::endl; +#endif + + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Entering State %d\\n\", i);" << std::endl; + stream << "#endif" << std::endl; + + stream << " " << _prefix << "config[i] = true;" << std::endl; + stream << std::endl; + + +#if 0 + stream << " /* initialize data */" << std::endl; + stream << " if (!BIT_HAS(i, ctx->initialized_data)) {" << std::endl; + stream << " if unlikely(USCXML_GET_STATE(i).data != NULL && ctx->exec_content_init != NULL) {" << std::endl; + stream << " ctx->exec_content_init(ctx, USCXML_GET_STATE(i).data);" << std::endl; + stream << " }" << std::endl; + stream << " BIT_SET_AT(i, ctx->initialized_data);" << std::endl; + stream << " }" << std::endl; + stream << std::endl; + +#endif + + stream << " if" << std::endl; + stream << " :: !" << _prefix << "initialized_data[i] -> {" << std::endl; + stream << " /* TODO: late data binding not supported yet */" << std::endl; + stream << " " << _prefix << "initialized_data[i] = true;" << std::endl; + stream << " skip" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi" << std::endl; + stream << std::endl; + +#if 0 + stream << " if (USCXML_GET_STATE(i).on_entry != NULL) {" << std::endl; + stream << " if unlikely((err = USCXML_GET_STATE(i).on_entry(ctx, &USCXML_GET_STATE(i), ctx->event)) != USCXML_ERR_OK)" << std::endl; + stream << " return err;" << std::endl; + stream << " }" << std::endl; + stream << std::endl; + +#endif + + stream << " /* Process executable content for entering a state */" << std::endl; + stream << " if" << std::endl; + for (auto i = 0; i < _states.size(); i++) { + std::list<DOMElement*> onentries = DOMUtils::filterChildElements(XML_PREFIX(_states[i]).str() + "onentry" , _states[i]); + if (onentries.size() > 0) { + stream << " :: i == " << toStr(i) << " -> {" << std::endl; + for (auto onentry : onentries) + writeExecContent(stream, onentry, 5); + stream << " }" << std::endl; + } + } + stream << " :: else ->skip;" << std::endl; + stream << " fi" << std::endl; + stream << std::endl; + +#if 0 + stream << " /* take history and initial transitions */" << std::endl; + stream << " for (j = 0; j < USCXML_NUMBER_TRANS; j++) {" << std::endl; + stream << " if unlikely(BIT_HAS(j, trans_set) &&" << std::endl; + stream << " (ctx->machine->transitions[j].type & (USCXML_TRANS_HISTORY | USCXML_TRANS_INITIAL)) &&" << std::endl; + stream << " ctx->machine->states[ctx->machine->transitions[j].source].parent == i) {" << std::endl; + stream << " /* call executable content in transition */" << std::endl; + stream << " if (ctx->machine->transitions[j].on_transition != NULL) {" << std::endl; + stream << " if unlikely((err = ctx->machine->transitions[j].on_transition(ctx," << std::endl; + stream << " &USCXML_GET_STATE(i)," << std::endl; + stream << " ctx->event)) != USCXML_ERR_OK)" << std::endl; + stream << " return err;" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << std::endl; + +#endif + + stream << " /* take history and initial transitions */" << std::endl; + stream << " j = 0;" << std::endl; + stream << " do" << std::endl; + stream << " :: j < USCXML_NUMBER_TRANS -> {" << std::endl; + stream << " if" << std::endl; + stream << " :: (trans_set[j] &&" << std::endl; + stream << " (" << _prefix << "transitions[j].type[USCXML_TRANS_HISTORY] ||" << std::endl; + stream << " " << _prefix << "transitions[j].type[USCXML_TRANS_INITIAL]) && " << std::endl; + stream << " " << _prefix << "states[" << _prefix << "transitions[j].source].parent == i) -> {" << std::endl; + stream << " /* Call executable content in history or initial transition */" << std::endl; + stream << " if" << std::endl; + for (auto i = 0; i < _transitions.size(); i++) { + stream << " :: j == " << toStr(i) << " -> {" << std::endl; + writeExecContent(stream, _transitions[i], 8); + stream << " skip;" << std::endl; + stream << " }" << std::endl; + } + stream << " :: else ->skip;" << std::endl; + stream << " fi" << std::endl; + stream << std::endl; + + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi" << std::endl; + stream << " j = j + 1;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> break;" << std::endl; + stream << " od" << std::endl; + + +#if 0 + stream << " /* handle final states */" << std::endl; + stream << " if unlikely(USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_FINAL) {" << std::endl; +#endif + + stream << " /* handle final states */" << std::endl; + stream << " if" << std::endl; + stream << " :: " << _prefix << "states[i].type[USCXML_STATE_FINAL] -> {" << std::endl; + + +#if 0 + stream << " if unlikely(USCXML_GET_STATE(i).ancestors[0] == 0x01) {" << std::endl; + stream << " ctx->flags |= USCXML_CTX_TOP_LEVEL_FINAL;" << std::endl; + stream << " } else {" << std::endl; + stream << " /* raise done event */" << std::endl; + stream << " const uscxml_elem_donedata* donedata = &ctx->machine->donedata[0];" << std::endl; + stream << " while(USCXML_ELEM_DONEDATA_IS_SET(donedata)) {" << std::endl; + stream << " if unlikely(donedata->source == i)" << std::endl; + stream << " break;" << std::endl; + stream << " donedata++;" << std::endl; + stream << " }" << std::endl; + stream << " ctx->raise_done_event(ctx, &ctx->machine->states[USCXML_GET_STATE(i).parent], (USCXML_ELEM_DONEDATA_IS_SET(donedata) ? donedata : NULL));" << std::endl; + stream << " }" << std::endl; +#endif + + stream << " if" << std::endl; + stream << " :: " << _prefix << "states[" << _prefix << "states[i].parent].children[1] -> {" << std::endl; + stream << " " << _prefix << "flags[USCXML_CTX_TOP_LEVEL_FINAL] = true;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> {" << std::endl; + stream << " /* TODO: raise done event */" << std::endl; + stream << " skip;" << std::endl; + stream << " }" << std::endl; + stream << " fi" << std::endl; + + +#if 0 + stream << std::endl; + stream << " /**" << std::endl; + stream << " * are we the last final state to leave a parallel state?:" << std::endl; + stream << " * 1. Gather all parallel states in our ancestor chain" << std::endl; + stream << " * 2. Find all states for which these parallels are ancestors" << std::endl; + stream << " * 3. Iterate all active final states and remove their ancestors" << std::endl; + stream << " * 4. If a state remains, not all children of a parallel are final" << std::endl; + stream << " */" << std::endl; + stream << " for (j = 0; j < USCXML_NUMBER_STATES; j++) {" << std::endl; + stream << " if unlikely(USCXML_STATE_MASK(ctx->machine->states[j].type) == USCXML_STATE_PARALLEL &&" << std::endl; + stream << " BIT_HAS(j, USCXML_GET_STATE(i).ancestors)) {" << std::endl; + stream << " bit_clear_all(tmp_states, nr_states_bytes);" << std::endl; + stream << " for (k = 0; k < USCXML_NUMBER_STATES; k++) {" << std::endl; + stream << " if unlikely(BIT_HAS(j, ctx->machine->states[k].ancestors) && BIT_HAS(k, ctx->config)) {" << std::endl; + stream << " if (USCXML_STATE_MASK(ctx->machine->states[k].type) == USCXML_STATE_FINAL) {" << std::endl; + stream << " bit_and_not(tmp_states, ctx->machine->states[k].ancestors, nr_states_bytes);" << std::endl; + stream << " } else {" << std::endl; + stream << " BIT_SET_AT(k, tmp_states);" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " if unlikely(!bit_has_any(tmp_states, nr_states_bytes)) {" << std::endl; + stream << " ctx->raise_done_event(ctx, &ctx->machine->states[j], NULL);" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << " }" << std::endl; + stream << std::endl; + + stream << " return USCXML_ERR_OK;" << std::endl; + stream << "}" << std::endl; + stream << std::endl; + stream << std::endl; +#endif + + stream << " /** TODO:" << std::endl; + stream << " * are we the last final state to leave a parallel state?:" << std::endl; + stream << " * 1. Gather all parallel states in our ancestor chain" << std::endl; + stream << " * 2. Find all states for which these parallels are ancestors" << std::endl; + stream << " * 3. Iterate all active final states and remove their ancestors" << std::endl; + stream << " * 4. If a state remains, not all children of a parallel are final" << std::endl; + stream << " */" << std::endl; + + + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi" << std::endl; + + stream << "" << std::endl; + + stream << " }" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " i = i + 1;" << std::endl; + stream << " fi;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> break;" << std::endl; + stream << " od;" << std::endl; + stream << std::endl; + + stream << "#if TRACE_EXECUTION" << std::endl; + stream << "printf(\"Done\\n\");" << std::endl; + stream << "#endif" << std::endl; + + stream << "}" << std::endl; + stream << ":: else -> break;" << std::endl; + stream << "od" << std::endl; + + + stream << "} }" << std::endl; + stream << std::endl; + +} + +#if 0 + +void ChartToPromela::writeProgram(std::ostream& stream) { + + _traceTransitions = envVarIsTrue("USCXML_PROMELA_TRANSITION_TRACE"); + _writeTransitionPrintfs = envVarIsTrue("USCXML_PROMELA_TRANSITION_DEBUG"); + + if (!HAS_ATTR(_scxml, "datamodel") || ATTR(_scxml, "datamodel") != "promela") { + LOG(ERROR) << "Can only convert SCXML documents with \"promela\" datamodel"; + return; + } + + if (HAS_ATTR(_scxml, "binding") && ATTR(_scxml, "binding") != "early") { + LOG(ERROR) << "Can only convert for early data bindings"; + return; + } + + // std::cerr << _scxml << std::endl; + + stream << "/* " << (std::string)_baseURL << " */" << std::endl; + stream << std::endl; + + initNodes(); + + for (std::map<Arabica::DOM::Node<std::string>, ChartToPromela*>::iterator nestedIter = _machines.begin(); nestedIter != _machines.end(); nestedIter++) { + if (nestedIter->second->_start == NULL) { + nestedIter->second->interpret(); + } + nestedIter->second->initNodes(); + } + + writeEvents(stream); + stream << std::endl; + writeStates(stream); + stream << std::endl; + writeStrings(stream); + stream << std::endl; + if (_analyzer->usesInPredicate()) { + writeStateMap(stream); + stream << std::endl; + } + if (_historyMembers.size() > 0) { + writeHistoryArrays(stream); + stream << std::endl; + } + writeTypeDefs(stream); + stream << std::endl; + writeDeclarations(stream); + stream << std::endl; + + for (std::map<Arabica::DOM::Node<std::string>, ChartToPromela*>::iterator nestedIter = _machines.begin(); nestedIter != _machines.end(); nestedIter++) { + nestedIter->second->writeDeclarations(stream); + stream << std::endl; + } + + stream << std::endl << "/* global inline functions */" << std::endl; + + if (_analyzer->usesComplexEventStruct()) { + stream << "hidden _event_t tmpE;" << std::endl; + } else { + stream << "hidden int tmpE;" << std::endl; + } + stream << "hidden int tmpIndex;" << std::endl; + + +#if NEW_DELAY_RESHUFFLE + if (_analyzer->usesEventField("delay")) { + writeInsertWithDelay(stream); + stream << std::endl; + } +#endif + + if (_analyzer->usesEventField("delay") && _machines.size() > 0) { + writeDetermineShortestDelay(stream); + stream << std::endl; + writeAdvanceTime(stream); + stream << std::endl; + writeRescheduleProcess(stream); + stream << std::endl; + writeScheduleMachines(stream); + stream << std::endl; + } + + { + NodeSet<std::string> cancels = DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "cancel", _scxml, true); + if (cancels.size() > 0) { + writeCancelEvents(stream); + stream << std::endl; + } + } + { + NodeSet<std::string> invokes = DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "invoke", _scxml, true); + if (invokes.size() > 0 && _analyzer->usesEventField("delay")) { + writeRemovePendingEventsFromInvoker(stream); + stream << std::endl; + } + + } + stream << std::endl; + writeEventSources(stream); + stream << std::endl; + writeFSM(stream); + stream << std::endl; + writeMain(stream); + stream << std::endl; + + for (std::map<Arabica::DOM::Node<std::string>, ChartToPromela*>::iterator nestedIter = _machines.begin(); nestedIter != _machines.end(); nestedIter++) { + nestedIter->second->writeFSM(stream); + stream << std::endl; + } + + // write ltl expression for success + std::stringstream acceptingStates; + std::string seperator; + + for (std::map<std::string, GlobalState*>::iterator stateIter = _activeConf.begin(); stateIter != _activeConf.end(); stateIter++) { + FlatStateIdentifier flatId(stateIter->first); + if (std::find(flatId.getActive().begin(), flatId.getActive().end(), "pass") != flatId.getActive().end()) { + acceptingStates << seperator << _prefix << "s == s" << stateIter->second->activeIndex; + seperator = " || "; + } + } + if (acceptingStates.str().size() > 0) { + stream << "ltl { eventually (" << acceptingStates.str() << ") }" << std::endl; + } +} +#endif + +void ChartToPromela::writeIfBlock(std::ostream& stream, std::list<DOMElement*>& condChain, size_t indent) { + if (condChain.size() == 0) + return; + + std::string padding; + for (size_t i = 0; i < indent; i++) { + padding += " "; + } + + bool noNext = condChain.size() == 1; + bool nextIsElse = false; + + DOMElement* ifNode = condChain.front(); + condChain.pop_front(); + + if (condChain.size() > 0) { + if (TAGNAME_CAST(condChain.front()) == "else") { + nextIsElse = true; + } + } + + stream << padding << "if" << std::endl; + // we need to nest the elseifs to resolve promela if semantics + stream << padding << ":: (" << ADAPT_SRC(ATTR(ifNode, "cond")) << ") -> {" << std::endl; + + DOMNode* child; + if (TAGNAME(ifNode) == "if") { + child = ifNode->getFirstChild(); + } else { + child = ifNode->getNextSibling(); + } + while(child) { + if (child->getNodeType() == DOMNode::ELEMENT_NODE) { + DOMElement* childElem = static_cast<DOMElement*>(child); + if (TAGNAME(childElem) == "elseif" || TAGNAME_CAST(childElem) == "else") + break; + writeExecContent(stream, childElem, indent + 1); + } + child = child->getNextSibling(); + } + stream << padding << "}" << std::endl; + stream << padding << ":: else -> "; + + if (nextIsElse) { + child = condChain.front()->getNextSibling(); + stream << "{" << std::endl; + while(child) { + if (child->getNodeType() == DOMNode::ELEMENT_NODE) { + writeExecContent(stream, child, indent + 1); + } + child = child->getNextSibling(); + } + stream << padding << "}" << std::endl; + + } else if (noNext) { + stream << "skip;" << std::endl; + } else { + stream << "{" << std::endl; + writeIfBlock(stream, condChain, indent + 1); + stream << padding << "}" << std::endl; + } + + stream << padding << "fi;" << std::endl; + +} + +std::string ChartToPromela::beautifyIndentation(const std::string& code, size_t indent) { + + std::string padding; + for (size_t i = 0; i < indent; i++) { + padding += " "; + } + + // remove topmost indentation from every line and reindent + std::stringstream beautifiedSS; + + std::string initialIndent; + bool gotIndent = false; + bool isFirstLine = true; + std::stringstream ssLine(code); + std::string line; + + while(std::getline(ssLine, line)) { + size_t firstChar = line.find_first_not_of(" \t\r\n"); + if (firstChar != std::string::npos) { + if (!gotIndent) { + initialIndent = line.substr(0, firstChar); + gotIndent = true; + } + beautifiedSS << (isFirstLine ? "" : "\n") << padding << boost::replace_first_copy(line, initialIndent, ""); + isFirstLine = false; + } + } + + return beautifiedSS.str(); +} + +std::string ChartToPromela::dataToAssignments(const std::string& prefix, const Data& data) { + std::stringstream retVal; + if (data.atom.size() > 0) { + if (data.type == Data::VERBATIM) { + retVal << prefix << " = " << _analyzer.macroForLiteral(data.atom) << ";" << std::endl; + } else { + retVal << prefix << " = " << data.atom << ";" << std::endl; + } + } else if (data.compound.size() > 0) { + for (std::map<std::string, Data>::const_iterator cIter = data.compound.begin(); cIter != data.compound.end(); cIter++) { + retVal << dataToAssignments(prefix + "." + cIter->first, cIter->second); + } + } else if (data.array.size() > 0) { + size_t index = 0; + for(std::list<Data>::const_iterator aIter = data.array.begin(); aIter != data.array.end(); aIter++) { + retVal << dataToAssignments(prefix + "[" + toStr(index) + "]", *aIter); + index++; + } + } + return retVal.str(); +} + +std::string ChartToPromela::sanitizeCode(const std::string& code) { + std::string replaced = code; + boost::replace_all(replaced, "\"", "'"); + boost::replace_all(replaced, "_sessionid", "_SESSIONID"); + boost::replace_all(replaced, "_name", "_NAME"); + return replaced; +} + +std::string ChartToPromela::declForRange(const std::string& identifier, long minValue, long maxValue, bool nativeOnly) { + // return "int " + identifier; // just for testing + + // we know nothing about this type + if (minValue == 0 && maxValue == 0) + return "int " + identifier; + + if (minValue < 0) { + // only short or int for negatives + if (minValue < -32769 || maxValue > 32767) + return "int " + identifier; + return "short " + identifier; + } + + // type is definitely positive + if (nativeOnly) { + if (maxValue > 32767) + return "int " + identifier; + if (maxValue > 255) + return "short " + identifier; + if (maxValue > 1) + return "byte " + identifier; + return "bool " + identifier; + } else { + return "unsigned " + identifier + " : " + toStr(BIT_WIDTH(maxValue)); + } +} + +void ChartToPromela::writeCancelEvents(std::ostream& stream, int indent) { + std::list<std::string> queues; + queues.push_back("eQ"); + if (_allowEventInterleaving) + queues.push_back("tmpQ"); + + stream << "inline cancelSendId(sendIdentifier, invokerIdentifier) {" << std::endl; + for (auto machine : *_machinesAll) { + for (auto queue : queues) { + stream << " cancelSendIdOnQueue(sendIdentifier, " << machine.second->_prefix << queue << ", invokerIdentifier);" << std::endl; + } + } + stream << "}" << std::endl; + stream << std::endl; + + + stream << "inline cancelSendIdOnQueue(sendIdentifier, queue, invokerIdentifier) {" << std::endl; + stream << " tmpIndex = 0;" << std::endl; + // stream << _analyzer->getTypeReset("tmpE", _analyzer->getType("_event"), " "); + stream << " do" << std::endl; + stream << " :: tmpIndex < len(queue) -> {" << std::endl; + stream << " queue?tmpE;" << std::endl; + stream << " if" << std::endl; + stream << " :: tmpE.invokeid != invokerIdentifier || tmpE.sendid != sendIdentifier || tmpE.delay == 0 -> queue!tmpE;" << std::endl; + stream << " :: else -> skip;" << std::endl; + stream << " fi" << std::endl; + stream << " tmpIndex++;" << std::endl; + stream << " }" << std::endl; + stream << " :: else -> break;" << std::endl; + stream << " od" << std::endl; + stream << "}" << std::endl; +} + + +} diff --git a/src/uscxml/transform/ChartToPromela.h b/src/uscxml/transform/ChartToPromela.h new file mode 100644 index 0000000..cfba760 --- /dev/null +++ b/src/uscxml/transform/ChartToPromela.h @@ -0,0 +1,130 @@ +/** + * @file + * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see <http://www.opensource.org/licenses/bsd-license>. + * @endcond + */ + +#ifndef CHARTTOPROMELA_H_RP48RFDJ +#define CHARTTOPROMELA_H_RP48RFDJ + +#include "Transformer.h" +#include "ChartToC.h" +#include "uscxml/util/DOM.h" + +#include "promela/PromelaInlines.h" +#include "promela/PromelaCodeAnalyzer.h" + +#include <ostream> + +namespace uscxml { + +class USCXML_API ChartToPromela : public ChartToC { +public: + virtual ~ChartToPromela(); + static Transformer transform(const Interpreter& other); + + void writeTo(std::ostream& stream); + +protected: + ChartToPromela(const Interpreter& other) : ChartToC(other) { + _prefix = "U" + _md5.substr(0, 8) + "_"; + } + + void writeTransitions(std::ostream& stream); + void writeStates(std::ostream& stream); + void writeTypeDefs(std::ostream& stream); + void writeTypes(std::ostream& stream); + void writeMacros(std::ostream& stream); + void writeHelpers(std::ostream& stream); + void writeFSM(std::ostream& stream); + void writeExecContent(std::ostream& stream, const XERCESC_NS::DOMNode* node, size_t indent = 0); + void writeStrings(std::ostream& stream); + + void writeCancelEvents(std::ostream& stream, int indent = 0); + + void prepare(); + + void bit_clear_all(std::ostream& stream, + const std::string& identifier, + size_t length, + size_t indent = 0); + + void bit_copy(std::ostream& stream, + const std::string& from, + const std::string& to, + size_t length, + size_t indent = 0); + + void bit_or(std::ostream& stream, + const std::string& to, + const std::string& mask, + size_t length, + size_t indent = 0); + + void bit_and(std::ostream& stream, + const std::string& to, + const std::string& mask, + size_t length, + size_t indent = 0); + + void bit_and_not(std::ostream& stream, + const std::string& to, + const std::string& mask, + size_t length, + size_t indent = 0); + + void bit_has_and(std::ostream& stream, + const std::string& a, + const std::string& b, + size_t length, + size_t indent = 0); + + void printBitArray(std::ostream& stream, + const std::string& array, + size_t length, + size_t indent = 0); + + PromelaCodeAnalyzer _analyzer; + + ChartToPromela* _parentTopMost; + ChartToPromela* _parent; + std::string _invokerid; + + size_t _internalQueueLength = 7; + size_t _externalQueueLength = 7; + bool _allowEventInterleaving = false; + + std::map<std::string, XERCESC_NS::DOMNode* > _machinesPerId; + std::map<std::string, XERCESC_NS::DOMNode* >* _machinesAllPerId = NULL; + std::map<XERCESC_NS::DOMNode*, ChartToPromela*> _machines; + std::map<XERCESC_NS::DOMNode*, ChartToPromela*>* _machinesAll = NULL; + + std::set<std::string> _dataModelVars; + std::list<std::string> _varInitializers; // pending initializations for arrays + + std::string beautifyIndentation(const std::string& code, size_t indent = 0); + void writeIfBlock(std::ostream& stream, std::list<XERCESC_NS::DOMElement*>& condChain, size_t indent = 0); + + std::string dataToAssignments(const std::string& prefix, const Data& data); + std::string sanitizeCode(const std::string& code); + std::string declForRange(const std::string& identifier, long minValue, long maxValue, bool nativeOnly = false); + + friend class PromelaCodeAnalyzer; +}; + +} + +#endif /* end of include guard: CHARTTOPROMELA_H_RP48RFDJ */ diff --git a/src/uscxml/transform/ChartToVHDL.cpp b/src/uscxml/transform/ChartToVHDL.cpp index a9fb49d..13e8120 100644 --- a/src/uscxml/transform/ChartToVHDL.cpp +++ b/src/uscxml/transform/ChartToVHDL.cpp @@ -40,9 +40,9 @@ namespace uscxml { using namespace XERCESC_NS; Transformer ChartToVHDL::transform(const Interpreter& other) { - ChartToVHDL* c2c = new ChartToVHDL(other); + ChartToVHDL* c2c = new ChartToVHDL(other); - return std::shared_ptr<TransformerImpl>(c2c); + return std::shared_ptr<TransformerImpl>(c2c); } ChartToVHDL::ChartToVHDL(const Interpreter& other) : ChartToC(other), _eventTrie(".") { @@ -52,1383 +52,1383 @@ ChartToVHDL::~ChartToVHDL() { } void ChartToVHDL::checkDocument() { - // filter unsupported stuff - std::list<DOMElement*> unsupported; - unsupported = DOMUtils::inDocumentOrder({ - XML_PREFIX(_scxml).str() + "datamodel", - XML_PREFIX(_scxml).str() + "data", - XML_PREFIX(_scxml).str() + "assign", - XML_PREFIX(_scxml).str() + "donedata", - XML_PREFIX(_scxml).str() + "content", - XML_PREFIX(_scxml).str() + "param", - XML_PREFIX(_scxml).str() + "script", - XML_PREFIX(_scxml).str() + "parallel", - XML_PREFIX(_scxml).str() + "history", - XML_PREFIX(_scxml).str() + "if", - XML_PREFIX(_scxml).str() + "foreach", - XML_PREFIX(_scxml).str() + "send", - XML_PREFIX(_scxml).str() + "cancel", - XML_PREFIX(_scxml).str() + "invoke", - XML_PREFIX(_scxml).str() + "finalize" - }, _scxml); - - std::stringstream ss; - if (unsupported.size() > 0) { - for (auto elem : unsupported) { - ss << " " << DOMUtils::xPathForNode(elem) << " unsupported" << std::endl; - } - throw std::runtime_error("Unsupported elements found:\n" + ss.str()); - } - - unsupported = DOMUtils::inDocumentOrder({ XML_PREFIX(_scxml).str() + "transition" }, _scxml); - - for (auto transition : unsupported) { - if (HAS_ATTR(transition, "cond")) { - ERROR_PLATFORM_THROW("transition with conditions not supported!"); - } - if (!HAS_ATTR(transition, "target")) { - ERROR_PLATFORM_THROW("targetless transition not supported!"); - } - } + // filter unsupported stuff + std::list<DOMElement*> unsupported; + unsupported = DOMUtils::inDocumentOrder({ + XML_PREFIX(_scxml).str() + "datamodel", + XML_PREFIX(_scxml).str() + "data", + XML_PREFIX(_scxml).str() + "assign", + XML_PREFIX(_scxml).str() + "donedata", + XML_PREFIX(_scxml).str() + "content", + XML_PREFIX(_scxml).str() + "param", + XML_PREFIX(_scxml).str() + "script", + XML_PREFIX(_scxml).str() + "parallel", + XML_PREFIX(_scxml).str() + "history", + XML_PREFIX(_scxml).str() + "if", + XML_PREFIX(_scxml).str() + "foreach", + XML_PREFIX(_scxml).str() + "send", + XML_PREFIX(_scxml).str() + "cancel", + XML_PREFIX(_scxml).str() + "invoke", + XML_PREFIX(_scxml).str() + "finalize" + }, _scxml); + + std::stringstream ss; + if (unsupported.size() > 0) { + for (auto elem : unsupported) { + ss << " " << DOMUtils::xPathForNode(elem) << " unsupported" << std::endl; + } + throw std::runtime_error("Unsupported elements found:\n" + ss.str()); + } + + unsupported = DOMUtils::inDocumentOrder({ XML_PREFIX(_scxml).str() + "transition" }, _scxml); + + for (auto transition : unsupported) { + if (HAS_ATTR(transition, "cond")) { + ERROR_PLATFORM_THROW("transition with conditions not supported!"); + } + if (!HAS_ATTR(transition, "target")) { + ERROR_PLATFORM_THROW("targetless transition not supported!"); + } + } } std::string ChartToVHDL::eventNameEscape(const std::string& eventName) { - std::string escaped = escape(eventName); - boost::replace_all(escaped, ".", "_"); - return escaped; + std::string escaped = escape(eventName); + boost::replace_all(escaped, ".", "_"); + return escaped; } void ChartToVHDL::findEvents() { - // elements with an event attribute - std::list<DOMElement*> withEvents = DOMUtils::inDocumentOrder({ - XML_PREFIX(_scxml).str() + "raise", - XML_PREFIX(_scxml).str() + "send", - XML_PREFIX(_scxml).str() + "transition", - - }, _scxml); - - for (auto withEvent : withEvents) { - if (HAS_ATTR_CAST(withEvent, "event")) { - // TODO: tokenize! - if (ATTR_CAST(withEvent, "event") != "*") - _eventTrie.addWord(ATTR_CAST(withEvent, "event")); - } - } - - _execContent = DOMUtils::inDocumentOrder({ - XML_PREFIX(_scxml).str() + "raise", - XML_PREFIX(_scxml).str() + "send" - }, _scxml); + // elements with an event attribute + std::list<DOMElement*> withEvents = DOMUtils::inDocumentOrder({ + XML_PREFIX(_scxml).str() + "raise", + XML_PREFIX(_scxml).str() + "send", + XML_PREFIX(_scxml).str() + "transition", + + }, _scxml); + + for (auto withEvent : withEvents) { + if (HAS_ATTR_CAST(withEvent, "event")) { + // TODO: tokenize! + if (ATTR_CAST(withEvent, "event") != "*") + _eventTrie.addWord(ATTR_CAST(withEvent, "event")); + } + } + + _execContent = DOMUtils::inDocumentOrder({ + XML_PREFIX(_scxml).str() + "raise", + XML_PREFIX(_scxml).str() + "send" + }, _scxml); } void ChartToVHDL::writeTo(std::ostream& stream) { - // same preparations as the C transformation - //prepare(); + // same preparations as the C transformation + prepare(); - // checkDocument(); - findEvents(); + // checkDocument(); + findEvents(); - stream << "-- generated from " << std::string(_baseURL) << std::endl; - stream << "-- run as " << std::endl; - stream << "-- ghdl --clean && ghdl -a foo.vhdl && ghdl -e tb && ./tb --stop-time=10ms --vcd=foo.vcd" << std::endl; - stream << std::endl; + stream << "-- generated from " << std::string(_baseURL) << std::endl; + stream << "-- run as " << std::endl; + stream << "-- ghdl --clean && ghdl -a foo.vhdl && ghdl -e tb && ./tb --stop-time=10ms --vcd=foo.vcd" << std::endl; + stream << std::endl; - writeTypes(stream); - writeFiFo(stream); - writeEventController(stream); - writeMicroStepper(stream); - writeTestbench(stream); + writeTypes(stream); + writeFiFo(stream); + writeEventController(stream); + writeMicroStepper(stream); + writeTestbench(stream); } void ChartToVHDL::writeTypes(std::ostream & stream) { - std::string seperator; - - stream << "-- required global types" << std::endl; - stream << "library IEEE;" << std::endl; - stream << "use IEEE.std_logic_1164.all;" << std::endl; - stream << std::endl; - stream << "package machine" << _md5 << " is" << std::endl; - // create state type - stream << " subtype state_type is std_logic_vector( "; - stream << _states.size() - 1; - stream << " downto 0);" << std::endl; - - std::list<TrieNode*> eventNames = _eventTrie.getWordsWithPrefix(""); - stream << " type event_type is ( hwe_null, "; - seperator = ""; - - for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { - stream << seperator << "hwe_" << eventNameEscape((*eventIter)->value); - seperator = ", "; - } - stream << " );" << std::endl; - - stream << "end machine" << _md5 << ";" << std::endl; - stream << std::endl; - stream << "-- END needed global types" << std::endl; + std::string seperator; + + stream << "-- required global types" << std::endl; + stream << "library IEEE;" << std::endl; + stream << "use IEEE.std_logic_1164.all;" << std::endl; + stream << std::endl; + stream << "package machine" << _md5 << " is" << std::endl; + // create state type + stream << " subtype state_type is std_logic_vector( "; + stream << _states.size() - 1; + stream << " downto 0);" << std::endl; + + std::list<TrieNode*> eventNames = _eventTrie.getWordsWithPrefix(""); + stream << " type event_type is ( hwe_null, "; + seperator = ""; + + for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { + stream << seperator << "hwe_" << eventNameEscape((*eventIter)->value); + seperator = ", "; + } + stream << " );" << std::endl; + + stream << "end machine" << _md5 << ";" << std::endl; + stream << std::endl; + stream << "-- END needed global types" << std::endl; } void ChartToVHDL::writeIncludes(std::ostream & stream) { - // Add controler specific stuff here - stream << "library IEEE;" << std::endl; - stream << "use IEEE.std_logic_1164.all;" << std::endl; - stream << "use work.machine" << _md5 << ".all;" << std::endl; - stream << std::endl; + // Add controler specific stuff here + stream << "library IEEE;" << std::endl; + stream << "use IEEE.std_logic_1164.all;" << std::endl; + stream << "use work.machine" << _md5 << ".all;" << std::endl; + stream << std::endl; } void ChartToVHDL::writeTestbench(std::ostream& stream) { - stream << "-- TESTBENCH" << std::endl; - writeIncludes(stream); - stream << std::endl; - - stream << "-- empty entity" << std::endl; - stream << "entity tb is" << std::endl; - stream << "end entity tb;" << std::endl; - stream << std::endl; - - stream << "architecture bhv of tb is" << std::endl; - stream << std::endl; - - // modules - stream << " -- Module declaration" << std::endl; - stream << " component micro_stepper is" << std::endl; - stream << " port (" << std::endl; - stream << " --inputs" << std::endl; - stream << " clk :in std_logic;" << std::endl; - stream << " rst_i :in std_logic;" << std::endl; - stream << " en :in std_logic;" << std::endl; - stream << " next_event_i :in event_type;" << std::endl; - stream << " next_event_we_i :in std_logic;" << std::endl; - stream << " --outputs" << std::endl; - stream << " error_o :out std_logic;" << std::endl; - - for (auto state : _states) { - stream << " state_active_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl; - - if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) { - stream << " entry_set_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl; - } - - if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) { - stream << " exit_set_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl; - } - } - - for (auto transition : _transitions) { - if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) { - stream << " transition_set_" << ATTR(transition, "postFixOrder") << "_o :out std_logic;" - << std::endl; - } - } - - stream << " completed_o :out std_logic" << std::endl; - stream << " );" << std::endl; - stream << " end component;" << std::endl; - stream << std::endl; - - stream << " component event_controller is" << std::endl; - stream << " port(" << std::endl; - stream << " --inputs" << std::endl; - stream << " clk :in std_logic;" << std::endl; - stream << " rst_i :in std_logic;" << std::endl; - - for (auto state : _states) { - stream << " state_active_" << ATTR(state, "documentOrder") - << "_i :in std_logic;" << std::endl; - - if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) { - stream << " entry_set_" << ATTR(state, "documentOrder") - << "_i :in std_logic;" << std::endl; - } - - if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) { - stream << " exit_set_" << ATTR(state, "documentOrder") - << "_i :in std_logic;" << std::endl; - } - } - - for (auto transition : _transitions) { - if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) { - stream << " transition_set_" << ATTR(transition, "postFixOrder") - << "_i :in std_logic;" << std::endl; - } - } - stream << " --outputs" << std::endl; - stream << " micro_stepper_en_o :out std_logic;" << std::endl; - stream << " event_o :out event_type;" << std::endl; - stream << " event_we_o :out std_logic" << std::endl; - // stream << " done_o :out std_logic" << std::endl; - stream << ");" << std::endl; - stream << "end component; " << std::endl; - - // signals - stream << " -- input" << std::endl; - stream << " signal clk : std_logic := '0';" << std::endl; - stream << " signal reset : std_logic;" << std::endl; - stream << " signal dut_enable : std_logic;" << std::endl; - stream << " signal next_event_we_i : std_logic;" << std::endl; - stream << " signal next_event_i : event_type;" << std::endl; - stream << std::endl; - - stream << " -- output" << std::endl; - stream << " signal error_o, completed_o : std_logic;" << std::endl; - stream << std::endl; - - stream << " -- wiring" << std::endl; - for (auto state : _states) { - stream << " signal state_active_" << ATTR(state, "documentOrder") - << "_sig : std_logic;" << std::endl; - - if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) { - stream << " signal entry_set_" << ATTR(state, "documentOrder") - << "_sig : std_logic;" << std::endl; - } - - if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) { - stream << " signal exit_set_" << ATTR(state, "documentOrder") - << "_sig : std_logic;" << std::endl; - } - } - - for (auto transition : _transitions) { - if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) { - stream << " signal transition_set_" << ATTR(transition, "postFixOrder") - << "_sig : std_logic;" << std::endl; - } - } - - // wiring - stream << "begin" << std::endl; - stream << " clk <= not clk after 20 ns; -- 25 MHz clock frequency" << std::endl; - stream << " reset <= '1', '0' after 100 ns; -- generates reset signal: --__" << std::endl; - stream << std::endl; - - stream << " -- Module instantiation" << std::endl; - stream << " dut : micro_stepper" << std::endl; - stream << " port map (" << std::endl; - stream << " clk => clk," << std::endl; - stream << " rst_i => reset," << std::endl; - stream << " en => dut_enable," << std::endl; - stream << std::endl; - - stream << " next_event_i => next_event_i," << std::endl; - stream << " next_event_we_i => next_event_we_i," << std::endl; - stream << " error_o => error_o," << std::endl; - - for (auto state : _states) { - stream << " state_active_" << ATTR(state, "documentOrder") - << "_o => state_active_" << ATTR(state, "documentOrder") - << "_sig," << std::endl; - - if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) { - stream << " entry_set_" << ATTR(state, "documentOrder") - << "_o => entry_set_" << ATTR(state, "documentOrder") - << "_sig," << std::endl; - } - - if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) { - stream << " exit_set_" << ATTR(state, "documentOrder") - << "_o => exit_set_" << ATTR(state, "documentOrder") - << "_sig," << std::endl; - } - } - - for (auto transition : _transitions) { - if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) { - stream << " transition_set_" << ATTR(transition, "postFixOrder") - << "_o => transition_set_" << ATTR(transition, "postFixOrder") - << "_sig," << std::endl; - } - } - - stream << " completed_o => completed_o" << std::endl; - stream << " );" << std::endl; - stream << std::endl; - - stream << " ec : event_controller" << std::endl; - stream << " port map (" << std::endl; - stream << " clk => clk," << std::endl; - stream << " rst_i => reset," << std::endl; - stream << std::endl; - - stream << " event_o => next_event_i," << std::endl; - stream << " event_we_o => next_event_we_i," << std::endl; - - for (auto state : _states) { - stream << " state_active_" << ATTR(state, "documentOrder") - << "_i => state_active_" << ATTR(state, "documentOrder") - << "_sig," << std::endl; - - if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) { - stream << " entry_set_" << ATTR(state, "documentOrder") - << "_i => entry_set_" << ATTR(state, "documentOrder") - << "_sig," << std::endl; - } - - if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) { - stream << " exit_set_" << ATTR(state, "documentOrder") - << "_i => exit_set_" << ATTR(state, "documentOrder") - << "_sig," << std::endl; - } - } - - for (auto transition : _transitions) { - if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) { - stream << " transition_set_" << ATTR(transition, "postFixOrder") - << "_i => transition_set_" << ATTR(transition, "postFixOrder") - << "_sig," << std::endl; - } - } - - stream << " micro_stepper_en_o => dut_enable" << std::endl; - // stream << " done_o => open" << std::endl; - stream << " );" << std::endl; - stream << std::endl; - - stream << "end architecture;" << std::endl; - stream << "-- END TESTBENCH" << std::endl; + stream << "-- TESTBENCH" << std::endl; + writeIncludes(stream); + stream << std::endl; + + stream << "-- empty entity" << std::endl; + stream << "entity tb is" << std::endl; + stream << "end entity tb;" << std::endl; + stream << std::endl; + + stream << "architecture bhv of tb is" << std::endl; + stream << std::endl; + + // modules + stream << " -- Module declaration" << std::endl; + stream << " component micro_stepper is" << std::endl; + stream << " port (" << std::endl; + stream << " --inputs" << std::endl; + stream << " clk :in std_logic;" << std::endl; + stream << " rst_i :in std_logic;" << std::endl; + stream << " en :in std_logic;" << std::endl; + stream << " next_event_i :in event_type;" << std::endl; + stream << " next_event_we_i :in std_logic;" << std::endl; + stream << " --outputs" << std::endl; + stream << " error_o :out std_logic;" << std::endl; + + for (auto state : _states) { + stream << " state_active_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl; + + if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) { + stream << " entry_set_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl; + } + + if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) { + stream << " exit_set_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl; + } + } + + for (auto transition : _transitions) { + if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) { + stream << " transition_set_" << ATTR(transition, "postFixOrder") << "_o :out std_logic;" + << std::endl; + } + } + + stream << " completed_o :out std_logic" << std::endl; + stream << " );" << std::endl; + stream << " end component;" << std::endl; + stream << std::endl; + + stream << " component event_controller is" << std::endl; + stream << " port(" << std::endl; + stream << " --inputs" << std::endl; + stream << " clk :in std_logic;" << std::endl; + stream << " rst_i :in std_logic;" << std::endl; + + for (auto state : _states) { + stream << " state_active_" << ATTR(state, "documentOrder") + << "_i :in std_logic;" << std::endl; + + if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) { + stream << " entry_set_" << ATTR(state, "documentOrder") + << "_i :in std_logic;" << std::endl; + } + + if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) { + stream << " exit_set_" << ATTR(state, "documentOrder") + << "_i :in std_logic;" << std::endl; + } + } + + for (auto transition : _transitions) { + if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) { + stream << " transition_set_" << ATTR(transition, "postFixOrder") + << "_i :in std_logic;" << std::endl; + } + } + stream << " --outputs" << std::endl; + stream << " micro_stepper_en_o :out std_logic;" << std::endl; + stream << " event_o :out event_type;" << std::endl; + stream << " event_we_o :out std_logic" << std::endl; + // stream << " done_o :out std_logic" << std::endl; + stream << ");" << std::endl; + stream << "end component; " << std::endl; + + // signals + stream << " -- input" << std::endl; + stream << " signal clk : std_logic := '0';" << std::endl; + stream << " signal reset : std_logic;" << std::endl; + stream << " signal dut_enable : std_logic;" << std::endl; + stream << " signal next_event_we_i : std_logic;" << std::endl; + stream << " signal next_event_i : event_type;" << std::endl; + stream << std::endl; + + stream << " -- output" << std::endl; + stream << " signal error_o, completed_o : std_logic;" << std::endl; + stream << std::endl; + + stream << " -- wiring" << std::endl; + for (auto state : _states) { + stream << " signal state_active_" << ATTR(state, "documentOrder") + << "_sig : std_logic;" << std::endl; + + if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) { + stream << " signal entry_set_" << ATTR(state, "documentOrder") + << "_sig : std_logic;" << std::endl; + } + + if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) { + stream << " signal exit_set_" << ATTR(state, "documentOrder") + << "_sig : std_logic;" << std::endl; + } + } + + for (auto transition : _transitions) { + if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) { + stream << " signal transition_set_" << ATTR(transition, "postFixOrder") + << "_sig : std_logic;" << std::endl; + } + } + + // wiring + stream << "begin" << std::endl; + stream << " clk <= not clk after 20 ns; -- 25 MHz clock frequency" << std::endl; + stream << " reset <= '1', '0' after 100 ns; -- generates reset signal: --__" << std::endl; + stream << std::endl; + + stream << " -- Module instantiation" << std::endl; + stream << " dut : micro_stepper" << std::endl; + stream << " port map (" << std::endl; + stream << " clk => clk," << std::endl; + stream << " rst_i => reset," << std::endl; + stream << " en => dut_enable," << std::endl; + stream << std::endl; + + stream << " next_event_i => next_event_i," << std::endl; + stream << " next_event_we_i => next_event_we_i," << std::endl; + stream << " error_o => error_o," << std::endl; + + for (auto state : _states) { + stream << " state_active_" << ATTR(state, "documentOrder") + << "_o => state_active_" << ATTR(state, "documentOrder") + << "_sig," << std::endl; + + if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) { + stream << " entry_set_" << ATTR(state, "documentOrder") + << "_o => entry_set_" << ATTR(state, "documentOrder") + << "_sig," << std::endl; + } + + if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) { + stream << " exit_set_" << ATTR(state, "documentOrder") + << "_o => exit_set_" << ATTR(state, "documentOrder") + << "_sig," << std::endl; + } + } + + for (auto transition : _transitions) { + if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) { + stream << " transition_set_" << ATTR(transition, "postFixOrder") + << "_o => transition_set_" << ATTR(transition, "postFixOrder") + << "_sig," << std::endl; + } + } + + stream << " completed_o => completed_o" << std::endl; + stream << " );" << std::endl; + stream << std::endl; + + stream << " ec : event_controller" << std::endl; + stream << " port map (" << std::endl; + stream << " clk => clk," << std::endl; + stream << " rst_i => reset," << std::endl; + stream << std::endl; + + stream << " event_o => next_event_i," << std::endl; + stream << " event_we_o => next_event_we_i," << std::endl; + + for (auto state : _states) { + stream << " state_active_" << ATTR(state, "documentOrder") + << "_i => state_active_" << ATTR(state, "documentOrder") + << "_sig," << std::endl; + + if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) { + stream << " entry_set_" << ATTR(state, "documentOrder") + << "_i => entry_set_" << ATTR(state, "documentOrder") + << "_sig," << std::endl; + } + + if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) { + stream << " exit_set_" << ATTR(state, "documentOrder") + << "_i => exit_set_" << ATTR(state, "documentOrder") + << "_sig," << std::endl; + } + } + + for (auto transition : _transitions) { + if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) { + stream << " transition_set_" << ATTR(transition, "postFixOrder") + << "_i => transition_set_" << ATTR(transition, "postFixOrder") + << "_sig," << std::endl; + } + } + + stream << " micro_stepper_en_o => dut_enable" << std::endl; + // stream << " done_o => open" << std::endl; + stream << " );" << std::endl; + stream << std::endl; + + stream << "end architecture;" << std::endl; + stream << "-- END TESTBENCH" << std::endl; } void ChartToVHDL::writeExContentBlock(std::ostream & stream, - std::string index, std::list< DOMElement* > commandSequence) { - // index should be [entry, transition, exit]_<index of state/transition>_<optional index for block> + std::string index, std::list< DOMElement* > commandSequence) { + // index should be [entry, transition, exit]_<index of state/transition>_<optional index for block> - // write clock blocks + // write clock blocks } void ChartToVHDL::writeEventController(std::ostream & stream) { - // Add controler specific stuff here - // create hardware top level - stream << "-- Event Controller Logic" << std::endl; - writeIncludes(stream); - stream << "entity event_controller is" << std::endl; - stream << "port(" << std::endl; - stream << " --inputs" << std::endl; - stream << " clk :in std_logic;" << std::endl; - stream << " rst_i :in std_logic;" << std::endl; - - for (auto state : _states) { - stream << " state_active_" << ATTR(state, "documentOrder") - << "_i :in std_logic;" << std::endl; - - if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) { - stream << " entry_set_" << ATTR(state, "documentOrder") - << "_i :in std_logic;" << std::endl; - } - - if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) { - stream << " exit_set_" << ATTR(state, "documentOrder") - << "_i :in std_logic;" << std::endl; - } - } - - for (auto transition : _transitions) { - if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) { - stream << " transition_set_" << ATTR(transition, "postFixOrder") - << "_i :in std_logic;" << std::endl; - } - } - - stream << " --outputs" << std::endl; - stream << " micro_stepper_en_o :out std_logic;" << std::endl; - stream << " event_o :out event_type;" << std::endl; - stream << " event_we_o :out std_logic" << std::endl; - stream << ");" << std::endl; - stream << "end event_controller; " << std::endl; - - stream << std::endl; - stream << "architecture behavioral of event_controller is " << std::endl; - stream << std::endl; - - // Add signals and components - stream << "signal rst : std_logic;" << std::endl; - stream << "signal micro_stepper_en : std_logic;" << std::endl; - stream << "signal cmpl_buf : std_logic;" << std::endl; - stream << "signal completed_sig : std_logic;" << std::endl; - stream << "signal event_bus : event_type;" << std::endl; - stream << "signal event_we : std_logic;" << std::endl; - - for (int i = 0; i < _execContent.size(); i++) { - stream << "signal done_" << toStr(i) << "_sig : std_logic;" << std::endl; - stream << "signal start_" << toStr(i) << "_sig : std_logic;" << std::endl; - } - - stream << "-- sequence input line" << std::endl; - for (int i = 0; i < _execContent.size(); i++) { - stream << "signal seq_" << toStr(i) << "_sig : std_logic;" << std::endl; - } - stream << std::endl; - - stream << "begin" << std::endl; - stream << std::endl; - // system signal mapping - stream << "rst <= rst_i;" << std::endl; - stream << "micro_stepper_en_o <= micro_stepper_en;" << std::endl; - stream << "event_o <= event_bus;" << std::endl; - stream << "event_we_o <= event_we;" << std::endl; - stream << std::endl; - - // stall management - stream << "-- stalling microstepper" << std::endl; - // stream << "ms_enable_manager : process (clk, rst) " << std::endl; - // stream << "begin" << std::endl; - // stream << " if rst = '1' then" << std::endl; - // stream << " micro_stepper_en <= '1';" << std::endl; - // stream << " elsif rising_edge(clk) then" << std::endl; - // stream << " " << std::endl; - stream << "micro_stepper_en <= completed_sig or not ( '0' "; - for (auto state : _states) { - - if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) { - stream << std::endl << " or entry_set_" << ATTR(state, "documentOrder") - << "_i"; - } - - if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) { - stream << std::endl << " or exit_set_" << ATTR(state, "documentOrder") - << "_i"; - } - } - for (auto transition : _transitions) { - if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) { - stream << std::endl << " or transition_set_" << ATTR(transition, "postFixOrder") - << "_i"; - } - } - stream << ");" << std::endl; - // stream << " end if;" << std::endl; - // stream << "end process;" << std::endl; - stream << std::endl; - - // write enable management - // stream << "-- write enable for FIFO buffer" << std::endl; - // stream << "event_we <= not rst and ('0'"; - // for (int i = 0; i < _execContent.size(); i++) { - // stream << std::endl << " or start_" << toStr(i) << "_sig"; - // } - // stream << ");" << std::endl; - // stream << std::endl; - - // sequential code operation - stream << "-- seq code block " << std::endl; - stream << "ex_content_block : process (clk, rst) " << std::endl; - stream << "begin" << std::endl; - stream << " if rst = '1' then" << std::endl; - for (int i = 0; i < _execContent.size(); i++) { - stream << " done_" << toStr(i) << "_sig <= '0';" << std::endl; - } - stream << " event_bus <= hwe_null;" << std::endl; - stream << " event_we <= '0';" << std::endl; - stream << " cmpl_buf <= '0';" << std::endl; - stream << " completed_sig <= '0';" << std::endl; - stream << " elsif rising_edge(clk) then" << std::endl; - - stream << " if micro_stepper_en = '1' then" << std::endl; - stream << " cmpl_buf <= '0' ;" << std::endl; - stream << " else" << std::endl; - stream << " cmpl_buf <= seq_" << toStr(_execContent.size() - 1) - << "_sig;" << std::endl; - stream << " end if;" << std::endl; - stream << " completed_sig <= cmpl_buf;" << std::endl << std::endl; - - size_t i = 0; - std::string seperator; - for (auto ecIter = _execContent.begin(); ecIter != _execContent.end(); ecIter++, i++) { - DOMElement* exContentElem = *ecIter; - - //TODO if raise - if (TAGNAME(exContentElem) == XML_PREFIX(_scxml).str() + "raise" || - TAGNAME(exContentElem) == XML_PREFIX(_scxml).str() + "send") { - stream << seperator << "if start_" << toStr(i) << "_sig = '1' then" - << std::endl; - //TODO use escape - stream << " event_bus <= hwe_" << ATTR(exContentElem, "event") - << ";" << std::endl; - stream << " done_" << toStr(i) << "_sig <= '1';" << std::endl; - stream << " event_we <= '1';" << std::endl; - seperator = " els"; - } - } - stream << " elsif micro_stepper_en = '1' then" << std::endl; - for (auto exContentElem : _execContent) { - - //TODO if raise - if (TAGNAME(exContentElem) == XML_PREFIX(_scxml).str() + "raise") { - stream << " done_" << toStr(i) << "_sig <= '0';" << std::endl; - } - } - stream << " event_we <= '0';" << std::endl; - stream << " end if;" << std::endl; - stream << " end if;" << std::endl; - stream << "end process;" << std::endl; - stream << std::endl; - - i = 0; - for (auto ecIter = _execContent.begin(); ecIter != _execContent.end(); ecIter++, i++) { - // start lines - stream << "start_" << toStr(i) << "_sig <= " - << getLineForExecContent(*ecIter) << " and " - << "not done_" << toStr(i) << "_sig"; - if (i != 0) { // if not first element - stream << " and seq_" << toStr(i) << "_sig"; - } - stream << ";" << std::endl; - - } - - stream << "seq_0_sig <= '1';" << std::endl; - - if (_execContent.size() > 1) { - i = 0; - for (auto ecIter = _execContent.begin(); ecIter != _execContent.end(); ecIter++, i++) { - // seq lines (input if process i is in seqence now) - stream << "seq_" << toStr(i) << "_sig <= " - << "done_" << toStr(i - 1) << "_sig or " - << "( not " - << getLineForExecContent(*ecIter); - stream << " and seq_" << toStr(i - 1) << "_sig"; - stream << " );" << std::endl; - } - } - stream << std::endl; - - stream << "end behavioral; " << std::endl; - stream << "-- END Event Controller Logic" << std::endl; + // Add controler specific stuff here + // create hardware top level + stream << "-- Event Controller Logic" << std::endl; + writeIncludes(stream); + stream << "entity event_controller is" << std::endl; + stream << "port(" << std::endl; + stream << " --inputs" << std::endl; + stream << " clk :in std_logic;" << std::endl; + stream << " rst_i :in std_logic;" << std::endl; + + for (auto state : _states) { + stream << " state_active_" << ATTR(state, "documentOrder") + << "_i :in std_logic;" << std::endl; + + if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) { + stream << " entry_set_" << ATTR(state, "documentOrder") + << "_i :in std_logic;" << std::endl; + } + + if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) { + stream << " exit_set_" << ATTR(state, "documentOrder") + << "_i :in std_logic;" << std::endl; + } + } + + for (auto transition : _transitions) { + if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) { + stream << " transition_set_" << ATTR(transition, "postFixOrder") + << "_i :in std_logic;" << std::endl; + } + } + + stream << " --outputs" << std::endl; + stream << " micro_stepper_en_o :out std_logic;" << std::endl; + stream << " event_o :out event_type;" << std::endl; + stream << " event_we_o :out std_logic" << std::endl; + stream << ");" << std::endl; + stream << "end event_controller; " << std::endl; + + stream << std::endl; + stream << "architecture behavioral of event_controller is " << std::endl; + stream << std::endl; + + // Add signals and components + stream << "signal rst : std_logic;" << std::endl; + stream << "signal micro_stepper_en : std_logic;" << std::endl; + stream << "signal cmpl_buf : std_logic;" << std::endl; + stream << "signal completed_sig : std_logic;" << std::endl; + stream << "signal event_bus : event_type;" << std::endl; + stream << "signal event_we : std_logic;" << std::endl; + + for (int i = 0; i < _execContent.size(); i++) { + stream << "signal done_" << toStr(i) << "_sig : std_logic;" << std::endl; + stream << "signal start_" << toStr(i) << "_sig : std_logic;" << std::endl; + } + + stream << "-- sequence input line" << std::endl; + for (int i = 0; i < _execContent.size(); i++) { + stream << "signal seq_" << toStr(i) << "_sig : std_logic;" << std::endl; + } + stream << std::endl; + + stream << "begin" << std::endl; + stream << std::endl; + // system signal mapping + stream << "rst <= rst_i;" << std::endl; + stream << "micro_stepper_en_o <= micro_stepper_en;" << std::endl; + stream << "event_o <= event_bus;" << std::endl; + stream << "event_we_o <= event_we;" << std::endl; + stream << std::endl; + + // stall management + stream << "-- stalling microstepper" << std::endl; + // stream << "ms_enable_manager : process (clk, rst) " << std::endl; + // stream << "begin" << std::endl; + // stream << " if rst = '1' then" << std::endl; + // stream << " micro_stepper_en <= '1';" << std::endl; + // stream << " elsif rising_edge(clk) then" << std::endl; + // stream << " " << std::endl; + stream << "micro_stepper_en <= completed_sig or not ( '0' "; + for (auto state : _states) { + + if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) { + stream << std::endl << " or entry_set_" << ATTR(state, "documentOrder") + << "_i"; + } + + if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) { + stream << std::endl << " or exit_set_" << ATTR(state, "documentOrder") + << "_i"; + } + } + for (auto transition : _transitions) { + if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) { + stream << std::endl << " or transition_set_" << ATTR(transition, "postFixOrder") + << "_i"; + } + } + stream << ");" << std::endl; + // stream << " end if;" << std::endl; + // stream << "end process;" << std::endl; + stream << std::endl; + + // write enable management + // stream << "-- write enable for FIFO buffer" << std::endl; + // stream << "event_we <= not rst and ('0'"; + // for (int i = 0; i < _execContent.size(); i++) { + // stream << std::endl << " or start_" << toStr(i) << "_sig"; + // } + // stream << ");" << std::endl; + // stream << std::endl; + + // sequential code operation + stream << "-- seq code block " << std::endl; + stream << "ex_content_block : process (clk, rst) " << std::endl; + stream << "begin" << std::endl; + stream << " if rst = '1' then" << std::endl; + for (int i = 0; i < _execContent.size(); i++) { + stream << " done_" << toStr(i) << "_sig <= '0';" << std::endl; + } + stream << " event_bus <= hwe_null;" << std::endl; + stream << " event_we <= '0';" << std::endl; + stream << " cmpl_buf <= '0';" << std::endl; + stream << " completed_sig <= '0';" << std::endl; + stream << " elsif rising_edge(clk) then" << std::endl; + + stream << " if micro_stepper_en = '1' then" << std::endl; + stream << " cmpl_buf <= '0' ;" << std::endl; + stream << " else" << std::endl; + stream << " cmpl_buf <= seq_" << toStr(_execContent.size() - 1) + << "_sig;" << std::endl; + stream << " end if;" << std::endl; + stream << " completed_sig <= cmpl_buf;" << std::endl << std::endl; + + size_t i = 0; + std::string seperator; + for (auto ecIter = _execContent.begin(); ecIter != _execContent.end(); ecIter++, i++) { + DOMElement* exContentElem = *ecIter; + + //TODO if raise + if (TAGNAME(exContentElem) == XML_PREFIX(_scxml).str() + "raise" || + TAGNAME(exContentElem) == XML_PREFIX(_scxml).str() + "send") { + stream << seperator << "if start_" << toStr(i) << "_sig = '1' then" + << std::endl; + //TODO use escape + stream << " event_bus <= hwe_" << ATTR(exContentElem, "event") + << ";" << std::endl; + stream << " done_" << toStr(i) << "_sig <= '1';" << std::endl; + stream << " event_we <= '1';" << std::endl; + seperator = " els"; + } + } + stream << " elsif micro_stepper_en = '1' then" << std::endl; + for (auto exContentElem : _execContent) { + + //TODO if raise + if (TAGNAME(exContentElem) == XML_PREFIX(_scxml).str() + "raise") { + stream << " done_" << toStr(i) << "_sig <= '0';" << std::endl; + } + } + stream << " event_we <= '0';" << std::endl; + stream << " end if;" << std::endl; + stream << " end if;" << std::endl; + stream << "end process;" << std::endl; + stream << std::endl; + + i = 0; + for (auto ecIter = _execContent.begin(); ecIter != _execContent.end(); ecIter++, i++) { + // start lines + stream << "start_" << toStr(i) << "_sig <= " + << getLineForExecContent(*ecIter) << " and " + << "not done_" << toStr(i) << "_sig"; + if (i != 0) { // if not first element + stream << " and seq_" << toStr(i) << "_sig"; + } + stream << ";" << std::endl; + + } + + stream << "seq_0_sig <= '1';" << std::endl; + + if (_execContent.size() > 1) { + i = 0; + for (auto ecIter = _execContent.begin(); ecIter != _execContent.end(); ecIter++, i++) { + // seq lines (input if process i is in seqence now) + stream << "seq_" << toStr(i) << "_sig <= " + << "done_" << toStr(i - 1) << "_sig or " + << "( not " + << getLineForExecContent(*ecIter); + stream << " and seq_" << toStr(i - 1) << "_sig"; + stream << " );" << std::endl; + } + } + stream << std::endl; + + stream << "end behavioral; " << std::endl; + stream << "-- END Event Controller Logic" << std::endl; } std::string ChartToVHDL::getLineForExecContent(const DOMNode* elem) { - const DOMNode* ecBlock = elem; - while (ecBlock) { - if (ecBlock->getNodeType() == DOMNode::ELEMENT_NODE) { - std::string localName = LOCALNAME_CAST(ecBlock); - if (localName == XML_PREFIX(_scxml).str() + "transition") { - return "transition_set_" + ATTR_CAST(ecBlock, "postFixOrder") + "_i"; - } - - if (localName == XML_PREFIX(_scxml).str() + "onentry") { - return "entry_set_" + ATTR_CAST(ecBlock->getParentNode(), "documentOrder") + "_i"; - } - - if (localName == XML_PREFIX(_scxml).str() + "onexit") { - return "exit_set_" + ATTR_CAST(ecBlock->getParentNode(), "documentOrder") + "_i"; - } - - } - ecBlock = ecBlock->getParentNode(); - } - - return ""; + const DOMNode* ecBlock = elem; + while (ecBlock) { + if (ecBlock->getNodeType() == DOMNode::ELEMENT_NODE) { + std::string localName = LOCALNAME_CAST(ecBlock); + if (localName == XML_PREFIX(_scxml).str() + "transition") { + return "transition_set_" + ATTR_CAST(ecBlock, "postFixOrder") + "_i"; + } + + if (localName == XML_PREFIX(_scxml).str() + "onentry") { + return "entry_set_" + ATTR_CAST(ecBlock->getParentNode(), "documentOrder") + "_i"; + } + + if (localName == XML_PREFIX(_scxml).str() + "onexit") { + return "exit_set_" + ATTR_CAST(ecBlock->getParentNode(), "documentOrder") + "_i"; + } + + } + ecBlock = ecBlock->getParentNode(); + } + + return ""; } void ChartToVHDL::writeMicroStepper(std::ostream & stream) { - // create MicroStepper top level - stream << "-- FSM Logic" << std::endl; - writeIncludes(stream); - stream << "entity micro_stepper is" << std::endl; - stream << "port(" << std::endl; - stream << " --inputs" << std::endl; - stream << " clk :in std_logic;" << std::endl; - stream << " rst_i :in std_logic;" << std::endl; - stream << " en :in std_logic;" << std::endl; - stream << " next_event_i :in event_type;" << std::endl; - stream << " next_event_we_i :in std_logic;" << std::endl; - stream << " --outputs" << std::endl; - stream << " error_o :out std_logic;" << std::endl; - - for (auto state : _states) { - stream << " state_active_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl; - - if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) { - stream << " entry_set_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl; - } - - if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) { - stream << " exit_set_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl; - } - } - - for (auto transition : _transitions) { - if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) { - stream << " transition_set_" << ATTR(transition, "postFixOrder") << "_o :out std_logic;" - << std::endl; - } - } - - stream << " completed_o :out std_logic" << std::endl; - stream << ");" << std::endl; - stream << "end micro_stepper; " << std::endl; - - stream << std::endl; - stream << "architecture behavioral of micro_stepper is " << std::endl; - stream << std::endl; - - // Add signals and components - writeSignalsAndComponents(stream); - - stream << std::endl; - stream << "begin" << std::endl; - stream << std::endl; - - // signal mapping - writeModuleInstantiation(stream); - - // signal handler - writeSpontaneousHandler(stream); - writeErrorHandler(stream); - writeInternalEventHandler(stream); - writeStateHandler(stream); - writeResetHandler(stream); - - // combinatorial logic for Sn+1 - writeOptimalTransitionSetSelection(stream); - writeExitSet(stream); - writeCompleteEntrySet(stream); - writeEntrySet(stream); - writeDefaultCompletions(stream); - writeActiveStateNplusOne(stream); - - // connect output signals - writeSystemSignalMapping(stream); - - - stream << std::endl; - stream << "end behavioral; " << std::endl; - stream << "-- END FSM Logic" << std::endl; + // create MicroStepper top level + stream << "-- FSM Logic" << std::endl; + writeIncludes(stream); + stream << "entity micro_stepper is" << std::endl; + stream << "port(" << std::endl; + stream << " --inputs" << std::endl; + stream << " clk :in std_logic;" << std::endl; + stream << " rst_i :in std_logic;" << std::endl; + stream << " en :in std_logic;" << std::endl; + stream << " next_event_i :in event_type;" << std::endl; + stream << " next_event_we_i :in std_logic;" << std::endl; + stream << " --outputs" << std::endl; + stream << " error_o :out std_logic;" << std::endl; + + for (auto state : _states) { + stream << " state_active_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl; + + if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) { + stream << " entry_set_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl; + } + + if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) { + stream << " exit_set_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl; + } + } + + for (auto transition : _transitions) { + if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) { + stream << " transition_set_" << ATTR(transition, "postFixOrder") << "_o :out std_logic;" + << std::endl; + } + } + + stream << " completed_o :out std_logic" << std::endl; + stream << ");" << std::endl; + stream << "end micro_stepper; " << std::endl; + + stream << std::endl; + stream << "architecture behavioral of micro_stepper is " << std::endl; + stream << std::endl; + + // Add signals and components + writeSignalsAndComponents(stream); + + stream << std::endl; + stream << "begin" << std::endl; + stream << std::endl; + + // signal mapping + writeModuleInstantiation(stream); + + // signal handler + writeSpontaneousHandler(stream); + writeErrorHandler(stream); + writeInternalEventHandler(stream); + writeStateHandler(stream); + writeResetHandler(stream); + + // combinatorial logic for Sn+1 + writeOptimalTransitionSetSelection(stream); + writeExitSet(stream); + writeCompleteEntrySet(stream); + writeEntrySet(stream); + writeDefaultCompletions(stream); + writeActiveStateNplusOne(stream); + + // connect output signals + writeSystemSignalMapping(stream); + + + stream << std::endl; + stream << "end behavioral; " << std::endl; + stream << "-- END FSM Logic" << std::endl; } void ChartToVHDL::writeFiFo(std::ostream & stream) { - // taken from: http://www.deathbylogic.com/2013/07/vhdl-standard-fifo/ - // alternativly take fifo logic for a ram device: http://www.eng.auburn.edu/~strouce/class/elec4200/vhdlmods.pdf - stream << "-- standard FIFO buffer" << std::endl; - writeIncludes(stream); - stream << "" << std::endl; - stream << "entity std_fifo is" << std::endl; - stream << "generic (" << std::endl; - stream << " constant FIFO_DEPTH : positive := 256" << std::endl; - stream << ");" << std::endl; - stream << "port ( " << std::endl; - stream << " clk : in std_logic;" << std::endl; - stream << " rst : in std_logic;" << std::endl; - stream << " write_en : in std_logic;" << std::endl; - stream << " read_en : in std_logic;" << std::endl; - stream << " data_in : in event_type;" << std::endl; - stream << " data_out : out event_type;" << std::endl; - stream << " empty : out std_logic;" << std::endl; - stream << " full : out std_logic" << std::endl; - stream << ");" << std::endl; - stream << "end std_fifo;" << std::endl; - stream << "" << std::endl; - stream << "architecture behavioral of std_fifo is" << std::endl; - stream << "begin" << std::endl; - stream << "-- Memory Pointer Process" << std::endl; - stream << "fifo_proc : process (clk)" << std::endl; - stream << " type FIFO_Memory is array (0 to FIFO_DEPTH - 1) of event_type;" << std::endl; - stream << " variable Memory : FIFO_Memory;" << std::endl; - stream << "" << std::endl; - stream << " variable Head : natural range 0 to FIFO_DEPTH - 1;" << std::endl; - stream << " variable Tail : natural range 0 to FIFO_DEPTH - 1;" << std::endl; - stream << "" << std::endl; - stream << " variable Looped : boolean;" << std::endl; - stream << "begin" << std::endl; - stream << " if rising_edge(clk) then" << std::endl; - stream << " if rst = '1' then" << std::endl; - stream << " Head := 0;" << std::endl; - stream << " Tail := 0;" << std::endl; - stream << "" << std::endl; - stream << " Looped := false;" << std::endl; - stream << "" << std::endl; - stream << " full <= '0';" << std::endl; - stream << " empty <= '1';" << std::endl; - stream << " else" << std::endl; - stream << " if (read_en = '1') then" << std::endl; - stream << " if ((Looped = true) or (Head /= Tail)) then" << std::endl; - stream << " -- Update data output" << std::endl; - stream << " data_out <= Memory(Tail);" << std::endl; - stream << " " << std::endl; - stream << " -- Update Tail pointer as needed" << std::endl; - stream << " if (Tail = FIFO_DEPTH - 1) then" << std::endl; - stream << " Tail := 0;" << std::endl; - stream << " " << std::endl; - stream << " Looped := false;" << std::endl; - stream << " else" << std::endl; - stream << " Tail := Tail + 1;" << std::endl; - stream << " end if;" << std::endl; - stream << "" << std::endl; - stream << " end if;" << std::endl; - stream << " end if;" << std::endl; - stream << "" << std::endl; - stream << " if (write_en = '1') then" << std::endl; - stream << " if ((Looped = false) or (Head /= Tail)) then" << std::endl; - stream << " -- Write Data to Memory" << std::endl; - stream << " Memory(Head) := data_in;" << std::endl; - stream << " " << std::endl; - stream << " -- Increment Head pointer as needed" << std::endl; - stream << " if (Head = FIFO_DEPTH - 1) then" << std::endl; - stream << " Head := 0;" << std::endl; - stream << " " << std::endl; - stream << " Looped := true;" << std::endl; - stream << " else" << std::endl; - stream << " Head := Head + 1;" << std::endl; - stream << " end if;" << std::endl; - stream << " end if;" << std::endl; - stream << " end if;" << std::endl; - stream << "" << std::endl; - stream << " -- Update empty and full flags" << std::endl; - stream << " if (Head = Tail) then" << std::endl; - stream << " if Looped then" << std::endl; - stream << " full <= '1';" << std::endl; - stream << " else" << std::endl; - stream << " empty <= '1';" << std::endl; - stream << " end if;" << std::endl; - stream << " else" << std::endl; - stream << " empty <= '0';" << std::endl; - stream << " full <= '0';" << std::endl; - stream << " end if;" << std::endl; - stream << " end if;" << std::endl; - stream << " end if;" << std::endl; - stream << "end process;" << std::endl; - stream << "" << std::endl; - stream << "end behavioral;" << std::endl; - stream << "-- END standard FIFO buffer" << std::endl; + // taken from: http://www.deathbylogic.com/2013/07/vhdl-standard-fifo/ + // alternativly take fifo logic for a ram device: http://www.eng.auburn.edu/~strouce/class/elec4200/vhdlmods.pdf + stream << "-- standard FIFO buffer" << std::endl; + writeIncludes(stream); + stream << "" << std::endl; + stream << "entity std_fifo is" << std::endl; + stream << "generic (" << std::endl; + stream << " constant FIFO_DEPTH : positive := 256" << std::endl; + stream << ");" << std::endl; + stream << "port ( " << std::endl; + stream << " clk : in std_logic;" << std::endl; + stream << " rst : in std_logic;" << std::endl; + stream << " write_en : in std_logic;" << std::endl; + stream << " read_en : in std_logic;" << std::endl; + stream << " data_in : in event_type;" << std::endl; + stream << " data_out : out event_type;" << std::endl; + stream << " empty : out std_logic;" << std::endl; + stream << " full : out std_logic" << std::endl; + stream << ");" << std::endl; + stream << "end std_fifo;" << std::endl; + stream << "" << std::endl; + stream << "architecture behavioral of std_fifo is" << std::endl; + stream << "begin" << std::endl; + stream << "-- Memory Pointer Process" << std::endl; + stream << "fifo_proc : process (clk)" << std::endl; + stream << " type FIFO_Memory is array (0 to FIFO_DEPTH - 1) of event_type;" << std::endl; + stream << " variable Memory : FIFO_Memory;" << std::endl; + stream << "" << std::endl; + stream << " variable Head : natural range 0 to FIFO_DEPTH - 1;" << std::endl; + stream << " variable Tail : natural range 0 to FIFO_DEPTH - 1;" << std::endl; + stream << "" << std::endl; + stream << " variable Looped : boolean;" << std::endl; + stream << "begin" << std::endl; + stream << " if rising_edge(clk) then" << std::endl; + stream << " if rst = '1' then" << std::endl; + stream << " Head := 0;" << std::endl; + stream << " Tail := 0;" << std::endl; + stream << "" << std::endl; + stream << " Looped := false;" << std::endl; + stream << "" << std::endl; + stream << " full <= '0';" << std::endl; + stream << " empty <= '1';" << std::endl; + stream << " else" << std::endl; + stream << " if (read_en = '1') then" << std::endl; + stream << " if ((Looped = true) or (Head /= Tail)) then" << std::endl; + stream << " -- Update data output" << std::endl; + stream << " data_out <= Memory(Tail);" << std::endl; + stream << " " << std::endl; + stream << " -- Update Tail pointer as needed" << std::endl; + stream << " if (Tail = FIFO_DEPTH - 1) then" << std::endl; + stream << " Tail := 0;" << std::endl; + stream << " " << std::endl; + stream << " Looped := false;" << std::endl; + stream << " else" << std::endl; + stream << " Tail := Tail + 1;" << std::endl; + stream << " end if;" << std::endl; + stream << "" << std::endl; + stream << " end if;" << std::endl; + stream << " end if;" << std::endl; + stream << "" << std::endl; + stream << " if (write_en = '1') then" << std::endl; + stream << " if ((Looped = false) or (Head /= Tail)) then" << std::endl; + stream << " -- Write Data to Memory" << std::endl; + stream << " Memory(Head) := data_in;" << std::endl; + stream << " " << std::endl; + stream << " -- Increment Head pointer as needed" << std::endl; + stream << " if (Head = FIFO_DEPTH - 1) then" << std::endl; + stream << " Head := 0;" << std::endl; + stream << " " << std::endl; + stream << " Looped := true;" << std::endl; + stream << " else" << std::endl; + stream << " Head := Head + 1;" << std::endl; + stream << " end if;" << std::endl; + stream << " end if;" << std::endl; + stream << " end if;" << std::endl; + stream << "" << std::endl; + stream << " -- Update empty and full flags" << std::endl; + stream << " if (Head = Tail) then" << std::endl; + stream << " if Looped then" << std::endl; + stream << " full <= '1';" << std::endl; + stream << " else" << std::endl; + stream << " empty <= '1';" << std::endl; + stream << " end if;" << std::endl; + stream << " else" << std::endl; + stream << " empty <= '0';" << std::endl; + stream << " full <= '0';" << std::endl; + stream << " end if;" << std::endl; + stream << " end if;" << std::endl; + stream << " end if;" << std::endl; + stream << "end process;" << std::endl; + stream << "" << std::endl; + stream << "end behavioral;" << std::endl; + stream << "-- END standard FIFO buffer" << std::endl; } void ChartToVHDL::writeSignalsAndComponents(std::ostream & stream) { - // create internal signals - stream << "-- system signals" << std::endl; - stream << "signal stall : std_logic;" << std::endl; - stream << "signal completed_sig : std_logic;" << std::endl; - // stream << "signal rst_2 : std_logic;" << std::endl; - // stream << "signal rst_1 : std_logic;" << std::endl; - stream << "signal rst : std_logic;" << std::endl; - stream << std::endl; - - stream << "-- state signals" << std::endl; - - std::list<std::string> signalDecls; - - for (auto state : _states) { - - signalDecls.push_back("signal state_active_" + ATTR(state, "documentOrder") + "_sig : std_logic;"); - signalDecls.push_back("signal state_next_" + ATTR(state, "documentOrder") + "_sig : std_logic;"); - signalDecls.push_back("signal in_entry_set_" + ATTR(state, "documentOrder") + "_sig : std_logic;"); - signalDecls.push_back("signal in_exit_set_" + ATTR(state, "documentOrder") + "_sig : std_logic;"); - signalDecls.push_back("signal in_complete_entry_set_up_" + ATTR(state, "documentOrder") + "_sig : std_logic;"); - signalDecls.push_back("signal in_complete_entry_set_" + ATTR(state, "documentOrder") + "_sig : std_logic;"); - signalDecls.push_back("signal default_completion_" + ATTR(state, "documentOrder") + "_sig : std_logic;"); - } - - signalDecls.sort(); - for (std::list<std::string>::iterator iter = signalDecls.begin(); iter != signalDecls.end(); iter++) { - stream << *iter << std::endl; - } - stream << std::endl; - - - stream << "-- transition signals" << std::endl; - stream << "signal spontaneous_en : std_logic;" << std::endl; - stream << "signal spontaneous_active : std_logic;" << std::endl; - stream << "signal optimal_transition_set_combined_sig : std_logic;" << std::endl; - - for (auto transition : _transitions) { - stream << "signal in_optimal_transition_set_" << ATTR(transition, "postFixOrder") << "_sig : std_logic;" - << std::endl; - } - stream << std::endl; - - stream << "-- event signals" << std::endl; - stream << "signal int_event_write_en : std_logic;" << std::endl; - stream << "signal int_event_read_en : std_logic;" << std::endl; - stream << "signal int_event_empty : std_logic;" << std::endl; - stream << "signal int_event_input : event_type;" << std::endl; - stream << "signal int_event_output : event_type;" << std::endl; - stream << "signal next_event_re : std_logic;" << std::endl; - stream << "signal next_event_dequeued : std_logic;" << std::endl; - stream << "signal next_event : event_type;" << std::endl; - stream << "signal event_consumed : std_logic;" << std::endl; - stream << std::endl; - - std::list<TrieNode*> eventNames = _eventTrie.getWordsWithPrefix(""); - for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { - stream << "signal event_" << eventNameEscape((*eventIter)->value) << "_sig : std_logic;" << std::endl; - } - stream << std::endl; - - stream << "-- error signals" << std::endl; - stream << "signal reg_error_out : std_logic;" << std::endl; - stream << "signal error_full_int_event_fifo : std_logic;" << std::endl; - stream << std::endl; - - // add components - stream << "-- event FIFO" << std::endl; - stream << "component std_fifo is" << std::endl; - stream << "port ( " << std::endl; - stream << " clk : in std_logic;" << std::endl; - stream << " rst : in std_logic;" << std::endl; - stream << " write_en : in std_logic;" << std::endl; - stream << " read_en : in std_logic;" << std::endl; - stream << " data_in : in event_type;" << std::endl; - stream << " data_out : out event_type;" << std::endl; - stream << " empty : out std_logic;" << std::endl; - stream << " full : out std_logic" << std::endl; // we calculate how much we need - stream << ");" << std::endl; - stream << "end component;" << std::endl; - stream << std::endl; + // create internal signals + stream << "-- system signals" << std::endl; + stream << "signal stall : std_logic;" << std::endl; + stream << "signal completed_sig : std_logic;" << std::endl; + // stream << "signal rst_2 : std_logic;" << std::endl; + // stream << "signal rst_1 : std_logic;" << std::endl; + stream << "signal rst : std_logic;" << std::endl; + stream << std::endl; + + stream << "-- state signals" << std::endl; + + std::list<std::string> signalDecls; + + for (auto state : _states) { + + signalDecls.push_back("signal state_active_" + ATTR(state, "documentOrder") + "_sig : std_logic;"); + signalDecls.push_back("signal state_next_" + ATTR(state, "documentOrder") + "_sig : std_logic;"); + signalDecls.push_back("signal in_entry_set_" + ATTR(state, "documentOrder") + "_sig : std_logic;"); + signalDecls.push_back("signal in_exit_set_" + ATTR(state, "documentOrder") + "_sig : std_logic;"); + signalDecls.push_back("signal in_complete_entry_set_up_" + ATTR(state, "documentOrder") + "_sig : std_logic;"); + signalDecls.push_back("signal in_complete_entry_set_" + ATTR(state, "documentOrder") + "_sig : std_logic;"); + signalDecls.push_back("signal default_completion_" + ATTR(state, "documentOrder") + "_sig : std_logic;"); + } + + signalDecls.sort(); + for (std::list<std::string>::iterator iter = signalDecls.begin(); iter != signalDecls.end(); iter++) { + stream << *iter << std::endl; + } + stream << std::endl; + + + stream << "-- transition signals" << std::endl; + stream << "signal spontaneous_en : std_logic;" << std::endl; + stream << "signal spontaneous_active : std_logic;" << std::endl; + stream << "signal optimal_transition_set_combined_sig : std_logic;" << std::endl; + + for (auto transition : _transitions) { + stream << "signal in_optimal_transition_set_" << ATTR(transition, "postFixOrder") << "_sig : std_logic;" + << std::endl; + } + stream << std::endl; + + stream << "-- event signals" << std::endl; + stream << "signal int_event_write_en : std_logic;" << std::endl; + stream << "signal int_event_read_en : std_logic;" << std::endl; + stream << "signal int_event_empty : std_logic;" << std::endl; + stream << "signal int_event_input : event_type;" << std::endl; + stream << "signal int_event_output : event_type;" << std::endl; + stream << "signal next_event_re : std_logic;" << std::endl; + stream << "signal next_event_dequeued : std_logic;" << std::endl; + stream << "signal next_event : event_type;" << std::endl; + stream << "signal event_consumed : std_logic;" << std::endl; + stream << std::endl; + + std::list<TrieNode*> eventNames = _eventTrie.getWordsWithPrefix(""); + for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { + stream << "signal event_" << eventNameEscape((*eventIter)->value) << "_sig : std_logic;" << std::endl; + } + stream << std::endl; + + stream << "-- error signals" << std::endl; + stream << "signal reg_error_out : std_logic;" << std::endl; + stream << "signal error_full_int_event_fifo : std_logic;" << std::endl; + stream << std::endl; + + // add components + stream << "-- event FIFO" << std::endl; + stream << "component std_fifo is" << std::endl; + stream << "port ( " << std::endl; + stream << " clk : in std_logic;" << std::endl; + stream << " rst : in std_logic;" << std::endl; + stream << " write_en : in std_logic;" << std::endl; + stream << " read_en : in std_logic;" << std::endl; + stream << " data_in : in event_type;" << std::endl; + stream << " data_out : out event_type;" << std::endl; + stream << " empty : out std_logic;" << std::endl; + stream << " full : out std_logic" << std::endl; // we calculate how much we need + stream << ");" << std::endl; + stream << "end component;" << std::endl; + stream << std::endl; } void ChartToVHDL::writeModuleInstantiation(std::ostream & stream) { - // instantiate event fifo - stream << "int_event_fifo : component std_fifo " << std::endl; - stream << "port map ( " << std::endl; - stream << " clk => clk," << std::endl; - stream << " rst => rst_i," << std::endl; - stream << " write_en => int_event_write_en," << std::endl; - stream << " read_en => int_event_read_en," << std::endl; - stream << " data_in => int_event_input," << std::endl; - stream << " data_out => int_event_output," << std::endl; - stream << " empty => int_event_empty," << std::endl; - stream << " full => error_full_int_event_fifo" << std::endl; // we calculate how much we need - stream << ");" << std::endl; - stream << std::endl; + // instantiate event fifo + stream << "int_event_fifo : component std_fifo " << std::endl; + stream << "port map ( " << std::endl; + stream << " clk => clk," << std::endl; + stream << " rst => rst_i," << std::endl; + stream << " write_en => int_event_write_en," << std::endl; + stream << " read_en => int_event_read_en," << std::endl; + stream << " data_in => int_event_input," << std::endl; + stream << " data_out => int_event_output," << std::endl; + stream << " empty => int_event_empty," << std::endl; + stream << " full => error_full_int_event_fifo" << std::endl; // we calculate how much we need + stream << ");" << std::endl; + stream << std::endl; } void ChartToVHDL::writeErrorHandler(std::ostream & stream) { - // sets error output signal if an error occures somewhere - stream << "-- error handler" << std::endl; - stream << "-- sets error output signal if an error occures somewhere" << std::endl; - stream << "error_handler : process (clk, rst) " << std::endl; - stream << "begin" << std::endl; - stream << " if rst = '1' then" << std::endl; - stream << " reg_error_out <= '0';" << std::endl; - stream << " elsif rising_edge(clk) then" << std::endl; - stream << " reg_error_out <= error_full_int_event_fifo;" << std::endl; - stream << " end if;" << std::endl; - stream << "end process;" << std::endl; - stream << std::endl; + // sets error output signal if an error occures somewhere + stream << "-- error handler" << std::endl; + stream << "-- sets error output signal if an error occures somewhere" << std::endl; + stream << "error_handler : process (clk, rst) " << std::endl; + stream << "begin" << std::endl; + stream << " if rst = '1' then" << std::endl; + stream << " reg_error_out <= '0';" << std::endl; + stream << " elsif rising_edge(clk) then" << std::endl; + stream << " reg_error_out <= error_full_int_event_fifo;" << std::endl; + stream << " end if;" << std::endl; + stream << "end process;" << std::endl; + stream << std::endl; } void ChartToVHDL::writeResetHandler(std::ostream & stream) { - stream << "-- reset handler" << std::endl; - stream << "rst <= rst_i;" << std::endl; - // stream << "rst_proc: process(clk, rst_i)" << std::endl; - // stream << "begin" << std::endl; - // stream << " if rst_i = '1' then" << std::endl; - // stream << " rst_2 <= '1';" << std::endl; - // stream << " rst_1 <= '1';" << std::endl; - // stream << " rst <= '1';" << std::endl; - // stream << " elsif (rising_edge(clk)) then" << std::endl; - // stream << " rst_2 <= rst_i;" << std::endl; - // stream << " rst_1 <= rst_i;" << std::endl; - // stream << " rst <= rst_1;" << std::endl; - // stream << " end if;" << std::endl; - // stream << "end process;" << std::endl; - stream << std::endl; + stream << "-- reset handler" << std::endl; + stream << "rst <= rst_i;" << std::endl; + // stream << "rst_proc: process(clk, rst_i)" << std::endl; + // stream << "begin" << std::endl; + // stream << " if rst_i = '1' then" << std::endl; + // stream << " rst_2 <= '1';" << std::endl; + // stream << " rst_1 <= '1';" << std::endl; + // stream << " rst <= '1';" << std::endl; + // stream << " elsif (rising_edge(clk)) then" << std::endl; + // stream << " rst_2 <= rst_i;" << std::endl; + // stream << " rst_1 <= rst_i;" << std::endl; + // stream << " rst <= rst_1;" << std::endl; + // stream << " end if;" << std::endl; + // stream << "end process;" << std::endl; + stream << std::endl; } void ChartToVHDL::writeSpontaneousHandler(std::ostream & stream) { - // sets spontaneous signal - stream << "-- spontaneous handler" << std::endl; - stream << "spontaneous_handler : process (clk, rst) " << std::endl; - stream << "begin" << std::endl; - stream << " if rst = '1' then" << std::endl; - stream << " spontaneous_en <= '1';" << std::endl; - stream << " elsif rising_edge(clk) and stall = '0' then" << std::endl; - stream << " if spontaneous_en = '1' then" << std::endl; - stream << " spontaneous_en <= optimal_transition_set_combined_sig;" << std::endl; - stream << " else" << std::endl; - //TODO if new event is dequeued then 1 else stay 0 - stream << " spontaneous_en <= next_event_dequeued;" << std::endl; - stream << " end if;" << std::endl; - stream << " end if;" << std::endl; - stream << "end process;" << std::endl; - stream << std::endl; + // sets spontaneous signal + stream << "-- spontaneous handler" << std::endl; + stream << "spontaneous_handler : process (clk, rst) " << std::endl; + stream << "begin" << std::endl; + stream << " if rst = '1' then" << std::endl; + stream << " spontaneous_en <= '1';" << std::endl; + stream << " elsif rising_edge(clk) and stall = '0' then" << std::endl; + stream << " if spontaneous_en = '1' then" << std::endl; + stream << " spontaneous_en <= optimal_transition_set_combined_sig;" << std::endl; + stream << " else" << std::endl; + //TODO if new event is dequeued then 1 else stay 0 + stream << " spontaneous_en <= next_event_dequeued;" << std::endl; + stream << " end if;" << std::endl; + stream << " end if;" << std::endl; + stream << "end process;" << std::endl; + stream << std::endl; } void ChartToVHDL::writeInternalEventHandler(std::ostream & stream) { - // Add controler specific stuff here - stream << "-- event handler" << std::endl; - stream << "-- pops events and set event signals" << std::endl; - stream << "event_handler : process (clk, rst) " << std::endl; - stream << "begin" << std::endl; - stream << " if rst = '1' then" << std::endl; - - std::list<TrieNode*> eventNames = _eventTrie.getWordsWithPrefix(""); - for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { - stream << " event_" << eventNameEscape((*eventIter)->value) << "_sig <= '0';" << std::endl; - } - - stream << " next_event_dequeued <= '0';" << std::endl; - stream << " event_consumed <= '0';" << std::endl; - - stream << " elsif falling_edge(clk) and stall = '0' then" << std::endl; - - VContainer eventConsumed = VOR; - for (auto transition : _transitions) { - - if (HAS_ATTR(transition, "event") == true) { - *eventConsumed += VLINE("in_optimal_transition_set_" - + ATTR(transition, "postFixOrder") + "_sig"); - } - } - - VBranch* tree = (VASSIGN, - VLINE("event_consumed"), - eventConsumed); - tree->print(stream); - stream << ";" << std::endl; - - stream << " if int_event_empty = '0' then " << std::endl; - stream << " case next_event is " << std::endl; - for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { - stream << " when hwe_" - << eventNameEscape((*eventIter)->value) << " =>" << std::endl; - for (std::list<TrieNode*>::iterator eventIter2 = eventNames.begin(); eventIter2 != eventNames.end(); eventIter2++) { - stream << " event_" << eventNameEscape((*eventIter2)->value); - if (eventNameEscape((*eventIter)->value) == eventNameEscape((*eventIter2)->value)) { - stream << "_sig <= '1';" << std::endl; - } else { - stream << "_sig <= '0';" << std::endl; - } - } - stream << " next_event_dequeued <= '1';" << std::endl; - } - stream << " when others =>" << std::endl; - for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { - stream << " event_" << eventNameEscape((*eventIter)->value) << "_sig <= '0';" << std::endl; - } - stream << " next_event_dequeued <= '0';" << std::endl; - stream << " end case;" << std::endl; - stream << " elsif int_event_empty = '1' and event_consumed = '1' then" << std::endl; - - for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { - stream << " event_" << eventNameEscape((*eventIter)->value) << "_sig <= '0';" << std::endl; - } - stream << " next_event_dequeued <= '0';" << std::endl; - stream << " end if;" << std::endl; - stream << " end if;" << std::endl; - stream << "end process;" << std::endl; - stream << std::endl; - - stream << "next_event_re <= not int_event_empty and not stall; " << std::endl; - stream << "next_event <= int_event_output; " << std::endl; - stream << "int_event_write_en <= next_event_we_i; " << std::endl; - stream << "int_event_input <= next_event_i; " << std::endl; - stream << "int_event_read_en <= not stall; --not spontaneous_en and " << std::endl; - stream << std::endl; + // Add controler specific stuff here + stream << "-- event handler" << std::endl; + stream << "-- pops events and set event signals" << std::endl; + stream << "event_handler : process (clk, rst) " << std::endl; + stream << "begin" << std::endl; + stream << " if rst = '1' then" << std::endl; + + std::list<TrieNode*> eventNames = _eventTrie.getWordsWithPrefix(""); + for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { + stream << " event_" << eventNameEscape((*eventIter)->value) << "_sig <= '0';" << std::endl; + } + + stream << " next_event_dequeued <= '0';" << std::endl; + stream << " event_consumed <= '0';" << std::endl; + + stream << " elsif falling_edge(clk) and stall = '0' then" << std::endl; + + VContainer eventConsumed = VOR; + for (auto transition : _transitions) { + + if (HAS_ATTR(transition, "event") == true) { + *eventConsumed += VLINE("in_optimal_transition_set_" + + ATTR(transition, "postFixOrder") + "_sig"); + } + } + + VBranch* tree = (VASSIGN, + VLINE("event_consumed"), + eventConsumed); + tree->print(stream); + stream << ";" << std::endl; + + stream << " if int_event_empty = '0' then " << std::endl; + stream << " case next_event is " << std::endl; + for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { + stream << " when hwe_" + << eventNameEscape((*eventIter)->value) << " =>" << std::endl; + for (std::list<TrieNode*>::iterator eventIter2 = eventNames.begin(); eventIter2 != eventNames.end(); eventIter2++) { + stream << " event_" << eventNameEscape((*eventIter2)->value); + if (eventNameEscape((*eventIter)->value) == eventNameEscape((*eventIter2)->value)) { + stream << "_sig <= '1';" << std::endl; + } else { + stream << "_sig <= '0';" << std::endl; + } + } + stream << " next_event_dequeued <= '1';" << std::endl; + } + stream << " when others =>" << std::endl; + for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { + stream << " event_" << eventNameEscape((*eventIter)->value) << "_sig <= '0';" << std::endl; + } + stream << " next_event_dequeued <= '0';" << std::endl; + stream << " end case;" << std::endl; + stream << " elsif int_event_empty = '1' and event_consumed = '1' then" << std::endl; + + for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { + stream << " event_" << eventNameEscape((*eventIter)->value) << "_sig <= '0';" << std::endl; + } + stream << " next_event_dequeued <= '0';" << std::endl; + stream << " end if;" << std::endl; + stream << " end if;" << std::endl; + stream << "end process;" << std::endl; + stream << std::endl; + + stream << "next_event_re <= not int_event_empty and not stall; " << std::endl; + stream << "next_event <= int_event_output; " << std::endl; + stream << "int_event_write_en <= next_event_we_i; " << std::endl; + stream << "int_event_input <= next_event_i; " << std::endl; + stream << "int_event_read_en <= not stall; --not spontaneous_en and " << std::endl; + stream << std::endl; } void ChartToVHDL::writeActiveStateNplusOne(std::ostream & stream) { - stream << "-- active configuration" << std::endl; + stream << "-- active configuration" << std::endl; - size_t i = 0; - for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) { + size_t i = 0; + for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) { // DOMElement* state = *stateIter; - // TÖDO: is there a case where complete entry set reflects not the next state ? - VBranch* tree = (VASSIGN, - VLINE("state_next_" + toStr(i) + "_sig"), - (VOR, - VLINE("in_complete_entry_set_" + toStr(i) + "_sig"), - (VAND, (VNOT, VLINE("in_exit_set_" + toStr(i) + "_sig")), VLINE("state_active_" + toStr(i) + "_sig")) - ) ); - - tree->print(stream); - stream << ";" << std::endl; - - } + // TÖDO: is there a case where complete entry set reflects not the next state ? + VBranch* tree = (VASSIGN, + VLINE("state_next_" + toStr(i) + "_sig"), + (VOR, + VLINE("in_complete_entry_set_" + toStr(i) + "_sig"), + (VAND, (VNOT, VLINE("in_exit_set_" + toStr(i) + "_sig")), VLINE("state_active_" + toStr(i) + "_sig")) + ) ); + + tree->print(stream); + stream << ";" << std::endl; + + } } void ChartToVHDL::writeOptimalTransitionSetSelection(std::ostream & stream) { - stream << "-- optimal transition set selection" << std::endl; - VContainer optimalTransitions = VOR; - VContainer spontaneoursActive = VOR; - size_t i = 0; - for (auto transIter = _transitions.begin(); transIter != _transitions.end(); transIter++, i++) { - DOMElement* transition = *transIter; - std::string conflicts = ATTR(transition, "conflictBools"); - - - VContainer nameMatchers = VOR; - if (HAS_ATTR(transition, "event")) { - std::list<std::string> eventDescs = tokenize(ATTR(transition, "event")); - for (std::list<std::string>::iterator descIter = eventDescs.begin(); descIter != eventDescs.end(); descIter++) { - std::list<TrieNode*> eventNames = _eventTrie.getWordsWithPrefix((*descIter) == "*" ? "" : *descIter); - for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { - *nameMatchers += VLINE("event_" + eventNameEscape((*eventIter)->value) + "_sig"); - } - } - } else { - *nameMatchers += VLINE("'1'"); - } - - VContainer conflicters = VOR; - for (size_t j = 0; j < i; j++) { - if (conflicts[j] == '1') { - *conflicters += VLINE("in_optimal_transition_set_" + toStr(j) + "_sig"); - } - } - - VBranch* tree = (VASSIGN, - VLINE("in_optimal_transition_set_" + ATTR(transition, "postFixOrder") + "_sig"), - (VAND, - (HAS_ATTR(transition, "event") - ? (VNOT, VLINE("spontaneous_active")) - : (VNOP, VLINE("spontaneous_en"))), - VLINE("state_active_" + ATTR(transition, "source") + "_sig"), - nameMatchers, - (VNOT, conflicters))); - - tree->print(stream); - stream << ";" << std::endl; - - *optimalTransitions += VLINE("in_optimal_transition_set_" - + ATTR(transition, "postFixOrder") + "_sig"); - if (HAS_ATTR(transition, "event") == false) { - *spontaneoursActive += VLINE("in_optimal_transition_set_" - + ATTR(transition, "postFixOrder") + "_sig"); - } - } - - VBranch* tree = (VASSIGN, - VLINE("optimal_transition_set_combined_sig"), - optimalTransitions); - tree->print(stream); - stream << ";" << std::endl; - - VBranch* tree2 = (VASSIGN, - VLINE("spontaneous_active"), - spontaneoursActive); - tree2->print(stream); - stream << ";" << std::endl; + stream << "-- optimal transition set selection" << std::endl; + VContainer optimalTransitions = VOR; + VContainer spontaneoursActive = VOR; + size_t i = 0; + for (auto transIter = _transitions.begin(); transIter != _transitions.end(); transIter++, i++) { + DOMElement* transition = *transIter; + std::string conflicts = ATTR(transition, "conflictBools"); + + + VContainer nameMatchers = VOR; + if (HAS_ATTR(transition, "event")) { + std::list<std::string> eventDescs = tokenize(ATTR(transition, "event")); + for (std::list<std::string>::iterator descIter = eventDescs.begin(); descIter != eventDescs.end(); descIter++) { + std::list<TrieNode*> eventNames = _eventTrie.getWordsWithPrefix((*descIter) == "*" ? "" : *descIter); + for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { + *nameMatchers += VLINE("event_" + eventNameEscape((*eventIter)->value) + "_sig"); + } + } + } else { + *nameMatchers += VLINE("'1'"); + } + + VContainer conflicters = VOR; + for (size_t j = 0; j < i; j++) { + if (conflicts[j] == '1') { + *conflicters += VLINE("in_optimal_transition_set_" + toStr(j) + "_sig"); + } + } + + VBranch* tree = (VASSIGN, + VLINE("in_optimal_transition_set_" + ATTR(transition, "postFixOrder") + "_sig"), + (VAND, + (HAS_ATTR(transition, "event") + ? (VNOT, VLINE("spontaneous_active")) + : (VNOP, VLINE("spontaneous_en"))), + VLINE("state_active_" + ATTR(transition, "source") + "_sig"), + nameMatchers, + (VNOT, conflicters))); + + tree->print(stream); + stream << ";" << std::endl; + + *optimalTransitions += VLINE("in_optimal_transition_set_" + + ATTR(transition, "postFixOrder") + "_sig"); + if (HAS_ATTR(transition, "event") == false) { + *spontaneoursActive += VLINE("in_optimal_transition_set_" + + ATTR(transition, "postFixOrder") + "_sig"); + } + } + + VBranch* tree = (VASSIGN, + VLINE("optimal_transition_set_combined_sig"), + optimalTransitions); + tree->print(stream); + stream << ";" << std::endl; + + VBranch* tree2 = (VASSIGN, + VLINE("spontaneous_active"), + spontaneoursActive); + tree2->print(stream); + stream << ";" << std::endl; } void ChartToVHDL::writeExitSet(std::ostream & stream) { - stream << "-- exit set selection" << std::endl; - - size_t i = 0; - for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) { - DOMElement* state = *stateIter; - - std::string completion = ATTR(state, "completionBools"); - std::string ancestors = ATTR(state, "ancBools"); - std::string children = ATTR(state, "childBools"); - std::string parent = ATTR(state, "parent"); - - VContainer exitsetters = VOR; - size_t j = 0; - for (auto transIter = _transitions.begin(); transIter != _transitions.end(); transIter++, j++) { - DOMElement* transition = *transIter; - std::string exitSet = ATTR(transition, "exitSetBools"); - if (exitSet[i] == '1') { - *exitsetters += VLINE("in_optimal_transition_set_" + toStr(j) + "_sig "); - } - } - - VBranch* tree = (VASSIGN, - VLINE("in_exit_set_" + toStr(i) + "_sig"), - (VAND, - VLINE("state_active_" + toStr(i) + "_sig"), - exitsetters)); - - tree->print(stream); - stream << ";" << std::endl; - } + stream << "-- exit set selection" << std::endl; + + size_t i = 0; + for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) { + DOMElement* state = *stateIter; + + std::string completion = ATTR(state, "completionBools"); + std::string ancestors = ATTR(state, "ancBools"); + std::string children = ATTR(state, "childBools"); + std::string parent = ATTR(state, "parent"); + + VContainer exitsetters = VOR; + size_t j = 0; + for (auto transIter = _transitions.begin(); transIter != _transitions.end(); transIter++, j++) { + DOMElement* transition = *transIter; + std::string exitSet = ATTR(transition, "exitSetBools"); + if (exitSet[i] == '1') { + *exitsetters += VLINE("in_optimal_transition_set_" + toStr(j) + "_sig "); + } + } + + VBranch* tree = (VASSIGN, + VLINE("in_exit_set_" + toStr(i) + "_sig"), + (VAND, + VLINE("state_active_" + toStr(i) + "_sig"), + exitsetters)); + + tree->print(stream); + stream << ";" << std::endl; + } } void ChartToVHDL::writeEntrySet(std::ostream & stream) { - stream << "-- entry set selection" << std::endl; - - size_t i = 0; - for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) { - DOMElement* state = *stateIter; - - VBranch* tree = (VASSIGN, - VLINE("in_entry_set_" + toStr(i) + "_sig"), - (VAND, - VLINE("in_complete_entry_set_" + toStr(i) + "_sig"), - (VOR, VLINE("in_exit_set_" + toStr(i) + "_sig"), - (VNOT, VLINE("state_active_" + toStr(i) + "_sig"))))); - - tree->print(stream); - stream << ";" << std::endl; - } + stream << "-- entry set selection" << std::endl; + + size_t i = 0; + for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) { + DOMElement* state = *stateIter; + + VBranch* tree = (VASSIGN, + VLINE("in_entry_set_" + toStr(i) + "_sig"), + (VAND, + VLINE("in_complete_entry_set_" + toStr(i) + "_sig"), + (VOR, VLINE("in_exit_set_" + toStr(i) + "_sig"), + (VNOT, VLINE("state_active_" + toStr(i) + "_sig"))))); + + tree->print(stream); + stream << ";" << std::endl; + } } void ChartToVHDL::writeDefaultCompletions(std::ostream & stream) { - // TODO direct connect the line in complete entry set (no extra line needed ...) - stream << "-- default completion assignments" << std::endl; - stream << "-- indikates if the state for which I am the def-completion is active" << std::endl; - std::map<DOMElement*, std::list<DOMNode*> > completions; - - size_t i = 0; - for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) { - DOMElement* state = *stateIter; - - completions[state]; // initialize other completions to 0 - - // we just need this if parent is a compound state - std::string parent = ATTR(state, "parent"); - - if (getParentState(state) != NULL - && isCompound(getParentState(state))) { - - // Am I default completen ? - std::string completion = ATTR_CAST(_states[strTo<size_t>(parent)], "completionBools"); - if (completion[i] == '1') { - // Yes? then give me the parent line - completions[state].push_back(getParentState(state)); - - } - } - } - - auto complIter = completions.begin(); - while (complIter != completions.end()) { - const DOMElement* state(complIter->first); - const std::list<DOMNode*> refs(complIter->second); - - std::string index = ATTR(state, "documentOrder"); - VContainer defaultCompleters = VOR; - - for (auto ref : refs) { - // *defaultCompleters += VLINE("in_complete_entry_set_" + - // TODO: default completion just when state is entered the first time ? - // if yes then we use the following code. If not we have to revert - *defaultCompleters += VLINE("in_entry_set_" + - ATTR_CAST(ref, "documentOrder") + "_sig "); - } - - VBranch* tree = (VASSIGN, - VLINE("default_completion_" + index + "_sig"), defaultCompleters); - - tree->print(stream); - stream << ";" << std::endl; - - complIter++; - } + // TODO direct connect the line in complete entry set (no extra line needed ...) + stream << "-- default completion assignments" << std::endl; + stream << "-- indikates if the state for which I am the def-completion is active" << std::endl; + std::map<DOMElement*, std::list<DOMNode*> > completions; + + size_t i = 0; + for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) { + DOMElement* state = *stateIter; + + completions[state]; // initialize other completions to 0 + + // we just need this if parent is a compound state + std::string parent = ATTR(state, "parent"); + + if (getParentState(state) != NULL + && isCompound(getParentState(state))) { + + // Am I default completen ? + std::string completion = ATTR_CAST(_states[strTo<size_t>(parent)], "completionBools"); + if (completion[i] == '1') { + // Yes? then give me the parent line + completions[state].push_back(getParentState(state)); + + } + } + } + + auto complIter = completions.begin(); + while (complIter != completions.end()) { + const DOMElement* state(complIter->first); + const std::list<DOMNode*> refs(complIter->second); + + std::string index = ATTR(state, "documentOrder"); + VContainer defaultCompleters = VOR; + + for (auto ref : refs) { + // *defaultCompleters += VLINE("in_complete_entry_set_" + + // TODO: default completion just when state is entered the first time ? + // if yes then we use the following code. If not we have to revert + *defaultCompleters += VLINE("in_entry_set_" + + ATTR_CAST(ref, "documentOrder") + "_sig "); + } + + VBranch* tree = (VASSIGN, + VLINE("default_completion_" + index + "_sig"), defaultCompleters); + + tree->print(stream); + stream << ";" << std::endl; + + complIter++; + } } void ChartToVHDL::writeCompleteEntrySet(std::ostream & stream) { - stream << "-- complete entry set selection" << std::endl; - - size_t i = 0; - for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) { - DOMElement* state = *stateIter; - - std::string completion = ATTR(state, "completionBools"); - std::string ancestors = ATTR(state, "ancBools"); - std::string children = ATTR(state, "childBools"); - std::string parent = ATTR(state, "parent"); - - VContainer optimalEntrysetters = VOR; - size_t j = 0; - for (auto transIter = _transitions.begin(); transIter != _transitions.end(); transIter++, j++) { - DOMElement* transition = *transIter; - - std::string targetSet = ATTR(transition, "targetBools"); - if (targetSet[i] == '1') {// <- ? TODO Was ist hier der vergleich? - *optimalEntrysetters += VLINE("in_optimal_transition_set_" + toStr(j) + "_sig"); - } - } - - VContainer completeEntrysetters = VOR; - stream << "--" << state->getNodeName() << std::endl; // for debugging - if (isCompound(state) || isParallel(state)) { // <- true for scxml? TODO - for (size_t j = 0; j < _states.size(); j++) { - if (children[j] != '1') // if is child of state j - continue; - *completeEntrysetters += VLINE("in_complete_entry_set_up_" + toStr(j) + "_sig"); - } - } - - VBranch* tree = (VASSIGN, - VLINE("in_complete_entry_set_up_" + toStr(i) + "_sig"), - (VOR, optimalEntrysetters, completeEntrysetters) - ); - tree->print(stream); - stream << ";" << std::endl; + stream << "-- complete entry set selection" << std::endl; + + size_t i = 0; + for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) { + DOMElement* state = *stateIter; + + std::string completion = ATTR(state, "completionBools"); + std::string ancestors = ATTR(state, "ancBools"); + std::string children = ATTR(state, "childBools"); + std::string parent = ATTR(state, "parent"); + + VContainer optimalEntrysetters = VOR; + size_t j = 0; + for (auto transIter = _transitions.begin(); transIter != _transitions.end(); transIter++, j++) { + DOMElement* transition = *transIter; + + std::string targetSet = ATTR(transition, "targetBools"); + if (targetSet[i] == '1') {// <- ? TODO Was ist hier der vergleich? + *optimalEntrysetters += VLINE("in_optimal_transition_set_" + toStr(j) + "_sig"); + } + } + + VContainer completeEntrysetters = VOR; + stream << "--" << state->getNodeName() << std::endl; // for debugging + if (isCompound(state) || isParallel(state)) { // <- true for scxml? TODO + for (size_t j = 0; j < _states.size(); j++) { + if (children[j] != '1') // if is child of state j + continue; + *completeEntrysetters += VLINE("in_complete_entry_set_up_" + toStr(j) + "_sig"); + } + } + + VBranch* tree = (VASSIGN, + VLINE("in_complete_entry_set_up_" + toStr(i) + "_sig"), + (VOR, optimalEntrysetters, completeEntrysetters) + ); + tree->print(stream); + stream << ";" << std::endl; #if 0 - stream << "in_complete_entry_set_up_" << toStr(i) << "_sig <= ('0'" << std::endl; - - for (size_t j = 0; j < _transitions.size(); j++) { - Element<std::string> transition(_transitions[j]); - // std::cout << transition; - std::string targetSet = ATTR(transition, "targetBools"); - if (targetSet[i] == '1') { - stream << " or in_optimal_transition_set_" << toStr(j) << std::endl; - } - } - if (isCompound(state)) { - for (size_t j = 0; j < _states.size(); j++) { - if (children[j] != '1') - continue; - - stream << " or in_complete_entry_set_up_" << toStr(j) << "_sig" << std::endl; - } - - } - stream << ");" << std::endl; + stream << "in_complete_entry_set_up_" << toStr(i) << "_sig <= ('0'" << std::endl; + + for (size_t j = 0; j < _transitions.size(); j++) { + Element<std::string> transition(_transitions[j]); + // std::cout << transition; + std::string targetSet = ATTR(transition, "targetBools"); + if (targetSet[i] == '1') { + stream << " or in_optimal_transition_set_" << toStr(j) << std::endl; + } + } + if (isCompound(state)) { + for (size_t j = 0; j < _states.size(); j++) { + if (children[j] != '1') + continue; + + stream << " or in_complete_entry_set_up_" << toStr(j) << "_sig" << std::endl; + } + + } + stream << ");" << std::endl; #endif - } - - for (auto state : _states) { - std::string completion = ATTR(state, "completionBools"); - std::string ancestors = ATTR(state, "ancBools"); - std::string parent = ATTR(state, "parent"); - - if (parent.size() == 0) { - continue; // TODO: FixMe <scxml> <-- ? - } - - VContainer tmp1 = VAND; - // if parent is compound - if (getParentState(state) != NULL && - isCompound(getParentState(state))) { - std::string children = ATTR_CAST(_states[strTo<size_t>(parent)], - "childBools"); - // TODO: do not add default_completion line if not needed - // --> just if this state is the default completion of parent - // --> init attr. or if not present first in document order <-- = completion bool ? - *tmp1 += VLINE("default_completion_" + ATTR(state, "documentOrder") + "_sig"); - - //TODO check this - for (size_t j = 0; j < _states.size(); j++) { - if (children[j] != '1') - continue; - *tmp1 += (VAND, - (VNOT, - (VAND, - VLINE("state_active_" + toStr(j) + "_sig"), - (VNOT, - VLINE("in_exit_set_" + toStr(j) + "_sig"))))); - - } - - } - - // if parent is parallel - if (getParentState(state) != NULL && - isParallel(getParentState(state))) { - *tmp1 += VLINE("in_complete_entry_set_" + toStr(parent) + "_sig"); - } - - VBranch* tree = (VASSIGN, - VLINE("in_complete_entry_set_" + toStr(i) + "_sig"), - (VOR, - VLINE("in_complete_entry_set_up_" + ATTR(state, "documentOrder") + "_sig"), - tmp1)); - - tree->print(stream); - stream << ";" << std::endl; + } + + for (auto state : _states) { + std::string completion = ATTR(state, "completionBools"); + std::string ancestors = ATTR(state, "ancBools"); + std::string parent = ATTR(state, "parent"); + + if (parent.size() == 0) { + continue; // TODO: FixMe <scxml> <-- ? + } + + VContainer tmp1 = VAND; + // if parent is compound + if (getParentState(state) != NULL && + isCompound(getParentState(state))) { + std::string children = ATTR_CAST(_states[strTo<size_t>(parent)], + "childBools"); + // TODO: do not add default_completion line if not needed + // --> just if this state is the default completion of parent + // --> init attr. or if not present first in document order <-- = completion bool ? + *tmp1 += VLINE("default_completion_" + ATTR(state, "documentOrder") + "_sig"); + + //TODO check this + for (size_t j = 0; j < _states.size(); j++) { + if (children[j] != '1') + continue; + *tmp1 += (VAND, + (VNOT, + (VAND, + VLINE("state_active_" + toStr(j) + "_sig"), + (VNOT, + VLINE("in_exit_set_" + toStr(j) + "_sig"))))); + + } + + } + + // if parent is parallel + if (getParentState(state) != NULL && + isParallel(getParentState(state))) { + *tmp1 += VLINE("in_complete_entry_set_" + toStr(parent) + "_sig"); + } + + VBranch* tree = (VASSIGN, + VLINE("in_complete_entry_set_" + toStr(i) + "_sig"), + (VOR, + VLINE("in_complete_entry_set_up_" + ATTR(state, "documentOrder") + "_sig"), + tmp1)); + + tree->print(stream); + stream << ";" << std::endl; #if 0 - stream << "in_complete_entry_set_" << toStr(i) << "_sig <= (in_complete_entry_set_up_" << toStr(i) << "_sig or (" << std::endl; + stream << "in_complete_entry_set_" << toStr(i) << "_sig <= (in_complete_entry_set_up_" << toStr(i) << "_sig or (" << std::endl; - if (isParallel(Element<std::string>(_states[strTo<size_t>(parent)]))) { - stream << " in_complete_entry_set_" << toStr(parent) << "_sig" << std::endl; - } else if (isCompound(Element<std::string>(_states[strTo<size_t>(parent)]))) { - stream << " default_completion_" << toStr(parent) << "_sig" << std::endl; + if (isParallel(Element<std::string>(_states[strTo<size_t>(parent)]))) { + stream << " in_complete_entry_set_" << toStr(parent) << "_sig" << std::endl; + } else if (isCompound(Element<std::string>(_states[strTo<size_t>(parent)]))) { + stream << " default_completion_" << toStr(parent) << "_sig" << std::endl; - for (size_t j = 0; j < _states.size(); j++) { - if (children[j] != '1') - continue; - stream << " and not (is_active" << toStr(j) << "_sig and not in_exit_set_" << toStr(j) << "_sig)" << std::endl; + for (size_t j = 0; j < _states.size(); j++) { + if (children[j] != '1') + continue; + stream << " and not (is_active" << toStr(j) << "_sig and not in_exit_set_" << toStr(j) << "_sig)" << std::endl; - } - } + } + } - stream << ");" << std::endl; + stream << ");" << std::endl; #endif - } + } } void ChartToVHDL::writeStateHandler(std::ostream & stream) { - // updater for current state - stream << "-- State Handler" << std::endl; - stream << "-- updates current state" << std::endl; - stream << "state_proc: process(clk, rst, stall)" << std::endl; - stream << "begin" << std::endl; - stream << " if rst = '1' then" << std::endl; - - size_t i = 0; - for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) { + // updater for current state + stream << "-- State Handler" << std::endl; + stream << "-- updates current state" << std::endl; + stream << "state_proc: process(clk, rst, stall)" << std::endl; + stream << "begin" << std::endl; + stream << " if rst = '1' then" << std::endl; + + size_t i = 0; + for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) { // DOMElement* state = *stateIter; - stream << " state_active_" << toStr(i) << "_sig <= " << "'0';" << std::endl; - } - - stream << " in_complete_entry_set_0_sig <= '1';" << std::endl; - stream << " elsif (rising_edge(clk) and stall = '0') then" << std::endl; - stream << " in_complete_entry_set_0_sig <= '0';" << std::endl; - - i = 0; - for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) { - // DOMElement* state = *stateIter; - stream << " state_active_" << toStr(i) << "_sig <= " << "state_next_" << toStr(i) << "_sig;" << std::endl; - } - - stream << " end if;" << std::endl; - stream << "end process;" << std::endl; - stream << std::endl; + stream << " state_active_" << toStr(i) << "_sig <= " << "'0';" << std::endl; + } + + stream << " in_complete_entry_set_0_sig <= '1';" << std::endl; + stream << " elsif (rising_edge(clk) and stall = '0') then" << std::endl; + stream << " in_complete_entry_set_0_sig <= '0';" << std::endl; + + i = 0; + for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) { + // DOMElement* state = *stateIter; + stream << " state_active_" << toStr(i) << "_sig <= " << "state_next_" << toStr(i) << "_sig;" << std::endl; + } + + stream << " end if;" << std::endl; + stream << "end process;" << std::endl; + stream << std::endl; } void ChartToVHDL::writeSystemSignalMapping(std::ostream & stream) { - stream << "-- system signals" << std::endl; - std::list<DOMElement*> topLevelFinal = DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "final", _scxml); - - VContainer tlf = VOR; - for (auto final : topLevelFinal) { - *tlf += VLINE("state_active_" + ATTR(final, "documentOrder") + "_sig"); - - } - - VBranch* tree = (VASSIGN, - VLINE("completed_sig"), - tlf); - - tree->print(stream); - stream << ";" << std::endl; - - // tmp mapping for events - stream << "stall <= not en or completed_sig or ( int_event_empty and not spontaneous_en ) ; " << std::endl; - stream << std::endl; - - // interface signals - stream << "-- interface signals" << std::endl; - for (auto state : _states) { - stream << "state_active_" << ATTR(state, "documentOrder") - << "_o <= state_active_" << ATTR(state, "documentOrder") - << "_sig;" << std::endl; - if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) { - stream << "exit_set_" << ATTR(state, "documentOrder") - << "_o <= in_exit_set_" << ATTR(state, "documentOrder") - << "_sig;" << std::endl; - } - - if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) { - stream << "entry_set_" << ATTR(state, "documentOrder") - << "_o <= in_entry_set_" << ATTR(state, "documentOrder") - << "_sig;" << std::endl; - } - } - - for (auto transition : _transitions) { - if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) { - stream << "transition_set_" << ATTR(transition, "postFixOrder") - << "_o <= in_optimal_transition_set_" << ATTR(transition, "postFixOrder") - << "_sig;" << std::endl; - } - } - - stream << "completed_o <= completed_sig; " << std::endl; - stream << "error_o <= reg_error_out; " << std::endl; - stream << std::endl; + stream << "-- system signals" << std::endl; + std::list<DOMElement*> topLevelFinal = DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "final", _scxml); + + VContainer tlf = VOR; + for (auto final : topLevelFinal) { + *tlf += VLINE("state_active_" + ATTR(final, "documentOrder") + "_sig"); + + } + + VBranch* tree = (VASSIGN, + VLINE("completed_sig"), + tlf); + + tree->print(stream); + stream << ";" << std::endl; + + // tmp mapping for events + stream << "stall <= not en or completed_sig or ( int_event_empty and not spontaneous_en ) ; " << std::endl; + stream << std::endl; + + // interface signals + stream << "-- interface signals" << std::endl; + for (auto state : _states) { + stream << "state_active_" << ATTR(state, "documentOrder") + << "_o <= state_active_" << ATTR(state, "documentOrder") + << "_sig;" << std::endl; + if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) { + stream << "exit_set_" << ATTR(state, "documentOrder") + << "_o <= in_exit_set_" << ATTR(state, "documentOrder") + << "_sig;" << std::endl; + } + + if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) { + stream << "entry_set_" << ATTR(state, "documentOrder") + << "_o <= in_entry_set_" << ATTR(state, "documentOrder") + << "_sig;" << std::endl; + } + } + + for (auto transition : _transitions) { + if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) { + stream << "transition_set_" << ATTR(transition, "postFixOrder") + << "_o <= in_optimal_transition_set_" << ATTR(transition, "postFixOrder") + << "_sig;" << std::endl; + } + } + + stream << "completed_o <= completed_sig; " << std::endl; + stream << "error_o <= reg_error_out; " << std::endl; + stream << std::endl; } }
\ No newline at end of file diff --git a/src/uscxml/transform/ChartToVHDL.h b/src/uscxml/transform/ChartToVHDL.h index 85fd30d..0a58b4e 100644 --- a/src/uscxml/transform/ChartToVHDL.h +++ b/src/uscxml/transform/ChartToVHDL.h @@ -161,19 +161,19 @@ protected: void writeTypes(std::ostream& stream); void writeIncludes(std::ostream& stream); - - // top layer components + + // top layer components void writeFiFo(std::ostream& stream); void writeEventController(std::ostream & stream); void writeMicroStepper(std::ostream& stream); void writeTestbench(std::ostream & stream); - - // system + + // system void writeSignalsAndComponents(std::ostream& stream); void writeSystemSignalMapping(std::ostream& stream); void writeModuleInstantiation(std::ostream& stream); - // combinatorial logic + // combinatorial logic void writeOptimalTransitionSetSelection(std::ostream& stream); void writeExitSet(std::ostream & stream); void writeEntrySet(std::ostream & stream); @@ -182,24 +182,24 @@ protected: void writeCompleteEntrySet(std::ostream & stream); void writeActiveStateNplusOne(std::ostream & stream); - // handler + // handler void writeStateHandler(std::ostream& stream); void writeResetHandler(std::ostream & stream); void writeSpontaneousHandler(std::ostream & stream); void writeInternalEventHandler(std::ostream & stream); void writeErrorHandler(std::ostream& stream); - - // event generation - void writeExContentBlock(std::ostream & stream, std::string index, - std::list< XERCESC_NS::DOMElement* > commandSequence); - + + // event generation + void writeExContentBlock(std::ostream & stream, std::string index, + std::list< XERCESC_NS::DOMElement* > commandSequence); + Trie _eventTrie; - std::list< XERCESC_NS::DOMElement* > _execContent; + std::list< XERCESC_NS::DOMElement* > _execContent; private: std::string eventNameEscape(const std::string& eventName); - std::string getLineForExecContent(const XERCESC_NS::DOMNode* elem); + std::string getLineForExecContent(const XERCESC_NS::DOMNode* elem); }; diff --git a/src/uscxml/transform/promela/PromelaCodeAnalyzer.cpp b/src/uscxml/transform/promela/PromelaCodeAnalyzer.cpp new file mode 100644 index 0000000..4d1d8d5 --- /dev/null +++ b/src/uscxml/transform/promela/PromelaCodeAnalyzer.cpp @@ -0,0 +1,596 @@ +/** + * @file + * @author 2016 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see <http://www.opensource.org/licenses/bsd-license>. + * @endcond + */ + +#define MAX_MACRO_CHARS 64 + +#include "PromelaCodeAnalyzer.h" +#include "uscxml/transform/ChartToPromela.h" +#include "uscxml/util/Predicates.h" +#include "uscxml/util/DOM.h" +#include "uscxml/util/String.h" + +#include <boost/algorithm/string.hpp> + +namespace uscxml { + +using namespace XERCESC_NS; + +void PromelaCodeAnalyzer::analyze(ChartToPromela* interpreter) { + + /** + Create macro names for state identifiers + Do not add as literals as they are not unique with nested state-charts + */ + { + for (size_t i = 0; i < interpreter->_states.size(); i++) { + DOMElement* state = interpreter->_states[i]; + if (HAS_ATTR(state, "id")) { + createMacroName(ATTR(state, "id")); + } + } + } +// _lastStrIndex = interpreter->_states.size(); + + /** Find all event names that might occur */ + { + std::list<XERCESC_NS::DOMElement*> internalEventNames = DOMUtils::inDocumentOrder({ + XML_PREFIX(interpreter->_scxml).str() + "transition", + XML_PREFIX(interpreter->_scxml).str() + "raise", + XML_PREFIX(interpreter->_scxml).str() + "send" + }, interpreter->_scxml); + + for (auto internalEventName : internalEventNames) { + if (HAS_ATTR_CAST(internalEventName, "event")) { + std::string eventNames = ATTR_CAST(internalEventName, "event"); + std::list<std::string> events = tokenize(eventNames); + for (std::list<std::string>::iterator eventIter = events.begin(); + eventIter != events.end(); eventIter++) { + std::string eventName = *eventIter; + if (boost::ends_with(eventName, "*")) + eventName = eventName.substr(0, eventName.size() - 1); + if (boost::ends_with(eventName, ".")) + eventName = eventName.substr(0, eventName.size() - 1); + if (eventName.size() > 0) + _eventTrie.addWord(eventName); + } + } + } + + for (auto state : interpreter->_states) { + if (HAS_ATTR(state, "id") && (isCompound(state) || isParallel(state))) { + _eventTrie.addWord("done.state." + ATTR(state, "id")); + } + } + } + + // add event names from trie to string literals + std::list<TrieNode*> events = _eventTrie.getWordsWithPrefix(""); + for (auto event : events) { + addLiteral(event->value); + } + + + /** Find all string literals */ + { + // string literals for raise / send content + std::list<XERCESC_NS::DOMElement*> contents = DOMUtils::inDocumentOrder({ + XML_PREFIX(interpreter->_scxml).str() + "content" + }, interpreter->_scxml); + + for (auto content : contents) { + std::string contentStr = spaceNormalize(X(((DOMElement*)content)->getFirstChild()->getNodeValue())); + if (!isNumeric(contentStr.c_str(), 10)) { + addLiteral(contentStr); + } + } + } + + /* add platform variables as string literals */ + addLiteral(interpreter->_prefix + "_sessionid"); + addLiteral(interpreter->_prefix + "_name"); + + + /** Extract and analyze source code */ + { + std::list<XERCESC_NS::DOMElement*> withCond = DOMUtils::inDocumentOrder({ + XML_PREFIX(interpreter->_scxml).str() + "transition", + XML_PREFIX(interpreter->_scxml).str() + "if", + XML_PREFIX(interpreter->_scxml).str() + "elseif" + }, interpreter->_scxml); + + for (auto cond : withCond) { + if (HAS_ATTR(cond, "cond")) { + std::string code = ATTR_CAST(cond, "cond"); + code = sanitizeCode(code); + addCode(code, interpreter); + cond->setAttribute(X("cond"), X(code)); + } + } + + std::list<XERCESC_NS::DOMElement*> withExpr = DOMUtils::inDocumentOrder({ + XML_PREFIX(interpreter->_scxml).str() + "log", + XML_PREFIX(interpreter->_scxml).str() + "data", + XML_PREFIX(interpreter->_scxml).str() + "assign", + XML_PREFIX(interpreter->_scxml).str() + "content", + XML_PREFIX(interpreter->_scxml).str() + "param" + }, interpreter->_scxml); + + for (auto expr : withExpr) { + if (HAS_ATTR(expr, "expr")) { + std::string code = ATTR_CAST(expr, "expr"); + code = sanitizeCode(code); + addCode(code, interpreter); + expr->setAttribute(X("expr"), X(code)); + } + } + + std::list<XERCESC_NS::DOMElement*> withLocation = DOMUtils::inDocumentOrder({ + XML_PREFIX(interpreter->_scxml).str() + "assign" + }, interpreter->_scxml); + + for (auto location : withLocation) { + if (HAS_ATTR(location, "location")) { + std::string code = ATTR_CAST(location, "location"); + code = sanitizeCode(code); + addCode(code, interpreter); + location->setAttribute(X("location"), X(code)); + } + } + + std::list<XERCESC_NS::DOMElement*> withText = DOMUtils::inDocumentOrder({ + XML_PREFIX(interpreter->_scxml).str() + "script" + }, interpreter->_scxml); + + for (auto text : withText) { + std::list<XERCESC_NS::DOMNode*> texts = DOMUtils::filterChildType(DOMNode::TEXT_NODE, text, true); + for (auto textBlock : texts) { + DOMText* textText = static_cast<DOMText*>(textBlock); + std::string code = X(textText->getNodeValue()).str(); + if (code.size() > 0) { + code = sanitizeCode(code); + addCode(code, interpreter); + textText->setNodeValue(X(code)); + } + } + } + + std::list<XERCESC_NS::DOMElement*> foreachs = DOMUtils::inDocumentOrder({ + XML_PREFIX(interpreter->_scxml).str() + "foreach" + }, interpreter->_scxml); + + for (auto foreach : foreachs) { + if (HAS_ATTR(foreach, "index")) { + addCode(ATTR(foreach, "index"), interpreter); + } else { + _hasIndexLessLoops = true; + } + if (HAS_ATTR(foreach, "item")) { + addCode(ATTR(foreach, "item"), interpreter); + } + } + + // do we need sendid / invokeid? + { + std::list<DOMElement*> invokes = DOMUtils::inDocumentOrder({XML_PREFIX(interpreter->_scxml).str() + "invoke"}, interpreter->_scxml); + std::list<DOMElement*> sends = DOMUtils::inDocumentOrder({XML_PREFIX(interpreter->_scxml).str() + "send"}, interpreter->_scxml); + std::list<DOMElement*> cancels = DOMUtils::inDocumentOrder({XML_PREFIX(interpreter->_scxml).str() + "cancel"}, interpreter->_scxml); + + if (cancels.size() > 0) { + addCode("_event.invokeid", interpreter); + _usesCancel = true; + } + + for (auto send : sends) { + if (HAS_ATTR(send, "idlocation")) { + addCode("_event.sendid", interpreter); + } + if (HAS_ATTR(send, "id")) { + addLiteral(ATTR(send, "id")); + addCode("_event.sendid", interpreter); + } + + // do we need delays? + if (HAS_ATTR(send, "delay") || HAS_ATTR(send, "delayexpr")) { + addCode("_event.delay", interpreter); +#if NEW_DELAY_RESHUFFLE +#else + addCode("_event.seqNr", interpreter); +#endif + } + } + } + + // add all namelist entries to the _event structure + { + std::list<DOMElement*> withNamelists; + withNamelists.splice(withNamelists.end(), DOMUtils::inDocumentOrder({XML_PREFIX(interpreter->_scxml).str() + "send"}, interpreter->_scxml)); + withNamelists.splice(withNamelists.end(), DOMUtils::inDocumentOrder({XML_PREFIX(interpreter->_scxml).str() + "invoke"}, interpreter->_scxml)); + for (auto withNamelist : withNamelists) { + if (HAS_ATTR(withNamelist, "namelist")) { + std::string namelist = ATTR(withNamelist, "namelist"); + std::list<std::string> names = tokenize(namelist); + for (std::list<std::string>::iterator nameIter = names.begin(); nameIter != names.end(); nameIter++) { + addCode("_event.data." + *nameIter + " = 0;", interpreter); // introduce for _event_t typedef + } + } + } + } + + } + +} + +std::string PromelaCodeAnalyzer::sanitizeCode(const std::string& code) { + std::string replaced = code; + boost::replace_all(replaced, "\"", "'"); + boost::replace_all(replaced, "_sessionid", "_SESSIONID"); + boost::replace_all(replaced, "_name", "_NAME"); + return replaced; +} + +void PromelaCodeAnalyzer::addCode(const std::string& code, ChartToPromela* interpreter) { + PromelaParser parser(code); + // parser.dump(); + + // find all strings + std::list<PromelaParserNode*> astNodes; + astNodes.push_back(parser.ast); + + while(astNodes.size() > 0) { + PromelaParserNode* node = astNodes.front(); + astNodes.pop_front(); + + // node->dump(); + + bool hasValue = false; + int assignedValue = 0; + + + switch (node->type) { + case PML_STRING: { + std::string unquoted = node->value; + if (boost::starts_with(unquoted, "'")) { + unquoted = unquoted.substr(1, unquoted.size() - 2); + } + addLiteral(unquoted); + break; + } + case PML_ASGN: + if (node->operands.back()->type == PML_CONST) { + hasValue = true; + if (isInteger(node->operands.back()->value.c_str(), 10)) { + assignedValue = strTo<int>(node->operands.back()->value); + } + } + if (node->operands.back()->type == PML_STRING) { + // remember strings for later + astNodes.push_back(node->operands.back()); + } + if (node->operands.front()->type == PML_CMPND) { + node = node->operands.front(); + } else { + break; + } + // if (node->operands.front()->type != PML_NAME) + // break; // this will skip array assignments + case PML_CMPND: { + std::string nameOfType; + std::list<PromelaParserNode*>::iterator opIter = node->operands.begin(); + if ((*opIter)->type != PML_NAME) { + node->dump(); + return; + assert(false); + } + + PromelaTypedef* td = &_typeDefs; + std::string seperator; + + while(opIter != node->operands.end()) { + switch ((*opIter)->type) { + case PML_NAME: + td = &td->types[(*opIter)->value]; + td->occurrences.insert(interpreter); + + nameOfType += seperator + (*opIter)->value; + if (nameOfType.compare("_x") == 0) + _usesPlatformVars = true; + seperator = "_"; + td->name = nameOfType + "_t"; + break; + case PML_VAR_ARRAY: { + PromelaParserNode* name = (*opIter)->operands.front(); + PromelaParserNode* subscript = *(++(*opIter)->operands.begin()); + td = &td->types[name->value]; + td->occurrences.insert(interpreter); + + nameOfType += seperator + name->value; + td->name = nameOfType + "_t"; + + if (isInteger(subscript->value.c_str(), 10)) { + td->arraySize = strTo<int>(subscript->value); + } + break; + } + default: + if ((*opIter)->type == PML_CONST) { + // break fall through from ASGN + break; + } + // node->dump(); + // assert(false); + break; + } + + if (nameOfType.compare("_x_states") == 0) { + _usesInPredicate = true; + } + if (nameOfType.compare("_event_type") == 0) { + addLiteral("internal"); + addLiteral("external"); + addLiteral("platform"); + } + if (nameOfType.compare("_event_origintype") == 0) { + addLiteral("http://www.w3.org/TR/scxml/#SCXMLEventProcessor"); + } + opIter++; + } + + if (hasValue) { + if (td->maxValue < assignedValue) + td->maxValue = assignedValue; + if (td->minValue > assignedValue) + td->minValue = assignedValue; + } + + continue; // skip processing nested AST nodes + } + case PML_NAME: { + _typeDefs.types[node->value].occurrences.insert(interpreter); + _typeDefs.types[node->value].minValue = 0; + _typeDefs.types[node->value].maxValue = 0; + // test325 + if (node->value.compare("_ioprocessors") == 0) { + addCode("_ioprocessors.scxml.location", interpreter); + } + + break; + } + + default: + // node->dump(); + break; + // assert(false); + } + + astNodes.insert(astNodes.end(), node->operands.begin(), node->operands.end()); + + } +} + +void PromelaCodeAnalyzer::addLiteral(const std::string& literal, int forceIndex) { + if (boost::starts_with(literal, "'")) + throw std::runtime_error("Literal " + literal + " passed with quotes"); + + if (_literals.find(literal) != _literals.end()) + return; + _literals.insert(literal); + createMacroName(literal); + enumerateLiteral(literal, forceIndex); +} + +int PromelaCodeAnalyzer::indexForLiteral(const std::string& literal) { + if (boost::starts_with(literal, "'")) + throw std::runtime_error("Literal " + literal + " passed with quotes"); + + if (_strIndex.find(literal) == _strIndex.end()) + throw std::runtime_error("No index for literal " + literal + " known"); + return _strIndex[literal]; +} + +std::string PromelaCodeAnalyzer::macroForLiteral(const std::string& literal) { + if (boost::starts_with(literal, "'")) + throw std::runtime_error("Literal " + literal + " passed with quotes"); + + if (_strMacros.find(literal) == _strMacros.end()) + throw std::runtime_error("No macro for literal '" + literal + "' known"); + return _strMacros[literal]; +} + + +std::string PromelaCodeAnalyzer::createMacroName(const std::string& literal) { + if (_strMacros.find(literal) != _strMacros.end()) + return _strMacros[literal]; + + // find a suitable macro name for the strings + std::string macroName = literal; //literal.substr(1, literal.size() - 2); + + // cannot start with digit + if (isInteger(macroName.substr(0,1).c_str(), 10)) + macroName = "_" + macroName; + + macroName = macroName.substr(0, MAX_MACRO_CHARS); + boost::to_upper(macroName); + + std::string illegalChars = "#\\/:?\"<>| \n\t()[]{}',.-"; + std::string tmp; + std::string::iterator it = macroName.begin(); + while (it < macroName.end()) { + bool found = illegalChars.find(*it) != std::string::npos; + if(found) { + tmp += '_'; + it++; + while(it < macroName.end() && illegalChars.find(*it) != std::string::npos) { + it++; + } + } else { + tmp += *it++; + } + } + macroName = tmp; + if(macroName.length() < 1) + macroName = "_EMPTY_STRING"; + if(macroName.length() < 2 && macroName[0] == '_') + macroName = "_WEIRD_CHARS"; + + unsigned int index = 2; + while (_macroNameSet.find(macroName) != _macroNameSet.end()) { + std::string suffix = toStr(index); + if (macroName.size() > suffix.size()) { + macroName = macroName.substr(0, macroName.size() - suffix.size()) + suffix; + } else { + macroName = suffix; + } + index++; + } + + _macroNameSet.insert(macroName); + _strMacros[literal] = macroName; + return macroName; +} + +int PromelaCodeAnalyzer::enumerateLiteral(const std::string& literal, int forceIndex) { + if (forceIndex >= 0) { + _strIndex[literal] = forceIndex; + return forceIndex; + } + + if (_strIndex.find(literal) != _strIndex.end()) + return _strIndex[literal]; + + _strIndex[literal] = _lastStrIndex++; + return _lastStrIndex + 1; +} + +std::string PromelaCodeAnalyzer::adaptCode(const std::string& code, const std::string& prefix) { + // for (std::map<std::string, std::string>::const_iterator litIter = _strMacros.begin(); litIter != _strMacros.end(); litIter++) { + // boost::replace_all(replaced, "'" + litIter->first + "'", litIter->second); + // } + // boost::replace_all(replaced, "_event", prefix + "_event"); + // replace all variables from analyzer + + std::string processed = code; + std::stringstream processedStr; + std::list<std::pair<size_t, size_t> > posList; + std::list<std::pair<size_t, size_t> >::iterator posIter; + size_t lastPos; + + // prepend all identifiers with our prefix + { + PromelaParser parsed(processed); + // parsed.dump(); + posList = getTokenPositions(code, PML_NAME, parsed.ast); + posList.sort(); + posIter = posList.begin(); + lastPos = 0; + + while (posIter != posList.end()) { + std::string token = code.substr(posIter->first, posIter->second - posIter->first); + if (std::all_of(token.begin(), token.end(), ::isupper) && false) { + // assume it is a state-name macro + processedStr << code.substr(lastPos, posIter->first - lastPos) << token; + } else { + processedStr << code.substr(lastPos, posIter->first - lastPos) << prefix << token; + } + lastPos = posIter->second; + posIter++; + } + processedStr << processed.substr(lastPos, processed.size() - lastPos); + + processed = processedStr.str(); + processedStr.clear(); + processedStr.str(""); + } + + // replace string literals + { + PromelaParser parsed(processed); + posList = getTokenPositions(code, PML_STRING, parsed.ast); + posList.sort(); + posIter = posList.begin(); + lastPos = 0; + + while (posIter != posList.end()) { + processedStr << processed.substr(lastPos, posIter->first - lastPos); + // std::cout << processed.substr(posIter->first + 1, posIter->second - posIter->first - 2) << std::endl; + assert(_strMacros.find(processed.substr(posIter->first + 1, posIter->second - posIter->first - 2)) != _strMacros.end()); + processedStr << _strMacros[processed.substr(posIter->first + 1, posIter->second - posIter->first - 2)]; + lastPos = posIter->second; + posIter++; + } + processedStr << processed.substr(lastPos, processed.size() - lastPos); + + processed = processedStr.str(); + processedStr.clear(); + processedStr.str(""); + } + + return processed; +} + +std::list<std::pair<size_t, size_t> > PromelaCodeAnalyzer::getTokenPositions(const std::string& expr, int type, PromelaParserNode* ast) { + std::list<std::pair<size_t, size_t> > posList; + if (ast->type == type && ast->loc != NULL) { + // ast->dump(); + if (type == PML_NAME && ast->parent && + ((ast->parent->type == PML_CMPND && ast->parent->operands.front() != ast) || + (ast->parent->parent && ast->parent->type == PML_VAR_ARRAY && ast->parent->parent->type == PML_CMPND))) { + // field in a compound + } else { + if (ast->loc->firstLine == 0) { + posList.push_back(std::make_pair(ast->loc->firstCol, ast->loc->lastCol)); + } else { + int line = ast->loc->firstLine; + size_t lastPos = 0; + while(line > 0) { + lastPos = expr.find_first_of('\n', lastPos + 1); + line--; + } + posList.push_back(std::make_pair(lastPos + ast->loc->firstCol, lastPos + ast->loc->lastCol)); + } + } + } + for (std::list<PromelaParserNode*>::iterator opIter = ast->operands.begin(); opIter != ast->operands.end(); opIter++) { + std::list<std::pair<size_t, size_t> > tmp = getTokenPositions(expr, type, *opIter); + posList.insert(posList.end(), tmp.begin(), tmp.end()); + } + return posList; +} + +std::string PromelaCodeAnalyzer::getTypeReset(const std::string& var, const PromelaTypedef& type, const std::string padding) { + std::stringstream assignment; + + std::map<std::string, PromelaTypedef>::const_iterator typeIter = type.types.begin(); + while(typeIter != type.types.end()) { + const PromelaTypedef& innerType = typeIter->second; + if (innerType.arraySize > 0) { + for (size_t i = 0; i < innerType.arraySize; i++) { + assignment << padding << var << "." << typeIter->first << "[" << i << "] = 0;" << std::endl; + } + } else if (innerType.types.size() > 0) { + assignment << getTypeReset(var + "." + typeIter->first, typeIter->second, padding); + } else { + assignment << padding << var << "." << typeIter->first << " = 0;" << std::endl; + } + typeIter++; + } + return assignment.str(); + +} + +} diff --git a/src/uscxml/transform/promela/PromelaCodeAnalyzer.h b/src/uscxml/transform/promela/PromelaCodeAnalyzer.h new file mode 100644 index 0000000..656b24e --- /dev/null +++ b/src/uscxml/transform/promela/PromelaCodeAnalyzer.h @@ -0,0 +1,150 @@ +/** + * @file + * @author 2016 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see <http://www.opensource.org/licenses/bsd-license>. + * @endcond + */ + +#ifndef PROMELACODEANALYZER_H_E89FF519 +#define PROMELACODEANALYZER_H_E89FF519 + +#include "uscxml/transform/Trie.h" +#include "uscxml/plugins/datamodel/promela/PromelaParser.h" +#include "uscxml/plugins/datamodel/promela/parser/promela.tab.hpp" + +#include <set> + +namespace uscxml { + +class ChartToPromela; + +class USCXML_API PromelaCodeAnalyzer { +public: + class PromelaTypedef { + public: + PromelaTypedef() {} + std::string name; + std::string type; + size_t arraySize = 0; + size_t minValue = 0; + size_t maxValue = 0; + std::map<std::string, PromelaTypedef> types; + std::set<ChartToPromela*> occurrences; + + bool operator==(const PromelaTypedef& other) const { + return name == other.name; + } + + }; + + PromelaCodeAnalyzer() : _eventTrie(".") {} + + void analyze(ChartToPromela* interpreter); + + void addCode(const std::string& code, ChartToPromela* interpreter); + void addLiteral(const std::string& stateName, int forceIndex = -1); + + bool usesComplexEventStruct() { + return _typeDefs.types.find("_event") != _typeDefs.types.end() && _typeDefs.types["_event"].types.size() > 0; + } + bool usesEventField(const std::string& fieldName) { + if (usesComplexEventStruct() && _typeDefs.types["_event"].types.find(fieldName) != _typeDefs.types["_event"].types.end()) + return true; + return false; + } + bool usesCancel(const std::string& elementName) { + return _usesCancel; + } + + bool usesEventDataField(const std::string& fieldName) { + if (usesComplexEventStruct() && + _typeDefs.types["_event"].types.find("data") != _typeDefs.types["_event"].types.end() && + _typeDefs.types["_event"].types["data"].types.find(fieldName) != _typeDefs.types["_event"].types["data"].types.end()) + return true; + return false; + } + + std::string getTypeAssignment(const std::string& varTo, const std::string& varFrom, const PromelaTypedef& type, const std::string padding = ""); + std::string getTypeReset(const std::string& var, const PromelaTypedef& type, const std::string padding = ""); + + bool usesInPredicate() { + return _usesInPredicate; + } + void usesInPredicate(bool value) { + _usesInPredicate = value; + } + bool usesPlatformVars() { + return _usesPlatformVars; + } + + bool hasIndexLessLoops() { + return _hasIndexLessLoops; + } + + std::string macroForLiteral(const std::string& literal); + int indexForLiteral(const std::string& literal); + + std::set<std::string> getLiterals() { + return _literals; + } + std::set<std::string> getEventsWithPrefix(const std::string& prefix); + + Trie& getTrie() { + return _eventTrie; + } + + std::string adaptCode(const std::string& code, const std::string& prefix); + + static std::string prefixIdentifiers(const std::string& expr, const std::string& prefix); + static std::list<std::pair<size_t, size_t> > getTokenPositions(const std::string& expr, int type, PromelaParserNode* ast); + + PromelaTypedef& getTypes() { + return _typeDefs; + } + + PromelaTypedef& getType(const std::string& typeName) { + return _typeDefs.types.at(typeName); + } + + std::string sanitizeCode(const std::string& code); + +protected: + void addEvent(const std::string& eventName); + void addState(const std::string& stateName, size_t index); + + std::string createMacroName(const std::string& literal); + int enumerateLiteral(const std::string& literal, int forceIndex = -1); + + std::map<std::string, std::string> _strMacros; // macronames for string literals + std::map<std::string, int> _strIndex; // integer enumeration for string + std::set<std::string> _literals; + + PromelaTypedef _typeDefs; + Trie _eventTrie; + +private: + std::set<std::string> _macroNameSet; // helper set for uniqueness of macros + int _lastStrIndex = 1; + bool _usesCancel = false; + bool _usesInPredicate = false; + bool _usesPlatformVars = false; + bool _hasIndexLessLoops = false; +}; + + + +} + +#endif /* end of include guard: PROMELACODEANALYZER_H_E89FF519 */ diff --git a/src/uscxml/transform/promela/PromelaInlines.cpp b/src/uscxml/transform/promela/PromelaInlines.cpp new file mode 100644 index 0000000..7d62762 --- /dev/null +++ b/src/uscxml/transform/promela/PromelaInlines.cpp @@ -0,0 +1,165 @@ +/** + * @file + * @author 2016 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see <http://www.opensource.org/licenses/bsd-license>. + * @endcond + */ + +#include "PromelaInlines.h" +#include <boost/algorithm/string.hpp> + +namespace uscxml { + +using namespace XERCESC_NS; + +void PromelaInline::dump() { +} + +PromelaInline::PromelaInline(const XERCESC_NS::DOMNode* node) { + if (node->getNodeType() != DOMNode::COMMENT_NODE && node->getNodeType() != DOMNode::TEXT_NODE) + return; // nothing to do + + std::stringstream ssLine(X(node->getNodeValue()).str()); + std::string line; + + while(std::getline(ssLine, line)) { + // skip to first promela line + boost::trim(line); + if (boost::starts_with(line, "promela")) + break; + } + + if (!boost::starts_with(line, "promela")) + return; + + if (false) { + } else if (boost::starts_with(line, "promela-code")) { + type = PROMELA_CODE; + } else if (boost::starts_with(line, "promela-ltl")) { + type = PROMELA_LTL; + } else if (boost::starts_with(line, "promela-event-all")) { + type = PROMELA_EVENT_ALL_BUT; + } else if (boost::starts_with(line, "promela-event")) { + type = PROMELA_EVENT_ONLY; + } else if (boost::starts_with(line, "promela-progress")) { + type = PROMELA_PROGRESS_LABEL; + } else if (boost::starts_with(line, "promela-accept")) { + type = PROMELA_ACCEPT_LABEL; + } else if (boost::starts_with(line, "promela-end")) { + type = PROMELA_END_LABEL; + } + + std::stringstream contentSS; + size_t endType = line.find_first_of(": \n"); + + std::string seperator; + if (endType != std::string::npos && endType + 1 < line.size()) { + contentSS << line.substr(endType + 1, line.size() - endType + 1); + seperator = "\n"; + } + + while(std::getline(ssLine, line)) { + boost::trim(line); + if (boost::starts_with(line, "promela")) { + std::cerr << "Split multiple #promela pragmas into multiple comments!" << std::endl; + break; + } + contentSS << seperator << line; + seperator = "\n"; + } + content = contentSS.str(); + +} + +PromelaInlines::PromelaInlines(const XERCESC_NS::DOMNode* node) { + + std::list<DOMNode*> levelNodes; + levelNodes.push_back(const_cast<XERCESC_NS::DOMNode*>(node)); + + size_t level = 0; + while(levelNodes.size() > 0) { + PromelaInline* predecessor = NULL; + + // iterate all nodes at given level + for (auto levelNode : levelNodes) { + + // get all comments + std::list<DOMNode*> comments = DOMUtils::filterChildType(DOMNode::COMMENT_NODE, levelNode); + for (auto comment : comments) { + + PromelaInline* tmp = new PromelaInline(comment); + if (tmp->type == PromelaInline::PROMELA_NIL) { + delete tmp; + continue; + } + + if (predecessor != NULL) { + tmp->prevSibling = predecessor; + predecessor->nextSibling = tmp; + } + tmp->level = level; + tmp->container = static_cast<DOMElement*>(levelNode); + predecessor = tmp; + inlines[levelNode].push_back(tmp); + allInlines.push_back(tmp); + } + } + + levelNodes = DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, levelNodes); + level++; + } + +} + +PromelaInlines::~PromelaInlines() { +} + +std::list<PromelaInline*> PromelaInlines::getRelatedTo(const XERCESC_NS::DOMNode* node, + PromelaInline::PromelaInlineType type) { + std::list<PromelaInline*> related; + + auto inlIter = inlines.begin(); + while (inlIter != inlines.end()) { + std::list<PromelaInline*>::iterator pmlIter = inlIter->second.begin(); + while (pmlIter != inlIter->second.end()) { + if ((type != PromelaInline::PROMELA_NIL || (*pmlIter)->type == type) && (*pmlIter)->relatesTo(node)) { + related.push_back(*pmlIter); + } + pmlIter++; + } + inlIter++; + } + return related; +} + +std::list<PromelaInline*> PromelaInlines::getAllOfType(uint32_t type) { + std::list<PromelaInline*> related; + + auto inlIter = inlines.begin(); + while (inlIter != inlines.end()) { + std::list<PromelaInline*>::iterator pmlIter = inlIter->second.begin(); + while (pmlIter != inlIter->second.end()) { + if ((*pmlIter)->type & type) { + related.push_back(*pmlIter); + } + pmlIter++; + } + inlIter++; + } + return related; + +} + +}
\ No newline at end of file diff --git a/src/uscxml/transform/promela/PromelaInlines.h b/src/uscxml/transform/promela/PromelaInlines.h new file mode 100644 index 0000000..2621f8d --- /dev/null +++ b/src/uscxml/transform/promela/PromelaInlines.h @@ -0,0 +1,113 @@ +/** + * @file + * @author 2016 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see <http://www.opensource.org/licenses/bsd-license>. + * @endcond + */ + +#ifndef PROMELAINLINES_H_29BF8EF3 +#define PROMELAINLINES_H_29BF8EF3 + +#include "uscxml/config.h" +#include "uscxml/Common.h" +#include "uscxml/messages/Data.h" +#include "uscxml/util/DOM.h" + +#include <xercesc/dom/DOM.hpp> +#include <list> +#include <string> + +namespace uscxml { + +class USCXML_API PromelaInline { +public: + enum PromelaInlineType { + PROMELA_NIL = 0x0000, + PROMELA_LTL = 0x0001, + PROMELA_CODE = 0x0002, + PROMELA_EVENT_ALL_BUT = 0x0004, + PROMELA_EVENT_ONLY = 0x0008, + PROMELA_PROGRESS_LABEL = 0x0010, + PROMELA_ACCEPT_LABEL = 0x0020, + PROMELA_END_LABEL = 0x0040 + }; + + PromelaInline(const XERCESC_NS::DOMNode* node); + virtual ~PromelaInline() {} + + operator bool() { + return (type != PROMELA_NIL); + } + + std::list<PromelaInline*> children; + PromelaInline* prevSibling; + PromelaInline* nextSibling; + + virtual void dump(); + + virtual bool relatesTo(const XERCESC_NS::DOMNode* node) { + return container == node; + } + + size_t level; + std::string content; + const XERCESC_NS::DOMElement* container; + PromelaInlineType type; + +protected: + PromelaInline() : prevSibling(NULL), nextSibling(NULL), type(PROMELA_NIL) {}; +}; + + +class USCXML_API PromelaEventSource : public PromelaInline { +public: + PromelaEventSource(const PromelaInline& pmlInline) { + type = pmlInline.type; + container = pmlInline.container; + content = pmlInline.content; + events = Data::fromJSON(pmlInline.content); + } + + virtual bool relatesTo(const XERCESC_NS::DOMNode* node) { + return container == node || DOMUtils::isDescendant(node, container); + } + + Data events; +}; + + +class USCXML_API PromelaInlines { +public: + + PromelaInlines(const XERCESC_NS::DOMNode* node); + PromelaInlines() {} + + virtual ~PromelaInlines(); + + std::list<PromelaInline*> getRelatedTo(const XERCESC_NS::DOMNode* node, PromelaInline::PromelaInlineType type); + std::list<PromelaInline*> getAllOfType(uint32_t type); + + std::map<const XERCESC_NS::DOMNode*, std::list<PromelaInline*> > inlines; + std::list<PromelaInline*> allInlines; + + static std::list<std::string> getStringLiterals(const Data& data); + static std::list<std::string> getEventNames(const Data& data); + + +}; + +} + +#endif /* end of include guard: PROMELAINLINES_H_29BF8EF3 */ diff --git a/src/uscxml/util/DOM.cpp b/src/uscxml/util/DOM.cpp index 7793fb5..1de6423 100644 --- a/src/uscxml/util/DOM.cpp +++ b/src/uscxml/util/DOM.cpp @@ -236,13 +236,13 @@ void DOMUtils::inPostFixOrder(const std::set<std::string>& elements, if (root == NULL) return; - for (auto childElem = root->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { + for (auto childElem = root->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { if (!includeEmbeddedDoc && LOCALNAME(childElem) == "scxml") continue; inPostFixOrder(elements, childElem, includeEmbeddedDoc, nodes); } - for (auto childElem = root->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { + for (auto childElem = root->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { if (!includeEmbeddedDoc && TAGNAME(childElem) == XML_PREFIX(root).str() + "scxml") continue; @@ -271,14 +271,14 @@ void DOMUtils::inDocumentOrder(const std::set<std::string>& elements, nodes.push_back((DOMElement*)root); } - /// @todo: item from getChildNodes is O(N)! - DOMElement* child = root->getFirstElementChild(); - while(child) { - if (includeEmbeddedDoc || TAGNAME(child) != XML_PREFIX(root).str() + "scxml") { - inDocumentOrder(elements, child, includeEmbeddedDoc, nodes); - } + /// @todo: item from getChildNodes is O(N)! + DOMElement* child = root->getFirstElementChild(); + while(child) { + if (includeEmbeddedDoc || TAGNAME(child) != XML_PREFIX(root).str() + "scxml") { + inDocumentOrder(elements, child, includeEmbeddedDoc, nodes); + } - child = child->getNextElementSibling(); + child = child->getNextElementSibling(); } } @@ -343,7 +343,7 @@ std::list<DOMElement*> DOMUtils::filterChildElements(const std::string& tagName, if (!node) return filteredChildElems; - for (auto childElem = node->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { + for (auto childElem = node->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { // std::cerr << TAGNAME(childs.item(i)) << std::endl; if(iequals(TAGNAME(childElem), tagName)) { filteredChildElems.push_back((DOMElement*)childElem); @@ -379,7 +379,7 @@ std::list<DOMNode*> DOMUtils::filterChildType(const DOMNode::NodeType type, if (!node) return filteredChildTypes; - for (auto child = node->getFirstChild(); child; child = child->getNextSibling()) { + for (auto child = node->getFirstChild(); child; child = child->getNextSibling()) { if (child->getNodeType() == type) filteredChildTypes.push_back(child); if (recurse) { diff --git a/src/uscxml/util/DOM.h b/src/uscxml/util/DOM.h index ae5fa60..e8094cf 100644 --- a/src/uscxml/util/DOM.h +++ b/src/uscxml/util/DOM.h @@ -159,7 +159,7 @@ public : } X(const char* const fromTranscode) { - + // Call the private transcoding method _localForm = fromTranscode; _unicodeForm = XERCESC_NS::XMLString::transcode(fromTranscode); @@ -168,24 +168,24 @@ public : X(char* fromTranscode) { - // Call the private transcoding method + // Call the private transcoding method _localForm = fromTranscode; _unicodeForm = XERCESC_NS::XMLString::transcode(fromTranscode); _deallocOther = true; } X() { - + _unicodeForm = NULL; _deallocOther = false; } ~X() { - + if (_deallocOther) XERCESC_NS::XMLString::release(&_unicodeForm); } - + const std::string& str() const { return _localForm; } @@ -202,7 +202,7 @@ public : operator std::string () { return _localForm; } - + protected: friend USCXML_API std::ostream& operator<< (std::ostream& os, const X& data); @@ -211,76 +211,76 @@ private: std::string _localForm; XMLCh* _unicodeForm; }; - + #else class USCXML_API X { public : - X() { - } - - void operator=(X const &other) { - localForm = other.localForm; - if (unicodeForm != NULL) { - XERCESC_NS::XMLString::release(&unicodeForm); - } - unicodeForm = XERCESC_NS::XMLString::replicate(other.unicodeForm); - } - - X(X const &other) { - localForm = other.localForm; - unicodeForm = XERCESC_NS::XMLString::replicate(other.unicodeForm); - } - - X(const char* const toTranscode) { - if (toTranscode != NULL) { - localForm = toTranscode; - unicodeForm = XERCESC_NS::XMLString::transcode(toTranscode); - } - } - - X(const XMLCh* toTranscode) { - if (toTranscode != NULL) { - unicodeForm = XERCESC_NS::XMLString::replicate(toTranscode); - localForm = XERCESC_NS::XMLString::transcode(toTranscode); - } - } - - X(const std::string& toTranscode) { - localForm = toTranscode; - unicodeForm = XERCESC_NS::XMLString::transcode(toTranscode.c_str()); - } - - ~X() { - if (unicodeForm != NULL) { - XERCESC_NS::XMLString::release(&unicodeForm); - } - } - - operator XMLCh* () const { - return unicodeForm; - } - - operator const std::string& () { - return localForm; - } - - const std::string& str() const { - return localForm; - } - - const XMLCh* unicode() const { - return unicodeForm; - } + X() { + } + + void operator=(X const &other) { + localForm = other.localForm; + if (unicodeForm != NULL) { + XERCESC_NS::XMLString::release(&unicodeForm); + } + unicodeForm = XERCESC_NS::XMLString::replicate(other.unicodeForm); + } + + X(X const &other) { + localForm = other.localForm; + unicodeForm = XERCESC_NS::XMLString::replicate(other.unicodeForm); + } + + X(const char* const toTranscode) { + if (toTranscode != NULL) { + localForm = toTranscode; + unicodeForm = XERCESC_NS::XMLString::transcode(toTranscode); + } + } + + X(const XMLCh* toTranscode) { + if (toTranscode != NULL) { + unicodeForm = XERCESC_NS::XMLString::replicate(toTranscode); + localForm = XERCESC_NS::XMLString::transcode(toTranscode); + } + } + + X(const std::string& toTranscode) { + localForm = toTranscode; + unicodeForm = XERCESC_NS::XMLString::transcode(toTranscode.c_str()); + } + + ~X() { + if (unicodeForm != NULL) { + XERCESC_NS::XMLString::release(&unicodeForm); + } + } + + operator XMLCh* () const { + return unicodeForm; + } + + operator const std::string& () { + return localForm; + } + + const std::string& str() const { + return localForm; + } + + const XMLCh* unicode() const { + return unicodeForm; + } protected: - friend USCXML_API std::ostream& operator<< (std::ostream& os, const X& data); + friend USCXML_API std::ostream& operator<< (std::ostream& os, const X& data); private: - XMLCh* unicodeForm = NULL; - std::string localForm; - + XMLCh* unicodeForm = NULL; + std::string localForm; + }; #endif @@ -295,14 +295,14 @@ static const X kElementFinalName = X("final"); static const X kElementOnEntryName = X("onentry"); static const X kElementOnExitName = X("onexit"); static const X kElementHistoryName = X("history"); - + static const X kElementRaiseName = X("raise"); static const X kElementIfName = X("if"); static const X kElementElseIfName = X("elseif"); static const X kElementElseName = X("else"); static const X kElementForEachName = X("foreach"); static const X kElementLogName = X("log"); - + static const X kElementDataModelName = X("datamodel"); static const X kElementDataName = X("data"); static const X kElementAssignName = X("assign"); @@ -310,7 +310,7 @@ static const X kElementContentName = X("content"); static const X kElementParamName = X("param"); static const X kElementScriptName = X("script"); #endif - + USCXML_API std::ostream& operator<< (std::ostream& os, const X& xmlString); USCXML_API std::ostream& operator<< (std::ostream& os, const XERCESC_NS::DOMNode& node); diff --git a/src/uscxml/util/Predicates.cpp b/src/uscxml/util/Predicates.cpp index 006e8dc..af47c68 100644 --- a/src/uscxml/util/Predicates.cpp +++ b/src/uscxml/util/Predicates.cpp @@ -27,7 +27,7 @@ using namespace XERCESC_NS; std::list<DOMElement*> getChildStates(const DOMElement* state, bool properOnly) { std::list<DOMElement*> children; - for (auto childElem = state->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { + for (auto childElem = state->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { if (isState(childElem, properOnly)) { children.push_back(childElem); } @@ -70,14 +70,14 @@ DOMElement* getSourceState(const DOMElement* transition) { #define VERBOSE_FIND_LCCA 0 DOMElement* findLCCA(const std::list<DOMElement*>& states) { - + std::list<DOMElement*> ancestors = getProperAncestors(states.front(), NULL); DOMElement* ancestor = NULL; #if VERBOSE_FIND_LCCA - std::cout << "states: " << states.size() << std::endl; - std::cout << "front: " << DOMUtils::xPathForNode(states.front()) << std::endl; - std::cout << "ancestors: " << ancestors.size() << std::endl; + std::cout << "states: " << states.size() << std::endl; + std::cout << "front: " << DOMUtils::xPathForNode(states.front()) << std::endl; + std::cout << "ancestors: " << ancestors.size() << std::endl; #endif for (auto ancIter = ancestors.begin(); ancIter != ancestors.end(); ancIter++) { @@ -121,8 +121,8 @@ std::list<DOMElement*> getProperAncestors(const DOMElement* s1, const DOMElement std::list<DOMElement*> ancestors; if (isState(s1, false)) { - // is it correct to also consider pseudo-states? - // gcc bug in findLCCA with test387, test388, test579, test580 otherwise + // is it correct to also consider pseudo-states? + // gcc bug in findLCCA with test387, test388, test579, test580 otherwise DOMNode* node = (DOMNode*)s1; while((node = node->getParentNode())) { if (node->getNodeType() != DOMNode::ELEMENT_NODE) @@ -133,8 +133,8 @@ std::list<DOMElement*> getProperAncestors(const DOMElement* s1, const DOMElement break; if (!iequals(LOCALNAME(nodeElem), "parallel") && - !iequals(LOCALNAME(nodeElem), "state") && - !iequals(LOCALNAME(nodeElem), "scxml")) + !iequals(LOCALNAME(nodeElem), "state") && + !iequals(LOCALNAME(nodeElem), "scxml")) break; if (node == s2) break; @@ -172,11 +172,11 @@ std::list<DOMElement*> getExitSet(const DOMElement* transition, const DOMElement bool conflicts(const DOMElement* t1, const DOMElement* t2, const DOMElement* root) { return ( - (getSourceState(t1) == getSourceState(t2)) || - (DOMUtils::isDescendant(getSourceState(t1), getSourceState(t2))) || - (DOMUtils::isDescendant(getSourceState(t2), getSourceState(t1))) || - (DOMUtils::hasIntersection(getExitSet(t1, root), getExitSet(t2, root))) - ); + (getSourceState(t1) == getSourceState(t2)) || + (DOMUtils::isDescendant(getSourceState(t1), getSourceState(t2))) || + (DOMUtils::isDescendant(getSourceState(t2), getSourceState(t1))) || + (DOMUtils::hasIntersection(getExitSet(t1, root), getExitSet(t2, root))) + ); } bool isState(const DOMElement* state, bool properOnly) { @@ -290,7 +290,7 @@ DOMElement* getTransitionDomain(const DOMElement* transition, const DOMElement* BREAK_LOOP: tStates.push_front(source); - + return findLCCA(tStates); } @@ -370,7 +370,7 @@ std::list<DOMElement*> getInitialStates(const DOMElement* state, const DOMElemen // first child state std::list<DOMElement*> initStates; - for (auto childElem = state->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { + for (auto childElem = state->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) { if (isState(childElem)) { initStates.push_back(childElem); return initStates; @@ -461,24 +461,24 @@ std::list<DOMElement*> getReachableStates(const DOMElement* root) { bool areFromSameMachine(const DOMNode* n1, const DOMNode* n2) { - // we traverse each nodes parent's until we reach an scxml element or null + // we traverse each nodes parent's until we reach an scxml element or null const DOMNode* p1 = n1; while(p1) { if(iequals(LOCALNAME(p1), "scxml")) { - break; + break; } p1 = p1->getParentNode(); } - const DOMNode* p2 = n2; - while(p2) { - if(iequals(LOCALNAME(p2), "scxml")) { - break; - } - p2 = p2->getParentNode(); - } + const DOMNode* p2 = n2; + while(p2) { + if(iequals(LOCALNAME(p2), "scxml")) { + break; + } + p2 = p2->getParentNode(); + } - return p1 == p2; + return p1 == p2; } }
\ No newline at end of file diff --git a/src/uscxml/util/URL.cpp b/src/uscxml/util/URL.cpp index 23b9854..79a0ad9 100644 --- a/src/uscxml/util/URL.cpp +++ b/src/uscxml/util/URL.cpp @@ -118,8 +118,8 @@ URLImpl::URLImpl(const std::string& url) : _orig(url), _handle(NULL), _requestTy URLImpl::~URLImpl() { uriFreeUriMembersA(&_uri); - if (_handle != NULL) - curl_easy_cleanup(_handle); + if (_handle != NULL) + curl_easy_cleanup(_handle); } URL URLImpl::resolve(URLImpl* relative, URLImpl* absolute) { @@ -592,7 +592,7 @@ void URLFetcher::fetchURL(URL& url) { char* header = (char*)malloc(paramIter->first.size() + strlen(value) + 3); sprintf(header,"%s: %s", paramIter->first.c_str(), value); headers = curl_slist_append(headers, header); - free(header); + free(header); // curl_free(key); // curl_free(value); paramIter++; @@ -600,9 +600,9 @@ void URLFetcher::fetchURL(URL& url) { // Disable "Expect: 100-continue" headers = curl_slist_append(headers, "Expect:"); - instance->_handlesToHeaders[handle] = headers; + instance->_handlesToHeaders[handle] = headers; - (curlError = curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers)) == CURLE_OK || + (curlError = curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers)) == CURLE_OK || LOG(ERROR) << "Cannot headers for " << std::string(url) << ": " << curl_easy_strerror(curlError); // curl_slist_free_all(headers); @@ -632,10 +632,10 @@ void URLFetcher::breakURL(URL& url) { curl_multi_remove_handle(instance->_multiHandle, handle); instance->_handlesToURLs.erase(handle); } - if (instance->_handlesToHeaders.find(handle) != instance->_handlesToHeaders.end()) { - curl_slist_free_all(instance->_handlesToHeaders[handle]); - instance->_handlesToHeaders.erase(handle); - } + if (instance->_handlesToHeaders.find(handle) != instance->_handlesToHeaders.end()) { + curl_slist_free_all(instance->_handlesToHeaders[handle]); + instance->_handlesToHeaders.erase(handle); + } } void URLFetcher::start() { @@ -759,13 +759,13 @@ void URLFetcher::perform() { if (err != CURLM_OK) { LOG(WARNING) << "curl_multi_remove_handle: " << curl_multi_strerror(err); } - break; + break; } - _handlesToURLs.erase(msg->easy_handle); - curl_slist_free_all(_handlesToHeaders[msg->easy_handle]); - _handlesToHeaders.erase(msg->easy_handle); - + _handlesToURLs.erase(msg->easy_handle); + curl_slist_free_all(_handlesToHeaders[msg->easy_handle]); + _handlesToHeaders.erase(msg->easy_handle); + } else { LOG(ERROR) << "Curl reports info on unfinished download?!"; } diff --git a/src/uscxml/util/URL.h b/src/uscxml/util/URL.h index 2b5c9e0..f6da30d 100644 --- a/src/uscxml/util/URL.h +++ b/src/uscxml/util/URL.h @@ -325,7 +325,7 @@ protected: bool _isStarted; std::map<CURL*, URL> _handlesToURLs; - std::map<CURL*, curl_slist*> _handlesToHeaders; + std::map<CURL*, curl_slist*> _handlesToHeaders; CURLM* _multiHandle; char* _envProxy; }; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e14586c..da70494 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -32,8 +32,7 @@ USCXML_TEST_COMPILE(NAME test-snippets LABEL general/test-snippets FILES src/tes # USCXML_TEST_COMPILE(NAME test-c89-parser LABEL general/test-c89-parser FILES src/test-c89-parser.cpp) # test-stress is not an automated test -add_executable(test-stress src/test-stress.cpp) -target_link_libraries(test-stress uscxml) +USCXML_TEST_COMPILE(BUILD_ONLY NAME test-stress LABEL general/test-stress FILES src/test-stress.cpp) file(GLOB_RECURSE USCXML_WRAPPERS ${PROJECT_SOURCE_DIR}/src/bindings/swig/wrapped/*.cpp @@ -41,6 +40,11 @@ file(GLOB_RECURSE USCXML_WRAPPERS ) USCXML_TEST_COMPILE(NAME test-bindings LABEL general/test-bindings FILES ${USCXML_WRAPPERS} src/test-bindings.cpp) +if (NOT MSVC) + # MSVC does not like to redefine 'protected' + USCXML_TEST_COMPILE(NAME test-promela-parser LABEL general/test-promela-parser FILES src/test-promela-parser.cpp) + target_link_libraries(test-promela-parser uscxml_transform) +endif() # the one binary to test for pass / fail final states add_executable(test-state-pass src/test-state-pass.cpp ${GETOPT_FILES}) @@ -134,14 +138,14 @@ if (NOT BUILD_MINIMAL) "null" "lua" "c89" - # "promela" + "promela" # generated c source "gen/c/ecma" # "gen/c/xpath" "gen/c/lua" # "gen/c/promela" - # "gen/vhdl/ecma" + "gen/vhdl/ecma" # bindings "binding/java/jexl" @@ -153,7 +157,7 @@ if (NOT BUILD_MINIMAL) # "fsm/promela" # formal verification - # "spin/promela" + "spin/promela" # performance tests # "perf/gen/c/ecma" diff --git a/test/bindings/java/org/uscxml/apache/commons/scxml2/JexlEvaluator.java b/test/bindings/java/org/uscxml/apache/commons/scxml2/JexlEvaluator.java index e50a259..127bed3 100644 --- a/test/bindings/java/org/uscxml/apache/commons/scxml2/JexlEvaluator.java +++ b/test/bindings/java/org/uscxml/apache/commons/scxml2/JexlEvaluator.java @@ -1,7 +1,7 @@ package org.uscxml.apache.commons.scxml2; import org.uscxml.Factory; -import org.uscxml.dm.jexl.JEXLDataModel; +import org.uscxml.dm.jexl.JexlDataModel; public class JexlEvaluator extends Evaluator { @@ -13,7 +13,7 @@ public class JexlEvaluator extends Evaluator { public Context newContext(Object object) { // TODO Auto-generated method stub Context ctx = new Context(); - ctx.dm = new JEXLDataModel(); + ctx.dm = new JexlDataModel(); return ctx; } } diff --git a/test/bindings/java/org/uscxml/dm/jexl/JEXLDataModel.java b/test/bindings/java/org/uscxml/dm/jexl/JEXLDataModel.java index 5564d63..cd9d175 100644 --- a/test/bindings/java/org/uscxml/dm/jexl/JEXLDataModel.java +++ b/test/bindings/java/org/uscxml/dm/jexl/JEXLDataModel.java @@ -10,7 +10,6 @@ import java.util.Map; import java.util.Set; import org.apache.commons.jexl3.JexlBuilder; -import org.apache.commons.jexl3.JexlContext; import org.apache.commons.jexl3.JexlEngine; import org.apache.commons.jexl3.JexlException; import org.apache.commons.jexl3.JexlExpression; @@ -19,18 +18,22 @@ import org.uscxml.Data; import org.uscxml.DataList; import org.uscxml.DataMap; import org.uscxml.DataModel; +import org.uscxml.DataModelExtension; import org.uscxml.ErrorEvent; import org.uscxml.Event; import org.uscxml.StringList; import org.uscxml.StringVector; -public class JEXLDataModel extends DataModel { +public class JexlDataModel extends DataModel { protected static final JexlEngine jexl = new JexlBuilder().cache(512).strict(true).silent(false).create(); - protected JexlContext ctx; - - - + public MapContext ctx = new MapContext(); + + @Override + public void addExtension(DataModelExtension ext) { + throw new UnsupportedOperationException("Cannot add extensions to the jexl datamodel"); + } + @Override public StringList getNames() { StringList names = new StringList(); @@ -40,8 +43,7 @@ public class JEXLDataModel extends DataModel { @Override public DataModel create() { - JEXLDataModel dm = new JEXLDataModel(); - dm.ctx = new MapContext(); + JexlDataModel dm = new JexlDataModel(); return dm; } @@ -73,10 +75,9 @@ public class JEXLDataModel extends DataModel { @Override public Data evalAsData(String content) { JexlExpression expr = jexl.createExpression(content); - System.out.println(); - Data d = new Data(); - d.setAtom(expr.getParsedText()); - d.setType(Data.Type.VERBATIM); + Data d = getJexlObjectAsData(expr.evaluate(ctx)); +// d.setAtom(expr.getParsedText()); +// d.setType(Data.Type.VERBATIM); return d; } diff --git a/test/bindings/java/org/uscxml/examples/DataModelExample.java b/test/bindings/java/org/uscxml/examples/DataModelExample.java index e6ad619..bba64eb 100644 --- a/test/bindings/java/org/uscxml/examples/DataModelExample.java +++ b/test/bindings/java/org/uscxml/examples/DataModelExample.java @@ -7,7 +7,7 @@ import org.uscxml.Factory; import org.uscxml.Interpreter; import org.uscxml.InterpreterException; import org.uscxml.InterpreterState; -import org.uscxml.dm.jexl.JEXLDataModel; +import org.uscxml.dm.jexl.JexlDataModel; import org.uscxml.helper.TestMonitor; public class DataModelExample { @@ -20,7 +20,7 @@ public class DataModelExample { System.load(uSCXMLLibPath); - JEXLDataModel jdm = new JEXLDataModel(); + JexlDataModel jdm = new JexlDataModel(); Factory.getInstance().registerDataModel(jdm);; TestMonitor tm = new TestMonitor(); diff --git a/test/bindings/java/org/uscxml/helper/StopWatch.java b/test/bindings/java/org/uscxml/helper/StopWatch.java new file mode 100644 index 0000000..4123ba1 --- /dev/null +++ b/test/bindings/java/org/uscxml/helper/StopWatch.java @@ -0,0 +1,22 @@ +package org.uscxml.helper; + +import org.uscxml.Data; +import org.uscxml.DataModelExtension; + +public class StopWatch { + + public StopWatch() { + } + + public void reset() { + System.out.println("RESET"); + } + + public void start() { + System.out.println("START"); + } + public void stop() { + System.out.println("STOP"); + } + +} diff --git a/test/bindings/java/org/uscxml/tests/JexlDataModelTest.java b/test/bindings/java/org/uscxml/tests/JexlDataModelTest.java index 876feb2..da79d37 100644 --- a/test/bindings/java/org/uscxml/tests/JexlDataModelTest.java +++ b/test/bindings/java/org/uscxml/tests/JexlDataModelTest.java @@ -3,11 +3,13 @@ package org.uscxml.tests; import java.io.File; import java.net.MalformedURLException; +import org.uscxml.ActionLanguage; import org.uscxml.Factory; import org.uscxml.Interpreter; import org.uscxml.InterpreterException; import org.uscxml.InterpreterState; -import org.uscxml.dm.jexl.JEXLDataModel; +import org.uscxml.dm.jexl.JexlDataModel; +import org.uscxml.helper.StopWatch; import org.uscxml.helper.TestMonitor; public class JexlDataModelTest { @@ -19,26 +21,37 @@ public class JexlDataModelTest { } System.load(uSCXMLLibPath); - String testUri = "/Users/sradomski/Documents/TK/Code/uscxml/test/w3c/jexl/test144.scxml"; +// String testUri = "/Users/sradomski/Documents/TK/Code/uscxml/test/w3c/jexl/test144.scxml"; +// String testUri = "/Users/sradomski/Desktop/stopwatch.xml"; - if (args.length > 0) { - testUri = args[0]; - } + +// if (args.length > 0) { +// testUri = args[0]; +// } { - JEXLDataModel jdm = new JEXLDataModel(); - Factory.getInstance().registerDataModel(jdm); + JexlDataModel jdm = new JexlDataModel(); +// Factory.getInstance().registerDataModel(jdm); + TestMonitor tm = new TestMonitor(); try { - File testFile = new File(testUri); - String testName = testFile.toURI().toURL().toString(); +// File testFile = new File(testUri); +// String testName = testFile.toURI().toURL().toString(); + String testName = "https://raw.githubusercontent.com/woonsan/commons-scxml-examples/master/stopwatch/src/main/resources/com/github/woonsan/commons/scxml/examples/stopwatch/stopwatch.xml"; System.out.println(testName); Interpreter scxml = Interpreter.fromURL(testName); + + jdm.ctx.set("stopWatch", new StopWatch()); + + ActionLanguage al = new ActionLanguage(); + al.setDataModel(jdm); + scxml.setActionLanguage(al); + scxml.addMonitor(tm); - + while (scxml.step() != InterpreterState.USCXML_FINISHED) { } @@ -48,7 +61,7 @@ public class JexlDataModelTest { } System.out.println("SUCCESS"); - } catch (InterpreterException | MalformedURLException e) { + } catch (InterpreterException e) { e.printStackTrace(); System.exit(-1); } diff --git a/test/ctest/scripts/run_promela_test.cmake b/test/ctest/scripts/run_promela_test.cmake index 818cf66..271434f 100644 --- a/test/ctest/scripts/run_promela_test.cmake +++ b/test/ctest/scripts/run_promela_test.cmake @@ -20,10 +20,10 @@ if(CMD_RESULT) endif() message(STATUS "time for transforming to c") -message(STATUS "${CXX_BIN} -DMEMLIM=1024 -DVECTORSZ=8192 -O2 -DXUSAFE -w -o ${OUTDIR}/pan ${OUTDIR}/pan.c") -execute_process(COMMAND time -p ${CXX_BIN} -DMEMLIM=1024 -DVECTORSZ=8192 -O2 -DXUSAFE -w -o ${OUTDIR}/pan ${OUTDIR}/pan.c WORKING_DIRECTORY ${OUTDIR} RESULT_VARIABLE CMD_RESULT) +message(STATUS "${CC_BIN} -DMEMLIM=1024 -DVECTORSZ=8192 -O2 -DXUSAFE -w -o ${OUTDIR}/pan ${OUTDIR}/pan.c") +execute_process(COMMAND time -p ${CC_BIN} -DMEMLIM=1024 -DVECTORSZ=8192 -O2 -DXUSAFE -w -o ${OUTDIR}/pan ${OUTDIR}/pan.c WORKING_DIRECTORY ${OUTDIR} RESULT_VARIABLE CMD_RESULT) if(CMD_RESULT) - message(FATAL_ERROR "Error running gcc ${CXX_BIN}: ${CMD_RESULT}") + message(FATAL_ERROR "Error running gcc ${CC_BIN}: ${CMD_RESULT}") endif() message(STATUS "time for transforming to binary") diff --git a/test/src/test-bindings.cpp b/test/src/test-bindings.cpp index 6932f67..61ed2d4 100644 --- a/test/src/test-bindings.cpp +++ b/test/src/test-bindings.cpp @@ -7,5 +7,5 @@ int main() { - return 0; + return 0; }
\ No newline at end of file diff --git a/test/src/test-c89-parser.cpp b/test/src/test-c89-parser.cpp index 9a4d570..11a1564 100644 --- a/test/src/test-c89-parser.cpp +++ b/test/src/test-c89-parser.cpp @@ -13,104 +13,104 @@ void testC89Parser() { c89_debug = 0; - std::list<std::string> localTest = { - "int main() { a = 10; }" - }; - - for (auto test : localTest) { - try { - C89Parser ast(test); - ast.dump(); - } catch (Event e) { - std::cerr << e << std::endl; - } - } + std::list<std::string> localTest = { + "int main() { a = 10; }" + }; - assert(false); - - std::list<URL> remoteTests = { - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/00_assignment.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/01_comment.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/02_printf.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/03_struct.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/04_for.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/05_array.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/06_case.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/07_function.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/08_while.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/09_do_while.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/10_pointer.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/11_precedence.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/12_hashdefine.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/13_integer_literals.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/14_if.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/15_recursion.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/16_nesting.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/17_enum.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/18_include.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/19_pointer_arithmetic.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/20_pointer_comparison.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/21_char_array.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/22_floating_point.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/23_type_coercion.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/24_math_library.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/25_quicksort.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/26_character_constants.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/27_sizeof.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/28_strings.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/29_array_address.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/30_hanoi.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/31_args.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/32_led.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/33_ternary_op.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/34_array_assignment.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/35_sizeof.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/36_array_initialisers.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/37_sprintf.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/38_multiple_array_index.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/39_typedef.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/40_stdio.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/41_hashif.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/42_function_pointer.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/43_void_param.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/44_scoped_declarations.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/45_empty_for.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/46_grep.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/47_switch_return.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/48_nested_break.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/49_bracket_evaluation.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/50_logical_second_arg.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/51_static.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/52_unnamed_enum.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/54_goto.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/55_array_initialiser.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/56_cross_structure.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/57_macro_bug.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/58_return_outside.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/59_break_before_loop.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/60_local_vars.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/61_initializers.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/62_float.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/63_typedef.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/64_double_prefix_op.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/65_typeless.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/66_printf_undefined.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/67_macro_crash.c"), - URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/68_return.c") - }; - - for (auto testURL : remoteTests) { + for (auto test : localTest) { try { - std::cout << std::endl << "'" << (std::string)testURL << "':" << std::endl; - std::cout << testURL.getInContent() << std::endl; - + C89Parser ast(test); + ast.dump(); + } catch (Event e) { + std::cerr << e << std::endl; + } + } + + assert(false); + + std::list<URL> remoteTests = { + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/00_assignment.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/01_comment.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/02_printf.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/03_struct.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/04_for.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/05_array.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/06_case.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/07_function.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/08_while.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/09_do_while.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/10_pointer.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/11_precedence.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/12_hashdefine.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/13_integer_literals.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/14_if.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/15_recursion.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/16_nesting.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/17_enum.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/18_include.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/19_pointer_arithmetic.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/20_pointer_comparison.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/21_char_array.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/22_floating_point.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/23_type_coercion.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/24_math_library.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/25_quicksort.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/26_character_constants.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/27_sizeof.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/28_strings.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/29_array_address.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/30_hanoi.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/31_args.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/32_led.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/33_ternary_op.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/34_array_assignment.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/35_sizeof.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/36_array_initialisers.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/37_sprintf.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/38_multiple_array_index.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/39_typedef.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/40_stdio.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/41_hashif.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/42_function_pointer.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/43_void_param.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/44_scoped_declarations.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/45_empty_for.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/46_grep.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/47_switch_return.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/48_nested_break.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/49_bracket_evaluation.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/50_logical_second_arg.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/51_static.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/52_unnamed_enum.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/54_goto.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/55_array_initialiser.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/56_cross_structure.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/57_macro_bug.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/58_return_outside.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/59_break_before_loop.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/60_local_vars.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/61_initializers.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/62_float.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/63_typedef.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/64_double_prefix_op.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/65_typeless.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/66_printf_undefined.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/67_macro_crash.c"), + URL("https://raw.githubusercontent.com/zsaleeba/picoc/master/tests/68_return.c") + }; + + for (auto testURL : remoteTests) { + try { + std::cout << std::endl << "'" << (std::string)testURL << "':" << std::endl; + std::cout << testURL.getInContent() << std::endl; + C89Parser ast(testURL.getInContent()); ast.dump(); - + } catch (Event e) { std::cerr << e << std::endl; } - std::this_thread::sleep_for(std::chrono::seconds(10)); + std::this_thread::sleep_for(std::chrono::seconds(10)); } } diff --git a/test/src/test-promela-parser.cpp b/test/src/test-promela-parser.cpp new file mode 100644 index 0000000..f0a019e --- /dev/null +++ b/test/src/test-promela-parser.cpp @@ -0,0 +1,323 @@ +#define protected public +#include "uscxml/util/URL.h" +#include "uscxml/Interpreter.h" +#include "uscxml/plugins/datamodel/promela/PromelaDataModel.h" +#include "uscxml/plugins/datamodel/promela/PromelaParser.h" +#include "uscxml/transform/ChartToPromela.h" +#include "uscxml/util/DOM.h" +#include "uscxml/util/Predicates.h" + +#include <xercesc/util/PlatformUtils.hpp> +#include <xercesc/dom/DOM.hpp> + +#include <assert.h> +#include <boost/algorithm/string.hpp> +#include <iostream> + +using namespace uscxml; +using namespace XERCESC_NS; + +extern int promela_debug; + +void testInlinePromela() { + + + DOMImplementation *implementation = DOMImplementationRegistry::getDOMImplementation(X("LS")); + DOMDocument* document = implementation->createDocument(); + + { + std::string test = "\ + promela-code This is foo!\ + "; + + DOMComment* comment = document->createComment(X(test)); + PromelaInline inl(comment); + assert(inl.type == PromelaInline::PROMELA_CODE); + assert(inl.content == "This is foo!"); + } + + { + std::string test = "\ + promela-code\n \ + This is foo!\ + "; + + DOMComment* comment = document->createComment(X(test)); + PromelaInline inl(comment); + assert(inl.type == PromelaInline::PROMELA_CODE); + assert(inl.content == "This is foo!"); + } + + { + std::string test = "\ + promela-event\n \ + [{\"name\": \"e1\", \"data\": { \"foo\": \"some string\" }}, \ + {\"name\": \"e1\", \"data\": { \"bar\": 12 }}]"; + + DOMComment* comment = document->createComment(X(test)); + PromelaInline inl(comment); + assert(inl.type == PromelaInline::PROMELA_EVENT_ONLY); + + PromelaEventSource es(inl); + assert(es.events.array.size() == 2); + + } + + { + Interpreter interpreter = Interpreter::fromURL("/Users/sradomski/Documents/TK/Code/uscxml/test/uscxml/promela/test-event-source-auto.scxml"); + assert(interpreter); + PromelaInlines inls(interpreter.getImpl()->getDocument()->getDocumentElement()); + + assert(inls.getAllOfType(PromelaInline::PROMELA_EVENT_ONLY).size() == 2); + assert(inls.getAllOfType(PromelaInline::PROMELA_EVENT_ALL_BUT).size() == 1); + } + +#if 0 + { + std::string test = "\ + #promela-inline:\n \ + This is foo!\ + "; + PromelaInlines prmInls = PromelaInlines::fromString(test); + assert(prmInls.nrAcceptLabels == 0 && + prmInls.nrCodes == 1 && + prmInls.nrEventSources == 0 && + prmInls.nrEndLabels == 0 && + prmInls.nrAcceptLabels == 0 && + prmInls.nrProgressLabels == 0); + assert(prmInls.code.size() == 1); + assert(prmInls.code.front().type == PromelaInline::PROMELA_CODE); + assert(boost::trim_copy(prmInls.code.front().content) == "This is foo!"); + } + + { + std::string test = "#promela-progress"; + PromelaInlines prmInls = PromelaInlines::fromString(test); + assert(prmInls.nrAcceptLabels == 0 && + prmInls.nrCodes == 0 && + prmInls.nrEventSources == 0 && + prmInls.nrEndLabels == 0 && + prmInls.nrProgressLabels == 1); + assert(prmInls.code.size() == 1); + assert(prmInls.code.front().type == PromelaInline::PROMELA_PROGRESS_LABEL); + } + + { + std::string test = "#promela-accept and then some"; + PromelaInlines prmInls = PromelaInlines::fromString(test); + assert(prmInls.nrAcceptLabels == 1 && + prmInls.nrCodes == 0 && + prmInls.nrEventSources == 0 && + prmInls.nrEndLabels == 0 && + prmInls.nrProgressLabels == 0); + assert(prmInls.code.size() == 1); + assert(prmInls.code.front().type == PromelaInline::PROMELA_ACCEPT_LABEL); + } + + { + std::string test = "#promela-end and then some"; + PromelaInlines prmInls = PromelaInlines::fromString(test); + assert(prmInls.nrAcceptLabels == 0 && + prmInls.nrCodes == 0 && + prmInls.nrEventSources == 0 && + prmInls.nrEndLabels == 1 && + prmInls.nrProgressLabels == 0); + assert(prmInls.code.size() == 1); + assert(prmInls.code.front().type == PromelaInline::PROMELA_END_LABEL); + } + + { + std::string test = "\ + #promela-event-source:\n \ + This is foo!\ + "; + PromelaInlines prmInls = PromelaInlines::fromString(test); + assert(prmInls.nrAcceptLabels == 0 && + prmInls.nrCodes == 0 && + prmInls.nrEventSources == 1 && + prmInls.nrEndLabels == 0 && + prmInls.nrProgressLabels == 0); + assert(prmInls.code.size() == 1); + assert(prmInls.code.front().type == PromelaInline::PROMELA_EVENT_SOURCE); + + PromelaEventSource pmlES(prmInls.code.front()); + assert(pmlES.sequences.size() == 1); + std::list<std::list<std::string> >::iterator seqsIter = pmlES.sequences.begin(); + std::list<std::string>::iterator seqIter = seqsIter->begin(); + assert(*seqIter++ == "This"); + assert(*seqIter++ == "is"); + assert(*seqIter++ == "foo!"); + assert(seqIter == seqsIter->end()); + seqsIter++; + assert(seqsIter == pmlES.sequences.end()); + } + + { + std::string test = "\ + #promela-event-source:\n \ + This is foo!\n \ + This is bar!\n \ + "; + PromelaInlines prmInls = PromelaInlines::fromString(test); + assert(prmInls.nrAcceptLabels == 0 && + prmInls.nrCodes == 0 && + prmInls.nrEventSources == 1 && + prmInls.nrEndLabels == 0 && + prmInls.nrProgressLabels == 0); + assert(prmInls.code.size() == 1); + assert(prmInls.code.front().type == PromelaInline::PROMELA_EVENT_SOURCE); + + PromelaEventSource pmlES(prmInls.code.front()); + + assert(pmlES.sequences.size() == 2); + std::list<std::list<std::string> >::iterator seqsIter = pmlES.sequences.begin(); + std::list<std::string>::iterator seqIter = seqsIter->begin(); + assert(*seqIter++ == "This"); + assert(*seqIter++ == "is"); + assert(*seqIter++ == "foo!"); + assert(seqIter == seqsIter->end()); + seqsIter++; + seqIter = seqsIter->begin(); + assert(*seqIter++ == "This"); + assert(*seqIter++ == "is"); + assert(*seqIter++ == "bar!"); + assert(seqIter == seqsIter->end()); + seqsIter++; + assert(seqsIter == pmlES.sequences.end()); + } + + { + std::string test = "\ + #promela-event-source-custom:\n \ + This is foo!\ + "; + PromelaInlines prmInls = PromelaInlines::fromString(test); + assert(prmInls.nrAcceptLabels == 0 && + prmInls.nrCodes == 0 && + prmInls.nrEventSources == 1 && + prmInls.nrEndLabels == 0 && + prmInls.nrProgressLabels == 0); + assert(prmInls.code.size() == 1); + assert(prmInls.code.front().type == PromelaInline::PROMELA_EVENT_SOURCE_CUSTOM); + + PromelaEventSource pmlES(prmInls.code.front()); + + assert(pmlES.sequences.size() == 0); + assert(boost::trim_copy(pmlES.source.content) == "This is foo!"); + } + + { + std::string test = "\ + #promela-event-source-custom:\n \ + This is foo! \n\ + #promela-progress\ + "; + PromelaInlines prmInls = PromelaInlines::fromString(test); + assert(prmInls.nrAcceptLabels == 0 && + prmInls.nrCodes == 0 && + prmInls.nrEventSources == 1 && + prmInls.nrEndLabels == 0 && + prmInls.nrProgressLabels == 1); + assert(prmInls.code.size() == 2); + assert(prmInls.code.front().type == PromelaInline::PROMELA_EVENT_SOURCE_CUSTOM); + + PromelaEventSource pmlES(prmInls.code.front()); + + assert(pmlES.sequences.size() == 0); + assert(boost::trim_copy(pmlES.source.content) == "This is foo!"); + } +#endif +} + +void checkTokenLocations(const std::string& expr, PromelaParserNode* ast) { + if (ast->loc != NULL) { + assert(expr.substr(ast->loc->firstCol, ast->loc->lastCol - ast->loc->firstCol) == ast->value); + } + for (std::list<PromelaParserNode*>::iterator opIter = ast->operands.begin(); opIter != ast->operands.end(); opIter++) { + checkTokenLocations(expr, *opIter); + } +} + +void testPromelaParser() { + + promela_debug = 0; +#if 1 + std::list<std::string> expressions; + /* declarations */ + expressions.push_back("bool b1"); + expressions.push_back("bool b1;"); + expressions.push_back("bool b1, b2, b3"); + expressions.push_back("bool b1, b2, b3;"); + expressions.push_back("bool b1, b2 = 3 + 4, b3, b4, b5;"); + expressions.push_back("bool b1; bool b2; bool b3; bool b4;"); + expressions.push_back("bool b1; bool b2; bool b3, b4, b5;"); + expressions.push_back("bit b = 1;"); + expressions.push_back("byte state = 1;"); + expressions.push_back("bool b1, b2 = 1, b3;"); + expressions.push_back("bool busy[3];"); + expressions.push_back("bool busy[3], us[4];"); + expressions.push_back("mtype = {\nred, white, blue,\nabort, accept, ack, sync_ack, close, connect,\ncreate, data, eof, open, reject, sync, transfer,\nFATAL, NON_FATAL, COMPLETE\n}"); + expressions.push_back("typedef D { short f; byte g }; "); + expressions.push_back("x = 1"); + expressions.push_back("x = foo.bar[2].baz; "); + expressions.push_back("_event.data[1].aParam.key1.key2[1].key3.key4"); + expressions.push_back("_event.data.aParam"); + expressions.push_back("_event.data"); + expressions.push_back("_event"); + expressions.push_back("states"); + expressions.push_back("states[1]"); + expressions.push_back("_x.states[1]"); + expressions.push_back("_x.states[1].foo"); + expressions.push_back("_event.data[1].aParam.key1.key2[1].key3.key4"); + expressions.push_back("\n\n\n\n int foo = 3;\n\nint bar = 5;"); + + + /* expressions */ + expressions.push_back("i+1"); + expressions.push_back("(x == false || t == Bturn);"); + expressions.push_back("a + (1 << b)"); + expressions.push_back("(a + 1) << b"); + expressions.push_back("(b < N)"); + expressions.push_back("(mt+1)%MAX;"); + expressions.push_back("state[0] = state[3] + 5 * state[3*2/n]"); + + /* statements */ + expressions.push_back("t = Bturn;"); + expressions.push_back("c++"); + expressions.push_back("state = state - 1"); + expressions.push_back("printf(\"hello world\\n\")"); + expressions.push_back("printf(\"result %d: %d\\n\", id, res, foo, bar)"); + expressions.push_back("printf(\"x = %d\\n\", x)"); + expressions.push_back("(n <= 1)"); + expressions.push_back("res = (a*a+b)/2*a;"); + expressions.push_back("assert(0) /* a forced stop, (Chapter 6) */"); + expressions.push_back("assert(count == 0 || count == 1)"); + expressions.push_back("busy[4 - 3] = 1;"); + + for (std::list<std::string>::iterator exprIter = expressions.begin(); + exprIter != expressions.end(); + exprIter++) { + try { + std::cout << std::endl << "'" << *exprIter << "':" << std::endl; + PromelaParser ast(*exprIter); + ast.dump(); + if (!boost::contains(*exprIter, "\n")) + checkTokenLocations(*exprIter, ast.ast); + } catch (Event e) { + std::cerr << e << std::endl; + } + } +#endif + +} + +int main(int argc, char** argv) { + try { + ::xercesc_3_1::XMLPlatformUtils::Initialize(); + } catch (const XERCESC_NS::XMLException& toCatch) { + ERROR_PLATFORM_THROW("Cannot initialize XercesC: " + X(toCatch.getMessage()).str()); + } + + testInlinePromela(); + testPromelaParser(); +}
\ No newline at end of file diff --git a/test/src/test-stress.cpp b/test/src/test-stress.cpp index 87000c8..d3209e2 100644 --- a/test/src/test-stress.cpp +++ b/test/src/test-stress.cpp @@ -24,21 +24,21 @@ class StatusMonitor : public uscxml::InterpreterMonitor { }; void printUsageAndExit() { - printf("test-stress version " USCXML_VERSION " (" CMAKE_BUILD_TYPE " build - " CMAKE_COMPILER_STRING ")\n"); - printf("Usage\n"); - printf("\ttest-stress"); + printf("test-stress version " USCXML_VERSION " (" CMAKE_BUILD_TYPE " build - " CMAKE_COMPILER_STRING ")\n"); + printf("Usage\n"); + printf("\ttest-stress"); #ifdef BUILD_AS_PLUGINS - printf(" [-p pluginPath]"); + printf(" [-p pluginPath]"); #endif - printf(" <PATH>\n"); - printf("\n"); - exit(1); + printf(" <PATH>\n"); + printf("\n"); + exit(1); } int main(int argc, char** argv) { using namespace uscxml; - if (argc < 2) { + if (argc < 2) { printUsageAndExit(); } @@ -62,7 +62,7 @@ int main(int argc, char** argv) { DirectoryWatch* watcher = new DirectoryWatch(argv[optind], true); watcher->updateEntries(true); - + std::map<std::string, struct stat> entries = watcher->getAllEntries(); StatusMonitor vm; @@ -77,27 +77,27 @@ int main(int argc, char** argv) { startedAt = time(NULL); lastTransitionAt = time(NULL); - Interpreter interpreter = Interpreter::fromURL(std::string(argv[optind]) + PATH_SEPERATOR + entryIter->first); + Interpreter interpreter = Interpreter::fromURL(std::string(argv[optind]) + PATH_SEPERATOR + entryIter->first); // Interpreter interpreter = Interpreter::fromURL("/Users/sradomski/Documents/TK/Code/uscxml/test/w3c/ecma/test422.scxml"); - LOG(INFO) << "Processing " << interpreter.getImpl()->getBaseURL(); + LOG(INFO) << "Processing " << interpreter.getImpl()->getBaseURL(); if (interpreter) { interpreter.addMonitor(&vm); - InterpreterState state = InterpreterState::USCXML_UNDEF; - int now = time(NULL); + InterpreterState state = InterpreterState::USCXML_UNDEF; + int now = time(NULL); - try { - while(state != USCXML_FINISHED && now - startedAt < 20 && now - lastTransitionAt < 2) { + try { + while(state != USCXML_FINISHED && now - startedAt < 20 && now - lastTransitionAt < 2) { // while(state != USCXML_FINISHED) { - state = interpreter.step(200); - now = time(NULL); - } - } catch (...) {} + state = interpreter.step(200); + now = time(NULL); + } + } catch (...) {} } entryIter++; - - // forever + + // forever // if (entryIter == entries.end()) { // entryIter = entries.begin(); // } @@ -105,5 +105,5 @@ int main(int argc, char** argv) { delete watcher; - return EXIT_SUCCESS; + return EXIT_SUCCESS; }
\ No newline at end of file diff --git a/test/uscxml/promela/test-complete.scxml b/test/uscxml/promela/test-complete.scxml new file mode 100644 index 0000000..a96152b --- /dev/null +++ b/test/uscxml/promela/test-complete.scxml @@ -0,0 +1,154 @@ +<scxml datamodel="promela"> + + <datamodel> + <data id="foreachArray1" type="int[3]">[1,2,3]</data> + <data id="parallelVar1" type="int" expr="0"/> + <data id="ifVar1">{ foo: 1, bar: 'baz' }</data> + <data id="counter">{ itemSum: 0, indexSum: 0 }</data> + <data id="sendVar1" type="int" expr="4"/> + <data id="histVar1" type="int">0</data> + <data id="finalizeVar1" type="int">0</data> + </datamodel> + + <state id="s0"> + <history id="s0.h0" type="deep" /> + <parallel id="p0"> + <state id="p0.s0"> + <state id="p0.s0.s0"> + <onentry> + <if cond="ifVar1.foo == 3"> + <log label="if choosen" /> + <log label="ifVar1.bar is" expr="ifVar1.bar" /> + <foreach array="foreachArray1" + item="foreachItem1" + index="foreachIndex1"> + <script> + counter.indexSum = counter.indexSum + foreachIndex1; + counter.itemSum = counter.itemSum + foreachItem1; + </script> + <log label="foreach counter.indexSum is" + expr="counter.indexSum" /> + <log label="foreach counter.itemSum is" + expr="counter.itemSum" /> + </foreach> + <raise event="if.choosen" /> + <elseif cond="ifVar1.bar == 'baz'" /> + <log label="elseif choosen" /> + <log label="ifVar1.bar is" expr="ifVar1.bar" /> + <assign location="ifVar1.foo" expr="3" /> + <send event="elseif.choosen" namelist="sendVar1"> + <param name="foo" expr="sendVar1 + 16" /> + <param name="bar" expr="'a string literal'" /> + </send> + <else /> + <log label="else choosen" /> + <log label="ifVar1.foo is" expr="ifVar1.foo" /> + <log label="ifVar1.bar is" expr="ifVar1.bar" /> + <raise event="else.choosen" /> + </if> + <script>parallelVar1++</script> + </onentry> + <transition event="else.choosen" target="p0"> + <assign location="ifVar1.bar" expr="'baz'" /> + </transition> + <transition event="elseif.choosen" target="p0" + cond="_event.data.foo == 20 && + _event.data.sendVar1 == 4 && + _event.data.bar == 'a string literal'" + /> + </state> + <state id="p0.s0.s1"> + <onentry> + <if cond="_x.states['p0'] && histVar1 == 1"> + <raise event="to.s2" /> + <else /> + <raise event="to.s1" /> + </if> + </onentry> + <transition event="to.s2" target="s2" /> + <transition event="to.s1" target="s1" /> + </state> + </state> + <state id="p0.s1"> + <onexit> + <script>parallelVar1++</script> + </onexit> + </state> + <transition event="if.choosen" + cond="counter.itemSum == 6 && + counter.indexSum == 3" + target="p0.s0.s1" /> + </parallel> + </state> + + <state id="s1"> + <invoke type="scxml" autoforward="true"> + <content> + <scxml datamodel="promela"> + <state id="waitForEvent"> + <transition event="trigger.child"> + <send target="#_parent" event="back.to.history" /> + </transition> + </state> + </scxml> + </content> + <finalize> + <script>finalizeVar1++;</script> + </finalize> + </invoke> + <onentry> + <send event="trigger.child" delay="1000" /> + </onentry> + <transition event="back.to.history" + cond="finalizeVar1 == 1" + target="s0.h0"> + <assign location="histVar1" expr="4-3" /> + </transition> + </state> + + <state id="s2" initial="s2.s0"> + <onentry> + <send event="cancel.delayed" delay="3000" sendid="cancel.delayed" /> + <cancel sendid="cancel.delayed" /> + </onentry> + <transition event="done.state.s2" + cond="_event.data.Var1 == 'foo'" + target="s3.h0"> + <assign location="histVar1" expr="8" /> + </transition> + <transition event="done.state.s2" target="fail" /> + <transition event="cancel.delayed" target="fail" /> + <transition target="pass" cond="histVar1 == 8" /> + <state id="s2.s0"> + <transition target="s2.s1"/> + </state> + <final id="s2.s1"> + <donedata> + <param name="Var1" expr="'foo'"/> + </donedata> + </final> + </state> + + <state id="s3"> + <history id="s3.h0" type="shallow"> + <transition target="s3.s1"> + <log label="history transition" /> + <assign location="histVar1" expr="4" /> + </transition> + </history> + <state id="s3.s1"> + <transition target="s2" /> + </state> + </state> + + <final id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml>
\ No newline at end of file diff --git a/test/uscxml/promela/test-event-source-auto.scxml b/test/uscxml/promela/test-event-source-auto.scxml new file mode 100644 index 0000000..cb33636 --- /dev/null +++ b/test/uscxml/promela/test-event-source-auto.scxml @@ -0,0 +1,45 @@ +<scxml datamodel="promela"> + <!-- + An auto event source will raise all events that enable transitions. If a + transition depends on a data field, these will have to be specified explicitly. + + promela-event-all-but + [ "error.bar" ] + --> + <!-- this will become a PROMELA_NIL --> + <state id="s0"> + <!-- + if _x.states[s0] + + These specialized events will only be dispatched in s0 + promela-event + [ {"name": "e1", + "data": { "foo": "some string" }}, + {"name": "e1", + "data": { "bar": 12 }} + ] + --> + <transition event="e1" cond="_event.data.foo == 'some string'" /> + <transition event="error.foo" cond="_event.data.foo == 'some string'" /> + <transition event="error.bar.*" /> + <transition event="error.baz.*" target="s1" /> + <transition event="e1" cond="_event.data.bar == 12" /> + <invoke type="foo"> + <!-- + promela-event + [ {"name": "inv1", + "data": { "foo": "something else" }}, + {"name": "inv2", + "data": { "baz": 23 }} + ] + --> + </invoke> + </state> + <state id="s1"> + <!-- This transition will never be enabled --> + <transition event="e1" cond="_event.data.bar == 23" /> + <transition event="e3" cond="bar == 23" /> + <transition event="e1" /> + <transition event="e2" /> + </state> +</scxml> diff --git a/test/uscxml/promela/test-event-source.scxml b/test/uscxml/promela/test-event-source.scxml new file mode 100644 index 0000000..3816bd0 --- /dev/null +++ b/test/uscxml/promela/test-event-source.scxml @@ -0,0 +1,39 @@ +<scxml datamodel="promela"> + <state id="s0"> + <invoke type="scxml"> + <!-- Sends a single event and exits --> + <!-- + #promela-event-source-custom: + if + :: 1 -> eQ!#to.s1#; goto #DONE#; // end this invoker + fi; + --> + <content> + <scxml> + <state id="s0"> + <onentry> + <send target="#_parent" event="to.s1" /> + </onentry> + </state> + </scxml> + </content> + </invoke> + <transition event="to.s1" target="s1" /> + </state> + <state id="s1"> + <onentry> + <!-- Send event to our external queue --> + <send event="to.s2" /> + </onentry> + <transition event="to.s2" target="s2" /> + </state> + <state id="s2"> + <onentry> + <!-- Send event to our internal queue --> + <raise event="to.s3" /> + </onentry> + <transition event="to.s3" target="s3" /> + </state> + + <state id="s3" final="true" /> +</scxml>
\ No newline at end of file diff --git a/test/uscxml/promela/test-history.scxml b/test/uscxml/promela/test-history.scxml new file mode 100644 index 0000000..ef48f6a --- /dev/null +++ b/test/uscxml/promela/test-history.scxml @@ -0,0 +1,16 @@ +<scxml datamodel="promela"> + <state id="s0"> + <history id="h01" type="deep" /> + <state id="s01"> + <transition target="s02" event="foo" /> + <transition target="s1" event="bar" /> + </state> + <state id="s02"> + <script>printf("In S02");</script> + <transition target="s1" /> + </state> + </state> + <state id="s1"> + <transition target="h01" /> + </state> +</scxml>
\ No newline at end of file diff --git a/test/uscxml/promela/test-ltl.scxml b/test/uscxml/promela/test-ltl.scxml new file mode 100644 index 0000000..23079d9 --- /dev/null +++ b/test/uscxml/promela/test-ltl.scxml @@ -0,0 +1,16 @@ +<scxml datamodel="promela"> + <!-- + #promela-event-source: + toggle.foo + --> + <datamodel> + <data id="foo" expr="0" type="bit" /> + </datamodel> + <parallel id="main"> + <state id="toggleFoo"> + <transition event="toggle.foo"> + <script>foo = !foo;</script> + </transition> + </state> + </parallel> +</scxml>
\ No newline at end of file diff --git a/test/uscxml/promela/test-non-progress.scxml b/test/uscxml/promela/test-non-progress.scxml new file mode 100644 index 0000000..2301bd6 --- /dev/null +++ b/test/uscxml/promela/test-non-progress.scxml @@ -0,0 +1,17 @@ +<!-- + Check for no-progress cycles + + $ uscxml-transform -s -i this_file.scxml > test.pml + $ spin -a test.pml + $ gcc -DNP pan.c + $ ./a.out -l +--> +<scxml datamodel="promela"> + <state id="s0"> + <onentry> + <raise event="foo" /> + </onentry> + <transition event="foo" target="s0" /> + </state> + <state id="s1" final="true" /> +</scxml>
\ No newline at end of file diff --git a/test/uscxml/promela/test-progress-label.scxml b/test/uscxml/promela/test-progress-label.scxml new file mode 100644 index 0000000..8e27345 --- /dev/null +++ b/test/uscxml/promela/test-progress-label.scxml @@ -0,0 +1,20 @@ +<!-- + + Check for no-progress cycles + + $ uscxml-transform -s -i this_file.scxml > test.pml + $ spin -a test.pml + $ gcc -DNP pan.c + $ ./a.out -l + +--> +<scxml datamodel="promela"> + <state id="s0"> + <onentry> + <!-- promela-progress --> + <raise event="foo" /> + </onentry> + <transition event="foo" target="s0" /> + </state> + <state id="s1" final="true" /> +</scxml>
\ No newline at end of file diff --git a/test/uscxml/promela/test-simple.scxml b/test/uscxml/promela/test-simple.scxml new file mode 100644 index 0000000..61c8022 --- /dev/null +++ b/test/uscxml/promela/test-simple.scxml @@ -0,0 +1,15 @@ +<!-- + Simple example + + $ uscxml-transform -s -i this_file.scxml > test.pml + $ spin -p -l -h test.pml +--> +<scxml datamodel="promela"> + <state id="s0"> + <onentry> + <raise event="foo" /> + </onentry> + <transition event="foo" target="s1" /> + </state> + <state id="s1" final="true" /> +</scxml>
\ No newline at end of file diff --git a/test/uscxml/promela/test-syntax.scxml b/test/uscxml/promela/test-syntax.scxml new file mode 100644 index 0000000..101c97a --- /dev/null +++ b/test/uscxml/promela/test-syntax.scxml @@ -0,0 +1,132 @@ +<scxml datamodel="promela" binding="early" > + <!-- + promela-event-source: + foo.bar + foo.baz foo.foo + error.communication + error.platform + err.foo + --> + <datamodel> + <data> + bool b1; + </data> + <data> + int fooSum = 0; + int fooIndex = 0; + int fooItem; + int foos[10]; + </data> + <data> + bool b2, b3, b4; + </data> + <data> + bool b5, b6 = 3 + 4, b7, b8, b9; + </data> + <data> + bool c1; bool c2; bool c3; bool c4; + bool c5; bool c6; bool c7, c8 = 4 + 6, c9; + </data> + <data> + byte state = 1; + mtype = { + FATAL, NON_FATAL, COMPLETE, INCOMPLETE, + red, white, blue + } + </data> + <data> + bool busy[3]; + bool lazy[4]; + </data> + <data> + bool v3, v2 = 1; + </data> + + </datamodel> + <state id="init"> + <invoke type="xhtml" id="xhtml1" src="resources/gui.xhtml"> + <!-- #promela-event-source: + foo.bar + foo.baz foo.foo + error.communication + error.platform + err.foo + --> + </invoke> + + <invoke type="scxml"> + <!-- + promela-event-source: + innerFoo + --> + + <final id="stop"> + <onentry> + <send target="#_parent" event="innerFoo" /> + </onentry> + </final> + </invoke> + <onentry> + <!-- + #promela-inline: + progress: skip; + --> + <raise event="foo.bar" /> + <script> + busy[4 - 3] = 1; + </script> + <log label="foos" expr="foos" /> + <foreach item="fooItem" array="foos" index="fooIndex"> + <script> + foos[fooIndex] = fooIndex; + </script> + </foreach> + <log label="foos" expr="foos" /> + <foreach item="fooItem" array="foos" index="fooIndex"> + <log label="fooItem" expr="fooItem" /> + <script> + fooSum = fooSum + fooItem; + </script> + </foreach> + <log label="fooSum" expr="fooSum" /> + <if cond="b1==0"> + <script> + b2=1; b3=1; + </script> + <elseif cond="b1==1" /> + <script> + b2=1; b3=1; + </script> + <else /> + <script> + b2=1; b3=1; + </script> + </if> + <script> + v2=1; v3=1; + </script> + </onentry> + <transition target="pass" cond="v2==v3 && busy[1] == 1" event="foo.bar"> + <!-- + promela-inline: + progress: skip; + --> + </transition> + <transition target="fail" event="*"> + <!-- + promela-inline: + progress: skip; + --> + </transition> + </state> + <final id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml>
\ No newline at end of file diff --git a/test/w3c/confPromela.xsl b/test/w3c/confPromela.xsl index a7414b3..37920a5 100644 --- a/test/w3c/confPromela.xsl +++ b/test/w3c/confPromela.xsl @@ -542,7 +542,7 @@ is the second argument --> </xsl:template> <xsl:template match="//@conf:inState"> - <xsl:attribute name="cond">_x.states['<xsl:value-of select="."/>']</xsl:attribute> + <xsl:attribute name="cond">config[<xsl:value-of select="upper-case(.)"/>]</xsl:attribute> </xsl:template> <!-- returns a value that cannot be converted into a Boolean --> diff --git a/test/w3c/promela/robots.txt b/test/w3c/promela/robots.txt new file mode 100644 index 0000000..fdd7340 --- /dev/null +++ b/test/w3c/promela/robots.txt @@ -0,0 +1,103 @@ +# +# robots.txt for http://www.w3.org/ +# +# $Id: robots.txt,v 1.74 2016/02/11 20:30:26 gerald Exp $ +# + +# For use by search.w3.org +User-agent: W3C-gsa +Disallow: /Out-Of-Date + +User-agent: W3T_SE +Disallow: /Out-Of-Date + +User-agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT; MS Search 4.0 Robot) +Disallow: / + +# W3C Link checker +User-agent: W3C-checklink +Disallow: + +# the following settings apply to all bots +User-agent: * +# Blogs - WordPress +# https://codex.wordpress.org/Search_Engine_Optimization_for_WordPress#Robots.txt_Optimization +Disallow: /*/wp-admin/ +Disallow: /*/wp-includes/ +Disallow: /*/wp-content/plugins/ +Disallow: /*/wp-content/cache/ +Disallow: /*/wp-content/themes/ +Disallow: /blog/*/trackback/ +Disallow: /blog/*/feed/ +Disallow: /blog/*/comments/ +Disallow: /blog/*/category/*/* +Disallow: /blog/*/*/trackback/ +Disallow: /blog/*/*/feed/ +Disallow: /blog/*/*/comments/ +Disallow: /blog/*/*? +Disallow: /community/trackback/ +Disallow: /community/feed/ +Disallow: /community/comments/ +Disallow: /community/category/*/* +Disallow: /community/*/trackback/ +Disallow: /community/*/feed/ +Disallow: /community/*/comments/ +Disallow: /community/*/category/*/* +Disallow: /community/*? +Disallow: /Consortium/Offices/trackback/ +Disallow: /Consortium/Offices/feed/ +Disallow: /Consortium/Offices/comments/ +Disallow: /Consortium/Offices/category/*/* +Disallow: /Consortium/Offices/*/trackback/ +Disallow: /Consortium/Offices/*/feed/ +Disallow: /Consortium/Offices/*/comments/ +Disallow: /Consortium/Offices/*? +# Wikis - Mediawiki +# https://www.mediawiki.org/wiki/Manual:Robots.txt +Disallow: /wiki/index.php? +Disallow: /wiki/index.php/Help +Disallow: /wiki/index.php/MediaWiki +Disallow: /wiki/index.php/Special: +Disallow: /wiki/index.php/Template +Disallow: /wiki/skins/ +Disallow: /*/wiki/index.php? +Disallow: /*/wiki/index.php/Help +Disallow: /*/wiki/index.php/MediaWiki +Disallow: /*/wiki/index.php/Special: +Disallow: /*/wiki/index.php/Template +# various other access-controlled or expensive areas +Disallow: /2004/ontaria/basic +Disallow: /Team/ +Disallow: /Project +Disallow: /Web +Disallow: /Systems +Disallow: /History +Disallow: /Out-Of-Date +Disallow: /2002/02/mid +Disallow: /mid/ +Disallow: /2005/06/blog/ +Disallow: /2004/08/W3CTalks +Disallow: /2007/11/Talks/search +Disallow: /People/all/ +Disallow: /RDF/Validator/ARPServlet +Disallow: /RDF/Validator/rdfval +Disallow: /2003/03/Translations/byLanguage +Disallow: /2003/03/Translations/byTechnology +Disallow: /2005/11/Translations/Query +Disallow: /2000/06/webdata/xslt +Disallow: /2000/09/webdata/xslt +Disallow: /2005/08/online_xslt/xslt +Disallow: /Bugs/ +Disallow: /Search/Mail/Public/ +Disallow: /2006/02/chartergen +Disallow: /2004/01/pp-impl +Disallow: /Consortium/supporters +Disallow: /2007/08/pyRdfa/ +Disallow: /2012/pyRdfa/extract +Disallow: /WAI/PF/comments/ +Disallow: /participate/conferences.xml +Disallow: /scripts/ +Disallow: /2005/01/yacker/ +Disallow: /2005/01/yacker? +Disallow: /2003/09/nschecker? + diff --git a/test/w3c/promela/test144.scxml b/test/w3c/promela/test144.scxml new file mode 100644 index 0000000..18055c4 --- /dev/null +++ b/test/w3c/promela/test144.scxml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that events are inserted into the queue in the order in which they are raised. If +foo occurs before bar, success, otherwise failure --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <raise event="foo"/> + <raise event="bar"/> + </onentry> + <transition event="foo" target="s1"/> + <transition event="*" target="fail"/> + </state> + <state id="s1"> + <transition event="bar" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test147.scxml b/test/w3c/promela/test147.scxml new file mode 100644 index 0000000..de4e35e --- /dev/null +++ b/test/w3c/promela/test147.scxml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that the first clause that evaluates to true - and only that clause - is executed. +Only one event should be raised, and it should be bar --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="s0"> + <onentry> + <if cond="false"> + <raise event="foo"/> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + <elseif cond="true"/> + <raise event="bar"/> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + <else/> + <raise event="baz"/> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </if> + <raise event="bat"/> + </onentry> + <transition event="bar" cond="Var1==1" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test148.scxml b/test/w3c/promela/test148.scxml new file mode 100644 index 0000000..fafb41a --- /dev/null +++ b/test/w3c/promela/test148.scxml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that the else clause executes if <if> and <elseif> evaluate to false. +Baz should be the only event generated by the <if>. bat is raised to catch the case where the <else> clause +fails and baz is not generated, i.e. it makes sure that the test doesn't hang. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="s0"> + <onentry> + <if cond="false"> + <raise event="foo"/> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + <elseif cond="false"/> + <raise event="bar"/> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + <else/> + <raise event="baz"/> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </if> + <raise event="bat"/> + </onentry> + <transition event="baz" cond="Var1==1" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test149.scxml b/test/w3c/promela/test149.scxml new file mode 100644 index 0000000..a11083e --- /dev/null +++ b/test/w3c/promela/test149.scxml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that neither if clause executes, so that bat is the only event raised. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="s0"> + <onentry> + <if cond="false"> + <raise event="foo"/> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + <elseif cond="false"/> + <raise event="bar"/> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </if> + <raise event="bat"/> + </onentry> + <transition event="bat" cond="Var1==0" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test150.scxml b/test/w3c/promela/test150.scxml new file mode 100644 index 0000000..3816c3e --- /dev/null +++ b/test/w3c/promela/test150.scxml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that foreach causes a new variable to be declared if 'item' doesn't already exist. Also +test that it will use an existing var if it does exist. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <datamodel> + <data id="Var1" type="int"/> + <data id="Var2" type="int"/> + <data id="Var3" type="int[3]"> + [1,2,3] + </data> + </datamodel> + <state id="s0"> + <onentry> + <!-- first use declared variables --> + <foreach item="Var1" index="Var2" array="Var3"/> + <raise event="foo"/> + </onentry> + <transition event="error" target="fail"/> + <transition event="*" target="s1"/> + </state> + <state id="s1"> + <onentry> + <!-- now use undeclared variables --> + <foreach item="Var4" index="Var5" array="Var3"/> + <raise event="bar"/> + </onentry> + <transition event="error" target="fail"/> + <transition event="*" target="s2"/> + </state> + <state id="s2"> + <!-- check that var4 is bound --> + <transition cond="Var4" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test151.scxml b/test/w3c/promela/test151.scxml new file mode 100644 index 0000000..bb50570 --- /dev/null +++ b/test/w3c/promela/test151.scxml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that foreach causes a new variable to be declared if 'item' doesn't already exist. Also +test that it will use an existing var if it does exist. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <datamodel> + <data id="Var1" type="int"/> + <data id="Var2" type="int"/> + <data id="Var3" type="int[3]"> + [1,2,3] + </data> + </datamodel> + <state id="s0"> + <onentry> + <!-- first use declared variables --> + <foreach item="Var1" index="Var2" array="Var3"/> + <raise event="foo"/> + </onentry> + <transition event="error" target="fail"/> + <transition event="*" target="s1"/> + </state> + <state id="s1"> + <onentry> + <!-- now use undeclared variables --> + <foreach item="Var4" index="Var5" array="Var3"/> + <raise event="bar"/> + </onentry> + <transition event="error" target="fail"/> + <transition event="*" target="s2"/> + </state> + <state id="s2"> + <!-- check that var5 is bound --> + <transition cond="Var5" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test152.scxml b/test/w3c/promela/test152.scxml new file mode 100644 index 0000000..71f0011 --- /dev/null +++ b/test/w3c/promela/test152.scxml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that an illegal array or item value causes error.execution and results in executable content +not being executed. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + <data id="Var2" type="int"/> + <data id="Var3" type="int"/> + <data id="Var4" type="int" expr="7"/> + <data id="Var5" type="int[3]"> + [1,2,3] + </data> + </datamodel> + <state id="s0"> + <onentry> + <!-- invalid array, legal item --> + <foreach item="Var2" index="Var3" array="Var4"> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </foreach> + <raise event="foo"/> + </onentry> + <transition event="error.execution" target="s1"/> + <transition event="*" target="fail"/> + </state> + <state id="s1"> + <onentry> + <!-- illegal item, legal array --> + <foreach item="'continue'" index="Var3" array="Var5"> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </foreach> + <raise event="bar"/> + </onentry> + <transition event="error.execution" target="s2"/> + <transition event="bar" target="fail"/> + </state> + <state id="s2"> + <!-- check that var1 has its original value (so executable content never got executed --> + <transition cond="Var1==0" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test153.scxml b/test/w3c/promela/test153.scxml new file mode 100644 index 0000000..9890b47 --- /dev/null +++ b/test/w3c/promela/test153.scxml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that foreach goes over the array in the right order. since the array contains 1 2 3, we compare the current +value with the previous value, which is stored in var1. The current value should always be larger. If +it ever isn't, set Var4 to 0, indicating failure --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + <!-- contains the previous value --> + <data id="Var2" type="int"/> + <!-- the item which will contain the current value --> + <data id="Var3" type="int[3]"> + [1,2,3] + </data> + <data id="Var4" type="int" expr="1"/> + <!-- 1 if success, 0 if failure --> + </datamodel> + <state id="s0"> + <onentry> + <foreach item="Var2" array="Var3"> + <if cond="Var1<Var2"> + <assign location="Var1" expr="Var2"/> + <else/> + <!-- values are out of order, record failure --> + <assign location="Var4" expr="0"/> + </if> + </foreach> + </onentry> + <!-- check that var1 has its original value --> + <transition cond="Var4==0" target="fail"/> + <transition target="pass"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test155.scxml b/test/w3c/promela/test155.scxml new file mode 100644 index 0000000..27fd196 --- /dev/null +++ b/test/w3c/promela/test155.scxml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that foreach executes the executable content once for each item in the list '(1,2,3)'. The executable +content sums the items into var1 so it should be 6 at the end --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + <data id="Var2" type="int"/> + <data id="Var3" type="int[3]"> + [1,2,3] + </data> + </datamodel> + <state id="s0"> + <onentry> + <foreach item="Var2" array="Var3"> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + Var2"/> + </foreach> + </onentry> + <transition cond="Var1==6" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test156.scxml b/test/w3c/promela/test156.scxml new file mode 100644 index 0000000..d81a2a2 --- /dev/null +++ b/test/w3c/promela/test156.scxml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that an error causes the foreach to stop execution. The second piece of executable content +should cause an error, so var1 should be incremented only once --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + <data id="Var2" type="int"/> + <data id="Var3" type="int[3]"> + [1,2,3] + </data> + </datamodel> + <state id="s0"> + <onentry> + <foreach item="Var2" array="Var3"> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + <!-- assign an illegal value to a non-existent var --> + <assign location="Var5" expr="return"/> + </foreach> + </onentry> + <transition cond="Var1==1" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test158.scxml b/test/w3c/promela/test158.scxml new file mode 100644 index 0000000..d921652 --- /dev/null +++ b/test/w3c/promela/test158.scxml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that executable content executes in document order. if event1 occurs then event2, succeed, otherwise fail --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="s0"> + <onentry> + <raise event="event1"/> + <raise event="event2"/> + </onentry> + <transition event="event1" target="s1"/> + <transition event="*" target="fail"/> + </state> + <state id="s1"> + <transition event="event2" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test159.scxml b/test/w3c/promela/test159.scxml new file mode 100644 index 0000000..f59d1f9 --- /dev/null +++ b/test/w3c/promela/test159.scxml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that any error raised by an element of executable content causes all subsequent elements to be skipped. +The send tag will raise an error so var1 should not be incremented. If it is fail, otherwise succeed --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="s0"> + <onentry> + <send event="thisWillFail" target="baz"/> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </onentry> + <transition cond="Var1==1" target="fail"/> + <transition target="pass"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test172.scxml b/test/w3c/promela/test172.scxml new file mode 100644 index 0000000..bd99e91 --- /dev/null +++ b/test/w3c/promela/test172.scxml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that eventexpr uses the current value of var1, not its initial value --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <datamodel> + <data id="Var1" type="string" expr="'event1'"/> + </datamodel> + <state id="s0"> + <onentry> + <assign location="Var1" expr="'event2'"/> + <send eventexpr="Var1"/> + </onentry> + <transition event="event2" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test173.scxml b/test/w3c/promela/test173.scxml new file mode 100644 index 0000000..cb3728e --- /dev/null +++ b/test/w3c/promela/test173.scxml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that targetexpr uses the current value of var1, not its initial value +(If it uses the initial value, it will generate an error. If it uses the current value, event1 will be raised --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="27"/> + </datamodel> + <state id="s0"> + <onentry> + <assign location="Var1" expr="'#_internal'"/> + <send targetexpr="Var1" event="event1"/> + </onentry> + <transition event="event1" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test174.scxml b/test/w3c/promela/test174.scxml new file mode 100644 index 0000000..1e44370 --- /dev/null +++ b/test/w3c/promela/test174.scxml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that typeexpr uses the current value of var1, not its initial value +(If it uses the initial value, it will generate an error. If it uses the current value, event1 will be raised --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <datamodel> + <data id="Var1" type="int" expr="27"/> + </datamodel> + <state id="s0"> + <onentry> + <assign location="Var1" expr="'http://www.w3.org/TR/scxml/#SCXMLEventProcessor'"/> + <send typeexpr="Var1" event="event1"/> + </onentry> + <transition event="event1" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test175.scxml b/test/w3c/promela/test175.scxml new file mode 100644 index 0000000..c44a6ab --- /dev/null +++ b/test/w3c/promela/test175.scxml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that delayexpr uses the current value of var1, not its initial value +(If it uses the initial value, event2 will be generated first, before event1. If it uses the current value, +event1 will be raised first. Succeed if event1 occurs before event2, otherwise fail --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="s0"> + <onentry> + <assign location="Var1" expr="1000"/> + <send delayexpr="Var1" event="event2"/> + <send delayexpr="500" event="event1"/> + </onentry> + <transition event="event1" target="s1"/> + <transition event="event2" target="fail"/> + </state> + <state id="s1"> + <transition event="event2" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test176.scxml b/test/w3c/promela/test176.scxml new file mode 100644 index 0000000..d79b32e --- /dev/null +++ b/test/w3c/promela/test176.scxml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that <param> uses the current value of var1, not its initial value. If the value of +aParam in event1 is 2 so that var2 gets set to 2, success, otherwise failure --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="1"/> + <data id="Var2" type="int"/> + </datamodel> + <state id="s0"> + <onentry> + <assign location="Var1" expr="2"/> + <send event="event1"> + <param name="aParam" expr="Var1"/> + </send> + </onentry> + <transition event="event1" target="s1"> + <assign location="Var2" expr="_event.data.aParam"/> + </transition> + <transition event="*" target="fail"/> + </state> + <state id="s1"> + <transition cond="Var2==2" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test178.scxml b/test/w3c/promela/test178.scxml new file mode 100644 index 0000000..5256cd3 --- /dev/null +++ b/test/w3c/promela/test178.scxml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that multiple key/value pairs are included, even when the keys are the same. +This is a manual test. The tester must look at the log output and verify that both +keys are there. (This test uses the SCXML Event I/O processor, which is the only +one that all platforms must support. It does not specify the message format, so +we cannot test _event.raw directly. Therefore we print it out for visual +inspection.) --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send event="event1"> + <param name="Var1" expr="2"/> + <param name="Var1" expr="3"/> + </send> + </onentry> + <transition event="event1" target="final"> + <log label="_event " expr="_event.raw"/> + </transition> + <transition event="*" target="fail"/> + </state> + <final id="final"/> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test179.scxml b/test/w3c/promela/test179.scxml new file mode 100644 index 0000000..c81030c --- /dev/null +++ b/test/w3c/promela/test179.scxml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that <content> can be used to populate body of a message --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send event="event1"> + <content>123</content> + </send> + </onentry> + <transition event="event1" cond="_event.data == 123" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test183.scxml b/test/w3c/promela/test183.scxml new file mode 100644 index 0000000..53ec8c7 --- /dev/null +++ b/test/w3c/promela/test183.scxml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that <send> stores the value of the sendid in idlocation. If it does, +var1 has a value and we pass. Otherwise we fail --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <datamodel> + <data id="Var1" type="int"/> + </datamodel> + <state id="s0"> + <onentry> + <send event="event1" idlocation="Var1"/> + </onentry> + <transition cond="Var1" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test185.scxml b/test/w3c/promela/test185.scxml new file mode 100644 index 0000000..0ef8c2e --- /dev/null +++ b/test/w3c/promela/test185.scxml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that <send> respects the delay specification. If it does, event1 arrives before event2 + and we pass. Otherwise we fail --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send event="event2" delayexpr="1000"/> + <send event="event1"/> + </onentry> + <transition event="event1" target="s1"/> + <transition event="*" target="fail"/> + </state> + <state id="s1"> + <transition event="event2" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test186.scxml b/test/w3c/promela/test186.scxml new file mode 100644 index 0000000..b30f6d0 --- /dev/null +++ b/test/w3c/promela/test186.scxml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that <send> evals its args when it is evaluated, not when the delay interval expires and the +message is actually sent. If it does, aParam will have the value of 1 (even though var1 has been incremented +in the interval.) If var2 ends up == 1, we pass. Otherwise we fail --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="1"/> + <data id="Var2" type="int"/> + </datamodel> + <state id="s0"> + <onentry> + <send event="event1" delayexpr="1000"> + <param name="aParam" expr="Var1"/> + </send> + <assign location="Var1" expr="2"/> + </onentry> + <transition event="event1" target="s1"> + <assign location="Var2" expr="_event.data.aParam"/> + </transition> + <transition event="*" target="fail"/> + </state> + <state id="s1"> + <transition cond="Var2==1" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test187.scxml b/test/w3c/promela/test187.scxml new file mode 100644 index 0000000..fe09a12 --- /dev/null +++ b/test/w3c/promela/test187.scxml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that delayed <send> is not sent if the sending session terminates. In this case, +a subscript is invoked which sends the event childToParent delayed by 1 second, and then terminates. The +parent session, should not receive childToParent. If it does, we fail. Otherwise the +10 sec timer expires and we pass --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send event="timeout" delayexpr="1000"/> + </onentry> + <invoke type="scxml"> + <content> + <!-- exit before the delayed send can execute --> + <scxml initial="sub0" version="1.0" datamodel="promela"> + <state id="sub0"> + <onentry> + <send event="childToParent" target="#_parent" delayexpr="500"/> + </onentry> + <transition target="subFinal"/> + </state> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <transition event="childToParent" target="fail"/> + <transition event="timeout" target="pass"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test189.scxml b/test/w3c/promela/test189.scxml new file mode 100644 index 0000000..b1bbf2a --- /dev/null +++ b/test/w3c/promela/test189.scxml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that #_internal as a target of <send> puts the event on the internal queue. If it does, +event1 will be processed before event2, because event1 is added to the internal queue while event2 is +added to the external queue (event though event2 is generated first) --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <!-- goes to the external queue --> + <send event="event2"/> + <!-- to the internal queue --> + <send event="event1" target="#_internal"/> + </onentry> + <!-- once we've entered the state, we should check for internal events first --> + <transition event="event1" target="pass"/> + <transition event="event2" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test190.scxml b/test/w3c/promela/test190.scxml new file mode 100644 index 0000000..2143e85 --- /dev/null +++ b/test/w3c/promela/test190.scxml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that #_scxml_sessionid as a target of <send> puts the event on the external queue. If it does, +event1 will be processed before event2, because event1 is added to the internal queue while event2 is +added to the external queue (event though event2 is generated first). we have to make sure that event2 +is actually delivered. The delayed <send> makes sure another event is generated (so the test doesn't hang) --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="string" expr="'#_scxml_'"/> + <data id="Var2" type="string" expr="_sessionid"/> + </datamodel> + <state id="s0"> + <onentry> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + Var2"/> + <!-- goes to the external queue --> + <send event="event2" targetexpr="Var1"/> + <!-- to the internal queue --> + <raise event="event1"/> + <!-- this should get added to the external queue after event2 --> + <send event="timeout"/> + </onentry> + <!-- once we've entered the state, we should check for internal events first --> + <transition event="event1" target="s1"/> + <transition event="*" target="fail"/> + </state> + <!-- now check that we get event2 and not a timeout --> + <state id="s1"> + <transition event="event2" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test191.scxml b/test/w3c/promela/test191.scxml new file mode 100644 index 0000000..6fc9a7f --- /dev/null +++ b/test/w3c/promela/test191.scxml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that #_parent works as a target of <send> . a subscript is invoked and sends the event +childToParent to its parent session (ths session) using #_parent as the target. If we get this event, we +pass, otherwise we fail. The timer insures that some event is generated and that the test does not hang. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="5000" event="timeout"/> + </onentry> + <invoke type="scxml"> + <content> + <!-- send an event to the parent session using #_parent as the target --> + <scxml initial="sub0" version="1.0" datamodel="promela"> + <state id="sub0"> + <onentry> + <send event="childToParent" target="#_parent"/> + </onentry> + <transition target="subFinal"/> + </state> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <transition event="childToParent" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test192.scxml b/test/w3c/promela/test192.scxml new file mode 100644 index 0000000..48a019a --- /dev/null +++ b/test/w3c/promela/test192.scxml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that #_invokeid works as a target of <send> . A child script is invoked and sends us +childToParent once its running. Then we send it the event parentToChild using its invokeid as the target. +If it receives this event, it sends sends the event eventReceived to its parent session (ths session). +If we get this event, we pass, otherwise the child script eventually times out sends invoke.done and we fail. +We also set a timeout in this process to make sure the test doesn't hang --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <state id="s0" initial="s01"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="5000" event="timeout"/> + </onentry> + <invoke type="scxml" id="invokedChild"> + <content> + <!-- let the parent session know we're running by sending childToParent, then wait for parentToChild. + If we get it, send eventReceived. If we don't we eventually time out --> + <scxml initial="sub0" version="1.0" datamodel="promela"> + <state id="sub0"> + <onentry> + <send event="childToParent" target="#_parent"/> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="3000" event="timeout"/> + </onentry> + <transition event="parentToChild" target="subFinal"> + <send target="#_parent" event="eventReceived"/> + </transition> + <transition event="timeout" target="subFinal"/> + </state> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <transition event="timeout" target="fail"/> + <transition event="done.invoke" target="fail"/> + <state id="s01"> + <transition event="childToParent" target="s02"> + <send target="#_invokedChild" event="parentToChild"/> + </transition> + </state> + <state id="s02"> + <transition event="eventReceived" target="pass"/> + </state> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test193.scxml b/test/w3c/promela/test193.scxml new file mode 100644 index 0000000..2d240e7 --- /dev/null +++ b/test/w3c/promela/test193.scxml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that omitting target and targetexpr of <send> when using the +SCXML event i/o processor puts the event on the external queue. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send event="internal"/> + <!-- this should put event1 in the external queue --> + <send event="event1" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor"/> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + </onentry> + <transition event="event1" target="fail"/> + <transition event="internal" target="s1"/> + </state> + <state id="s1"> + <transition event="event1" target="pass"/> + <transition event="timeout" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test194.scxml b/test/w3c/promela/test194.scxml new file mode 100644 index 0000000..b9be1a2 --- /dev/null +++ b/test/w3c/promela/test194.scxml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that specifying an illegal target for <send> causes the event error.execution to be raised. If it does, +we succeed. Otherwise we eventually timeout and fail. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <!-- should cause an error --> + <send target="baz" event="event2"/> + <!-- this will get added to the external event queue after the error has been raised --> + <send event="timeout"/> + </onentry> + <!-- once we've entered the state, we should check for internal events first --> + <transition event="error.execution" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test198.scxml b/test/w3c/promela/test198.scxml new file mode 100644 index 0000000..2a45282 --- /dev/null +++ b/test/w3c/promela/test198.scxml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that if type is not provided <send> uses the scxml event i/o processor. The only way to tell +what processor was used is to look at the origintype of the resulting event --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send event="event1"/> + <send event="timeout"/> + </onentry> + <transition event="event1" cond=" _event.origintype == 'http://www.w3.org/TR/scxml/#SCXMLEventProcessor'" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test199.scxml b/test/w3c/promela/test199.scxml new file mode 100644 index 0000000..dbea699 --- /dev/null +++ b/test/w3c/promela/test199.scxml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that using an invalid send type results in error.execution --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send type="27" event="event1"/> + <send event="timeout"/> + </onentry> + <transition event="error.execution" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test200.scxml b/test/w3c/promela/test200.scxml new file mode 100644 index 0000000..e4503fb --- /dev/null +++ b/test/w3c/promela/test200.scxml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that the processor supports the scxml event i/o processor --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <state id="s0"> + <onentry> + <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="event1"/> + <send event="timeout"/> + </onentry> + <transition event="event1" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test201.scxml b/test/w3c/promela/test201.scxml new file mode 100644 index 0000000..d517776 --- /dev/null +++ b/test/w3c/promela/test201.scxml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that the processor supports the basic http event i/o processor. This is an optional +test since platforms are not required to support basic http event i/o --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" targetexpr="_ioprocessors.basichttp.location" event="event1"/> + <send event="timeout"/> + </onentry> + <transition event="event1" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test205.scxml b/test/w3c/promela/test205.scxml new file mode 100644 index 0000000..604b311 --- /dev/null +++ b/test/w3c/promela/test205.scxml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that the processor doesn't change the message. We can't test that it never does this, but +at least we can check that the event name and included data are the same as we sent. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int"/> + </datamodel> + <state id="s0"> + <onentry> + <send event="event1"> + <param name="aParam" expr="1"/> + </send> + <send event="timeout"/> + </onentry> + <transition event="event1" target="s1"> + <assign location="Var1" expr="_event.data.aParam"/> + </transition> + <transition event="*" target="fail"/> + </state> + <state id="s1"> + <transition cond="Var1==1" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test207.scxml b/test/w3c/promela/test207.scxml new file mode 100644 index 0000000..a780b41 --- /dev/null +++ b/test/w3c/promela/test207.scxml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that that we can't cancel an event in another session. We invoke a child process. It notifies +us when it has generated a delayed event with sendid foo. We try to cancel foo. The child process sends us event + event success if the event is not cancelled, event fail otherwise. This doesn't test that there is absolutely no way to cancel an event +raised in another session, but the spec doesn't define any way to refer to an event in another process --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0" initial="s01"> + <onentry> + <send event="timeout" delayexpr="2000"/> + </onentry> + <invoke type="scxml"> + <content> + <!-- when invoked, we raise a delayed event1 with sendid 'foo' and notify our parent. Then we wait. + If event1 occurs, the parent hasn't succeeded in canceling it and we return pass. If event2 occurs + it means event1 was canceled (because event2 is delayed longer than event1) and we return 'fail'. --> + <scxml initial="sub0" version="1.0" datamodel="promela"> + <state id="sub0"> + <onentry> + <send event="event1" id="foo" delayexpr="1000"/> + <send event="event2" delayexpr="1500"/> + <send target="#_parent" event="childToParent"/> + </onentry> + <transition event="event1" target="subFinal"> + <send target="#_parent" event="pass"/> + </transition> + <transition event="*" target="subFinal"> + <send target="#_parent" event="fail"/> + </transition> + </state> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <state id="s01"> + <transition event="childToParent" target="s02"> + <cancel sendid="foo"/> + </transition> + </state> + <state id="s02"> + <transition event="pass" target="pass"/> + <transition event="fail" target="fail"/> + <transition event="timeout" target="fail"/> + </state> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test208.scxml b/test/w3c/promela/test208.scxml new file mode 100644 index 0000000..3fce2d2 --- /dev/null +++ b/test/w3c/promela/test208.scxml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that cancel works. We cancel delayed event1. If cancel works, we get event2 first and pass. If +we get event1 or an error first, cancel didn't work and we fail. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send id="foo" event="event1" delayexpr="1000"/> + <send event="event2" delayexpr="1500"/> + <cancel sendid="foo"/> + </onentry> + <transition event="event2" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test210.scxml b/test/w3c/promela/test210.scxml new file mode 100644 index 0000000..08612be --- /dev/null +++ b/test/w3c/promela/test210.scxml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that sendidexpr works with cancel. If it takes the most recent value of var1, it should cancel +delayed event1. Thus we get event2 first and pass. If we get event1 or an error first, cancel didn't work and we fail. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="string" expr="'bar'"/> + </datamodel> + <state id="s0"> + <onentry> + <send id="foo" event="event1" delayexpr="1000"/> + <send event="event2" delayexpr="1500"/> + <assign location="Var1" expr="'foo'"/> + <cancel sendidexpr="Var1"/> + </onentry> + <transition event="event2" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test215.scxml b/test/w3c/promela/test215.scxml new file mode 100644 index 0000000..3f139c5 --- /dev/null +++ b/test/w3c/promela/test215.scxml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that typexpr is evaluated at runtime. If the original value of var1 is used, the invocation +will fail (test215sub1.scxml is not of type 'foo', even if the platform supports foo as a type). If +the runtime value is used, the invocation will succeed --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <datamodel> + <data id="Var1" type="string" expr="'foo'"/> + </datamodel> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="5000" event="timeout"/> + <assign location="Var1" expr="'http://www.w3.org/TR/scxml/'"/> + </onentry> + <invoke typeexpr="Var1"> + <content> + <!-- when invoked, terminate returning done.invoke. This proves that the invocation succeeded. --> + <scxml initial="subFinal" datamodel="promela" version="1.0"> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <transition event="done.invoke" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test216.scxml b/test/w3c/promela/test216.scxml new file mode 100644 index 0000000..8555040 --- /dev/null +++ b/test/w3c/promela/test216.scxml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that srcexpr is evaluated at runtime. If the original value of var1 is used, the invocation +will fail (assuming that there is no script named 'foo'). If +the runtime value is used, the invocation will succeed --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="string" expr="'foo'"/> + </datamodel> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="5000" event="timeout"/> + <assign location="Var1" expr="'file:test216sub1.scxml'"/> + </onentry> + <invoke srcexpr="Var1" type="http://www.w3.org/TR/scxml"/> + <transition event="done.invoke" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test216sub1.scxml b/test/w3c/promela/test216sub1.scxml new file mode 100644 index 0000000..9a5d74e --- /dev/null +++ b/test/w3c/promela/test216sub1.scxml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- when invoked, terminate returning done.invoke. This proves that the invocation succeeded. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="final" version="1.0" datamodel="promela"> + <final id="final"/> +</scxml> diff --git a/test/w3c/promela/test220.scxml b/test/w3c/promela/test220.scxml new file mode 100644 index 0000000..e16f838 --- /dev/null +++ b/test/w3c/promela/test220.scxml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that the scxml type is supported. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="5000" event="timeout"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <content> + <!-- when invoked, terminate returning done.invoke. This proves that the invocation succeeded. --> + <scxml initial="subFinal" version="1.0" datamodel="promela"> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <transition event="done.invoke" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test223.scxml b/test/w3c/promela/test223.scxml new file mode 100644 index 0000000..99ee320 --- /dev/null +++ b/test/w3c/promela/test223.scxml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that idlocation is supported. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int"/> + </datamodel> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/" idlocation="Var1"> + <content> + <!-- when invoked, terminate returning done.invoke. This proves that the invocation succeeded. --> + <scxml initial="subFinal" version="1.0" datamodel="promela"> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <transition event="*" target="s1"/> + </state> + <state id="s1"> + <transition cond="Var1" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test224.scxml b/test/w3c/promela/test224.scxml new file mode 100644 index 0000000..09bbb25 --- /dev/null +++ b/test/w3c/promela/test224.scxml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that the automatically generated id has the form stateid.platformid. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int"/> + <data id="Var2" type="string" expr="'s0.'"/> + </datamodel> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/" idlocation="Var1"> + <content> + <!-- when invoked, terminate returning done.invoke. This proves that the invocation succeeded. --> + <scxml version="1.0" initial="subFinal" datamodel="promela"> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <transition event="*" target="s1"/> + </state> + <state id="s1"> + <transition cond="(function(str, starts){if (starts == '') return true;if (str == null || starts == null) return false;str = String(str); starts = String(starts);return str.length >= starts.length && str.slice(0, starts.length) == starts;})(Var1, Var2)" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test225.scxml b/test/w3c/promela/test225.scxml new file mode 100644 index 0000000..b38d1a2 --- /dev/null +++ b/test/w3c/promela/test225.scxml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that the automatically generated id is unique, we call invoke twice and compare the ids. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int"/> + <data id="Var2" type="int"/> + </datamodel> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/" idlocation="Var1"> + <content> + <scxml initial="subFinal1" version="1.0" datamodel="promela"> + <final id="subFinal1"/> + </scxml> + </content> + </invoke> + <invoke type="http://www.w3.org/TR/scxml/" idlocation="Var2"> + <content> + <scxml initial="subFinal2" version="1.0" datamodel="promela"> + <final id="subFinal2"/> + </scxml> + </content> + </invoke> + <transition event="*" target="s1"/> + </state> + <state id="s1"> + <transition cond="Var1==Var2" target="fail"/> + <transition target="pass"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test226.scxml b/test/w3c/promela/test226.scxml new file mode 100644 index 0000000..9a003c2 --- /dev/null +++ b/test/w3c/promela/test226.scxml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- this is basically just a test that invoke works correctly and that you can pass data +to the invoked process. If the invoked session finds aParam==1, it exits, signalling +success. otherwise it will hang and the timeout in this doc signifies failure. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="3000" event="timeout"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/" src="file:test226sub1.scxml"> + <param name="Var1" expr="1"/> + </invoke> + <transition event="varBound" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test226sub1.scxml b/test/w3c/promela/test226sub1.scxml new file mode 100644 index 0000000..3d7869a --- /dev/null +++ b/test/w3c/promela/test226sub1.scxml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- when invoked, if var1 has a value notify parent. Then terminate. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <datamodel> + <data id="Var1" type="int"/> + </datamodel> + <state id="s0"> + <transition cond="Var1" target="final"> + <send target="#_parent" event="varBound"/> + </transition> + <transition target="final"/> + </state> + <final id="final"/> +</scxml> diff --git a/test/w3c/promela/test228.scxml b/test/w3c/promela/test228.scxml new file mode 100644 index 0000000..137418a --- /dev/null +++ b/test/w3c/promela/test228.scxml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that the invokeid is included in events returned from the invoked process. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int"/> + </datamodel> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="3000" event="timeout"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/" id="foo"> + <content> + <scxml initial="subFinal" version="1.0" datamodel="promela"> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <transition event="done.invoke" target="s1"> + <assign location="Var1" expr="_event.invokeid"/> + </transition> + <transition event="*" target="fail"/> + </state> + <state id="s1"> + <transition cond="Var1=='foo'" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test229.scxml b/test/w3c/promela/test229.scxml new file mode 100644 index 0000000..4030b85 --- /dev/null +++ b/test/w3c/promela/test229.scxml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that autofoward works. If the child process receives back a copy of the +childToParent event that it sends to this doc, it sends eventReceived, signalling success. (Note +that this doc is not required to process that event explicitly. It should be forwarded in any case.) Otherwise +it eventually times out and the done.invoke signals failure --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="3000" event="timeout"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/" autoforward="true"> + <content> + <!-- when invoked, send childToParent to parent. + If it is forwarded back to us, send + eventReceived to signal success and terminate. + Otherwise wait for timer to expire and terminate. --> + <scxml initial="sub0" version="1.0" datamodel="promela"> + <state id="sub0"> + <onentry> + <send target="#_parent" event="childToParent"/> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="3000" event="timeout"/> + </onentry> + <transition event="childToParent" target="subFinal"> + <send target="#_parent" event="eventReceived"/> + </transition> + <transition event="*" target="subFinal"/> + </state> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <transition event="childToParent"/> + <transition event="eventReceived" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test230.scxml b/test/w3c/promela/test230.scxml new file mode 100644 index 0000000..e8bd447 --- /dev/null +++ b/test/w3c/promela/test230.scxml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- a manual test that an autofowarded event has the same fields and values as the original event. +the child process sends the parent process an event which is forwarded back to it. +Both the parent and child process print out the contents of the event. The tester +must check if they are the same and report his result. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0" initial="s01"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="3000" event="timeout"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/" autoforward="true"> + <content> + <!-- when invoked, send childToParent to parent. If it is forwarded back to us, print out its + fields and terminate. --> + <scxml initial="sub0" version="1.0" datamodel="promela"> + <state id="sub0"> + <onentry> + <send target="#_parent" event="childToParent"/> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="2000" event="timeout"/> + </onentry> + <transition event="childToParent" target="subFinal"> + <log label="name is " expr="_event.name"/> + <log label="type is " expr="_event.type"/> + <log label="sendid is " expr="_event.sendid"/> + <log label="origin is " expr="_event.origin"/> + <log label="origintype is " expr="_event.origintype"/> + <log label="invokeid is " expr="_event.invokeid"/> + <log label="data is " expr="_event.data"/> + </transition> + <transition event="*" target="subFinal"/> + </state> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <transition event="timeout" target="final"/> + <state id="s01"> + <transition event="childToParent" target="s02"> + <log label="name is " expr="_event.name"/> + <log label="type is " expr="_event.type"/> + <log label="sendid is " expr="_event.sendid"/> + <log label="origin is " expr="_event.origin"/> + <log label="origintype is " expr="_event.origintype"/> + <log label="invokeid is " expr="_event.invokeid"/> + <log label="data is " expr="_event.data"/> + </transition> + <transition event="*" target="fail"/> + </state> + <state id="s02"> + <!-- wait till we get the done event to ensure that the child process has time to print out its results --> + <transition event="done.invoke" target="final"/> + </state> + </state> + <final id="final"/> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test232.scxml b/test/w3c/promela/test232.scxml new file mode 100644 index 0000000..c54874e --- /dev/null +++ b/test/w3c/promela/test232.scxml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that a parent process can receive multiple events from a child process --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0" initial="s01"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="3000" event="timeout"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <content> + <scxml initial="subFinal" version="1.0" datamodel="promela"> + <final id="subFinal"> + <onentry> + <send target="#_parent" event="childToParent1"/> + <send target="#_parent" event="childToParent2"/> + </onentry> + </final> + </scxml> + </content> + </invoke> + <transition event="timeout" target="fail"/> + <state id="s01"> + <transition event="childToParent1" target="s02"/> + </state> + <state id="s02"> + <transition event="childToParent2" target="s03"/> + </state> + <state id="s03"> + <transition event="done.invoke" target="pass"/> + </state> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test233.scxml b/test/w3c/promela/test233.scxml new file mode 100644 index 0000000..195d244 --- /dev/null +++ b/test/w3c/promela/test233.scxml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that finalize markup runs before the event is processed. The invoked process will +return 2 in _event.data.aParam, so that new value should be in force when we select +the transtitions. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="1"/> + </datamodel> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="3000" event="timeout"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <content> + <scxml initial="subFinal" version="1.0" datamodel="promela"> + <final id="subFinal"> + <onentry> + <send target="#_parent" event="childToParent"> + <param name="aParam" expr="2"/> + </send> + </onentry> + </final> + </scxml> + </content> + <finalize> + <assign location="Var1" expr="_event.data.aParam"/> + </finalize> + </invoke> + <transition event="childToParent" cond="Var1==2" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test234.scxml b/test/w3c/promela/test234.scxml new file mode 100644 index 0000000..2e79a98 --- /dev/null +++ b/test/w3c/promela/test234.scxml @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that only finalize markup in the invoking state runs. the first invoked process will +return 2 in _event.data.aParam, while second invoked process sleeps without returning any events. +Only the first finalize should execute. So when we get to s1 var1 should have value 2 but +var2 should still be set to 1 --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="p0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="1"/> + <data id="Var2" type="int" expr="1"/> + </datamodel> + <parallel id="p0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="3000" event="timeout"/> + </onentry> + <transition event="timeout" target="fail"/> + <state id="p01"> + <invoke type="http://www.w3.org/TR/scxml/"> + <content> + <scxml version="1.0" initial="subFinal1" datamodel="promela"> + <final id="subFinal1"> + <onentry> + <send target="#_parent" event="childToParent"> + <param name="aParam" expr="2"/> + </send> + </onentry> + </final> + </scxml> + </content> + <finalize> + <assign location="Var1" expr="_event.data.aParam"/> + </finalize> + </invoke> + <transition event="childToParent" cond="Var1==2" target="s1"/> + <transition event="childToParent" target="fail"/> + </state> + <state id="p02"> + <invoke type="http://www.w3.org/TR/scxml/"> + <content> + <scxml version="1.0" initial="sub0" datamodel="promela"> + <state id="sub0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="2000" event="timeout"/> + </onentry> + <transition event="timeout" target="subFinal2"/> + </state> + <final id="subFinal2"/> + </scxml> + </content> + <finalize> + <assign location="Var2" expr="_event.data.aParam"/> + </finalize> + </invoke> + </state> + </parallel> + <state id="s1"> + <transition cond="Var2==1" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test235.scxml b/test/w3c/promela/test235.scxml new file mode 100644 index 0000000..6c6383b --- /dev/null +++ b/test/w3c/promela/test235.scxml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that done.invoke.id event has the right id. the invoked child terminates immediately +and should generate done.invoke.foo --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="2000" event="timeout"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/" id="foo"> + <content> + <scxml initial="subFinal" version="1.0" datamodel="promela"> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <transition event="done.invoke.foo" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test236.scxml b/test/w3c/promela/test236.scxml new file mode 100644 index 0000000..2a8c76c --- /dev/null +++ b/test/w3c/promela/test236.scxml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that done.invoke.id event is the last event we receive. the invoked process sends childToParent +in the exit handler of its final state. We should get it before the done.invoke, and we should get no +events after the done.invoke. Hence timeout indicates success --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send event="timeout" delayexpr="2000"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <content> + <scxml initial="subFinal" version="1.0" datamodel="promela"> + <final id="subFinal"> + <onexit> + <send target="#_parent" event="childToParent"/> + </onexit> + </final> + </scxml> + </content> + </invoke> + <transition event="childToParent" target="s1"/> + <transition event="done.invoke" target="fail"/> + </state> + <state id="s1"> + <!-- here we should get done.invoke --> + <transition event="done.invoke" target="s2"/> + <transition event="*" target="fail"/> + </state> + <state id="s2"> + <transition event="timeout" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test237.scxml b/test/w3c/promela/test237.scxml new file mode 100644 index 0000000..b39e7db --- /dev/null +++ b/test/w3c/promela/test237.scxml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that cancelling works. invoked child sleeps for two seconds, then terminates. We +sleep for 1 sec in s0, then move to s1. This should cause the invocation to get cancelled. +If we receive done.invoke, the invocation wasn't cancelled, and we fail. If we receive no events by +the time timeout2 fires, success --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send event="timeout1" delayexpr="1000"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <content> + <!-- when invoked, sleep for 2 secs then terminate. Parent will try to cancel this session --> + <scxml initial="sub0" version="1.0" datamodel="promela"> + <state id="sub0"> + <onentry> + <send event="timeout" delayexpr="2000"/> + </onentry> + <transition event="timeout" target="subFinal"/> + </state> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <transition event="timeout1" target="s1"/> + </state> + <state id="s1"> + <onentry> + <send event="timeout2" delayexpr="1500"/> + </onentry> + <!-- here we should NOT get done.invoke --> + <transition event="done.invoke" target="fail"/> + <transition event="*" target="pass"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test239.scxml b/test/w3c/promela/test239.scxml new file mode 100644 index 0000000..dc13d5f --- /dev/null +++ b/test/w3c/promela/test239.scxml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that markup can be specified both by 'src' and by <content> --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0" initial="s01"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="2000" event="timeout"/> + </onentry> + <transition event="timeout" target="fail"/> + <state id="s01"> + <invoke type="http://www.w3.org/TR/scxml/" src="file:test239sub1.scxml"/> + <transition event="done.invoke" target="s02"/> + </state> + <state id="s02"> + <invoke type="http://www.w3.org/TR/scxml/"> + <!-- identical to test239sub1.scxml. --> + <content> + <scxml version="1.0" initial="final" datamodel="promela"> + <final id="final"/> + </scxml> + </content> + </invoke> + <transition event="done.invoke" target="pass"/> + </state> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test239sub1.scxml b/test/w3c/promela/test239sub1.scxml new file mode 100644 index 0000000..4f0ea59 --- /dev/null +++ b/test/w3c/promela/test239sub1.scxml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- when invoked, just terminate. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="final" version="1.0" datamodel="promela"> + <final id="final"/> +</scxml> diff --git a/test/w3c/promela/test240.scxml b/test/w3c/promela/test240.scxml new file mode 100644 index 0000000..f18b796 --- /dev/null +++ b/test/w3c/promela/test240.scxml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that datamodel values can be specified both by 'namelist' and by <param>. +invoked child will return success if its Var1 is set to 1, failure otherwise. This +test will fail schema validation because of the multiple occurences of Var1, but +should run correctly. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="1"/> + </datamodel> + <state id="s0" initial="s01"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="2000" event="timeout"/> + </onentry> + <transition event="timeout" target="fail"/> + <state id="s01"> + <invoke type="http://www.w3.org/TR/scxml/" namelist="Var1"> + <content> + <scxml initial="sub01" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="sub01"> + <transition cond="Var1==1" target="subFinal1"> + <send target="#_parent" event="success"/> + </transition> + <transition target="subFinal1"> + <send target="#_parent" event="failure"/> + </transition> + </state> + <final id="subFinal1"/> + </scxml> + </content> + </invoke> + <transition event="success" target="s02"/> + <transition event="failure" target="fail"/> + </state> + <state id="s02"> + <invoke type="http://www.w3.org/TR/scxml/"> + <param name="Var1" expr="1"/> + <content> + <scxml initial="sub02" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="sub02"> + <transition cond="Var1==1" target="subFinal2"> + <send target="#_parent" event="success"/> + </transition> + <transition target="subFinal2"> + <send target="#_parent" event="failure"/> + </transition> + </state> + <final id="subFinal2"/> + </scxml> + </content> + </invoke> + <transition event="success" target="pass"/> + <transition event="failure" target="fail"/> + </state> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test241.scxml b/test/w3c/promela/test241.scxml new file mode 100644 index 0000000..f2cebaa --- /dev/null +++ b/test/w3c/promela/test241.scxml @@ -0,0 +1,96 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- The child process will return success ifits Var1 is set to 1, failure otherwise. For this test +we try passing in Var1 by param and by namelist and check that we either get two successes +or two failures. This test will fail schema validation due to multiple declarations of +Var1, but should run correctly. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="1"/> + </datamodel> + <state id="s0" initial="s01"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="2000" event="timeout"/> + </onentry> + <transition event="timeout" target="fail"/> + <state id="s01"> + <invoke type="http://www.w3.org/TR/scxml/" namelist="Var1"> + <content> + <scxml initial="sub01" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="sub01"> + <transition cond="Var1==1" target="subFinal1"> + <send target="#_parent" event="success"/> + </transition> + <transition target="subFinal1"> + <send target="#_parent" event="failure"/> + </transition> + </state> + <final id="subFinal1"/> + </scxml> + </content> + </invoke> + <transition event="success" target="s02"/> + <transition event="failure" target="s03"/> + </state> + <state id="s02"> + <invoke type="http://www.w3.org/TR/scxml/"> + <param name="Var1" expr="1"/> + <content> + <scxml initial="sub02" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="sub02"> + <transition cond="Var1==1" target="subFinal2"> + <send target="#_parent" event="success"/> + </transition> + <transition target="subFinal2"> + <send target="#_parent" event="failure"/> + </transition> + </state> + <final id="subFinal2"/> + </scxml> + </content> + </invoke> + <!-- we got success in s01, so we need to do so here --> + <transition event="success" target="pass"/> + <transition event="failure" target="fail"/> + </state> + <state id="s03"> + <invoke type="http://www.w3.org/TR/scxml/"> + <param name="Var1" expr="1"/> + <content> + <scxml initial="sub03" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="sub03"> + <transition cond="Var1==1" target="subFinal3"> + <send target="#_parent" event="success"/> + </transition> + <transition target="subFinal3"> + <send target="#_parent" event="failure"/> + </transition> + </state> + <final id="subFinal3"/> + </scxml> + </content> + </invoke> + <!-- we got failure in s01, so we need to do so here --> + <transition event="failure" target="pass"/> + <transition event="success" target="fail"/> + </state> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test242.scxml b/test/w3c/promela/test242.scxml new file mode 100644 index 0000000..2184c54 --- /dev/null +++ b/test/w3c/promela/test242.scxml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that markup specified by 'src' and by <content> is treated the same way. That means that +either we get done.invoke in both cases or in neither case (in which case we timeout) --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + </onentry> + <transition event="timeout" target="fail"/> + <invoke type="http://www.w3.org/TR/scxml/" src="file:test242sub1.scxml"/> + <transition event="done.invoke" target="s02"/> + <transition event="timeout1" target="s03"/> + </state> + <state id="s02"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <!-- identical to test242sub1.scxml. --> + <content> + <scxml version="1.0" initial="subFinal1" datamodel="promela"> + <final id="subFinal1"/> + </scxml> + </content> + </invoke> + <!-- we got done.invoke last time, so we need it this time too --> + <transition event="done.invoke" target="pass"/> + <transition event="timeout2" target="fail"/> + </state> + <state id="s03"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <!-- identical to test242sub1.scxml. --> + <content> + <scxml version="1.0" initial="subFinal2" datamodel="promela"> + <final id="subFinal2"/> + </scxml> + </content> + </invoke> + <!-- we got timeout last time, so we need it this time too --> + <transition event="timeout3" target="pass"/> + <transition event="done.invoke" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test242sub1.scxml b/test/w3c/promela/test242sub1.scxml new file mode 100644 index 0000000..4f0ea59 --- /dev/null +++ b/test/w3c/promela/test242sub1.scxml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- when invoked, just terminate. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="final" version="1.0" datamodel="promela"> + <final id="final"/> +</scxml> diff --git a/test/w3c/promela/test243.scxml b/test/w3c/promela/test243.scxml new file mode 100644 index 0000000..886f732 --- /dev/null +++ b/test/w3c/promela/test243.scxml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that datamodel values can be specified by param. +test240sub1 will return success ifits Var1 is set to 1, failure otherwise. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="2000" event="timeout"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <param name="Var1" expr="1"/> + <content> + <scxml version="1.0" initial="sub0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="sub0"> + <transition cond="Var1==1" target="subFinal"> + <send target="#_parent" event="success"/> + </transition> + <transition target="subFinal"> + <send target="#_parent" event="failure"/> + </transition> + </state> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <transition event="success" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test244.scxml b/test/w3c/promela/test244.scxml new file mode 100644 index 0000000..87d1f0e --- /dev/null +++ b/test/w3c/promela/test244.scxml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that datamodel values can be specified by namelist. +invoked child will return success ifits Var1 is set to 1, failure otherwise. +This test will fail schema validation due to multiple occurrences of Var1, +but should run correctly. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="1"/> + </datamodel> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="2000" event="timeout"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/" namelist="Var1"> + <content> + <scxml initial="sub0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="sub0"> + <transition cond="Var1==1" target="subFinal"> + <send target="#_parent" event="success"/> + </transition> + <transition target="subFinal"> + <send target="#_parent" event="failure"/> + </transition> + </state> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <transition event="success" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test245.scxml b/test/w3c/promela/test245.scxml new file mode 100644 index 0000000..5f5db7f --- /dev/null +++ b/test/w3c/promela/test245.scxml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that non-existent datamodel values are not set. Var2 is not defined in +invoked child's datamodel. It will will return success if its Var2 remains unbound, failure otherwise. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var2" type="int" expr="3"/> + </datamodel> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="2000" event="timeout"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/" namelist="Var2"> + <content> + <scxml initial="sub0" version="1.0" datamodel="promela"> + <state id="sub0"> + <transition cond="Var2" target="subFinal"> + <send target="#_parent" event="failure"/> + </transition> + <transition target="subFinal"> + <send target="#_parent" event="success"/> + </transition> + </state> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <transition event="success" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test247.scxml b/test/w3c/promela/test247.scxml new file mode 100644 index 0000000..383813b --- /dev/null +++ b/test/w3c/promela/test247.scxml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that we get done.invoke. timeout indicates failure --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="2000" event="timeout"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <content> + <scxml version="1.0" initial="subFinal" datamodel="promela"> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <transition event="done.invoke" target="pass"/> + <transition event="timeout" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test250.scxml b/test/w3c/promela/test250.scxml new file mode 100644 index 0000000..0747224 --- /dev/null +++ b/test/w3c/promela/test250.scxml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that the onexit handlers run in the invoked process if it is cancelled. This has to be a +manual test, since this process won't accept any events from the child process once it has been cancelled. +Tester must examine log output from child process to determine success --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send event="foo"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <content> + <scxml initial="sub0" version="1.0" datamodel="promela"> + <state id="sub0" initial="sub01"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="2000" event="timeout"/> + </onentry> + <transition event="timeout" target="subFinal"/> + <onexit> + <log expr="'Exiting sub0'"/> + </onexit> + <state id="sub01"> + <onexit> + <log expr="'Exiting sub01'"/> + </onexit> + </state> + </state> + <final id="subFinal"> + <onentry> + <log expr="'entering final state, invocation was not cancelled'"/> + </onentry> + </final> + </scxml> + </content> + </invoke> + <!-- this transition will cause the invocation to be cancelled --> + <transition event="foo" target="final"/> + </state> + <final id="final"/> +</scxml> diff --git a/test/w3c/promela/test252.scxml b/test/w3c/promela/test252.scxml new file mode 100644 index 0000000..1cc6010 --- /dev/null +++ b/test/w3c/promela/test252.scxml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that we don't process any events received from the invoked process once it is cancelled. child +process tries to send us childToParent in an onexit handler. If we get it, we fail. +timeout indicates success. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0" initial="s01"> + <onentry> + <send event="timeout" delayexpr="1000"/> + </onentry> + <transition event="timeout" target="pass"/> + <transition event="childToParent" target="fail"/> + <transition event="done.invoke" target="fail"/> + <state id="s01"> + <onentry> + <send event="foo"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <content> + <scxml initial="sub0" version="1.0" datamodel="promela"> + <state id="sub0"> + <onentry> + <send event="timeout" delayexpr="500"/> + </onentry> + <transition event="timeout" target="subFinal"/> + <onexit> + <send target="#_parent" event="childToParent"/> + </onexit> + </state> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <!-- this transition will cause the invocation to be cancelled --> + <transition event="foo" target="s02"/> + </state> + <state id="s02"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test253.scxml b/test/w3c/promela/test253.scxml new file mode 100644 index 0000000..d8777ca --- /dev/null +++ b/test/w3c/promela/test253.scxml @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that the scxml event processor is used in both directions. If child process uses the +scxml event i/o processor to communicate with us, send it an event. It will send back success if +this process uses the scxml processor to send the message to it, otherwise failure. For this test we allow +'scxml' as an alternative to the full url. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int"/> + </datamodel> + <state id="s0" initial="s01"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="2000" event="timeout"/> + </onentry> + <transition event="timeout" target="fail"/> + <invoke type="scxml" id="foo"> + <content> + <!-- inform parent we're running then wait for it to send us an event. If it uses the scxml event i/o + processor to do so, return success, otherwise return failure. --> + <scxml initial="sub0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var2" type="int"/> + </datamodel> + <state id="sub0"> + <onentry> + <send target="#_parent" event="childRunning"/> + </onentry> + <transition event="parentToChild" target="sub1"> + <assign location="Var2" expr="_event.origintype"/> + </transition> + </state> + <state id="sub1"> + <transition cond="Var2=='http://www.w3.org/TR/scxml/#SCXMLEventProcessor'" target="subFinal"> + <send target="#_parent" event="success"/> + </transition> + <transition cond="Var2=='scxml'" target="subFinal"> + <send target="#_parent" event="success"/> + </transition> + <transition target="subFinal"> + <send target="#_parent" event="failure"/> + </transition> + </state> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <state id="s01"> + <transition event="childRunning" target="s02"> + <assign location="Var1" expr="_event.origintype"/> + </transition> + </state> + <state id="s02"> + <transition cond="Var1=='http://www.w3.org/TR/scxml/#SCXMLEventProcessor'" target="s03"> + <send target="#_foo" event="parentToChild"/> + </transition> + <transition cond="Var1=='scxml'" target="s03"> + <send target="#_foo" event="parentToChild"/> + </transition> + <transition target="fail"/> + </state> + <state id="s03"> + <transition event="success" target="pass"/> + <transition event="fail" target="fail"/> + </state> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test276.scxml b/test/w3c/promela/test276.scxml new file mode 100644 index 0000000..3602bb0 --- /dev/null +++ b/test/w3c/promela/test276.scxml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that values passed in from parent process override default values specified in the child, test276sub1.scxml. +The child returns event1 if var1 has value 1, event0 if it has default value 0. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <invoke type="scxml" src="file:test276sub1.scxml"> + <param name="Var1" expr="1"/> + </invoke> + <transition event="event1" target="pass"/> + <transition event="event0" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test276sub1.scxml b/test/w3c/promela/test276sub1.scxml new file mode 100644 index 0000000..a95592e --- /dev/null +++ b/test/w3c/promela/test276sub1.scxml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- define var1 with default value 0. Parent will invoke this process setting var1 = 1. Return event1 if var1 == 1, event0 otherwise --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="s0"> + <transition cond="Var1==1" target="final"> + <send target="#_parent" event="event1"/> + </transition> + <transition target="final"> + <send target="#_parent" event="event0"/> + </transition> + </state> + <final id="final"/> +</scxml> diff --git a/test/w3c/promela/test277.scxml b/test/w3c/promela/test277.scxml new file mode 100644 index 0000000..89090d2 --- /dev/null +++ b/test/w3c/promela/test277.scxml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that platform creates undound variable if we assign an illegal value to it. Thus + we can assign to it later in state s1. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="return"/> + </datamodel> + <state id="s0"> + <onentry> + <raise event="foo"/> + </onentry> + <transition event="error.execution" cond="!(Var1)" target="s1"/> + <transition event="*" target="fail"/> + </state> + <state id="s1"> + <onentry> + <assign location="Var1" expr="1"/> + </onentry> + <transition cond="Var1==1" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test278.scxml b/test/w3c/promela/test278.scxml new file mode 100644 index 0000000..a2d613a --- /dev/null +++ b/test/w3c/promela/test278.scxml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <!-- test that a variable can be accessed from a state that is outside its lexical scope --> + <state id="s0"> + <transition cond="Var1==1" target="pass"/> + <transition target="fail"/> + </state> + <state id="s1"> + <datamodel> + <data id="Var1" type="int" expr="1"/> + </datamodel> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test279.scxml b/test/w3c/promela/test279.scxml new file mode 100644 index 0000000..8c12d30 --- /dev/null +++ b/test/w3c/promela/test279.scxml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- testing that in case of early binding variables are assigned values at init time, before + the state containing them is visited --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <transition cond="Var1==1" target="pass"/> + <transition target="fail"/> + </state> + <state id="s1"> + <datamodel> + <data id="Var1" type="int" expr="1"/> + </datamodel> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test280.scxml b/test/w3c/promela/test280.scxml new file mode 100644 index 0000000..d43a883 --- /dev/null +++ b/test/w3c/promela/test280.scxml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test late binding. var2 won't get bound until s1 is entered, so it shouldn't have a value in s0 and +accessing it should cause an error. It should get bound before the onentry code in s1 so it should be +possible access it there and assign its value to var1 --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela" binding="late"> + <datamodel> + <data id="Var1" type="int"/> + </datamodel> + <state id="s0"> + <transition cond="!(Var2)" target="s1"/> + <transition target="fail"/> + </state> + <state id="s1"> + <datamodel> + <data id="Var2" type="int" expr="1"/> + </datamodel> + <onentry> + <assign location="Var1" expr="Var2"/> + </onentry> + <transition cond="Var1==Var2" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test286.scxml b/test/w3c/promela/test286.scxml new file mode 100644 index 0000000..9b84ced --- /dev/null +++ b/test/w3c/promela/test286.scxml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that assigment to a non-declared var causes an error. the transition on foo catches the case +where no error is raised --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="promela" initial="s0"> + <state id="s0"> + <onentry> + <assign location="foo.bar.baz " expr="1"/> + <raise event="foo"/> + </onentry> + <transition event="error.execution" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test287.scxml b/test/w3c/promela/test287.scxml new file mode 100644 index 0000000..2d22f15 --- /dev/null +++ b/test/w3c/promela/test287.scxml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- a simple test that a legal value may be assigned to a valid data model location --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" datamodel="promela" version="1.0" initial="s0"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="s0"> + <onentry> + <assign location="Var1" expr="1"/> + </onentry> + <transition cond="Var1==1" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test288.scxml b/test/w3c/promela/test288.scxml new file mode 100644 index 0000000..8e9b01a --- /dev/null +++ b/test/w3c/promela/test288.scxml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- a simple test that a legal value may be assigned to a valid data model location +using child content --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" datamodel="promela" version="1.0" initial="s0"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="s0"> + <onentry> + <assign location="Var1">123</assign> + </onentry> + <transition cond="Var1 == 123" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test294.scxml b/test/w3c/promela/test294.scxml new file mode 100644 index 0000000..dd38f2d --- /dev/null +++ b/test/w3c/promela/test294.scxml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that a param inside donedata ends up in the data field of the done event and +that content inside donedata sets the full value of the event.data field --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="promela" initial="s0"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="s0" initial="s01"> + <transition event="done.state.s0" cond="_event.data.Var1==1" target="s1"> + </transition> + <transition event="done.state.s0" target="fail"> + </transition> + <state id="s01"> + <transition target="s02"/> + </state> + <final id="s02"> + <donedata> + <param name="Var1" expr="1"/> + </donedata> + </final> + </state> + <state id="s1" initial="s11"> + <transition event="done.state.s1" cond="_event.data == 'foo'" target="pass"> + </transition> + <transition event="done.state.s1" target="fail"> + </transition> + <state id="s11"> + <transition target="s12"/> + </state> + <final id="s12"> + <donedata> + <content xmlns:scxml="http://www.w3.org/2005/07/scxml">foo</content> + </donedata> + </final> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test298.scxml b/test/w3c/promela/test298.scxml new file mode 100644 index 0000000..692b7da --- /dev/null +++ b/test/w3c/promela/test298.scxml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- reference a non-existent data model location in param in donedata and see that the right error is raised --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="promela" initial="s0"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="s0" initial="s01"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + </onentry> + <transition event="error.execution" target="pass"/> + <transition event="*" target="fail"/> + <state id="s01"> + <transition target="s02"/> + </state> + <final id="s02"> + <donedata> + <param name="Var3" location="foo.bar.baz "/> + </donedata> + </final> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test301.scxml b/test/w3c/promela/test301.scxml new file mode 100644 index 0000000..f089387 --- /dev/null +++ b/test/w3c/promela/test301.scxml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- the processor should reject this document because it can't download the script. +Therefore we fail if it runs at all. This test is valid only for datamodels that support scripting --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" initial="s0"> + <script src="D:\foo"/> + <state id="s0"> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test302.scxml b/test/w3c/promela/test302.scxml new file mode 100644 index 0000000..a8161f8 --- /dev/null +++ b/test/w3c/promela/test302.scxml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that a script is evaluated at load time. <conf:script> shoudl assign the value 1 to +Var1. Hence, if script is evaluated at download time, Var1 has a value in the initial state s0. +This test is valid only for datamodels that support scripting --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="promela" initial="s0"> + <script xmlns:scxml="http://www.w3.org/2005/07/scxml">Var1 = 1</script> + <state id="s0"> + <transition cond="Var1==1" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test303.scxml b/test/w3c/promela/test303.scxml new file mode 100644 index 0000000..bf41d39 --- /dev/null +++ b/test/w3c/promela/test303.scxml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- to test that scripts are run as part of executable content, we check that it changes the value of a var at the +right point. This test is valid only for datamodels that support scripting --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="promela" initial="s0"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="s0"> + <onentry> + <assign location="Var1" expr="2"/> + <script xmlns:scxml="http://www.w3.org/2005/07/scxml">Var1 = 1</script> + </onentry> + <transition cond="Var1==1" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test304.scxml b/test/w3c/promela/test304.scxml new file mode 100644 index 0000000..1f8197a --- /dev/null +++ b/test/w3c/promela/test304.scxml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that a variable declared by a script can be accessed like any other part of the data model --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" datamodel="promela" version="1.0" initial="s0"> + <script xmlns:scxml="http://www.w3.org/2005/07/scxml">Var1 = 1</script> + <state id="s0"> + <transition cond="Var1==1" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test307.scxml b/test/w3c/promela/test307.scxml new file mode 100644 index 0000000..bde6684 --- /dev/null +++ b/test/w3c/promela/test307.scxml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" datamodel="promela" version="1.0" initial="s0" binding="late"> + <!-- with binding=late, in s0 we access a variable that isn't created until we get to s1. Then in s1 +we access a non-existent substructure of a variable. We use log tags to report the values that both operations +yield, and whether there are errors. This is a manual test, since the tester must report whether the output +is the same in the two cases --> + <state id="s0"> + <onentry> + <log label="entering s0 value of Var 1 is: " expr="Var1"/> + <raise event="foo"/> + </onentry> + <transition event="error" target="s1"> + <log label="error in state s0" expr="_event"/> + </transition> + <transition event="foo" target="s1"> + <log label="no error in s0" expr=""/> + </transition> + </state> + <state id="s1"> + <datamodel> + <data id="Var1" type="int" expr="1"/> + </datamodel> + <onentry> + <log label="entering s1, value of non-existent substructure of Var 1 is: " expr="Var1.bar"/> + <raise event="bar"/> + </onentry> + <transition event="error" target="final"> + <log label="error in state s1" expr="_event"/> + </transition> + <transition event="bar" target="final"> + <log label="No error in s1" expr=""/> + </transition> + </state> + <final id="final"/> +</scxml> diff --git a/test/w3c/promela/test309.scxml b/test/w3c/promela/test309.scxml new file mode 100644 index 0000000..fb1525c --- /dev/null +++ b/test/w3c/promela/test309.scxml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that an expression that cannot be interpreted as a boolean is treated as false --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="promela" initial="s0"> + <state id="s0"> + <transition cond="return" target="fail"/> + <transition target="pass"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test310.scxml b/test/w3c/promela/test310.scxml new file mode 100644 index 0000000..2428dcd --- /dev/null +++ b/test/w3c/promela/test310.scxml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- simple test of the in() predicate --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="promela" initial="p"> + <parallel id="p"> + <state id="s0"> + <transition cond="config[S1]" target="pass"/> + <transition target="fail"/> + </state> + <state id="s1"/> + </parallel> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test311.scxml b/test/w3c/promela/test311.scxml new file mode 100644 index 0000000..8453a82 --- /dev/null +++ b/test/w3c/promela/test311.scxml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that assignment to a non-existent location yields an error --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="promela" initial="s0"> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + <assign location="foo.bar.baz " expr="1"/> + </onentry> + <transition event="error.execution" target="pass"/> + <transition event=".*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test312.scxml b/test/w3c/promela/test312.scxml new file mode 100644 index 0000000..10bc8cf --- /dev/null +++ b/test/w3c/promela/test312.scxml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that assignment with an illegal expr raises an error --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="promela" initial="s0"> + <datamodel> + <data id="Var1" type="int" expr="1"/> + </datamodel> + <state id="s0"> + <onentry> + <assign location="Var1" expr="return"/> + <raise event="foo"/> + </onentry> + <transition event="error.execution" target="pass"/> + <transition event=".*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test313.scxml b/test/w3c/promela/test313.scxml new file mode 100644 index 0000000..b16fa2f --- /dev/null +++ b/test/w3c/promela/test313.scxml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- this is a manual test. The processor is allowed to reject this doc, but if it executes it with its illegal +expression, it must raise an error --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="promela" initial="s0"> + <datamodel> + <data id="Var1" type="int" expr="1"/> + </datamodel> + <state id="s0"> + <onentry> + <assign location="Var1" expr="return"/> + <raise event="foo"/> + </onentry> + <transition event="error.execution" target="pass"/> + <transition event=".*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test314.scxml b/test/w3c/promela/test314.scxml new file mode 100644 index 0000000..9fea77d --- /dev/null +++ b/test/w3c/promela/test314.scxml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- this is a manual test because the processor is allowed to reject this document. But if it executes it, +it should not raise an error until it gets to s03 and evaluates the illegal expr --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="promela" initial="s0"> + <datamodel> + <data id="Var1" type="int" expr="1"/> + </datamodel> + <state id="s0" initial="s01"> + <transition event="error.execution" target="fail"/> + <state id="s01"> + <transition target="s02"/> + </state> + <state id="s02"> + <transition target="s03"/> + </state> + <state id="s03"> + <onentry> + <assign location="Var1" expr="return"/> + <raise event="foo"/> + </onentry> + <transition event="error.execution" target="pass"/> + <transition event=".*" target="fail"/> + </state> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test318.scxml b/test/w3c/promela/test318.scxml new file mode 100644 index 0000000..27651a4 --- /dev/null +++ b/test/w3c/promela/test318.scxml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that _event stays bound during the onexit and entry into the next state --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela" name="machineName"> + <datamodel> + <data id="Var1" type="int"/> + </datamodel> + <state id="s0"> + <onentry> + <raise event="foo"/> + </onentry> + <transition event="foo" target="s1"/> + </state> + <state id="s1"> + <onentry> + <raise event="bar"/> + <!-- _event should still be bound to 'foo' at this point --> + <assign location="Var1" expr="_event.name"/> + </onentry> + <transition cond="Var1=='foo'" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test319.scxml b/test/w3c/promela/test319.scxml new file mode 100644 index 0000000..2c7159e --- /dev/null +++ b/test/w3c/promela/test319.scxml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that _event is not bound before any event has been raised --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0" name="machineName"> + <state id="s0"> + <onentry> + <if cond="_event"> + <raise event="bound"/> + <else/> + <raise event="unbound"/> + </if> + </onentry> + <transition event="unbound" target="pass"/> + <transition event="bound" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test321.scxml b/test/w3c/promela/test321.scxml new file mode 100644 index 0000000..09c29dd --- /dev/null +++ b/test/w3c/promela/test321.scxml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that _sessionid is bound on startup --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0" name="machineName"> + <datamodel> + <data id="Var1" type="string" expr="_sessionid"/> + </datamodel> + <state id="s0"> + <transition cond="Var1" target="pass"/> + <transition cond="true" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test322.scxml b/test/w3c/promela/test322.scxml new file mode 100644 index 0000000..10bca29 --- /dev/null +++ b/test/w3c/promela/test322.scxml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that _sessionid remains bound to the same value throught the session. this means that it can't +be assigned to --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0" name="machineName"> + <datamodel> + <data id="Var1" type="string" expr="_sessionid"/> + <data id="Var2" type="int"/> + </datamodel> + <state id="s0"> + <transition target="s1"/> + </state> + <state id="s1"> + <onentry> + <assign location="_sessionid" expr="'otherName'"/> + <raise event="foo"/> + </onentry> + <transition event="error.execution" target="s2"/> + <transition event="*" target="fail"/> + </state> + <state id="s2"> + <transition cond="Var1==_sessionid" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test323.scxml b/test/w3c/promela/test323.scxml new file mode 100644 index 0000000..28952fa --- /dev/null +++ b/test/w3c/promela/test323.scxml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that _name is bound on startup --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela" name="machineName"> + <datamodel> + <data id="Var1" type="string" expr="_name"/> + </datamodel> + <state id="s0"> + <transition cond="Var1" target="pass"/> + <transition cond="true" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test324.scxml b/test/w3c/promela/test324.scxml new file mode 100644 index 0000000..12beb71 --- /dev/null +++ b/test/w3c/promela/test324.scxml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that _name stays bound till the session ends. This means that it cannot be assigned to --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela" name="machineName"> + <state id="s0"> + <transition cond="_name == 'machineName'" target="s1"/> + <transition target="fail"/> + </state> + <state id="s1"> + <onentry> + <assign location="_name" expr="'otherName'"/> + </onentry> + <transition cond="_name == 'machineName'" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test325.scxml b/test/w3c/promela/test325.scxml new file mode 100644 index 0000000..38c892f --- /dev/null +++ b/test/w3c/promela/test325.scxml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that _ioprocessors is bound at startup. I'm not sure how to test for a set value or +how to test that the entries in it do represent I/O processors, since the set that each implementation +supports may be different. Suggestions welcome --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0" name="machineName"> + <datamodel> + <data id="Var1" type="string" expr="_ioprocessors"/> + </datamodel> + <state id="s0"> + <transition cond="Var1" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test326.scxml b/test/w3c/promela/test326.scxml new file mode 100644 index 0000000..c649b8d --- /dev/null +++ b/test/w3c/promela/test326.scxml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that _ioprocessors stays bound till the session ends. This means that it cannot be assigned to --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0" name="machineName"> + <datamodel> + <data id="Var1" type="string" expr="_ioprocessors"/> + <data id="Var2" type="int"/> + </datamodel> + <state id="s0"> + <transition cond="Var1" target="s1"/> + <transition cond="true" target="fail"/> + </state> + <state id="s1"> + <onentry> + <assign location="_ioprocessors" expr="'otherName'"/> + <raise event="foo"/> + </onentry> + <transition event="error.execution" target="s2"/> + <transition event="*" target="fail"/> + </state> + <state id="s2"> + <onentry> + <assign location="Var2" expr="_ioprocessors"/> + </onentry> + <transition cond="Var1==Var2" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test329.scxml b/test/w3c/promela/test329.scxml new file mode 100644 index 0000000..6f6dd64 --- /dev/null +++ b/test/w3c/promela/test329.scxml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that none of the system variables can be modified --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela" name="machineName"> + <datamodel> + <data id="Var1" type="int"/> + <data id="Var2" type="int"/> + <data id="Var3" type="int"/> + <data id="Var4" type="int"/> + </datamodel> + <state id="s0"> + <onentry> + <!-- get _event bound so we can use it in s1--> + <raise event="foo"/> + <assign location="Var1" expr="_sessionid"/> + <assign location="_sessionid" expr="27"/> + </onentry> + <transition event="foo" cond="Var1==_sessionid" target="s1"/> + <transition event="*" target="fail"/> + </state> + <state id="s1"> + <onentry> + <assign location="Var2" expr="_event"/> + <assign location="_event" expr="27"/> + </onentry> + <transition cond="Var2==_event" target="s2"/> + <transition target="fail"/> + </state> + <state id="s2"> + <onentry> + <assign location="Var3" expr="_name"/> + <assign location="_name" expr="27"/> + </onentry> + <transition cond="Var3==_name" target="s3"/> + <transition target="fail"/> + </state> + <state id="s3"> + <onentry> + <assign location="Var4" expr="_ioprocessors"/> + <assign location="_ioprocessors" expr="27"/> + </onentry> + <transition cond="Var4==_ioprocessors" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test330.scxml b/test/w3c/promela/test330.scxml new file mode 100644 index 0000000..13a5fbc --- /dev/null +++ b/test/w3c/promela/test330.scxml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- check that the required fields are present in both internal and external events --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" initial="s0" datamodel="promela" name="machineName"> + <state id="s0"> + <onentry> + <raise event="foo"/> + </onentry> + <transition event="foo" cond="_event.name && _event.type" target="s1"/> + <transition event="*" target="fail"/> + </state> + <state id="s1"> + <onentry> + <send event="foo"/> + </onentry> + <transition event="foo" cond="_event.name && _event.type" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test331.scxml b/test/w3c/promela/test331.scxml new file mode 100644 index 0000000..cd85652 --- /dev/null +++ b/test/w3c/promela/test331.scxml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="promela" initial="s0" name="machineName"> + <!-- test that _event.type is set correctly for internal, platform, and external events --> + <datamodel> + <data id="Var1" type="string"/> + </datamodel> + <state id="s0"> + <onentry> + <!-- internal event --> + <raise event="foo"/> + </onentry> + <transition event="foo" target="s1"> + <assign location="Var1" expr="_event.type"/> + </transition> + <transition event="*" target="fail"/> + </state> + <state id="s1"> + <transition cond="Var1=='internal'" target="s2"/> + <transition target="fail"/> + </state> + <state id="s2"> + <onentry> + <!-- this will generate an error, which is a platform event --> + <assign location="foo.bar.baz " expr="1"/> + </onentry> + <transition event="error" target="s3"> + <assign location="Var1" expr="_event.type"/> + </transition> + <transition event="*" target="fail"/> + </state> + <state id="s3"> + <transition cond="Var1=='platform'" target="s4"/> + <transition target="fail"/> + </state> + <state id="s4"> + <onentry> + <!-- external event --> + <send event="foo"/> + </onentry> + <transition event="foo" target="s5"> + <assign location="Var1" expr="_event.type"/> + </transition> + <transition event="*" target="fail"/> + </state> + <state id="s5"> + <transition cond="Var1=='external'" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test332.scxml b/test/w3c/promela/test332.scxml new file mode 100644 index 0000000..74ffa55 --- /dev/null +++ b/test/w3c/promela/test332.scxml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that sendid is present in error events triggered by send errors --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" initial="s0" datamodel="promela" name="machineName"> + <datamodel> + <data id="Var1" type="int"/> + <data id="Var2" type="int"/> + </datamodel> + <state id="s0"> + <onentry> + <!-- this will raise an error and also store the sendid in var1 --> + <send target="baz" event="foo" idlocation="Var1"/> + </onentry> + <transition event="error" target="s1"> + <!-- get the sendid out of the error event --> + <assign location="Var2" expr="_event.sendid"/> + </transition> + <transition event="*" target="fail"/> + </state> + <state id="s1"> + <!-- make sure that the sendid in the error event matches the one generated when send executed --> + <transition cond="Var1==Var2" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test333.scxml b/test/w3c/promela/test333.scxml new file mode 100644 index 0000000..f26c53c --- /dev/null +++ b/test/w3c/promela/test333.scxml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- make sure sendid is blank in a non-error event --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" initial="s0" datamodel="promela" name="machineName"> + <state id="s0"> + <onentry> + <send event="foo"/> + </onentry> + <transition event="foo" cond="!(_event.sendid)" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test335.scxml b/test/w3c/promela/test335.scxml new file mode 100644 index 0000000..8d0a1ad --- /dev/null +++ b/test/w3c/promela/test335.scxml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that origin field is blank for internal events --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" initial="s0" datamodel="promela" name="machineName"> + <state id="s0"> + <onentry> + <raise event="foo"/> + </onentry> + <transition event="foo" cond="!(_event.origin)" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test336.scxml b/test/w3c/promela/test336.scxml new file mode 100644 index 0000000..6b502ae --- /dev/null +++ b/test/w3c/promela/test336.scxml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that the origin field of an external event contains a URL that lets you send back to the originator. In +this case it's the same session, so if we get bar we succeed --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0" name="machineName"> + <state id="s0"> + <onentry> + <send event="foo"/> + </onentry> + <transition event="foo" target="s1"> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" event="bar" targetexpr="_event.origin" typeexpr="_event.origintype"/> + </transition> + <transition event="*" target="fail"/> + </state> + <state id="s1"> + <onentry> + <send event="baz"/> + </onentry> + <transition event="bar" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test337.scxml b/test/w3c/promela/test337.scxml new file mode 100644 index 0000000..64500af --- /dev/null +++ b/test/w3c/promela/test337.scxml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that origintype is blank on internal events --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0" name="machineName"> + <state id="s0"> + <onentry> + <raise event="foo"/> + </onentry> + <transition event="foo" cond="!(_event.origintype)" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test338.scxml b/test/w3c/promela/test338.scxml new file mode 100644 index 0000000..46c702c --- /dev/null +++ b/test/w3c/promela/test338.scxml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that invokeid is set correctly in events received from an invoked process. timeout event catches the +case where the invoke doesn't work correctly --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int"/> + <data id="Var2" type="int"/> + </datamodel> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="2000" event="timeout"/> + </onentry> + <invoke idlocation="Var1" type="http://www.w3.org/TR/scxml/"> + <content> + <scxml initial="sub0" version="1.0" datamodel="promela" name="machineName"> + <final id="sub0"> + <onentry> + <send target="#_parent" event="event1"/> + </onentry> + </final> + </scxml> + </content> + </invoke> + <transition event="event1" target="s1"> + <assign location="Var2" expr="_event.invokeid"/> + </transition> + <transition event="event0" target="fail"/> + </state> + <state id="s1"> + <transition cond="Var1==Var2" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test339.scxml b/test/w3c/promela/test339.scxml new file mode 100644 index 0000000..b91fc5f --- /dev/null +++ b/test/w3c/promela/test339.scxml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that invokeid is blank in an event that wasn't returned from an invoked process --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela" name="machineName"> + <state id="s0"> + <onentry> + <raise event="foo"/> + </onentry> + <transition event="foo" cond="!(_event.invokeid)" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test342.scxml b/test/w3c/promela/test342.scxml new file mode 100644 index 0000000..ab953e5 --- /dev/null +++ b/test/w3c/promela/test342.scxml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that eventexpr works and sets the name field of the resulting event --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela" name="machineName"> + <datamodel> + <data id="Var1" type="string" expr="'foo'"/> + <data id="Var2" type="int"/> + </datamodel> + <state id="s0"> + <onentry> + <send eventexpr="Var1"/> + </onentry> + <transition event="foo" target="s1"> + <assign location="Var2" expr="_event.name"/> + </transition> + <transition event="*" target="fail"/> + </state> + <state id="s1"> + <transition cond="Var1==Var2" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test343.scxml b/test/w3c/promela/test343.scxml new file mode 100644 index 0000000..38dac5c --- /dev/null +++ b/test/w3c/promela/test343.scxml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that illegal <param> produces error.execution and empty event.data --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="promela" initial="s0"> + <state id="s0" initial="s01"> + <!-- we should get the error before the done event --> + <transition event="error.execution" target="s1"/> + <transition event="done.state.s0" target="fail"/> + <transition event="done.state.s0" target="fail"> + </transition> + <state id="s01"> + <transition target="s02"/> + </state> + <final id="s02"> + <donedata> + <param location="foo.bar.baz " name="someParam"/> + </donedata> + </final> + </state> + <!-- if we get here, we received the error event. Now check that the done + event has empty event.data --> + <state id="s1"> + <transition event="done.state.s0" cond="!(_event.data)" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test344.scxml b/test/w3c/promela/test344.scxml new file mode 100644 index 0000000..eb3c292 --- /dev/null +++ b/test/w3c/promela/test344.scxml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that a cond expression that cannot be evaluated as a +boolean cond expression evaluates to false and causes error.execution to be raised. +In some languages, any valid expression/object can be converted to a boolean, so conf:nonBoolean will +have to be mapped onto something that produces a syntax error or something similarly invalid --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="promela" initial="s0"> + <state id="s0"> + <transition cond="return" target="fail"/> + <transition target="s1"/> + </state> + <state id="s1"> + <onentry> + <raise event="foo"/> + </onentry> + <transition event="error.execution" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test346.scxml b/test/w3c/promela/test346.scxml new file mode 100644 index 0000000..5d8dc30 --- /dev/null +++ b/test/w3c/promela/test346.scxml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that any attempt to change the value of a system variable causes error.execution to be raised. +Event1..4 are there to catch the case where the error event is not raised. In cases where it is, we have +to dispose of eventn in the next state, hence the targetless transitions (which simply throw away the event.) --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela" name="machineName"> + <state id="s0"> + <onentry> + <assign location="_sessionid" expr="'otherName'"/> + <raise event="event1"/> + </onentry> + <transition event="error.execution" target="s1"/> + <transition event="*" target="fail"/> + </state> + <state id="s1"> + <onentry> + <assign location="_event" expr="'otherName'"/> + <raise event="event2"/> + </onentry> + <!-- throw out event1 if it's still around --> + <transition event="event1"/> + <transition event="error.execution" target="s2"/> + <!-- event1 would trigger this transition if we didn't drop it. We want this transition to have + a very general trigger to catch cases where the wrong error event was raised --> + <transition event="*" target="fail"/> + </state> + <state id="s2"> + <onentry> + <assign location="_ioprocessors" expr="'otherName'"/> + <raise event="event3"/> + </onentry> + <transition event="event2"/> + <transition event="error.execution" target="s3"/> + <transition event="*" target="fail"/> + </state> + <state id="s3"> + <onentry> + <assign location="_name" expr="'otherName'"/> + <raise event="event4"/> + </onentry> + <transition event="event3"/> + <transition event="error.execution" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test347.scxml b/test/w3c/promela/test347.scxml new file mode 100644 index 0000000..a08590e --- /dev/null +++ b/test/w3c/promela/test347.scxml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that the scxml event I/O processor works by sending events back and forth between an invoked child +and its parent process --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <state id="s0" initial="s01"> + <invoke id="child" type="scxml"> + <content> + <scxml initial="sub0" version="1.0" datamodel="promela" name="machineName"> + <state id="sub0"> + <onentry> + <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" target="#_parent" event="childToParent"/> + </onentry> + <transition event="parentToChild" target="subFinal"/> + </state> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="20000" event="timeout"/> + </onentry> + <transition event="timeout" target="fail"/> + <state id="s01"> + <transition event="childToParent" target="s02"/> + </state> + <state id="s02"> + <onentry> + <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" target="#_child" event="parentToChild"/> + </onentry> + <transition event="done.invoke" target="pass"/> + <transition event="error" target="fail"/> + </state> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test348.scxml b/test/w3c/promela/test348.scxml new file mode 100644 index 0000000..57d43d9 --- /dev/null +++ b/test/w3c/promela/test348.scxml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <!-- test that event param of send sets the name of the event --> + <state id="s0"> + <onentry> + <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="s0Event"/> + </onentry> + <transition event="s0Event" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test349.scxml b/test/w3c/promela/test349.scxml new file mode 100644 index 0000000..57ac1cd --- /dev/null +++ b/test/w3c/promela/test349.scxml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that value in origin field can be used to send an event back to the sender --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int"/> + </datamodel> + <state id="s0"> + <onentry> + <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="s0Event"/> + </onentry> + <transition event="s0Event" target="s2"> + <assign location="Var1" expr="_event.origin"/> + </transition> + <transition event="*" target="fail"/> + </state> + <state id="s2"> + <onentry> + <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" targetexpr="Var1" event="s0Event2"/> + </onentry> + <transition event="s0Event2" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test350.scxml b/test/w3c/promela/test350.scxml new file mode 100644 index 0000000..d356f22 --- /dev/null +++ b/test/w3c/promela/test350.scxml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that target value is used to decide what session to deliver the event to. A session should be +able to send an event to itself using its own session ID as the target --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <datamodel> + <data id="Var1" type="string" expr="'#_scxml_'"/> + <data id="Var2" type="string" expr="_sessionid"/> + </datamodel> + <state id="s0"> + <onentry> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + Var2"/> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="5000" event="timeout"/> + <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" targetexpr="Var1" event="s0Event"/> + </onentry> + <transition event="s0Event" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test351.scxml b/test/w3c/promela/test351.scxml new file mode 100644 index 0000000..5e2a5b0 --- /dev/null +++ b/test/w3c/promela/test351.scxml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that sendid is set in event if present in send, blank otherwise --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <datamodel> + <data id="Var1" type="int"/> + <data id="Var2" type="int"/> + </datamodel> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="5000" event="timeout"/> + <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" id="send1" event="s0Event"/> + </onentry> + <transition event="s0Event" target="s1"> + <assign location="Var1" expr="_event.sendid"/> + </transition> + <transition event="*" target="fail"> + </transition> + </state> + <state id="s1"> + <transition cond="Var1=='send1'" target="s2"/> + <transition target="fail"/> + </state> + <state id="s2"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="5000" event="timeout"/> + <send event="s0Event2"/> + </onentry> + <transition event="s0Event2" target="s3"> + <assign location="Var2" expr="_event.sendid"/> + </transition> + <transition event="*" target="fail"/> + </state> + <state id="s3"> + <transition cond="!Var2" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test352.scxml b/test/w3c/promela/test352.scxml new file mode 100644 index 0000000..a113c6a --- /dev/null +++ b/test/w3c/promela/test352.scxml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test the origintype is 'http://www.w3.org/TR/scxml/#SCXMLEventProcessor' --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int"/> + </datamodel> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="5000" event="timeout"/> + <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="s0Event"/> + </onentry> + <transition event="s0Event" target="s1"> + <assign location="Var1" expr="_event.origintype"/> + </transition> + <transition event="*" target="fail"> + </transition> + </state> + <state id="s1"> + <transition cond="Var1=='http://www.w3.org/TR/scxml/#SCXMLEventProcessor'" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test354.scxml b/test/w3c/promela/test354.scxml new file mode 100644 index 0000000..5a5d234 --- /dev/null +++ b/test/w3c/promela/test354.scxml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that event.data can be populated using both namelist, param and <content> +and that correct values are used --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="1"/> + <data id="Var2" type="int"/> + <data id="Var3" type="int"/> + </datamodel> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="5000" event="timeout"/> + <send event="event1" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" namelist="Var1"> + <param name="param1" expr="2"/> + </send> + </onentry> + <transition event="event1" target="s1"> + <assign location="Var2" expr="_event.data.Var1"/> + <assign location="Var3" expr="_event.data.param1"/> + </transition> + <transition event="*" target="fail"> + </transition> + </state> + <state id="s1"> + <transition cond="Var2==1" target="s2"/> + <transition target="fail"/> + </state> + <state id="s2"> + <transition cond="Var3==2" target="s3"/> + <transition target="fail"/> + </state> + <state id="s3"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="5000" event="timeout"/> + <send event="event2"> + <content>123</content> + </send> + </onentry> + <transition event="event2" cond="_event.data == 123" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test355.scxml b/test/w3c/promela/test355.scxml new file mode 100644 index 0000000..91c6ecf --- /dev/null +++ b/test/w3c/promela/test355.scxml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that default initial state is first in document order. If we enter s0 first we succeed, if s1, failure. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" datamodel="promela" version="1.0"> + <state id="s0"> + <transition target="pass"/> + </state> + <state id="s1"> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test364.scxml b/test/w3c/promela/test364.scxml new file mode 100644 index 0000000..585754d --- /dev/null +++ b/test/w3c/promela/test364.scxml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that default initial states are entered when a compound state is entered. First we test +the 'initial' attribute, then the initial element, then default to the first child in document order. +If we get to s01111 we succeed, if any other state, failure. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" datamodel="promela" initial="s1" version="1.0"> + <state id="s1" initial="s11p112 s11p122"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + </onentry> + <transition event="timeout" target="fail"/> + <state id="s11" initial="s111"> + <state id="s111"/> + <parallel id="s11p1"> + <state id="s11p11" initial="s11p111"> + <state id="s11p111"/> + <state id="s11p112"> + <onentry> + <raise event="In-s11p112"/> + </onentry> + </state> + </state> + <state id="s11p12" initial="s11p121"> + <state id="s11p121"/> + <state id="s11p122"> + <transition event="In-s11p112" target="s2"/> + </state> + </state> + </parallel> + </state> + </state> + <state id="s2"> + <initial> + <transition target="s21p112 s21p122"/> + </initial> + <transition event="timeout" target="fail"/> + <state id="s21" initial="s211"> + <state id="s211"/> + <parallel id="s21p1"> + <state id="s21p11" initial="s21p111"> + <state id="s21p111"/> + <state id="s21p112"> + <onentry> + <raise event="In-s21p112"/> + </onentry> + </state> + </state> + <state id="s21p12" initial="s21p121"> + <state id="s21p121"/> + <state id="s21p122"> + <transition event="In-s21p112" target="s3"/> + </state> + </state> + </parallel> + </state> + </state> + <state id="s3"> + <transition target="fail"/> + <state id="s31"> + <state id="s311"> + <state id="s3111"> + <transition target="pass"/> + </state> + <state id="s3112"/> + <state id="s312"/> + <state id="s32"/> + </state> + </state> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test372.scxml b/test/w3c/promela/test372.scxml new file mode 100644 index 0000000..481f348 --- /dev/null +++ b/test/w3c/promela/test372.scxml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that entering a final state generates done.state.parentid after executing the onentry elements. +Var1 should be set to 2 (but not 3) by the time the event is raised --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" datamodel="promela" version="1.0"> + <datamodel> + <data id="Var1" type="int" expr="1"/> + </datamodel> + <state id="s0" initial="s0final"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + </onentry> + <transition event="done.state.s0" cond="Var1==2" target="pass"/> + <transition event="*" target="fail"/> + <final id="s0final"> + <onentry> + <assign location="Var1" expr="2"/> + </onentry> + <onexit> + <assign location="Var1" expr="3"/> + </onexit> + </final> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test375.scxml b/test/w3c/promela/test375.scxml new file mode 100644 index 0000000..a78a9d1 --- /dev/null +++ b/test/w3c/promela/test375.scxml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that onentry handlers are executed in document order. event1 should be raised before event2 --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" datamodel="promela" version="1.0"> + <state id="s0"> + <onentry> + <raise event="event1"/> + </onentry> + <onentry> + <raise event="event2"/> + </onentry> + <transition event="event1" target="s1"/> + <transition event="*" target="fail"/> + </state> + <state id="s1"> + <transition event="event2" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test376.scxml b/test/w3c/promela/test376.scxml new file mode 100644 index 0000000..d3d81bc --- /dev/null +++ b/test/w3c/promela/test376.scxml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that each onentry handler is a separate block. The <send> of event1 will cause an error but + the increment to var1 should happen anyways --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" datamodel="promela" version="1.0"> + <datamodel> + <data id="Var1" type="int" expr="1"/> + </datamodel> + <state id="s0"> + <onentry> + <send target="baz" event="event1"/> + </onentry> + <onentry> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </onentry> + <transition cond="Var1==2" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test377.scxml b/test/w3c/promela/test377.scxml new file mode 100644 index 0000000..d105bbe --- /dev/null +++ b/test/w3c/promela/test377.scxml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that onexit handlers are executed in document order. event1 should be raised before event2 --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" datamodel="promela" version="1.0"> + <state id="s0"> + <onexit> + <raise event="event1"/> + </onexit> + <onexit> + <raise event="event2"/> + </onexit> + <transition target="s1"/> + </state> + <state id="s1"> + <transition event="event1" target="s2"/> + <transition event="*" target="fail"/> + </state> + <state id="s2"> + <transition event="event2" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test378.scxml b/test/w3c/promela/test378.scxml new file mode 100644 index 0000000..e1c74c0 --- /dev/null +++ b/test/w3c/promela/test378.scxml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that each onexithandler is a separate block. The <send> of event1 will cause an error but + the increment to var1 should happen anyways --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="1"/> + </datamodel> + <state id="s0"> + <onexit> + <send target="baz" event="event1"/> + </onexit> + <onexit> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </onexit> + <transition target="s1"/> + </state> + <state id="s1"> + <transition cond="Var1==2" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test387.scxml b/test/w3c/promela/test387.scxml new file mode 100644 index 0000000..9983f48 --- /dev/null +++ b/test/w3c/promela/test387.scxml @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that the default history state works correctly. From initial state s3 we take a transition to s0's default +shallow history state. That should generate "enteringS011", which takes us to s4. In s4, we +transition to s1's default deep history state. We should end up in s122, generating "enteringS122". Otherwise failure.--> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s3" version="1.0" datamodel="promela"> + <state id="s0" initial="s01"> + <transition event="enteringS011" target="s4"/> + <transition event="*" target="fail"/> + <history type="shallow" id="s0HistShallow"> + <transition target="s01"/> + </history> + <history type="deep" id="s0HistDeep"> + <transition target="s022"/> + </history> + <state id="s01" initial="s011"> + <state id="s011"> + <onentry> + <raise event="enteringS011"/> + </onentry> + </state> + <state id="s012"> + <onentry> + <raise event="enteringS012"/> + </onentry> + </state> + </state> + <state id="s02" initial="s021"> + <state id="s021"> + <onentry> + <raise event="enteringS021"/> + </onentry> + </state> + <state id="s022"> + <onentry> + <raise event="enteringS022"/> + </onentry> + </state> + </state> + </state> + <state id="s1" initial="s11"> + <transition event="enteringS122" target="pass"/> + <transition event="*" target="fail"/> + <history type="shallow" id="s1HistShallow"> + <transition target="s11"/> + </history> + <history type="deep" id="s1HistDeep"> + <transition target="s122"/> + </history> + <state id="s11" initial="s111"> + <state id="s111"> + <onentry> + <raise event="enteringS111"/> + </onentry> + </state> + <state id="s112"> + <onentry> + <raise event="enteringS112"/> + </onentry> + </state> + </state> + <state id="s12" initial="s121"> + <state id="s121"> + <onentry> + <raise event="enteringS121"/> + </onentry> + </state> + <state id="s122"> + <onentry> + <raise event="enteringS122"/> + </onentry> + </state> + </state> + </state> + <state id="s3"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + </onentry> + <transition target="s0HistShallow"/> + </state> + <state id="s4"> + <transition target="s1HistDeep"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test388.scxml b/test/w3c/promela/test388.scxml new file mode 100644 index 0000000..1f9971b --- /dev/null +++ b/test/w3c/promela/test388.scxml @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that history states works correctly. The counter Var1 counts how many times +we have entered s0. The initial state is s012. We then transition to s1, which transitions +to s0's deep history state. entering.s012 should be raised, otherwise failure. Then we transition +to s02, which transitions to s0's shallow history state. That should have value s01, and its initial +state is s011, so we should get entering.s011, otherwise failure.--> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" initial="s012" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="s0" initial="s01"> + <onentry> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </onentry> + <!-- the first time through, go to s1, setting a timer just in case something hangs --> + <transition event="entering.s012" cond="Var1==1" target="s1"> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="2000" event="timeout"/> + </transition> + <!-- the second time, we should get entering.s012. If so, go to s2, otherwise fail --> + <transition event="entering.s012" cond="Var1==2" target="s2"/> + <transition event="entering" cond="Var1==2" target="fail"/> + <!-- the third time we should get entering-s011. If so, pass, otherwise fail --> + <transition event="entering.s011" cond="Var1==3" target="pass"/> + <transition event="entering" cond="Var1==3" target="fail"/> + <!-- if we timeout, the state machine is hung somewhere, so fail --> + <transition event="timeout" target="fail"/> + <history type="shallow" id="s0HistShallow"> + <transition target="s02"/> + </history> + <history type="deep" id="s0HistDeep"> + <transition target="s022"/> + </history> + <state id="s01" initial="s011"> + <state id="s011"> + <onentry> + <raise event="entering.s011"/> + </onentry> + </state> + <state id="s012"> + <onentry> + <raise event="entering.s012"/> + </onentry> + </state> + </state> + <state id="s02" initial="s021"> + <state id="s021"> + <onentry> + <raise event="entering.s021"/> + </onentry> + </state> + <state id="s022"> + <onentry> + <raise event="entering.s022"/> + </onentry> + </state> + </state> + </state> + <state id="s1"> + <transition target="s0HistDeep"/> + </state> + <state id="s2"> + <transition target="s0HistShallow"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test396.scxml b/test/w3c/promela/test396.scxml new file mode 100644 index 0000000..745b7cf --- /dev/null +++ b/test/w3c/promela/test396.scxml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that the value in _event.name matches the event name used to match against transitions --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" datamodel="promela" version="1.0"> + <state id="s0"> + <onentry> + <raise event="foo"/> + </onentry> + <transition event="foo" cond="_event.name == 'foo'" target="pass"/> + <transition event="foo" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test399.scxml b/test/w3c/promela/test399.scxml new file mode 100644 index 0000000..574d303 --- /dev/null +++ b/test/w3c/promela/test399.scxml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that the event name matching works correctly, including prefix matching and the fact +that the event attribute of transition may contain multiple event designators. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0" initial="s01"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="2000" event="timeout"/> + </onentry> + <!-- this will catch the failure case --> + <transition event="timeout" target="fail"/> + <state id="s01"> + <onentry> + <raise event="foo"/> + </onentry> + <!-- test that an event can match against a transition with multiple descriptors --> + <transition event="foo bar" target="s02"/> + </state> + <state id="s02"> + <onentry> + <raise event="bar"/> + </onentry> + <!-- test that an event can match the second descriptor as well --> + <transition event="foo bar" target="s03"/> + </state> + <state id="s03"> + <onentry> + <raise event="foo.zoo"/> + </onentry> + <!-- test that a prefix descriptor matches --> + <transition event="foo bar" target="s04"/> + </state> + <state id="s04"> + <onentry> + <raise event="foos"/> + </onentry> + <!-- test that only token prefixes match --> + <transition event="foo" target="fail"/> + <transition event="foos" target="s05"/> + </state> + <state id="s05"> + <onentry> + <raise event="foo.zoo"/> + </onentry> + <!-- test that .* works at the end of a descriptor --> + <transition event="foo.*" target="s06"/> + </state> + <state id="s06"> + <onentry> + <raise event="foo"/> + </onentry> + <!-- test that "*" works by itself --> + <transition event="*" target="pass"/> + </state> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test401.scxml b/test/w3c/promela/test401.scxml new file mode 100644 index 0000000..96f3765 --- /dev/null +++ b/test/w3c/promela/test401.scxml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that errors go in the internal event queue. We send ourselves an external event foo, then perform +and operation that raises an error. Then check that the error event is processed first, even though +it was raised second --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send event="foo"/> + <!-- assigning to a non-existent location should raise an error --> + <assign location="foo.bar.baz " expr="2"/> + </onentry> + <transition event="foo" target="fail"/> + <transition event="error" target="pass"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test402.scxml b/test/w3c/promela/test402.scxml new file mode 100644 index 0000000..5de6f9f --- /dev/null +++ b/test/w3c/promela/test402.scxml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- the assertion that errors are 'like any other event' is pretty broad, but we can check that they +are pulled off the internal queue in order, and that prefix matching works on them. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0" initial="s01"> + <onentry> + <!-- catch the failure case --> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + </onentry> + <transition event="timeout" target="fail"/> + <state id="s01"> + <onentry> + <!-- the first internal event. The error will be the second, and event2 will be the third --> + <raise event="event1"/> + <!-- assigning to a non-existent location should raise an error --> + <assign location="foo.bar.baz " expr="2"/> + </onentry> + <transition event="event1" target="s02"> + <raise event="event2"/> + </transition> + <transition event="*" target="fail"/> + </state> + <state id="s02"> + <transition event="error" target="s03"/> + <transition event="*" target="fail"/> + </state> + <state id="s03"> + <transition event="event2" target="pass"/> + <transition event="*" target="fail"/> + </state> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test403a.scxml b/test/w3c/promela/test403a.scxml new file mode 100644 index 0000000..7042e7b --- /dev/null +++ b/test/w3c/promela/test403a.scxml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test one part of 'optimal enablement' meaning that of all transitions that are enabled, we chose the ones +in child states over parent states, and use document order to break ties. We have +a parent state s0 with two children, s01 and s02. In s01, we test that a) if +a transition in the child matches, we don't consider matches in the parent and b) +that if two transitions match in any state, we take the first in document order. +In s02 we test that we take a transition in the parent if there is no +matching transition in the child. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0" initial="s01"> + <onentry> + <!-- catch the failure case --> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + </onentry> + <transition event="timeout" target="fail"/> + <transition event="event1" target="fail"/> + <transition event="event2" target="pass"/> + <state id="s01"> + <onentry> + <!-- this should be caught by the first transition in this state, taking us to S02 --> + <raise event="event1"/> + </onentry> + <transition event="event1" target="s02"/> + <transition event="*" target="fail"/> + </state> + <state id="s02"> + <onentry> + <!-- since the local transition has a cond that evaluates to false this should be caught by a + transition in the parent state, taking us to pass --> + <raise event="event2"/> + </onentry> + <transition event="event1" target="fail"/> + <transition event="event2" cond="false" target="fail"/> + </state> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test403b.scxml b/test/w3c/promela/test403b.scxml new file mode 100644 index 0000000..5c28ee2 --- /dev/null +++ b/test/w3c/promela/test403b.scxml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that 'optimally enabled set' really is a set, specifically that if a transition is optimally enabled in +two different states, it is taken only once. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="s0" initial="p0"> + <!-- this transition should never be taken because a transition in a lower state should + always be selected --> + <transition event="event1"> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </transition> + <parallel id="p0"> + <onentry> + <raise event="event1"/> + <raise event="event2"/> + </onentry> + <!-- this transition will be selected by both states p0s1 and p0s2, but should be executed only once --> + <transition event="event1"> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </transition> + <state id="p0s1"> + <transition event="event2" cond="Var1==1" target="pass"/> + <transition event="event2" target="fail"/> + </state> + <state id="p0s2"/> + </parallel> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test403c.scxml b/test/w3c/promela/test403c.scxml new file mode 100644 index 0000000..909d675 --- /dev/null +++ b/test/w3c/promela/test403c.scxml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test 'optimally enabled set', specifically that preemption works correctly --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="s0" initial="p0"> + <onentry> + <raise event="event1"/> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + </onentry> + <transition event="event2" target="fail"/> + <transition event="timeout" target="fail"/> + <parallel id="p0"> + <state id="p0s1"> + <transition event="event1"/> + <transition event="event2"/> + </state> + <state id="p0s2"> + <transition event="event1" target="p0s1"> + <raise event="event2"/> + </transition> + </state> + <state id="p0s3"> + <!-- this transition should be blocked by the one in p0s2--> + <transition event="event1" target="fail"/> + <!-- this transition will preempt the one that p0s2 inherits + from an ancestor --> + <transition event="event2" target="s1"/> + </state> + <state id="p0s4"> + <!-- this transition never gets preempted, should fire twice --> + <transition event="*"> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </transition> + </state> + </parallel> + </state> + <state id="s1"> + <transition cond="Var1==2" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test404.scxml b/test/w3c/promela/test404.scxml new file mode 100644 index 0000000..ce61f1e --- /dev/null +++ b/test/w3c/promela/test404.scxml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that states are exited in exit order (children before parents with reverse doc order used to break ties + before the executable content in the transitions. event1, event2, event3, event4 should be raised in that + order when s01p is exited --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0" initial="s01p"> + <parallel id="s01p"> + <onexit> + <!-- this should be the 3rd event raised --> + <raise event="event3"/> + </onexit> + <transition target="s02"> + <!-- this should be the fourth event raised --> + <raise event="event4"/> + </transition> + <state id="s01p1"> + <onexit> + <!-- this should be the second event raised --> + <raise event="event2"/> + </onexit> + </state> + <state id="s01p2"> + <!-- this should be the first event raised --> + <onexit> + <raise event="event1"/> + </onexit> + </state> + </parallel> + <state id="s02"> + <transition event="event1" target="s03"/> + <transition event="*" target="fail"/> + </state> + <state id="s03"> + <transition event="event2" target="s04"/> + <transition event="*" target="fail"/> + </state> + <state id="s04"> + <transition event="event3" target="s05"/> + <transition event="*" target="fail"/> + </state> + <state id="s05"> + <transition event="event4" target="pass"/> + <transition event="*" target="fail"/> + </state> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test405.scxml b/test/w3c/promela/test405.scxml new file mode 100644 index 0000000..7b61986 --- /dev/null +++ b/test/w3c/promela/test405.scxml @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that the executable content in the transitions is executed in document order after +the states are exited. event1, event2, event3, event4 should be raised in that order when the +state machine is entered --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0" initial="s01p"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + </onentry> + <transition event="timeout" target="fail"/> + <parallel id="s01p"> + <transition event="event1" target="s02"/> + <state id="s01p1" initial="s01p11"> + <state id="s01p11"> + <onexit> + <!-- this should be the second event raised --> + <raise event="event2"/> + </onexit> + <transition target="s01p12"> + <!-- this should be the third event raised --> + <raise event="event3"/> + </transition> + </state> + <state id="s01p12"/> + </state> + <!-- end s01p1 --> + <state id="s01p2" initial="s01p21"> + <state id="s01p21"> + <onexit> + <!-- this should be the first event raised --> + <raise event="event1"/> + </onexit> + <transition target="s01p22"> + <!-- this should be the fourth event raised --> + <raise event="event4"/> + </transition> + </state> + <state id="s01p22"/> + </state> + <!-- end s01p2 --> + </parallel> + <state id="s02"> + <transition event="event2" target="s03"/> + <transition event="*" target="fail"/> + </state> + <state id="s03"> + <transition event="event3" target="s04"/> + <transition event="*" target="fail"/> + </state> + <state id="s04"> + <transition event="event4" target="pass"/> + <transition event="*" target="fail"/> + </state> + </state> + <!-- end s01 --> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test406.scxml b/test/w3c/promela/test406.scxml new file mode 100644 index 0000000..b6928b6 --- /dev/null +++ b/test/w3c/promela/test406.scxml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Test that states are entered in entry order (parents before children with document order used to break ties) +after the executable content in the transition is executed. event1, event2, event3, event4 should be raised in that +order when the transition in s01 is taken --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" initial="s0" datamodel="promela"> + <state id="s0" initial="s01"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + </onentry> + <transition event="timeout" target="fail"/> + <state id="s01"> + <transition target="s0p2"> + <!-- this should be the first event raised --> + <raise event="event1"/> + </transition> + </state> + <parallel id="s0p2"> + <transition event="event1" target="s03"/> + <state id="s01p21"> + <onentry> + <!-- third event --> + <raise event="event3"/> + </onentry> + </state> + <state id="s01p22"> + <onentry> + <!-- the fourth event --> + <raise event="event4"/> + </onentry> + </state> + <onentry> + <!-- this should be the second event raised --> + <raise event="event2"/> + </onentry> + </parallel> + <state id="s03"> + <transition event="event2" target="s04"/> + <transition event="*" target="fail"/> + </state> + <state id="s04"> + <transition event="event3" target="s05"/> + <transition event="*" target="fail"/> + </state> + <state id="s05"> + <transition event="event4" target="pass"/> + <transition event="*" target="fail"/> + </state> + </state> + <!-- end s0 --> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test407.scxml b/test/w3c/promela/test407.scxml new file mode 100644 index 0000000..9260c05 --- /dev/null +++ b/test/w3c/promela/test407.scxml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- a simple test that onexit handlers work. var1 should be incremented when we leave s0 --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="s0"> + <onexit> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </onexit> + <transition target="s1"/> + </state> + <state id="s1"> + <transition cond="Var1==1" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test409.scxml b/test/w3c/promela/test409.scxml new file mode 100644 index 0000000..c4a1421 --- /dev/null +++ b/test/w3c/promela/test409.scxml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that states are removed from the active states list as they are exited. When s01's onexit handler +fires, s011 should not be on the active state list, so in(S011) should be false, and event1 should not +be raised. Therefore the timeout should fire to indicate success --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0" initial="s01"> + <onentry> + <send event="timeout" delayexpr="1000"/> + </onentry> + <transition event="timeout" target="pass"/> + <transition event="event1" target="fail"/> + <state id="s01" initial="s011"> + <onexit> + <if cond="config[S011]"> + <raise event="event1"/> + </if> + </onexit> + <state id="s011"> + <transition target="s02"/> + </state> + </state> + <!-- end s01 --> + <state id="s02"/> + </state> + <!-- end s0 --> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test411.scxml b/test/w3c/promela/test411.scxml new file mode 100644 index 0000000..317b8c4 --- /dev/null +++ b/test/w3c/promela/test411.scxml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that states are added to the active states list as they are entered and before onentry handlers +are executed. When s0's onentry handler fires we should not be in s01. But when s01's onentry handler +fires, we should be in s01. Therefore event1 should not fire, but event2 should. Either event1 or +timeout also indicates failure --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0" initial="s01"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + <if cond="config[S01]"> + <raise event="event1"/> + </if> + </onentry> + <transition event="timeout" target="fail"/> + <transition event="event1" target="fail"/> + <transition event="event2" target="pass"/> + <state id="s01"> + <onentry> + <if cond="config[S01]"> + <raise event="event2"/> + </if> + </onentry> + </state> + </state> + <!-- end s0 --> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test412.scxml b/test/w3c/promela/test412.scxml new file mode 100644 index 0000000..564647b --- /dev/null +++ b/test/w3c/promela/test412.scxml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that executable content in the <initial> transition executes after the onentry handler on the state +and before the onentry handler of the child states. Event1, event2, and event3 should occur in that order. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0" initial="s01"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + </onentry> + <transition event="timeout" target="fail"/> + <transition event="event1" target="fail"/> + <transition event="event2" target="pass"/> + <state id="s01"> + <onentry> + <raise event="event1"/> + </onentry> + <initial> + <transition target="s011"> + <raise event="event2"/> + </transition> + </initial> + <state id="s011"> + <onentry> + <raise event="event3"/> + </onentry> + <transition target="s02"/> + </state> + </state> + <state id="s02"> + <transition event="event1" target="s03"/> + <transition event="*" target="fail"/> + </state> + <state id="s03"> + <transition event="event2" target="s04"/> + <transition event="*" target="fail"/> + </state> + <state id="s04"> + <transition event="event3" target="pass"/> + <transition event="*" target="fail"/> + </state> + </state> + <!-- end s0 --> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test413.scxml b/test/w3c/promela/test413.scxml new file mode 100644 index 0000000..f4c983d --- /dev/null +++ b/test/w3c/promela/test413.scxml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that the state machine is put into the configuration specified by the initial element, without regard +to any other defaults. we should start off in s2p111 and s2p122. the atomic +states we should not enter all have immediate transitions to failure in them --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s2p112 s2p122" version="1.0" datamodel="promela"> + <state id="s1"> + <transition target="fail"/> + </state> + <state id="s2" initial="s2p1"> + <parallel id="s2p1"> + <!-- this transition will be triggered only if we end up in an illegal configuration where we're in + either s2p112 or s2p122, but not both of them --> + <transition target="fail"/> + <state id="s2p11" initial="s2p111"> + <state id="s2p111"> + <transition target="fail"/> + </state> + <state id="s2p112"> + <transition cond="config[S2P122]" target="pass"/> + </state> + </state> + <!-- end s2p11 --> + <state id="s2p12" initial="s2p121"> + <state id="s2p121"> + <transition target="fail"/> + </state> + <state id="s2p122"> + <transition cond="config[S2P112]" target="pass"/> + </state> + </state> + </parallel> + </state> + <!-- end s2 --> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test415.scxml b/test/w3c/promela/test415.scxml new file mode 100644 index 0000000..64d0c18 --- /dev/null +++ b/test/w3c/promela/test415.scxml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Test that the state machine halts when it enters a top-level final state. Since + the initial state is a final state, this machine should halt immediately without + processing "event1" which is raised in the final state's on-entry handler. This + is a manual test since there is no platform-independent way to test that event1 + is not processed --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="final" version="1.0" datamodel="promela"> + <final id="final"> + <onentry> + <raise event="event1"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test416.scxml b/test/w3c/promela/test416.scxml new file mode 100644 index 0000000..ee747f4 --- /dev/null +++ b/test/w3c/promela/test416.scxml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that the done.state.id gets generated when we enter the final state of a compound state --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" initial="s1" datamodel="promela"> + <state id="s1" initial="s11"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + </onentry> + <transition event="timeout" target="fail"/> + <state id="s11" initial="s111"> + <transition event="done.state.s11" target="pass"/> + <state id="s111"> + <transition target="s11final"/> + </state> + <final id="s11final"/> + </state> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test417.scxml b/test/w3c/promela/test417.scxml new file mode 100644 index 0000000..ed38eea --- /dev/null +++ b/test/w3c/promela/test417.scxml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that we get the done.state.id event when all of a +parallel elements children enter final states. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" initial="s1" datamodel="promela"> + <state id="s1" initial="s1p1"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + </onentry> + <transition event="timeout" target="fail"/> + <parallel id="s1p1"> + <transition event="done.state.s1p1" target="pass"/> + <state id="s1p11" initial="s1p111"> + <state id="s1p111"> + <transition target="s1p11final"/> + </state> + <final id="s1p11final"/> + </state> + <state id="s1p12" initial="s1p121"> + <state id="s1p121"> + <transition target="s1p12final"/> + </state> + <final id="s1p12final"/> + </state> + </parallel> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test419.scxml b/test/w3c/promela/test419.scxml new file mode 100644 index 0000000..1a26d2f --- /dev/null +++ b/test/w3c/promela/test419.scxml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that eventless transitions take precedence over event-driven ones --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" initial="s1" datamodel="promela"> + <state id="s1"> + <onentry> + <raise event="internalEvent"/> + <send event="externalEvent"/> + </onentry> + <transition event="*" target="fail"/> + <transition target="pass"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test421.scxml b/test/w3c/promela/test421.scxml new file mode 100644 index 0000000..09483d2 --- /dev/null +++ b/test/w3c/promela/test421.scxml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that internal events take priority over external ones, and that the processor +keeps pulling off internal events until it finds one that triggers a transition --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" initial="s1" datamodel="promela"> + <state id="s1" initial="s11"> + <onentry> + <send event="externalEvent"/> + <raise event="internalEvent1"/> + <raise event="internalEvent2"/> + <raise event="internalEvent3"/> + <raise event="internalEvent4"/> + </onentry> + <transition event="externalEvent" target="fail"/> + <state id="s11"> + <transition event="internalEvent3" target="s12"/> + </state> + <state id="s12"> + <transition event="internalEvent4" target="pass"/> + </state> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test422.scxml b/test/w3c/promela/test422.scxml new file mode 100644 index 0000000..12cbf2f --- /dev/null +++ b/test/w3c/promela/test422.scxml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Test that at the end of a macrostep, the processor executes all invokes in states +that have been entered and not exited during the step. (The invokes are supposed to be executed +in document order, but we can test that since each invocation is separate and they may take +different amounts to time to start up.) In this case, there are three invoke statements, +in states s1, s11 and s12. Each invoked process returns an event named after its parent state. +The invokes in s1 and s12 should execute, but not the one +in s11. So we should receive invokeS1, invokeS12, but not invokeS12. Furthermore, when the timeout fires, var1 should equal 2.--> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" initial="s1" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <state id="s1" initial="s11"> + <onentry> + <send event="timeout" delayexpr="2000"/> + </onentry> + <transition event="invokeS1 invokeS12"> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </transition> + <transition event="invokeS11" target="fail"/> + <transition event="timeout" cond="Var1==2" target="pass"/> + <transition event="timeout" target="fail"/> + <invoke> + <content> + <!-- when invoked, send 'foo' to parent, then terminate. --> + <scxml initial="sub0" version="1.0" datamodel="promela"> + <state id="sub0"> + <onentry> + <send target="#_parent" event="invokeS1"/> + </onentry> + <transition target="subFinal0"/> + </state> + <final id="subFinal0"/> + </scxml> + </content> + </invoke> + <state id="s11"> + <invoke> + <content> + <!-- when invoked, send 'foo' to parent, then terminate. --> + <scxml initial="sub1" version="1.0" datamodel="promela"> + <state id="sub1"> + <onentry> + <send target="#_parent" event="invokeS11"/> + </onentry> + <transition target="subFinal1"/> + </state> + <final id="subFinal1"/> + </scxml> + </content> + </invoke> + <transition target="s12"/> + </state> + <state id="s12"> + <invoke> + <content> + <!-- when invoked, send 'foo' to parent, then terminate. --> + <scxml initial="sub2" version="1.0" datamodel="promela"> + <state id="sub2"> + <onentry> + <send target="#_parent" event="invokeS12"/> + </onentry> + <transition target="subFinal2"/> + </state> + <final id="subFinal2"/> + </scxml> + </content> + </invoke> + </state> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test423.scxml b/test/w3c/promela/test423.scxml new file mode 100644 index 0000000..5527d7f --- /dev/null +++ b/test/w3c/promela/test423.scxml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that we keep pulling external events off the queue till we find one that matches a transition. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send event="externalEvent1"/> + <send event="externalEvent2" delayexpr="1000"/> + <raise event="internalEvent"/> + </onentry> + <!-- in this state we should process only internalEvent --> + <transition event="internalEvent" target="s1"/> + <transition event="*" target="fail"/> + </state> + <state id="s1"> + <!-- in this state we ignore externalEvent1 and wait for externalEvent2 --> + <transition event="externalEvent2" target="pass"/> + <transition event="internalEvent" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test446.txt b/test/w3c/promela/test446.txt new file mode 100644 index 0000000..3a26a2e --- /dev/null +++ b/test/w3c/promela/test446.txt @@ -0,0 +1 @@ +[1,2,3]
\ No newline at end of file diff --git a/test/w3c/promela/test487.scxml b/test/w3c/promela/test487.scxml new file mode 100644 index 0000000..3b81768 --- /dev/null +++ b/test/w3c/promela/test487.scxml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test illegal assignment. error.execution should be raised. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <datamodel> + <data id="Var1" type="int"/> + </datamodel> + <state id="s0"> + <onentry> + <assign location="Var1" expr="return"/> + <raise event="event"/> + </onentry> + <transition event="error.execution" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test488.scxml b/test/w3c/promela/test488.scxml new file mode 100644 index 0000000..78154b4 --- /dev/null +++ b/test/w3c/promela/test488.scxml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that illegal expr in <param> produces error.execution and empty event.data --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="promela" initial="s0"> + <state id="s0" initial="s01"> + <!-- we should get the error before the done event --> + <transition event="error.execution" target="s1"/> + <transition event="done.state.s0" target="fail"/> + <transition event="done.state.s0" target="fail"> + </transition> + <state id="s01"> + <transition target="s02"/> + </state> + <final id="s02"> + <donedata> + <param expr="return" name="someParam"/> + </donedata> + </final> + </state> + <!-- if we get here, we received the error event. Now check that the done + event has empty event.data --> + <state id="s1"> + <transition event="done.state.s0" cond="!(_event.data)" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test495.scxml b/test/w3c/promela/test495.scxml new file mode 100644 index 0000000..2c07a91 --- /dev/null +++ b/test/w3c/promela/test495.scxml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that the scxml event i/o processor puts events in the correct queues.--> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <!-- default target is external queue --> + <send event="event1" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor"/> + <send event="event2" target="#_internal" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor"/> + </onentry> + <!-- we should get the internal event first --> + <transition event="event1" target="fail"/> + <transition event="event2" target="s1"/> + </state> + <state id="s1"> + <transition event="event1" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test496.scxml b/test/w3c/promela/test496.scxml new file mode 100644 index 0000000..c3babeb --- /dev/null +++ b/test/w3c/promela/test496.scxml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="event" target="#_scxml_foo"/> + <raise event="foo"/> + </onentry> + <transition event="error.communication" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test500.scxml b/test/w3c/promela/test500.scxml new file mode 100644 index 0000000..0b046d0 --- /dev/null +++ b/test/w3c/promela/test500.scxml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that location field is found inside entry for SCXML Event I/O processor --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="_ioprocessors.scxml.location"/> + </datamodel> + <state id="s0"> + <transition cond="Var1" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test501.scxml b/test/w3c/promela/test501.scxml new file mode 100644 index 0000000..ea7f1ad --- /dev/null +++ b/test/w3c/promela/test501.scxml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that the location entry for the SCXML Event I/O processor can be used as the target for an event --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="_ioprocessors.scxml.location"/> + </datamodel> + <state id="s0"> + <onentry> + <send targetexpr="Var1" event="foo"/> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="2000" event="timeout"/> + </onentry> + <transition event="foo" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test503.scxml b/test/w3c/promela/test503.scxml new file mode 100644 index 0000000..5914d69 --- /dev/null +++ b/test/w3c/promela/test503.scxml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that a targetless transition does not exit and reenter its source state --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s1" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + <!-- how often we have exited s2 --> + <data id="Var2" type="int" expr="0"/> + <!-- how often the targetless transition in s2 has been executed --> + </datamodel> + <state id="s1"> + <onentry> + <raise event="foo"/> + <raise event="bar"/> + </onentry> + <transition target="s2"/> + </state> + <state id="s2"> + <onexit> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </onexit> + <transition event="foo"> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var2" expr="Var2 + 1"/> + </transition> + <!-- make sure the transition on foo was actually taken --> + <transition event="bar" cond="Var2==1" target="s3"/> + <transition event="bar" target="fail"/> + </state> + <state id="s3"> + <!-- make sure that s2 was exited only once --> + <transition cond="Var1==1" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test504.scxml b/test/w3c/promela/test504.scxml new file mode 100644 index 0000000..0aa69b4 --- /dev/null +++ b/test/w3c/promela/test504.scxml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that an external transition exits all states up the the LCCA --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s1" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + <!-- how often we have exited p --> + <data id="Var2" type="int" expr="0"/> + <!-- how often we have exited ps1 --> + <data id="Var3" type="int" expr="0"/> + <!-- how often we have exited ps2 --> + <data id="Var4" type="int" expr="0"/> + <!-- how often the transition for foo has been taken --> + <data id="Var5" type="int" expr="0"/> + <!-- how often we have exited s2 --> + </datamodel> + <state id="s1"> + <onentry> + <raise event="foo"/> + <raise event="bar"/> + </onentry> + <transition target="p"/> + </state> + <state id="s2"> + <onexit> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var5" expr="Var5 + 1"/> + </onexit> + <parallel id="p"> + <onexit> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </onexit> + <transition event="foo" target="ps1"> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var4" expr="Var4 + 1"/> + </transition> + <!-- make sure the transition on foo was actually taken --> + <transition event="bar" cond="Var4==1" target="s3"/> + <transition event="bar" target="fail"/> + <state id="ps1"> + <onexit> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var2" expr="Var2 + 1"/> + </onexit> + </state> + <state id="ps2"> + <onexit> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var3" expr="Var3 + 1"/> + </onexit> + </state> + </parallel> + </state> + <state id="s3"> + <!-- make sure that p was exited twice --> + <transition cond="Var1==2" target="s4"/> + <transition target="fail"/> + </state> + <state id="s4"> + <!-- make sure that ps1 was exited twice --> + <transition cond="Var2==2" target="s5"/> + <transition target="fail"/> + </state> + <state id="s5"> + <!-- make sure that ps2 was exited twice --> + <transition cond="Var3==2" target="s6"/> + <transition target="fail"/> + </state> + <state id="s6"> + <!-- make sure that s1 was exited once --> + <transition cond="Var5==1" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test505.scxml b/test/w3c/promela/test505.scxml new file mode 100644 index 0000000..02e18b0 --- /dev/null +++ b/test/w3c/promela/test505.scxml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that an internal transition does not exit its source state --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s1" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + <!-- how often we have exited s1 --> + <data id="Var2" type="int" expr="0"/> + <!-- how often we have exited s11 --> + <data id="Var3" type="int" expr="0"/> + <!-- how often the transition for foo has been taken --> + </datamodel> + <state id="s1"> + <onentry> + <raise event="foo"/> + <raise event="bar"/> + </onentry> + <onexit> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </onexit> + <transition event="foo" type="internal" target="s11"> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var3" expr="Var3 + 1"/> + </transition> + <!-- make sure the transition on foo was actually taken --> + <transition event="bar" cond="Var3==1" target="s2"/> + <transition event="bar" target="fail"/> + <state id="s11"> + <onexit> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var2" expr="Var2 + 1"/> + </onexit> + </state> + </state> + <state id="s2"> + <!-- make sure that s1 was exited once --> + <transition cond="Var1==1" target="s3"/> + <transition target="fail"/> + </state> + <state id="s3"> + <!-- make sure that s11 was exited twice --> + <transition cond="Var2==2" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test506.scxml b/test/w3c/promela/test506.scxml new file mode 100644 index 0000000..83b05b9 --- /dev/null +++ b/test/w3c/promela/test506.scxml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that an internal transition whose targets are not proper descendants of its source state +behaves like an external transition --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s1" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + <!-- how often we have exited s2 --> + <data id="Var2" type="int" expr="0"/> + <!-- how often we have exited s21 --> + <data id="Var3" type="int" expr="0"/> + <!-- how often the transition for foo has been taken --> + </datamodel> + <state id="s1"> + <onentry> + <raise event="foo"/> + <raise event="bar"/> + </onentry> + <transition target="s2"/> + </state> + <state id="s2" initial="s21"> + <onexit> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </onexit> + <transition event="foo" type="internal" target="s2"> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var3" expr="Var3 + 1"/> + </transition> + <!-- make sure the transition on foo was actually taken --> + <transition event="bar" cond="Var3==1" target="s3"/> + <transition event="bar" target="fail"/> + <state id="s21"> + <onexit> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var2" expr="Var2 + 1"/> + </onexit> + </state> + </state> + <state id="s3"> + <!-- make sure that s2 was exited twice --> + <transition cond="Var1==2" target="s4"/> + <transition target="fail"/> + </state> + <state id="s4"> + <!-- make sure that s21 was exited twice --> + <transition cond="Var2==2" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test509.scxml b/test/w3c/promela/test509.scxml new file mode 100644 index 0000000..009a1bc --- /dev/null +++ b/test/w3c/promela/test509.scxml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that Basic HTTP Event I/O processor uses POST method and that it can receive messages +at the accessURI --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="30000" event="timeout"/> + <send event="test" targetexpr="_ioprocessors.basichttp.location" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"/> + </onentry> + <!-- if the event was send by http and we get it, we succeed --> + <transition event="test" cond="_event.raw.search('POST') !== -1" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test510.scxml b/test/w3c/promela/test510.scxml new file mode 100644 index 0000000..11901fa --- /dev/null +++ b/test/w3c/promela/test510.scxml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that Basic HTTP messages go into external queue. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="30000" event="timeout"/> + <send event="test" targetexpr="_ioprocessors.basichttp.location" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"/> + <!-- this creates an internal event --> + <raise event="internal"/> + </onentry> + <!-- we should get 'internal' first, then 'test' --> + <transition event="internal" target="s1"/> + <transition event="*" target="fail"/> + </state> + <state id="s1"> + <transition event="test" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test513.txt b/test/w3c/promela/test513.txt new file mode 100644 index 0000000..08e9b01 --- /dev/null +++ b/test/w3c/promela/test513.txt @@ -0,0 +1,16 @@ +This is a fully manual test. You send a well formed event to the 'location' URL + specified for your SCXML interpreter and check that you get a 200 response code back. + One way of doing this, using wget, is shown below (you can use any event name you + want, but you must use '_scxmleventname' to indicate the name of the event): + +$ wget \ +--post-data='key1=value1&key2=value2' \ +--header '_scxmleventname: test' \ +<!-- URL of your processor goes here --> + +--2014-06-25 17:54:49-- http://epikur.local:8090/925c760f-2093-4054-a24c-d972d75f0dcd/basichttp +Resolving epikur.local (epikur.local)... 10.211.55.2, 10.37.129.2, 10.0.1.54, ... +Connecting to epikur.local (epikur.local)|10.211.55.2|:8090... connected. +HTTP request sent, awaiting response... 200 OK +Length: 0 [text/html] +Saving to: ‘basichttp’
\ No newline at end of file diff --git a/test/w3c/promela/test518.scxml b/test/w3c/promela/test518.scxml new file mode 100644 index 0000000..0962b3c --- /dev/null +++ b/test/w3c/promela/test518.scxml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that that namelist values get encoded as POST parameters. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <datamodel> + <data id="Var1" type="int" expr="2"/> + </datamodel> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="30000" event="timeout"/> + <send event="test" targetexpr="_ioprocessors.basichttp.location" namelist="Var1" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"/> + </onentry> + <transition event="test" cond="_event.raw.search(/Var1=2/) !== -1" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test519.scxml b/test/w3c/promela/test519.scxml new file mode 100644 index 0000000..f4c5e39 --- /dev/null +++ b/test/w3c/promela/test519.scxml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that that <param> values get encoded as POST parameters. . --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="30000" event="timeout"/> + <send event="test" targetexpr="_ioprocessors.basichttp.location" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"> + <param name="param1" expr="1"/> + </send> + </onentry> + <!-- if other end sends us back this event, we succeed --> + <transition event="test" cond="_event.raw.search('param1=1') !== -1" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test520.scxml b/test/w3c/promela/test520.scxml new file mode 100644 index 0000000..fba68fe --- /dev/null +++ b/test/w3c/promela/test520.scxml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that that <content> gets sent as the body of the message. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="30000" event="timeout"/> + <send targetexpr="_ioprocessors.basichttp.location" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"> + <content>this is some content</content> + </send> + </onentry> + <!-- if other end sends us back this event, we succeed. Test for two common + ways of encoding --> + <transition event="HTTP.POST" cond="_event.raw.search(/this+is+some+content/) !== -1" target="pass"/> + <transition event="HTTP.POST" cond="_event.raw.search(/this%20is%20some%20content/) !== -1" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test521.scxml b/test/w3c/promela/test521.scxml new file mode 100644 index 0000000..f5e5859 --- /dev/null +++ b/test/w3c/promela/test521.scxml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that the processor raises error.communication if it cannot dispatch the event. +(To create an undispatchable event, we choose a non-existent session as target). If it raises +the error event, we succeed. Otherwise we eventually timeout and fail. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <state id="s0"> + <onentry> + <!-- should cause an error --> + <send target="#_scxml_foo" event="event2"/> + <!-- this will get added to the external event queue after the error has been raised --> + <send event="timeout"/> + </onentry> + <!-- once we've entered the state, we should check for internal events first --> + <transition event="error.communication" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test522.scxml b/test/w3c/promela/test522.scxml new file mode 100644 index 0000000..e98e1c9 --- /dev/null +++ b/test/w3c/promela/test522.scxml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that location field the entry for Basic HTTP Event I/O processor can be used +to send a message to the processor --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="30000" event="timeout"/> + <send event="test" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" targetexpr="_ioprocessors.basichttp.location"/> + </onentry> + <!-- the event we receive should be called 'test', but that's not actually + required for this test. Only that the send deliver some event to us. So if + we get something other than timeout or error, we call it success --> + <transition event="timeout" target="fail"/> + <transition event="error" target="fail"/> + <transition event="*" target="pass"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test525.scxml b/test/w3c/promela/test525.scxml new file mode 100644 index 0000000..e2ec38b --- /dev/null +++ b/test/w3c/promela/test525.scxml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that <foreach> does a shallow copy, so that modifying the array does not change +the iteration behavior. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" datamodel="promela" version="1.0"> + <datamodel> + <data id="Var1" type="int[3]"> + [1,2,3] + </data> + <data id="Var2" type="int" expr="0"/> + <!-- counts the number of iterations --> + </datamodel> + <state id="s0"> + <onentry> + <foreach item="Var3" array="Var1"> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="[].concat(Var1, [4])"/> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var2" expr="Var2 + 1"/> + </foreach> + </onentry> + <transition cond="Var2==3" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test527.scxml b/test/w3c/promela/test527.scxml new file mode 100644 index 0000000..337c027 --- /dev/null +++ b/test/w3c/promela/test527.scxml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- simple test that 'expr' works with <content> --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="promela" initial="s0"> + <state id="s0" initial="s01"> + <transition event="done.state.s0" cond="_event.data == 'foo'" target="pass"> + </transition> + <transition event="done.state.s0" target="fail"> + </transition> + <state id="s01"> + <transition target="s02"/> + </state> + <final id="s02"> + <donedata> + <content expr="'foo'"/> + </donedata> + </final> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test528.scxml b/test/w3c/promela/test528.scxml new file mode 100644 index 0000000..8b79479 --- /dev/null +++ b/test/w3c/promela/test528.scxml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that illegal 'expr' produces error.execution and empty event.data --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="promela" initial="s0"> + <state id="s0" initial="s01"> + <!-- we should get the error before the done event --> + <transition event="error.execution" target="s1"/> + <transition event="done.state.s0" target="fail"/> + <state id="s01"> + <transition target="s02"/> + </state> + <final id="s02"> + <donedata> + <content expr="return"/> + </donedata> + </final> + </state> + <!-- if we get here, we received the error event. Now check that the done + event has empty event.data --> + <state id="s1"> + <transition event="done.state.s0" cond="!(_event.data)" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test529.scxml b/test/w3c/promela/test529.scxml new file mode 100644 index 0000000..4d5347c --- /dev/null +++ b/test/w3c/promela/test529.scxml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- simple test that children workn with <content> --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" datamodel="promela" initial="s0"> + <state id="s0" initial="s01"> + <transition event="done.state.s0" cond="_event.data == 21" target="pass"> + </transition> + <transition event="done.state.s0" target="fail"> + </transition> + <state id="s01"> + <transition target="s02"/> + </state> + <final id="s02"> + <donedata> + <content>21</content> + </donedata> + </final> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test530.scxml b/test/w3c/promela/test530.scxml new file mode 100644 index 0000000..431802c --- /dev/null +++ b/test/w3c/promela/test530.scxml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that <content> child is evaluated when <invoke> is. Var1 is initialized +with an integer value, then set to an scxml script in the onentry to s0. If <content> +is evaluated at the right time, we should get invoke.done, otherwise an error --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="1"/> + </datamodel> + <state id="s0"> + <onentry> + <assign location="Var1"> + <scxml version="1.0"> + <final/> + </scxml> + </assign> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="2000" event="timeout"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <content expr="Var1"/> + </invoke> + <transition event="done.invoke" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test531.scxml b/test/w3c/promela/test531.scxml new file mode 100644 index 0000000..d2ea9a6 --- /dev/null +++ b/test/w3c/promela/test531.scxml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that that the value of the <param> _scxmleventname gets used as the name +of the raised event. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="3000" event="timeout"/> + <send targetexpr="_ioprocessors.basichttp.location" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"> + <param name="_scxmleventname" expr="'test'"/> + </send> + </onentry> + <!-- if we get an event named 'test' we succeed. Otherwise fail --> + <transition event="test" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test532.scxml b/test/w3c/promela/test532.scxml new file mode 100644 index 0000000..356342d --- /dev/null +++ b/test/w3c/promela/test532.scxml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that that if _scxmleventname is not present, the name of the HTTP method is used +as the name of the resulting event. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="3000" event="timeout"/> + <send targetexpr="_ioprocessors.basichttp.location" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"> + <!-- this content will be ignored, but it's here to make sure we have a message body --> + <content>some content</content> + </send> + </onentry> + <transition event="HTTP.POST" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test533.scxml b/test/w3c/promela/test533.scxml new file mode 100644 index 0000000..68d9406 --- /dev/null +++ b/test/w3c/promela/test533.scxml @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that an internal transition whose source state is not compound does exit its source state --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s1" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + <!-- how often we have exited p --> + <data id="Var2" type="int" expr="0"/> + <!-- how often we have exited ps1 --> + <data id="Var3" type="int" expr="0"/> + <!-- how often we have exited ps2 --> + <data id="Var4" type="int" expr="0"/> + <!-- how often the transition for foo has been taken --> + </datamodel> + <state id="s1"> + <onentry> + <raise event="foo"/> + <raise event="bar"/> + </onentry> + <transition target="p"/> + </state> + <parallel id="p"> + <onexit> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </onexit> + <transition event="foo" type="internal" target="ps1"> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var4" expr="Var4 + 1"/> + </transition> + <!-- make sure the transition on foo was actually taken --> + <transition event="bar" cond="Var4==1" target="s2"/> + <transition event="bar" target="fail"/> + <state id="ps1"> + <onexit> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var2" expr="Var2 + 1"/> + </onexit> + </state> + <state id="ps2"> + <onexit> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var3" expr="Var3 + 1"/> + </onexit> + </state> + </parallel> + <state id="s2"> + <!-- make sure that p was exited twice --> + <transition cond="Var1==2" target="s3"/> + <transition target="fail"/> + </state> + <state id="s3"> + <!-- make sure that ps1 was exited twice --> + <transition cond="Var2==2" target="s4"/> + <transition target="fail"/> + </state> + <state id="s4"> + <!-- make sure that ps2 was exited twice --> + <transition cond="Var3==2" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test534.scxml b/test/w3c/promela/test534.scxml new file mode 100644 index 0000000..ec9dfc0 --- /dev/null +++ b/test/w3c/promela/test534.scxml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that that <send> 'event' value gets sent as the param _scxmleventname . --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="30000" event="timeout"/> + <send event="test" targetexpr="_ioprocessors.basichttp.location" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"> + </send> + </onentry> + <!-- if other end sends us back this event, we succeed --> + <transition event="test" cond="_event.raw.search('_scxmleventname=test') !== -1" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test539.txt b/test/w3c/promela/test539.txt new file mode 100644 index 0000000..de1b0a1 --- /dev/null +++ b/test/w3c/promela/test539.txt @@ -0,0 +1,4 @@ + <books xmlns=""> + <book title="title1"/> + <book title="title2"/> + </books>
\ No newline at end of file diff --git a/test/w3c/promela/test540.txt b/test/w3c/promela/test540.txt new file mode 100644 index 0000000..2191239 --- /dev/null +++ b/test/w3c/promela/test540.txt @@ -0,0 +1,3 @@ +123 +4 5 +
\ No newline at end of file diff --git a/test/w3c/promela/test550.scxml b/test/w3c/promela/test550.scxml new file mode 100644 index 0000000..fc00d05 --- /dev/null +++ b/test/w3c/promela/test550.scxml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that expr can be used to assign a value to a var. This test uses early binding --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela" binding="early"> + <state id="s0"> + <transition cond="Var1==2" target="pass"/> + <transition target="fail"/> + </state> + <state id="s1"> + <datamodel> + <data id="Var1" type="int" expr="2"/> + </datamodel> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test551.scxml b/test/w3c/promela/test551.scxml new file mode 100644 index 0000000..9ef6405 --- /dev/null +++ b/test/w3c/promela/test551.scxml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that inline content can be used to assign a value to a var. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" binding="early" datamodel="promela"> + <state id="s0"> + <transition cond="Var1[1]" target="pass"/> + <transition target="fail"/> + </state> + <state id="s1"> + <datamodel> + <data id="Var1" type="int[3]"> + [1,2,3] + </data> + </datamodel> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test552.scxml b/test/w3c/promela/test552.scxml new file mode 100644 index 0000000..320b42d --- /dev/null +++ b/test/w3c/promela/test552.scxml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that src content can be used to assign a value to a var. Edit +test552.txt to have a value that's legal for the datamodel in question --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" src="file:test552.txt"/> + </datamodel> + <state id="s0"> + <transition cond="Var1" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test552.txt b/test/w3c/promela/test552.txt new file mode 100644 index 0000000..d8263ee --- /dev/null +++ b/test/w3c/promela/test552.txt @@ -0,0 +1 @@ +2
\ No newline at end of file diff --git a/test/w3c/promela/test553.scxml b/test/w3c/promela/test553.scxml new file mode 100644 index 0000000..7f641d4 --- /dev/null +++ b/test/w3c/promela/test553.scxml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- we test that the processor does not dispatch the event if evaluation +of <send>'s args causes an error.. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <state id="s0"> + <onentry> + <!-- timeout event --> + <send event="timeout" delayexpr="1000"/> + <!-- generate an invalid namelist --> + <send event="event1" namelist=""foo"/> + </onentry> + <!-- if we get the timeout before event1, we assume that event1 hasn't been sent + We ignore the error event here because this assertion doesn't mention it --> + <transition event="timeout" target="pass"/> + <transition event="event1" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test554.scxml b/test/w3c/promela/test554.scxml new file mode 100644 index 0000000..5832090 --- /dev/null +++ b/test/w3c/promela/test554.scxml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that if the evaluation of <invoke>'s args causes an error, the +invocation is cancelled. In this test, that means that we don't get done.invoke +before the timer goes off. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="promela"> + <state id="s0"> + <onentry> + <send event="timer" delayexpr="1000"/> + </onentry> + <!-- reference an invalid namelist --> + <invoke type="http://www.w3.org/TR/scxml/" namelist=""foo"> + <content> + <scxml initial="subFinal" version="1.0" datamodel="promela"> + <final id="subFinal"/> + </scxml> + </content> + </invoke> + <transition event="timer" target="pass"/> + <transition event="done.invoke" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test557.txt b/test/w3c/promela/test557.txt new file mode 100644 index 0000000..a8e51da --- /dev/null +++ b/test/w3c/promela/test557.txt @@ -0,0 +1,4 @@ +<books xmlns=""> + <book title="title1"/> + <book title="title2"/> + </books>
\ No newline at end of file diff --git a/test/w3c/promela/test558.txt b/test/w3c/promela/test558.txt new file mode 100644 index 0000000..bb2bcc7 --- /dev/null +++ b/test/w3c/promela/test558.txt @@ -0,0 +1,3 @@ + +this is +a string
\ No newline at end of file diff --git a/test/w3c/promela/test567.scxml b/test/w3c/promela/test567.scxml new file mode 100644 index 0000000..5d99e88 --- /dev/null +++ b/test/w3c/promela/test567.scxml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that that any content in the message other than _scxmleventname is used to populate +_event.data. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <datamodel> + <data id="Var1" type="int" expr="2"/> + </datamodel> + <state id="s0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="3000" event="timeout"/> + <!-- in this case, 'test' will be placed in _scxmleventname. The <param> should + be used to populate _event.data --> + <send event="test" targetexpr="_ioprocessors.basichttp.location" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"> + <param name="param1" expr="2"/> + </send> + </onentry> + <!-- if we get this event, we succeed --> + <transition event="test" target="s1"> + <assign location="Var1" expr="_event.data.param1"/> + </transition> + <transition event="*" target="fail"/> + </state> + <state id="s1"> + <transition cond="Var1==2" target="pass"/> + <transition target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test570.scxml b/test/w3c/promela/test570.scxml new file mode 100644 index 0000000..1a14640 --- /dev/null +++ b/test/w3c/promela/test570.scxml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that we generate done.state.id when all a parallel state's children are in final states --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="p0" datamodel="promela" version="1.0"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <parallel id="p0"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="2000" event="timeout"/> + <raise event="e1"/> + <raise event="e2"/> + </onentry> + <!-- record that we get the first done event --> + <transition event="done.state.p0s1"> + <assign location="Var1" expr="1"/> + </transition> + <!-- we should get the second done event before done.state.p0 --> + <transition event="done.state.p0s2" target="s1"/> + <transition event="timeout" target="fail"/> + <state id="p0s1" initial="p0s11"> + <state id="p0s11"> + <transition event="e1" target="p0s1final"/> + </state> + <final id="p0s1final"/> + </state> + <state id="p0s2" initial="p0s21"> + <state id="p0s21"> + <transition event="e2" target="p0s2final"/> + </state> + <final id="p0s2final"/> + </state> + </parallel> + <state id="s1"> + <!-- if we get done.state.p0, success --> + <transition event="done.state.p0" cond="Var1==1" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test576.scxml b/test/w3c/promela/test576.scxml new file mode 100644 index 0000000..eeff4be --- /dev/null +++ b/test/w3c/promela/test576.scxml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that the 'initial' value of scxml is respected. We set the value to deeply nested non-default parallel siblings and +test that both are entered. --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s11p112 s11p122" datamodel="promela" version="1.0"> + <state id="s0"> + <transition target="fail"/> + </state> + <state id="s1"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="1000" event="timeout"/> + </onentry> + <transition event="timeout" target="fail"/> + <state id="s11" initial="s111"> + <state id="s111"/> + <parallel id="s11p1"> + <state id="s11p11" initial="s11p111"> + <state id="s11p111"/> + <state id="s11p112"> + <onentry> + <raise event="In-s11p112"/> + </onentry> + </state> + </state> + <state id="s11p12" initial="s11p121"> + <state id="s11p121"/> + <state id="s11p122"> + <transition event="In-s11p112" target="pass"/> + </state> + </state> + </parallel> + </state> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test577.scxml b/test/w3c/promela/test577.scxml new file mode 100644 index 0000000..b5922ca --- /dev/null +++ b/test/w3c/promela/test577.scxml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that that <send> without target in basichttp event i/o processor +causes error.communication to get added to internal queue . --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" datamodel="promela" version="1.0"> + <state id="s0"> + <onentry> + <!-- sent by scxml event i/o processor, added to external queue --> + <send event="event1"/> + <!-- should put error.communication on internal queue --> + <send event="test" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"/> + </onentry> + <transition event="error.communication" target="pass"/> + <transition event="*" target="fail"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test579.scxml b/test/w3c/promela/test579.scxml new file mode 100644 index 0000000..8ed8ac1 --- /dev/null +++ b/test/w3c/promela/test579.scxml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that default history content is executed correctly. The Process MUST execute any executable content in the transition after the parent state's onentry handlers, and, in the case where the history pseudo-state is the target of an <initial> transition, +the executable content inside the <initial> transition. However the Processor MUST +execute this content only if there is no stored history. Once the history state's +parent state has been visited and exited, the default history content must not be executed --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" initial="s0" datamodel="promela"> + <state id="s0"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <initial> + <transition target="sh1"> + <raise event="event2"/> + </transition> + </initial> + <onentry> + <send delayexpr="1000" event="timeout"/> + <raise event="event1"/> + </onentry> + <onexit> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </onexit> + <history id="sh1"> + <transition target="s01"> + <raise event="event3"/> + </transition> + </history> + <state id="s01"> + <transition event="event1" target="s02"/> + <transition event="*" target="fail"/> + </state> + <state id="s02"> + <transition event="event2" target="s03"/> + <transition event="*" target="fail"/> + </state> + <state id="s03"> + <transition cond="Var1==0" event="event3" target="s0"/> + <transition cond="Var1==1" event="event1" target="s2"/> + <transition event="*" target="fail"/> + </state> + </state> + <state id="s2"> + <transition event="event2" target="s3"/> + <transition event="*" target="fail"/> + </state> + <state id="s3"> + <transition event="event3" target="fail"/> + <transition event="timeout" target="pass"/> + </state> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> diff --git a/test/w3c/promela/test580.scxml b/test/w3c/promela/test580.scxml new file mode 100644 index 0000000..f614a12 --- /dev/null +++ b/test/w3c/promela/test580.scxml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- test that a history state never ends up part of the configuration --> +<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" version="1.0" initial="p1" datamodel="promela"> + <datamodel> + <data id="Var1" type="int" expr="0"/> + </datamodel> + <parallel id="p1"> + <onentry> + <send xmlns:scxml="http://www.w3.org/2005/07/scxml" delay="2000" event="timeout"/> + </onentry> + <state id="s0"> + <transition cond="config[SH1]" target="fail"/> + <transition event="timeout" target="fail"/> + </state> + <state id="s1"> + <initial> + <transition target="sh1"/> + </initial> + <history id="sh1"> + <transition target="s11"/> + </history> + <state id="s11"> + <transition cond="config[SH1]" target="fail"/> + <transition target="s12"/> + </state> + <state id="s12"/> + <transition cond="config[SH1]" target="fail"/> + <transition cond="Var1==0" target="sh1"/> + <transition cond="Var1==1" target="pass"/> + <onexit> + <assign xmlns:scxml="http://www.w3.org/2005/07/scxml" location="Var1" expr="Var1 + 1"/> + </onexit> + </state> + </parallel> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="pass"> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </final> + <final xmlns:scxml="http://www.w3.org/2005/07/scxml" id="fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> +</scxml> |