summaryrefslogtreecommitdiff
path: root/digital/ai/src
diff options
context:
space:
mode:
authorJerome Jutteau2013-02-27 21:54:29 +0100
committerJerome Jutteau2013-02-27 22:16:07 +0100
commit0fe95079677149ca0791aa5edd7dc99c7276748b (patch)
tree0f1a0bcd9a557d5d5e006777fb33ce451196473c /digital/ai/src
parentce8581af2514e8d60c0ce14f4a2c39944b6ab988 (diff)
digital/ai/src/fsm: update angfsm
Diffstat (limited to 'digital/ai/src')
-rw-r--r--digital/ai/src/fsm/Makefile.fsm8
-rw-r--r--digital/ai/src/fsm/angfsm.h62
-rw-r--r--digital/ai/src/fsm/angfsm.host.c2456
-rw-r--r--digital/ai/src/fsm/angfsm_generic.h89
-rw-r--r--digital/ai/src/fsm/angfsm_host_exec.h525
-rw-r--r--digital/ai/src/fsm/angfsm_renaming.h45
-rw-r--r--digital/ai/src/fsm/fsm.h566
-rw-r--r--digital/ai/src/fsm/fsm.host.c1607
-rw-r--r--digital/ai/src/fsm/init.c4
9 files changed, 3183 insertions, 2179 deletions
diff --git a/digital/ai/src/fsm/Makefile.fsm b/digital/ai/src/fsm/Makefile.fsm
index 5fcb896b..97363bbd 100644
--- a/digital/ai/src/fsm/Makefile.fsm
+++ b/digital/ai/src/fsm/Makefile.fsm
@@ -1,8 +1,8 @@
-fsm_AI_gen.avr.c: fsm_AI_gen.h
+fsm_AI_gen.avr.c: angfsm_gen_avr_AI.h
dot_AI_1.dot: fsm_AI_gen.h
-fsm_AI_gen.h: io_hub.host
- ./$< --gen
- mv fsm_AI_gen.c fsm_AI_gen.avr.c
+angfsm_gen_avr_AI.h: io_hub.host
+ ./$< --ang-gen avr
+ mv angfsm_gen_avr_AI.c fsm_AI_gen.avr.c
view: dot_AI_1.view
png: dot_AI_1.png
diff --git a/digital/ai/src/fsm/angfsm.h b/digital/ai/src/fsm/angfsm.h
new file mode 100644
index 00000000..2934ec4e
--- /dev/null
+++ b/digital/ai/src/fsm/angfsm.h
@@ -0,0 +1,62 @@
+/*
+ AngFSM - Almost Non Generated Finite State Machine
+ Copyright 2011, 2012 Jerome Jutteau
+
+ This file is part of AngFSM.
+
+ AngFSM is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ AngFSM 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 Lesser General Public License
+ along with AngFSM. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <inttypes.h>
+
+#ifndef _ANGFSM_GEN_
+#define _ANGFSM_GEN_
+
+#ifndef ANGFSM_NAME
+#define ANGFSM_NAME ANGFSM
+#endif
+
+/* Usefull macros. */
+#define XSTR(s) STR(s)
+#define STR(s) #s
+#define ANGFSM_PASTE(a, b) a ## b
+#define ANGFSM_PASTE_EXPAND(a, b) ANGFSM_PASTE (a, b)
+#define ANGFSM_PASTE3_EXPAND(a, b, c)\
+ANGFSM_PASTE_EXPAND (a, ANGFSM_PASTE_EXPAND (b, c))
+#define FIRST(first, others...) first
+
+#ifdef __HOST_ARCH__
+/* Include generated header. */
+#include XSTR (ANGFSM_PASTE_EXPAND (angfsm_gen_host_, ANGFSM_NAME).h)
+#include "angfsm_generic.h"
+
+#elif defined(__AVR_ARCH__)
+/* Include generated header. */
+#include XSTR (ANGFSM_PASTE_EXPAND (angfsm_gen_avr_, ANGFSM_NAME).h)
+#include "angfsm_generic.h"
+
+#elif defined(__arm__)
+/* Include generated header. */
+#include XSTR (ANGFSM_PASTE_EXPAND (angfsm_gen_arm_, ANGFSM_NAME).h)
+#include "angfsm_generic.h"
+
+#else
+/* Compiling for HOST but for direct execution. */
+#include "angfsm_host_exec.h"
+
+#endif
+
+#include "angfsm_renaming.h"
+
+#endif /* #ifdef _ANGFSM_GEN_ */
diff --git a/digital/ai/src/fsm/angfsm.host.c b/digital/ai/src/fsm/angfsm.host.c
new file mode 100644
index 00000000..fe8f403e
--- /dev/null
+++ b/digital/ai/src/fsm/angfsm.host.c
@@ -0,0 +1,2456 @@
+/*
+ AngFSM - Almost Non Generated Finite State Machine
+ Copyright 2011, 2012 Jerome Jutteau
+
+ This file is part of AngFSM.
+
+ AngFSM is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ AngFSM 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 Lesser General Public License
+ along with AngFSM. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HOST
+
+#include "angfsm.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+const char *angfsm_build_arch_name[ANGFSM_BUILD_ARCH_NB] = {
+ "host",
+ "avr",
+ "arm"
+};
+
+void
+angfsm_build_print_help ()
+{
+ printf (
+ "AngFSM Copyright (C) 2011, 2012 Jérôme Jutteau\n"
+ "This program comes with ABSOLUTELY NO WARRANTY;\n"
+ "This is free software, and you are welcome to redistribute it\n"
+ "under certain conditions; consult license for details.\n"
+ "\n"
+ "options:\n"
+ "--ang-help : show this help.\n"
+ "--ang-fsm [FSM_NAME]\n"
+ " Select a specific fsm by it's name, the next parameters will use\n"
+ " this parameter until another is set. You don't have to specifie\n"
+ " a fsm name with this option if there is only one fsm.\n"
+ "--ang-dot [FILENAME]\n"
+ " Generate the dot representation of the current fsm in the\n"
+ " specified filename.\n"
+ "--ang-gen [ARCH]\n"
+ " Generate a optimized code of all fsm for the specified\n"
+ " architecture. You will have to recompile your fsm with the\n"
+ " generated files but you won't have to edit your fsm code.\n"
+ " Available architecture are: "
+ );
+ int i;
+ for (i = 0; i < ANGFSM_BUILD_ARCH_NB - 1; i++)
+ printf ("%s, ", angfsm_build_arch_name[i]);
+ printf ("%s.\n", angfsm_build_arch_name[ANGFSM_BUILD_ARCH_NB - 1]);
+ printf (
+ " Once the code generated, you will have to recompile your code\n"
+ " and the generated .c files with the architecture's specific\n"
+ " compiler. If you want to recompile the fsm for the \"host\" target\n"
+ " you have to provide the -D __HOST_ARCH__ option to your compiler.\n"
+ "--ang-embedded-strings\n"
+ " Add events and states strings in generated code for all fsm or\n"
+ " for a selected fsm. Put this option before --ang-gen.\n"
+ "--ang-no-sanity-check\n"
+ " Disable sanity check during execution on the selected fsm or on\n"
+ " all fsm. Sanity checks are not embedded in generated code."
+ "--ang-print-transitions\n"
+ " Print transition to stdout each time one occurs. Not available for\n"
+ " generated code."
+ );
+}
+
+void
+angfsm_build_arg_parse (char *string, char ***tab, int *nb)
+{
+ long i = 0;
+ long buff_cnt = 0;
+ char *buff;
+ int nb_cur = 0;
+ int param = 0;
+
+ assert (string && tab && nb);
+ if (strlen (string) == 0)
+ {
+ *nb = 0;
+ **tab = NULL;
+ return;
+ }
+ buff = strdup (string);
+
+ /* Count. */
+ *nb = 1;
+ for (i = 0; string[i] != '\0'; i++)
+ if (string[i] == ',')
+ (*nb)++;
+ *tab = (char **) malloc ((*nb) * sizeof (char *));
+
+ /* Fill. */
+ for (i = 0; i < (long) strlen (string) + 1; i++)
+ {
+ if (string[i] == ',' || string[i] == '\0')
+ {
+ param = 0;
+ buff[buff_cnt] = '\0';
+ (*tab)[nb_cur] = strdup (buff);
+ buff_cnt = 0;
+ nb_cur++;
+ }
+ else if (string[i] != '"' && string[i] != ' ')
+ {
+ if (param == 0)
+ param = 1;
+ if (param == 2)
+ printf ("Parse error in \"%s\"\n", string);
+ buff[buff_cnt++] = string[i];
+ }
+ else if (string[i] == ' ')
+ {
+ if (param == 1)
+ param = 2;
+ }
+ }
+ free (buff);
+}
+
+void
+angfsm_build_arg_free (char ***tab, int nb)
+{
+ assert (*tab);
+ int i;
+ for (i = 0; i < nb; i++)
+ {
+ assert ((*tab)[i]);
+ free ((*tab)[i]);
+ }
+ free (*tab);
+}
+
+void
+angfsm_build_print (angfsm_build_t *fsm,
+ angfsm_build_trans_t *trans,
+ angfsm_build_branch_chain_t *branch)
+{
+ if (branch->name == NULL)
+ fprintf (stderr, "Transition: %s -- %s --> %s\n",
+ trans->state->var_name,
+ trans->event->var_name,
+ branch->state->var_name);
+ else
+ fprintf (stderr, "Transition: %s -- %s --> %s (%s)\n",
+ trans->state->var_name,
+ trans->event->var_name,
+ branch->name,
+ branch->state->var_name);
+}
+
+void
+angfsm_build_sanity_check (angfsm_build_t *fsm)
+{
+ angfsm_build_event_chain_t *ec;
+ angfsm_build_event_chain_t *ec_tmp;
+ angfsm_build_state_chain_t *sc;
+ angfsm_build_state_chain_t *sc_tmp;
+ angfsm_build_trans_chain_t *tc;
+ angfsm_build_trans_chain_t *tc_tmp;
+ angfsm_build_branch_chain_t *bc;
+ uint b;
+
+ /* Sanity check 1: are all states has a different name ? */
+ sc = fsm->states;
+ while (sc != NULL)
+ {
+ sc_tmp = fsm->states;
+ while (sc_tmp != NULL)
+ {
+ if (sc != sc_tmp
+ && strcmp (sc->state.var_name, sc_tmp->state.var_name)
+ == 0)
+ assert (!"All states must have a different name.");
+ sc_tmp = sc_tmp->next;
+ }
+ sc = sc->next;
+ }
+
+ /* Sanity check 2: are all events has a different name ? */
+ ec = fsm->events;
+ while (ec != NULL)
+ {
+ ec_tmp = fsm->events;
+ while (ec_tmp != NULL)
+ {
+ if (ec != ec_tmp
+ && strcmp (ec->event.var_name, ec_tmp->event.var_name)
+ == 0)
+ assert (!"All events must have a different name.");
+ ec_tmp = ec_tmp->next;
+ }
+ ec = ec->next;
+ }
+
+ /* Sanity check 3: are all events used in a transition ? */
+ ec = fsm->events;
+ while (ec != NULL)
+ {
+ b = 0;
+ tc = fsm->trans;
+ while (tc != NULL)
+ {
+ if (&ec->event == tc->trans.event)
+ {
+ b = 1;
+ break;
+ }
+ tc = tc->next;
+ }
+ if (!b)
+ fprintf (stderr, "Warning, some events are not used in a transition (%s).\n",
+ ec->event.var_name);
+ ec = ec->next;
+ }
+
+ /* Sanity check 4: are all states used in a transition ? */
+ sc = fsm->states;
+ while (sc != NULL)
+ {
+ b = 0;
+ tc = fsm->trans;
+ while (tc != NULL)
+ {
+ if (&sc->state == tc->trans.state)
+ {
+ b = 1;
+ break;
+ }
+ /* This state may be a final state. */
+ bc = tc->trans.output_branches;
+ while (bc != NULL)
+ {
+ if (&sc->state == bc->state)
+ {
+ b = 1;
+ break;
+ }
+ bc = bc->next;
+ }
+
+ tc = tc->next;
+ }
+ if (!b)
+ fprintf (stderr, "Warning, some states are not used in a transition (%s).\n",
+ sc->state.var_name);
+ sc = sc->next;
+ }
+
+ /* Sanity check 5: are all states can be reached during execution ? */
+ angfsm_build_state_chain_t *stack = NULL;
+ angfsm_build_state_chain_t *tail = NULL;
+ uint i;
+ /* Initialise check array. */
+ uint *check_tab = (uint *) malloc (fsm->state_nb * sizeof (uint));
+ memset (check_tab, 0, fsm->state_nb * sizeof (uint));
+ /* Initialize by adding first active states the stack. */
+ sc = fsm->starters;
+ while (sc != NULL)
+ {
+ sc_tmp = (angfsm_build_state_chain_t *)
+ malloc (sizeof (angfsm_build_state_chain_t));
+ sc_tmp->state = sc->state;
+ if (stack == NULL)
+ stack = sc_tmp;
+ if (tail != NULL)
+ tail->next = sc_tmp;
+ sc_tmp->next = NULL;
+ tail = sc_tmp;
+ sc = sc->next;
+ }
+ /* Get next states from the stack and check them. */
+ while (stack != NULL)
+ {
+ /* Check state. */
+ check_tab[stack->state.code] = 1;
+ /* Add to the tail of the stack th next states if they are not checked
+ * yet. */
+ tc = fsm->trans;
+ while (tc != NULL)
+ {
+ if (tc->trans.state->code == stack->state.code)
+ {
+ bc = tc->trans.output_branches;
+ while (bc != NULL)
+ {
+ if (!check_tab[bc->state->code])
+ {
+ check_tab[bc->state->code] = 1;
+ /* Add at the end of the stack. */
+ sc_tmp = (angfsm_build_state_chain_t *)
+ malloc (sizeof (angfsm_build_state_chain_t));
+ sc_tmp->state = *bc->state;
+ sc_tmp->next = NULL;
+ tail->next = sc_tmp;
+ tail = sc_tmp;
+ }
+ bc = bc->next;
+ }
+ }
+ tc = tc->next;
+ }
+ sc_tmp = stack->next;
+ free (stack);
+ stack = sc_tmp;
+ }
+ /* Check if some states are not reached. */
+ for (i = 0; i < fsm->state_nb; i++)
+ if (!check_tab[i])
+ fprintf (stderr, "Warning, some states won't be reachable during execution (%s).\n",
+ angfsm_build_get_state_by_code (fsm, i)->var_name);
+ /* Free. */
+ free (check_tab);
+
+ /* Sanity check 6: Any transition how have the same state and same event ?
+ * Useless test ? Making the same state/event couple will cause a
+ * compilation error.
+ */
+ tc = fsm->trans;
+ while (tc != NULL)
+ {
+ tc_tmp = fsm->trans;
+ while (tc_tmp != NULL)
+ {
+ if (tc != tc_tmp
+ && tc->trans.state == tc_tmp->trans.state
+ && tc->trans.event == tc_tmp->trans.event)
+ assert (!"All transitions must have a different state/event\
+ couple.");
+ tc_tmp = tc_tmp->next;
+ }
+ tc = tc->next;
+ }
+
+ /* Sanity check 7: check that all first active states are unique. */
+ sc = fsm->starters;
+ while (sc != NULL)
+ {
+ uint b = 0;
+ sc_tmp = fsm->starters;
+ while (sc_tmp != NULL)
+ {
+ if (sc_tmp->state.code == sc->state.code)
+ b++;
+ if (b > 1)
+ assert (!"Your first active states must be unique.");
+ sc_tmp = sc_tmp->next;
+ }
+ sc = sc->next;
+ }
+
+ /* Sanity check 8: any transition output error ?
+ * for example, as we are in state s42, making a angfsm_NEXT (s1, e2) will
+ * work but this is a user's mistake.
+ *
+ * TODO Find a way to check this.
+ **/
+}
+
+void
+angfsm_build_reset (angfsm_build_t *fsm)
+{
+ uint i;
+ angfsm_build_state_chain_t *curs = fsm->starters;
+ for (i = 0; i < fsm->max_active_states; i++)
+ {
+ fsm->run.active_states[i] = NULL;
+ fsm->run.events_before_active_state[i] = NULL;
+ }
+ i = 0;
+ while (curs != NULL)
+ {
+ fsm->run.active_states[i++] = &curs->state;
+ curs = curs->next;
+ }
+}
+
+void
+angfsm_build_gen_dot (angfsm_build_t *fsm, char* output)
+{
+ uint j;
+ angfsm_build_trans_chain_t *tc;
+ angfsm_build_branch_chain_t *bc;
+ char *fn = NULL;
+ if (!output || strlen (output) == 0)
+ {
+ uint fns = strlen (fsm->name) + strlen ("angfsm_.dot") + 1;
+ char *fn = (char *) malloc (fns * sizeof (char));
+ snprintf (fn, fns, "angfsm_%s.dot", fsm->name);
+ }
+ else
+ fn = output;
+ assert (fn);
+ FILE *f = fopen (fn, "w");
+ if (!f)
+ {
+ fprintf (stderr, "Warning: could not open %s\n", fn);
+ return;
+ }
+
+ /* Gen graph. */
+ fprintf (f, "digraph %s {\n", fsm->name);
+ tc = fsm->trans;
+ while (tc != NULL)
+ {
+ bc = tc->trans.output_branches;
+ while (bc != NULL)
+ {
+ fprintf (f, "\t%s -> %s [label=\"%s",
+ tc->trans.state->var_name,
+ bc->state->var_name,
+ tc->trans.event->var_name);
+ if (bc->name != NULL)
+ fprintf (f, " (%s)", bc->name);
+ fprintf (f, "\"");
+ /* If the next state is an active state we look if this this event
+ * was handled before. */
+ for (j = 0; j < fsm->max_active_states; j++)
+ if (fsm->run.active_states[j]
+ && fsm->run.active_states[j]->code == bc->state->code)
+ if (fsm->run.events_before_active_state[j]
+ && fsm->run.events_before_active_state[j]->code
+ == tc->trans.event->code)
+ fprintf (f, ", color=red");
+
+ fprintf (f, "];\n");
+ bc = bc->next;
+ }
+ tc = tc->next;
+ }
+ /* Colorise active states. */
+ for (j = 0; j < fsm->max_active_states; j++)
+ if (fsm->run.active_states[j])
+ fprintf (f, "\t%s [color=blue, fontcolor=white, style=filled];\n",
+ fsm->run.active_states[j]->var_name);
+
+ fprintf (f, "}\n\n");
+
+ /* Close file. */
+ fclose (f);
+
+ /* Free. */
+ if (!output || strlen (output) == 0)
+ free (fn);
+}
+
+/* All fsm. */
+angfsm_build_chain_t *angfsm_build_all_fsm;
+
+void
+angfsm_build_init_all_fsm ()
+{
+ angfsm_build_all_fsm = NULL;
+}
+
+/* Just initialise structures. */
+void
+angfsm_build_init (angfsm_build_t *fsm, char *name)
+{
+ assert (fsm);
+ fsm->events = NULL;
+ fsm->states = NULL;
+ fsm->trans = NULL;
+ fsm->name = name;
+ fsm->max_active_states = 0;
+ fsm->event_nb = 0;
+ fsm->state_nb = 0;
+ fsm->starters = NULL;
+ fsm->timeouts = NULL;
+
+ fsm->run.trans_table = NULL;
+ fsm->run.active_states = NULL;
+ fsm->run.events_before_active_state = NULL;
+ fsm->run.func_pool = NULL;
+ fsm->run.timeout_counters = NULL;
+
+ /* Set default user's options. */
+ fsm->options.embedded_strings = 0;
+ fsm->options.sanity_check = 1;
+ fsm->options.gen_dot = NULL;
+ fsm->options.gen_code = NULL;
+ fsm->options.print_trans = 0;
+
+ /* Store fsm. */
+ angfsm_build_chain_t *niou = (angfsm_build_chain_t *)
+ malloc (sizeof (angfsm_build_chain_t));
+ niou->fsm = fsm;
+ niou->next = angfsm_build_all_fsm;
+ angfsm_build_all_fsm = niou;
+}
+
+/* Prepare the fsm to run (at very end). */
+void
+angfsm_build_run_init (angfsm_build_t *fsm)
+{
+ uint i, j;
+
+ /* Create empty transition table. */
+ fsm->run.trans_table = (angfsm_build_run_strans_func_t **)
+ malloc (fsm->event_nb * sizeof (angfsm_build_run_strans_func_t *));
+ for (i = 0; i < fsm->event_nb; i++)
+ {
+ fsm->run.trans_table[i] = (angfsm_build_run_strans_func_t *)
+ malloc (fsm->state_nb * sizeof (angfsm_build_run_strans_func_t));
+ for (j = 0; j < fsm->state_nb; j++)
+ fsm->run.trans_table[i][j] = NULL;
+ }
+
+ /* Fill with transitions. */
+ angfsm_trans_func_chain_t *fc = fsm->run.func_pool;
+ while (fc != NULL)
+ {
+ fsm->run.trans_table[fc->trans.event->code][fc->trans.state->code] =
+ fc->func;
+ fc = fc->next;
+ }
+
+ /* Free function pool. */
+ angfsm_trans_func_chain_t *old_fc;
+ fc = fsm->run.func_pool;
+ while (fc != NULL)
+ {
+ old_fc = fc;
+ fc = fc->next;
+ free (old_fc);
+ }
+ fsm->run.func_pool = NULL;
+
+ /* Initialize active states. */
+ fsm->run.active_states = (angfsm_build_state_t **) malloc
+ (fsm->max_active_states * sizeof (angfsm_build_state_t *));
+ for (i = 0; i < fsm->max_active_states; i++)
+ fsm->run.active_states[i] = NULL;
+ angfsm_build_state_chain_t *s = fsm->starters;
+ i = 0;
+ while (s != NULL)
+ {
+ fsm->run.active_states[i++] = &s->state;
+ s = s->next;
+ }
+
+ /* Initialize last events before active states. */
+ fsm->run.events_before_active_state = (angfsm_build_event_t **) malloc
+ (fsm->max_active_states * sizeof (angfsm_build_event_t *));
+ for (i = 0; i < fsm->max_active_states; i++)
+ fsm->run.events_before_active_state[i] = NULL;
+
+ /* Initialize timeout counters. */
+ fsm->run.timeout_counters = (int *)
+ malloc (fsm->max_active_states * sizeof (int));
+ for (i = 0; i < fsm->max_active_states; i++)
+ fsm->run.timeout_counters[i] = -1;
+ angfsm_build_timeout_chain_t *toc = fsm->timeouts;
+ for (i = 0; i < fsm->max_active_states; i++)
+ while (toc != NULL)
+ {
+ if (fsm->run.active_states[i]->code
+ == toc->timeout.trans->state->code)
+ fsm->run.timeout_counters[i] = toc->timeout.timeout;
+ toc = toc->next;
+ }
+}
+
+void
+angfsm_build_states (angfsm_build_t *fsm, char *states)
+{
+ angfsm_build_state_chain_t *head = fsm->states;
+ char **args;
+ int i, nb;
+
+ angfsm_build_arg_parse (states, &args, &nb);
+ for (i = 0; i < nb; i++)
+ {
+ angfsm_build_state_chain_t *s = (angfsm_build_state_chain_t *)
+ malloc (sizeof (angfsm_build_state_chain_t));
+ s->state.var_name = strdup (args[i]);
+ s->state.code = fsm->state_nb++;
+ s->next = head;
+ head = s;
+ }
+ angfsm_build_arg_free (&args, nb);
+ fsm->states = head;
+}
+
+void
+angfsm_build_events (angfsm_build_t *fsm, char *events)
+{
+ angfsm_build_event_chain_t *head = fsm->events;
+ char **args;
+ int i, nb;
+
+ if (strcmp (events, "_TIMEOUT_") == 0
+ && angfsm_build_get_event (fsm, events) != NULL)
+ return;
+ angfsm_build_arg_parse (events, &args, &nb);
+ for (i = 0; i < nb; i++)
+ {
+ angfsm_build_event_chain_t *e = (angfsm_build_event_chain_t *)
+ malloc (sizeof (angfsm_build_event_chain_t));
+ e->event.var_name = strdup (args[i]);
+ e->event.code = fsm->event_nb++;
+ e->next = head;
+ head = e;
+ }
+ angfsm_build_arg_free (&args, nb);
+ fsm->events = head;
+}
+
+angfsm_build_event_t *
+angfsm_build_get_event (angfsm_build_t *fsm, char *event)
+{
+ angfsm_build_event_chain_t *curs = fsm->events;
+ while (curs != NULL)
+ {
+ if (strcmp (curs->event.var_name, event) == 0)
+ return &(curs->event);
+ curs = curs->next;
+ }
+ return NULL;
+}
+
+angfsm_build_state_t *
+angfsm_build_get_state (angfsm_build_t *fsm, char *state)
+{
+ angfsm_build_state_chain_t *curs = fsm->states;
+ while (curs != NULL)
+ {
+ if (strcmp (curs->state.var_name, state) == 0)
+ return &(curs->state);
+ curs = curs->next;
+ }
+ return NULL;
+}
+
+angfsm_build_event_t*
+angfsm_build_get_event_by_code (angfsm_build_t *fsm, uint event)
+{
+ angfsm_build_event_chain_t *curs = fsm->events;
+ while (curs != NULL)
+ {
+ if (curs->event.code == event)
+ return &(curs->event);
+ curs = curs->next;
+ }
+ return NULL;
+}
+
+angfsm_build_state_t*
+angfsm_build_get_state_by_code (angfsm_build_t *fsm, uint state)
+{
+ angfsm_build_state_chain_t *curs = fsm->states;
+ while (curs != NULL)
+ {
+ if (curs->state.code == state)
+ return &(curs->state);
+ curs = curs->next;
+ }
+ return NULL;
+}
+
+uint16_t
+angfsm_build_get_event_code (angfsm_build_t *fsm, char *event)
+{
+ assert (fsm);
+ angfsm_build_event_t *e = angfsm_build_get_event (fsm, event);
+ assert (e);
+ return e->code;
+}
+
+void
+angfsm_build_trans (angfsm_build_t *fsm,
+ char *state,
+ char *event,
+ char *output_branches,
+ angfsm_build_run_strans_func_t trans_func)
+{
+ angfsm_build_trans_t t;
+ angfsm_build_branch_chain_t *b;
+ char **args;
+ int i, nb;
+
+ t.output_branches = NULL;
+ /* Check state and event exists. */
+ t.state = angfsm_build_get_state (fsm, state);
+ t.event = angfsm_build_get_event (fsm, event);
+ assert (t.state);
+ assert (t.event);
+
+ angfsm_build_arg_parse (output_branches, &args, &nb);
+ /* Only one output state. */
+ if (nb == 1)
+ {
+ t.output_branches = (angfsm_build_branch_chain_t *)
+ malloc (sizeof (angfsm_build_branch_chain_t));
+ t.output_branches->name = NULL;
+ t.output_branches->state = angfsm_build_get_state (fsm, args[0]);
+ assert (t.output_branches->state);
+ t.output_branches->next = NULL;
+ }
+ else
+ for (i = 0; i < nb; i = i + 2)
+ {
+ b = (angfsm_build_branch_chain_t *)
+ malloc (sizeof (angfsm_build_branch_chain_t));
+ b->name = strdup (args[i]);
+ b->state = angfsm_build_get_state (fsm, args[i + 1]);
+ assert (b->state);
+ b->next = t.output_branches;
+ t.output_branches = b;
+ }
+ angfsm_build_arg_free (&args, nb);
+
+ /* Add trans to fsm. */
+ angfsm_build_trans_chain_t *tc = (angfsm_build_trans_chain_t *)
+ malloc (sizeof (angfsm_build_trans_chain_t));
+ tc->trans = t;
+ tc->next = fsm->trans;
+ fsm->trans = tc;
+
+ /* Add trans function to run context. */
+ angfsm_trans_func_chain_t *fc = (angfsm_trans_func_chain_t *)
+ malloc (sizeof (angfsm_trans_func_chain_t));
+ fc->func = trans_func;
+ fc->trans = tc->trans;
+ fc->next = fsm->run.func_pool;
+ fsm->run.func_pool = fc;
+}
+
+void
+angfsm_build_timeout (angfsm_build_t *fsm, char *state, char *event, uint timeout)
+{
+ angfsm_build_trans_chain_t *tc = NULL;
+ angfsm_build_trans_t *t = NULL;
+ angfsm_build_state_t *s = NULL;
+ angfsm_build_event_t *e = NULL;
+ angfsm_build_timeout_chain_t *to = NULL;
+
+ assert (fsm);
+ assert (state);
+ assert (event);
+
+ /* Find the corresponding transition. */
+ tc = fsm->trans;
+ s = angfsm_build_get_state (fsm, state);
+ e = angfsm_build_get_event (fsm, event);
+ assert (tc);
+ assert (s);
+ assert (e);
+ while (tc != NULL)
+ {
+ if (tc->trans.state == s && tc->trans.event == e)
+ {
+ t = &tc->trans;
+ break;
+ }
+ tc = tc->next;
+ }
+ assert (t);
+
+ /* Fill a new timeout. */
+ to = (angfsm_build_timeout_chain_t *)
+ malloc (sizeof (angfsm_build_timeout_chain_t));
+ to->timeout.timeout = timeout;
+ to->timeout.trans = t;
+
+ /* Add timeout to chain. */
+ to->next = fsm->timeouts;
+ fsm->timeouts = to;
+}
+
+void
+angfsm_build_start_with (angfsm_build_t *fsm, char *starters)
+{
+ char **args;
+ int nb, i;
+ angfsm_build_arg_parse (starters, &args, &nb);
+ fsm->max_active_states += nb;
+ for (i = 0; i < nb; i++)
+ {
+ angfsm_build_state_chain_t *sc = (angfsm_build_state_chain_t *)
+ malloc (sizeof (angfsm_build_state_chain_t));
+ angfsm_build_state_t *s = angfsm_build_get_state (fsm, args[i]);
+ assert (s);
+ sc->state = *s;
+ sc->next = fsm->starters;
+ fsm->starters = sc;
+ }
+ angfsm_build_arg_free (&args, nb);
+}
+
+int
+angfsm_build_handle (angfsm_build_t *fsm, angfsm_build_event_t *e)
+{
+ angfsm_build_state_t *s = NULL;
+ angfsm_build_timeout_chain_t *toc = NULL;
+ assert (e);
+ uint i;
+ int handled = 0;
+ for (i = 0; i < fsm->max_active_states; i++)
+ {
+ s = fsm->run.active_states[i];
+ if (s && fsm->run.trans_table[e->code][s->code])
+ {
+ fsm->run.events_before_active_state[i] = e;
+ fsm->run.active_states[i] = fsm->run.trans_table[e->code][s->code]();
+ /* Check the new state has a timeout or not. */
+ toc = fsm->timeouts;
+ fsm->run.timeout_counters[i] = -1;
+ while (toc != NULL)
+ {
+ if (toc->timeout.trans->state->code
+ == fsm->run.active_states[i]->code)
+ {
+ fsm->run.timeout_counters[i] = toc->timeout.timeout;
+ break;
+ }
+ toc = toc->next;
+ }
+
+ handled = 1;
+ }
+ }
+ return handled;
+}
+
+int
+angfsm_build_handle_string (angfsm_build_t *fsm, char *event)
+{
+ angfsm_build_event_t *e = angfsm_build_get_event (fsm, event);
+ return angfsm_build_handle (fsm, e);
+}
+
+int
+angfsm_build_handle_integer (angfsm_build_t *fsm, uint16_t event)
+{
+ angfsm_build_event_t *e = angfsm_build_get_event_by_code (fsm, event);
+ return angfsm_build_handle (fsm, e);
+}
+
+int
+angfsm_build_can_handle (angfsm_build_t *fsm, angfsm_build_event_t *e)
+{
+ angfsm_build_state_t *s = NULL;
+ assert (e);
+ uint i;
+ for (i = 0; i < fsm->max_active_states; i++)
+ {
+ s = fsm->run.active_states[i];
+ if (s && fsm->run.trans_table[e->code][s->code])
+ return 1;
+ }
+ return 0;
+}
+
+int
+angfsm_build_can_handle_string (angfsm_build_t *fsm, char *event)
+{
+ angfsm_build_event_t *e = angfsm_build_get_event (fsm, event);
+ return angfsm_build_can_handle (fsm, e);
+}
+
+int
+angfsm_build_can_handle_integer (angfsm_build_t *fsm, uint16_t event)
+{
+ angfsm_build_event_t *e = angfsm_build_get_event_by_code (fsm, event);
+ return angfsm_build_can_handle (fsm, e);
+}
+
+int
+angfsm_build_handle_timeout (angfsm_build_t *fsm)
+{
+ int out = 0;
+ int i;
+ char *event = NULL;
+ for (i = 0; i < (int) fsm->max_active_states; i++)
+ {
+ if (fsm->run.timeout_counters[i] > 0)
+ fsm->run.timeout_counters[i]--;
+ /* We have a timeout event. */
+ if (fsm->run.timeout_counters[i] == 0)
+ {
+ fsm->run.timeout_counters[i] = -1;
+ /* build event string */
+ event = (char *) malloc (
+ (strlen (fsm->run.active_states[i]->var_name)
+ + strlen ("_TIMEOUT") + 1) * sizeof (char));
+ sprintf (event, "%s_TIMEOUT", fsm->run.active_states[i]->var_name);
+ angfsm_build_handle_string (fsm, event);
+ out = 1;
+ }
+ }
+ return out;
+}
+
+angfsm_build_state_t*
+angfsm_build_get_next_state (angfsm_build_t *fsm,
+ char *state,
+ char *event,
+ char *branch)
+{
+ angfsm_build_state_t *s;
+ angfsm_build_event_t *e;
+ angfsm_build_trans_chain_t *t_curs;
+ angfsm_build_branch_chain_t *b_curs;
+
+ /* Convert input data. */
+ s = angfsm_build_get_state (fsm, state);
+ e = angfsm_build_get_event (fsm, event);
+ assert (s && e);
+
+ /* Get transition. */
+ t_curs = fsm->trans;
+ while (t_curs != NULL)
+ {
+ if (s == t_curs->trans.state && e == t_curs->trans.event)
+ break;
+ t_curs = t_curs->next;
+ }
+ assert (t_curs);
+ assert (t_curs->trans.output_branches);
+
+ /* If we have only one branch. */
+ if (strlen (branch) == 0)
+ {
+ /* Branch has to be given is there are multiple branches. */
+ assert (t_curs->trans.output_branches->next == NULL);
+ if (fsm->options.print_trans)
+ angfsm_build_print (fsm, &t_curs->trans, t_curs->trans.output_branches);
+ return t_curs->trans.output_branches->state;
+ }
+
+ /* Find correct branch. */
+ b_curs = t_curs->trans.output_branches;
+ while (b_curs != NULL)
+ {
+ if (strcmp (b_curs->name, branch) == 0)
+ break;
+ b_curs = b_curs->next;
+ }
+ assert (b_curs);
+ if (fsm->options.print_trans)
+ angfsm_build_print (fsm, &t_curs->trans, b_curs);
+ return b_curs->state;
+}
+
+int
+angfsm_build_options (int argc, char **argv)
+{
+ assert (argv);
+ int has_option = 0;
+ int i;
+ if (argc <= 1)
+ return has_option;
+
+ /* Select 1st FSM if it is the only one. */
+ angfsm_build_t *fsm = NULL;
+ angfsm_build_chain_t *fc = angfsm_build_all_fsm;
+ if (fc && fc->next == NULL)
+ fsm = fc->fsm;
+
+ /* Option parsing. Ok it's dirty. */
+ for (i = 1; i < argc; i++)
+ {
+ /* Print help. */
+ if (strcmp ("--ang-help", argv[i]) == 0)
+ {
+ angfsm_build_print_help ();
+ has_option = 1;
+ }
+
+ /* Select a specific FSM. */
+ if (strcmp ("--ang-fsm", argv[i]) == 0 && i + 1 < argc)
+ {
+ fc = angfsm_build_all_fsm;
+ while (fc != NULL)
+ {
+ if (strcmp (fc->fsm->name, argv[i + 1]) == 0)
+ {
+ fsm = fc->fsm;
+ i++;
+ break;
+ }
+ fc = fc->next;
+ }
+ has_option = 1;
+ }
+
+ /* Generate dot file. */
+ if (strcmp ("--ang-dot", argv[i]) == 0 && i + 1 < argc && fsm)
+ {
+ fsm->options.gen_dot = argv[++i];
+ has_option = 1;
+ }
+
+ /* Generate optimized code for specific architectures. */
+ if (strcmp ("--ang-gen", argv[i]) == 0 && i + 1 < argc)
+ {
+ if (fsm)
+ fsm->options.gen_code = argv[i + 1];
+ else
+ {
+ fc = angfsm_build_all_fsm;
+ while (fc != NULL)
+ {
+ fc->fsm->options.gen_code = argv[i + 1];
+ fc = fc->next;
+ }
+ }
+ i++;
+ has_option = 1;
+ }
+
+ /* Embed strings in generated code. */
+ if (strcmp ("--ang-embedded-strings", argv[i]) == 0)
+ {
+ if (fsm)
+ fsm->options.embedded_strings = 1;
+ else
+ {
+ fc = angfsm_build_all_fsm;
+ while (fc != NULL)
+ {
+ fc->fsm->options.embedded_strings = 1;
+ fc = fc->next;
+ }
+ }
+ has_option = 1;
+ }
+
+ /* No sanity check for a specific fsm or for all fsm. */
+ if (strcmp ("--ang-no-sanity-check", argv[i]) == 0)
+ {
+ if (fsm)
+ fsm->options.sanity_check = 0;
+ else
+ {
+ fc = angfsm_build_all_fsm;
+ while (fc != NULL)
+ {
+ fc->fsm->options.sanity_check = 0;
+ fc = fc->next;
+ }
+ }
+ }
+
+ /* Print transitions each time one occurs. */
+ if (strcmp ("--ang-print-transitions", argv[i]) == 0)
+ {
+ if (fsm)
+ fsm->options.print_trans = 1;
+ else
+ {
+ fc = angfsm_build_all_fsm;
+ while (fc != NULL)
+ {
+ fc->fsm->options.print_trans = 1;
+ fc = fc->next;
+ }
+ }
+ }
+ }
+
+ /* Option execution. */
+ if (has_option)
+ {
+ fc = angfsm_build_all_fsm;
+ while (fc != NULL)
+ {
+ if (fc->fsm->options.gen_dot)
+ angfsm_build_gen_dot (fc->fsm, fc->fsm->options.gen_dot);
+ if (fc->fsm->options.gen_code)
+ angfsm_build_gen (fc->fsm->options.gen_code);
+ if (fc->fsm->options.sanity_check)
+ angfsm_build_sanity_check (fc->fsm);
+ fc = fc->next;
+ }
+ }
+ return has_option;
+}
+
+void
+angfsm_build_gen_no_opti_h (angfsm_build_t *fsm, angfsm_build_arch_t arch)
+{
+ assert (arch < ANGFSM_BUILD_ARCH_NB);
+ angfsm_build_state_chain_t *sc;
+ angfsm_build_event_chain_t *ec;
+ angfsm_build_trans_chain_t *tc;
+ angfsm_build_branch_chain_t *bc;
+ angfsm_build_state_t *s;
+ angfsm_build_event_t *e;
+ angfsm_build_chain_t *all_fsm;
+ uint i, j;
+ uint embedded_strings = fsm->options.embedded_strings;
+
+ /* Open file. */
+ char *fn = (char*) malloc ((strlen (fsm->name)
+ + strlen ("angfsm_gen__.h")
+ + strlen (angfsm_build_arch_name[arch])
+ + 1) * sizeof (char));
+ sprintf (fn, "angfsm_gen_%s_%s.h", angfsm_build_arch_name[arch], fsm->name);
+ FILE *f = fopen (fn, "w");
+
+ /* Introduction. */
+ fprintf (f, "/* This file has been generated, do not edit. */\n\n");
+ fprintf (f, "#ifndef _angfsm_%s_\n", fsm->name);
+ fprintf (f, "#define _angfsm_%s_\n\n", fsm->name);
+ fprintf (f, "#include <inttypes.h>\n\n");
+ fprintf (f, "#include <string.h>\n\n");
+
+ /* Include all other fsm headers. */
+ all_fsm = angfsm_build_all_fsm;
+ while (all_fsm != NULL)
+ {
+ fprintf (f, "#include \"angfsm_gen_%s_%s.h\"\n",
+ angfsm_build_arch_name[arch],
+ all_fsm->fsm->name);
+ all_fsm = all_fsm->next;
+ }
+
+ /* Gen max active states define */
+ fprintf (f, "#define angfsm_%s_max_active_states %u\n",
+ fsm->name,
+ fsm->max_active_states);
+
+ /* Gen state enum. */
+ fprintf (f, "typedef enum\n{\n");
+ sc = fsm->states;
+ while (sc != NULL)
+ {
+ fprintf (f, "\tangfsm_STATE_%s_%s = %u,\n", fsm->name, sc->state.var_name, sc->state.code);
+ sc = sc->next;
+ }
+ fprintf (f, "\tangfsm_STATE_%s_NB_ = %u\n", fsm->name, fsm->state_nb);
+ fprintf (f, "} angfsm_%s_state_t;\n\n", fsm->name);
+
+ /* Gen event enum. */
+ fprintf (f, "typedef enum\n{\n");
+ ec = fsm->events;
+ while (ec != NULL)
+ {
+ fprintf (f, "\tangfsm_EVENT_%s_%s = %u,\n", fsm->name, ec->event.var_name, ec->event.code);
+ ec = ec->next;
+ }
+ fprintf (f, "\tangfsm_EVENT_%s_NB_ = %u\n", fsm->name, fsm->event_nb);
+ fprintf (f, "} angfsm_%s_event_t;\n\n", fsm->name);
+
+ /* Gen state strings. */
+ if (embedded_strings)
+ {
+ sc = fsm->states;
+ while (sc != NULL)
+ {
+ fprintf (f, "extern char angfsm_%s_state_str_%s[%u];\n",
+ fsm->name,
+ sc->state.var_name,
+ strlen (sc->state.var_name) + 1);
+ sc = sc->next;
+ }
+ fprintf (f, "extern char *angfsm_%s_state_str[%u];\n\n",
+ fsm->name,
+ fsm->state_nb);
+
+ /* Gen event strings. */
+ ec = fsm->events;
+ while (ec != NULL)
+ {
+ fprintf (f, "extern char angfsm_%s_event_str_%s[%u];\n",
+ fsm->name,
+ ec->event.var_name,
+ strlen (ec->event.var_name) + 1);
+ ec = ec->next;
+ }
+ fprintf (f, "extern char *angfsm_%s_event_str[%u];\n\n",
+ fsm->name,
+ fsm->event_nb);
+
+ /* Create a RAM string able to store event or state string. */
+ j = 0;
+ for (i = 0; i < fsm->event_nb; i++)
+ {
+ e = angfsm_build_get_event_by_code (fsm, i);
+ if (strlen (e->var_name) > j)
+ j = strlen (e->var_name);
+ }
+ for (i = 0; i < fsm->state_nb; i++)
+ {
+ s = angfsm_build_get_state_by_code (fsm, i);
+ if (strlen (s->var_name) > j)
+ j = strlen (s->var_name);
+ }
+ fprintf (f, "extern char angfsm_%s_str_buff[%u];\n", fsm->name, j + 1);
+
+ /* Convert an event enum in string. */
+ fprintf (f, "char *\nangfsm_%s_get_event_string_from_enum \
+ (angfsm_%s_event_t e);\n", fsm->name, fsm->name);
+
+ /* Convert a event string in enum. */
+ fprintf (f, "angfsm_%s_event_t\nangfsm_%s_get_event_enum_from_string \
+ (char *str);\n", fsm->name, fsm->name);
+
+ /* Convert an state enum in string. */
+ fprintf (f, "char *\nangfsm_%s_get_state_string_from_enum \
+ (angfsm_%s_state_t s);\n", fsm->name, fsm->name);
+
+ /* Convert a state string in enum. */
+ fprintf (f, "angfsm_%s_state_t\nangfsm_%s_get_state_enum_from_string \
+ (char *str);\n", fsm->name, fsm->name);
+ }
+
+ /* Gen transitions branches enum. */
+ fprintf (f, "typedef enum\n{\n");
+ tc = fsm->trans;
+ while (tc != NULL)
+ {
+ bc = tc->trans.output_branches;
+ while (bc != NULL)
+ {
+ if (bc->name != NULL)
+ fprintf (f, "\tangfsm_BRANCH_%s_%s_%s_%s = %u,\n",
+ fsm->name,
+ tc->trans.state->var_name,
+ tc->trans.event->var_name,
+ bc->name,
+ bc->state->code);
+ else
+ fprintf (f, "\tangfsm_BRANCH_%s_%s_%s_ = %u,\n",
+ fsm->name,
+ tc->trans.state->var_name,
+ tc->trans.event->var_name,
+ bc->state->code);
+ bc = bc->next;
+ }
+ tc = tc->next;
+ }
+ fprintf (f, "} angfsm_%s_branch_t;\n\n", fsm->name);
+
+ /* Gen function headers. */
+ tc = fsm->trans;
+ while (tc != NULL)
+ {
+ fprintf (f, "angfsm_%s_branch_t angfsm_%s_trans_func_%s_%s (void);\n",
+ fsm->name,
+ fsm->name,
+ tc->trans.state->var_name,
+ tc->trans.event->var_name);
+ tc = tc->next;
+ }
+ fprintf (f, "\n");
+
+ /* Gen function table. */
+ fprintf (f, "typedef angfsm_%s_branch_t (*angfsm_%s_func_t)(void);\n", fsm->name,
+ fsm->name);
+ fprintf (f, "extern const angfsm_%s_func_t angfsm_%s_trans_table[%u][%u];\n",
+ fsm->name,
+ fsm->name,
+ fsm->event_nb,
+ fsm->state_nb);
+ /* Gen read function for trans table. */
+ fprintf (f, "angfsm_%s_func_t angfsm_%s_read_trans (angfsm_%s_event_t event, "
+ "angfsm_%s_state_t state);\n\n",
+ fsm->name,
+ fsm->name,
+ fsm->name,
+ fsm->name);
+
+ /* Gen active states array. */
+ fprintf (f, "extern angfsm_%s_state_t angfsm_%s_active_states[%u];\n\n",
+ fsm->name,
+ fsm->name,
+ fsm->max_active_states);
+
+ /* Gen initialization function. */
+ sc = fsm->starters;
+ i = 0;
+ fprintf (f, "void\nangfsm_%s_init () __attribute__ ((constructor));\n\n",
+ fsm->name);
+
+ /* Gen handle function. */
+ fprintf (f, "int\nangfsm_%s_handle (angfsm_%s_event_t e);\n",
+ fsm->name,
+ fsm->name);
+
+ /* Gen can handle function. */
+ fprintf (f, "uint16_t\nangfsm_%s_can_handle (angfsm_%s_event_t e);\n\n",
+ fsm->name,
+ fsm->name);
+
+ if (fsm->timeouts != NULL)
+ {
+ /* Gen handle timeout function. */
+ fprintf (f, "int\nangfsm_%s_handle_timeout ();\n",
+ fsm->name);
+
+ /* Gen timeout values. */
+ fprintf (f, "extern int32_t angfsm_%s_timeout_values[angfsm_STATE_%s_NB_];\n",
+ fsm->name,
+ fsm->name);
+
+ /* Gen timeout corresponding events. */
+ fprintf (f, "extern angfsm_%s_event_t angfsm_%s_timeout_events[angfsm_STATE_%s_NB_];\n",
+ fsm->name,
+ fsm->name,
+ fsm->name);
+
+ /* Gen timeout counters array. */
+ fprintf (f, "extern int32_t angfsm_%s_timeout_counters[%u];\n\n",
+ fsm->name,
+ fsm->max_active_states);
+ }
+
+ /* Conclusion. */
+ fprintf (f, "#endif /* #ifndef _angfsm_%s_ */", fsm->name);
+
+ /* Close file. */
+ fclose (f);
+ free (fn);
+}
+
+void
+angfsm_build_gen_no_opti_c (angfsm_build_t *fsm, angfsm_build_arch_t arch)
+{
+ assert (arch < ANGFSM_BUILD_ARCH_NB);
+ angfsm_build_state_chain_t *sc;
+ angfsm_build_event_chain_t *ec;
+ angfsm_build_trans_chain_t *tc;
+ angfsm_build_timeout_chain_t *toc;
+ angfsm_build_state_t *s;
+ angfsm_build_event_t *e;
+ uint i, j, found;
+ uint embedded_strings = fsm->options.embedded_strings;
+
+ /* Open file. */
+ char *fn = (char*) malloc ((strlen (fsm->name)
+ + strlen ("angfsm_gen__.c")
+ + strlen (angfsm_build_arch_name[arch])
+ + 1) * sizeof (char));
+ sprintf (fn, "angfsm_gen_%s_%s.c", angfsm_build_arch_name[arch], fsm->name);
+ FILE *f = fopen (fn, "w");
+
+ /* Introduction. */
+ fprintf (f, "/* This file has been generated, do not edit. */\n\n");
+ fprintf (f, "#include \"angfsm_gen_%s_%s.h\"\n\n",
+ angfsm_build_arch_name[arch],
+ fsm->name);
+
+ /* Gen state strings. */
+ if (embedded_strings)
+ {
+ sc = fsm->states;
+ while (sc != NULL)
+ {
+ fprintf (f, "char angfsm_%s_state_str_%s[] = \"%s\";\n",
+ fsm->name,
+ sc->state.var_name,
+ sc->state.var_name);
+ sc = sc->next;
+ }
+ fprintf (f, "char *angfsm_%s_state_str[] =\n{\n", fsm->name);
+ for (i = 0; i < fsm->state_nb; i++)
+ {
+ s = angfsm_build_get_state_by_code (fsm, i);
+ fprintf (f, "\tangfsm_%s_state_str_%s", fsm->name, s->var_name);
+ if (i == fsm->state_nb - 1)
+ fprintf (f, "\n");
+ else
+ fprintf (f, ",\n");
+ }
+ fprintf (f, "};\n\n");
+
+ /* Gen event strings. */
+ ec = fsm->events;
+ while (ec != NULL)
+ {
+ fprintf (f, "char angfsm_%s_event_str_%s[] = \"%s\";\n",
+ fsm->name,
+ ec->event.var_name,
+ ec->event.var_name);
+ ec = ec->next;
+ }
+ fprintf (f, "char *angfsm_%s_event_str[] =\n{\n", fsm->name);
+ for (i = 0; i < fsm->event_nb; i++)
+ {
+ e = angfsm_build_get_event_by_code (fsm, i);
+ fprintf (f, "\tangfsm_%s_event_str_%s", fsm->name, e->var_name);
+ if (i == fsm->event_nb - 1)
+ fprintf (f, "\n");
+ else
+ fprintf (f, ",\n");
+ }
+ fprintf (f, "};\n\n");
+
+ /* Create a RAM string able to store event or state string. */
+ j = 0;
+ for (i = 0; i < fsm->event_nb; i++)
+ {
+ e = angfsm_build_get_event_by_code (fsm, i);
+ if (strlen (e->var_name) > j)
+ j = strlen (e->var_name);
+ }
+ for (i = 0; i < fsm->state_nb; i++)
+ {
+ s = angfsm_build_get_state_by_code (fsm, i);
+ if (strlen (s->var_name) > j)
+ j = strlen (s->var_name);
+ }
+ fprintf (f, "char angfsm_%s_str_buff[%u];\n", fsm->name, j + 1);
+
+ /* Convert an event enum in string. */
+ fprintf (f, "char *\nangfsm_%s_get_event_string_from_enum \
+ (angfsm_%s_event_t e)\n{\n", fsm->name, fsm->name);
+ fprintf (f, "\treturn strcpy (angfsm_%s_str_buff, \
+ (char *) (&(angfsm_%s_event_str[e])));\n", fsm->name, fsm->name);
+ fprintf (f, "}\n\n");
+
+ /* Convert a event string in enum. */
+ fprintf (f, "angfsm_%s_event_t\nangfsm_%s_get_event_enum_from_string \
+ (char *str)\n{\n", fsm->name, fsm->name);
+ fprintf (f, "\tuint16_t i;\n");
+ fprintf (f, "\tfor (i = 0; i < angfsm_EVENT_%s_NB_; i++)\n", fsm->name);
+ fprintf (f, "\t\tif (strcpy (str, \
+ (char *) (&(angfsm_%s_event_str[i]))) == 0)\n", fsm->name);
+ fprintf (f, "\t\t\treturn i;\n");
+ fprintf (f, "\treturn angfsm_EVENT_%s_NB_;\n", fsm->name);
+ fprintf (f, "}\n\n");
+
+ /* Convert an state enum in string. */
+ fprintf (f, "char *\nangfsm_%s_get_state_string_from_enum \
+ (angfsm_%s_state_t s)\n{\n", fsm->name, fsm->name);
+ fprintf (f, "\treturn strcpy (angfsm_%s_str_buff, \
+ (char *) (&(angfsm_%s_state_str[s])));\n", fsm->name, fsm->name);
+ fprintf (f, "}\n\n");
+
+ /* Convert a state string in enum. */
+ fprintf (f, "angfsm_%s_state_t\nangfsm_%s_get_state_enum_from_string \
+ (char *str)\n{\n", fsm->name, fsm->name);
+ fprintf (f, "\tuint16_t i;\n");
+ fprintf (f, "\tfor (i = 0; i < angfsm_STATE_%s_NB_; i++)\n", fsm->name);
+ fprintf (f, "\t\tif (strcpy (str, \
+ (char *) (&(angfsm_%s_state_str[i]))) == 0)\n", fsm->name);
+ fprintf (f, "\t\t\treturn i;\n");
+ fprintf (f, "\treturn angfsm_STATE_%s_NB_;\n", fsm->name);
+ fprintf (f, "}\n\n");
+ }
+
+ /* Gen function table. */
+ fprintf (f, "const angfsm_%s_func_t angfsm_%s_trans_table[%u][%u] = \n{\n",
+ fsm->name,
+ fsm->name,
+ fsm->event_nb,
+ fsm->state_nb);
+ /* for each events and state, see if it exists an associated transition. */
+ for (i = 0; i < fsm->event_nb; i++)
+ {
+ e = angfsm_build_get_event_by_code (fsm, i);
+ fprintf (f, "\t{");
+ for (j = 0; j < fsm->state_nb; j++)
+ {
+ s = angfsm_build_get_state_by_code (fsm, j);
+ tc = fsm->trans;
+ found = 0;
+ while (tc != NULL)
+ {
+ if (tc->trans.state == s && tc->trans.event == e)
+ {
+ found = 1;
+ fprintf (f, "&angfsm_%s_trans_func_%s_%s",
+ fsm->name,
+ tc->trans.state->var_name,
+ tc->trans.event->var_name);
+ tc = tc->next;
+ break;
+ }
+ tc = tc->next;
+ }
+ if (!found)
+ fprintf (f, "(angfsm_%s_func_t) 0", fsm->name);
+ if (j == fsm->state_nb - 1)
+ fprintf (f, "}");
+ else
+ fprintf (f, ", ");
+ }
+ if (i != fsm->event_nb - 1)
+ fprintf (f, ",");
+ fprintf (f, "\n");
+ }
+ fprintf (f, "};\n\n");
+
+ /* Gen read function for trans table. */
+ fprintf (f, "angfsm_%s_func_t angfsm_%s_read_trans (angfsm_%s_event_t event, "
+ "angfsm_%s_state_t state)\n{\n",
+ fsm->name,
+ fsm->name,
+ fsm->name,
+ fsm->name);
+ fprintf (f, "\treturn (angfsm_%s_func_t) angfsm_%s_trans_table[event][state];\n",
+ fsm->name,
+ fsm->name);
+ fprintf (f, "}\n\n");
+
+ /* Gen active states array. */
+ fprintf (f, "angfsm_%s_state_t angfsm_%s_active_states[%u];\n\n",
+ fsm->name,
+ fsm->name,
+ fsm->max_active_states);
+
+ /* Gen initialization function. */
+ sc = fsm->starters;
+ i = 0;
+ fprintf (f, "void\nangfsm_%s_init ()\n{\n", fsm->name);
+ while (sc != NULL)
+ {
+ fprintf (f, "\tangfsm_%s_active_states[%u] = (angfsm_%s_state_t) %u;\n",
+ fsm->name,
+ i,
+ fsm->name,
+ sc->state.code);
+ if (fsm->timeouts != NULL)
+ {
+ toc = fsm->timeouts;
+ while (toc != NULL)
+ {
+ if (toc->timeout.trans->state->code == sc->state.code)
+ {
+ fprintf (f, "\tangfsm_%s_timeout_counters[%u] = %u;\n",
+ fsm->name,
+ i,
+ toc->timeout.timeout);
+ }
+ toc = toc->next;
+ }
+ }
+ i++;
+ sc = sc->next;
+ }
+ fprintf (f, "}\n\n");
+
+ /* Gen handle function. */
+ fprintf (f, "int\nangfsm_%s_handle (angfsm_%s_event_t e)\n{\n",
+ fsm->name,
+ fsm->name);
+ fprintf (f, "\tuint16_t i;\n");
+ fprintf (f, "\tint handled = 0;\n");
+ fprintf (f, "\tfor (i = 0; i < angfsm_%s_max_active_states; i++)\n\t{\n",
+ fsm->name);
+ fprintf (f, "\t\tangfsm_%s_func_t trans = angfsm_%s_read_trans (e, angfsm_%s_active_states[i]);\n",
+ fsm->name,
+ fsm->name,
+ fsm->name);
+ fprintf (f, "\t\tif (trans)\n");
+ fprintf (f, "\t\t{\n");
+ fprintf (f, "\t\t\tangfsm_%s_active_states[i] = (angfsm_%s_state_t) trans ();\n", fsm->name, fsm->name);
+ fprintf (f, "\t\t\thandled = 1;\n");
+ if (fsm->timeouts != NULL)
+ {
+ fprintf (f, "\t\t\tangfsm_%s_timeout_counters[i] = "
+ "angfsm_%s_timeout_values[angfsm_%s_active_states[i]];\n",
+ fsm->name,
+ fsm->name,
+ fsm->name);
+ }
+ fprintf (f, "\t\t}\n");
+ fprintf (f, "\t}\n");
+ fprintf (f, "\treturn handled;\n");
+ fprintf (f, "}\n\n");
+
+ /* Gen can handle function. */
+ fprintf (f, "uint16_t\nangfsm_%s_can_handle (angfsm_%s_event_t e)\n{\n",
+ fsm->name,
+ fsm->name);
+ fprintf (f, "\tuint16_t i;\n");
+ fprintf (f, "\tfor (i = 0; i < angfsm_%s_max_active_states; i++)\n",
+ fsm->name);
+ fprintf (f, "\t\tif (angfsm_%s_read_trans (e, angfsm_%s_active_states[i]))\n",
+ fsm->name,
+ fsm->name);
+ fprintf (f, "\t\t\treturn 1;\n");
+ fprintf (f, "\treturn 0;\n");
+ fprintf (f, "}\n\n");
+
+ if (fsm->timeouts != NULL)
+ {
+ /* Gen timeout counters array. */
+ fprintf (f, "int32_t angfsm_%s_timeout_counters[%u];\n",
+ fsm->name,
+ fsm->max_active_states);
+
+ /* Gen timeout values array. */
+ fprintf (f, "int32_t angfsm_%s_timeout_values[angfsm_STATE_%s_NB_] =\n{\n",
+ fsm->name,
+ fsm->name);
+ int value;
+ for (i = 0; i < fsm->state_nb; i++)
+ {
+ value = -1;
+ s = angfsm_build_get_state_by_code (fsm, i);
+ assert (s);
+ toc = fsm->timeouts;
+ while (toc != NULL)
+ {
+ if (s->code == toc->timeout.trans->state->code)
+ {
+ value = toc->timeout.timeout;
+ break;
+ }
+ toc = toc->next;
+ }
+ fprintf (f, "\t%i", value);
+ if (i != fsm->state_nb - 1)
+ fprintf (f, ",");
+ fprintf (f, "\n");
+ }
+ fprintf (f, "};\n\n");
+
+ /* Gen timeout corresponding events array. */
+ fprintf (f, "angfsm_%s_event_t angfsm_%s_timeout_events[angfsm_STATE_%s_NB_] =\n{\n",
+ fsm->name,
+ fsm->name,
+ fsm->name);
+ for (i = 0; i < fsm->state_nb; i++)
+ {
+ value = -1;
+ s = angfsm_build_get_state_by_code (fsm, i);
+ assert (s);
+ toc = fsm->timeouts;
+ while (toc != NULL)
+ {
+ if (s->code == toc->timeout.trans->state->code)
+ {
+ value = toc->timeout.trans->event->code;
+ break;
+ }
+ toc = toc->next;
+ }
+ if (value == -1)
+ fprintf (f, "\t(angfsm_%s_event_t) angfsm_STATE_%s_NB_", fsm->name, fsm->name);
+ else
+ fprintf (f, "\t(angfsm_%s_event_t) %u", fsm->name, value);
+
+ if (i != fsm->state_nb - 1)
+ fprintf (f, ",");
+ fprintf (f, "\n");
+ }
+ fprintf (f, "};\n\n");
+
+ /* Gen handle timeout function. */
+ fprintf (f, "int\nangfsm_%s_handle_timeout ()\n{\n",
+ fsm->name);
+ fprintf (f, "\tuint16_t i;\n");
+ fprintf (f, "\tint out = 0;\n");
+ fprintf (f, "\tfor (i = 0; i < angfsm_%s_max_active_states; i++)\n\t{\n",
+ fsm->name);
+ fprintf (f, "\t\tif (angfsm_%s_timeout_counters[i] > 0)\n\t\t{\n",
+ fsm->name);
+ fprintf (f, "\t\t\tangfsm_%s_timeout_counters[i]--;\n",
+ fsm->name);
+ fprintf (f, "\t\t\tif (angfsm_%s_timeout_counters[i] == 0)\n\t\t\t{\n",
+ fsm->name);
+ fprintf (f, "\t\t\t\tangfsm_%s_handle (angfsm_%s_timeout_events[angfsm_%s_active_states[i]]);\n",
+ fsm->name,
+ fsm->name,
+ fsm->name);
+ fprintf (f, "\t\t\t\tout = 1;\n");
+ fprintf (f, "\t\t\t}\n");
+ fprintf (f, "\t\t}\n");
+ fprintf (f, "\t}\n");
+ fprintf (f, "\treturn out;\n");
+ fprintf (f, "}\n\n");
+ }
+
+ /* Close file. */
+ fclose (f);
+ free (fn);
+}
+
+void
+angfsm_build_gen_opti_avr_h (angfsm_build_t *fsm, angfsm_build_arch_t arch)
+{
+ assert (arch < ANGFSM_BUILD_ARCH_NB);
+ angfsm_build_state_chain_t *sc;
+ angfsm_build_event_chain_t *ec;
+ angfsm_build_trans_chain_t *tc;
+ angfsm_build_branch_chain_t *bc;
+ angfsm_build_state_t *s;
+ angfsm_build_event_t *e;
+ angfsm_build_chain_t *all_fsm;
+ uint i, j;
+ uint embedded_strings = fsm->options.embedded_strings;
+
+ /* Open file. */
+ char *fn = (char*) malloc ((strlen (fsm->name)
+ + strlen ("angfsm_gen__.h")
+ + strlen (angfsm_build_arch_name[arch])
+ + 1) * sizeof (char));
+ sprintf (fn, "angfsm_gen_%s_%s.h", angfsm_build_arch_name[arch], fsm->name);
+ FILE *f = fopen (fn, "w");
+
+ /* Introduction. */
+ fprintf (f, "/* This file has been generated, do not edit. */\n\n");
+ fprintf (f, "#ifndef _angfsm_%s_\n", fsm->name);
+ fprintf (f, "#define _angfsm_%s_\n\n", fsm->name);
+ fprintf (f, "#include <avr/pgmspace.h>\n");
+ fprintf (f, "#include <inttypes.h>\n\n");
+
+ /* Include all other fsm headers. */
+ all_fsm = angfsm_build_all_fsm;
+ while (all_fsm != NULL)
+ {
+ fprintf (f, "#include \"angfsm_gen_%s_%s.h\"\n",
+ angfsm_build_arch_name[arch],
+ all_fsm->fsm->name);
+ all_fsm = all_fsm->next;
+ }
+
+ /* Gen max active states define */
+ fprintf (f, "#define angfsm_%s_max_active_states %u\n",
+ fsm->name,
+ fsm->max_active_states);
+
+ /* Gen state enum. */
+ fprintf (f, "typedef enum\n{\n");
+ sc = fsm->states;
+ while (sc != NULL)
+ {
+ fprintf (f, "\tangfsm_STATE_%s_%s = %u,\n", fsm->name, sc->state.var_name, sc->state.code);
+ sc = sc->next;
+ }
+ fprintf (f, "\tangfsm_STATE_%s_NB_ = %u\n", fsm->name, fsm->state_nb);
+ fprintf (f, "} angfsm_%s_state_t;\n\n", fsm->name);
+
+ /* Gen event enum. */
+ fprintf (f, "typedef enum\n{\n");
+ ec = fsm->events;
+ while (ec != NULL)
+ {
+ fprintf (f, "\tangfsm_EVENT_%s_%s = %u,\n", fsm->name, ec->event.var_name, ec->event.code);
+ ec = ec->next;
+ }
+ fprintf (f, "\tangfsm_EVENT_%s_NB_ = %u\n", fsm->name, fsm->event_nb);
+ fprintf (f, "} angfsm_%s_event_t;\n\n", fsm->name);
+
+ /* Gen state strings. */
+ if (embedded_strings)
+ {
+ sc = fsm->states;
+ while (sc != NULL)
+ {
+ fprintf (f, "extern prog_char angfsm_%s_state_str_%s[%u] PROGMEM;\n",
+ fsm->name,
+ sc->state.var_name,
+ strlen (sc->state.var_name) + 1);
+ sc = sc->next;
+ }
+ fprintf (f, "extern const char *angfsm_%s_state_str[%u] PROGMEM;\n\n",
+ fsm->name,
+ fsm->state_nb);
+
+ /* Gen event strings. */
+ ec = fsm->events;
+ while (ec != NULL)
+ {
+ fprintf (f, "extern prog_char angfsm_%s_event_str_%s[%u] PROGMEM;\n",
+ fsm->name,
+ ec->event.var_name,
+ strlen (ec->event.var_name) + 1);
+ ec = ec->next;
+ }
+ fprintf (f, "extern const char *angfsm_%s_event_str[%u] PROGMEM;\n\n",
+ fsm->name,
+ fsm->event_nb);
+
+ /* Create a RAM string able to store event or state string. */
+ j = 0;
+ for (i = 0; i < fsm->event_nb; i++)
+ {
+ e = angfsm_build_get_event_by_code (fsm, i);
+ if (strlen (e->var_name) > j)
+ j = strlen (e->var_name);
+ }
+ for (i = 0; i < fsm->state_nb; i++)
+ {
+ s = angfsm_build_get_state_by_code (fsm, i);
+ if (strlen (s->var_name) > j)
+ j = strlen (s->var_name);
+ }
+ fprintf (f, "extern char angfsm_%s_str_buff[%u];\n", fsm->name, j + 1);
+
+ /* Convert an event enum in string. */
+ fprintf (f, "char *\nangfsm_%s_get_event_string_from_enum \
+ (angfsm_%s_event_t e);\n", fsm->name, fsm->name);
+
+ /* Convert a event string in enum. */
+ fprintf (f, "angfsm_%s_event_t\nangfsm_%s_get_event_enum_from_string \
+ (char *str);\n", fsm->name, fsm->name);
+
+ /* Convert an state enum in string. */
+ fprintf (f, "char *\nangfsm_%s_get_state_string_from_enum \
+ (angfsm_%s_state_t s);\n", fsm->name, fsm->name);
+
+ /* Convert a state string in enum. */
+ fprintf (f, "angfsm_%s_state_t\nangfsm_%s_get_state_enum_from_string \
+ (char *str);\n", fsm->name, fsm->name);
+ }
+
+ /* Gen transitions branches enum. */
+ fprintf (f, "typedef enum\n{\n");
+ tc = fsm->trans;
+ while (tc != NULL)
+ {
+ bc = tc->trans.output_branches;
+ while (bc != NULL)
+ {
+ if (bc->name != NULL)
+ fprintf (f, "\tangfsm_BRANCH_%s_%s_%s_%s = %u,\n",
+ fsm->name,
+ tc->trans.state->var_name,
+ tc->trans.event->var_name,
+ bc->name,
+ bc->state->code);
+ else
+ fprintf (f, "\tangfsm_BRANCH_%s_%s_%s_ = %u,\n",
+ fsm->name,
+ tc->trans.state->var_name,
+ tc->trans.event->var_name,
+ bc->state->code);
+ bc = bc->next;
+ }
+ tc = tc->next;
+ }
+ fprintf (f, "} angfsm_%s_branch_t;\n\n", fsm->name);
+
+ /* Gen function headers. */
+ tc = fsm->trans;
+ while (tc != NULL)
+ {
+ fprintf (f, "angfsm_%s_branch_t angfsm_%s_trans_func_%s_%s (void);\n",
+ fsm->name,
+ fsm->name,
+ tc->trans.state->var_name,
+ tc->trans.event->var_name);
+ tc = tc->next;
+ }
+ fprintf (f, "\n");
+
+ /* Gen function table. */
+ fprintf (f, "typedef angfsm_%s_branch_t (*angfsm_%s_func_t)(void);\n", fsm->name,
+ fsm->name);
+ fprintf (f, "extern const angfsm_%s_func_t PROGMEM angfsm_%s_trans_table[%u][%u];\n",
+ fsm->name,
+ fsm->name,
+ fsm->event_nb,
+ fsm->state_nb);
+ /* Gen read function for trans table. */
+ fprintf (f, "angfsm_%s_func_t angfsm_%s_read_trans (angfsm_%s_event_t event, "
+ "angfsm_%s_state_t state);\n\n",
+ fsm->name,
+ fsm->name,
+ fsm->name,
+ fsm->name);
+
+ /* Gen active states array. */
+ fprintf (f, "extern angfsm_%s_state_t angfsm_%s_active_states[%u];\n\n",
+ fsm->name,
+ fsm->name,
+ fsm->max_active_states);
+
+ /* Gen initialization function. */
+ sc = fsm->starters;
+ i = 0;
+ fprintf (f, "void\nangfsm_%s_init () __attribute__ ((constructor));\n\n",
+ fsm->name);
+
+ /* Gen handle function. */
+ fprintf (f, "int\nangfsm_%s_handle (angfsm_%s_event_t e);\n",
+ fsm->name,
+ fsm->name);
+
+ /* Gen can handle function. */
+ fprintf (f, "uint16_t\nangfsm_%s_can_handle (angfsm_%s_event_t e);\n\n",
+ fsm->name,
+ fsm->name);
+
+ if (fsm->timeouts != NULL)
+ {
+ /* Gen handle timeout function. */
+ fprintf (f, "int\nangfsm_%s_handle_timeout ();\n",
+ fsm->name);
+
+ /* Gen timeout values. */
+ fprintf (f, "extern int32_t angfsm_%s_timeout_values[angfsm_STATE_%s_NB_];\n",
+ fsm->name,
+ fsm->name);
+
+ /* Gen timeout corresponding events. */
+ fprintf (f, "extern angfsm_%s_event_t angfsm_%s_timeout_events[angfsm_STATE_%s_NB_];\n",
+ fsm->name,
+ fsm->name,
+ fsm->name);
+
+ /* Gen timeout counters array. */
+ fprintf (f, "extern int32_t angfsm_%s_timeout_counters[%u];\n\n",
+ fsm->name,
+ fsm->max_active_states);
+ }
+
+ /* Conclusion. */
+ fprintf (f, "#endif /* #ifndef _angfsm_%s_ */", fsm->name);
+
+ /* Close file. */
+ fclose (f);
+ free (fn);
+}
+
+void
+angfsm_build_gen_opti_avr_c (angfsm_build_t *fsm, angfsm_build_arch_t arch)
+{
+ assert (arch < ANGFSM_BUILD_ARCH_NB);
+ angfsm_build_state_chain_t *sc;
+ angfsm_build_event_chain_t *ec;
+ angfsm_build_trans_chain_t *tc;
+ angfsm_build_timeout_chain_t *toc;
+ angfsm_build_state_t *s;
+ angfsm_build_event_t *e;
+ uint i, j, found;
+ uint embedded_strings = fsm->options.embedded_strings;
+
+ /* Open file. */
+ char *fn = (char*) malloc ((strlen (fsm->name)
+ + strlen ("angfsm_gen__.c")
+ + strlen (angfsm_build_arch_name[arch])
+ + 1) * sizeof (char));
+ sprintf (fn, "angfsm_gen_%s_%s.c", angfsm_build_arch_name[arch], fsm->name);
+ FILE *f = fopen (fn, "w");
+
+ /* Introduction. */
+ fprintf (f, "/* This file has been generated, do not edit. */\n\n");
+ fprintf (f, "#include \"angfsm_gen_%s_%s.h\"\n\n",
+ angfsm_build_arch_name[arch],
+ fsm->name);
+
+ /* Gen state strings. */
+ if (embedded_strings)
+ {
+ sc = fsm->states;
+ while (sc != NULL)
+ {
+ fprintf (f, "prog_char angfsm_%s_state_str_%s[] PROGMEM = \"%s\";\n",
+ fsm->name,
+ sc->state.var_name,
+ sc->state.var_name);
+ sc = sc->next;
+ }
+ fprintf (f, "const char *angfsm_%s_state_str[] PROGMEM =\n{\n", fsm->name);
+ for (i = 0; i < fsm->state_nb; i++)
+ {
+ s = angfsm_build_get_state_by_code (fsm, i);
+ fprintf (f, "\tangfsm_%s_state_str_%s", fsm->name, s->var_name);
+ if (i == fsm->state_nb - 1)
+ fprintf (f, "\n");
+ else
+ fprintf (f, ",\n");
+ }
+ fprintf (f, "};\n\n");
+
+ /* Gen event strings. */
+ ec = fsm->events;
+ while (ec != NULL)
+ {
+ fprintf (f, "prog_char angfsm_%s_event_str_%s[] PROGMEM = \"%s\";\n",
+ fsm->name,
+ ec->event.var_name,
+ ec->event.var_name);
+ ec = ec->next;
+ }
+ fprintf (f, "const char *angfsm_%s_event_str[] PROGMEM =\n{\n", fsm->name);
+ for (i = 0; i < fsm->event_nb; i++)
+ {
+ e = angfsm_build_get_event_by_code (fsm, i);
+ fprintf (f, "\tangfsm_%s_event_str_%s", fsm->name, e->var_name);
+ if (i == fsm->event_nb - 1)
+ fprintf (f, "\n");
+ else
+ fprintf (f, ",\n");
+ }
+ fprintf (f, "};\n\n");
+
+ /* Create a RAM string able to store event or state string. */
+ j = 0;
+ for (i = 0; i < fsm->event_nb; i++)
+ {
+ e = angfsm_build_get_event_by_code (fsm, i);
+ if (strlen (e->var_name) > j)
+ j = strlen (e->var_name);
+ }
+ for (i = 0; i < fsm->state_nb; i++)
+ {
+ s = angfsm_build_get_state_by_code (fsm, i);
+ if (strlen (s->var_name) > j)
+ j = strlen (s->var_name);
+ }
+ fprintf (f, "char angfsm_%s_str_buff[%u];\n", fsm->name, j + 1);
+
+ /* Convert an event enum in string. */
+ fprintf (f, "char *\nangfsm_%s_get_event_string_from_enum \
+ (angfsm_%s_event_t e)\n{\n", fsm->name, fsm->name);
+ fprintf (f, "\treturn strcpy_P (angfsm_%s_str_buff, \
+ (char *) pgm_read_word (&(angfsm_%s_event_str[e])));\n", fsm->name, fsm->name);
+ fprintf (f, "}\n\n");
+
+ /* Convert a event string in enum. */
+ fprintf (f, "angfsm_%s_event_t\nangfsm_%s_get_event_enum_from_string \
+ (char *str)\n{\n", fsm->name, fsm->name);
+ fprintf (f, "\tuint16_t i;\n");
+ fprintf (f, "\tfor (i = 0; i < angfsm_EVENT_%s_NB_; i++)\n", fsm->name);
+ fprintf (f, "\t\tif (strcpy_P (str, \
+ (char *) pgm_read_word (&(angfsm_%s_event_str[i]))) == 0)\n", fsm->name);
+ fprintf (f, "\t\t\treturn i;\n");
+ fprintf (f, "\treturn angfsm_EVENT_%s_NB_;\n", fsm->name);
+ fprintf (f, "}\n\n");
+
+ /* Convert an state enum in string. */
+ fprintf (f, "char *\nangfsm_%s_get_state_string_from_enum \
+ (angfsm_%s_state_t s)\n{\n", fsm->name, fsm->name);
+ fprintf (f, "\treturn strcpy_P (angfsm_%s_str_buff, \
+ (char *) pgm_read_word (&(angfsm_%s_state_str[s])));\n", fsm->name, fsm->name);
+ fprintf (f, "}\n\n");
+
+ /* Convert a state string in enum. */
+ fprintf (f, "angfsm_%s_state_t\nangfsm_%s_get_state_enum_from_string \
+ (char *str)\n{\n", fsm->name, fsm->name);
+ fprintf (f, "\tuint16_t i;\n");
+ fprintf (f, "\tfor (i = 0; i < angfsm_STATE_%s_NB_; i++)\n", fsm->name);
+ fprintf (f, "\t\tif (strcpy_P (str, \
+ (char *) pgm_read_word (&(angfsm_%s_state_str[i]))) == 0)\n", fsm->name);
+ fprintf (f, "\t\t\treturn i;\n");
+ fprintf (f, "\treturn angfsm_STATE_%s_NB_;\n", fsm->name);
+ fprintf (f, "}\n\n");
+ }
+
+ /* Gen function table. */
+ fprintf (f, "const angfsm_%s_func_t PROGMEM angfsm_%s_trans_table[%u][%u] = \n{\n",
+ fsm->name,
+ fsm->name,
+ fsm->event_nb,
+ fsm->state_nb);
+ /* for each events and state, see if it exists an associated transition. */
+ for (i = 0; i < fsm->event_nb; i++)
+ {
+ e = angfsm_build_get_event_by_code (fsm, i);
+ fprintf (f, "\t{");
+ for (j = 0; j < fsm->state_nb; j++)
+ {
+ s = angfsm_build_get_state_by_code (fsm, j);
+ tc = fsm->trans;
+ found = 0;
+ while (tc != NULL)
+ {
+ if (tc->trans.state == s && tc->trans.event == e)
+ {
+ found = 1;
+ fprintf (f, "&angfsm_%s_trans_func_%s_%s",
+ fsm->name,
+ tc->trans.state->var_name,
+ tc->trans.event->var_name);
+ tc = tc->next;
+ break;
+ }
+ tc = tc->next;
+ }
+ if (!found)
+ fprintf (f, "(angfsm_%s_func_t) 0", fsm->name);
+ if (j == fsm->state_nb - 1)
+ fprintf (f, "}");
+ else
+ fprintf (f, ", ");
+ }
+ if (i != fsm->event_nb - 1)
+ fprintf (f, ",");
+ fprintf (f, "\n");
+ }
+ fprintf (f, "};\n\n");
+
+ /* Gen read function for trans table. */
+ fprintf (f, "angfsm_%s_func_t angfsm_%s_read_trans (angfsm_%s_event_t event, "
+ "angfsm_%s_state_t state)\n{\n",
+ fsm->name,
+ fsm->name,
+ fsm->name,
+ fsm->name);
+ fprintf (f, "\treturn (angfsm_%s_func_t) pgm_read_word "
+ "(&angfsm_%s_trans_table[event][state]);\n",
+ fsm->name,
+ fsm->name);
+ fprintf (f, "}\n\n");
+
+ /* Gen active states array. */
+ fprintf (f, "angfsm_%s_state_t angfsm_%s_active_states[%u];\n\n",
+ fsm->name,
+ fsm->name,
+ fsm->max_active_states);
+
+ /* Gen initialization function. */
+ sc = fsm->starters;
+ i = 0;
+ fprintf (f, "void\nangfsm_%s_init ()\n{\n", fsm->name);
+ while (sc != NULL)
+ {
+ fprintf (f, "\tangfsm_%s_active_states[%u] = (angfsm_%s_state_t) %u;\n",
+ fsm->name,
+ i,
+ fsm->name,
+ sc->state.code);
+ if (fsm->timeouts != NULL)
+ {
+ toc = fsm->timeouts;
+ while (toc != NULL)
+ {
+ if (toc->timeout.trans->state->code == sc->state.code)
+ {
+ fprintf (f, "\tangfsm_%s_timeout_counters[%u] = %u;\n",
+ fsm->name,
+ i,
+ toc->timeout.timeout);
+ }
+ toc = toc->next;
+ }
+ }
+ i++;
+ sc = sc->next;
+ }
+ fprintf (f, "}\n\n");
+
+ /* Gen handle function. */
+ fprintf (f, "int\nangfsm_%s_handle (angfsm_%s_event_t e)\n{\n",
+ fsm->name,
+ fsm->name);
+ fprintf (f, "\tuint16_t i;\n");
+ fprintf (f, "\tint handled = 0;\n");
+ fprintf (f, "\tfor (i = 0; i < angfsm_%s_max_active_states; i++)\n\t{\n",
+ fsm->name);
+ fprintf (f, "\t\tangfsm_%s_func_t trans = angfsm_%s_read_trans (e, angfsm_%s_active_states[i]);\n",
+ fsm->name,
+ fsm->name,
+ fsm->name);
+ fprintf (f, "\t\tif (trans)\n");
+ fprintf (f, "\t\t{\n");
+ fprintf (f, "\t\t\tangfsm_%s_active_states[i] = (angfsm_%s_state_t) trans ();\n", fsm->name, fsm->name);
+ fprintf (f, "\t\t\thandled = 1;\n");
+ if (fsm->timeouts != NULL)
+ {
+ fprintf (f, "\t\t\tangfsm_%s_timeout_counters[i] = "
+ "angfsm_%s_timeout_values[angfsm_%s_active_states[i]];\n",
+ fsm->name,
+ fsm->name,
+ fsm->name);
+ }
+ fprintf (f, "\t\t}\n");
+ fprintf (f, "\t}\n");
+ fprintf (f, "\treturn handled;\n");
+ fprintf (f, "}\n\n");
+
+ /* Gen can handle function. */
+ fprintf (f, "uint16_t\nangfsm_%s_can_handle (angfsm_%s_event_t e)\n{\n",
+ fsm->name,
+ fsm->name);
+ fprintf (f, "\tuint16_t i;\n");
+ fprintf (f, "\tfor (i = 0; i < angfsm_%s_max_active_states; i++)\n",
+ fsm->name);
+ fprintf (f, "\t\tif (angfsm_%s_read_trans (e, angfsm_%s_active_states[i]))\n",
+ fsm->name,
+ fsm->name);
+ fprintf (f, "\t\t\treturn 1;\n");
+ fprintf (f, "\treturn 0;\n");
+ fprintf (f, "}\n\n");
+
+ if (fsm->timeouts != NULL)
+ {
+ /* Gen timeout counters array. */
+ fprintf (f, "int32_t angfsm_%s_timeout_counters[%u];\n",
+ fsm->name,
+ fsm->max_active_states);
+
+ /* Gen timeout values array. */
+ fprintf (f, "int32_t angfsm_%s_timeout_values[angfsm_STATE_%s_NB_] =\n{\n",
+ fsm->name,
+ fsm->name);
+ int value;
+ for (i = 0; i < fsm->state_nb; i++)
+ {
+ value = -1;
+ s = angfsm_build_get_state_by_code (fsm, i);
+ assert (s);
+ toc = fsm->timeouts;
+ while (toc != NULL)
+ {
+ if (s->code == toc->timeout.trans->state->code)
+ {
+ value = toc->timeout.timeout;
+ break;
+ }
+ toc = toc->next;
+ }
+ fprintf (f, "\t%i", value);
+ if (i != fsm->state_nb - 1)
+ fprintf (f, ",");
+ fprintf (f, "\n");
+ }
+ fprintf (f, "};\n\n");
+
+ /* Gen timeout corresponding events array. */
+ fprintf (f, "angfsm_%s_event_t angfsm_%s_timeout_events[angfsm_STATE_%s_NB_] =\n{\n",
+ fsm->name,
+ fsm->name,
+ fsm->name);
+ for (i = 0; i < fsm->state_nb; i++)
+ {
+ value = -1;
+ s = angfsm_build_get_state_by_code (fsm, i);
+ assert (s);
+ toc = fsm->timeouts;
+ while (toc != NULL)
+ {
+ if (s->code == toc->timeout.trans->state->code)
+ {
+ value = toc->timeout.trans->event->code;
+ break;
+ }
+ toc = toc->next;
+ }
+ if (value == -1)
+ fprintf (f, "\t(angfsm_%s_event_t) angfsm_STATE_%s_NB_", fsm->name, fsm->name);
+ else
+ fprintf (f, "\t(angfsm_%s_event_t) %u", fsm->name, value);
+
+ if (i != fsm->state_nb - 1)
+ fprintf (f, ",");
+ fprintf (f, "\n");
+ }
+ fprintf (f, "};\n\n");
+
+ /* Gen handle timeout function. */
+ fprintf (f, "int\nangfsm_%s_handle_timeout ()\n{\n",
+ fsm->name);
+ fprintf (f, "\tuint16_t i;\n");
+ fprintf (f, "\tint out = 0;\n");
+ fprintf (f, "\tfor (i = 0; i < angfsm_%s_max_active_states; i++)\n\t{\n",
+ fsm->name);
+ fprintf (f, "\t\tif (angfsm_%s_timeout_counters[i] > 0)\n\t\t{\n",
+ fsm->name);
+ fprintf (f, "\t\t\tangfsm_%s_timeout_counters[i]--;\n",
+ fsm->name);
+ fprintf (f, "\t\t\tif (angfsm_%s_timeout_counters[i] == 0)\n\t\t\t{\n",
+ fsm->name);
+ fprintf (f, "\t\t\t\tangfsm_%s_handle (angfsm_%s_timeout_events[angfsm_%s_active_states[i]]);\n",
+ fsm->name,
+ fsm->name,
+ fsm->name);
+ fprintf (f, "\t\t\t\tout = 1;\n");
+ fprintf (f, "\t\t\t}\n");
+ fprintf (f, "\t\t}\n");
+ fprintf (f, "\t}\n");
+ fprintf (f, "\treturn out;\n");
+ fprintf (f, "}\n\n");
+ }
+
+ /* Close file. */
+ fclose (f);
+ free (fn);
+}
+
+void
+angfsm_build_gen_c (angfsm_build_t *fsm,
+ angfsm_build_arch_t arch)
+{
+ /* TODO: make a generic code generator. */
+ assert (arch < ANGFSM_BUILD_ARCH_NB);
+
+ switch (arch)
+ {
+ case ANGFSM_BUILD_ARCH_HOST:
+ angfsm_build_gen_no_opti_c (fsm, arch);
+ break;
+ case ANGFSM_BUILD_ARCH_AVR:
+ angfsm_build_gen_opti_avr_c (fsm, arch);
+ break;
+ case ANGFSM_BUILD_ARCH_ARM:
+ angfsm_build_gen_no_opti_c (fsm, arch);
+ break;
+ default:
+ assert (1);
+ }
+}
+
+void
+angfsm_build_gen_h (angfsm_build_t *fsm,
+ angfsm_build_arch_t arch)
+{
+ /* TODO: make a generic code generator. */
+ assert (arch < ANGFSM_BUILD_ARCH_NB);
+
+ switch (arch)
+ {
+ case ANGFSM_BUILD_ARCH_HOST:
+ angfsm_build_gen_no_opti_h (fsm, arch);
+ break;
+ case ANGFSM_BUILD_ARCH_AVR:
+ angfsm_build_gen_opti_avr_h (fsm, arch);
+ break;
+ case ANGFSM_BUILD_ARCH_ARM:
+ angfsm_build_gen_no_opti_h (fsm, arch);
+ break;
+ default:
+ assert (1);
+ }
+}
+
+void
+angfsm_build_gen (char *arch_string)
+{
+ angfsm_build_chain_t *curs = angfsm_build_all_fsm;
+ angfsm_build_arch_t arch = ANGFSM_BUILD_ARCH_NB;
+ uint i;
+ for (i = 0; i < ANGFSM_BUILD_ARCH_NB; i++)
+ if (strcmp (arch_string, angfsm_build_arch_name[i]) == 0)
+ {
+ arch = (angfsm_build_arch_t) i;
+ break;
+ }
+ if (arch == ANGFSM_BUILD_ARCH_NB)
+ {
+ fprintf (stderr, "Warning, architecture didn't match for \"%s\".\n",
+ arch_string);
+ return;
+ }
+
+ while (curs != NULL)
+ {
+ angfsm_build_gen_h (curs->fsm, arch);
+ angfsm_build_gen_c (curs->fsm, arch);
+ curs = curs->next;
+ }
+
+}
+
+void
+angfsm_build_free (angfsm_build_t *fsm)
+{
+ angfsm_build_state_chain_t *sc;
+ angfsm_build_state_chain_t *sc_tmp;
+ angfsm_build_event_chain_t *ec;
+ angfsm_build_event_chain_t *ec_tmp;
+ angfsm_build_trans_chain_t *tc;
+ angfsm_build_trans_chain_t *tc_tmp;
+ angfsm_build_branch_chain_t *bc;
+ angfsm_build_branch_chain_t *bc_tmp;
+ angfsm_trans_func_chain_t *fc;
+ angfsm_trans_func_chain_t *fc_tmp;
+ angfsm_build_timeout_chain_t *toc;
+ angfsm_build_timeout_chain_t *toc_tmp;
+ uint i;
+
+ /* Free states. */
+ sc = fsm->states;
+ while (sc != NULL)
+ {
+ sc_tmp = sc;
+ free (sc->state.var_name);
+ sc = sc->next;
+ free (sc_tmp);
+ }
+
+ /* Free events. */
+ ec = fsm->events;
+ while (sc != NULL)
+ {
+ ec_tmp = ec;
+ free (ec->event.var_name);
+ ec = ec->next;
+ free (ec_tmp);
+ }
+
+ /* Free trans */
+ tc = fsm->trans;
+ while (tc != NULL)
+ {
+ tc_tmp = tc;
+
+ /* Free each branches. */
+ bc = tc->trans.output_branches;
+ while (bc != NULL)
+ {
+ bc_tmp = bc;
+ free (bc->name);
+ bc = bc->next;
+ free (bc_tmp);
+ }
+
+ tc = tc->next;
+ free (tc_tmp);
+ }
+
+ /* Free start chain. */
+ sc = fsm->starters;
+ while (sc != NULL)
+ {
+ sc_tmp = sc;
+ sc = sc->next;
+ free (sc_tmp);
+ }
+
+ /* Free timeout chain. */
+ toc = fsm->timeouts;
+ while (toc != NULL)
+ {
+ toc_tmp = toc;
+ toc = toc->next;
+ free (toc_tmp);
+ }
+
+ /* Free run data (trans_table). */
+ for (i = 0; i < fsm->event_nb; i++)
+ free (fsm->run.trans_table[i]);
+ free (fsm->run.trans_table);
+
+ /* Free run data (active states). */
+ free (fsm->run.active_states);
+
+ /* Free last-seen event array*/
+ free (fsm->run.events_before_active_state);
+
+ /* Free run data (function pool). */
+ fc = fsm->run.func_pool;
+ while (fc != NULL)
+ {
+ fc_tmp = fc;
+ fc = fc->next;
+ free (fc_tmp);
+ }
+
+ /*Free run data (timeout counters). */
+ free (fsm->run.timeout_counters);
+}
+
+#endif /* HOST */
diff --git a/digital/ai/src/fsm/angfsm_generic.h b/digital/ai/src/fsm/angfsm_generic.h
new file mode 100644
index 00000000..4e1c589f
--- /dev/null
+++ b/digital/ai/src/fsm/angfsm_generic.h
@@ -0,0 +1,89 @@
+/*
+ AngFSM - Almost Non Generated Finite State Machine
+ Copyright 2011, 2012 Jerome Jutteau
+
+ This file is part of AngFSM.
+
+ AngFSM is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ AngFSM 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 Lesser General Public License
+ along with AngFSM. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ You may not include this file in your code, this step is done by angfsm.h
+ */
+
+#ifndef __GENERIC_ARCH__
+#define __GENERIC_ARCH__
+
+/* Disable init macro. */
+#define ANGFSM_INIT
+
+/** Disable options passing. */
+#define ANGFSM_OPTIONS(argc, argv) (0)
+
+/* Disable code generation macro. */
+#define ANGFSM_GENERATE(arch, string)
+
+/* Disable ANGFSM_IMPORT macro. */
+#define ANGFSM_IMPORT(fsm_name)
+
+/** Immediatly handle an event by the fsm. */
+#define ANGFSM_HANDLE(fsm, event) angfsm_##fsm##_handle (angfsm_EVENT_##fsm##_##event)
+
+/** Says if an event can actually be handle or not by the fsm. */
+#define ANGFSM_CAN_HANDLE(fsm, event) angfsm_##fsm##_can_handle \
+ (angfsm_EVENT_##fsm##_##event)
+
+/** Reset fsm to it's initial state. */
+#define ANGFSM_RESET(fsm) angfsm_##fsm##_init ();
+
+/** Disable dot generation. */
+#define ANGFSM_GEN_DOT(fsm, output)
+
+/** Disable state defining
+ *
+ * Define states of the fsm, can be called several times to add other states. */
+#define ANGFSM_STATES(states...)
+
+/** Disable event defining */
+#define ANGFSM_EVENTS(events...)
+
+/** Disable macro. */
+#define ANGFSM_START_WITH(starters...)
+
+#define ANGFSM_TRANS(state, event, output_branches...) \
+ ANGFSM_PASTE3_EXPAND (angfsm_, ANGFSM_NAME,_branch_t) \
+ ANGFSM_PASTE3_EXPAND (angfsm_, ANGFSM_NAME,_trans_func_##state##_##event) ()
+
+#define ANGFSM_NEXT(state, event, branch...) \
+ ANGFSM_PASTE3_EXPAND (angfsm_BRANCH_, ANGFSM_NAME,_##state##_##event##_##branch)
+
+/** Transform an event in uint16_t. */
+#define ANGFSM_EVENT(fsm, event) angfsm_EVENT_##fsm##_##event
+
+/** Handle event from uint16_t. */
+#define ANGFSM_HANDLE_VAR(fsm, event) angfsm_##fsm##_handle (event)
+
+/* Can we handle event from uint16_t ? */
+#define ANGFSM_CAN_HANDLE_VAR(fsm, event) angfsm_##fsm##_can_handle (event)
+
+/* Time out macros. */
+#define ANGFSM_TRANS_TIMEOUT(state, timeout, output_branches...) \
+ ANGFSM_TRANS (state, state##_TIMEOUT, output_branches)
+
+#define ANGFSM_NEXT_TIMEOUT(state, branch...) \
+ ANGFSM_NEXT (state, state##_TIMEOUT, branch)
+
+#define ANGFSM_HANDLE_TIMEOUT(fsm_name) angfsm_##fsm_name##_handle_timeout ()
+
+#endif \ No newline at end of file
diff --git a/digital/ai/src/fsm/angfsm_host_exec.h b/digital/ai/src/fsm/angfsm_host_exec.h
new file mode 100644
index 00000000..956ef4ed
--- /dev/null
+++ b/digital/ai/src/fsm/angfsm_host_exec.h
@@ -0,0 +1,525 @@
+/*
+ AngFSM - Almost Non Generated Finite State Machine
+ Copyright 2011, 2012 Jerome Jutteau
+
+ This file is part of AngFSM.
+
+ AngFSM is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ AngFSM 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 Lesser General Public License
+ along with AngFSM. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ You may not include this file in your code, this step is done by angfsm.h
+ */
+
+#ifndef __HOST_EXEC__
+#define __HOST_EXEC__
+
+#include <stdlib.h>
+#include <stdio.h>
+
+typedef enum {
+ ANGFSM_BUILD_ARCH_HOST,
+ ANGFSM_BUILD_ARCH_AVR,
+ ANGFSM_BUILD_ARCH_ARM,
+ ANGFSM_BUILD_ARCH_NB,
+} angfsm_build_arch_t;
+
+extern const char *angfsm_build_arch_name[ANGFSM_BUILD_ARCH_NB];
+
+typedef struct {
+ int embedded_strings;
+ int sanity_check;
+ char *gen_dot;
+ char *gen_code;
+ int print_trans;
+} angfsm_build_user_options_t;
+
+/* Describe an event. */
+typedef struct {
+ /* Name of the event. */
+ char *var_name;
+ /* Unique code of the event. */
+ uint code;
+} angfsm_build_event_t;
+
+/* Chain of events. */
+typedef struct angfsm_build_event_chain_t {
+ angfsm_build_event_t event;
+ struct angfsm_build_event_chain_t *next;
+} angfsm_build_event_chain_t;
+
+/* Describe a state. Same as event. */
+typedef angfsm_build_event_t angfsm_build_state_t;
+
+/* Chain of state */
+typedef struct angfsm_build_state_chain_t {
+ angfsm_build_state_t state;
+ struct angfsm_build_state_chain_t *next;
+} angfsm_build_state_chain_t;
+
+/**
+ * Describe a branch. It is the output of a transition.
+ * Branches can be chained when there are several possible output state for
+ * one event.
+ */
+typedef struct angfsm_build_branch_chain_t {
+ /* Pointer to the output state of the branch. */
+ angfsm_build_state_t *state;
+ /* Name of the branch. */
+ char *name;
+ /* Pointer to the next branch when we have the choice of the output */
+ struct angfsm_build_branch_chain_t *next;
+} angfsm_build_branch_chain_t;
+
+/**
+ * Describe a transition.
+ * When an event occurs, an active state may react to this event an execute a
+ * transition. The transition function returns the new state which become
+ * active.
+ */
+typedef struct {
+ /* Active state. */
+ angfsm_build_state_t *state;
+ /* Active event. */
+ angfsm_build_event_t *event;
+ /* Possible states the transition will return. */
+ angfsm_build_branch_chain_t *output_branches;
+} angfsm_build_trans_t;
+
+/* Chain of transitions. */
+typedef struct angfsm_build_trans_chain_t {
+ angfsm_build_trans_t trans;
+ struct angfsm_build_trans_chain_t *next;
+} angfsm_build_trans_chain_t;
+
+/* Pointer to a transition function. */
+typedef angfsm_build_state_t* (*angfsm_build_run_strans_func_t)(void);
+
+/* Chain of transitions with associated function's pointer. */
+typedef struct angfsm_trans_func_chain_t {
+ angfsm_build_run_strans_func_t func;
+ angfsm_build_trans_t trans;
+ struct angfsm_trans_func_chain_t *next;
+} angfsm_trans_func_chain_t;
+
+/* Timeout structure. */
+typedef struct angfsm_build_timeout_t {
+ uint timeout;
+ angfsm_build_trans_t *trans;
+} angfsm_build_timeout_t;
+
+/* Chain of angfsm_timeout_t. */
+typedef struct angfsm_build_timeout_chain_t {
+ angfsm_build_timeout_t timeout;
+ struct angfsm_build_timeout_chain_t *next;
+} angfsm_build_timeout_chain_t;
+
+/* Data needed for fsm execution (for host). */
+typedef struct {
+ /* This table store pointers of aff all transition functions. The first
+ * dimension correspond to the events and the second to the states. If
+ * there is no transition of a event/state couple, NULL is set. This
+ * permit to react quickly to an event during execution but is not the
+ * best for memory cost.
+ */
+ angfsm_build_run_strans_func_t **trans_table;
+ /* Store pointer to active states. */
+ angfsm_build_state_t **active_states;
+ /* This array has the size of active_states and store the event who has
+ * triggered the corresponding active state. This is used for dot
+ * generation for visual purposes.
+ */
+ angfsm_build_event_t **events_before_active_state;
+ /* Store all pointers of transition functions. */
+ angfsm_trans_func_chain_t *func_pool;
+ /* Array of counters for timeout events.
+ * -1 mean counter is off. */
+ int *timeout_counters;
+} angfsm_build_run_t;
+
+/* Store all Finite State Machine (fsm) informations. */
+typedef struct {
+ /* All events. */
+ angfsm_build_event_chain_t *events;
+ /* All states. */
+ angfsm_build_state_chain_t *states;
+ /* All transitions. */
+ angfsm_build_trans_chain_t *trans;
+ /* Name of the fsm. */
+ char *name;
+ /* Maximal number of active states. */
+ uint max_active_states;
+ /* Total number of events. */
+ uint event_nb;
+ /* Total number of states. */
+ uint state_nb;
+ /* First active states. */
+ angfsm_build_state_chain_t *starters;
+ /* All timeout. */
+ angfsm_build_timeout_chain_t *timeouts;
+ /* Data for running purposes. */
+ angfsm_build_run_t run;
+ /* User's options. */
+ angfsm_build_user_options_t options;
+} angfsm_build_t;
+
+/* Store all fsm in a chain. */
+typedef struct angfsm_build_chain_t {
+ angfsm_build_t *fsm;
+ struct angfsm_build_chain_t *next;
+} angfsm_build_chain_t;
+
+/* Store all fsm. */
+extern angfsm_build_chain_t *fsm_build_all_fsm;
+/* Function to initialize angfsm_build_all_fsm. */
+void angfsm_build_init_all_fsm() __attribute__((constructor(101)));
+
+/** Create the fsm and functions who will be executed before and after main
+ * function. This permits initilialization of the fsm. */
+extern angfsm_build_t ANGFSM_PASTE_EXPAND(angfsm_, ANGFSM_NAME);
+void ANGFSM_PASTE_EXPAND(angfsm_build_init_, ANGFSM_NAME)() __attribute__((constructor(102)));
+void ANGFSM_PASTE_EXPAND(angfsm_build_run_init_, ANGFSM_NAME)() __attribute__((constructor(107)));
+void ANGFSM_PASTE_EXPAND(angfsm_build_free_, ANGFSM_NAME)() __attribute__((destructor));
+
+#define ANGFSM_INIT \
+ angfsm_build_t ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME); \
+ void ANGFSM_PASTE_EXPAND (angfsm_build_init_, ANGFSM_NAME)() \
+ { \
+ angfsm_build_init (ANGFSM_PASTE_EXPAND (&angfsm_, ANGFSM_NAME), XSTR(ANGFSM_NAME)); \
+ } \
+ void ANGFSM_PASTE_EXPAND (angfsm_build_run_init_, ANGFSM_NAME)() \
+ { \
+ angfsm_build_run_init (& ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME)); \
+ } \
+ void ANGFSM_PASTE_EXPAND (angfsm_build_free_, ANGFSM_NAME)() \
+ { \
+ angfsm_build_free (& ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME)); \
+ }
+
+#define ANGFSM_IMPORT(fsm_name) \
+extern angfsm_build_t angfsm_##fsm_name;
+
+/** Pass options to angfsm though argc and argv. */
+#define ANGFSM_OPTIONS(argc, argv) angfsm_build_options (argc, argv)
+
+/** Generate source ou header files for the specific architecture */
+#define ANGFSM_GENERATE(arch, string) angfsm_build_gen (#arch, string)
+
+/** Immediatly handle an event by the fsm. */
+#define ANGFSM_HANDLE(fsm, event) angfsm_build_handle_string (&angfsm_##fsm , #event)
+
+/** Says if an event can actually be handle or not by the fsm. */
+#define ANGFSM_CAN_HANDLE(fsm, event) \
+ angfsm_build_can_handle_string (&angfsm_##fsm, #event)
+
+/** Reset fsm to it's initial state. */
+#define ANGFSM_RESET(fsm) angfsm_build_reset (&angfsm_##fsm)
+
+/** Generate dot. */
+#define ANGFSM_GEN_DOT(fsm, output) angfsm_build_gen_dot (&angfsm_##fsm, output)
+
+/** Define states of the fsm, can be called several times to add other states. */
+#define ANGFSM_STATES(states...) \
+ void ANGFSM_PASTE3_EXPAND (fsm_build_states_, ANGFSM_NAME, FIRST (states)) () \
+ __attribute__((constructor(103)));\
+ void ANGFSM_PASTE3_EXPAND (fsm_build_states_, ANGFSM_NAME, FIRST (states)) () \
+ { \
+ angfsm_build_states (& ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME), #states); \
+ }
+
+/** Define events of the fsm, can be called several times to add other events. */
+#define ANGFSM_EVENTS(events...) \
+ void ANGFSM_PASTE3_EXPAND (fsm_build_events_, ANGFSM_NAME, FIRST (events)) () \
+ __attribute__((constructor(103)));\
+ void ANGFSM_PASTE3_EXPAND (fsm_build_events_, ANGFSM_NAME, FIRST (events)) () \
+ { \
+ angfsm_build_events (& ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME), #events); \
+ }
+
+/** Define wich state(s) will be active at the beginning. */
+#define ANGFSM_START_WITH(starters...) \
+ void ANGFSM_PASTE3_EXPAND (fsm_build_start_with_, ANGFSM_NAME, FIRST (starters))() __attribute__((constructor(104))); \
+ void ANGFSM_PASTE3_EXPAND (fsm_build_start_with_, ANGFSM_NAME, FIRST (starters))() \
+ { \
+ angfsm_build_start_with (& ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME), #starters); \
+ }
+
+/**
+ * Define a transition by giving a state, an event and:
+ * - a event if the transition returns only one state.
+ * - branches if the transition returns different states.
+ * See examples for reel usage.
+ */
+#define ANGFSM_TRANS(state, event, output_branches...) \
+angfsm_build_state_t* ANGFSM_PASTE3_EXPAND (angfsm_trans_, ANGFSM_NAME,_##state##_##event) (); \
+ void ANGFSM_PASTE3_EXPAND (angfsm_build_trans_, ANGFSM_NAME,_##state##_##event)() __attribute__((constructor(105))); \
+ void ANGFSM_PASTE3_EXPAND (angfsm_build_trans_, ANGFSM_NAME,_##state##_##event)() \
+ { \
+ angfsm_build_trans (& ANGFSM_PASTE_EXPAND(angfsm_, ANGFSM_NAME), #state, #event, \
+ #output_branches, \
+ & ANGFSM_PASTE3_EXPAND (angfsm_trans_, ANGFSM_NAME,_##state##_##event)); \
+ } \
+ angfsm_build_state_t* ANGFSM_PASTE3_EXPAND (angfsm_trans_, ANGFSM_NAME,_##state##_##event) ()
+
+/**
+ * Used to return next state by giving the actual transition informations and
+ * the branch (if there are several branches).
+ * Not directly returning the state can avoid some errors. *
+ */
+#define ANGFSM_NEXT(state, event, branch...) \
+ angfsm_build_get_next_state (& ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME), #state, #event, #branch)
+
+/**
+ * Define a transition when a state times out.
+ * You have to provide a state, a timeout value and:
+ * - a event if the transition returns only one state.
+ * - branches if the transition returns different states.
+ * See examples for reel usage.
+ */
+#define ANGFSM_TRANS_TIMEOUT(state, timeout, output_branches...) \
+ void ANGFSM_PASTE3_EXPAND (angfsm_build_timeout_, ANGFSM_NAME,_##state##_TIMEOUT)() __attribute__((constructor(106))); \
+ void ANGFSM_PASTE3_EXPAND (angfsm_build_timeout_, ANGFSM_NAME,_##state##_TIMEOUT)() \
+ { \
+ angfsm_build_timeout (& ANGFSM_PASTE_EXPAND(angfsm_, ANGFSM_NAME), #state, XSTR(state##_TIMEOUT), timeout); \
+ } \
+ ANGFSM_EVENTS (state##_TIMEOUT) \
+ ANGFSM_TRANS (state, state##_TIMEOUT, output_branches)
+
+/**
+ * Used to return next state after a timeout.
+ * Same as ANGFSM_NEXT but without specifying an event.
+ */
+#define ANGFSM_NEXT_TIMEOUT(state, branch...) \
+ ANGFSM_NEXT (state, state##_TIMEOUT, branch)
+
+/** Used to handle timeout events. */
+#define ANGFSM_HANDLE_TIMEOUT(fsm_name) \
+ angfsm_build_handle_timeout (& ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME))
+
+/** Transform an event in uint16_t. */
+#define ANGFSM_EVENT(fsm_name, event) \
+ angfsm_build_get_event_code (& ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME), #event)
+
+/** Handle event from uint16_t. */
+#define ANGFSM_HANDLE_VAR(fsm, event) \
+ angfsm_build_handle_integer (& ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME), event)
+
+/* Can we handle event from uint16_t ? */
+#define ANGFSM_CAN_HANDLE_VAR(fSM, event) \
+ angfsm_build_can_handle_integer (& ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME), event)
+
+/**
+ * Parse a string who contains a list of arguments separated by comma.
+ * It will create and store each parameters (without space and ") in an array
+ * and give the number of parsed arguments.
+ * \param string string to parse
+ * \param tab pointer to a table of strings where to store the array
+ * \param nb pointer where to store the number of parsed arguments
+ */
+void
+angfsm_build_arg_parse(char *string, char ***tab, int *nb);
+
+/**
+ * Free an array of strings generated by angfsm_build_arg_parse.
+ * \param tab pointer to the array of strings
+ * \param nb number of arguments stored in the array.
+ */
+void
+angfsm_build_arg_free(char ***tab, int nb);
+
+/**
+ * This function is executed when a state is returned by a transition.
+ * \param fsm fsm
+ * \param trans transition where the return occurs
+ * \param branch branch to transition has chosen.
+ */
+void
+angfsm_build_print(angfsm_build_t *fsm,
+ angfsm_build_trans_t* trans,
+ angfsm_build_branch_chain_t* branch);
+
+/**
+ * Test the fsm and search for errors.
+ */
+void
+angfsm_build_sanity_check(angfsm_build_t *fsm);
+
+/** Reset the fsm to it's initial state. */
+void
+angfsm_build_reset(angfsm_build_t *fsm);
+
+/** Generate the dot file of the actual fsm state.
+ * \param fsm fsm
+ * \param output output file name. If empty or NULL, it will generate a file
+ * like "angfsm_{FSM NAME}.dot" .
+ */
+void
+angfsm_build_gen_dot(angfsm_build_t *fsm, char *output);
+
+/** Initialize the fsm. */
+void
+angfsm_build_init(angfsm_build_t *fsm, char *name);
+
+/** Initialize the running data of the fsm. */
+void
+angfsm_build_run_init(angfsm_build_t *fsm);
+
+/**
+ * Add some states to the fsm.
+ * \param fsm fsm
+ * \param states states separated by comma
+ **/
+void
+angfsm_build_states(angfsm_build_t *fsm, char *states);
+
+/**
+ * Add some events to the fsm.
+ * \param fsm fsm
+ * \param events events separated by comma
+ **/
+void
+angfsm_build_events(angfsm_build_t *fsm, char *events);
+
+/** Get event's pointer by giving it's name. */
+angfsm_build_event_t*
+angfsm_build_get_event(angfsm_build_t *fsm, char *event);
+
+/** Get state's pointer by giving it's name. */
+angfsm_build_state_t*
+angfsm_build_get_state(angfsm_build_t *fsm, char *state);
+
+/** Get event's pointer by giving it's code. */
+angfsm_build_event_t*
+angfsm_build_get_event_by_code(angfsm_build_t *fsm, uint event);
+
+/** Get state's pointer by giving it's code. */
+angfsm_build_state_t*
+angfsm_build_get_state_by_code(angfsm_build_t *fsm, uint state);
+
+/** Get event code as uint16_t */
+uint16_t
+angfsm_build_get_event_code(angfsm_build_t *fsm, char *event);
+
+/**
+ * Add a transition to the fsm.
+ * \param fsm fsm
+ * \param state state who will be active for the transition
+ * \param event event to react
+ * \param output_branches list of output branches seperated by comma or a
+ * single state (if there is only one branche).
+ * For example:
+ * - If the transition return a single state, it will be "stateX"
+ * - If the transition can return different states, it will be
+ * "branch1, state1, branch2, state2, branch3, state3" [...]
+ * \param trans_func pointer to the transition function.
+ */
+void
+angfsm_build_trans(angfsm_build_t *fsm,
+ char *state,
+ char *event,
+ char *output_branches,
+ angfsm_build_run_strans_func_t trans_func);
+
+/* Create transition based on a timeout.
+ * \param fsm fsm
+ * \param state state who times out
+ * \param event name of the timeout (specific to this state and described in
+ macro)
+ * \param timeout value of timeout
+ */
+void
+angfsm_build_timeout(angfsm_build_t *fsm, char *state, char *event, uint timeout);
+
+/**
+ * Define with which states the fsm will start.
+ * \param fsm fsm
+ * \param starters list of states seperated by comma
+ */
+void
+angfsm_build_start_with(angfsm_build_t *fsm, char *starters);
+
+/** Handle an event by the fsm.
+ * \param fsm fsm
+ * \param event event to handle with fsm
+ * \return zero if event is not handled at all, one otherwise
+ **/
+int
+angfsm_build_handle(angfsm_build_t *fsm, angfsm_build_event_t *event);
+int
+angfsm_build_handle_string(angfsm_build_t *fsm, char *event);
+int
+angfsm_build_handle_integer(angfsm_build_t *fsm, uint16_t event);
+
+/**
+ * Say if the event can be handled or not.
+ * \param fsm fsm
+ * \param event event to test with the fsm
+ * \return zero if the event can be handled, non-zero otherwhise
+ */
+int
+angfsm_build_can_handle(angfsm_build_t *fsm, angfsm_build_event_t *event);
+int
+angfsm_build_can_handle_string(angfsm_build_t *fsm, char *event);
+int
+angfsm_build_can_handle_integer(angfsm_build_t *fsm, uint16_t event);
+
+/**
+ * Handle timeout events of the fsm.
+ * \param fsm fsm
+ * \return one if an event has been handled, zero otherwise
+ */
+int
+angfsm_build_handle_timeout(angfsm_build_t *fsm);
+
+/** Give the state at the transition output. */
+angfsm_build_state_t*
+angfsm_build_get_next_state(angfsm_build_t *fsm,
+ char *state,
+ char *event,
+ char *branch);
+
+/** Pass parameters to AngFSM at execution. Try --ang-help
+ * \param argc argc from your main.
+ * \param argv argv from your main.
+ * \return different from zero if any argument has been used, zero otherwhise.
+ * */
+int
+angfsm_build_options(int argc, char **argv);
+
+/**
+ * Generate header file for target which provides more optimised version of
+ * fsm execution
+ * \param arch specify generated architecture by it's string.
+ * embedded).
+ */
+void
+angfsm_build_gen(char *arch);
+void
+angfsm_build_gen_no_opti_h(angfsm_build_t *fsm, angfsm_build_arch_t arch);
+void
+angfsm_build_gen_no_opti_c(angfsm_build_t *fsm, angfsm_build_arch_t arch);
+void
+angfsm_build_gen_opti_avr_h(angfsm_build_t *fsm, angfsm_build_arch_t arch);
+void
+angfsm_build_gen_opti_avr_c(angfsm_build_t *fsm, angfsm_build_arch_t arch);
+
+/** Free fsm allocated data. */
+void
+angfsm_build_free(angfsm_build_t *fsm);
+
+/** Print help. */
+void
+angfsm_build_print_help();
+
+#endif
diff --git a/digital/ai/src/fsm/angfsm_renaming.h b/digital/ai/src/fsm/angfsm_renaming.h
new file mode 100644
index 00000000..393fad42
--- /dev/null
+++ b/digital/ai/src/fsm/angfsm_renaming.h
@@ -0,0 +1,45 @@
+/*
+ AngFSM - Almost Non Generated Finite State Machine
+ Copyright 2011, 2012 Jerome Jutteau
+
+ This file is part of AngFSM.
+
+ AngFSM is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ AngFSM 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 Lesser General Public License
+ along with AngFSM. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ANGFSM_RENAME_
+#define _ANGFSM_RENAME_
+
+#define FSM_INIT ANGFSM_INIT
+#define FSM_OPTIONS ANGFSM_OPTIONS
+#define FSM_GENERATE ANGFSM_GENERATE
+#define FSM_IMPORT ANGFSM_IMPORT
+#define FSM_HANDLE ANGFSM_HANDLE
+#define FSM_CAN_HANDLE ANGFSM_CAN_HANDLE
+#define FSM_RESET ANGFSM_RESET
+#define FSM_GEN_DOTANGFSM_GEN_DOT
+#define FSM_STATES ANGFSM_STATES
+#define FSM_EVENTS ANGFSM_EVENTS
+#define FSM_START_WITH ANGFSM_START_WITH
+#define FSM_TRANS ANGFSM_TRANS
+#define FSM_NEXT ANGFSM_NEXT
+#define FSM_EVENT ANGFSM_EVENT
+#define FSM_HANDLE_VAR ANGFSM_HANDLE_VAR
+#define FSM_CAN_HANDLE_VAR ANGFSM_CAN_HANDLE_VAR
+#define FSM_TRANS_TIMEOUT ANGFSM_TRANS_TIMEOUT
+#define FSM_NEXT_TIMEOUT ANGFSM_NEXT_TIMEOUT
+#define FSM_HANDLE_TIMEOUT ANGFSM_HANDLE_TIMEOUT
+
+
+#endif /* #ifdef _ANGFSM_RENAME_ */
diff --git a/digital/ai/src/fsm/fsm.h b/digital/ai/src/fsm/fsm.h
deleted file mode 100644
index 6b376d30..00000000
--- a/digital/ai/src/fsm/fsm.h
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- AngFSM - AngFSM - Almost Non Generated Finite State Machine
-
- Copyright 2011 Jerome Jutteau
-
-Contact:
- * email: j.jutteau _AT_ gmail _DOT_ com
- * website: http://fuu.im/angfsm/
-
- This file is part of AngFSM.
-
- AngFSM 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.
-
- AngFSM 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 AngFSM. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <inttypes.h>
-
-#ifndef _FSM_GEN_
-#define _FSM_GEN_
-
-#ifndef FSM_NAME
-#define FSM_NAME FSM
-#endif
-
-#define XSTR(s) STR(s)
-#define STR(s) #s
-#define FSM_PASTE(a, b) a ## b
-#define FSM_PASTE_EXPAND(a, b) FSM_PASTE (a, b)
-#define FSM_PASTE3_EXPAND(a, b, c)\
- FSM_PASTE_EXPAND (a, FSM_PASTE_EXPAND (b, c))
-#define FIRST(first, others...) first
-
-#ifdef __AVR_ARCH__
-/* Include generated header. */
-#include XSTR (FSM_PASTE_EXPAND (fsm_, FSM_NAME)_gen.h)
-
-/* Disable init macro. */
-#define FSM_INIT
-
-/* Disable code generation macro. */
-#define FSM_GENERATE(arch, string)
-
-/* Disable FSM_IMPORT macro. */
-#define FSM_IMPORT(fsm_name)
-
-/** Immediatly handle an event by the fsm. */
-#define FSM_HANDLE(fsm, event) fsm_##fsm##_handle (FSM_EVENT_##fsm##_##event )
-
-/** Says if an event can actually be handle or not by the fsm. */
-#define FSM_CAN_HANDLE(fsm, event) fsm_##fsm##_can_handle \
- (FSM_EVENT_##fsm##_##event)
-
-/** Reset fsm to it's initial state. */
-#define FSM_RESET(fsm) fsm_##fsm##_init ();
-
-/** Disable dot generation. */
-#define FSM_GEN_DOT(fsm)
-
-/** Disable state defining
- *
- * Define states of the fsm, can be called several times to add other states. */
-#define FSM_STATES(states...)
-
-/** Disable event defining */
-#define FSM_EVENTS(events...)
-
-/** Disable macro. */
-#define FSM_START_WITH(starters...)
-
-#define FSM_TRANS(state, event, output_branches...)\
- FSM_PASTE3_EXPAND (fsm_, FSM_NAME,_branch_t)\
-FSM_PASTE3_EXPAND (fsm_, FSM_NAME,_trans_func_##state##_##event) ()
-
-#define FSM_NEXT(state, event, branch...)\
- FSM_PASTE3_EXPAND (FSM_BRANCH_, FSM_NAME,_##state##_##event##_##branch)
-
-/** Transform an event in uint16_t. */
-#define FSM_EVENT(fsm, event) FSM_EVENT_##fsm##_##event
-
-/** Handle event from uint16_t. */
-#define FSM_HANDLE_VAR(fsm, event) fsm_##fsm##_handle (event)
-
-/* Can we handle event from uint16_t ? */
-#define FSM_CAN_HANDLE_VAR(fsm, event) fsm_##fsm##_can_handle (event)
-
-/* Time out macros. */
-#define FSM_TRANS_TIMEOUT(state, timeout, output_branches...)\
- FSM_TRANS (state, state##_TIMEOUT, output_branches)
-
-#define FSM_NEXT_TIMEOUT(state, branch...)\
- FSM_NEXT (state, state##_TIMEOUT, branch)
-
-#define FSM_HANDLE_TIMEOUT(fsm_name) fsm_##fsm_name##_handle_timeout ()
-
-#else /* Compiling for HOST */
-#include <stdlib.h>
-
-/* Describe an event. */
-typedef struct
-{
- /* Name of the event. */
- char *var_name;
- /* Unique code of the event. */
- uint code;
-} fsm_build_event_t;
-
-/* Chain of events. */
-typedef struct fsm_build_event_chain_t
-{
- fsm_build_event_t event;
- struct fsm_build_event_chain_t *next;
-} fsm_build_event_chain_t;
-
-/* Describe a state. Same as event. */
-typedef fsm_build_event_t fsm_build_state_t;
-
-/* Chain of state */
-typedef struct fsm_build_state_chain_t
-{
- fsm_build_state_t state;
- struct fsm_build_state_chain_t *next;
-} fsm_build_state_chain_t;
-
-/**
- * Describe a branch. It is the output of a transition.
- * Branches can be chained when there are several possible output state for
- * one event.
- */
-typedef struct fsm_build_branch_chain_t
-{
- /* Pointer to the output state of the branch. */
- fsm_build_state_t *state;
- /* Name of the branch. */
- char *name;
- /* Pointer to the next branch when we have the choice of the output */
- struct fsm_build_branch_chain_t *next;
-} fsm_build_branch_chain_t;
-
-/**
- * Describe a transition.
- * When an event occurs, an active state may react to this event an execute a
- * transition. The transition function returns the new state which become
- * active.
- */
-typedef struct
-{
- /* Active state. */
- fsm_build_state_t *state;
- /* Active event. */
- fsm_build_event_t *event;
- /* Possible states the transition will return. */
- fsm_build_branch_chain_t *output_branches;
-} fsm_build_trans_t;
-
-/* Chain of transitions. */
-typedef struct fsm_build_trans_chain_t
-{
- fsm_build_trans_t trans;
- struct fsm_build_trans_chain_t *next;
-} fsm_build_trans_chain_t;
-
-/* Pointer to a transition function. */
-typedef fsm_build_state_t* (*fsm_build_run_strans_func_t)(void);
-
-/* Chain of transitions with associated function's pointer. */
-typedef struct fsm_trans_func_chain_t
-{
- fsm_build_run_strans_func_t func;
- fsm_build_trans_t trans;
- struct fsm_trans_func_chain_t *next;
-} fsm_trans_func_chain_t;
-
-/* Timeout structure. */
-typedef struct fsm_build_timeout_t
-{
- uint timeout;
- fsm_build_trans_t *trans;
-} fsm_build_timeout_t;
-
-/* Chain of fsm_timeout_t. */
-typedef struct fsm_build_timeout_chain_t
-{
- fsm_build_timeout_t timeout;
- struct fsm_build_timeout_chain_t *next;
-} fsm_build_timeout_chain_t;
-
-/* Data needed for fsm execution (for host). */
-typedef struct
-{
- /* This table store pointers of aff all transition functions. The first
- * dimension correspond to the events and the second to the states. If
- * there is no transition of a event/state couple, NULL is set. This
- * permit to react quickly to an event during execution but is not the
- * best for memory cost.
- */
- fsm_build_run_strans_func_t **trans_table;
- /* Store pointer to active states. */
- fsm_build_state_t **active_states;
- /* This array has the size of active_states and store the event who has
- * triggered the corresponding active state. This is used for dot
- * generation for visual purposes.
- */
- fsm_build_event_t **events_before_active_state;
- /* Store all pointers of transition functions. */
- fsm_trans_func_chain_t *func_pool;
- /* Array of counters for timeout events.
- * -1 mean counter is off. */
- int *timeout_counters;
-} fsm_build_run_t;
-
-/* Store all Finite State Machine (fsm) informations. */
-typedef struct
-{
- /* All events. */
- fsm_build_event_chain_t *events;
- /* All states. */
- fsm_build_state_chain_t *states;
- /* All transitions. */
- fsm_build_trans_chain_t *trans;
- /* Name of the fsm. */
- char *name;
- /* Maximal number of active states. */
- uint max_active_states;
- /* Total number of events. */
- uint event_nb;
- /* Total number of states. */
- uint state_nb;
- /* First active states. */
- fsm_build_state_chain_t *starters;
- /* All timeout. */
- fsm_build_timeout_chain_t *timeouts;
- /* Data for running purposes. */
- fsm_build_run_t run;
-} fsm_build_t;
-
-/* Store all fsm in a chain. */
-typedef struct fsm_build_chain_t
-{
- fsm_build_t *fsm;
- struct fsm_build_chain_t *next;
-} fsm_build_chain_t;
-
-/* Store all fsm. */
-extern fsm_build_chain_t *fsm_build_all_fsm;
-/* Function to initialize fsm_build_all_fsm. */
-void fsm_build_init_all_fsm () __attribute__((constructor(101)));
-
-/** Create the fsm and functions who will be executed before and after main
- * function. This permits initilialization of the fsm. */
-extern fsm_build_t FSM_PASTE_EXPAND (fsm_, FSM_NAME);
-void FSM_PASTE_EXPAND (fsm_build_init_, FSM_NAME)() __attribute__((constructor(102)));
-void FSM_PASTE_EXPAND (fsm_build_run_init_, FSM_NAME)() __attribute__((constructor(107)));
-void FSM_PASTE_EXPAND (fsm_build_free_, FSM_NAME)() __attribute__((destructor));
-
-#define FSM_INIT\
- fsm_build_t FSM_PASTE_EXPAND (fsm_, FSM_NAME);\
-void FSM_PASTE_EXPAND (fsm_build_init_, FSM_NAME)()\
-{\
- fsm_build_init (FSM_PASTE_EXPAND (&fsm_, FSM_NAME), XSTR(FSM_NAME));\
-}\
-void FSM_PASTE_EXPAND (fsm_build_run_init_, FSM_NAME)()\
-{\
- fsm_build_run_init (& FSM_PASTE_EXPAND (fsm_, FSM_NAME));\
-}\
-void FSM_PASTE_EXPAND (fsm_build_free_, FSM_NAME)()\
-{\
- fsm_build_free (& FSM_PASTE_EXPAND (fsm_, FSM_NAME));\
-}
-
-#define FSM_IMPORT(fsm_name)\
- extern fsm_build_t fsm_##fsm_name;
-
-/** Generate source ou header files for the specific architecture */
-#define FSM_GENERATE(arch, string) fsm_build_gen (#arch, string);
-
-/** Immediatly handle an event by the fsm. */
-#define FSM_HANDLE(fsm, event) fsm_build_handle_string (&fsm_##fsm , #event)
-
-/** Says if an event can actually be handle or not by the fsm. */
-#define FSM_CAN_HANDLE(fsm, event) fsm_build_can_handle_string (&fsm_##fsm, #event)
-
-/** Reset fsm to it's initial state. */
-#define FSM_RESET(fsm) fsm_build_reset (&fsm_##fsm)
-
-/** Generate dot. */
-#define FSM_GEN_DOT(fsm) fsm_build_gen_dot (&fsm_##fsm)
-
-/** Define states of the fsm, can be called several times to add other states. */
-#define FSM_STATES(states...)\
- void FSM_PASTE3_EXPAND (fsm_build_states_, FSM_NAME, FIRST (states)) () __attribute__((constructor(103)));\
-void FSM_PASTE3_EXPAND (fsm_build_states_, FSM_NAME, FIRST (states)) ()\
-{\
- fsm_build_states (& FSM_PASTE_EXPAND (fsm_, FSM_NAME), #states);\
-}
-
-/** Define events of the fsm, can be called several times to add other events. */
-#define FSM_EVENTS(events...)\
- void FSM_PASTE3_EXPAND (fsm_build_events_, FSM_NAME, FIRST (events)) () __attribute__((constructor(103)));\
-void FSM_PASTE3_EXPAND (fsm_build_events_, FSM_NAME, FIRST (events)) ()\
-{\
- fsm_build_events (& FSM_PASTE_EXPAND (fsm_, FSM_NAME), #events);\
-}
-
-/** Define wich state(s) will be active at the beginning. */
-#define FSM_START_WITH(starters...)\
- void FSM_PASTE3_EXPAND (fsm_build_start_with_, FSM_NAME, FIRST (starters))() __attribute__((constructor(104)));\
-void FSM_PASTE3_EXPAND (fsm_build_start_with_, FSM_NAME, FIRST (starters))()\
-{\
- fsm_build_start_with (& FSM_PASTE_EXPAND (fsm_, FSM_NAME), #starters);\
-}
-
-/**
- * Define a transition by giving a state, an event and:
- * - a event if the transition returns only one state.
- * - branches if the transition returns different states.
- * See examples for reel usage.
- */
-#define FSM_TRANS(state, event, output_branches...)\
- fsm_build_state_t* FSM_PASTE3_EXPAND (fsm_trans_, FSM_NAME,_##state##_##event) ();\
-void FSM_PASTE3_EXPAND (fsm_build_trans_, FSM_NAME,_##state##_##event)() __attribute__((constructor(105)));\
-void FSM_PASTE3_EXPAND (fsm_build_trans_, FSM_NAME,_##state##_##event)()\
-{\
- fsm_build_trans (& FSM_PASTE_EXPAND(fsm_, FSM_NAME), #state, #event,\
-#output_branches,\
- & FSM_PASTE3_EXPAND (fsm_trans_, FSM_NAME,_##state##_##event));\
-}\
-fsm_build_state_t* FSM_PASTE3_EXPAND (fsm_trans_, FSM_NAME,_##state##_##event) ()
-
-/**
- * Used to return next state by giving the actual transition informations and
- * the branch (if there are several branches).
- * Not directly returning the state can avoid some errors. *
- */
-#define FSM_NEXT(state, event, branch...)\
- fsm_build_get_next_state (& FSM_PASTE_EXPAND (fsm_, FSM_NAME), #state, #event, #branch)
-
-/**
- * Define a transition when a state times out.
- * You have to provide a state, a timeout value and:
- * - a event if the transition returns only one state.
- * - branches if the transition returns different states.
- * See examples for reel usage.
- */
-#define FSM_TRANS_TIMEOUT(state, timeout, output_branches...)\
- void FSM_PASTE3_EXPAND (fsm_build_timeout_, FSM_NAME,_##state##_TIMEOUT)() __attribute__((constructor(106)));\
-void FSM_PASTE3_EXPAND (fsm_build_timeout_, FSM_NAME,_##state##_TIMEOUT)()\
-{\
- fsm_build_timeout (& FSM_PASTE_EXPAND(fsm_, FSM_NAME), #state, XSTR(state##_TIMEOUT), timeout);\
-}\
-FSM_EVENTS (state##_TIMEOUT)\
-FSM_TRANS (state, state##_TIMEOUT, output_branches)
-
-/**
- * Used to return next state after a timeout.
- * Same as FSM_NEXT but without specifying an event.
- */
-#define FSM_NEXT_TIMEOUT(state, branch...)\
- FSM_NEXT (state, state##_TIMEOUT, branch)
-
-/** Used to handle timeout events. */
-#define FSM_HANDLE_TIMEOUT(fsm_name) fsm_build_handle_timeout (& FSM_PASTE_EXPAND (fsm_, FSM_NAME))
-
-/** Transform an event in uint16_t. */
-#define FSM_EVENT(fsm_name, event) fsm_build_get_event_code (& FSM_PASTE_EXPAND (fsm_, FSM_NAME), #event)
-
-/** Handle event from uint16_t. */
-#define FSM_HANDLE_VAR(fsm, event) fsm_build_handle_integer (& FSM_PASTE_EXPAND (fsm_, FSM_NAME), event)
-
-/* Can we handle event from uint16_t ? */
-#define FSM_CAN_HANDLE_VAR(fSM, event) fsm_build_can_handle_integer (& FSM_PASTE_EXPAND (fsm_, FSM_NAME), event)
-
-/**
- * Parse a string who contains a list of arguments seperated by comma.
- * It will create and store each parameters (without space and ") in an array
- * and give the number of parsed arguments.
- * \param string string to parse
- * \param tab pointer to a table of strings where to store the array
- * \param nb pointer where to store the number of parsed arguments
- */
-void
-fsm_build_arg_parse (char *string, char ***tab, int *nb);
-
-/**
- * Free an array of strings generated by fsm_build_arg_parse.
- * \param tab pointer to the array of strings
- * \param nb number of arguments stored in the array.
- */
-void
-fsm_build_arg_free (char ***tab, int nb);
-
-/**
- * This function is executed when a state is returned by a transition.
- * \param fsm fsm
- * \param trans transition where the return occurs
- * \param branch branch to transition has chosen.
- */
-void
-fsm_build_print (fsm_build_t *fsm,
- fsm_build_trans_t* trans,
- fsm_build_branch_chain_t* branch);
-
-/**
- * Test the fsm and search for errors.
- */
-void
-fsm_build_sanity_check (fsm_build_t *fsm);
-
-/** Reset the fsm to it's initial state. */
-void
-fsm_build_reset (fsm_build_t *fsm);
-
-/** Generate the dot file of the actual fsm state. */
-void
-fsm_build_gen_dot (fsm_build_t *fsm);
-
-/** Initialize the fsm. */
-void
-fsm_build_init (fsm_build_t *fsm, char *name);
-
-/** Initialize the running data of the fsm. */
-void
-fsm_build_run_init (fsm_build_t *fsm);
-
-/**
- * Add some states to the fsm.
- * \param fsm fsm
- * \param states states separated by comma
- **/
-void
-fsm_build_states (fsm_build_t *fsm, char *states);
-
-/**
- * Add some events to the fsm.
- * \param fsm fsm
- * \param events events separated by comma
- **/
-void
-fsm_build_events (fsm_build_t *fsm, char *events);
-
-/** Get event's pointer by giving it's name. */
-fsm_build_event_t*
-fsm_build_get_event (fsm_build_t *fsm, char *event);
-
-/** Get state's pointer by giving it's name. */
-fsm_build_state_t*
-fsm_build_get_state (fsm_build_t *fsm, char *state);
-
-/** Get event's pointer by giving it's code. */
-fsm_build_event_t*
-fsm_build_get_event_by_code (fsm_build_t *fsm, uint event);
-
-/** Get state's pointer by giving it's code. */
-fsm_build_state_t*
-fsm_build_get_state_by_code (fsm_build_t *fsm, uint state);
-
-/** Get event code as uint16_t */
-uint16_t
-fsm_build_get_event_code (fsm_build_t *fsm, char *event);
-
-/**
- * Add a transition to the fsm.
- * \param fsm fsm
- * \param state state who will be active for the transition
- * \param event event to react
- * \param output_branches list of output branches seperated by comma or a
- * single state (if there is only one branche).
- * For example:
- * - If the transition return a single state, it will be "stateX"
- * - If the transition can return different states, it will be
- * "branch1, state1, branch2, state2, branch3, state3" [...]
- * \param trans_func pointer to the transition function.
- */
-void
-fsm_build_trans (fsm_build_t *fsm,
- char *state,
- char *event,
- char *output_branches,
- fsm_build_run_strans_func_t trans_func);
-
-/* Create transition based on a timeout.
- * \param fsm fsm
- * \param state state who times out
- * \param event name of the timeout (specific to this state and described in macro)
- * \param timeout value of timeout
- */
-void
-fsm_build_timeout (fsm_build_t *fsm, char *state, char *event, uint timeout);
-
-/**
- * Define with which states the fsm will start.
- * \param fsm fsm
- * \param starters list of states seperated by comma
- */
-void
-fsm_build_start_with (fsm_build_t *fsm, char *starters);
-
-/** Handle an event by the fsm.
- * \param fsm fsm
- * \param event event to handle with fsm
- * \return zero if event is not handled at all, one otherwise
- **/
-int
-fsm_build_handle (fsm_build_t *fsm, fsm_build_event_t *event);
-int
-fsm_build_handle_string (fsm_build_t *fsm, char *event);
-int
-fsm_build_handle_integer (fsm_build_t *fsm, uint16_t event);
-
-/**
- * Say if the event can be handled or not.
- * \param fsm fsm
- * \param event event to test with the fsm
- * \return zero if the event can be handled, non-zero otherwhise
- */
-int
-fsm_build_can_handle (fsm_build_t *fsm, fsm_build_event_t *event);
-int
-fsm_build_can_handle_string (fsm_build_t *fsm, char *event);
-int
-fsm_build_can_handle_integer (fsm_build_t *fsm, uint16_t event);
-
-/**
- * Handle timeout events of the fsm.
- * \param fsm fsm
- * \return one if an event has been handled, zero otherwise
- */
-int
-fsm_build_handle_timeout (fsm_build_t *fsm);
-
-/** Give the state at the transition output. */
-fsm_build_state_t*
-fsm_build_get_next_state (fsm_build_t *fsm,
- char *state,
- char *event,
- char *branch);
-
-/** Generate header file for target which provides more optimised version of
- * fsm execution
- * \param arch specify generated architecture
- * \param embedded_strings ask to embed states and events strings (0 = not
- * embedded)
- */
-void
-fsm_build_gen (char *arch, uint embedded_strings);
-void
-fsm_build_gen_avr_h (fsm_build_t *fsm, uint embedded_strings);
-void
-fsm_build_gen_avr_c (fsm_build_t *fsm, uint embedded_strings);
-
-/** Free fsm allocated data. */
-void
-fsm_build_free (fsm_build_t *fsm);
-
-#endif /* Architectures */
-
-#endif /* #ifdef _FSM_GEN_ */
diff --git a/digital/ai/src/fsm/fsm.host.c b/digital/ai/src/fsm/fsm.host.c
deleted file mode 100644
index ad9d0b00..00000000
--- a/digital/ai/src/fsm/fsm.host.c
+++ /dev/null
@@ -1,1607 +0,0 @@
-/*
- AngFSM - AngFSM - Almost Non Generated Finite State Machine
-
- Copyright 2011 Jerome Jutteau
-
-Contact:
- * email: j.jutteau _AT_ gmail _DOT_ com
- * website: http://fuu.im/angfsm/
-
- This file is part of AngFSM.
-
- AngFSM 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.
-
- AngFSM 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 AngFSM. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "fsm.h"
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-void
-fsm_build_arg_parse (char *string, char ***tab, int *nb)
-{
- long i = 0;
- long buff_cnt = 0;
- char *buff;
- int nb_cur = 0;
- int param = 0;
-
- assert (string && tab && nb);
- if (strlen (string) == 0)
- {
- *nb = 0;
- **tab = NULL;
- return;
- }
- buff = strdup (string);
-
- /* Count. */
- *nb = 1;
- for (i = 0; string[i] != '\0'; i++)
- if (string[i] == ',')
- (*nb)++;
- *tab = (char **) malloc ((*nb) * sizeof (char *));
-
- /* Fill. */
- for (i = 0; i < (long) strlen (string) + 1; i++)
- {
- if (string[i] == ',' || string[i] == '\0')
- {
- param = 0;
- buff[buff_cnt] = '\0';
- (*tab)[nb_cur] = strdup (buff);
- buff_cnt=0;
- nb_cur++;
- }
- else if (string[i] != '"' && string[i] != ' ')
- {
- if (param == 0)
- param = 1;
- if (param == 2)
- printf ("Parse error in \"%s\"\n", string);
- buff[buff_cnt++] = string[i];
- }
- else if (string[i] == ' ')
- {
- if (param == 1)
- param = 2;
- }
- }
- free (buff);
-}
-
-void
-fsm_build_arg_free (char ***tab, int nb)
-{
- assert (*tab);
- int i;
- for (i = 0; i < nb; i++)
- {
- assert ((*tab)[i]);
- free ((*tab)[i]);
- }
- free (*tab);
-}
-
-void
-fsm_build_print (fsm_build_t *fsm,
- fsm_build_trans_t *trans,
- fsm_build_branch_chain_t *branch)
-{
- //XXX What to do here ?
- if (branch->name == NULL)
- fprintf (stderr, "Transition: %s -- %s --> %s\n",
- trans->state->var_name,
- trans->event->var_name,
- branch->state->var_name);
- else
- fprintf (stderr, "Transition: %s -- %s --> %s (%s)\n",
- trans->state->var_name,
- trans->event->var_name,
- branch->name,
- branch->state->var_name);
-}
-
-void
-fsm_build_sanity_check (fsm_build_t *fsm)
-{
- fsm_build_event_chain_t *ec;
- fsm_build_event_chain_t *ec_tmp;
- fsm_build_state_chain_t *sc;
- fsm_build_state_chain_t *sc_tmp;
- fsm_build_trans_chain_t *tc;
- fsm_build_trans_chain_t *tc_tmp;
- fsm_build_branch_chain_t *bc;
- uint b;
-
- /* Sanity check 1: are all states has a different name ? */
- sc = fsm->states;
- while (sc != NULL)
- {
- sc_tmp = fsm->states;
- while (sc_tmp != NULL)
- {
- if (sc != sc_tmp
- && strcmp (sc->state.var_name, sc_tmp->state.var_name)
- == 0)
- assert (!"All states must have a different name.");
- sc_tmp = sc_tmp->next;
- }
- sc = sc->next;
- }
-
- /* Sanity check 2: are all events has a different name ? */
- ec = fsm->events;
- while (ec != NULL)
- {
- ec_tmp = fsm->events;
- while (ec_tmp != NULL)
- {
- if (ec != ec_tmp
- && strcmp (ec->event.var_name, ec_tmp->event.var_name)
- == 0)
- assert (!"All events must have a different name.");
- ec_tmp = ec_tmp->next;
- }
- ec = ec->next;
- }
-
- /* Sanity check 3: are all events used in a transition ? */
- ec = fsm->events;
- while (ec != NULL)
- {
- b = 0;
- tc = fsm->trans;
- while (tc != NULL)
- {
- if (&ec->event == tc->trans.event)
- {
- b = 1;
- break;
- }
- tc = tc->next;
- }
- if (!b)
- fprintf (stderr, "Warning, some events are not used in a transition (%s).\n",
- ec->event.var_name);
- ec = ec->next;
- }
-
- /* Sanity check 4: are all states used in a transition ? */
- sc = fsm->states;
- while (sc != NULL)
- {
- b = 0;
- tc = fsm->trans;
- while (tc != NULL)
- {
- if (&sc->state == tc->trans.state)
- {
- b = 1;
- break;
- }
- /* This state may be a final state. */
- bc = tc->trans.output_branches;
- while (bc != NULL)
- {
- if (&sc->state == bc->state)
- {
- b = 1;
- break;
- }
- bc = bc->next;
- }
-
- tc = tc->next;
- }
- if (!b)
- fprintf (stderr, "Warning, some states are not used in a transition (%s).\n",
- sc->state.var_name);
- sc = sc->next;
- }
-
- /* Sanity check 5: are all states can be reached during execution ? */
- fsm_build_state_chain_t *stack = NULL;
- fsm_build_state_chain_t *tail = NULL;
- uint i;
- /* Initialise check array. */
- uint *check_tab = malloc (fsm->state_nb * sizeof (uint));
- memset (check_tab, 0, fsm->state_nb * sizeof (uint));
- /* Initialize by adding first active states the stack. */
- sc = fsm->starters;
- while (sc != NULL)
- {
- sc_tmp = (fsm_build_state_chain_t *)
- malloc (sizeof (fsm_build_state_chain_t));
- sc_tmp->state = sc->state;
- if (stack == NULL)
- stack = sc_tmp;
- if (tail != NULL)
- tail->next = sc_tmp;
- sc_tmp->next = NULL;
- tail = sc_tmp;
- sc = sc->next;
- }
- /* Get next states from the stack and check them. */
- while (stack != NULL)
- {
- /* Check state. */
- check_tab[stack->state.code] = 1;
- /* Add to the tail of the stack th next states if they are not checked
- * yet. */
- tc = fsm->trans;
- while (tc != NULL)
- {
- if (tc->trans.state->code == stack->state.code)
- {
- bc = tc->trans.output_branches;
- while (bc != NULL)
- {
- if (!check_tab[bc->state->code])
- {
- check_tab[bc->state->code] = 1;
- /* Add at the end of the stack. */
- sc_tmp = (fsm_build_state_chain_t *)
- malloc (sizeof (fsm_build_state_chain_t));
- sc_tmp->state = *bc->state;
- sc_tmp->next = NULL;
- tail->next = sc_tmp;
- tail = sc_tmp;
- }
- bc = bc->next;
- }
- }
- tc = tc->next;
- }
- sc_tmp = stack->next;
- free (stack);
- stack = sc_tmp;
- }
- /* Check if some states are not reached. */
- for (i = 0; i < fsm->state_nb; i++)
- if (!check_tab[i])
- fprintf (stderr, "Warning, some states won't be reachable during execution (%s).\n",
- fsm_build_get_state_by_code (fsm, i)->var_name);
- /* Free. */
- free (check_tab);
-
- /* Sanity check 6: Any transition how have the same state and same event ?
- * Useless test ? Making the same state/event couple will cause a
- * compilation error.
- */
- tc = fsm->trans;
- while (tc != NULL)
- {
- tc_tmp = fsm->trans;
- while (tc_tmp != NULL)
- {
- if (tc != tc_tmp
- && tc->trans.state == tc_tmp->trans.state
- && tc->trans.event == tc_tmp->trans.event)
- assert (!"All transitions must have a different state/event\
- couple.");
- tc_tmp = tc_tmp->next;
- }
- tc = tc->next;
- }
-
- /* Sanity check 7: check that all first active states are unique. */
- sc = fsm->starters;
- while (sc != NULL)
- {
- uint b = 0;
- sc_tmp = fsm->starters;
- while (sc_tmp != NULL)
- {
- if (sc_tmp->state.code == sc->state.code)
- b++;
- if (b > 1)
- assert (!"Your first active states must be unique.");
- sc_tmp = sc_tmp->next;
- }
- sc = sc->next;
- }
-
- /* Sanity check 8: any transition output error ?
- * for example, as we are in state s42, making a FSM_NEXT (s1, e2) will
- * work but this is a user's mistake.
- *
- * TODO Find a way to check this.
- **/
-}
-
-void
-fsm_build_reset (fsm_build_t *fsm)
-{
- uint i;
- fsm_build_state_chain_t *curs = fsm->starters;
- for (i = 0; i < fsm->max_active_states; i++)
- {
- fsm->run.active_states[i] = NULL;
- fsm->run.events_before_active_state[i] = NULL;
- }
- i = 0;
- while (curs != NULL)
- {
- fsm->run.active_states[i++] = &curs->state;
- curs = curs->next;
- }
-}
-
-void
-fsm_build_gen_dot (fsm_build_t *fsm)
-{
- static uint cpt = 1;
- uint j;
- fsm_build_trans_chain_t *tc;
- fsm_build_branch_chain_t *bc;
-
- uint fns = strlen (fsm->name) + strlen ("dot__.dot") + cpt + 1;
- char *fn = malloc (fns * sizeof (char));
- snprintf (fn, fns, "dot_%s_%u.dot", fsm->name, cpt++);
- FILE *f = fopen(fn,"w");
-
- /* Gen graph. */
- fprintf (f, "digraph %s {\n", fsm->name);
- tc = fsm->trans;
- while (tc != NULL)
- {
- bc = tc->trans.output_branches;
- while (bc != NULL)
- {
- fprintf (f, "\t%s -> %s [label=\"%s",
- tc->trans.state->var_name,
- bc->state->var_name,
- tc->trans.event->var_name);
- if (bc->name != NULL)
- fprintf (f, " (%s)", bc->name);
- fprintf (f, "\"");
- /* If the next state is an active state we look if this this event
- * was handled before. */
- for (j = 0; j < fsm->max_active_states; j++)
- if (fsm->run.active_states[j]
- && fsm->run.active_states[j]->code == bc->state->code)
- if (fsm->run.events_before_active_state[j]
- && fsm->run.events_before_active_state[j]->code
- == tc->trans.event->code)
- fprintf (f, ", color=red");
-
- fprintf (f, "];\n");
- bc = bc->next;
- }
- tc = tc->next;
- }
- /* Colorise active states. */
- for (j = 0; j < fsm->max_active_states; j++)
- if (fsm->run.active_states[j])
- fprintf (f, "\t%s [color=blue, fontcolor=white, style=filled];\n",
- fsm->run.active_states[j]->var_name);
-
- fprintf (f, "}\n\n");
-
- /* Close file. */
- fclose (f);
-
- /* Free. */
- free (fn);
-}
-
-/* All fsm. */
-fsm_build_chain_t *fsm_build_all_fsm;
-void fsm_build_init_all_fsm ()
-{
- fsm_build_all_fsm = NULL;
-}
-
-/* Just initialise structures. */
-void
-fsm_build_init (fsm_build_t *fsm, char *name)
-{
- assert (fsm);
- fsm->events = NULL;
- fsm->states = NULL;
- fsm->trans = NULL;
- fsm->name = name;
- fsm->max_active_states = 0;
- fsm->event_nb = 0;
- fsm->state_nb = 0;
- fsm->starters = NULL;
- fsm->timeouts = NULL;
-
- fsm->run.trans_table = NULL;
- fsm->run.active_states = NULL;
- fsm->run.events_before_active_state = NULL;
- fsm->run.func_pool = NULL;
- fsm->run.timeout_counters = NULL;
-
- /* Store fsm. */
- fsm_build_chain_t *niou = (fsm_build_chain_t *)
- malloc (sizeof (fsm_build_chain_t));
- niou->fsm = fsm;
- niou->next = fsm_build_all_fsm;
- fsm_build_all_fsm = niou;
-}
-
-/* Prepare the fsm to run (at very end). */
-void
-fsm_build_run_init (fsm_build_t *fsm)
-{
- uint i,j;
-
- /* Sanity check. */
- fsm_build_sanity_check (fsm);
-
- /* Create empty transition table. */
- fsm->run.trans_table = (fsm_build_run_strans_func_t **)
- malloc (fsm->event_nb * sizeof (fsm_build_run_strans_func_t *));
- for (i = 0; i < fsm->event_nb; i++)
- {
- fsm->run.trans_table[i] = (fsm_build_run_strans_func_t *)
- malloc (fsm->state_nb * sizeof (fsm_build_run_strans_func_t));
- for (j = 0; j < fsm->state_nb; j++)
- fsm->run.trans_table[i][j] = NULL;
- }
-
- /* Fill with transitions. */
- fsm_trans_func_chain_t *fc = fsm->run.func_pool;
- while (fc != NULL)
- {
- fsm->run.trans_table[fc->trans.event->code][fc->trans.state->code] =
- fc->func;
- fc = fc->next;
- }
-
- /* Free function pool. */
- fsm_trans_func_chain_t *old_fc;
- fc = fsm->run.func_pool;
- while (fc != NULL)
- {
- old_fc = fc;
- fc = fc->next;
- free (old_fc);
- }
- fsm->run.func_pool = NULL;
-
- /* Initialize active states. */
- fsm->run.active_states = (fsm_build_state_t **) malloc
- (fsm->max_active_states * sizeof (fsm_build_state_t *));
- for (i = 0; i < fsm->max_active_states; i++)
- fsm->run.active_states[i] = NULL;
- fsm_build_state_chain_t *s = fsm->starters;
- i = 0;
- while (s != NULL)
- {
- fsm->run.active_states[i++] = &s->state;
- s = s->next;
- }
-
- /* Initialize last events before active states. */
- fsm->run.events_before_active_state = (fsm_build_event_t **) malloc
- (fsm->max_active_states * sizeof (fsm_build_event_t *));
- for (i = 0; i < fsm->max_active_states; i++)
- fsm->run.events_before_active_state[i] = NULL;
-
- /* Initialize timeout counters. */
- fsm->run.timeout_counters = (int *)
- malloc (fsm->max_active_states * sizeof (int));
- for (i = 0; i < fsm->max_active_states; i++)
- fsm->run.timeout_counters[i] = -1;
- fsm_build_timeout_chain_t *toc = fsm->timeouts;
- for (i = 0; i < fsm->max_active_states; i++)
- while (toc != NULL)
- {
- if (fsm->run.active_states[i]->code
- == toc->timeout.trans->state->code)
- fsm->run.timeout_counters[i] = toc->timeout.timeout;
- toc = toc->next;
- }
-}
-
-void
-fsm_build_states (fsm_build_t *fsm, char *states)
-{
- fsm_build_state_chain_t *head = fsm->states;
- char **args;
- int i, nb;
-
- fsm_build_arg_parse (states, &args, &nb);
- for (i = 0; i < nb; i++)
- {
- fsm_build_state_chain_t *s = (fsm_build_state_chain_t *)
- malloc (sizeof (fsm_build_state_chain_t));
- s->state.var_name = strdup (args[i]);
- s->state.code = fsm->state_nb++;
- s->next = head;
- head = s;
- }
- fsm_build_arg_free (&args, nb);
- fsm->states = head;
-}
-
-void
-fsm_build_events (fsm_build_t *fsm, char *events)
-{
- fsm_build_event_chain_t *head = fsm->events;
- char **args;
- int i, nb;
-
- if (strcmp (events, "_TIMEOUT_") == 0
- && fsm_build_get_event (fsm, events) != NULL)
- return;
- fsm_build_arg_parse (events, &args, &nb);
- for (i = 0; i < nb; i++)
- {
- fsm_build_event_chain_t *e = (fsm_build_event_chain_t *)
- malloc (sizeof (fsm_build_event_chain_t));
- e->event.var_name = strdup (args[i]);
- e->event.code = fsm->event_nb++;
- e->next = head;
- head = e;
- }
- fsm_build_arg_free (&args, nb);
- fsm->events = head;
-}
-
-fsm_build_event_t *
-fsm_build_get_event (fsm_build_t *fsm, char *event)
-{
- fsm_build_event_chain_t *curs = fsm->events;
- while (curs != NULL)
- {
- if (strcmp (curs->event.var_name, event) == 0)
- return &(curs->event);
- curs = curs->next;
- }
- return NULL;
-}
-
-fsm_build_state_t *
-fsm_build_get_state (fsm_build_t *fsm, char *state)
-{
- fsm_build_state_chain_t *curs = fsm->states;
- while (curs != NULL)
- {
- if (strcmp (curs->state.var_name, state) == 0)
- return &(curs->state);
- curs = curs->next;
- }
- return NULL;
-}
-
-fsm_build_event_t*
-fsm_build_get_event_by_code (fsm_build_t *fsm, uint event)
-{
- fsm_build_event_chain_t *curs = fsm->events;
- while (curs != NULL)
- {
- if (curs->event.code == event)
- return &(curs->event);
- curs = curs->next;
- }
- return NULL;
-}
-
-fsm_build_state_t*
-fsm_build_get_state_by_code (fsm_build_t *fsm, uint state)
-{
- fsm_build_state_chain_t *curs = fsm->states;
- while (curs != NULL)
- {
- if (curs->state.code == state)
- return &(curs->state);
- curs = curs->next;
- }
- return NULL;
-}
-
-uint16_t
-fsm_build_get_event_code (fsm_build_t *fsm, char *event)
-{
- assert (fsm);
- fsm_build_event_t *e = fsm_build_get_event (fsm, event);
- assert (e);
- return e->code;
-}
-
-void
-fsm_build_trans (fsm_build_t *fsm,
- char *state,
- char *event,
- char *output_branches,
- fsm_build_run_strans_func_t trans_func)
-{
- fsm_build_trans_t t;
- fsm_build_branch_chain_t *b;
- char **args;
- int i, nb;
-
- t.output_branches = NULL;
- /* Check state and event exists. */
- t.state = fsm_build_get_state (fsm, state);
- t.event = fsm_build_get_event (fsm, event);
- assert (t.state);
- assert (t.event);
-
- fsm_build_arg_parse (output_branches, &args, &nb);
- /* Only one output state. */
- if (nb == 1)
- {
- t.output_branches = (fsm_build_branch_chain_t *)
- malloc (sizeof (fsm_build_branch_chain_t));
- t.output_branches->name = NULL;
- t.output_branches->state = fsm_build_get_state (fsm, args[0]);
- assert (t.output_branches->state);
- t.output_branches->next = NULL;
- }
- else
- for (i = 0; i < nb; i = i + 2)
- {
- b = (fsm_build_branch_chain_t *)
- malloc (sizeof (fsm_build_branch_chain_t));
- b->name = strdup (args[i]);
- b->state = fsm_build_get_state (fsm, args[i+1]);
- assert (b->state);
- b->next = t.output_branches;
- t.output_branches = b;
- }
- fsm_build_arg_free (&args, nb);
-
- /* Add trans to fsm. */
- fsm_build_trans_chain_t *tc = (fsm_build_trans_chain_t *)
- malloc (sizeof (fsm_build_trans_chain_t));
- tc->trans = t;
- tc->next = fsm->trans;
- fsm->trans = tc;
-
- /* Add trans function to run context. */
- fsm_trans_func_chain_t *fc = (fsm_trans_func_chain_t *)
- malloc (sizeof (fsm_trans_func_chain_t));
- fc->func = trans_func;
- fc->trans = tc->trans;
- fc->next = fsm->run.func_pool;
- fsm->run.func_pool = fc;
-}
-
-void
-fsm_build_timeout (fsm_build_t *fsm, char *state, char *event, uint timeout)
-{
- fsm_build_trans_chain_t *tc = NULL;
- fsm_build_trans_t *t = NULL;
- fsm_build_state_t *s = NULL;
- fsm_build_event_t *e = NULL;
- fsm_build_timeout_chain_t *to = NULL;
-
- assert (fsm);
- assert (state);
- assert (event);
-
- /* Find the corresponding transition. */
- tc = fsm->trans;
- s = fsm_build_get_state (fsm, state);
- e = fsm_build_get_event (fsm, event);
- assert (tc);
- assert (s);
- assert (e);
- while (tc != NULL)
- {
- if (tc->trans.state == s && tc->trans.event == e)
- {
- t = &tc->trans;
- break;
- }
- tc = tc->next;
- }
- assert (t);
-
- /* Fill a new timeout. */
- to = (fsm_build_timeout_chain_t *)
- malloc (sizeof (fsm_build_timeout_chain_t));
- to->timeout.timeout = timeout;
- to->timeout.trans = t;
-
- /* Add timeout to chain. */
- to->next = fsm->timeouts;
- fsm->timeouts = to;
-}
-
-void
-fsm_build_start_with (fsm_build_t *fsm, char *starters)
-{
- char **args;
- int nb, i;
- fsm_build_arg_parse (starters, &args, &nb);
- fsm->max_active_states += nb;
- for (i=0; i < nb; i++)
- {
- fsm_build_state_chain_t *sc = (fsm_build_state_chain_t *)
- malloc (sizeof (fsm_build_state_chain_t));
- fsm_build_state_t *s = fsm_build_get_state (fsm, args[i]);
- assert (s);
- sc->state = *s;
- sc->next = fsm->starters;
- fsm->starters = sc;
- }
- fsm_build_arg_free (&args, nb);
-}
-
-int
-fsm_build_handle (fsm_build_t *fsm, fsm_build_event_t *e)
-{
- fsm_build_state_t *s = NULL;
- fsm_build_timeout_chain_t *toc = NULL;
- assert (e);
- uint i;
- int handled = 0;
- for (i = 0; i < fsm->max_active_states; i++)
- {
- s = fsm->run.active_states[i];
- if (s && fsm->run.trans_table[e->code][s->code])
- {
- fsm->run.events_before_active_state[i] = e;
- fsm->run.active_states[i] = fsm->run.trans_table[e->code][s->code]();
- /* Check the new state has a timeout or not. */
- toc = fsm->timeouts;
- fsm->run.timeout_counters[i] = -1;
- while (toc != NULL)
- {
- if (toc->timeout.trans->state->code
- == fsm->run.active_states[i]->code)
- {
- fsm->run.timeout_counters[i] = toc->timeout.timeout;
- break;
- }
- toc = toc->next;
- }
-
- handled = 1;
- }
- }
- return handled;
-}
-
-int
-fsm_build_handle_string (fsm_build_t *fsm, char *event)
-{
- fsm_build_event_t *e = fsm_build_get_event (fsm, event);
- return fsm_build_handle (fsm, e);
-}
-
-int
-fsm_build_handle_integer (fsm_build_t *fsm, uint16_t event)
-{
- fsm_build_event_t *e = fsm_build_get_event_by_code (fsm, event);
- return fsm_build_handle (fsm, e);
-}
-
-int
-fsm_build_can_handle (fsm_build_t *fsm, fsm_build_event_t *e)
-{
- fsm_build_state_t *s = NULL;
- assert (e);
- uint i;
- for (i = 0; i < fsm->max_active_states; i++)
- {
- s = fsm->run.active_states[i];
- if (s && fsm->run.trans_table[e->code][s->code])
- return 1;
- }
- return 0;
-}
-
-int
-fsm_build_can_handle_string (fsm_build_t *fsm, char *event)
-{
- fsm_build_event_t *e = fsm_build_get_event (fsm, event);
- return fsm_build_can_handle (fsm, e);
-}
-
-int
-fsm_build_can_handle_integer (fsm_build_t *fsm, uint16_t event)
-{
- fsm_build_event_t *e = fsm_build_get_event_by_code (fsm, event);
- return fsm_build_can_handle (fsm, e);
-}
-
-int
-fsm_build_handle_timeout (fsm_build_t *fsm)
-{
- int out = 0;
- int i;
- char *event = NULL;
- for (i = 0; i < (int) fsm->max_active_states; i++)
- {
- if (fsm->run.timeout_counters[i] > 0)
- fsm->run.timeout_counters[i]--;
- /* We have a timeout event. */
- if (fsm->run.timeout_counters[i] == 0)
- {
- fsm->run.timeout_counters[i] = -1;
- /* build event string */
- event = (char *) malloc (
- (strlen (fsm->run.active_states[i]->var_name)
- + strlen ("_TIMEOUT") + 1) * sizeof (char));
- sprintf (event, "%s_TIMEOUT", fsm->run.active_states[i]->var_name);
- fsm_build_handle_string (fsm, event);
- out = 1;
- }
- }
- return out;
-}
-
-fsm_build_state_t*
-fsm_build_get_next_state (fsm_build_t *fsm,
- char *state,
- char *event,
- char *branch)
-{
- fsm_build_state_t *s;
- fsm_build_event_t *e;
- fsm_build_trans_chain_t *t_curs;
- fsm_build_branch_chain_t *b_curs;
-
- /* Convert input data. */
- s = fsm_build_get_state (fsm, state);
- e = fsm_build_get_event (fsm, event);
- assert (s && e);
-
- /* Get transition. */
- t_curs = fsm->trans;
- while (t_curs != NULL)
- {
- if (s == t_curs->trans.state && e == t_curs->trans.event)
- break;
- t_curs = t_curs->next;
- }
- assert (t_curs);
- assert (t_curs->trans.output_branches);
-
- /* If we have only one branch. */
- if (strlen (branch) == 0)
- {
- /* Branch has to be given is there are multiple branches. */
- assert (t_curs->trans.output_branches->next == NULL);
- fsm_build_print (fsm, &t_curs->trans, t_curs->trans.output_branches);
- return t_curs->trans.output_branches->state;
- }
-
- /* Find correct branch. */
- b_curs = t_curs->trans.output_branches;
- while (b_curs != NULL)
- {
- if (strcmp (b_curs->name, branch) == 0)
- break;
- b_curs = b_curs->next;
- }
- assert (b_curs);
- fsm_build_print (fsm, &t_curs->trans, b_curs);
- return b_curs->state;
-}
-
-void
-fsm_build_gen_avr_h (fsm_build_t *fsm, uint embedded_strings)
-{
- fsm_build_state_chain_t *sc;
- fsm_build_event_chain_t *ec;
- fsm_build_trans_chain_t *tc;
- fsm_build_branch_chain_t *bc;
- fsm_build_state_t *s;
- fsm_build_event_t *e;
- fsm_build_chain_t *all_fsm;
- uint i, j;
-
- /* Open file. */
- char *fn = (char *) malloc ((strlen (fsm->name)
- + strlen ("fsm_gen_.h") + 1) * sizeof (char));
- sprintf (fn, "fsm_%s_gen.h", fsm->name);
- FILE *f = fopen (fn, "w");
-
- /* Introduction. */
- fprintf (f, "/* This file has been generated, do not edit. */\n\n");
- fprintf (f, "#ifndef _FSM_%s_\n", fsm->name);
- fprintf (f, "#define _FSM_%s_\n\n", fsm->name);
- fprintf (f, "#include <avr/pgmspace.h>\n");
- fprintf (f, "#include <inttypes.h>\n\n");
-
- /* Include all other fsm headers. */
- all_fsm = fsm_build_all_fsm;
- while (all_fsm != NULL)
- {
- fprintf (f, "#include \"fsm_%s_gen.h\"\n",all_fsm->fsm->name);
- all_fsm = all_fsm->next;
- }
-
- /* Gen max active states define */
- fprintf (f, "#define fsm_%s_max_active_states %u\n",
- fsm->name,
- fsm->max_active_states);
-
- /* Gen state enum. */
- fprintf (f, "typedef enum\n{\n");
- sc = fsm->states;
- while (sc != NULL)
- {
- fprintf (f, "\tFSM_STATE_%s_%s = %u,\n", fsm->name, sc->state.var_name, sc->state.code);
- sc = sc->next;
- }
- fprintf (f, "\tFSM_STATE_%s_NB_ = %u\n", fsm->name, fsm->state_nb);
- fprintf (f, "} fsm_%s_state_t;\n\n", fsm->name);
-
- /* Gen event enum. */
- fprintf (f, "typedef enum\n{\n");
- ec = fsm->events;
- while (ec != NULL)
- {
- fprintf (f, "\tFSM_EVENT_%s_%s = %u,\n", fsm->name, ec->event.var_name, ec->event.code);
- ec = ec->next;
- }
- fprintf (f, "\tFSM_EVENT_%s_NB_ = %u\n", fsm->name, fsm->event_nb);
- fprintf (f, "} fsm_%s_event_t;\n\n", fsm->name);
-
- /* Gen state strings. */
- if (embedded_strings)
- {
- sc = fsm->states;
- while (sc != NULL)
- {
- fprintf (f, "extern prog_char fsm_%s_state_str_%s[%u] PROGMEM;\n",
- fsm->name,
- sc->state.var_name,
- strlen (sc->state.var_name) + 1);
- sc = sc->next;
- }
- fprintf (f, "extern const char *fsm_%s_state_str[%u] PROGMEM;\n\n",
- fsm->name,
- fsm->state_nb);
-
- /* Gen event strings. */
- ec = fsm->events;
- while (ec != NULL)
- {
- fprintf (f, "extern prog_char fsm_%s_event_str_%s[%u] PROGMEM;\n",
- fsm->name,
- ec->event.var_name,
- strlen (ec->event.var_name) + 1);
- ec = ec->next;
- }
- fprintf (f, "extern const char *fsm_%s_event_str[%u] PROGMEM;\n\n",
- fsm->name,
- fsm->event_nb);
-
- /* Create a RAM string able to store event or state string. */
- j = 0;
- for (i = 0; i < fsm->event_nb; i++)
- {
- e = fsm_build_get_event_by_code (fsm, i);
- if (strlen (e->var_name) > j)
- j = strlen (e->var_name);
- }
- for (i = 0; i < fsm->state_nb; i++)
- {
- s = fsm_build_get_state_by_code (fsm, i);
- if (strlen (s->var_name) > j)
- j = strlen (s->var_name);
- }
- fprintf (f, "extern char fsm_%s_str_buff[%u];\n", fsm->name, j + 1);
-
- /* Convert an event enum in string. */
- fprintf (f, "char *\nfsm_%s_get_event_string_from_enum \
- (fsm_%s_event_t e);\n", fsm->name, fsm->name);
-
- /* Convert a event string in enum. */
- fprintf (f, "fsm_%s_event_t\nfsm_%s_get_event_enum_from_string \
- (char *str);\n", fsm->name, fsm->name);
-
- /* Convert an state enum in string. */
- fprintf (f, "char *\nfsm_%s_get_state_string_from_enum \
- (fsm_%s_state_t s);\n", fsm->name, fsm->name);
-
- /* Convert a state string in enum. */
- fprintf (f, "fsm_%s_state_t\nfsm_%s_get_state_enum_from_string \
- (char *str);\n", fsm->name, fsm->name);
- }
-
- /* Gen transitions branches enum. */
- fprintf (f, "typedef enum\n{\n");
- tc = fsm->trans;
- while (tc != NULL)
- {
- bc = tc->trans.output_branches;
- while (bc != NULL)
- {
- if (bc->name != NULL)
- fprintf (f, "\tFSM_BRANCH_%s_%s_%s_%s = %u,\n",
- fsm->name,
- tc->trans.state->var_name,
- tc->trans.event->var_name,
- bc->name,
- bc->state->code);
- else
- fprintf (f, "\tFSM_BRANCH_%s_%s_%s_ = %u,\n",
- fsm->name,
- tc->trans.state->var_name,
- tc->trans.event->var_name,
- bc->state->code);
- bc = bc->next;
- }
- tc = tc->next;
- }
- fprintf (f, "} fsm_%s_branch_t;\n\n", fsm->name);
-
- /* Gen function headers. */
- tc = fsm->trans;
- while (tc != NULL)
- {
- fprintf (f, "fsm_%s_branch_t fsm_%s_trans_func_%s_%s (void);\n",
- fsm->name,
- fsm->name,
- tc->trans.state->var_name,
- tc->trans.event->var_name);
- tc = tc->next;
- }
- fprintf (f, "\n");
-
- /* Gen function table. */
- fprintf (f, "typedef fsm_%s_branch_t (*fsm_%s_func_t)(void);\n", fsm->name,
- fsm->name);
- fprintf (f, "extern const fsm_%s_func_t PROGMEM fsm_%s_trans_table[%u][%u];\n",
- fsm->name,
- fsm->name,
- fsm->event_nb,
- fsm->state_nb);
- /* Gen read function for trans table. */
- fprintf (f, "fsm_%s_func_t fsm_%s_read_trans (fsm_%s_event_t event, "
- "fsm_%s_state_t state);\n\n",
- fsm->name,
- fsm->name,
- fsm->name,
- fsm->name);
-
- /* Gen active states array. */
- fprintf (f, "extern fsm_%s_state_t fsm_%s_active_states[%u];\n\n",
- fsm->name,
- fsm->name,
- fsm->max_active_states);
-
- /* Gen initialization function. */
- sc = fsm->starters;
- i = 0;
- fprintf (f, "void\nfsm_%s_init () __attribute__ ((constructor));\n\n",
- fsm->name);
-
- /* Gen handle function. */
- fprintf (f, "int\nfsm_%s_handle (fsm_%s_event_t e);\n",
- fsm->name,
- fsm->name);
-
- /* Gen can handle function. */
- fprintf (f, "uint16_t\nfsm_%s_can_handle (fsm_%s_event_t e);\n\n",
- fsm->name,
- fsm->name);
-
- if (fsm->timeouts != NULL)
- {
- /* Gen handle timeout function. */
- fprintf (f, "int\nfsm_%s_handle_timeout ();\n",
- fsm->name);
-
- /* Gen timeout values. */
- fprintf (f, "extern int32_t fsm_%s_timeout_values[FSM_STATE_%s_NB_];\n",
- fsm->name,
- fsm->name);
-
- /* Gen timeout corresponding events. */
- fprintf (f, "extern fsm_%s_event_t fsm_%s_timeout_events[FSM_STATE_%s_NB_];\n",
- fsm->name,
- fsm->name,
- fsm->name);
-
- /* Gen timeout counters array. */
- fprintf (f, "extern int32_t fsm_%s_timeout_counters[%u];\n\n",
- fsm->name,
- fsm->max_active_states);
- }
-
- /* Conclusion. */
- fprintf (f, "#endif /* #ifndef _FSM_%s_ */", fsm->name),
-
- /* Close file. */
- fclose (f);
-
- /* Free. */
- free (fn);
-}
-
-void
-fsm_build_gen_avr_c (fsm_build_t *fsm, uint embedded_strings)
-{
- fsm_build_state_chain_t *sc;
- fsm_build_event_chain_t *ec;
- fsm_build_trans_chain_t *tc;
- fsm_build_timeout_chain_t *toc;
- fsm_build_state_t *s;
- fsm_build_event_t *e;
- uint i, j, found;
-
- /* Open file. */
- char *fn = (char*) malloc ((strlen (fsm->name)
- + strlen ("fsm_gen_.c") + 1) * sizeof (char));
- sprintf (fn, "fsm_%s_gen.c", fsm->name);
- FILE *f = fopen (fn, "w");
-
- /* Introduction. */
- fprintf (f, "/* This file has been generated, do not edit. */\n\n");
- fprintf (f, "#include \"common.h\"\n\n");
- fprintf (f, "#include \"io.h\"\n\n");
- fprintf (f, "#include \"fsm_%s_gen.h\"\n\n", fsm->name);
- fprintf (f, "#include \"logger.h\"\n\n");
- fprintf (f, "#include \"modules/proto/proto.h\"\n\n");
-
- /* Gen state strings. */
- if (embedded_strings)
- {
- sc = fsm->states;
- while (sc != NULL)
- {
- fprintf (f, "prog_char fsm_%s_state_str_%s[] PROGMEM = \"%s\";\n",
- fsm->name,
- sc->state.var_name,
- sc->state.var_name);
- sc = sc->next;
- }
- fprintf (f, "const char *fsm_%s_state_str[] PROGMEM =\n{\n", fsm->name);
- for (i = 0; i < fsm->state_nb; i++)
- {
- s = fsm_build_get_state_by_code (fsm, i);
- fprintf (f, "\tfsm_%s_state_str_%s", fsm->name, s->var_name);
- if (i == fsm->state_nb - 1)
- fprintf (f, "\n");
- else
- fprintf (f, ",\n");
- }
- fprintf (f, "};\n\n");
-
- /* Gen event strings. */
- ec = fsm->events;
- while (ec != NULL)
- {
- fprintf (f, "prog_char fsm_%s_event_str_%s[] PROGMEM = \"%s\";\n",
- fsm->name,
- ec->event.var_name,
- ec->event.var_name);
- ec = ec->next;
- }
- fprintf (f, "const char *fsm_%s_event_str[] PROGMEM =\n{\n", fsm->name);
- for (i = 0; i < fsm->event_nb; i++)
- {
- e = fsm_build_get_event_by_code (fsm, i);
- fprintf (f, "\tfsm_%s_event_str_%s", fsm->name, e->var_name);
- if (i == fsm->event_nb - 1)
- fprintf (f, "\n");
- else
- fprintf (f, ",\n");
- }
- fprintf (f, "};\n\n");
-
- /* Create a RAM string able to store event or state string. */
- j = 0;
- for (i = 0; i < fsm->event_nb; i++)
- {
- e = fsm_build_get_event_by_code (fsm, i);
- if (strlen (e->var_name) > j)
- j = strlen (e->var_name);
- }
- for (i = 0; i < fsm->state_nb; i++)
- {
- s = fsm_build_get_state_by_code (fsm, i);
- if (strlen (s->var_name) > j)
- j = strlen (s->var_name);
- }
- fprintf (f, "char fsm_%s_str_buff[%u];\n", fsm->name, j + 1);
-
- /* Convert an event enum in string. */
- fprintf (f, "char *\nfsm_%s_get_event_string_from_enum \
- (fsm_%s_event_t e)\n{\n", fsm->name, fsm->name);
- fprintf (f, "\treturn strcpy_P (fsm_%s_str_buff, \
- (char *) pgm_read_word (&(fsm_%s_event_str[e])));\n", fsm->name, fsm->name);
- fprintf (f, "}\n\n");
-
- /* Convert a event string in enum. */
- fprintf (f, "fsm_%s_event_t\nfsm_%s_get_event_enum_from_string \
- (char *str)\n{\n", fsm->name, fsm->name);
- fprintf (f, "\tuint16_t i;\n");
- fprintf (f, "\tfor (i = 0; i < FSM_EVENT_%s_NB_; i++)\n", fsm->name);
- fprintf (f, "\t\tif (strcpy_P (str, \
- (char *) pgm_read_word (&(fsm_%s_event_str[i]))) == 0)\n", fsm->name);
- fprintf (f, "\t\t\treturn i;\n");
- fprintf (f, "\treturn FSM_EVENT_%s_NB_;\n", fsm->name);
- fprintf (f, "}\n\n");
-
- /* Convert an state enum in string. */
- fprintf (f, "char *\nfsm_%s_get_state_string_from_enum \
- (fsm_%s_state_t s)\n{\n", fsm->name, fsm->name);
- fprintf (f, "\treturn strcpy_P (fsm_%s_str_buff, \
- (char *) pgm_read_word (&(fsm_%s_state_str[s])));\n", fsm->name, fsm->name);
- fprintf (f, "}\n\n");
-
- /* Convert a state string in enum. */
- fprintf (f, "fsm_%s_state_t\nfsm_%s_get_state_enum_from_string \
- (char *str)\n{\n", fsm->name, fsm->name);
- fprintf (f, "\tuint16_t i;\n");
- fprintf (f, "\tfor (i = 0; i < FSM_STATE_%s_NB_; i++)\n", fsm->name);
- fprintf (f, "\t\tif (strcpy_P (str, \
- (char *) pgm_read_word (&(fsm_%s_state_str[i]))) == 0)\n", fsm->name);
- fprintf (f, "\t\t\treturn i;\n");
- fprintf (f, "\treturn FSM_STATE_%s_NB_;\n", fsm->name);
- fprintf (f, "}\n\n");
- }
-
- /* Gen function table. */
- fprintf (f, "const fsm_%s_func_t PROGMEM fsm_%s_trans_table[%u][%u] = \n{\n",
- fsm->name,
- fsm->name,
- fsm->event_nb,
- fsm->state_nb);
- /* for each events and state, see if it exists an associated transition. */
- for (i = 0; i < fsm->event_nb; i++)
- {
- e = fsm_build_get_event_by_code (fsm, i);
- fprintf (f, "\t{");
- for (j = 0; j < fsm->state_nb; j++)
- {
- s = fsm_build_get_state_by_code (fsm, j);
- tc = fsm->trans;
- found = 0;
- while (tc != NULL)
- {
- if (tc->trans.state == s && tc->trans.event == e)
- {
- found = 1;
- fprintf (f, "&fsm_%s_trans_func_%s_%s",
- fsm->name,
- tc->trans.state->var_name,
- tc->trans.event->var_name);
- tc = tc->next;
- break;
- }
- tc = tc->next;
- }
- if (!found)
- fprintf (f, "(fsm_%s_func_t) 0", fsm->name);
- if (j == fsm->state_nb - 1)
- fprintf (f, "}");
- else
- fprintf (f, ", ");
- }
- if (i != fsm->event_nb - 1)
- fprintf (f, ",");
- fprintf (f, "\n");
- }
- fprintf (f, "};\n\n");
-
- /* Gen read function for trans table. */
- fprintf (f, "fsm_%s_func_t fsm_%s_read_trans (fsm_%s_event_t event, "
- "fsm_%s_state_t state)\n{\n",
- fsm->name,
- fsm->name,
- fsm->name,
- fsm->name);
- fprintf (f, "\treturn (fsm_%s_func_t) pgm_read_word "
- "(&fsm_%s_trans_table[event][state]);\n",
- fsm->name,
- fsm->name);
- fprintf (f, "}\n\n");
-
- /* Gen active states array. */
- fprintf (f, "fsm_%s_state_t fsm_%s_active_states[%u];\n\n",
- fsm->name,
- fsm->name,
- fsm->max_active_states);
-
- /* Gen initialization function. */
- sc = fsm->starters;
- i = 0;
- fprintf (f, "void\nfsm_%s_init ()\n{\n", fsm->name);
- while (sc != NULL)
- {
- fprintf (f, "\tfsm_%s_active_states[%u] = %u;\n",
- fsm->name,
- i,
- sc->state.code);
- if (fsm->timeouts != NULL)
- {
- toc = fsm->timeouts;
- while (toc != NULL)
- {
- if (toc->timeout.trans->state->code == sc->state.code)
- {
- fprintf (f, "\tfsm_%s_timeout_counters[%u] = %u;\n",
- fsm->name,
- i,
- toc->timeout.timeout);
- }
- toc = toc->next;
- }
- }
- i++;
- sc = sc->next;
- }
- fprintf (f, "}\n\n");
-
- /* Gen handle function. */
- fprintf (f, "int\nfsm_%s_handle (fsm_%s_event_t e)\n{\n",
- fsm->name,
- fsm->name);
- fprintf (f, "\tuint16_t i;\n");
- fprintf (f, "\tint handled = 0;\n");
- fprintf (f, "\tfor (i = 0; i < fsm_%s_max_active_states; i++)\n\t{\n",
- fsm->name);
- fprintf (f, "\t\tif (fsm_%s_read_trans (e, fsm_%s_active_states[i]))\n",
- fsm->name,
- fsm->name);
- fprintf (f, "\t\t{\n");
- fprintf (f, "\t\t\tfsm_%s_state_t old_state = fsm_%s_active_states[i];\n",
- fsm->name,
- fsm->name);
- fprintf (f, "\t\t\tfsm_%s_active_states[i] = fsm_%s_read_trans (e, "
- "fsm_%s_active_states[i])();\n",
- fsm->name,
- fsm->name,
- fsm->name);
- fprintf (f, "\t\t\tlogger_log (old_state, e, "
- "fsm_%s_active_states[i]);\n",
- fsm->name);
- fprintf (f, "\t\t\tproto_send3b ('F', old_state, e, "
- "fsm_%s_active_states[i]);\n",
- fsm->name);
- fprintf (f, "\t\t\thandled = 1;\n");
- if (fsm->timeouts != NULL)
- {
- fprintf (f, "\t\t\tfsm_%s_timeout_counters[i] = "
- "fsm_%s_timeout_values[fsm_%s_active_states[i]];\n",
- fsm->name,
- fsm->name,
- fsm->name);
- }
- fprintf (f, "\t\t}\n");
- fprintf (f, "\t}\n");
- fprintf (f, "\treturn handled;\n");
- fprintf (f, "}\n\n");
-
- /* Gen can handle function. */
- fprintf (f, "uint16_t\nfsm_%s_can_handle (fsm_%s_event_t e)\n{\n",
- fsm->name,
- fsm->name);
- fprintf (f, "\tuint16_t i;\n");
- fprintf (f, "\tfor (i = 0; i < fsm_%s_max_active_states; i++)\n",
- fsm->name);
- fprintf (f, "\t\tif (fsm_%s_read_trans (e, fsm_%s_active_states[i]))\n",
- fsm->name,
- fsm->name);
- fprintf (f, "\t\t\treturn 1;\n");
- fprintf (f, "\treturn 0;\n");
- fprintf (f, "}\n\n");
-
- if (fsm->timeouts != NULL)
- {
- /* Gen timeout counters array. */
- fprintf (f, "int32_t fsm_%s_timeout_counters[%u];\n",
- fsm->name,
- fsm->max_active_states);
-
- /* Gen timeout values array. */
- fprintf (f, "int32_t fsm_%s_timeout_values[FSM_STATE_%s_NB_] =\n{\n",
- fsm->name,
- fsm->name);
- int value;
- for (i = 0; i < fsm->state_nb; i++)
- {
- value = -1;
- s = fsm_build_get_state_by_code (fsm, i);
- assert (s);
- toc = fsm->timeouts;
- while (toc != NULL)
- {
- if (s->code == toc->timeout.trans->state->code)
- {
- value = toc->timeout.timeout;
- break;
- }
- toc = toc->next;
- }
- fprintf (f, "\t%i", value);
- if (i != fsm->state_nb - 1)
- fprintf (f, ",");
- fprintf (f, "\n");
- }
- fprintf (f, "};\n\n");
-
- /* Gen timeout corresponding events array. */
- fprintf (f, "fsm_%s_event_t fsm_%s_timeout_events[FSM_STATE_%s_NB_] =\n{\n",
- fsm->name,
- fsm->name,
- fsm->name);
- for (i = 0; i < fsm->state_nb; i++)
- {
- value = -1;
- s = fsm_build_get_state_by_code (fsm, i);
- assert (s);
- toc = fsm->timeouts;
- while (toc != NULL)
- {
- if (s->code == toc->timeout.trans->state->code)
- {
- value = toc->timeout.trans->event->code;
- break;
- }
- toc = toc->next;
- }
- if (value == -1)
- fprintf (f, "\tFSM_STATE_%s_NB_", fsm->name);
- else
- fprintf (f, "\t%u", value);
-
- if (i != fsm->state_nb - 1)
- fprintf (f, ",");
- fprintf (f, "\n");
- }
- fprintf (f, "};\n\n");
-
- /* Gen handle timeout function. */
- fprintf (f, "int\nfsm_%s_handle_timeout ()\n{\n",
- fsm->name);
- fprintf (f, "\tuint16_t i;\n");
- fprintf (f, "\tint out = 0;\n");
- fprintf (f, "\tfor (i = 0; i < fsm_%s_max_active_states; i++)\n\t{\n",
- fsm->name);
- fprintf (f, "\t\tif (fsm_%s_timeout_counters[i] > 0)\n\t\t{\n",
- fsm->name);
- fprintf (f, "\t\t\tfsm_%s_timeout_counters[i]--;\n",
- fsm->name);
- fprintf (f, "\t\t\tif (fsm_%s_timeout_counters[i] == 0)\n\t\t\t{\n",
- fsm->name);
- fprintf (f, "\t\t\t\tfsm_%s_handle (fsm_%s_timeout_events[fsm_%s_active_states[i]]);\n",
- fsm->name,
- fsm->name,
- fsm->name);
- fprintf (f, "\t\t\t\tout = 1;\n");
- fprintf (f, "\t\t\t}\n");
- fprintf (f, "\t\t}\n");
- fprintf (f, "\t}\n");
- fprintf (f, "\treturn out;\n");
- fprintf (f, "}\n\n");
- }
-
- /* Close file. */
- fclose (f);
-
- /* Free. */
- free (fn);
-}
-
-void
-fsm_build_gen (char *arch, uint embedded_strings)
-{
- fsm_build_chain_t *curs = fsm_build_all_fsm;
- while (curs != NULL)
- {
- if (strcmp (arch, "AVR") == 0)
- {
- fsm_build_gen_avr_h (curs->fsm, embedded_strings);
- fsm_build_gen_avr_c (curs->fsm, embedded_strings);
- }
- curs = curs->next;
- }
-}
-
-void
-fsm_build_free (fsm_build_t *fsm)
-{
- fsm_build_state_chain_t *sc;
- fsm_build_state_chain_t *sc_tmp;
- fsm_build_event_chain_t *ec;
- fsm_build_event_chain_t *ec_tmp;
- fsm_build_trans_chain_t *tc;
- fsm_build_trans_chain_t *tc_tmp;
- fsm_build_branch_chain_t *bc;
- fsm_build_branch_chain_t *bc_tmp;
- fsm_trans_func_chain_t *fc;
- fsm_trans_func_chain_t *fc_tmp;
- fsm_build_timeout_chain_t *toc;
- fsm_build_timeout_chain_t *toc_tmp;
- uint i;
-
- /* Free states. */
- sc = fsm->states;
- while (sc != NULL)
- {
- sc_tmp = sc;
- free (sc->state.var_name);
- sc = sc->next;
- free (sc_tmp);
- }
-
- /* Free events. */
- ec = fsm->events;
- while (sc != NULL)
- {
- ec_tmp = ec;
- free (ec->event.var_name);
- ec = ec->next;
- free (ec_tmp);
- }
-
- /* Free trans */
- tc = fsm->trans;
- while (tc != NULL)
- {
- tc_tmp = tc;
-
- /* Free each branches. */
- bc = tc->trans.output_branches;
- while (bc != NULL)
- {
- bc_tmp = bc;
- free (bc->name);
- bc = bc->next;
- free (bc_tmp);
- }
-
- tc = tc->next;
- free (tc_tmp);
- }
-
- /* Free start chain. */
- sc = fsm->starters;
- while (sc != NULL)
- {
- sc_tmp = sc;
- sc = sc->next;
- free (sc_tmp);
- }
-
- /* Free timeout chain. */
- toc = fsm->timeouts;
- while (toc != NULL)
- {
- toc_tmp = toc;
- toc = toc->next;
- free (toc_tmp);
- }
-
- /* Free run data (trans_table). */
- for (i = 0; i < fsm->event_nb; i++)
- free (fsm->run.trans_table[i]);
- free (fsm->run.trans_table);
-
- /* Free run data (active states). */
- free (fsm->run.active_states);
-
- /* Free last-seen event array*/
- free (fsm->run.events_before_active_state);
-
- /* Free run data (function pool). */
- fc = fsm->run.func_pool;
- while (fc != NULL)
- {
- fc_tmp = fc;
- fc = fc->next;
- free (fc_tmp);
- }
-
- /*Free run data (timeout counters). */
- free (fsm->run.timeout_counters);
-}
-
diff --git a/digital/ai/src/fsm/init.c b/digital/ai/src/fsm/init.c
index 60e6b088..72479a32 100644
--- a/digital/ai/src/fsm/init.c
+++ b/digital/ai/src/fsm/init.c
@@ -28,8 +28,8 @@
#include "contact.h"
#include "chrono.h"
-#define FSM_NAME AI
-#include "fsm.h"
+#define ANGFSM_NAME AI
+#include "angfsm.h"
#include "fsm_queue.h"
#include "bot.h"