mirror of
https://github.com/Hizenberg469/Finite-State-Machine.git
synced 2026-04-19 16:42:23 +03:00
basic FSM app build
This commit is contained in:
76
Makefile
76
Makefile
@@ -1,27 +1,13 @@
|
|||||||
#Setting a default configuration if invoked with just "make":
|
#Setting a default configuration if invoked with just "make":
|
||||||
CFG ?= debug
|
CFG?=debug
|
||||||
|
|
||||||
# Config specific settings
|
# Config specific settings
|
||||||
ifeq ($(CFG),debug)
|
ifeq ($(CFG),debug)
|
||||||
CFLAGS += -g -DDEBUG
|
CFLAGS=-g -DDEBUG
|
||||||
else
|
else
|
||||||
CFLAGS += -O3 -DNDEBUG
|
CFLAGS=-O3 -DNDEBUG
|
||||||
endif
|
endif
|
||||||
|
|
||||||
inform:
|
|
||||||
ifneq ($(CFG),release)
|
|
||||||
ifneq ($(CFG),debug)
|
|
||||||
@echo "Invalid configuration "$(CFG)" specified."
|
|
||||||
@echo
|
|
||||||
@echo "Possible choices for configuration are 'CFG=release' and 'CFG=debug'"
|
|
||||||
@exit 1
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
@echo "Configuration "$(CFG)
|
|
||||||
@echo "--------------------------------------------------"
|
|
||||||
|
|
||||||
rule : dep | inform
|
|
||||||
|
|
||||||
BUILD_DIR=bin/$(CFG)
|
BUILD_DIR=bin/$(CFG)
|
||||||
OBJS_DIR=objs/$(CFG)
|
OBJS_DIR=objs/$(CFG)
|
||||||
LIBDIR=lib/${CFG}
|
LIBDIR=lib/${CFG}
|
||||||
@@ -31,25 +17,49 @@ SRCDIR=src
|
|||||||
|
|
||||||
APP=$(BUILD_DIR)/app
|
APP=$(BUILD_DIR)/app
|
||||||
APP_OBJECT=$(OBJS_DIR)/app.o
|
APP_OBJECT=$(OBJS_DIR)/app.o
|
||||||
|
APP_DEPFILES=$(OBJS_DIR)/app.d
|
||||||
FSMLIB_NAME=fsm
|
FSMLIB_NAME=fsm
|
||||||
FSMLIB=$(LIBDIR)/lib$(FSMLIB_NAME)
|
FSMLIB=$(LIBDIR)/lib$(FSMLIB_NAME)
|
||||||
CODEDIRS=./src
|
CODEDIRS=src
|
||||||
INCDIRS=. ./include/ # can be list
|
INCDIRS=./ ./include/ # can be list
|
||||||
|
|
||||||
CC=gcc
|
CC=gcc
|
||||||
OPT=-O0
|
|
||||||
#generate files that encode make rules for the .h dependencies
|
#generate files that encode make rules for the .h dependencies
|
||||||
DEPFLAGS=-MP -MD
|
DEPFLAGS=-MMD -MP
|
||||||
#automatically add the -I onto each include directory
|
#automatically add the -I onto each include directory
|
||||||
CFLAGS+=-Wall -Wextra $(foreach D,$(INCDIRS),-I$(D)) $(OPT) $(DEPFLAGS)
|
CFLAGS+=-Wall -Wextra $(foreach D , $(INCDIRS) , -I$(D)) $(DEPFLAGS)
|
||||||
|
|
||||||
# for-style iteration (foreach) and regular expression completions (wildcard)
|
# for-style iteration (foreach) and regular expression completions (wildcard)
|
||||||
CFILES=$(foreach D, $(CODEDIRS),$(wildcard $(D)/*.c))
|
CFILES=$(foreach D , $(CODEDIRS) , $(wildcard $(D)/*.c))
|
||||||
# regular expression replacement
|
|
||||||
OBJECTS=$(patsubst %.c,$(OBJS_DIR)/%.o,$(CFILES))
|
|
||||||
DEPFILES=$(patsubst %.c,$(OBJS_DIR)/%.d,$(CFILES))
|
|
||||||
|
|
||||||
all: $(FSMLIB) $(APP) | create_dir
|
|
||||||
|
#WTF, this below code is f**ked me up.
|
||||||
|
#didn't change anything but still works.
|
||||||
|
#WHYYY???
|
||||||
|
# regular expression replacement
|
||||||
|
OBJECTS=$(patsubst $(SRCDIR)/%.c, $(OBJS_DIR)/%.o , $(CFILES))
|
||||||
|
DEPFILES=$(patsubst $(SRCDIR)/%.c, $(OBJS_DIR)/%.d , $(CFILES))
|
||||||
|
DEPFILES += $(APP_DEPFILES)
|
||||||
|
|
||||||
|
# $(info CFILES: $(CFILES))
|
||||||
|
# $(info OBJECTS: $(OBJECTS))
|
||||||
|
# $(info DEPFILES: $(DEPFILES))
|
||||||
|
# $(info APP_OBJECT: $(APP_OBJECT))
|
||||||
|
# $(info APP_DEPFILES: $(APP_DEPFILES))
|
||||||
|
|
||||||
|
all: create_dir inform $(FSMLIB) $(APP)
|
||||||
|
|
||||||
|
inform:
|
||||||
|
ifneq ($(CFG),release)
|
||||||
|
ifneq ($(CFG),debug)
|
||||||
|
@echo "Invalid configuration $(CFG) specified."
|
||||||
|
@echo
|
||||||
|
@echo "Possible choices for configuration are 'CFG=release' and 'CFG=debug'"
|
||||||
|
@exit 1
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
@echo "Configuration $(CFG)"
|
||||||
|
@echo "--------------------------------------------------"
|
||||||
|
|
||||||
create_dir:
|
create_dir:
|
||||||
mkdir -p $(BUILD_DIR)
|
mkdir -p $(BUILD_DIR)
|
||||||
@@ -57,18 +67,18 @@ create_dir:
|
|||||||
mkdir -p $(LIBDIR)
|
mkdir -p $(LIBDIR)
|
||||||
|
|
||||||
|
|
||||||
$(APP): $(APP_OBJECT) | create_dir
|
$(APP): $(APP_OBJECT) $(FSMLIB).a
|
||||||
$(CC) -o $@ $^ -L $(LIBDIR) -l$(FSMLIB_NAME)
|
$(CC) -o $@ $^ -L$(LIBDIR) -l$(FSMLIB_NAME)
|
||||||
|
|
||||||
$(FSMLIB): $(OBJECTS) | create_dir
|
$(FSMLIB): $(OBJECTS)
|
||||||
ar cr $(LIBDIR)/${FSMLIB}.a ${OBJECTS}
|
ar cr $(FSMLIB).a $(OBJECTS)
|
||||||
|
|
||||||
# only want the .c file dependency here, thus $< instead of $^.
|
# only want the .c file dependency here, thus $< instead of $^.
|
||||||
#
|
#
|
||||||
$(OBJS_DIR)/%.o:$(SRCDIR)/%.c | create_dir
|
$(OBJS_DIR)/%.o: $(SRCDIR)/%.c
|
||||||
$(CC) $(CFLAGS) -c -o $@ $<
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
$(OBJS_DIR)/%.o:%.c | create_dir
|
$(OBJS_DIR)/%.o: %.c
|
||||||
$(CC) $(CFLAGS) -c -o $@ $<
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|||||||
133
app.c
133
app.c
@@ -1,15 +1,140 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include <fsm.h>
|
#include <string.h>
|
||||||
|
#include "fsm.h"
|
||||||
|
|
||||||
|
#define MAX_FSM_STATE 24
|
||||||
|
|
||||||
|
#define modify_string(state,num) #state ## #num
|
||||||
|
#define modify_var(state,num) state ## num
|
||||||
|
|
||||||
|
state_t *fsm_states[MAX_FSM_STATE];
|
||||||
|
|
||||||
|
|
||||||
|
void print_fsm(fsm_t *fsm){
|
||||||
|
|
||||||
|
printf("FSM name : %s\n", fsm->fsm_name);
|
||||||
|
printf("States : ");
|
||||||
|
char state[6];
|
||||||
|
for(unsigned int i = 0 ; i < fsm->state_count ; i++ ){
|
||||||
|
sprintf(state,"q%1d",i);
|
||||||
|
printf("%s", state);
|
||||||
|
|
||||||
|
if( i < fsm->state_count - 1 )
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
putchar('\n');
|
||||||
|
|
||||||
|
printf("Alphabets : %s\n", fsm->alphabet);
|
||||||
|
printf("Initial State : %s\n", fsm->initial_state->state_name);
|
||||||
|
printf("Final States : %s\n", fsm->final_states);
|
||||||
|
|
||||||
|
printf("Transition Table :\n");
|
||||||
|
|
||||||
|
printf(" | 1 0 \n");
|
||||||
|
printf("------------------------\n");
|
||||||
|
|
||||||
|
|
||||||
|
char state1[6] = {0};
|
||||||
|
char state2[6] = {0};
|
||||||
|
char state3[6] = {0};
|
||||||
|
|
||||||
|
tt_t *table_ptr = NULL;
|
||||||
|
tt_entry_t *entry_ptr = NULL;
|
||||||
|
for( unsigned int i = 0 ; i < fsm->state_count ; i++ ){
|
||||||
|
|
||||||
|
strncpy(state1, fsm_states[i]->state_name,
|
||||||
|
strlen(fsm_states[i]->state_name));
|
||||||
|
|
||||||
|
table_ptr = &(fsm_states[i]->state_trans_table);
|
||||||
|
FSM_ITERATE_TRANS_TABLE_BEGIN(table_ptr, entry_ptr){
|
||||||
|
|
||||||
|
if( is_tt_entry_empty(entry_ptr) == FSM_FALSE ){
|
||||||
|
if( strcmp(entry_ptr->transition_key, "1") == 0 ){
|
||||||
|
strncpy(state2, entry_ptr->next_state->state_name,
|
||||||
|
strlen(entry_ptr->next_state->state_name));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
strncpy(state3, entry_ptr->next_state->state_name,
|
||||||
|
strlen(entry_ptr->next_state->state_name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}FSM_ITERATE_TRANS_TABLE_END(table_ptr, entry_ptr)
|
||||||
|
|
||||||
|
printf(" %s | %s %s \n", state1, state2, state3);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int main(){
|
int main(){
|
||||||
|
|
||||||
fsm_t* fsm = create_new_fsm("FSM_1");
|
fsm_t *fsm = create_new_fsm("FSM_1", "0,1");
|
||||||
|
|
||||||
state_t* initial_state = create_new_state("q0", FSM_FALSE);
|
//States
|
||||||
set_fsm_initial_state(fsm, initial_state);
|
state_t *q0 = create_new_state("q0", FSM_FALSE, "FSM_1", fsm);
|
||||||
|
state_t *q1 = create_new_state("q1", FSM_TRUE, "FSM_1", fsm);
|
||||||
|
state_t *q2 = create_new_state("q2", FSM_TRUE, "FSM_1", fsm);
|
||||||
|
state_t *q3 = create_new_state("q3", FSM_FALSE, "FSM_1", fsm);
|
||||||
|
|
||||||
|
fsm_states[0] = q0;
|
||||||
|
fsm_states[1] = q1;
|
||||||
|
fsm_states[2] = q2;
|
||||||
|
fsm_states[3] = q3;
|
||||||
|
|
||||||
|
set_fsm_initial_state(fsm, q0);
|
||||||
|
|
||||||
|
//State q0
|
||||||
|
tt_t *trans_table = &(q0->state_trans_table);
|
||||||
|
create_and_insert_new_tt_entry(trans_table,
|
||||||
|
"0",
|
||||||
|
1,
|
||||||
|
q2);
|
||||||
|
|
||||||
|
create_and_insert_new_tt_entry(trans_table,
|
||||||
|
"1",
|
||||||
|
1,
|
||||||
|
q1);
|
||||||
|
|
||||||
|
//State q1
|
||||||
|
trans_table = &(q1->state_trans_table);
|
||||||
|
create_and_insert_new_tt_entry(trans_table,
|
||||||
|
"0",
|
||||||
|
1,
|
||||||
|
q2);
|
||||||
|
|
||||||
|
create_and_insert_new_tt_entry(trans_table,
|
||||||
|
"1",
|
||||||
|
1,
|
||||||
|
q3);
|
||||||
|
|
||||||
|
//State q2
|
||||||
|
trans_table = &(q2->state_trans_table);
|
||||||
|
create_and_insert_new_tt_entry(trans_table,
|
||||||
|
"0",
|
||||||
|
1,
|
||||||
|
q3);
|
||||||
|
|
||||||
|
create_and_insert_new_tt_entry(trans_table,
|
||||||
|
"1",
|
||||||
|
1,
|
||||||
|
q1);
|
||||||
|
|
||||||
|
//State q3
|
||||||
|
trans_table = &(q3->state_trans_table);
|
||||||
|
create_and_insert_new_tt_entry(trans_table,
|
||||||
|
"0",
|
||||||
|
1,
|
||||||
|
q3);
|
||||||
|
|
||||||
|
create_and_insert_new_tt_entry(trans_table,
|
||||||
|
"1",
|
||||||
|
1,
|
||||||
|
q3);
|
||||||
|
|
||||||
|
|
||||||
|
print_fsm(fsm);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
BIN
bin/debug/.fuse_hidden0000009f00000006
Normal file
BIN
bin/debug/.fuse_hidden0000009f00000006
Normal file
Binary file not shown.
@@ -9,6 +9,8 @@
|
|||||||
#define MAX_STATE_NAME_SIZE 32
|
#define MAX_STATE_NAME_SIZE 32
|
||||||
#define MAX_FSM_NAME_SIZE 32
|
#define MAX_FSM_NAME_SIZE 32
|
||||||
#define MAX_TRANSITION_KEY_SIZE 64
|
#define MAX_TRANSITION_KEY_SIZE 64
|
||||||
|
#define MAX_ALP_BUFFER_SIZE 30
|
||||||
|
#define MAX_FINAL_STATE 128
|
||||||
|
|
||||||
|
|
||||||
/***Data structures and custom datatypes***/
|
/***Data structures and custom datatypes***/
|
||||||
@@ -61,6 +63,9 @@ struct state_{
|
|||||||
/*Boolean value to distinguish b/w
|
/*Boolean value to distinguish b/w
|
||||||
* accept/final state or vice-versa*/
|
* accept/final state or vice-versa*/
|
||||||
fsm_bool_t is_final;
|
fsm_bool_t is_final;
|
||||||
|
|
||||||
|
/*FSM which the current state belongs to*/
|
||||||
|
char fsm[MAX_FSM_NAME_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fsm_{
|
struct fsm_{
|
||||||
@@ -68,6 +73,15 @@ struct fsm_{
|
|||||||
/*Initial state of FSM to start with*/
|
/*Initial state of FSM to start with*/
|
||||||
state_t *initial_state;
|
state_t *initial_state;
|
||||||
|
|
||||||
|
/*Number of states in FSM*/
|
||||||
|
unsigned int state_count;
|
||||||
|
|
||||||
|
/*Set of alphabet*/
|
||||||
|
char alphabet[MAX_ALP_BUFFER_SIZE];
|
||||||
|
|
||||||
|
/*Set of final/accept states*/
|
||||||
|
char final_states[MAX_FINAL_STATE];
|
||||||
|
|
||||||
/*Name of FSM*/
|
/*Name of FSM*/
|
||||||
char fsm_name[MAX_FSM_NAME_SIZE];
|
char fsm_name[MAX_FSM_NAME_SIZE];
|
||||||
|
|
||||||
@@ -87,18 +101,20 @@ struct fsm_{
|
|||||||
/***Function Prototypes***/
|
/***Function Prototypes***/
|
||||||
|
|
||||||
fsm_t*
|
fsm_t*
|
||||||
create_new_fsm(const char *fsm_name);
|
create_new_fsm(const char *fsm_name, const char *inp_alpha);
|
||||||
|
|
||||||
state_t*
|
state_t*
|
||||||
create_new_state(char *state_name,
|
create_new_state(const char *state_name,
|
||||||
fsm_bool_t is_final);
|
fsm_bool_t is_final,
|
||||||
|
const char *fsm_name,
|
||||||
|
fsm_t *fsm);
|
||||||
|
|
||||||
void
|
void
|
||||||
set_fsm_initial_state(fsm_t *fsm, state_t *state);
|
set_fsm_initial_state(fsm_t *fsm, state_t *state);
|
||||||
|
|
||||||
tt_entry_t*
|
tt_entry_t*
|
||||||
create_and_insert_new_tt_entry(tt_t *trans_table,
|
create_and_insert_new_tt_entry(tt_t *trans_table,
|
||||||
char *transition_key,
|
const char *transition_key,
|
||||||
unsigned int sizeof_key,
|
unsigned int sizeof_key,
|
||||||
state_t* next_state);
|
state_t* next_state);
|
||||||
|
|
||||||
@@ -110,7 +126,7 @@ get_next_empty_tt_entry(tt_t *trans_table);
|
|||||||
static inline fsm_bool_t
|
static inline fsm_bool_t
|
||||||
is_tt_entry_empty(tt_entry_t *tt_entry){
|
is_tt_entry_empty(tt_entry_t *tt_entry){
|
||||||
|
|
||||||
if(!tt_entry->next_state)
|
if( tt_entry != NULL && !tt_entry->next_state)
|
||||||
return FSM_TRUE;
|
return FSM_TRUE;
|
||||||
|
|
||||||
return FSM_FALSE;
|
return FSM_FALSE;
|
||||||
|
|||||||
51
src/fsm.c
51
src/fsm.c
@@ -1,29 +1,41 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
#include <assert.h>
|
||||||
#include "fsm.h"
|
#include "fsm.h"
|
||||||
|
|
||||||
fsm_t*
|
fsm_t *
|
||||||
create_new_fsm(const char* fsm_name)
|
create_new_fsm(const char* fsm_name, const char *inp_alpha)
|
||||||
{
|
{
|
||||||
|
|
||||||
fsm_t *fsm = calloc(1, sizeof(fsm_t));
|
fsm_t *fsm = calloc(1, sizeof(fsm_t));
|
||||||
strncpy(fsm->fsm_name, fsm_name, MAX_FSM_NAME_SIZE - 1 );
|
strncpy(fsm->fsm_name, fsm_name, strlen(fsm_name) );
|
||||||
fsm->fsm_name[MAX_FSM_NAME_SIZE] = '\0';
|
fsm->fsm_name[strlen(fsm_name)] = '\0';
|
||||||
|
fsm->state_count = 0;
|
||||||
|
|
||||||
|
strncpy(fsm->alphabet, inp_alpha, strlen(inp_alpha));
|
||||||
|
fsm->alphabet[strlen(inp_alpha)] = '\0';
|
||||||
|
|
||||||
|
memset(fsm->final_states, 0, 1);
|
||||||
|
memset(fsm->input_buffer, 0, 1);
|
||||||
|
fsm->input_buffer_cursor = 0;
|
||||||
|
fsm->input_buffer_size = 0;
|
||||||
return fsm;
|
return fsm;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state_t*
|
state_t *
|
||||||
create_new_state(char *state_name,
|
create_new_state(const char *state_name,
|
||||||
fsm_bool_t is_final){
|
fsm_bool_t is_final,
|
||||||
|
const char *fsm_name,
|
||||||
|
fsm_t *fsm){
|
||||||
|
|
||||||
assert(state_name);
|
assert(state_name);
|
||||||
|
|
||||||
state_t *state = calloc(1, sizeof(state_t));
|
state_t *state = calloc(1, sizeof(state_t));
|
||||||
|
|
||||||
strncpy(state->state_name, state_name, MAX_STATE_NAME_SIZE - 1);
|
strncpy(state->state_name, state_name, strlen(state_name));
|
||||||
state->state_name[MAX_STATE_NAME_SIZE] = '\0';
|
state->state_name[strlen(state_name)] = '\0';
|
||||||
|
|
||||||
tt_t *trans_table = &(state->state_trans_table);
|
tt_t *trans_table = &(state->state_trans_table);
|
||||||
tt_entry_t *tt_entry_ptr = NULL;
|
tt_entry_t *tt_entry_ptr = NULL;
|
||||||
@@ -34,6 +46,21 @@ create_new_state(char *state_name,
|
|||||||
|
|
||||||
state->is_final = is_final;
|
state->is_final = is_final;
|
||||||
|
|
||||||
|
char temp_state_name[strlen(state_name)+2];
|
||||||
|
strncpy(temp_state_name, state_name, strlen(state_name));
|
||||||
|
temp_state_name[strlen(state_name)] = '\0';
|
||||||
|
|
||||||
|
if(state->is_final == FSM_TRUE){
|
||||||
|
strcat(temp_state_name,",");
|
||||||
|
strcat(fsm->final_states,temp_state_name);
|
||||||
|
}
|
||||||
|
// fsm->final_states[strlen(fsm->final_states)+2] = '\0';
|
||||||
|
|
||||||
|
strncpy(state->fsm, fsm_name, strlen(fsm_name));
|
||||||
|
state->fsm[strlen(fsm_name)] = '\0';
|
||||||
|
|
||||||
|
fsm->state_count++;
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +72,7 @@ set_fsm_initial_state(fsm_t *fsm, state_t *state){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tt_entry_t*
|
tt_entry_t *
|
||||||
get_next_empty_tt_entry(tt_t *trans_table){
|
get_next_empty_tt_entry(tt_t *trans_table){
|
||||||
|
|
||||||
tt_entry_t* tt_entry_ptr = NULL;
|
tt_entry_t* tt_entry_ptr = NULL;
|
||||||
@@ -64,9 +91,9 @@ get_next_empty_tt_entry(tt_t *trans_table){
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
tt_entry_t*
|
tt_entry_t *
|
||||||
create_and_insert_new_tt_entry(tt_t *trans_table,
|
create_and_insert_new_tt_entry(tt_t *trans_table,
|
||||||
char *transition_key,
|
const char *transition_key,
|
||||||
unsigned int sizeof_key,
|
unsigned int sizeof_key,
|
||||||
state_t* next_state){
|
state_t* next_state){
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user