/*
 * GTools C compiler
 * =================
 * source file :
 * C
 *
 * Copyright 2001-2004 Paul Froissart.
 * Credits to Christoph van Wuellen and Matthew Brandt.
 * All commercial rights reserved.
 *
 * This compiler may be redistributed as long there is no
 * commercial interest. The compiler must not be redistributed
 * without its full sources. This notice must stay intact.
 */

#ifndef C_H
#define C_H
#ifdef PC
	#ifdef SHORT_INT
	#undef int
	#endif
	#include <stddef.h>
	//#include <times.h>
	#include <stdio.h>
	#ifdef SHORT_INT
	#define int short
	#endif
#else
	#include "define.h"
#endif
//#warning hey hey!
#include "error.h"

#ifdef CPU_DEFINED
#undef CPU_DEFINED
#endif

#ifdef MC68000
#define MC680X0
#ifdef CPU_DEFINED
error, define only one target CPU!
#endif
#define CPU_DEFINED
#define LIST_NAME  "gtclist.txt"
#define ICODE_NAME "gtcicode.txt"
#endif

#ifdef MC68010
#define MC680X0
#ifdef CPU_DEFINED
error, define only one target CPU!
#endif
#define CPU_DEFINED
#define LIST_NAME  "gtclist.txt"
#define ICODE_NAME "gtcicode.txt"
#endif

#ifdef MC68020
#define MC680X0
#ifdef CPU_DEFINED
error, define only one target CPU!
#endif
#define CPU_DEFINED
#define LIST_NAME  "gtclist.txt"
#define ICODE_NAME "gtcicode.txt"
#endif

#ifdef MC68030
#define MC680X0
#ifdef CPU_DEFINED
error, define only one target CPU!
#endif
#define CPU_DEFINED
#define LIST_NAME  "gtclist.txt"
#define ICODE_NAME "gtcicode.txt"
#endif

#ifdef MC68040
#define MC680X0
#ifdef CPU_DEFINED
error, define only one target CPU!
#endif
#define CPU_DEFINED
#define LIST_NAME  "gtclist.txt"
#define ICODE_NAME "gtcicode.txt"
#endif

#ifdef	INTEL_486
#ifndef INTEL_386
#define INTEL_386
#endif
#endif

#ifdef INTEL_386
#ifdef CPU_DEFINED
#error define only one target CPU!
#endif
#define CPU_DEFINED
#define LIST_NAME  "c386.list"
#define ICODE_NAME "c386.icode"
/*
 * if FUNCS_USE_387 is defined, extra library calls are generated if the
 * nofpu option is in effect that allows to use code generated by
 * this compiler to be linked with functions that return values
 * on the 387 stack
 */
#define FUNCS_USE_387
#endif

#ifndef CPU_DEFINED
#error target CPU type must be defined
#endif

/* the tokens returned from lexical analysis */

/* assumptions about the order :
 *  none currently (beware of is_lang_ext though) */
enum e_sym {
	// 0x00
	cconst, iconst, lconst, uconst, ulconst, sconst, rconst, plus, minus,
	// 0x09
	divide, lshift, rshift, modop, eq, neq, lt, leq, gt,
	// 0x12
	geq, assign, asplus, asminus, astimes, asdivide, asmodop,
	asuparrow,
	// 0x1A
	aslshift, asrshift, asand, asor, autoinc, autodec, hook, compl,
	// 0x22
	comma, colon, semicolon, uparrow, openbr, closebr, begin, end,
	// 0x2A
	closepa, pointsto, dot, lor, land, not, or, and,
	// 0x32
	star, openpa, id, kw_int, kw_char, kw_short, kw_long,
	kw_void, kw_float, kw_double, kw_struct, kw_union,
	kw_enum, kw_unsigned, kw_signed, kw_auto, kw_extern,
	kw_const, kw_volatile,
	// 0x45
	kw_register, kw_typedef, kw_static, kw_goto, kw_return,
	kw_sizeof, kw_break, kw_continue, kw_if, kw_else, kw_for,
	kw_do, kw_while, kw_switch, kw_case, kw_default,
	// 0x55
	eof,
	// ANSI extensions
	kw_typeof, dots, kw_alloca,
	// GTC extensions
	kw_loop, kw_until, kw_count, kw_eval,	// (lang extensions)
	kw_defined, kw_incbin, kw_softcast, kw_c,
	// GNU C extensions
	kw_asm, kwb_constant_p, kw_attr,
	// ASM keywords
	kw_dreg, kw_areg, sharp,
#ifdef OLD_AMODE_INPUT
	kw_offs_end,
#endif
	kw_instr,
};
#define is_lang_ext(__st) (__st>=kw_loop && __st<=kw_eval)

