/*
 * star.h - STAR 1.04.4 header file
 *
 */

#if !defined(MSDOS) && !defined(VMS)

/* #define SYSV */		/* System V (AT&T, Interactive, etc) */
#define BSD			/* BSD or SunOS */

/* #define AMIGA */		/* AmigaDOS and Lattice C */

#define FILE_CASE_SIG		/* Define if file names are case
				   significant, i.e. UNIX flavored */
#endif

/* #define NONDOS_FILETYPES */	/* Define to override standard MS-DOS
				   file types with Unix/Amiga/VMS
				   file types */

#ifdef VMS
#define VMS_FILENAMES
#endif

#ifdef MSDOS
#define MSDOS_FILENAMES
#endif

#ifdef AMIGA
#define SYSV
#endif

#ifdef __TURBOC__
#define USE_STDARG
#endif

#if defined(MSDOS_FILENAMES) || defined(VMS_FILENAMES)

#ifdef MSDOS_FILENAMES
#define FILE_SUBDIR '\\'	/* Subdirectory delimiter (MS-DOS) */
#else
#define FILE_SUBDIR '>'		/* Subdirectory delimiter (VAX/VMS) */
#endif

#define CODE_FILETYPE ".BIN"	/* Default file type for code */

#if defined(VMS_FILENAMES)
#define SOURCE_FILETYPE ".STAR"	/* Default file type for VMS sources */
#define LIST_FILETYPE ".LIS"	/* Default file type for VMS listing */
#else

#ifdef NONDOS_FILETYPES
#define SOURCE_FILETYPE ".STA"	/* Unix-compatible src file type for MS-DOS */
#define LIST_FILETYPE ".LIS"	/* Unix-compatible list file type for MS-DOS */

#else

#define SOURCE_FILETYPE ".STR"	/* Default file type for MS-DOS sources */
#define LIST_FILETYPE ".LST"	/* Default file type for MS-DOS listing */
#endif
#endif


#else /* I.e. unixen */

#define FILE_SUBDIR '/'		/* Subdirectory delimiter (UNIX) */
#define SOURCE_FILETYPE ".star"	/* Default file type for sources */
#define LIST_FILETYPE ".list"	/* Default file type for listing */
#define CODE_FILETYPE ""	/* Default file type for code */

#define UNIX_ERRORS		/* Unix flavored error messages */

#endif

#define SRCMAX	32		/* Maximum number of source files */



/* Mask used to mask out a short value */
#define SHORT_MASK ((1<<(sizeof(short)*8))-1)

#define MAXSRC	SRCMAX

#ifndef TRUE
#define FALSE 0
#define TRUE (!FALSE)
#endif

#ifdef SYSV
#define UNIX
#define bcopy(S,D,N) memcpy(D,S,N)
#define bclear(D,N) memset(D,'\0',N)
#define bcmp(S1,S2,N)  memcmp(S1,S2,N)
#else

#ifdef BSD
#define UNIX
#define bclear bzero
#else

#ifdef MSDOS
#define bcopy(S,D,N) memcpy(D,S,N)
#define bclear(D,N) memset(D,'\0',N)
#define bcmp(S1,S2,N) memcmp(S1,S2,N)

#define inp __inp		/* Resolve MSC name conflict */

#define BINARY_OPEN_FLAG "wb"
#else

#ifdef VMS
#define bcopy(S,D,N) memcpy(D,S,N)
#define bclear(D,N) memset(D,'\0',N)
#define bcmp(S1,S2,N) memcmp(S1,S2,N)

#else

#define bcopy block_copy
#define bclear block_clear
#define bcmp block_compare

#endif /* !VMS */
#endif /* !MSDOS */
#endif /* !BSD */
#endif /* !SYSV */


#ifndef BINARY_OPEN_FLAG
#define BINARY_OPEN_FLAG "w"
#endif


/* Exit codes */
#ifdef VMS
#define EXIT_SUCC  0x10000001	/* Successful completion */
#define EXIT_ERROR 0x10000004	/* Failure */
#endif

#if defined(MSDOS) || defined(UNIX)
#define EXIT_SUCC  0
#define EXIT_ERROR 1
#endif


/* ISO 8859-1 character conversions and classification.
 * The actualy character class table can be found in star.c
 */
extern unsigned char
  upper_table[], cclass_table[];

#define toupper(C)  \
  upper_table[(unsigned char) C]

