|
i |
Here is a simple example. It decides whether or not the input properly represents a list of value ranges. The input syntax is approximately:
[[ '!' ] <lo-num>] ['-' [<hi-num>]] \
[',' [[ '!' ] <lo-num>] ['-' [<hi-num>]] ... ]
If there is no hyphen, then a number must be present.
You should not have more than one "bang" operator,
but this FSM does not check for that.
This page contains: The input definitions See the usage page for a description of the attributes supported.
AutoGen Definitions fsm;
#if 0
Here is a simple example. It decides whether or not the input properly
represents a list of value ranges. The input syntax is approximately:
[[ '!' ] <lo-num>] ['-' [<hi-num>]] \
[',' [[ '!' ] <lo-num>] ['-' [<hi-num>]] ... ]
#endif
event = comma, num, dash, bang, eol;
state = lonum, dash, hinum;
type = looping;
method = case;
prefix = ex;
cookie = "void* cookie";
dash = "-";
bang = "!";
eol = "End-Of-Line";
comma = ",";
/*
* Define a transition for every valid transition.
* Specify the Transition_STate, the TransitionEVent and
* what the NEXT state will be. A unique transition
* enumeration will be produced for each defined transition.
*/
transition = { tst = init; tev = num; next = lonum; };
transition = { tst = init; tev = bang; next = init; };
transition = { tst = dash; tev = num; next = hinum; };
/*
* Dash transition. Always go to 'dash' state, except when we are in
* the 'hinum' or 'dash' state. Then, do the 'invalid' transition.
*/
transition = { tst = "*"; tev = dash; next = dash; },
{ tst = hinum, dash; tev = dash; ttype = invalid; next = invalid; };
/*
* Comma transition, other than in 'init'. You cannot have two
* commas together and you cannot start with one. Transitions out of
* "hinum" state require no processing.
*/
transition = { tst = "*"; tev = comma; next = init; },
{ tst = hinum; tev = comma; ttype = noop; next = init; },
{ tst = init; tev = comma; ttype = invalid; next = invalid; };
/*
* End of line transition, other than in 'init'.
* You cannot end with a comma or without any ranges specified.
*/
transition = { tst = "*"; tev = eol; next = done; },
{ tst = hinum; tev = eol; ttype = noop; next = done; },
{ tst = init; tev = eol; ttype = invalid; next = invalid; };
back to top
#ifndef AUTOFSM_EXAMPLE_FSM_H_GUARD
#define AUTOFSM_EXAMPLE_FSM_H_GUARD 1
/**
* Finite State machine States
*
* Count of non-terminal states. The generated states INVALID and DONE
* are terminal, but INIT is not :-).
*/
#define EX_STATE_CT 4
typedef enum {
EX_ST_INIT, EX_ST_LONUM, EX_ST_DASH, EX_ST_HINUM, EX_ST_INVALID,
EX_ST_DONE
} te_ex_state;
/**
* Finite State machine transition Events.
*
* Count of the valid transition events
*/
#define EX_EVENT_CT 5
typedef enum {
EX_EV_COMMA, EX_EV_NUM, EX_EV_DASH, EX_EV_BANG, EX_EV_EOL,
EX_EV_INVALID
} te_ex_event;
/**
* Run the FSM. Will return EX_ST_DONE or EX_ST_INVALID
*/
extern te_ex_state
ex_run_fsm(
void* cookie );
#endif /* AUTOFSM_EXAMPLE_FSM_H_GUARD */
back to topAnd the associated code file:
#define DEFINE_FSM
#include "example-fsm.h"
#include <stdio.h>
/*
* Do not make changes to this file, except between the START/END
* comments, or it will be removed the next time it is generated.
*/
/* START === USER HEADERS === DO NOT CHANGE THIS COMMENT */
/* END === USER HEADERS === DO NOT CHANGE THIS COMMENT */
#ifndef NULL
# define NULL 0
#endif
/**
* Enumeration of the valid transition types
* Some transition types may be common to several transitions.
*/
typedef enum {
EX_TR_DASH_COMMA,
EX_TR_DASH_EOL,
EX_TR_DASH_NUM,
EX_TR_INIT_BANG,
EX_TR_INIT_DASH,
EX_TR_INIT_NUM,
EX_TR_INVALID,
EX_TR_LONUM_COMMA,
EX_TR_LONUM_DASH,
EX_TR_LONUM_EOL,
EX_TR_NOOP
} te_ex_trans;
#define EX_TRANSITION_CT 11
/**
* State transition handling map. Map the state enumeration and the event
* enumeration to the new state and the transition enumeration code (in that
* order). It is indexed by first the current state and then the event code.
*/
typedef struct ex_transition t_ex_transition;
struct ex_transition {
te_ex_state next_state;
te_ex_trans transition;
};
static const t_ex_transition
ex_trans_table[ EX_STATE_CT ][ EX_EVENT_CT ] = {
/* STATE 0: EX_ST_INIT */
{ { EX_ST_INVALID, EX_TR_INVALID }, /* EVT: , */
{ EX_ST_LONUM, EX_TR_INIT_NUM }, /* EVT: NUM */
{ EX_ST_DASH, EX_TR_INIT_DASH }, /* EVT: - */
{ EX_ST_INIT, EX_TR_INIT_BANG }, /* EVT: ! */
{ EX_ST_INVALID, EX_TR_INVALID } /* EVT: End-Of-Line */
},
/* STATE 1: EX_ST_LONUM */
{ { EX_ST_INIT, EX_TR_LONUM_COMMA }, /* EVT: , */
{ EX_ST_INVALID, EX_TR_INVALID }, /* EVT: NUM */
{ EX_ST_DASH, EX_TR_LONUM_DASH }, /* EVT: - */
{ EX_ST_INVALID, EX_TR_INVALID }, /* EVT: ! */
{ EX_ST_DONE, EX_TR_LONUM_EOL } /* EVT: End-Of-Line */
},
/* STATE 2: EX_ST_DASH */
{ { EX_ST_INIT, EX_TR_DASH_COMMA }, /* EVT: , */
{ EX_ST_HINUM, EX_TR_DASH_NUM }, /* EVT: NUM */
{ EX_ST_INVALID, EX_TR_INVALID }, /* EVT: - */
{ EX_ST_INVALID, EX_TR_INVALID }, /* EVT: ! */
{ EX_ST_DONE, EX_TR_DASH_EOL } /* EVT: End-Of-Line */
},
/* STATE 3: EX_ST_HINUM */
{ { EX_ST_INIT, EX_TR_NOOP }, /* EVT: , */
{ EX_ST_INVALID, EX_TR_INVALID }, /* EVT: NUM */
{ EX_ST_INVALID, EX_TR_INVALID }, /* EVT: - */
{ EX_ST_INVALID, EX_TR_INVALID }, /* EVT: ! */
{ EX_ST_DONE, EX_TR_NOOP } /* EVT: End-Of-Line */
}
};
#define ExFsmErr_off 19
#define ExEvInvalid_off 75
#define ExStInit_off 83
static char const zExStrings[127] =
/* 0 */ "** OUT-OF-RANGE **\0"
/* 19 */ "FSM Error: in state %d (%s), event %d (%s) is invalid\n\0"
/* 75 */ "invalid\0"
/* 83 */ "init\0"
/* 88 */ "lonum\0"
/* 94 */ "dash\0"
/* 99 */ "hinum\0"
/* 105 */ ",\0"
/* 107 */ "num\0"
/* 111 */ "-\0"
/* 113 */ "!\0"
/* 115 */ "End-Of-Line";
static const size_t aszExStates[4] = {
83, 88, 94, 99 };
static const size_t aszExEvents[6] = {
105, 107, 111, 113, 115, 75 };
#define EX_EVT_NAME(t) ( (((unsigned)(t)) >= 6) \
? zExStrings : zExStrings + aszExEvents[t])
#define EX_STATE_NAME(s) ( (((unsigned)(s)) >= 4) \
? zExStrings : zExStrings + aszExStates[s])
#ifndef EXIT_FAILURE
# define EXIT_FAILURE 1
#endif
static int ex_invalid_transition( te_ex_state st, te_ex_event evt );
/* * * * * * * * * THE CODE STARTS HERE * * * * * * * */
/**
* Print out an invalid transition message and return EXIT_FAILURE
*/
static int
ex_invalid_transition( te_ex_state st, te_ex_event evt )
{
/* START == INVALID TRANS MSG == DO NOT CHANGE THIS COMMENT */
char const * fmt = zExStrings + ExFsmErr_off;
fprintf( stderr, fmt, st, EX_STATE_NAME(st), evt, EX_EVT_NAME(evt));
/* END == INVALID TRANS MSG == DO NOT CHANGE THIS COMMENT */
return EXIT_FAILURE;
}
/**
* Run the FSM. Will return EX_ST_DONE or EX_ST_INVALID
*/
te_ex_state
ex_run_fsm(
void* cookie )
{
te_ex_state ex_state = EX_ST_INIT;
te_ex_event trans_evt;
te_ex_state nxtSt;
te_ex_trans trans;
void* saved_cookie = cookie;
(void)saved_cookie;
while (ex_state < EX_ST_INVALID) {
/* START == FIND TRANSITION == DO NOT CHANGE THIS COMMENT */
trans_evt = GET_NEXT_TRANS();
/* END == FIND TRANSITION == DO NOT CHANGE THIS COMMENT */
#ifndef __COVERITY__
if (trans_evt >= EX_EV_INVALID) {
nxtSt = EX_ST_INVALID;
trans = EX_TR_INVALID;
} else
#endif /* __COVERITY__ */
{
const t_ex_transition* pTT =
ex_trans_table[ ex_state ] + trans_evt;
nxtSt = pTT->next_state;
trans = pTT->transition;
}
switch (trans) {
case EX_TR_DASH_COMMA:
/* START == DASH_COMMA == DO NOT CHANGE THIS COMMENT */
nxtSt = HANDLE_DASH_COMMA();
/* END == DASH_COMMA == DO NOT CHANGE THIS COMMENT */
break;
case EX_TR_DASH_EOL:
/* START == DASH_EOL == DO NOT CHANGE THIS COMMENT */
nxtSt = HANDLE_DASH_EOL();
/* END == DASH_EOL == DO NOT CHANGE THIS COMMENT */
break;
case EX_TR_DASH_NUM:
/* START == DASH_NUM == DO NOT CHANGE THIS COMMENT */
nxtSt = HANDLE_DASH_NUM();
/* END == DASH_NUM == DO NOT CHANGE THIS COMMENT */
break;
case EX_TR_INIT_BANG:
/* START == INIT_BANG == DO NOT CHANGE THIS COMMENT */
nxtSt = HANDLE_INIT_BANG();
/* END == INIT_BANG == DO NOT CHANGE THIS COMMENT */
break;
case EX_TR_INIT_DASH:
/* START == INIT_DASH == DO NOT CHANGE THIS COMMENT */
nxtSt = HANDLE_INIT_DASH();
/* END == INIT_DASH == DO NOT CHANGE THIS COMMENT */
break;
case EX_TR_INIT_NUM:
/* START == INIT_NUM == DO NOT CHANGE THIS COMMENT */
nxtSt = HANDLE_INIT_NUM();
/* END == INIT_NUM == DO NOT CHANGE THIS COMMENT */
break;
case EX_TR_INVALID:
/* START == INVALID == DO NOT CHANGE THIS COMMENT */
exit(ex_invalid_transition(ex_state, trans_evt));
/* END == INVALID == DO NOT CHANGE THIS COMMENT */
break;
case EX_TR_LONUM_COMMA:
/* START == LONUM_COMMA == DO NOT CHANGE THIS COMMENT */
nxtSt = HANDLE_LONUM_COMMA();
/* END == LONUM_COMMA == DO NOT CHANGE THIS COMMENT */
break;
case EX_TR_LONUM_DASH:
/* START == LONUM_DASH == DO NOT CHANGE THIS COMMENT */
nxtSt = HANDLE_LONUM_DASH();
/* END == LONUM_DASH == DO NOT CHANGE THIS COMMENT */
break;
case EX_TR_LONUM_EOL:
/* START == LONUM_EOL == DO NOT CHANGE THIS COMMENT */
nxtSt = HANDLE_LONUM_EOL();
/* END == LONUM_EOL == DO NOT CHANGE THIS COMMENT */
break;
case EX_TR_NOOP: break;
default:
/* START == BROKEN MACHINE == DO NOT CHANGE THIS COMMENT */
exit(ex_invalid_transition(ex_state, trans_evt));
/* END == BROKEN MACHINE == DO NOT CHANGE THIS COMMENT */
}
ex_state = nxtSt;
}
return ex_state;
}
|