/************************************************************************/
/*									*/
/*	If the library function alloca is available and the C programs	*/
/*	are compiled with the flag -DStackAlloc, then the memory space	*/
/*	for open array value parameters will be allocated in the stack	*/
/*	frame of the corresponding procedure. This temporary space	*/
/*	will be freed automatically when the procedure returns.		*/
/*	Otherwise, malloc and free will be used to allocate and		*/
/*	deallocate memory space for open array value parameters.	*/
/*									*/
/*	By default open array value parameters are copied using the	*/
/*	library function memcpy. This can be switched to bcopy by	*/
/*	compiling with the flag -DBCOPY on systems without memcpy.	*/
/*									*/
/************************************************************************/

#include <math.h>			  /* e.g. M_PI */
#include <stdio.h>			  /* e.g. fprintf() */
#include <string.h>			  /* e.g. strncpy(), memcpy() */
#include <stdlib.h>			  /* e.g. exit() */
#include <limits.h>			  /* e.g. DBL_MIN */

#ifdef __sun__			          /* Our SUNs don't have headers */
extern double drand48(void);		  /* which define the rand48() */
extern long   mrand48(void);		  /* functions. :-( */
extern void   srand48(long);		  /* Usually they are in stdlib.h */
#endif

/* Definition of library functions **************************************/

#ifdef StackAlloc
#include <alloca.h>			  /* alloca() */
#else
#include <malloc.h>			  /* malloc(), free() */
#endif

# ifdef __STDC__
# define ARGS(parameters)       parameters
# else
# define ARGS(parameters)       ()
# endif

/* Definition of standard constants *************************************/

#ifndef FALSE
#define FALSE           ((BOOLEAN) 0)
#endif
#ifndef TRUE
#define TRUE            ((BOOLEAN) 1)
#endif
#define NIL             0L
#define EOL             '\n'
#ifdef M_PI
#define pi              M_PI   /*3.141592653589793116*/
#else
#define pi              3.141592653589793116
#endif

/* Definition of basic types ********************************************/

typedef long            INTEGER;
typedef unsigned long	CARDINAL;
typedef unsigned char   BOOLEAN;
typedef unsigned char   CHAR;
typedef double          REAL;

/* Definition of standard types *****************************************/

typedef unsigned long   BITSET;
typedef void            (*PROC)();
typedef unsigned char   WORD;
typedef WORD            BYTE;
#ifdef __STDC__
typedef void           *ADDRESS;
#else
typedef char           *ADDRESS;
#endif

/* Definition of parallaxis types ***************************************/

typedef struct S_1 {
  struct S_1 *Previous;
  CHAR *Elem;
} BOOLEAN_ELEM, *BOOLEAN_ELEM_PTR;

typedef struct {
  CARDINAL ElemSize;          /* number of bytes needed for one StackElem */
  BOOLEAN_ELEM_PTR StackElem;
} ACTIVE_STACK, *ACTIVE_STACK_PTR, ELSE_STACK, *ELSE_STACK_PTR;

typedef struct S_2 {
  struct S_2 *Next;
  CARDINAL SourceID;
  CARDINAL DestinationID;
} LINK;

typedef struct {
  struct S_6 *SourceConfig;
  struct S_6  *DestinationConfig;
  LINK *Links;
} CONNECTION;

typedef struct S_3 {
  struct S_3 *Next;
  INTEGER Parameter;
  LINK *Links;
} PARAMETER_LINK;

typedef struct {
  struct S_6 *SourceConfig;
  struct S_6 *DestinationConfig;
  PARAMETER_LINK *ParameterLinks;
} PARAMETER_CONNECTION;

typedef struct S_4 {
  struct S_4 *Next;
  char ConnectionName[256];
  struct S_6 *Configuration;
  LINK *Links;
} GENERIC_CONNECTIONS;

typedef struct S_5 {
  struct S_5 *Next;
  char ConnectionName[256];
  struct S_6 *Configuration;
  PARAMETER_LINK *ParameterLinks;
} GENERIC_PARAMETER_CONNECTIONS;

