/* ---------------------------------------------------------------------------- fsm.c a finite state machine within sics M. Zolliker, Aug 2004 ---------------------------------------------------------------------------- */ #include #include #include #include "fsm.h" #define MAXSTACK 8 typedef struct { long pc; FsmFunc func; } StackItem; struct Fsm { void *obj; FsmHandler handler; long pc; FsmFunc func; time_t till; int pause; int sp; StackItem stack[MAXSTACK]; }; static Fsm *fsm = NULL; void FsmWait(long delay) { assert(fsm); fsm->till = time(NULL) + delay; } int FsmTaskHandler(Fsm *this) { long line; if (this->pause) { this->handler(this->obj); return 1; } if (this->pc >= 0) { /* this->pc < 0 means stop current function */ if (this->till != 0) { if (time(NULL) < this->till) return 1; /* wait */ this->till = 0; } if (this->handler(this->obj) == 0) { return 1; /* wait for answer */ } fsm = this; this->pc = this->func(this->pc, this->obj); fsm = NULL; } if (this->pc <= 0) { if (this->sp == 0) return 0; this->sp--; this->pc = this->stack[this->sp].pc; this->func = this->stack[this->sp].func; } return 1; } void FsmKill(void *data) { free(data); } Fsm *FsmStartTask(void *obj, FsmHandler handler, FsmFunc func) { Fsm *new; new=malloc(sizeof *new); new->obj = obj; new->pc = 0; new->func = func; new->handler = handler; new->sp = 0; new->pause = 0; new->till = 0; return new; } int FsmStop(Fsm *this, FsmFunc func) { int i; if (this == NULL) this = fsm; assert(this); for (i=0; i < this->sp; i++) { if (func == this->stack[i].func) { break; } } if (i == this->sp) { if (func != this->func) return 0; } else { this->sp = i; } this->pc = -1; return 1; } void FsmPause(Fsm *this, int pause) { this->pause = pause; } long FsmCall(long pc, FsmFunc func) { assert(fsm); assert(fsm->sp < MAXSTACK); fsm->stack[fsm->sp].pc = pc; fsm->stack[fsm->sp].func = fsm->func; fsm->sp++; fsm->func = func; fsm->pc = 0; return fsm->func(fsm->pc, fsm->obj); }