state machine programming – smp

This is a little C program used to show the framework of state machine programming (smp,状态机编程). Detailed state transition picture is as below. Try to build the source code below and enjoy:)

/*
* State Machine Program (SMP)
* This program is used to construct basic framework
* of state machine programming, which is very useful
* in telecom software. Imagine when a protocol stack,
* multi-threads and socket are involved here…
* Language: C/C++
* OS: Unix/Linux
* Originated: Dec 29, 2010
* dave.tian@alcatel-lucent.com
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MSG_BUF_SIZE_MAX        1000

/* Event definition used to tigger State transition */
typedef enum _QuestionEvent
{
QUESTION_NONE,
QUESTION_HI,
QUESTION_WHO_ARE_YOU,
QUESTION_BYE,
QUESTION_NOT_SUPPORTED,
QUESTION_MAX
} QuestionEvent;

/* State definition */
typedef enum _ProgramMoodState
{
PROGRAM_MOOD_STATE_NONE,
PROGRAM_MOOD_STATE_GOOD,
PROGRAM_MOOD_STATE_HIGH,
PROGRAM_MOOD_STATE_ANY,
PROGRAM_MOOD_STATE_MAX
} ProgramMoodState;

/* Function definition for State transition */
typedef void (*ProgramActionFunction) (void);

/* State Machine transition element definition */
typedef struct _ProgramStateMachineTransition
{
ProgramMoodState currentState;
QuestionEvent eventReceived;
ProgramActionFunction actionFunction;
ProgramMoodState newState;
} ProgramStateMachineTransition;

/* State Machine entry definition used during transition */
typedef struct _ProgramStateMachineEntry
{
ProgramActionFunction actionFunction;
ProgramMoodState newState;
} ProgramStateMachineEntry;

/* Action function declaration for different state transition
* ‘static’ is used here to guarantee that the function could
* only be used within this source file */
static void processOthers( void);
static void processWhoAreYouBeforeHi( void);
static void processByeBeforeHi( void);
static void processHiAfterHi( void);
static void processByeAfterHi( void);
static void processHiAfterWhoAreYou( void);
static void processWhoAreYouAfterWhoAreYou( void);
static void processHi( void);
static void processWhoAreYou( void);
static void processBye( void);

/* State Machine transition table definition
* ‘static’ is used here to guarantee that only
* functions in this source file could access this table */
static ProgramStateMachineTransition programSMTtable[] =
{

/* This is the core part of State Machine Programming */
/* Unexpected state transition handling below */
{PROGRAM_MOOD_STATE_ANY, QUESTION_NOT_SUPPORTED, processOthers, PROGRAM_MOOD_STATE_NONE},
{PROGRAM_MOOD_STATE_NONE, QUESTION_WHO_ARE_YOU, processWhoAreYouBeforeHi, PROGRAM_MOOD_STATE_NONE},
{PROGRAM_MOOD_STATE_NONE, QUESTION_BYE, processByeBeforeHi, PROGRAM_MOOD_STATE_NONE},
{PROGRAM_MOOD_STATE_GOOD, QUESTION_HI, processHiAfterHi, PROGRAM_MOOD_STATE_GOOD},
{PROGRAM_MOOD_STATE_GOOD, QUESTION_BYE, processByeAfterHi, PROGRAM_MOOD_STATE_NONE},
{PROGRAM_MOOD_STATE_HIGH, QUESTION_HI, processHiAfterWhoAreYou, PROGRAM_MOOD_STATE_HIGH},
{PROGRAM_MOOD_STATE_HIGH, QUESTION_WHO_ARE_YOU, processWhoAreYouAfterWhoAreYou, PROGRAM_MOOD_STATE_HIGH},

/* Expected state transition handling below */
{PROGRAM_MOOD_STATE_NONE, QUESTION_HI, processHi, PROGRAM_MOOD_STATE_GOOD},
{PROGRAM_MOOD_STATE_GOOD, QUESTION_WHO_ARE_YOU, processWhoAreYou, PROGRAM_MOOD_STATE_HIGH},
{PROGRAM_MOOD_STATE_HIGH, QUESTION_BYE, processBye, PROGRAM_MOOD_STATE_NONE}
};

/* Max number of entries definition used to State Machine initialization
* for SMP, this value is used to determine how many entries init’ed from
* programSMTtable[] to programSMTentry[][]. This value should not bigger
* than the max size of array programSMTtable. Once programSMTtable[] is
* added new state transitions, this value needs to be updated */
#define STATE_MACHINE_ENTRY_MAX         10

/* State Machine transition entry definition
* used to provide usable entry to State Machine
* transition table – init’ed by transition table */
static ProgramStateMachineEntry programSMTentry[ PROGRAM_MOOD_STATE_MAX][ QUESTION_MAX];