typedef struct S_6 {
  char Name[256];
  CARDINAL Rank;
  CARDINAL Len;
  INTEGER *Lower;
  INTEGER *Upper;
  CARDINAL *DimLen;
  ACTIVE_STACK_PTR ActiveStack;
  ELSE_STACK_PTR ElseStack;
  GENERIC_CONNECTIONS *Generics;
  GENERIC_PARAMETER_CONNECTIONS *GenericsParam;
} CONFIGURATION;

/* Definition of standard functions *************************************/

#define ABS(x)		((x) < 0 ? -(x) : (x))
#define ABSC(x)	        ((CARDINAL) (x))
#define CHR(x)		((CHAR) (x))
#define FLOAT(x)	((REAL) (x))
#define ORD(x)		((CARDINAL) (x))
#define TRUNC(x)	((CARDINAL) (x))
#define VAL(T,x)	((T) (x))
#define MOD(x, y)       (((x) % (y) < 0) ? (x) % (y) + ((y) < 0 ? -(y) : (y)) : (x) % (y))


extern INTEGER ABSI ARGS((INTEGER x));
extern REAL ABSR ARGS((REAL x));
extern CHAR CAP ARGS((CHAR ch));
extern CARDINAL MOD1 ARGS((INTEGER x, INTEGER y));

/* INTEGER limits */
#ifdef LONG_MIN
#define MIN_INTEGER     LONG_MIN
#else
#define MIN_INTEGER	(-2147483648L)
#endif
#ifdef LONG_MAX
#define MAX_INTEGER     LONG_MAX
#else
#define MAX_INTEGER	2147483647L
#endif

/* CARDINAL limits */
#define MIN_CARDINAL	((CARDINAL)0L)
#ifdef ULONG_MAX
#define MAX_CARDINAL    ULONG_MAX
#else
#define MAX_CARDINAL	((CARDINAL)4294967295L)
#endif

/* BOOLEAN limits */
#define MIN_BOOLEAN	FALSE
#define MAX_BOOLEAN	TRUE

/* CHAR limits */
#undef MIN_CHAR
#define MIN_CHAR	((CHAR)'\0')
#undef MAX_CHAR
#define MAX_CHAR	((CHAR)'\377')

/* REAL limits */
#ifdef DBL_MIN
#define MIN_REAL        DBL_MIN
#else
#define MIN_REAL	4.94065645841246544e-324
#endif
#ifdef DBL_MAX
#define MAX_REAL        DBL_MAX
#else
#define MAX_REAL	1.79769313486231470e+308
#endif

/* Definition of parallaxis standard funktions **************************/

#define ODD(x)		((BOOLEAN)((x) & 01))

#define EVEN(x)         (!ODD(x))
#define LEN(x)          (x).Len
#define LEN1(x, y)      (x).DimLen[(x).Rank - (y)]
#define LOWER(x, y)     (x).Lower[(x).Rank - (y)]
#define RANK(x)         (x).Rank
#define UPPER(x, y)     (x).Upper[(x).Rank - (y)]

extern CARDINAL argc ARGS((void));

#define round(r)        ((INTEGER) ((r) + 0.5))
#define RandomCard      ((CARDINAL) mrand48())
#define RandomInt       ((INTEGER) mrand48())
#define RandomReal      ((REAL) drand48())
#define RandomBool      ((BOOLEAN) ((mrand48() & 01000) == 0))
#define RandomChar      ((CHAR) (mrand48() & 0xff))

extern CARDINAL DIM2ID ARGS((CONFIGURATION Config, INTEGER *Dim));
extern INTEGER *DIM ARGS((CONFIGURATION Config, CARDINAL Dim));
extern CARDINAL *ID ARGS((CONFIGURATION Config));

extern REAL ArcTan2 ARGS((REAL x, REAL y));

/* Definition of standard procedures ************************************/

#define INC(x)		(x)++
#define INC1(x,n)	x += n
#define DEC(x)		(x)--
#define DEC1(x,n)	x -= n

#define EXCL(s,i)	s &= ~(0X1L << (i))
#define INCL(s,i)	s |= 0X1L << (i)

#define ADR(x)		((ADDRESS) &(x))
#define ADR1(x)		((ADDRESS) (x))

