/*{{{  Header*/
/******************************************************************************
 * File name          : Occam2c.h
 * Owner              : OyT
 * Module Description : SPOC header file
 * Document name(s)   :
 * Main project name  : RIFT/GL-100 (800620UN)
 * Sub  project name  : DSP CPU S.W (800821UN)
 *
 * Copyright Autronica AS 1996-97
 * 7005 TRONDHEIM, NORWAY
 *
 * Ver. yy-mm-dd Author Approved Description
 * ---- -------- ------ -------- ----------------------------------------------
 * 0.01                          See banner above
 * 1.24 20Aug98  OyT             lint-ed
 * 1.24 02Dec98  OyT             GLKDSP=1044: SETERR involves no lineNo and fileName
 ******************************************************************************/
/*}}}  */
/*{{{  includes*/
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <limits.h>
#include <setjmp.h>
#include <math.h>
#define inline
/*}}}  */
/*{{{  Teig*/
/*
*  I have not modified any control structure in here, only layout, in the
*  process of trying to understand.
*  "ReadTimer" has been modified so that all timing is "low priority"
*  Also, some LINT errors have been fixed.
*  All #define etc in CheckPrimitiveSizes removed
*  BYTE is char instead of unsigned char
*  #define MOSTNEGINT16 ((INT16)0xFFFF8000) , was 0x8000
*  MSG_MALLOC is new, plus seterr
*  MSG_TIMER is new
*  BREAKPOINT_F and BREAKPOINT_M
*  ChanOut4_InterruptEvent (17Apr98)
*  PC-lint done (Aug98)
*  SETERR_MLF is new, it has replaced several "seterr(m,l,f)"
*/
#define USE_RANGE_FUNCTIONS_NO_LINEFILE
/*}}}  */
/*{{{  SPOC 1.3*/
// SPOC 1.3:
// #define BITS_PER_CHAR (8)
// #define NaN (1./0.-1./0.)
// #define Inf (1./0.)
/*}}}  */
/*{{{  DO_BREAK*/
// GLKDSP=1044.4: #define BREAK_ now defined: For lint, to remove the bulk of "control flows into case/default" (warning 616)
#ifdef DO_BREAK
  // For lint, to remove the bulk of "control flows into case/default" (warning 616)
  #define BREAK_ break
  /*lint -save +fce -e309 : Continue on error, filter #error */
  #error DO_BREAK filters some PC-lint warnings 616, undef to create functional code! It's ok for run-time make, DO_BREAK is not defined in "mak"-files.
  /*lint -restore */
#else
  // Resolves into single ';' (=null statemennt)
  #define BREAK_
#endif
/*}}}  */
/*{{{  NO_BREAKPOINT_C and BREAKPOINT_F*/
#if (defined NO_BREAKPOINT_C)
   // Observe that ExceptionHandler calls Breakpoint directly, so it cannet be removed!
   #define BREAKPOINT_F(b)
#else
   #define BREAKPOINT_F(b) Breakpoint(b)
