/* ----------------------------------------------------------------------------
fsm.h

a finite state machine

M. Zolliker, Aug 2004
---------------------------------------------------------------------------- */

#ifndef FSM_H
#define FSM_H

typedef struct Fsm Fsm;

typedef long (*FsmFunc) (long pc, void *obj);
/* the prototype for a task function
   a task function body has the following form:
   
   int Func(long pc, Object *obj) {
     <declarations>
     BEGIN
       ...
     RETURN
   }
   
   The ellipsis might be replaced by any code containing fsm macros.
   Loops and conditional statements containing fsm macros are not
   allowed, goto statements may be used instead.
*/

#define FSM_BEGIN switch (pc) { default:
#define FSM_END fsm_quit: return 0; }

/* fsm macros: */

#define FSM_NEXT return __LINE__; case __LINE__:
/* waiting for response */

#define FSM_WAIT(DELTA) FsmWait(DELTA); return __LINE__; case __LINE__:
/* waiting DELTA seconds */

#define FSM_CALL(FUNC) return FsmCallOld(__LINE__, (FsmFunc)FUNC); case __LINE__:
/* call a task subfunction */

typedef int (*FsmHandler) (void *obj);
/* the prototype for the handler. Should return 0 when waiting for an answer
   or 1 when result is o.k. */

Fsm *FsmStartTask(void *obj, FsmHandler handler, FsmFunc func, char *name);
/* start a task and return a pointer to it */

void FsmRestartTask(Fsm * task, FsmFunc func);
/* restart a stopped task */

long FsmPc(void);
/* check current pc (used in EasePchk called in first step in fsm functions) */

int FsmTaskHandler(Fsm * task);
/* this is the task handler.
   the argument should be the pointer obtained from FsmStartTask
   returns 0 when finished, 1 when still running */

int FsmStop(Fsm * task, FsmFunc func);
/* stop a function. returns to the caller next time */

void FsmStopTask(Fsm * task);
/* stops the task, it will be killed after next execution */

void FsmKill(void *task);
/* kill the task */

void FsmPause(Fsm * task, int pause);
/* pause=1: pause task, pause=0: continue task */

void FsmCall(FsmFunc func);

void FsmWait(long delay);

void FsmSpeed(Fsm * task);

#endif
