/* 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