⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fsm.c

📁 linuxFedure4环境下串口编程后台运行状态机
💻 C
字号:
#include"fsm.h"#include"hash.h"#include<stdlib.h>#include<stdio.h>#include<string.h>#include<strings.h>#ifndef DEBUG#define ifdbg if(0)#else#define ifdbg if(1)#endif#define STATE_BUCKET_NUM 32#define EVENT_BUCKET_NUM 32#define FUNC_BUCKET_NUM 32struct FSM{	/* current state */	unsigned char state[MAX_SYMBOL_LEN];	/* function table */	struct hash_table *func_table;	/* state transition rule table */	struct hash_table *state_table;};struct func_table_entry{	/* every hash table entry should include this, see hash.h */	struct hash_table_entry hash;	/* callback function pointer */	callback_ptr func;};struct state_table_entry{	/* every hash table entry should include this, see hash.h */	struct hash_table_entry hash;	/* 2nd-level hash table, with the events as key */	struct hash_table *table;};struct event_table_entry{	/* every hash table entry should include this, see hash.h */	struct hash_table_entry hash;	/* next state */	unsigned char next[MAX_SYMBOL_LEN];	/* symbol name of the function */	unsigned char func[MAX_SYMBOL_LEN];	/* symbol id of the resource */	unsigned char res[MAX_SYMBOL_LEN];};static void outofmemory(){	ifdbg printf("out of memory\n");}struct FSM *fsm_create(const struct func_table *funcv, int funcc){	int i;	struct FSM *fsm=malloc(sizeof(struct FSM));	if(fsm==NULL){		outofmemory();		return NULL;	}	if((fsm->state_table=hash_table_create(STATE_BUCKET_NUM))==NULL){		outofmemory();		free(fsm);		return NULL;	}	if((fsm->func_table=hash_table_create(FUNC_BUCKET_NUM))==NULL){		outofmemory();		hash_table_free(fsm->state_table);		free(fsm);		return NULL;	}	/* fill the function table */	for(i=0; i<funcc; ++i){		struct func_table_entry *entry			=malloc(sizeof(struct func_table_entry));		if(entry==NULL){			outofmemory();			fsm_free(fsm);			return NULL;		}		strcpy(entry->hash.key, funcv[i].symbol);		entry->func=funcv[i].func;		hash_table_add(fsm->func_table, &entry->hash);	}	ifdbg printf("fsm with %d defined functions created\n", funcc);	return fsm;}voidfsm_setstate(struct FSM *fsm, const unsigned char *state){	strcpy(fsm->state, state);	ifdbg printf("fsm state switched to %s\n", state);}intfsm_add(struct FSM *fsm, const unsigned char *state,         const unsigned char *event, const unsigned char *next,         const unsigned char *func, const unsigned char *resource){	struct hash_table_entry *entry;	struct state_table_entry *se;	struct event_table_entry *ee;	struct hash_table *event_table;	entry=hash_table_get(fsm->state_table, state);	if(entry!=NULL){		ifdbg printf("state %s appeared earlier\n", state);		se=hash_entry(entry, struct state_table_entry, hash);		event_table=se->table;	}else{		ifdbg printf("state %s first appeared\n", state);		/* allocate entry for the new state */		se=malloc(sizeof(struct state_table_entry));		if(se==NULL){			outofmemory();			return -2;		}		strcpy(se->hash.key, state);		event_table=se->table=hash_table_create(EVENT_BUCKET_NUM);		if(event_table==NULL){			outofmemory();			free(se);			return -2;		}		hash_table_add(fsm->state_table, &se->hash);	}	entry=hash_table_get(event_table, event);	if(entry!=NULL){		ifdbg printf("state transition rule with (%s, %s)"			     "already exists\n", state, event);		return -1;	}	ee=malloc(sizeof(struct event_table_entry));	if(ee==NULL){		outofmemory();		return -2;	}	strcpy(ee->hash.key, event);	strcpy(ee->next, next);	strcpy(ee->func, func);	strcpy(ee->res, resource);	hash_table_add(event_table, &ee->hash);	ifdbg printf("state transition rule (%s, %s, %s, %s, %s) added.\n",			fsm->state, event, next, func, resource);	return 0;}voidfsm_free(struct FSM *fsm){	struct hash_table_entry *pos, *pos2;	struct func_table_entry *fe;	struct state_table_entry *se;	struct event_table_entry *ee;	/* free entries in the function table */	hash_for_each(pos, fsm->func_table){		fe=hash_entry(pos, struct func_table_entry, hash);		free(fe);	}	hash_table_free(fsm->func_table);	/* free entries in the state transition rules table */	hash_for_each(pos, fsm->state_table){		se=hash_entry(pos, struct state_table_entry, hash);		/**		 * every state transition rule entry contains a 2nd		 * level hash table, free it first		 */		hash_for_each(pos2, se->table){			ee=hash_entry(pos2, struct event_table_entry, hash); 			free(ee);		}		hash_table_free(se->table);		free(se);	}	hash_table_free(fsm->state_table);	ifdbg printf("fsm freed\n");	free(fsm);}/** * read a line from given file, skipping empty or comment lines * return -1 on EOF */static int fgetline(FILE *fp, unsigned char *buf, unsigned int size){	while(!feof(fp)){		int i=0;		fgets(buf, size, fp);		while(buf[i]!='\0' && buf[i]!='#' && buf[i]!='\n'			&& (buf[i]==' ' || buf[i]=='\t')) ++i;		if(buf[i]=='\0' || buf[i]=='#' || buf[i]=='\n'){			ifdbg printf("empty line or comment line skipped\n");			continue;		}		else return 0;	}	ifdbg printf("end of file reached\n");	return -1;}/** * split buf into n tokens * return negative on error */static inttokenize(unsigned char *buf, unsigned char *tok[], unsigned int n){	int i=0, j;	/* preprocessing */	while(buf[i]!='\0'){		switch(buf[i]){			/* convert tabs into spaces */			case '\t':				buf[i]=' ';				break;			/* 			 * end-of-line and comment character: 			 * simply treat as end-of-string 			 */			case '\n':			case '#':				buf[i]='\0';				break;		}		++i;	}	i=0;	for(j=0;j<n;++j){		/* skip whitespaces */		while(buf[i]==' ') ++i;		/* end-of-buf before retrieving all required tokens? */		if(buf[i]=='\0'){			ifdbg{			       	printf("not enough fields in line");				for(i=0; i<j; ++i) printf("%s  ", tok[i]);				printf("required %d\n", n);			}			return -1;		}		/* beginning of token */		tok[j]=buf+i;		while(buf[i]!=' ' && buf[i]!='\0') ++i;		/* end of token */		if(buf[i]!='\0') buf[i++]='\0';	}		/* any extra fields? */	while(buf[i]==' ') ++i;	if(buf[i]=='\0') return 0; /* no */	else{		ifdbg{			printf("too many fields in line");			for(i=0; i<n; ++i) printf("%s  ", tok[i]);			printf("...  required %d\n", n);		}	       	return -2;	}}struct FSM *fsm_load(const unsigned char *filename,          const struct func_table *funcv, int funcc){	const unsigned int BUFLEN=(MAX_SYMBOL_LEN*6u);	unsigned char buf[BUFLEN];	unsigned char *token[5];	FILE *fp=fopen(filename, "r");	struct FSM *fsm;	if(fp==NULL){		ifdbg printf("failed to open file %s\n", filename);		return NULL;	}	fsm=fsm_create(funcv, funcc);	if(fsm==NULL){		ifdbg printf("failed to create fsm object\n");		goto err;	}	/* read initial state */	if(fgetline(fp, buf, BUFLEN)!=0){		ifdbg printf("failed to read initial state\n");		goto err;	}	if(tokenize(buf, token, 2)!=0){		ifdbg printf("failed to read initial state\n");		goto err;	}	if(strcasecmp("initstate", token[0])!=0){		ifdbg printf("failed to read initial state\n");		goto err;	}	fsm_setstate(fsm, token[1]);	/* read state transition rules */	while(1){		if(fgetline(fp, buf, BUFLEN)!=0) break;		if(tokenize(buf, token, 5)!=0){			ifdbg printf("failed to read transition rule\n");			goto err;		}		fsm_add(fsm, token[0], token[1], token[2], token[3], token[4]);	}	fclose(fp);		ifdbg printf("fsm configuration file read successfully\n");	return fsm;err:	if(fp!=NULL) fclose(fp);	if(fsm!=NULL) fsm_free(fsm);	return NULL;}int fsm_doevent(struct FSM *fsm, const unsigned char *event){	struct hash_table_entry *entry;	struct state_table_entry *se;	struct event_table_entry *ee;	struct func_table_entry *fe;	entry=hash_table_get(fsm->state_table, fsm->state);	if(entry==NULL){		ifdbg printf("state %s not defined\n", fsm->state);		return -1;	}	se=hash_entry(entry, struct state_table_entry, hash);	entry=hash_table_get(se->table, event);	if(entry==NULL){		ifdbg printf("event %s not defined for state %s\n", 			     event, fsm->state);		return -2;	}	ee=hash_entry(entry, struct event_table_entry, hash);	entry=hash_table_get(fsm->func_table, ee->func);	if(entry==NULL){		ifdbg printf("function %s not defined\n", ee->func);		return -3;	}	fe=hash_entry(entry, struct func_table_entry, hash);	ifdbg printf("calling function %s with resource %s on event %s "		     "at state %s\n", ee->func, ee->res, fsm->state, event);	fe->func(ee->res);	fsm_setstate(fsm, ee->next);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -