/* @(#)Copyright (c), 1987, 1996 StatSci, Inc.  All rights reserved. */

#ifndef _S_SYSTEM_H_ /*(*/
#define _S_SYSTEM_H_

#include <ansi_things.h>
SCCS_ID_C(0046,@(#)system.h 3.67 last edit 6/4/96 StatSci)

#include "cdefs.h"

/* to get size_t declaration when only system.h included */
#if defined(S_ANSI_LibC)
#include <stddef.h>
#else
#if defined(IBMRS6000) || defined(NEXTM)
#include <sys/types.h>
#endif
#endif

#if defined(APOLLO) /*(*/
#define FTRUE -1  
/* Would the default IS_FTRUE definition be OK for Apollo? */
#define IS_FTRUE(x) (((x) & (1 << 31)) != 0)
#define IS_FFALSE(x) (((x) & (1 << 31)) == 0)
#endif /*)*/

#if defined(OSF1_DECALPHA) || defined(DECSTATION) /*(*/
#define FTRUE -1  
#define IS_FTRUE(x) (((x) & 1) != 0)
#define IS_FFALSE(x) (((x) & 1) == 0)
#endif /*)*/

#if defined(HP800) /*(*/
#define FTRUE 0x01000000
#define IS_FTRUE(x) (((x) & (1 << 24)) != 0)
#define IS_FFALSE(x) (((x) & (1 << 24)) == 0)
#endif /*)*/

#ifndef FTRUE /*(*/
#define FTRUE 1
#endif /*)*/

#ifndef FFALSE /*(*/
#define FFALSE 0
#endif /*)*/

#ifndef IS_FTRUE /*(*/
#define IS_FTRUE(x) ((x) != FFALSE)
#endif /*)*/

#ifndef IS_FFALSE /*(*/
#define IS_FFALSE(x) ((x) == FFALSE)
#endif /*)*/

#if (FFALSE != 0) || (FTRUE != 1) /*(*/
#define F77_MAP_LOGICALS
#endif

/* Define this for the new AT&T January 91 Beta Tape */
#if defined(IEEE) /*(*/
#define IEEE754
#endif /*)*/

#if defined(UNIX386)  /* ( */
/*
 * From the July/91 ATT tape:
 *
 * Both the Toshiba 5200 and the AT&T 6386 claim to be IEEE conforming,
 * but aren't in a number of ways.  For example, 1.0/0.0 yields 1.0 and
 * x!=x is 0 for NaN.  Since both of these are used in the S code, these
 * 80386 machines will have to be flagged an non-IEEE754.  If they ever
 * fix these things, IEEE754 can be restored.
 */
#if defined(IEEE754)
#undef IEEE754
#endif
#endif /* ) UNIX386 */

#if defined (NEW)  /*(*/
/* defines for NA */
#define NA_PATTERN 0x7ff00000
        /* dec 2146435072L */
#endif /*)*/

/* defines for NA */
#if (defined(IEEE) && defined(HAS_64BIT_LONG))
#define NA_PATTERN 0x7fffffff7fffffffL
#define NA_PATTERN64 0x7fffffff7fffffffL
#define NA_PATTERN32 0x7fffffffL
#elif (defined(IEEE) || defined(CONVEX)) /*(*/
#define NA_PATTERN 0x7ff00001
	/* dec 2146435073L */
#else /* vax )( */
#define NA_PATTERN 0x40000001
	/* dec 1073741825L */
#endif /* ) */


/* Define a type VOID_P which is void * for those machines whose
   compiler allows it, and char * for others (like mips).
   */
   
#if defined(IRIS4D) || defined(DECSTATION)
typedef char *	VOID_P;
#else
typedef void *	VOID_P;
#endif

/* Define a "signed char" type. For many (most?) compilers, this is what a
   normal "char" is. For some, you have to say "signed char", but that
   doesn't compile on the former set of compilers.
 */
#if (defined(SUNOS) || defined(HPPA) || defined(APOLLO)) && !defined(S_ANSI_Syntax)
typedef char SIGNED_CHAR;
#else
typedef signed char SIGNED_CHAR;
#endif

/* Define "VOLATILE".  The volatile type is only available with ANSI C */
#if defined(S_ANSI_Syntax)
#define VOLATILE volatile
#else
#define VOLATILE
#endif

/* typedef for the return value of signal handlers */

#if defined(VAX)
typedef int S_sig ;
#define S_SIG_DEFINED
#endif

/* void is the default type; see S.h after July/91 tape. */
/* True on these so far:  HP300, HP800, SUN386I, APOLLO, SUNOS4_SPARC, IRIS4D */
/* SAB 10/23/91 ...and DECSTATION, and SUN3(SunOS 4.1.1). */

#if defined(S_ANSI_Syntax) || defined(HPUX) || defined(IRIS4D) || defined(ULTRIX) || defined(IBMRS6000) || defined(OSF1_DECALPHA)
typedef void *  S_malloc_t;
#else
typedef char *  S_malloc_t;
#endif
typedef S_malloc_t malloc_t;
/* AT&T typedef a malloc_t for all platforms and thus it may be used in code. */
/* We already had S_malloc_t. -ps */

#if defined(S_ANSI_Syntax) || defined(IBMRS6000)
typedef size_t malloc_len;
#else
typedef unsigned malloc_len;
#endif

/* the mapping from f77 to C intermediate code -- may be machine dependent
 * the first definition satisfies lint's narrowminded preprocessing & should
 * stay the same for all implementations.  The S_ANSI_Syntax definition is for
 * ANSI standard conforming C compilers. The #else definition should
 * generate the version of the fortran subroutine & common block names x
 * handed to the local loader; e.g., "x_" in system V, Berkeley & 9th edition
 */

#ifdef lint /*(*/
#define F77_SUB(x) x
#define F77_COM(x) x
#else /*) lint (*/

#if defined(S_ANSI_Syntax) /*(*/
#if defined(F77_TRAILING_UNDERSCORE) /*(*/
#if defined(CONVEX) /*(*/
#define F77_SUB(x) x##_
#define F77_COM(x) _##x##_
#else /*) ! CONVEX (*/
#define F77_SUB(x) x##_
#define F77_COM(x) x##_
#endif /*) CONVEX */
#else /*) F77 TRAILING UNDERSCORE (*/
#if defined(DOS386) /*(*/
#define F77_SUB(x) fortran x
#define F77_COM(x) x
#else /*)(*/
#define F77_SUB(x) x
#define F77_COM(x) x
#endif /*)*/
#endif /*) F77 TRAILING UNDERSCORE */
#else /*) S_ANSI_Syntax (*/
#if defined(F77_TRAILING_UNDERSCORE) /*(*/
#if defined(CONVEX) /*(*/
#define F77_SUB(x) x/**/_
#define F77_COM(x) _/**/x/**/_
#else /*) CONVEX (*/
#define F77_SUB(x) x/**/_
#define F77_COM(x) x/**/_
#endif /*)*/
#else /*) F77 TRAILING UNDERSCORE (*/
#define F77_SUB(x) x
#define F77_COM(x) x
#endif /*) F77 TRAILING UNDERSCORE */
#endif /*) S_ANSI_Syntax */
#endif /*) lint */

/*
	The following are needed to allow distinctions to be made between the
	declaration, definition and invocation/usage of a Fortran common block
	or Fortran subroutine (coded in either C or Fortran):

	F77_NAME    - declaration of a Fortran subroutine.
	F77_SUB     - definition of a Fortran subroutine.
	F77_CALL    - invocation of a Fortran subroutine.
	F77_COMDECL - declaration of a Fortran common block.
	F77_COM     - usage of a Fortran common block.
*/

#if defined(DOS386) /*(*/
#define F77_NAME(x)    fortran x
#define F77_CALL(x)    x
#define F77_COMDECL(x) fortran x
#else /*)(*/
#define F77_NAME(x)    F77_SUB(x)
#define F77_CALL(x)    F77_SUB(x)
#define F77_COMDECL(x) F77_COM(x)
#endif /*)*/

/* Defines to handle generation of internal names for C and Fortran
 * on many machines, these symbols are have a leading underscore
 * but on some, particularly System V, they do not
 */
#if defined(C_LEADING_UNDERSCORE) /*(*/
#if defined(S_ANSI_Syntax) /*(*/
#define SYMBOL(x)       QUOTE(_##x)
#else /*) STDC (*/
#define SYMBOL(x)       QUOTE(_/**/x)
#endif /*) STDC*/
#else /*)(*/
#if defined(DOS386) /*(*/
#define SYMBOL(x)	QUOTE(x##_)
#else /*)(*/
#define SYMBOL(x)       QUOTE(x)
#endif /*)*/
#endif /*)*/


#if defined(S_ANSI_Syntax) /*(*/

#if defined(F77_TRAILING_UNDERSCORE) /*(*/
#if defined(F77_LEADING_UNDERSCORE) /*(*/
#define FSYMBOL(x)      QUOTE(_##x##_)
#else /*)(*/
#define FSYMBOL(x)      QUOTE(x##_)
#endif/*)*/
#else /*)(*/
#if defined(F77_LEADING_UNDERSCORE) /*(*/
#define FSYMBOL(x)      QUOTE(_##x)
#else /*)(*/
#define FSYMBOL(x)      QUOTE(x)
#endif/*)*/
#endif /*)*/

#else /*) ! STDC (*/

#if defined(F77_TRAILING_UNDERSCORE) /*(*/
#if defined(F77_LEADING_UNDERSCORE) /*(*/
#define FSYMBOL(x)      QUOTE(_/**/x/**/_)
#else /*) LEADING (*/
#define FSYMBOL(x)      QUOTE(x/**/_)
#endif/*) LEADING */
#else /*) TRAILING (*/
#if defined(F77_LEADING_UNDERSCORE) /*(*/
#define FSYMBOL(x)      QUOTE(_/**/x)
#else /*) LEADING(*/
#define FSYMBOL(x)      QUOTE(x)
#endif/*) LEADING*/
#endif /*) TRIALING*/

#endif /*) STDC */

#if defined(S_ANSI_Syntax) /*(*/
#define QUOTE(x)	#x
#else /*) STDC (*/
#define QUOTE(x)	"x"
#endif /*)*/

/* Typedef and define to handle conversion of character variables between
 * Fortran and C
 */

#if defined(U3B2) /*(*/
/* for the XLA+ fortran compiler -- needs special handling of characters
passed between fortran and C */
typedef struct { char *string; long  length; } F_charstruct;
#define F_CHARSTRUCT F_charstruct
#define F_CHARLEN(x) ((x)->length)
typedef struct { char *string; long  length; } * F_CHARTYPE;
#define F_CHARP(x)      ((x)->string)   /* convert F_CHARTYPE to a pointer to
                                         * the real string */
#else /*)(*/
#if defined(DOS386) /*(*/
typedef struct {char *string; unsigned length;} F_CHARDESCR;
typedef F_CHARDESCR *F_CHARTYPE;
#define F_CHARP(x)	((x)->string)
#else /*)(*/
typedef char *F_CHARTYPE;	/* how C sees F77 character variables */
#define F_CHARP(x)	(x)	/* how to convert F_CHARTYPE to a pointer to
				 * the real string */
#endif /*)*/
#endif /*)*/

/* max file name length - dataset names truncated to this size*/

#if !defined(DOS386) /*(*/
#if defined(HP300) || defined(U3B2) || defined(UNIX386) /*(*/
#define MAX_FILE_NAME_LEN 14
#else /*)(*/
#define MAX_FILE_NAME_LEN 255
#endif /*)*/
#define IS_DELIM(x) ((x) == '/')
#else /*)(*/
/* defines for DOS file name checking */
#if !defined(_MAX_PATH) /*(*/
#include <stdlib.h>
#endif /*)*/
#define DOS_MAX_PATH_LEN (_MAX_PATH-1)
#define DOS_MAX_DIR (DOS_MAX_PATH_LEN-DOS_MAX_NAME-1)
#define DOS_MAX_BASE 8
#define DOS_MAX_EXT 3
#define DOS_MAX_NAME (DOS_MAX_BASE+1+DOS_MAX_EXT)
extern char dos_fchar[];		/* gives each char's validity in DOS filename */
#define IS_BDCHAR(x) ((x) >= 128 || dos_fchar[x] == 0)
#define IS_BDCASE(x) ((x) < 128 && dos_fchar[x] == 1)
#define IS_OKCHAR(x) ((x) < 128 && dos_fchar[x] == 2)
#include "dos_util.h"
#endif /*)*/

/* UNIX/DOS C library differences */

#if defined(DOS386) /*(*/
#define link rename
#define kill(x,y) raise(y)
#else /*)(*/
#define Binopen fopen
#endif /*)*/

/*
 * The following is for the Setjmp in eval.c:do_S(), which for Windows (see
 * $INC/dos/setjmp.h) allows for a "chained" recover, since errors can occur
 * during a callback by Windows (the return path must be traversed to allow
 * clean-up of 32 bit <=> 16 bit conversions).
 */

#if !defined(WIN386) /*(*/
#define Setjmp setjmp
#endif /*)*/

/* I wasn't sure where these should go, they were in the old cdefs.h */

#define PIPESIZE 4096

/* chars per word, bits per char*/

#define NCPW (sizeof(long)/sizeof(char))

/* There are source-level routine names like coevec in both C and Fortran
source files, and this would cause confusion at link time on platforms
like HP-300 where the compilers don't add leading/trailing underscores to
distinguish.  We used to make these C name changes directly in the source;
now we leave things as they are in AT&T source, and map via cpp. */

#define coevec	coe_vec
#define coeves	coe_ves
#define seedin	seed_in
#define seedout	seed_out
#define nprime	n_prime

/* DOS vs Unix filename restriction defines, 2nd arg of define is in cdefs.h: */
#define FUNS_DIR	FunctionsDir
#define DSETS_DIR	DatasetsDir
#define HELP_DIR	HelpDir
#define DATA_DIR	DataDir
#define AUDIT_FILE	AuditFile

/* Define an lgamma to return log-gamma, for those platforms which don't
   have one yet. $QPE/random.c expects there to be an lgamma. */

#if defined(ULTRIX) || defined(UNIX386) || defined(DOS386) /*(*/
#define lgamma gamma
/* Do it this way and not #define lgamma(x) gamma(x) so decl'ns work too. */
#define S_LGAMMA_MAPPED_TO_GAMMA
#endif /*)*/

#endif /* !_S_SYSTEM_H_ )*/