#define CCLASS_DIGIT	001	/* Character is digit */
#define CCLASS_SYM	002	/* Character is valid in symbol names */
#define CCLASS_ISYM	0004	/* Character is valid as first symbol char */
#define CCLASS_EOE	0010	/* Character terminates expression */
#define CCLASS_EXPR	0020	/* Character is component of expression */
#define CCLASS_HEX	0040	/* Character is hex digit */
#define CCLASS_OCT	0100	/* Character is octal digit */
#define CCLASS_BLANK	0200	/* Character is whitespace */

#define CCLASS(C,BITS) \
  (cclass_table[(unsigned char) C] & (BITS))

#define isisym(C)  CCLASS(C, CCLASS_ISYM)
#define issym(C)   CCLASS(C, CCLASS_SYM|CCLASS_ISYM)
#define isdigit(C) CCLASS(C, CCLASS_DIGIT)
#define ishex(C)   CCLASS(C, CCLASS_HEX)
#define isoct(C)   CCLASS(C, CCLASS_OCT)
#define isexpr(C)  CCLASS(C, CCLASS_EXPR)
#define isblank(C) CCLASS(C, CCLASS_BLANK)
#define eoe(CP)    \
  (!(CP) || CCLASS(*(CP), CCLASS_EOE))


/* Digit to hex character */
#define hex1(I)  \
  ("0123456789abcdef"[(I) & 0xf])


/* The following define returns the base 10 exponent of a double, as
 * an integral double.
 */
#if defined(UNIX) || defined(VMS)
#define EXPONENT(X) \
  ((X) == 0.0 ? 0.0 : floor(log10((X) >= 0 ? (X) : -(X))))
#endif

#ifdef MSDOS
#define EXPONENT(X) \
  ((X) == 0.0 ? 0.0 : floor(log10((X) >= 0 ? (X) : -(X))))
#endif


/* Skip spaces */
#ifdef __GNUC__
#define byspace(CP) \
({  register char *s; \
     if(s = (char *) (CP)) for(; isblank(*s); s++); \
    s; })
#else
extern char
  *byspace(char *);
#endif


/* List of ANSI/POSIX double-double functions.
 * These defines form indices into the dispatch table in
 * eval.c (ftable[])
 */
#define DF_ACOS 0
#define DF_ASIN 1
#define DF_ATAN 2
#define DF_CEIL 3
#define DF_COS 4
#define DF_COSH 5
#define DF_EXP 6
#define DF_FABS 7
#define DF_FLOOR 8
#define DF_FMOD 9
#define DF_LOG 10
#define DF_LOG10 11
#define DF_SIN 12
#define DF_SINH 13
#define DF_SQRT 14
#define DF_TAN 15
#define DF_TANH 16

#define DF_NFUNS 17		/* # of functions */

/* Instruction descriptor */
struct istruct {
  char	*name;			/* Instruction name */
  void	(*scandef)();		/* Code */
  int
    length,			/* Data length etc */
    opcode;			/* Instruction-dependent opcode	*/
};


/* Macro definition */

/* Macro argument */
struct marg {
  struct sstruct
    *argsym;			/* Argument symbol */

  char
    *def;			/* Default value, NULL if none */
};
  

/* Macro as value */
struct macro {
  int
    nargs,			/* # of arguments */
    nlines;			/* # of lines */

  struct marg
    *args;			/* Arguments */

  struct sstruct
    *label;			/* Label symbol */

  char
    *lines[1];			/* Macro lines */
};


/* Sections can be values, but we don't want to include sect.h 
 * in every file that includes star.h. Instead, we make a dummy
 * define here.
 */
#ifndef _SECT_DEF_
#define STRUCT_SECT void
#else
#define STRUCT_SECT struct sect
#endif

/* Value holder */

#ifdef __GNUC__
#define INT long long
#define REAL /* long */ double
#else
#define INT long
#define REAL double
#endif

struct val {
  short type;			/* Type, VT_xxx */
  union {
    char *str;			/* Value as string */
    INT l;			/* Value as integer */
    REAL d;			/* Value as real */
    struct macro *m;		/* Value as macro */
    STRUCT_SECT *sect;		/* Value as section */
    struct fstruct *f;		/* Value as op */
  } v;
};

#define VT_INT 1		/* Integer value (long) */
#define VT_STR 2		/* String value (char *) */
#define VT_MAC 3		/* Macro value (struct macro *) */
#define VT_REAL 4		/* Real value (double) */
#define VT_SECT 5		/* Section value (struct sect *) */
#define VT_OP 6			/* Operator (no numerical usage) */

#define vstr v.str
#define vint v.l
#define vdouble v.d
#define vmacro v.m
#define vsect v.sect
#define vop v.f