#endif
/*}}}  */
/*{{{  architectures and operating systems*/
#define TRANSPUTER 0
#define PC   1
#define VAX  2
#define SUN3 3
#define SUN4 4
#define LITTLE 0
#define BIG 1
#define NONE  0
#define DOS   1
#define VMS   2
#define SUNOS 3
/*}}}  */
/*{{{  endianness*/
#define LITTLE_AND_LITTLE
/*}}}  */
/*{{{  maths support*/
#define NaN ((float)0x7f800010)
#define Inf ((float)0x7f800000) // DSP: 0x7f7fffff (?)
/*}}}  */
/*{{{  jmp_buf*/
extern jmp_buf STOPP_env; // In <setjmp.h>, was originally in SPOC
// For lint:
// Info 718: _setjmp undeclared, assumed to return int
// Info 746: call to _setjmp() not made in the presence of a prototype
// --- Global Wrap-up
// Warning 628: no argument information provided for function _setjmp()
// This did not quiet lint, we still had to do "-esym(526,_setjmp)" in occam2c.lnt
extern int setjmp (jmp_buf); // In <rts.src>, inserted by Teig. This quiets Texas compiler!
/*}}}  */
/*{{{  typedef tFuncPtr, CHAN, tTask, bool, tTimer*/
typedef const void *(*tFuncPtr)();
typedef struct Task tTask; /* "struct Task" defined in fold below */
#define NoTask (tTask *)0
typedef struct { tTask *Task; void *Data; } CHAN;
#define false 0
// Better for lint, will avoid all lint 731's:
#define true (1) 
// was: true (!false)
#define SETSCOPE(S)
typedef long tTimer;
#define AFTER(a,b) ((a-b)>0)
/*}}}  */
/*{{{  task states and priorities*/
//efine NUM_PRIORITY_LEVELS 2
#define NUM_PRIORITY_LEVELS 3 // When DINT1 needed to be served fast
typedef enum
{
   HighPriority = 0,
   LowPriority  = 1
} tTaskPri;
typedef enum
{
   OUT_p     = 1,
   IN_p      = 2,
   EXEC_p    = 3,
   WAIT_p    = 4,
   ALTING_p  = 5,
   TALTING_p = 6,
   TWAIT_p   = 7,
   TSOCK_p   = 8
} tTaskMode;
typedef enum
{
   NotAlting_p = -1,
   Enabling_p  = -2,
   Waiting_p   = -3,
   Ready_p     = -4,
   TReady_p    = -5
} tAltMode;
typedef enum
{
   TimeNotSet_p = -2,
   TimeSet_p    = -3
} tTimerMode;
/*}}}  */
/*{{{  struct Task*/
struct Task
{
   tTask *Next;    /* Linked List of Active Tasks */
   tTask *Parent;  /* Parent Task */
   tFuncPtr Func;  /* Current Function being executed by this task */
   void *FP;       /* Frame Pointer for this task */
   tTaskMode state;
   int Children;   /* Active Children Count */
   char *name;     /* Task Name */
   union
   {
      struct
      {
	 long len;     /* Comms */
	 void *data;   /* Comms */
	 // char buff[4]; /* Comms */ // lint: Not referenced (768)
      } io;
      struct
      {
	 tTimerMode TimerMode; /* Timer Alternation */
	 tTimer time;
      } timer;
   } comms;
   tAltMode AltMode; /* Alternation */
   int TaskId;       /* Number identifying task, for debugging */
   int TaskPriority;
};
/*}}}  */
/*{{{  scheduling queues*/
extern tTask *QFP[NUM_PRIORITY_LEVELS];
extern tTask *QBP[NUM_PRIORITY_LEVELS];
extern tTask *QTM;
extern tTask *CURTASK;
extern tTimer TIMER;
/*}}}  */
/*{{{  MSG*/
//                                    bits 8..3:
//                                     \x20 See ULL_CALC_SETERR_A in "Survive.h"
static char* MSG_EXRAM_ERR          = "\x28 EXRAM error";
static char* MSG_STACK_OVERFLOW     = "\x30 Stack overflow";
//atic char* MSG_FLASHDRV           =  \x38 Defined in "FlashDrv.c"
static char* MSG_I0_CODE_CKSUM_ERR  = "\x40 "; // Vacant
static char* MSG_I1_CODE_CKSUM_ERR  = "\x48 "; // vacant
static char* MSG_I01_CODE_CKSUM_ERR = "\x50 I01 Err";
static char* MSG_ALBUM_ERR          = "\x58 Album error";
//
static char* MSG_NULL               = "\x98";
static char* MSG_MALLOC             = "\xa0 Malloc failed in main";
static char* MSG_TIMER              = "\xa8 Timer interrupt failed";
static char* MSG_EFROL              = "\xb0 ERROR FLAG raised on line %d of file %s";
static char* MSG_TA                 = "\xb8 Terminating application";
static char* MSG_INT                = "\xc0 Interrupt processing failed";
static char* MSG_SP                 = "\xc8 STOPPing process %s";
static char* MSG_IF                 = "\xd0 All IF branches failed";
static char* MSG_CASE               = "\xd8 No CASE option matched";
static char* MSG_CASEIN             = "\xe0 Input tag does not match CASE options";
static char* MSG_STOP               = "\xe8 Executed STOP process";
static char* MSG_PRI                = "\xf0 Invalid priority level";
static char* MSG_IP                 = "\xf8 Invalid Instruction Pointer";
/*}}}  */
/*{{{  runtime error handling*/
#if (defined STOPP_ON_ERROR)
   #define SETERR_PROCEED longjmp (STOPP_env,0);
#elif (defined CONTINUE_ON_ERROR)
   #define SETERR_PROCEED
#else // TERMINATE_ON_ERROR = GLK-100
   #define SETERR_PROCEED exit(1)
