?? fsm.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 + -