diff --git a/Makefile b/Makefile index fba10d8..9fcf4b6 100644 --- a/Makefile +++ b/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 diff --git a/app.c b/app.c new file mode 100644 index 0000000..090cadd --- /dev/null +++ b/app.c @@ -0,0 +1,15 @@ +#include +#include +#include + +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; +} \ No newline at end of file diff --git a/include/fsm.h b/include/fsm.h index 15ca01c..a12782c 100644 --- a/include/fsm.h +++ b/include/fsm.h @@ -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 \ No newline at end of file diff --git a/src/fsm.c b/src/fsm.c new file mode 100644 index 0000000..b3e348f --- /dev/null +++ b/src/fsm.c @@ -0,0 +1,89 @@ +#include +#include +#include +#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; +} \ No newline at end of file