/* Word sizes */
#define BPC		8	/* Bits per char */
#define BPINT		(BPC*sizeof(INT)) /* Bits per INT */
#define MAXSUFFIX	(BPINT>>2) /* Largest possible suffix */


/* Absolute value */
#ifdef __GNUC__
#define ABSL(L) ({typeof (L) _L = (L); _L >= 0 ? _L : -_L; })
#else
#define ABSL abs_l
#endif

/* Int to INT value */
#ifdef __GNUC__
#define intval(I) \
  ({struct val _V; _V.type = VT_INT; _V.vint = (I); _V;})
#else
extern struct val
  intval(INT);
#endif

/* Double to REAL value */
#ifdef __GNUC__
#define realval(D) \
  ({struct val _V; _V.type = VT_REAL; _V.vdouble = (D); _V;})
#else
extern struct val
  realval(REAL);
#endif


/* Argument descriptor */
struct astruct	{
  int
    pres,			/* Presence bits P_xxx */
    type,			/* Type	T_xxx */
    reg;			/* Register R_xxx */
  
  INT
    disp1;			/* General value holder */
};

/* Argument types */
#define	T_REG	1		/* reg */
#define T_IMM	2		/* #imm */
#define T_IND	3		/* @Dreg */
#define T_ID    4		/* ID */
#define T_CN	5		/* C.n (0 <= n <= 15), disp1 = n */
#define T_PPLUS1 6		/* P+1 */
#define T_HST	7		/* HST */
#define T_INDAC 010		/* @A or @C */

/* Presence bits (currently not used in STAR) */

/* Registers */
#define R_D0	0
#define R_D1	1
#define R_A	2
#define R_B	3
#define R_C	4
#define R_D	5
#define R_R0	6
#define R_R1	7
#define	R_R2	8
#define R_R3	9
#define R_R4	10
#define R_PC	11
#define R_ST	12
#define R_P	13

/* Field sizes */
#define F_P	0		/* .p */
#define F_WP	1		/* .wp */
#define F_XS	2		/* .xs */
#define F_X	3		/* .x */
#define F_S	4		/* .s */
#define F_M	5		/* .m */
#define F_B	6		/* .b */
#define F_W	7		/* .w */
#define F_A	010		/* .a */
#define F_PN	0100		/* .Pn (1 <= n <= 16), value = 0100+n */
#define F_N	0200		/* .n (1 <= n <= 16), value = 0200+n */
#define F_DEFLT 0400		/* Used to avoid errors */

#define FT_NONE  0000		/* No field at all */
#define FT_FIX  010000		/* Fixed field acceptable */
#define FT_PN	020000		/* .Pn field acceptable */
#define FT_N	040000		/* .N field acceptable */
#define FT_DEFLT 0100000	/* No field acceptable, use default */

/* Argument type patterns */
#define AP_PMASK 077		/* Pattern data mask */
#define AP_REG	0000		/* Register R_xxx: AP_REG | R_xxx */
#define AP_RABCD 0100		/* Register A,B,C, or D */
#define AP_D01  0200		/* Register D0 or D1 */
#define AP_TYPE 0300		/* Type T_xxx: AP_TYPE | T_xxx */
#define AP_ID01 0400		/* @D0 or @D1 */
#define AP_RN   0500		/* Register R0, R1, R2, R3, or R4 */
#define AP_RAC  0600		/* Register A or C */


/* Function definition */
struct fstruct
{
  char	*name;			/* Function identifier */
  int	type;			/* Function type (see below) */
  struct val
    (*feval)();			/* Function evaluator */
  int	auxval;			/* Function-dependent */
};

#define	OPX	1		/* op x */
#define XOPY	2		/* x op y */
#define F_FAST	4		/* Fast evaluation */
#define REG	8		/* Actually register */


/* Some common functions and variables */
extern struct val
  evexpr(), evdec(), evhex(), evoct(), evbin(), evreal(), ev1arg(),
  toint(struct val), tostr(struct val), toreal(struct val),
  solidify(struct val), localize(struct val), val_zero, val_one,
  val_nullstr;

extern
  pass, codeblock;

extern long
  loc, loc0;

extern void
  assert_imm_range(struct astruct *, INT, unsigned INT),
  assert_range(INT, INT, unsigned INT),

#if defined(__TURBOC__)
  fatal(char *, ...), sgnerr(char *, ...), sgnwrn(char *, ...),
#else
  fatal(), sgnerr(), sgnwrn(),
#endif

  expr_gc(), decode_args(), decode_suffix(),
  coden(int, INT), code1(unsigned), code2(unsigned), code3(unsigned),
  code4(unsigned), code5(unsigned long);

extern char
  *expand_symbols(char *);