int main ( void)
{

/* Globle variable standing for this program’s mood */
ProgramMoodState myMood = PROGRAM_MOOD_STATE_NONE;

/* Globel variable standing for event got from user */
QuestionEvent myEvent = QUESTION_NONE;

char msgBuf[ MSG_BUF_SIZE_MAX];
char *stringPtr;
int i;

printf(“nState Machine Program (SMP)n”);
printf(“Developed by Stupid Maniac Programmer (SMP) davetin”);
printf(“dave.tian@alcatel-lucent.comn”);
printf(“Type ‘help’ for detailed usagen”);

/* Init State Machine (entry) */
initSMT();

while ( 1)
{
myEvent = QUESTION_NONE;
printf(“n>> “);

/*
* scanf() is unable to support empty input – stupid
* gets() is able to cause buffer overflow – dangerous
* fgets() is including the newline right before ” – no comment
*/

/* Note: newline is read into buffer 2! */
fgets( msgBuf, MSG_BUF_SIZE_MAX, stdin);

/* Change the newline to null */
msgBuf[ strlen( msgBuf) – 1] = ”;

stringPtr = msgBuf;
for ( i = 0; i < strlen( msgBuf); i++)
{
if ( isspace( msgBuf[ i]))
{

/* Bypass the whitespaces forwarded */
stringPtr++;
}
else
{
break;
}
}

if ( stringPtr == msgBuf + strlen( msgBuf))
{

/* No valid input in this time */
continue;
}

if ( strcasecmp( stringPtr, “hi”) == 0)
{
myEvent = QUESTION_HI;
}
else if ( strcasecmp( stringPtr, “whoru”) == 0)
{
myEvent = QUESTION_WHO_ARE_YOU;
}
else if ( strcasecmp( stringPtr, “bye”) == 0)
{
myEvent = QUESTION_BYE;
}
else if ( strcasecmp( stringPtr, “help”) == 0)
{
showHelp();
continue;
}
else if (strcasecmp( stringPtr, “exit”) == 0)
{

/* Exit SMP */
return 0;
}
else
{
myEvent = QUESTION_NOT_SUPPORTED;
}

/* Start State Machine Transition */
startSMT( &myMood, myEvent);
}

return 0;
}

/* State Machine (entry) initialization function definition */
void initSMT( void)
{
QuestionEvent e;
ProgramMoodState s, sNew;
ProgramActionFunction af;
int i;

for ( i = 0; i < STATE_MACHINE_ENTRY_MAX; i++)
{
s = programSMTtable[ i].currentState;
e = programSMTtable[ i].eventReceived;
af = programSMTtable[ i].actionFunction;
sNew = programSMTtable[ i].newState;

programSMTentry[ s][ e].actionFunction = af;
programSMTentry[ s][ e].newState = sNew;
}
}

/* State Machine transition function definition */
void startSMT( ProgramMoodState *myMood, QuestionEvent event)
{
ProgramMoodState mState;
ProgramStateMachineEntry *smEntry;

if ( event == QUESTION_NOT_SUPPORTED)
{

/* Update the local mood state to wildcard */
mState = PROGRAM_MOOD_STATE_ANY;
}
else
{

/* Set the local mood state to globle mood */
mState = *myMood;
}

/* Do the mapping via programSMTtable */
smEntry = &programSMTentry[ mState][ event];

/* Note: no pointer checking here – memory fault may happen if
* un-covered state transition in state machine transition table
* is triggered here – be ware of this! */

/* Call for action function */
smEntry->actionFunction();

/* Update the globle mood with new state */
*myMood = smEntry->newState;
}

/* Detailed action function definitions */
void processWhoAreYouBeforeHi( void)
{
printf(“Hey, Man, u never say hi to me before asking who i am…n”);
}

void processByeBeforeHi( void)
{
printf(“Hey, Man, u never say hi before saying bye to me…ok, bye…n”);
}

void processHiAfterHi( void)
{
printf(“Hey, Man, I am sure this is not the first time u saying hi to me…r u a hi machine?n”);
}

void processByeAfterHi( void)
{
printf(“Bye, Man!n”);
}

void processHiAfterWhoAreYou( void)
{
printf(“Hey, Man, u are saying hi to me againe…ok, hi…n”);
}

void processWhoAreYouAfterWhoAreYou( void)
{
printf(“Hey, Man, u did ask me this question before right? I am SMP, us 2?n”);
}

void processOthers( void)
{
printf(“Hey, Man, couldn’t you please make me feel a little better?n”);
}

void processHi( void)
{
printf(“Hi, Man, you are so nice!n”);
}

void processWhoAreYou( void)
{
printf(“As you might have already known, I am a stupid State Machine Program coded by a nuts job…n”);
}

void processBye( void)
{
printf(“Bye, Man, wish you a good day!n”);
}

/* Stupid Boring help function definition */
void showHelp( void)
{
char dispBuf[ MSG_BUF_SIZE_MAX];
snprintf( dispBuf, MSG_BUF_SIZE_MAX, “%s”,
“SMP supports following questions/commands belown”
“hi – say hello to SMPn”
“whoru – ask SMP ‘who are you’n”
“bye – say byebye to SMPn”
“help – show this help menun”
“exit – exit SMPn”
“Note: any other words to SMP would make her feel unhappy!n” );

printf(“%s”, dispBuf);
}

About daveti

Interested in kernel hacking, compilers, machine learning and guitars.
This entry was posted in Dave's Tools, Programming and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.