/* storage classes */

enum e_sc {
	sc_static, sc_auto, sc_global, sc_external, sc_type, sc_const,
	sc_member, sc_label, sc_ulabel, sc_typedef, sc_parms, sc_parms2,
	sc_define, sc_vamac
};

/* basic data types */

#ifndef BCDFLT
#define bt_size(__x) ((__x)<bt_long?((__x)<bt_short?1:2):4)
#define float_size 4
#else
#ifdef DOUBLE
#define bt_size(__x) ((__x)<bt_long?((__x)<bt_short?1:2):((__x)==bt_double?10:4))
#define float_size !!! CAUTION, VARIES BETWEEN DOUBLE AND FLOAT !!!
#else
#define bt_size(__x) ((__x)<bt_long?((__x)<bt_short?1:2):((__x)==bt_float?10:4))
#define float_size 10
#endif
#endif
#define bt_uns(__x) ((__x)&1)
#define bt_integral(__x) ((__x)<=bt_ulong)
#ifndef DOUBLE
#define bt_bcd bt_float
#define bt_double bt_float
#define tp_double tp_float
#define bt_scalar(__x) ((__x)<=bt_double)
#else
#define bt_bcd bt_double
#endif
#ifdef NOBCDFLT
#undef bt_bcd
#endif
#define bt_comparable(__x) ((__x)<=bt_pointer)
#ifndef NOBCDFLT
#define bt_aggregate(__x) ((__x)==bt_bcd || (__x)>=bt_struct)
#else
#define bt_aggregate(__x) ((__x)>=bt_struct)
#endif
#define bt_uncastable(__x) ((__x)>=bt_struct)
#define iscomparable(tp) bt_comparable((tp)->type)
#define isscalar(tp) bt_scalar((tp)->type)
#define integral(tp) bt_integral((tp)->type)
#define isaggregate(tp) bt_aggregate((tp)->type)
enum e_bt {
	bt_char, bt_uchar, bt_short, bt_ushort,
	bt_long, bt_ulong, bt_float,
#ifdef DOUBLE
	bt_double,
#endif
	bt_pointer,
	bt_func,
	bt_void, bt_bitfield,
	bt_struct, bt_union,
};

/* these form the string literal pool */

struct slit {
	struct slit    *next;
	char		   *str;
	short			label;
	short			len;
};

/* a symbol table */
struct stab {
	int				hash;
	struct sym	   *head;
	struct sym	   *tail;
};
/* important points for reconsidering N_HASH value :
  - a HTABLE is about 8*N_HASH -byte long
  - each imbricated 'compound()' call takes the space of 2 HTABLEs on the stack
   (512 bytes with N_HASH=32, thus allowing only 20 imbricated compound stmts)
  - there are 6 static HTABLEs, 7 if AS is defined (but could be improved with malloc() / BSS)
  - N_HASH = 1 << HASH_LOG */
#define N_HASH 32
#define N_HASH_AND "31"
#define HASH_LOG 5
typedef struct hstab {
	int				hash;
	struct htab {
		struct sym	   *head;
		struct sym	   *tail;
	}				h[N_HASH];
} HTABLE;

/* structure defining a data type */

struct typ {
	struct stab 	lst;
	struct typ	   *btp;
#ifdef LISTING
	char		   *sname;
#endif
	long			size;
	enum(e_bt)		type;
/*
 * The following six chars may be unsigned -- no harm.
 * They could be ints without restriction -- this is to save memory
 */
	/*
	 * val_flag is normally 0, except for:
	 * - type==bt_pointer: set to 1 if it's an array, to 0 if it's a pointer
	 * - type==bt_func: always set to 1
	 *   (passing a function is like passing an array, we should actually be passing a pointer;
	 *   and like an array, we do not want cond_deref() to build an en_ref node)
	 * - type==bt_integral: set to 1 to indicate an enum (this feature is currently unused)
	 */
	char			val_flag;

	char			st_flag;	// is the type already stored globally?
	char			const_flag;	// is it a 'const' type?
	char			vol_flag;	// is it a 'volatile' type?
	char			bit_width;
	char			bit_offset;
};
#ifdef REGPARM
#define rp_dn bit_width
#define rp_an bit_offset
#endif

/* a symbol table entry */

