#ifndef H_ED_FSM_20030404085131
#define H_ED_FSM_20030404085131

#ifdef __cplusplus
extern "C"
{
#endif

/* ---------------------------------------------------------------------
   (c) ED 1998-2008
   Project      : CLIB
   Function     : Finite State Machine (FSM) manager
   Module       : CL_FSM
   File         : CL_FSM.H
   Created      : 15-02-1998
   Modified     : 20-05-2008
   --------------------------------------------------------------------- */
/* *INDENT-OFF* */
/* ---------------------------------------------------------------------
   Log

    2.15 20-05-2008 'this' becomes 'self' (C++ compatible)
    2.14 04-12-2003 Implementation : explicit pointer to functions removed on
                    interface.
    2.13 28-05-2003 Reset command 'FSM_EVT_RESET' added to FSM_engine().
    2.12 15-04-2003 Cast added for '-1'. Minor comments fixes
    2.11 16-10-2002 Translated in English. Layout
                    FSM_list() debugging.
                    Initial state added to FSM_init().
                    Error status added to FSM_transition()
                    info management redesigned
    2.10 19-09-2002 "sysalloc.h" removed from header. sys_*() removed
    2.9  13-07-2002 LCLint
    2.8  01-07-2002 Object renamed in FSM
    2.7  25-04-2002 Object renamed in CL_FSM
    2.6  20-02-2002 Static version
                   Define the FSM_DYN macro for a dynamic version
                  'pFsm' becomes 'this'
    2.5  03-09-2001 Macro FSM_MEMCHK added (well, supposed to be...)
    2.4  18-01-2001 sELEM becomes sFSM_ELEM
    2.3  16-01-2001 Data become public.
    2.2  16-11-2000 Function FSM_dbg_str_dyn() added
                   sys_calloc() replaced by sys_malloc()
    2.1  31-05-2000 Function FSM_info() added
    2.0  20-03-2000 Data become private. Cloning
    1.9  07-12-1999 szTag = "ERR" on error
    1.8  04-12-1999 AUT becomes FSM
    1.7  13-10-1999 calloc() and free() replaced by sys_*
    1.6  06-10-1999 <aut.h> becomes "aut.h"
    1.5  15-01-1999 The context is passed in the debug transition
    1.4  16-12-1998 Port to Win32 (return types changed from WORD to int)
    1.3  08-09-1998 Integration to the CLIB project
    1.2  26-05-1998 Adaptation to H.320
    1.1  15-02-1998 Data context added
    1.0  15-02-1998 Initial version
    0.0  15-02-1998 Creation

   Specification
   -------------

   The FSM object allows the implementation of Finie State Machines:

   . Application                 |         FSM
   .                             |
   .                             |
   . call init() ----------------|-------> init()
   .      <----------------------|-------- cr
   .                             |
   . call transition() ----------|-------> transition()
   .      <----------------------|-------- cr
   .                             |
   . call engine() --------------|-------> engine()
   .       [debug() <- - - - - - | - - - - - callback pDebug()]
   .        action() <-----------|---------- callback pAction()
   .        cr      -------------|---------> cr
   .      <----------------------|-------- cr

   Notes
   -----

   The FSM_DYN externally defined macro
   ------------------------------------

   Not defined : the object uses the static memory
   Defined     : the object uses the dynamic memory (intenal malloc/free)

   --------------------------------------------------------------------- */
/* *INDENT-ON* */

#include <stddef.h>
#include "ed/inc/types.h"

/* public data ========================================================= */
/* macros ============================================================== */

#ifdef FSM_DYN
#define FSM_MODE FSM_MODE_DYN
#else
#define FSM_MODE FSM_MODE_STA
#endif

/* 0 = err 1 = OK */
#define FSM_CHK_LIB (FSM_mode () == FSM_MODE)

#define FSM_EVT_RESET ((size_t) -1)

/* constants =========================================================== */

/* compile mode */
   typedef enum
   {
      FSM_MODE_STA,
      FSM_MODE_DYN,
      FSM_MODE_NB
   }
   eFSM_MODE;

/* error numbers */
   typedef enum
   {
      FSM_OK,

#define ITEM(e, s) \
   FSM_ERR_##e,
#include "ed/inc/fsm_err.itm"
#undef ITEM

      FSM_ERR_NB
   }
   eFSM_ERR;

/* types =============================================================== */
/* structures ========================================================== */
   typedef struct
   {
      size_t Ini;               /* initial status */
      size_t Fin;               /* final status */
      size_t Evt;               /* event */
      const char *szTag;        /* Transition tag */
      void *pData;              /* user context */
   }
   sFSM_INFO;

/* debug callback function. Called by transitions */
   typedef void fFSM_DEBUG (const sFSM_INFO * pInfo);

/* transition callback */
   typedef int fFSM_TRANSITION (void *pdata);

   typedef struct
   {
      size_t sts;               /* Next status */
      fFSM_TRANSITION *pfTransition;  /* pointer to the transition action */
      char const *stag;         /* Name of the transition */
   }
   sFSM_ELEM;

   typedef struct
   {
      size_t sts;               /* current status */
      size_t sts0;              /* initial status */
      size_t Nb_evt;            /* event number */
      size_t Nb_sts;            /* status number */
      sFSM_ELEM *tab;           /* pointeur to the elements array */
      size_t Tra;               /* current transitions number */
      const char *stag;         /* Name of the last transition */
      fFSM_DEBUG *cb_debug;     /* debug CB fonction called at transition */
      sFSM_INFO info;           /* current status */
      eFSM_ERR last_err;        /* last error number */
      uint dyn:1;               /* array status (1 = dyn) */
   }
   sFSM;

/* internal public data ================================================ */
/* internal public functions =========================================== */
/* entry points ======================================================== */

/* ---------------------------------------------------------------------
   FSM_sver()
   ---------------------------------------------------------------------
   Role : Returns a "Version" string
   ---------------------------------------------------------------------
   E :
   S : constant string pointer
   --------------------------------------------------------------------- */
   const char *FSM_sver (void);

/* ---------------------------------------------------------------------
   FSM_sid()
   ---------------------------------------------------------------------
   Role : Returns an "Identification" string
   ---------------------------------------------------------------------
   E :
   S : constant string pointer
   --------------------------------------------------------------------- */
   const char *FSM_sid (void);

/* ---------------------------------------------------------------------
   FSM_mode()
   ---------------------------------------------------------------------
   Role : Returns the compile mode
   ---------------------------------------------------------------------
   E :
   S : compile mode :
   .   - FSM_MODE_STA
   .   - FSM_MODE_DYN
   --------------------------------------------------------------------- */
   eFSM_MODE FSM_mode (void);

#ifdef FSM_DYN
/* ---------------------------------------------------------------------
   FSM_init()
   ---------------------------------------------------------------------
   Creation and Initialisation (Dynamic)
   ---------------------------------------------------------------------
   E : events number
   E : status number
   E : debug function
   E : initial state
   S : object pointer
   --------------------------------------------------------------------- */
   sFSM *FSM_init (size_t const Nb_evt
                   ,size_t const Nb_sts
                   ,fFSM_DEBUG * const cb_debug
                   ,size_t const initial_state
   );
#else
/* ---------------------------------------------------------------------
   FSM_init()
   ---------------------------------------------------------------------
   Role : Initialisation (Static)
   ---------------------------------------------------------------------
   E : object pointer
   E : FSM matrix address (1D matrix)
   E : events number
   E : status number
   E : debug function
   E : initial state
   S : object pointer
   --------------------------------------------------------------------- */
   void FSM_init (sFSM * const self
                  ,sFSM_ELEM * const tab
                  ,size_t const Nb_evt
                  ,size_t const Nb_sts
                  ,fFSM_DEBUG * const cb_debug
                  ,size_t const initial_state
   );
#endif

/* ---------------------------------------------------------------------
   FSM_clone()
   ---------------------------------------------------------------------
   Role : Clonage d'un objet existant
   ---------------------------------------------------------------------
   E : Objet de reference
   S : Objet cree
   --------------------------------------------------------------------- */
#ifdef FSM_DYN
   sFSM *FSM_clone (sFSM const *const pFsmRef);
#else
   void FSM_clone (sFSM * const self, sFSM const *const pFsmRef);
#endif

/* ---------------------------------------------------------------------
   FSM_end()
   ---------------------------------------------------------------------
   Role : Destruction de l'objet
   ---------------------------------------------------------------------
   E : Objet
   S :
   --------------------------------------------------------------------- */
   void FSM_end (sFSM * const self);

/* ---------------------------------------------------------------------
   FSM_transition()
   ---------------------------------------------------------------------
   Role : Definition of a transition
   ---------------------------------------------------------------------
   E : Object
   E : associated action
   E : transition name
   E : Current status
   E : Next status
   E : Event
   S : err :
   .   - 0 = OK
   .   - 1 = transition already defined.
   --------------------------------------------------------------------- */
   int FSM_transition (sFSM * const self
                       ,fFSM_TRANSITION Transition
                       ,char const *const stag
                       ,size_t const Curr
                       ,size_t const Next
                       ,size_t const Evt);

/* ---------------------------------------------------------------------
   FSM_engine()
   ---------------------------------------------------------------------
   Role : Event processing (FSM engine)
   ---------------------------------------------------------------------
   E : Pointeur d'automate
   E : Evenement
   E : Pointeur de donnees associees a l'evenement (strictement applicatif)
   S : -1 : transition non autorisee. Autre : code retour de l'action
   --------------------------------------------------------------------- */
   int FSM_engine (sFSM * const self
                   ,size_t const evt
                   ,void *const pData);

/* ---------------------------------------------------------------------
   FSM_last_err()
   ---------------------------------------------------------------------
   Role : Get the last error string
   ---------------------------------------------------------------------
   E : Objet
   S :
   --------------------------------------------------------------------- */
   eFSM_ERR FSM_last_err (sFSM const *const self);

#ifndef FSM_LIGHT
/* ---------------------------------------------------------------------
   FSM_list()
   ---------------------------------------------------------------------
   Role : Afficher les transitions (DEBUG)
   ---------------------------------------------------------------------
   E : Objet
   S :
   --------------------------------------------------------------------- */
   void FSM_list (sFSM * const self);

/* ---------------------------------------------------------------------
   FSM_info()
   ---------------------------------------------------------------------
   Role : Lire l'etat courant (DEBUG)
   ---------------------------------------------------------------------
   E : Objet
   E : Infos
   S :
   --------------------------------------------------------------------- */
   void FSM_info (sFSM const *const self, sFSM_INFO * const pInfo);

#ifdef FSM_DYN
/* ---------------------------------------------------------------------
   FSM_dbg_str_dyn()
   ---------------------------------------------------------------------
   Role : Fabriquer une chaine de debug (DEBUG). Chaine dynamique
   ---------------------------------------------------------------------
   E : Infos
   S : Chaine
   --------------------------------------------------------------------- */
   char *FSM_dbg_str_dyn (sFSM_INFO const *const pInfo);
#endif                          /* FSM_DYN */

/* ---------------------------------------------------------------------
   FSM_dbg_str()
   ---------------------------------------------------------------------
   Role : Fabriquer une chaine de debug (DEBUG).
   ---------------------------------------------------------------------
   E : Infos
   S : Chaine
   --------------------------------------------------------------------- */
   void FSM_dbg_str (sFSM_INFO const *const pInfo, char *s, size_t const size);

/* ---------------------------------------------------------------------
   FSM_last_err_str()
   ---------------------------------------------------------------------
   Role : Get the last error string
   ---------------------------------------------------------------------
   E : Objet
   S :
   --------------------------------------------------------------------- */
   char const *FSM_last_err_str (sFSM const *const self);

#endif                          /* /FSM_LIGHT */

#ifdef __cplusplus
}
#endif

#endif                          /* H_ED_FSM_20030404085131 */

/* Guards added by GUARD (c) ED 2000-2003 Feb 14 2003 Ver. 1.5 */
