Files
sicspsi/fsm.c

119 lines
2.1 KiB
C

/* ----------------------------------------------------------------------------
fsm.c
a finite state machine within sics
M. Zolliker, Aug 2004
---------------------------------------------------------------------------- */
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#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);
}