struct sym {
	char		   *name;
	struct sym	   *prev;
	struct sym	   *next;
	struct typ	   *tp;
	union {
		long			i;
		unsigned long	u;
		int				splab;
		char		   *s;
	}				value;
	enum(e_sc)		storage_class;
	int 			used;	// note:
							// - for 'normal' symbols (C variables), this belongs to {-1,0,1}
							// - for preprocessor symbols, the lower 8 bits is the number of arguments to the macro
							//   and the higher 8 bits are described in enum(e_ppsymflags) below
};
enum e_ppsymflags {
	PPSYM_UNDER_EXPANSION = 0x8000,	// set if we are currently expanding this symbol (avoid recursive expansion)
#ifdef ASM
	PPSYM_ASM_KEYWORD = 0x4000,		// set if this an ASM reserved keyword ('move', 'b', 'w', 'l', 'd7', 'sp')
	PPSYM_DEFINED_IN_ASM = 0x2000,	// set if this symbol was defined inside an asm{} statement
#endif
};

#define SYM 	struct sym
#define TYP 	struct typ
#define TABLE	struct stab

#ifdef PC
#define MAX_ERROR_COUNT 1
#else
#define MAX_ERROR_COUNT 1
#endif
#define MAX_STRLEN		1500
#define MAX_ID_LEN		50
#ifdef OLD_MACRO
#define MAX_MAC_LEN 	800
#define LINE_LENGTH (1800+MAX_MAC_LEN+1)
#else
#define LINE_LENGTH (1800+1)
#endif
#define MAX_PARAMS		20
#define REG_LIST		20
#define AUTO_LIST		100

#define ERR_SYNTAX		0		/* general error */
#define ERR_ILLCHAR 	1		/* illegal character */
#define ERR_FPCON		2		/* illegal floating-point constant */
#define ERR_ILLTYPE 	3		/* illegal type */
#define ERR_UNDEFINED	4		/* undefined identifier */
#define ERR_FIELD		5		/* no field allowed here */
#define ERR_PUNCT		6		/* expected symbol not found */
#define ERR_IDEXPECT	7		/* identifier expected */
#define ERR_NOINIT		8		/* initialization invalid */
#define ERR_INCOMPLETE	9		/* incomplete struct/union/enum declaration */
#define ERR_ILLINIT 	10		/* illegal initialization */
#define ERR_INITSIZE	11		/* too many initializers */
#define ERR_ILLCLASS	12		/* illegal storage class */
#define ERR_BLOCK		13		/* function body expected */
#define ERR_NOPOINTER	14		/* pointer type expected */
#define ERR_NOFUNC		15		/* function type expected */
#define ERR_NOMEMBER	16		/* struct/union member expected */
#define ERR_LVALUE		17		/* l-value required */
#define ERR_DEREF		18		/* error dereferencing a pointer */
#define ERR_MISMATCH	19		/* type mismatch error */
#define ERR_EXPREXPECT	20		/* expression expected */
#define ERR_WHILEXPECT	21		/* 'while' expected in do-loop */
#define ERR_ENUMVAL 	22		/* enum value out of range */
#define ERR_DUPCASE 	23		/* duplicate case label */
#define ERR_LABEL		24		/* undefined label */
//#define ERR_PREPROC 	25		/* preprocessing error */
#define ERR_ARG 		26		/* declared Argument missing */
#define ERR_WIDTH		27		/* illegal field width */
#define ERR_INTEXPR 	28		/* illegal constant integer expression */
#define ERR_CAST		29		/* error doing a cast */
#define ERR_INTEGER 	30		/* integer-valued type expected */
#define ERR_CASTCON 	31		/* error casting a constant */
#define ERR_REDECL		32		/* illegal redeclaration */
//#define ERR_PARMS		33		/* error while scanning a parameter list */
#define ERR_FTYPE		34		/* bad host type for bit fields */
#define ERR_INCLFILE	35		/* #include: no include file specified */
#define ERR_CANTOPEN	36		/* can't open include file */
#define ERR_DEFINE		37		/* wrong #define */
#define ERR_CUSTOM		38		/* #error */
#define ERR_DUPSYM	 	39		/* duplicate symbol */
#define ERR_CONSTEXPECT	40		/* constant expression expected */
#define ERR_OUTRANGE 	41		/* value out of range */
#define ERR_TOOMPARAMS	42		/* too many parameters to function */
#define ERR_TOOFPARAMS	43		/* too few parameters to function */
#define ERR_CASERANGE 	44		/* invalid case range */
#define ERR_UNEXPECTEOF	45		/* unexpected end of file */
#define ERR_OTH			46		/* (custom error) */
#define ERR_SYS			47		/* (system limitation) */
#define ERRA_INVALIDREL 48		/* invalid relocation in expression */

/* alignment sizes */

#ifdef MC68000
/*
 * MC68000 is a 16-bit processor. Word alignment is OK in all cases
 */
#define AL_CHAR 		1
#define AL_SHORT		2
#define AL_LONG 		2
#define AL_POINTER		2
#define AL_FLOAT		2
#define AL_DOUBLE		2
#define AL_STRUCT		2
#define AL_FUNC 		2