/* Definition of parallaxis standard procedures *************************/

extern void argv ARGS((CARDINAL index, CHAR arg[]));

extern void CloseInput ARGS((void));
extern void CloseOutput ARGS((void));
extern void OpenInput ARGS((CHAR *s));
extern void OpenOutput ARGS((CHAR *s));

extern void Read ARGS((CHAR *c));
extern void Read1 ARGS((CONFIGURATION Config, CHAR *c));
extern void ReadBool ARGS((BOOLEAN *b));
extern void ReadBool1 ARGS((CONFIGURATION Config, BOOLEAN *b));
extern void ReadCard ARGS((CARDINAL *c));
extern void ReadCard1 ARGS((CONFIGURATION Config, CARDINAL *c));
extern void ReadInt ARGS((INTEGER *i));
extern void ReadInt1 ARGS((CONFIGURATION Config, INTEGER *i));
extern void ReadReal ARGS((REAL *r));
extern void ReadReal1 ARGS((CONFIGURATION Config, REAL *r));
extern void ReadString ARGS((CHAR *s));
extern void ReadString1 ARGS((CONFIGURATION Config, CHAR **s));

extern void Write ARGS((CHAR c));
extern void Write1 ARGS((CONFIGURATION Config, CHAR c[]));
extern void WriteBool ARGS((BOOLEAN b, CARDINAL l));
extern void WriteBool1 ARGS((CONFIGURATION Config, BOOLEAN b[], CARDINAL l));
extern void WriteCard ARGS((CARDINAL c, CARDINAL l));
extern void WriteCard1 ARGS((CONFIGURATION Config, CARDINAL c[], CARDINAL l));
extern void WriteFixPt ARGS((REAL r, CARDINAL l, CARDINAL m));
extern void WriteFixPt1 ARGS((CONFIGURATION Config, REAL r[], CARDINAL l, CARDINAL m));
extern void WriteInt ARGS((INTEGER i, CARDINAL l));
extern void WriteInt1 ARGS((CONFIGURATION Config, INTEGER i[], CARDINAL l));
extern void WriteLn ARGS((void));
extern void WriteReal ARGS((REAL r, CARDINAL l));
extern void WriteReal1 ARGS((CONFIGURATION Config, REAL r[], CARDINAL l));
extern void WriteString ARGS((CHAR *s));
extern void WriteString1 ARGS((CONFIGURATION Config, CHAR **s));
extern void WriteStringChar1 ARGS((CONFIGURATION Config, CHAR s[]));

/* Definition of (some) set operators ***********************************/

#define SYSTEM_MaxSet		(sizeof (unsigned long) * 8 - 1)

#define SET_ELEM(el)		(0X1UL << (el))
#define SET_cRNG(lo,hi) \
	((lo) <= (hi) ? ~0X0UL >> (lo) << (lo) + SYSTEM_MaxSet - (hi) >> SYSTEM_MaxSet - (hi) : 0X0UL)
#define SET_RANGE(lo,hi)	SET_RANGE1((CARDINAL)(lo), (CARDINAL)(hi))

extern unsigned long SET_RANGE1 ARGS((CARDINAL lo, CARDINAL hi));

#define SET_DIFF(s1,s2)		((s1) & ~(s2))
#define IN(x,s)			((BOOLEAN)((s) >> (x) & 0X1UL))
#define SET_IS_SUBSET1(s1,s2)	((BOOLEAN)!((s1) & ~(s2)))
#define SET_IS_SUBSET2(s1,s2)	((BOOLEAN)!((s2) & ~(s1)))

/* Definition of compiler constants *************************************/

#define SYSTEM_ALIGN		8
#define SYSTEM_MASK             (~(SYSTEM_ALIGN - 1))

/* Definition of compiler types *****************************************/

typedef ADDRESS		OPAQUE;

/* Definition of compiler variables *************************************/

extern unsigned int SYSTEM_argc;
extern char **SYSTEM_argv;
extern char **SYSTEM_envp;

extern FILE *SYSTEM_stdin;
extern FILE *SYSTEM_stdout;