#endif
// A copy of these lines are in "Seterr2c.h":
// GLKDSP=1044: seterr_ is new, SETERR() redefined:
#define SETERR(M)         /*lint -save -function(exit,seterr_) */ seterr_ (M)                   /*lint -restore*/
//efine SETERR(M)         /*lint -save -function(exit,seterr)  */ seterr  (M,__LINE__,__FILE__) /*lint -restore*/
#define SETERR_MLF(M,L,F) /*lint -save -function(exit,seterr)  */ seterr  (M,L,F)               /*lint -restore*/
// lint: Warning 644: var_name may not have been initialized in state-macines
static void seterr  (char *Message, int LineNo, char *FileName);
extern void seterr_ (char *Message);
/*}}}  */
/*{{{  primitive types*/
/*{{{  values*/
#undef INT
#undef INT16
#undef INT32
#undef INT64
#undef BYTE
#undef REAL32
#undef REAL64
#undef BOOL
#undef TEMPVAL
// New definition 18Aug98 to satisfy lint better:
// I still had to swith lint 737 off, so maybe we could just keep the old ones?
#define INT   int
#define INT32 int
#define INT16 int
// Was:
// #define INT   long int
// #define INT32 long int
// #define INT16 short int
//#define BYTE  unsigned char // Original
#define BYTE char             // Teig: Helps for debugger, arrays; but not single-bytes
#define REAL32 float
#define BOOL char
typedef union
{
   BOOL VBOOL;
   INT VINT;
   INT32 VINT32;
   INT16 VINT16;
   BYTE VBYTE;
   REAL32 VREAL32;
} TEMPVAL;
#define MOSTPOSINT16 ((INT16)0x7FFF)
#define MOSTNEGINT16 ((INT16)0xFFFF8000)  // Teig
#define MOSTPOSINT32 ((INT32)0x7FFFFFFF)
#define MOSTNEGINT32 ((INT32)0x80000000)
/*}}}  */
/*{{{  casting down primitives*/
//GLKDSP=1044.3: FailConvert(void), was FailConvert (int V,int L, char *F)
//static void inline FailConvert (int V,int L, char *F)
static void inline FailConvert(void)
{
   // was s e t e r r(MSG_NULL,L,F);
   SETERR(MSG_NULL);
}
#ifdef CHECK_CONVERSIONS
// #define downtoINT16(v) ((((v)<MOSTNEGINT16)||((v)>MOSTPOSINT16)) ? (FailConvert((v),__LINE__,__FILE__),((INT16)(v))):((INT16)(v)))
// #define downtoBYTE(v)  ((((v)<0)||((v)>255)) ?                     (FailConvert((v),__LINE__,__FILE__),((BYTE)(v))):((BYTE)(v)))
// #define downtoBOOL(v)  ((((v)<0)||((v)>1)) ?                       (FailConvert((v),__LINE__,__FILE__),((BOOL)(v))):((BOOL)(v)))
//GLKDSP=1044.3: New downtoINT16, downtoBYTE, downtoBOOL
#define downtoINT16(v)  ((((v)<MOSTNEGINT16)||((v)>MOSTPOSINT16)) ? (FailConvert(), ((INT16)(v))) : ((INT16)(v)))
#define downtoBYTE(v)   ((((v)<0)||((v)>255)) ?                     (FailConvert(), ((BYTE)(v)))  : ((BYTE)(v)))
#define downtoBOOL(v)   ((((v)<0)||((v)>1)) ?                       (FailConvert(), ((BOOL)(v)))  : ((BOOL)(v)))
#define downtoINT32(v)  ((INT32)(v))
#define downtoREAL32(v) ((REAL32)(v))
#else
#define downtoINT32(v)  ((INT32)(v))
#define downtoINT16(v)  ((INT16)(v))
#define downtoBYTE(v)   ((BYTE)(v))
#define downtoBOOL(v)   ((BOOL)(v))
#define downtoREAL32(v) ((REAL32)(v))
#endif
/*}}}  */
/*{{{  fixed word size integer conversions*/
#define INT32INT32(v) (v)
#define INT32INT16(v) ((INT32) (v))
#define INT32BYTE(v)  ((INT32) (v))
#define INT32BOOL(v)  ((INT32) ((v)?1:0))
#define INT16INT32(v) downtoINT16(v)
#define BYTEINT32(v)  downtoBYTE(v)
#define BOOLINT32(v)  downtoBOOL(v)
#define INT16INT16(v) (v)
#define INT16BYTE(v)  ((INT16) (v))
#define INT16BOOL(v)  ((INT16) ((v)?1:0))
#define BYTEINT16(v)  downtoBYTE(v)
#define BOOLINT16(v)  downtoBOOL(v)
#define BYTEBYTE(v)   (v)
#define BYTEBOOL(v)   ((BYTE) ((v)?1:0))
#define BOOLBYTE(v)   downtoBOOL(v)
#define BOOLBOOL(v)   (v)
/*}}}  */
/*{{{  REAL32 conversions*/
#define INT32REAL32TRUNC(v) downtoINT32(v)
#define REAL32INT32TRUNC(v) ((REAL32) (v))
#define INT32REAL32ROUND(v) downtoINT32((v)+0.5)
#define REAL32INT32ROUND(v) ((REAL32) (v))
#define INT16REAL32TRUNC(v) downtoINT16(v)
#define REAL32INT16TRUNC(v) ((REAL32) (v))
#define INT16REAL32ROUND(v) downtoINT16((v)+0.5)
#define REAL32INT16ROUND(v) ((REAL32) (v))
#define BYTEREAL32TRUNC(v) downtoBYTE(v)
#define REAL32BYTETRUNC(v) ((REAL32) (v))
#define BYTEREAL32ROUND(v) downtoBYTE((v)+0.5)
#define REAL32BYTEROUND(v) ((REAL32) (v))
#define BOOLREAL32TRUNC(v) downtoBOOL(v)
#define REAL32BOOLTRUNC(v) ((REAL32) (v))
#define BOOLREAL32ROUND(v) downtoBOOL((v)+0.5)
#define REAL32BOOLROUND(v) ((REAL32) (v))
#define REAL32REAL32(v)      (v)
#define REAL32REAL32ROUND(v) (v)
#define REAL32REAL32TRUNC(v) (v)
/*}}}  */
/*{{{  conversions involving INT*/
#if (BYTES_PER_WORD==4)
#define MOSTPOSINT MOSTPOSINT32
#define MOSTNEGINT MOSTNEGINT32
#define INT16INT(v) INT16INT32(v)
#define INT32INT(v) INT32INT32(v)
#define INTINT(v)   INT32INT(v)
#define INTINT16(v) INT32INT16(v)
#define INTINT32(v) INT32INT32(v)
#define INTBOOL(v)  INT32BOOL(v)
#define INTBYTE(v)  INT32BYTE(v)
#define BYTEINT(v)  BYTEINT32(v)
#define BOOLINT(v)  BOOLINT32(v)
#define INTREAL32TRUNC(v) INT32REAL32TRUNC(v)
#define REAL32INTTRUNC(v) REAL32INT32TRUNC(v)
#define INTREAL32ROUND(v) INT32REAL32ROUND(v)
#define REAL32INTROUND(v) REAL32INT32ROUND(v)
#elif (BYTES_PER_WORD==2)
#define MOSTPOSINT MOSTPOSINT16
#define MOSTNEGINT MOSTNEGINT16
#define INT16INT(v) INT16INT16(v)
#define INT32INT(v) INT32INT16(v)
#define INTINT(v)   INT16INT16(v)
#define INTINT16(v) INT16INT16(v)
#define INTINT32(v) INT16INT32(v)
#define INTBOOL(v)  INT16BOOL(v)
#define INTBYTE(v)  INT16BYTE(v)
#define BYTEINT(v)  BYTEINT16(v)
#define INTREAL32TRUNC(v) INT16REAL32TRUNC(v)
#define REAL32INTTRUNC(v) REAL32INT16TRUNC(v)
#define INTREAL32ROUND(v) INT16REAL32ROUND(v)
#define REAL32INTROUND(v) REAL32INT16ROUND(v)
#else
#error Compilation Error- Unsupported word length
#endif
/*}}}  */
/*}}}  */
/*{{{  SPOC 1.3*/
// Teig: This turned up in the COMPLEX32 RECORD example:
#define USER INT
#define SIZEUSER(s) (sizeof(INT)*s)
/*}}}  */
/*{{{  CheckPrimitiveSizes*/
static void inline CheckPrimitiveSizes(void)
{
   char *failedtype=NULL;
   // All these tests evaluate to false, so the code is optimized away:
   // Not needed: we already filter with 774 in occam2c.lnt:
   /* lint -save -e774  Boolean within 'if' always evaluates to False*/
   if (4 * sizeof(INT)    != BYTES_PER_WORD) failedtype="INT";
   if (4 * sizeof(INT32)  != 4             ) failedtype="INT32";
   if (2 * sizeof(INT16)  != 2             ) failedtype="INT16";
   if (    sizeof(BOOL)   != 1             ) failedtype="BOOL";
   if (    sizeof(BYTE)   != 1             ) failedtype="BYTE";
   if (4 * sizeof(REAL32) != 4             ) failedtype="REAL32";
   /* lint -restore */
   if (failedtype != NULL)
   {
      // exit(1);
      SETERR(MSG_NULL); // Internal Error - C primitive type used is not of expected size
   }
}
/*}}}  */
/*{{{  frame header*/
typedef struct
{
   void     *ReturnFP;
   tFuncPtr  ReturnFunc;
   int       IP;
   TEMPVAL   Temp;
   // int       Scope; // lint: Not referenced (768)
   char     *ProcName;
} tHeader;
/*}}}  */
/*{{{  scheduling / communication primitives*/
#define INPUT(c,m,s,l)  {FP->_Header.IP = l;  if (ChanIn  (c,m,s)) return;} BREAK_
#define INPUT1(c,m,l)   {FP->_Header.IP = l;  if (ChanIn1 (c,m)) return;} BREAK_
#define INPUT2(c,m,l)   {FP->_Header.IP = l;  if (ChanIn2 (c,m)) return;} BREAK_
#define INPUT4(c,m,l)   {FP->_Header.IP = l;  if (ChanIn4 (c,m)) return;} BREAK_
#define INPUT8(c,m,l)   INPUT(c,m,8,l)
#define OUTPUT(c,m,s,l) {FP->_Header.IP = l;  if (ChanOut (c,m,s)) return;} BREAK_
#define OUTPUT1(c,m,l)  {FP->_Header.IP = l;  if (ChanOut1(c,m)) return;} BREAK_
#define OUTPUT2(c,m,l)  {FP->_Header.IP = l;  if (ChanOut2(c,m)) return;} BREAK_
#define OUTPUT4(c,m,l)  {FP->_Header.IP = l;  if (ChanOut4(c,m)) return;} BREAK_
#define OUTPUT8(c,m,l)  OUTPUT(c,m,8,l)
#define OUTPUT4_InScheduler(c,m,l) {FP->_Header.IP = l; ChanOut4(c,m);} // (Teig) No return statement
#define ALT()       { AltStart(); }
#define ENBC(f,c)   { if (f) EnableChannel(c); }
#define ENBS(f)     { if (f) EnableSkip(); }
#define ENBT(f,t)   { if (f) EnableTimer(t); }
#define ALTWT(l)    { FP->_Header.IP = l; if (AltWait()) return; } BREAK_
#define DISC(l,f,c) ( (f) ? DisableChannel(l,c) : (false) )
#define DISS(l,f)   ( (f) ? DisableSkip(l)      : (false) )
#define DIST(l,f,t) ( (f) ? DisableTimer(l,t)   : (false) )
#define DELAY(t,l)  { FP->_Header.IP = l; WaitOnTimer(t); return; } BREAK_
#define ALTEND()    { FP->_Header.IP = AltFinish(); break; } BREAK_
#ifdef FASTGOTOS
#define CASE(x) case x: label_ ## x
#define GOTO(x) goto label_ ## x; BREAK_
#else
#define CASE(x) case x
#define GOTO(x) {FP->_Header.IP = x; break;}
#endif
#define STARTP(t,f,s,n,p) {(s)->Chain = FP;  (s)->_Header.IP = 0; Start_Process(t,(tFuncPtr)f,s,n,p);}
#define PLACED_STARTP(proc,t,f,s,n) {(s)->Chain = FP;  (s)->_Header.IP = 0; Start_Placed(t,(tFuncPtr)f,s,n,proc); }
#define ENDP()          {End_Process(); return; } BREAK_
#define WAITP(l)        {FP->_Header.IP = l; DeSchedule(WAIT_p); return; } BREAK_
#define INITCH(c)       {(c)->Task = NoTask; (c)->Data = NULL; }
#define CALL(p,s,l,n)   {(s)->_Header.ReturnFunc=CURTASK->Func;\
			 (s)->_Header.ReturnFP=FP;\
			 FP->_Header.IP = l;\
			 (s)->_Header.ProcName = n;\
			 CURTASK->Func=(tFuncPtr)p;\
			 CURTASK->FP=(void *)s;\
			 IDENTIFYCALL(n);\
			 (s)->_Header.IP = 0;\
			 return;\
			} BREAK_
