From 0fe95079677149ca0791aa5edd7dc99c7276748b Mon Sep 17 00:00:00 2001 From: Jerome Jutteau Date: Wed, 27 Feb 2013 21:54:29 +0100 Subject: digital/ai/src/fsm: update angfsm --- digital/ai/src/fsm/Makefile.fsm | 8 +- digital/ai/src/fsm/angfsm.h | 62 + digital/ai/src/fsm/angfsm.host.c | 2456 +++++++++++++++++++++++++++++++++ digital/ai/src/fsm/angfsm_generic.h | 89 ++ digital/ai/src/fsm/angfsm_host_exec.h | 525 +++++++ digital/ai/src/fsm/angfsm_renaming.h | 45 + digital/ai/src/fsm/fsm.h | 566 -------- digital/ai/src/fsm/fsm.host.c | 1607 --------------------- digital/ai/src/fsm/init.c | 4 +- 9 files changed, 3183 insertions(+), 2179 deletions(-) create mode 100644 digital/ai/src/fsm/angfsm.h create mode 100644 digital/ai/src/fsm/angfsm.host.c create mode 100644 digital/ai/src/fsm/angfsm_generic.h create mode 100644 digital/ai/src/fsm/angfsm_host_exec.h create mode 100644 digital/ai/src/fsm/angfsm_renaming.h delete mode 100644 digital/ai/src/fsm/fsm.h delete mode 100644 digital/ai/src/fsm/fsm.host.c (limited to 'digital/ai') 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 . + */ + +#include + +#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 . + */ + +#ifdef HOST + +#include "angfsm.h" + +#include +#include +#include +#include + +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 \n\n"); + fprintf (f, "#include \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 \n"); + fprintf (f, "#include \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 . + */ + +/* + 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 . + */ + +/* + You may not include this file in your code, this step is done by angfsm.h + */ + +#ifndef __HOST_EXEC__ +#define __HOST_EXEC__ + +#include +#include + +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 . + */ + +#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 . - */ - -#include - -#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 - -/* 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 . - */ - -#include "fsm.h" - -#include -#include -#include -#include - -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 \n"); - fprintf (f, "#include \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" -- cgit v1.2.3