extern CHAR termCH;
extern BOOLEAN Done;

CARDINAL PE;
extern INTEGER *SOURCE_ARRAY;
extern INTEGER *DESTINATION_ARRAY;
extern CONFIGURATION CONFIG_1;

extern GENERIC_CONNECTIONS *ALL_GENERIC_CONNECTIONS;
extern GENERIC_PARAMETER_CONNECTIONS *ALL_GENERIC_PARAMETER_CONNECTIONS;

/* Definition of compiler macros and functions **************************/

#ifdef StackAlloc

#define OPEN_ARRAY_LOCALS	char *FREE_POINTER;
#define ALLOC_OPEN_ARRAYS(size, arrays) \
	FREE_POINTER = alloca((int)((size) + (arrays) * (SYSTEM_ALIGN - 1)));
#define FREE_OPEN_ARRAYS

#else

#define OPEN_ARRAY_LOCALS	char *BLOCK_POINTER, *FREE_POINTER;
#define ALLOC_OPEN_ARRAYS(size, arrays)	\
	BLOCK_POINTER = FREE_POINTER = \
		malloc((unsigned)((size) + (arrays) * (SYSTEM_ALIGN - 1)));
#define FREE_OPEN_ARRAYS	free(BLOCK_POINTER);

#endif

#ifdef BCOPY
#define COPY_OPEN_ARRAY(array, elems, type) \
	{ int ARRAY_SIZE = elems * sizeof(type); \
	  bcopy((char *)array, FREE_POINTER, ARRAY_SIZE); \
	  array = FREE_POINTER; \
	  FREE_POINTER += (ARRAY_SIZE + (SYSTEM_ALIGN - 1)) & SYSTEM_MASK; \
	}
#else
#define COPY_OPEN_ARRAY(array, elems, type) \
	{ int ARRAY_SIZE = elems * sizeof(type); \
	  array = (type *)memcpy(FREE_POINTER, (char *)array, ARRAY_SIZE); \
	  FREE_POINTER += (ARRAY_SIZE + (SYSTEM_ALIGN - 1)) & SYSTEM_MASK; \
	}
#endif

#define FOR_LIMIT_UP(last, step, min) \
	((last) < (min) + ((step) - 1) ? (min) : (last) - ((step) - 1))

#define FOR_LIMIT_DOWN(last, step, max) \
	((last) > (max) + ((step) + 1) ? (max) : (last) - ((step) + 1))

extern void CaseError ARGS((char file[], int line));
extern void ReturnError ARGS((char file[], int line));
extern INTEGER CHECK_PE_NUMBER ARGS((CONFIGURATION Config, INTEGER PeNumber, char file[], int line));

/* Definition of parallaxis compiler macros and functions ***************/

extern void INIT_MODULE ARGS((int argc, char *argv[], char *envp[]));
extern void EXIT_MODULE ARGS((void));

#define FOR_ALL_ACTIVES(Config) \
        for (PE = 0; PE < LEN(Config); PE++) \
          if (IS_ACTIVE(Config, PE))

#define MAX(x, y) (x) > (y) ? (x) : (y)
#define MIN(x, y) (x) < (y) ? (x) : (y)

/* configuration */

extern void INIT_CONFIGURATION ARGS((char Name[], CONFIGURATION *Config, CARDINAL Rank));
extern void SET_BOUNDS ARGS((CONFIGURATION *Config, CARDINAL Dim, INTEGER Lwb, INTEGER Upb));
extern void INIT_STACKS ARGS((CONFIGURATION *Config));
extern void COPY_STACKS ARGS((CONFIGURATION *DestConfig, CONFIGURATION *SourceConfig));
extern void FREE_CONFIGURATION ARGS((CONFIGURATION *Config, BOOLEAN FreeStacks));

/* connection without index */

extern void INIT_CONNECTION ARGS((CONNECTION *Connection, CONFIGURATION *SourceConfig, CONFIGURATION *DestinationConfig));
extern void REGISTER_LINK ARGS((CONNECTION *Connection, INTEGER *SourceArray, INTEGER *DestinationArray));
LINK *GET_LINKS ARGS((CONNECTION Connection));
extern void FREE_CONNECTION ARGS((CONNECTION *Connection));