#define RETURN()        {CURTASK->Func=FP->_Header.ReturnFunc;\
			 CURTASK->FP = FP->_Header.ReturnFP;\
			 return;\
			} BREAK_
#define WAITSOCKET(s)  { CURTASK->Func=FP->_Header.ReturnFunc;\
			 CURTASK->FP = FP->_Header.ReturnFP;\
			 WaitSocket(s); return; }
/*}}}  */
/*{{{  scheduling / communication routines*/
/*{{{  DeSchedule*/
static void inline DeSchedule(register tTaskMode state)
{
   register tTask *task = CURTASK;
   task->state = state;
   QFP[task->TaskPriority] = CURTASK->Next;
   if (QFP[task->TaskPriority] == NoTask)
   {
      QBP[task->TaskPriority] = NoTask;
   }
}   
/*}}}  */
/*{{{  ReSchedule*/
static void inline ReSchedule(register tTask *task)
{
   if (task->state == TWAIT_p || task->state == TALTING_p)
   {
      tTask *prev = NoTask;
      tTask *this = QTM;
      while(this != NoTask && this != task)
      {
	 prev = this;
	 this = this->Next;
      }
      if (prev != NoTask)
	 prev->Next = task->Next;
      else
	 QTM = task->Next;
   }
   task->Next = NoTask;
   if (QFP[task->TaskPriority] != NoTask)
      QBP[task->TaskPriority]->Next = task;
   else
      QFP[task->TaskPriority] = task;
   task->state = EXEC_p;
   QBP[task->TaskPriority] = task;
}
/*}}}  */
/*{{{  End_Process*/
static void inline End_Process (void)
{
   register tTask *task = CURTASK;
   QFP[task->TaskPriority] = task->Next;
   if (QFP[task->TaskPriority] == NoTask) QBP[task->TaskPriority] = NoTask;
   task->Next = NoTask;
   if (task->Parent)
   {
      if (--(task->Parent->Children) == 0) ReSchedule(task->Parent);
   }
}
/*}}}  */
/*{{{  ChanIn*/
static int inline ChanIn (register CHAN *chan,register void *data,register long len)
{
   register tTask *task = chan->Task;
   if (task != NoTask)
   {
      if (len > 0) memcpy(data,task->comms.io.data,(size_t)len);
      chan->Task = NoTask;
      ReSchedule(task);
      return 0;
   }
   chan->Task = CURTASK;
   CURTASK->comms.io.data = data;
   CURTASK->comms.io.len = len;
   DeSchedule(IN_p);
   return 1;
}
/*}}}  */
/*{{{  ChanIn1*/
static int inline ChanIn1(register CHAN *chan,register void *data)
{
   register tTask *task = chan->Task;
   if (task != NoTask)
   {
      *((BYTE *)data) = *((BYTE *)task->comms.io.data);
      chan->Task = NoTask;
      ReSchedule(task);
      return 0;
   }
   chan->Task = CURTASK;
   CURTASK->comms.io.data = data;
   CURTASK->comms.io.len = 1;
   DeSchedule(IN_p);
   return 1;
}
/*}}}  */
/*{{{  ChanIn2*/
static int inline ChanIn2(register CHAN *chan,register void *data)
{
   register tTask *task = chan->Task;
   if (task != NoTask)
   {
      *((INT16 *)data) = *((INT16 *)task->comms.io.data);
      chan->Task = NoTask;
      ReSchedule(task);
      return 0;
   }
   chan->Task = CURTASK;
   CURTASK->comms.io.data = data;
   CURTASK->comms.io.len = 2;
   DeSchedule(IN_p);
   return 1;
}
/*}}}  */
/*{{{  ChanIn4*/
static int inline ChanIn4(register CHAN *chan,register void *data)
{
   register tTask *task = chan->Task;
   if (task != NoTask)
   {
      *((INT32 *)data) = *((INT32 *)task->comms.io.data);
      chan->Task = NoTask;
      ReSchedule(task);
      return 0;
   }
   chan->Task = CURTASK;
   CURTASK->comms.io.data = data;
   CURTASK->comms.io.len = 4;
   DeSchedule(IN_p);
   return 1;
}
/*}}}  */
/*{{{  ChanOut*/
static int inline ChanOut (register CHAN *chan,register void *data,register long len)
{
   register tTask *task = chan->Task;
   if (task != NoTask)
   {
      tAltMode mode = task->AltMode;
      if (mode == NotAlting_p)
      {
	 if (len>0) memcpy(task->comms.io.data,data,(size_t)len);
	 chan->Task = NoTask;
	 ReSchedule(task);
	 return 0;
      }
      else if (mode == Waiting_p)
      {
	 ReSchedule(task);
      }
   }
   chan->Task = CURTASK;
   CURTASK->comms.io.data = data;
   CURTASK->comms.io.len = len;
   DeSchedule(OUT_p);
   return 1;
}
/*}}}  */
/*{{{  ChanOut1*/
static int inline ChanOut1 (register CHAN *chan,register void *data)
{
   register tTask *task = chan->Task;
   if (task != NoTask)
   {
      tAltMode mode = task->AltMode;
      if (mode == NotAlting_p)
      {
	 *((BYTE *)task->comms.io.data) = *((BYTE *)data);
	 chan->Task = NoTask;
	 ReSchedule(task);
	 return 0;
      }
      else if (mode == Waiting_p)
      {
	 task->AltMode = Ready_p;
	 ReSchedule(task);
      }
   }
   chan->Task = CURTASK;
   CURTASK->comms.io.data = data;
   CURTASK->comms.io.len = 1;
   DeSchedule(OUT_p);
   return 1;
}
/*}}}  */
/*{{{  ChanOut2*/
static int inline ChanOut2 (register CHAN *chan,register void *data)
{
   register tTask *task = chan->Task;
   if (task != NoTask)
   {
      tAltMode mode = task->AltMode;
      if (mode == NotAlting_p)
      {
	 *((INT16 *)task->comms.io.data) = *((INT16 *)data);
	 chan->Task = NoTask;
	 ReSchedule(task);
	 return 0;
      }
      else if (mode == Waiting_p)
      {
	 task->AltMode = Ready_p;
	 ReSchedule(task);
      }
   }
   chan->Task = CURTASK;
   CURTASK->comms.io.data = data;
   CURTASK->comms.io.len = 2;
   DeSchedule(OUT_p);
   return 1;
}
/*}}}  */
/*{{{  ChanOut4*/
static int inline ChanOut4 (register CHAN *chan,register void *data)
{
   register tTask *task = chan->Task;
   if (task != NoTask)
   {
      tAltMode mode = task->AltMode;
      if (mode == NotAlting_p)
      {
	 *((INT32 *)task->comms.io.data) = *((INT32 *)data);
	 chan->Task = NoTask;
	 ReSchedule(task);
	 return 0;
      }
      else if (mode == Waiting_p)
      {
	 task->AltMode = Ready_p;
	 ReSchedule(task);
      }
   }
   chan->Task = CURTASK;
   CURTASK->comms.io.data = data;
   CURTASK->comms.io.len = 4;
   DeSchedule(OUT_p);
   return 1;
}
/*}}}  */
/*{{{  ChanOut4_InterruptEvent Teig*/
static int inline ChanOut4_InterruptEvent (register CHAN *chan, register void *data, register tTask *sender)
{
   register tTask *task = chan->Task;
   int return_value = 0; // Default is not success!
   if (task != NoTask)
   {
      tAltMode mode = task->AltMode;
      if (mode == NotAlting_p)
      {
	 // return 0; // Not success! (Default value used)
      }
      else if (mode == Waiting_p)
      {
	 task->AltMode = Ready_p;
	 ReSchedule(task); // Receiving task
	 // Receiving end takes data from this sending end:
	 chan->Task = sender;
	 sender->comms.io.data = data;
	 sender->comms.io.len = 4;
	 return_value = 1; // Success!
      }
   }
   else
   {
      // return 0; // Not success! (Default value used)
   }
   return return_value;
}
/*}}}  */
/*{{{  TimerWait*/
static void inline TimerWait(tTimer when)
{
   tTask *prev = NoTask;
   tTask *tq = QTM;
   CURTASK->comms.timer.time = when;
   while(tq != NoTask && !AFTER(tq->comms.timer.time,when))
   {
      prev = tq;
      tq = tq->Next;
   }
   if (prev == NoTask)
   {
      CURTASK->Next = QTM;
      QTM=CURTASK;
   }
   else
   {
      CURTASK->Next = prev->Next;
      prev->Next = CURTASK;
   }
}
/*}}}  */
/*{{{  AltStart*/
static void inline AltStart (void)
{
   #ifdef CHECK_INTERNALS
   if (CURTASK->AltMode != NotAlting_p)
   {
      // exit(1);
      SETERR(MSG_NULL);
   }
   #endif
   CURTASK->AltMode = Enabling_p;
   CURTASK->comms.timer.TimerMode = TimeNotSet_p;
}
/*}}}  */
/*{{{  EnableChannel*/
static void inline EnableChannel (register CHAN *chan)
{
   if (chan->Task != CURTASK)
   {
      if (chan->Task != NoTask)
      {
	 CURTASK->AltMode = Ready_p;
      }
      else
      {
	 chan->Task = CURTASK;
      }
   }
}
/*}}}  */
/*{{{  EnableSkip*/
static void inline EnableSkip (void)
{
   CURTASK->AltMode = Ready_p;
}
/*}}}  */
/*{{{  EnableTimer*/
static void inline EnableTimer (register long t)
{
   if (CURTASK->comms.timer.TimerMode == TimeNotSet_p)
   {
      CURTASK->comms.timer.TimerMode = TimeSet_p;
      CURTASK->comms.timer.time = t;
   }
   else
   {
      if (AFTER(CURTASK->comms.timer.time,t))
      {
	 CURTASK->comms.timer.time = t;
      }
   }
}
/*}}}  */
/*{{{  AltWait*/
static int  inline AltWait (void)
{
   if ((CURTASK->comms.timer.TimerMode == TimeSet_p) &&
      AFTER(TIMER,CURTASK->comms.timer.time))
   {
      CURTASK->AltMode = TReady_p;
   }
   if (CURTASK->AltMode == Enabling_p)
   {
      CURTASK->AltMode = Waiting_p;
      if (CURTASK->comms.timer.TimerMode == TimeSet_p)
      {
	 DeSchedule(TALTING_p);
	 TimerWait(CURTASK->comms.timer.time);
      }
      else
	 DeSchedule(ALTING_p);
      return 1;
   }
   return 0;
}
/*}}}  */
/*{{{  DisableChannel*/
static BOOL inline DisableChannel (register int label, register CHAN *chan)
{
   if (chan->Task != NoTask)
   {
      if (chan->Task == CURTASK)
      {
	 chan->Task = NoTask;
      }
      else
      {
	 if (CURTASK->AltMode < ((tAltMode)0))
	 {
	    CURTASK->AltMode = (tAltMode) label;
	    return(true);
	 }
      }
   }
   return(false);
}
/*}}}  */
/*{{{  DisableSkip*/
static BOOL inline DisableSkip (register int label)
{
   if (CURTASK->AltMode < ((tAltMode)0))
   {
      CURTASK->AltMode = (tAltMode) label;
      return(true);
   }
   return(false);
}
/*}}}  */
/*{{{  DisableTimer*/
static BOOL inline DisableTimer (register int label, register long t)
{
   if (CURTASK->AltMode == TReady_p && CURTASK->comms.timer.time == t)
   {
      CURTASK->AltMode = (tAltMode) label;
      return(true);
   }
   return(false);
}
/*}}}  */
/*{{{  AltFinish*/
static int  inline AltFinish (void)
{
   tAltMode mode = CURTASK->AltMode;
   #ifdef CHECK_INTERNALS
   if (mode < 0)
   {
      // exit(1);
      SETERR(MSG_NULL);
   }
   else
   #endif
      CURTASK->AltMode = NotAlting_p;
   return (int) mode;
}
/*}}}  */
/*{{{  WaitOnTimer*/
static void WaitOnTimer(tTimer when)
{
   DeSchedule(TWAIT_p);
   TimerWait(when);
}
/*}}}  */
/*{{{  ReadTimer*/
static tTimer inline ReadTimer(void)
{
   // New scheme:
   return TIMER;
   // Since we have only one timer interrupt, why not have
   // only one universal time?
   // Original scheme:
   // register tTask *task = CURTASK;
   // return (task->TaskPriority==0) ? TIMER<<6 : TIMER;
   // This is the only place where TIMER is shifted.
   // The scheme above makes high-pri task time slow
}
/*}}}  */
/*{{{  WaitSocket*/
extern void WaitSocket (int socket);
/*}}}  */
/*{{{  Start_Process*/
extern void Start_Process(register tTask *task, register tFuncPtr Func, register void *FP, register char *name,int Pri);
/*}}}  */
/*{{{  Start_Placed*/
extern void Start_Placed(register tTask *task, register tFuncPtr Func, register void *FP, register char *name,int Processor);
/*}}}  */
/*}}}  */
/*{{{  heap management*/
// Not used, let's remove them
// static char *MSG_HEAP = "Error- Out of heap storage\n"; // If used with GLK-100,
//                          see "MSG" above for how first char should be used
// static inline void *ALLOCVEC(int s)
// {
//    void *vec = malloc((unsigned int) s); /* lint fixed */
//    if (!vec) SETERR(MSG_HEAP);
//
//    return vec;
// }
//
// static inline void FREEVEC(void *vec)
// {
//    free(vec);
// }
/*}}}  */
/*{{{  retype defines*/
#define ALLOCRETYPE(symb,type,size) (symb=(type)ALLOCVEC(size)) /* lint fixed */
#define FREERETYPE(s) FREEVEC(s)
#if (defined BIG_AND_LITTLE || defined LITTLE_AND_BIG)
static inline void RETYPE(int swap,int l,void *d,void *s)
{
   int i;
   char *from=(char *)s;
   char *to=(char *)d;
   for(i = 0; i < l; ++i)
     to[i ^ swap] = *from++;
}
#else
#define RETYPE(swap,l,d,s) memcpy((char*)d,(char*)s,l);
#endif
/*}}}  */
/*{{{  other primitives*/
#define ASSIGN(d,s,n) memcpy(d,s,(size_t)n)
/*{{{  MSG's*/
static char *MSG_ASM   = "Array size mismatch";
static char *MSG_ARM   = "Array RETYPES abbreviation mismatch";
static char *MSG_AIM   = "Array IS abbreviation mismatch";
static char *MSG_CITL  = "Counted input too long";
static char *MSG_EACF  = "Error- Array check failed : %s\n";
static char *MSG_ERCF  = "Error- Range check (0<=%d<%d) failed\n";
static char *MSG_ELBCF = "Error- Lower bound check (0<=%d) failed\n"; 
static char *MSG_EUBCF = "Error- Upper bound check (0<=%d,%d<=%d) failed\n"; 
/*}}}  */
/*{{{  Shifts*/
#ifdef FAST_SHIFTS
  #define LOGSHIFTLEFT(t,x,y)  ((signed t)(((unsigned t)(x)) << (y)))
  #define LOGSHIFTRIGHT(t,x,y) ((signed t)(((unsigned t)(x)) >> (y)))
  //lint -esym(750, BITS_PER_WORD) To accept that it is not referenced
