mirror of
https://github.com/Hizenberg469/Finite-State-Machine.git
synced 2026-04-19 16:42:23 +03:00
Basic apis' ready
This commit is contained in:
40
Makefile
40
Makefile
@@ -3,7 +3,7 @@ CFG ?= debug
|
||||
|
||||
# Config specific settings
|
||||
ifeq ($(CFG),debug)
|
||||
CFLAGS += -DDEBUG
|
||||
CFLAGS += -g -DDEBUG
|
||||
else
|
||||
CFLAGS += -O3 -DNDEBUG
|
||||
endif
|
||||
@@ -22,13 +22,18 @@ endif
|
||||
|
||||
rule : dep | inform
|
||||
|
||||
BUILD_DIR = build/$(CFG)
|
||||
OBJS_DIR = $(BUILD_DIR)/objs
|
||||
BUILD_DIR=bin/$(CFG)
|
||||
OBJS_DIR=objs/$(CFG)
|
||||
LIBDIR=lib/${CFG}
|
||||
SRCDIR=src
|
||||
#--------------------------------------------------
|
||||
|
||||
|
||||
BINARY=$(BUILD_DIR)/fsm
|
||||
CODEDIRS=. ./src
|
||||
APP=$(BUILD_DIR)/app
|
||||
APP_OBJECT=$(OBJS_DIR)/app.o
|
||||
FSMLIB_NAME=fsm
|
||||
FSMLIB=$(LIBDIR)/lib$(FSMLIB_NAME)
|
||||
CODEDIRS=./src
|
||||
INCDIRS=. ./include/ # can be list
|
||||
|
||||
CC=gcc
|
||||
@@ -36,7 +41,7 @@ OPT=-O0
|
||||
#generate files that encode make rules for the .h dependencies
|
||||
DEPFLAGS=-MP -MD
|
||||
#automatically add the -I onto each include directory
|
||||
CFLAGS=-Wall -Wextra -g $(foreach D,$(INCDIRS),-I$(D)) $(OPT) $(DEPFLAGS)
|
||||
CFLAGS+=-Wall -Wextra $(foreach D,$(INCDIRS),-I$(D)) $(OPT) $(DEPFLAGS)
|
||||
|
||||
# for-style iteration (foreach) and regular expression completions (wildcard)
|
||||
CFILES=$(foreach D, $(CODEDIRS),$(wildcard $(D)/*.c))
|
||||
@@ -44,18 +49,31 @@ CFILES=$(foreach D, $(CODEDIRS),$(wildcard $(D)/*.c))
|
||||
OBJECTS=$(patsubst %.c,$(OBJS_DIR)/%.o,$(CFILES))
|
||||
DEPFILES=$(patsubst %.c,$(OBJS_DIR)/%.d,$(CFILES))
|
||||
|
||||
all: $(BINARY)
|
||||
all: $(FSMLIB) $(APP) | create_dir
|
||||
|
||||
$(BINARY): $(OBJECTS)
|
||||
$(CC) -o $@ $^
|
||||
create_dir:
|
||||
mkdir -p $(BUILD_DIR)
|
||||
mkdir -p $(OBJS_DIR)
|
||||
mkdir -p $(LIBDIR)
|
||||
|
||||
|
||||
$(APP): $(APP_OBJECT) | create_dir
|
||||
$(CC) -o $@ $^ -L $(LIBDIR) -l$(FSMLIB_NAME)
|
||||
|
||||
$(FSMLIB): $(OBJECTS) | create_dir
|
||||
ar cr $(LIBDIR)/${FSMLIB}.a ${OBJECTS}
|
||||
|
||||
# only want the .c file dependency here, thus $< instead of $^.
|
||||
#
|
||||
%.o:%.c
|
||||
$(OBJS_DIR)/%.o:$(SRCDIR)/%.c | create_dir
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
$(OBJS_DIR)/%.o:%.c | create_dir
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -rf $(BINARY) $(OBJECTS) $(DEPFILES)
|
||||
rm -rf $(APP) $(APP_OBJECT) $(OBJECTS) $(DEPFILES)
|
||||
rm -rf $(BUILD_DIR) $(OBJS_DIR) $(LIBDIR)
|
||||
|
||||
# shell commands are a set of keystrokes away
|
||||
distribute: clean
|
||||
|
||||
15
app.c
Normal file
15
app.c
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
#include <fsm.h>
|
||||
|
||||
int main(){
|
||||
|
||||
fsm_t* fsm = create_new_fsm("FSM_1");
|
||||
|
||||
state_t* initial_state = create_new_state("q0", FSM_FALSE);
|
||||
set_fsm_initial_state(fsm, initial_state);
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,15 +1,21 @@
|
||||
#ifndef __FSM__
|
||||
#define __FSM__
|
||||
|
||||
typedef struct fsm_ fsm_t;
|
||||
typedef struct state_ state_t;
|
||||
|
||||
#define MAX_INP_BUFFER_SIZE 128
|
||||
/***Constants***/
|
||||
|
||||
#define MAX_INP_BUFFER_LEN 128
|
||||
#define MAX_TRANSITION_TABLE_SIZE 128
|
||||
#define MAX_STATE_NAME_SIZE 32
|
||||
#define MAX_FSM_NAME_SIZE 32
|
||||
#define MAX_TRANSITION_KEY_SIZE 64
|
||||
|
||||
|
||||
/***Data structures and custom datatypes***/
|
||||
|
||||
typedef struct fsm_ fsm_t;
|
||||
typedef struct state_ state_t;
|
||||
|
||||
/*Custom-defined datatype
|
||||
* to define boolean value
|
||||
* for FSM*/
|
||||
@@ -67,6 +73,9 @@ struct fsm_{
|
||||
|
||||
/*Input data fed by application to parse
|
||||
* by FSM library*/
|
||||
char input_buffer[MAX_INP_BUFFER_LEN];
|
||||
|
||||
/*Size of input buffer*/
|
||||
unsigned int input_buffer_size;
|
||||
|
||||
/*Pointer which point to the current input
|
||||
@@ -74,4 +83,51 @@ struct fsm_{
|
||||
unsigned int input_buffer_cursor;
|
||||
};
|
||||
|
||||
|
||||
/***Function Prototypes***/
|
||||
|
||||
fsm_t*
|
||||
create_new_fsm(const char *fsm_name);
|
||||
|
||||
state_t*
|
||||
create_new_state(char *state_name,
|
||||
fsm_bool_t is_final);
|
||||
|
||||
void
|
||||
set_fsm_initial_state(fsm_t *fsm, state_t *state);
|
||||
|
||||
tt_entry_t*
|
||||
create_and_insert_new_tt_entry(tt_t *trans_table,
|
||||
char *transition_key,
|
||||
unsigned int sizeof_key,
|
||||
state_t* next_state);
|
||||
|
||||
|
||||
tt_entry_t*
|
||||
get_next_empty_tt_entry(tt_t *trans_table);
|
||||
|
||||
/**static(hidden) functions***/
|
||||
static inline fsm_bool_t
|
||||
is_tt_entry_empty(tt_entry_t *tt_entry){
|
||||
|
||||
if(!tt_entry->next_state)
|
||||
return FSM_TRUE;
|
||||
|
||||
return FSM_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***Iterators' Macro***/
|
||||
|
||||
#define FSM_ITERATE_TRANS_TABLE_BEGIN(tr_table_ptr, tt_entry_ptr) \
|
||||
do{ \
|
||||
unsigned int index = 0; \
|
||||
for( ; index < MAX_TRANSITION_TABLE_SIZE ; index++ ){ \
|
||||
tt_entry_ptr = &(tr_table_ptr->tt_entry[index]);
|
||||
|
||||
#define FSM_ITERATE_TRANS_TABLE_END(tr_table_ptr, tt_entry_ptr) \
|
||||
} \
|
||||
}while(0);
|
||||
|
||||
#endif
|
||||
89
src/fsm.c
Normal file
89
src/fsm.c
Normal file
@@ -0,0 +1,89 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include "fsm.h"
|
||||
|
||||
fsm_t*
|
||||
create_new_fsm(const char* fsm_name)
|
||||
{
|
||||
|
||||
fsm_t *fsm = calloc(1, sizeof(fsm_t));
|
||||
strncpy(fsm->fsm_name, fsm_name, MAX_FSM_NAME_SIZE - 1 );
|
||||
fsm->fsm_name[MAX_FSM_NAME_SIZE] = '\0';
|
||||
return fsm;
|
||||
|
||||
}
|
||||
|
||||
state_t*
|
||||
create_new_state(char *state_name,
|
||||
fsm_bool_t is_final){
|
||||
|
||||
assert(state_name);
|
||||
|
||||
state_t *state = calloc(1, sizeof(state_t));
|
||||
|
||||
strncpy(state->state_name, state_name, MAX_STATE_NAME_SIZE - 1);
|
||||
state->state_name[MAX_STATE_NAME_SIZE] = '\0';
|
||||
|
||||
tt_t *trans_table = &(state->state_trans_table);
|
||||
tt_entry_t *tt_entry_ptr = NULL;
|
||||
|
||||
FSM_ITERATE_TRANS_TABLE_BEGIN(trans_table, tt_entry_ptr){
|
||||
tt_entry_ptr->next_state = NULL;
|
||||
}FSM_ITERATE_TRANS_TABLE_END(trans_table, tt_entry_ptr)
|
||||
|
||||
state->is_final = is_final;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void
|
||||
set_fsm_initial_state(fsm_t *fsm, state_t *state){
|
||||
|
||||
assert(!fsm->initial_state);
|
||||
fsm->initial_state = state;
|
||||
}
|
||||
|
||||
|
||||
tt_entry_t*
|
||||
get_next_empty_tt_entry(tt_t *trans_table){
|
||||
|
||||
tt_entry_t* tt_entry_ptr = NULL;
|
||||
|
||||
assert(trans_table);
|
||||
|
||||
FSM_ITERATE_TRANS_TABLE_BEGIN(trans_table, tt_entry_ptr){
|
||||
if( is_tt_entry_empty(tt_entry_ptr) == FSM_TRUE )
|
||||
break;
|
||||
}FSM_ITERATE_TRANS_TABLE_END(trans_table, tt_entry_ptr)
|
||||
|
||||
|
||||
if(is_tt_entry_empty(tt_entry_ptr) == FSM_TRUE)
|
||||
return tt_entry_ptr;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tt_entry_t*
|
||||
create_and_insert_new_tt_entry(tt_t *trans_table,
|
||||
char *transition_key,
|
||||
unsigned int sizeof_key,
|
||||
state_t* next_state){
|
||||
|
||||
|
||||
assert( sizeof transition_key < MAX_TRANSITION_KEY_SIZE);
|
||||
|
||||
tt_entry_t *tt_entry_ptr = get_next_empty_tt_entry(trans_table);
|
||||
|
||||
if(!tt_entry_ptr){
|
||||
printf("FATAL : Transition Table is Full\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(tt_entry_ptr->transition_key , transition_key, sizeof_key);
|
||||
tt_entry_ptr->transition_key[sizeof_key] = '\0';
|
||||
tt_entry_ptr->transition_key_size = sizeof_key;
|
||||
tt_entry_ptr->next_state = next_state;
|
||||
|
||||
return tt_entry_ptr;
|
||||
}
|
||||
Reference in New Issue
Block a user