/* connection with index */

extern void INIT_PARAMETER_CONNECTION ARGS((PARAMETER_CONNECTION *Connection, CONFIGURATION *SourceConfig, CONFIGURATION *DestinationConfig));
extern void REGISTER_PARAMETER_LINK ARGS((PARAMETER_CONNECTION *Connection, INTEGER Index, INTEGER *SourceArray, INTEGER *DestinationArray));
extern LINK *GET_PARAMETER_LINKS ARGS((PARAMETER_CONNECTION Connection, INTEGER Parameter));
extern void FREE_PARAMETER_CONNECTION ARGS((PARAMETER_CONNECTION *Connection));

/* generic connection without index */

extern void INIT_GENERIC_CONNECTION ARGS((char Connection[], CONFIGURATION *Configuration));
extern void REGISTER_GENERIC_LINK ARGS((char ConnectionName[], CONFIGURATION *Configuration, INTEGER *SourceArray, INTEGER *DestinationArray));
extern LINK *GET_GENERIC_LINKS ARGS((char Connection[], CONFIGURATION *Configuration));
extern void FREE_GENERIC_CONNECTION ARGS((char Connection[], CONFIGURATION *Configuration));

/* generic connection with index */

extern void INIT_GENERIC_PARAMETER_CONNECTION ARGS((char Connection[], CONFIGURATION *Configuration));
extern void REGISTER_GENERIC_PARAMETER_LINK ARGS((char ConnectionName[], CONFIGURATION *Configuration, INTEGER Parameter, INTEGER *SourceArray, INTEGER *DestinationArray));
extern LINK *GET_GENERIC_PARAMETER_LINKS ARGS((char Connection[], CONFIGURATION *Configuration, INTEGER Parameter));
extern void FREE_GENERIC_PARAMETER_CONNECTION ARGS((char Connection[], CONFIGURATION *Configuration));

/* check for configuration bounds */

extern BOOLEAN IS_IN_CONFIG ARGS((CONFIGURATION Config, INTEGER *IndexArray));

/* active stack */

extern void INIT_ACTIVE_STACK ARGS((CONFIGURATION *Config));
extern void FREE_ACTIVE_STACK ARGS((CONFIGURATION *Config));
extern void PUSH_ACTIVE_ALL ARGS((CONFIGURATION Config));
extern void PUSH_ACTIVE ARGS((CONFIGURATION Config));
extern void POP_ACTIVE ARGS((CONFIGURATION Config));
extern void TOP_ACTIVE ARGS((CONFIGURATION Config));
extern BOOLEAN_ELEM_PTR READ_ACTIVE ARGS((CONFIGURATION Config));
extern void RESET_ACTIVE ARGS((CONFIGURATION Config, BOOLEAN_ELEM_PTR Pointer));
extern void SET_INACTIVE ARGS((CONFIGURATION Config, CARDINAL Processor));
extern void EXIT_ALL_ACTIVES ARGS((CONFIGURATION Config, BOOLEAN_ELEM_PTR ActivePtr, BOOLEAN_ELEM_PTR ElsePtr));
extern BOOLEAN IS_ACTIVE ARGS((CONFIGURATION Config, CARDINAL Processor));
extern BOOLEAN IS_ANY_ACTIVE ARGS((CONFIGURATION Config));

/* else stack */

extern void INIT_ELSE_STACK ARGS((CONFIGURATION *Config));
extern void FREE_ELSE_STACK ARGS((CONFIGURATION *Config));
extern void PUSH_ELSE ARGS((CONFIGURATION Config));
extern void POP_ELSE ARGS((CONFIGURATION Config));
extern BOOLEAN_ELEM_PTR READ_ELSE ARGS((CONFIGURATION Config));
extern void RESET_ELSE ARGS((CONFIGURATION Config, BOOLEAN_ELEM_PTR Pointer));
extern void COPY_ELSE_TO_ACTIVE ARGS((CONFIGURATION Config));
extern void UNSET_ELSE ARGS((CONFIGURATION Config, CARDINAL Processor));