#else
  // "y" appears twice, side effects possible (try "n++" for "y"):
  // PC-lint could then complain with warning 666, like:
  //   "Expression with side effects passed to repeated parameter 3 in macro LOGSHIFTLEFT"
  //  Example of this in FlashDriver
  #define LOGSHIFTLEFT(t,x,y)  (((y) >= ((INT)(sizeof(t)*BITS_PER_WORD))) ? 0 : ((signed t)(((unsigned t)(x)) << (y))))
  #define LOGSHIFTRIGHT(t,x,y) (((y) >= ((INT)(sizeof(t)*BITS_PER_WORD))) ? 0 : ((signed t)(((unsigned t)(x)) >> (y))))
#endif
/*}}}  */
/*{{{  CHK*/
#ifdef CHECK_ARRAYS
#define CHK(c,s) if (!(c)) {SETERR(MSG_NULL);}
#else
#define CHK(c,s)
#endif
/*}}}  */
#ifdef CHECK_RANGES
#ifdef USE_RANGE_MACROS
/*{{{  USE_RANGE_MACROS ........................... (not in GL-100)*/
// was (3) s e t e r r (MSG_NULL,__LINE__,__FILE__)
#define RNGCHK(v,s) ((((v) < 0) || ((v) >= (s))) ? (,SETERR(MSG_NULL),v) :v)
#define RNGCHKLB(v) (((v) < 0) ? (,SETERR(MSG_NULL),v) :v)
// GLKDSP=1044.2: Macro RNGCHKUB does not need to return b (never used, discovered by Lint)
#define RNGCHKUB(b,f,s) ((((f) < 0) || (((b)+(f)) > (s))) ? (,SETERR(MSG_NULL),b) :b)
/*}}}  */
#elif (!defined USE_RANGE_FUNCTIONS_NO_LINEFILE)
/*{{{  NOT USE_RANGE_FUNCTIONS_NO_LINEFILE ........ (not in GL-100)*/
#define RNGCHK(v,s) rngchk(v,s,__LINE__,__FILE__)
static INT inline rngchk(INT v, INT s, int line, char *file)
{
   if ((v<0)||(v>=s))
   {
      // was s e t e r r(MSG_NULL,line,file);
      //SETERR_MLF(MSG_NULL,line,file);
      SETERR(MSG_NULL);
   }
   return v;
}
#define RNGCHKLB(v) rngchklb(v,__LINE__,__FILE__)
static INT inline rngchklb(INT v, int line, char *file)
{
   if (v<0)
   {
      // was s e t e r r(MSG_NULL,line,file);
      SETERR_MLF(MSG_NULL,line,file);
   }
   return v;
}
// GLKDSP=1044.2: Macro RNGCHKUB does not need to return b (never used, discovered by Lint)
#define RNGCHKUB(b,f,s) rngchkub(b,f,s,__LINE__,__FILE__)
static INT inline rngchkub(INT b, INT f, INT s, int line, char *file)
{
   if ((f<0)||((b+f)>s))
   {
      // was s e t e r r(MSG_NULL,line,file);
      SETERR_MLF(MSG_NULL,line,file);
   }
   return b;
}
/*}}}  */
#elif (defined USE_RANGE_FUNCTIONS_NO_LINEFILE)
/*{{{  USE_RANGE_FUNCTIONS_NO_LINEFILE ............ (in GL-100)*/
// Teig:
// Reasons for using USE_RANGE_FUNCTIONS_NO_LINEFILE:
// 1. Reduces code (by 1-2% only)
// 2. Increases speed of tests
// 3. We don't have a "println" that can actually use the line number an file name!
// 4. The debugger tells us about the call tree
#define RNGCHK(v,s) rngchk_(v,s)
static INT inline rngchk_(INT v, INT s)
{
   if ((v<0)||(v>=s))
   {
      // was s e t e r r (MSG_NULL,__LINE__,__FILE__); // Here
      SETERR(MSG_NULL); // Here
   }
   return v;
}
#define RNGCHKLB(v) rngchklb_(v)
static INT inline rngchklb_(INT v)
{
   if (v<0)
   {
      // was s e t e r r (MSG_NULL,__LINE__,__FILE__); // Here
      SETERR(MSG_NULL); // Here
   }
   return v;
}
// GLKDSP=1044.2: Macro rngchkub_ return parameter is never used, so we remove it
// GLKDSP=1044.2: RNGCHKUB is always used as the left-hand side of a comma operator
//
#define RNGCHKUB(b,f,s) rngchkub_(b,f,s)
static void inline rngchkub_(INT b, INT f, INT s)
{
   if ((f<0)||((b+f)>s))
   {
      // was s e t e r r (MSG_NULL,__LINE__,__FILE__); // Here
      SETERR(MSG_NULL); // Here
   }
   // return b;
}
/*}}}  */
#endif
#else
#define RNGCHK(v,s) (v)
#define RNGCHKLB(v) (v)
#define RNGCHKUB(b,f,s) (b)
#endif
#ifdef SHOWTASKING
#define IDENTIFYTASK()
#define IDENTIFYCALL(n)  
#else
#define IDENTIFYCALL(n)  
#define IDENTIFYTASK()
#endif
/*}}}  */