#define AL_DEFAULT		2		/* alignment suitable for all types */
#endif /* MC68000 */

#ifdef MC68010
/*
 * MC68010 is a 16-bit processor. Word alignment is OK in all cases
 */
#define AL_CHAR 		1
#define AL_SHORT		2
#define AL_LONG 		2
#define AL_POINTER		2
#define AL_FLOAT		2
#define AL_DOUBLE		2
#define AL_STRUCT		2
#define AL_FUNC 		2

#define AL_DEFAULT		2		/* alignment suitable for all types */
#endif /* MC68010 */

#ifdef MC68020
/*
 * perhaps not necessary, but useful: 32-bit alignment for 32-bit types
 */
#define AL_CHAR 		1
#define AL_SHORT		2
#define AL_LONG 		4
#define AL_POINTER		4
#define AL_FLOAT		4
#define AL_DOUBLE		4
#define AL_STRUCT		4
#define AL_FUNC 		4

#define AL_DEFAULT		4		/* alignment suitable for all types */
#endif /* MC68020 */

#ifdef MC68030
/*
 * perhaps not necessary, but useful: 32-bit alignment for 32-bit types
 */
#define AL_CHAR 		1
#define AL_SHORT		2
#define AL_LONG 		4
#define AL_POINTER		4
#define AL_FLOAT		4
#define AL_DOUBLE		4
#define AL_STRUCT		4
#define AL_FUNC 		4

#define AL_DEFAULT		4		/* alignment suitable for all types */
#endif /* MC68030 */

#ifdef MC68040
/*
 * perhaps not necessary, but useful: 32-bit alignment for 32-bit types
 */
#define AL_CHAR 		1
#define AL_SHORT		2
#define AL_LONG 		4
#define AL_POINTER		4
#define AL_FLOAT		4
#define AL_DOUBLE		4
#define AL_STRUCT		4
#define AL_FUNC 		4

#define AL_DEFAULT		4		/* alignment suitable for all types */
#endif /* MC68040 */

#ifdef INTEL_386
/*
 * perhaps not necessary, but useful: 32-bit alignment for 32-bit types
 */
#define AL_CHAR 		1
#define AL_SHORT		2
#define AL_LONG 		4
#define AL_POINTER		4
#define AL_FLOAT		4
#define AL_DOUBLE		4
#define AL_STRUCT		4
#define AL_FUNC 		4

#define AL_DEFAULT		4		/* alignment suitable for all types */
#endif /* INTEL_386 */


#ifdef SPARC
#define AL_CHAR 		1
#define AL_SHORT		2
#define AL_LONG 		4
#define AL_POINTER		4
#define AL_FLOAT		4
#define AL_DOUBLE		8
#define AL_STRUCT		8
#define AL_FUNC 		4

#define AL_DEFAULT		8		/* alignment suitable for all types */
#endif /* SPARC */


int 		   *_xalloc(int);
struct sym	   *search();
struct sym	   *gsearch();
char		   *strsave();
TYP 		   *expression();
TYP 		   *exprnc();
TYP 		   *cast_op();
TYP 		   *mk_type();
long			intexpr();
int 			getch();
//void			error();
void			getsym();
void			needpunc();
void			initsym();
void			append();
long			strip_icon();
long			push_param();
void			do_warning(char *,...);

struct sym *symremove();
void getidstr();
void skipspace();
void msg(char *s);

void rel_local();
void rel_global();
void clean_up();

void out_init();
void out_close();
void do_compile();
void initpch();
void closepch();

void insert(SYM *sp,HTABLE *table);

#ifdef DUAL_STACK
extern void *dualstack;
extern void *ds_currentlo,*ds_currenthi;
void ds_allocatleast(unsigned int size);
void ds_free(void);
#define ds_remaining (unsigned int)((char *)ds_currenthi-(char *)dualstack)
#define ds_ensure(size) ((ds_remaining>=(size) ? 0 : ds_allocatleast(size),0), dualstack)
#define ds_pop(target) (void)((target)!=ds_currentlo ? (dualstack = (target)) : ds_free(),0)
#ifdef PC
#define ds_update(ptr) (void)(dualstack=(ptr),dualstack+=(-(size_t)dualstack)&3,0)
#else
#define ds_update(ptr) (void)(dualstack=(ptr),1&(short)(long)dualstack ? ++dualstack,0 : 0,0)
#endif
#define ds_var(type) (type)dualstack
#define DS_BSIZE 6000 // we set aside 6 kb for each stack block
#endif
#endif
// vim:ts=4:sw=4
