echo Extracting msm.h...
cat <<WRAP_EOF >msm.h
/* MSM.h, Copyright (C) 1992 by Jon Shemitz.

   Declarations and inline code for a MSM engine
   and not much else -- this code has been slashed
   to minimize magazine space:  Features and *error
   checking* have been stripped out and made
   "exercises for the reader".

   Code is inlined for convenience and to save
   magazine space, not because of any analysis
   of time-space tradeoffs.
*/

typedef unsigned int Word;
typedef unsigned char Byte;

const
  StackSize = 25,
  NTasks    = 50;
  // Must be <= 255, so a TaskNumber can be a Byte

typedef void (*Handler) (); // A pointer to a function
typedef Handler States;
	// Makes it easier to add token-threading

typedef Byte TaskToken;
typedef Byte Priorities;

template <class DataType, int StackSize>
class SimpleStack {
      Word Top;
      DataType Data[StackSize];

      public:
      SimpleStack()            {Top = 0;}
      void Push(DataType Item) {Data[Top++] = Item;}
      DataType Pop()           {return Data[--Top];}
};

class Tasks {
      TaskToken    Number;
      States       State;
      Word	   Waits;
      Priorities   Priority;
      SimpleStack <States, StackSize>
	           Stack;
      public:
        Tasks(Handler S, Word W, Priorities P);
        ~Tasks();
        void SetState(States S)  {State = S;}
        States GetState()        {return State;}

        void PushState(States S) {Stack.Push(S);}
        void PopState()
	  {SetState(Stack.Pop());} // `return'

        void Sleep(Word BitMap)
          {Waits |= BitMap; Deactivate();}
        void Wake(Word BitMap)
          {Waits &= (~BitMap); Activate();}

        void SetPriority(Priorities P);
        Priorities GetPriority() {return Priority;}

      private:
        void Activate();
	// Move to an active task list
        void Deactivate();
        // Remove from an active task list
};

typedef Tasks * TaskPtr;

extern TaskPtr ThisTask; /* The current task

       Any handler may use this pointer to read
       and write its task record.
*/


// There's only 1 engine, so it shouldn't be an object

void MSM_Run();  // Run the 'engine'

void MSM_Stop(); // Handlers can call to stop engine

TaskPtr Task(TaskToken TT);



