typedef uchar		BYTE;		/* 8  bits */
typedef int		WORD;		/* 32 bits */
typedef unsigned int	UWORD;		/* 32 bits */
typedef vlong		LONG;		/* 64 bits */
typedef uvlong		ULONG;		/* 64 bits */
typedef double		REAL;		/* 64 double IEEE754 */
typedef short		SHORT;		/* 16 bits */
typedef float		SREAL;		/* 32 float IEEE754 */

enum
{
	Palt,				/* blocked in alt instruction */
	Psend,				/* waiting to send */
	Precv,				/* waiting to recv */
	Pdebug,				/* debugged */
	Pready,				/* ready to be scheduled */
	Prelease,			/* interpreter released */
	Pexiting,			/* exit because of kill or error */
	Pbroken,			/* thread crashed */

	PRNSIZE	= 1024,
	BIHASH	= 23,

	MODNAMEMAX = 28,
};

typedef struct Alt	Alt;
typedef struct Channel	Channel;
typedef struct Inst	Inst;
typedef struct Module	Module;
typedef struct Modlink	Modlink;
typedef struct Modl	Modl;
typedef struct Prog	Prog;
typedef struct Link	Link;
typedef struct List	List;
typedef struct Array	Array;
typedef struct String	String;
typedef union  Linkpc	Linkpc;
typedef struct REG	REG;
typedef struct Frame	Frame;
typedef union  Stkext	Stkext;
typedef struct Altc	Altc;
typedef struct Exception Exception;

struct Frame
{
	Inst*		lr;	/* REGLINK isa.h */
	uchar*		fp;	/* REGFP */
	Modlink*	mr;	/* REGMOD */
	Type*		t;	/* REGTYPE */
};

union Stkext
{
	uchar	stack[1];
	struct {
		Type*	TR;
		uchar*	SP;
		uchar*	TS;
		uchar*	EX;
		union {
			uchar	fu[1];
			Frame	fr[1];
		} tos;
	} reg;
};

struct Array
{
	WORD	len;
	Type*	t;
	Array*	root;
	uchar*	data;
};

struct List
{
	List*	tail;
	Type*	t;
	WORD	data[STRUCTALIGN];
};

struct Channel
{
	Prog*	send;		/* Queue of progs ready to send */
	Prog*	sendalt;	/* Single prog waiting to send in ALT */
	Prog*	recv;		/* Queue of progs ready to receive */
	Prog*	recvalt;	/* Single prog waiting to receive in ALT */
	void*	aux;		/* Rock for devsrv */
	void	(*mover)(void);	/* Data mover */
	union {
		WORD	w;
		Type*	t;
	} mid;
};

struct String
{
	int	len;		/* / length */
	int	max;		/* maximum length in representation */
	char*	tmp;
	union {
	#define	Sascii	data.ascii
	#define Srune	data.runes
		char	ascii[STRUCTALIGN];
		Rune	runes[1];
	}data;	
};

union Linkpc
{
	void	(*runt)(void*);
	Inst*	pc;
};

struct Link
{
	Link*	next;
	int	sig;
	Type*	frame;
	Linkpc	u;
	char	name[STRUCTALIGN];
};

typedef union	Adr	Adr;
union Adr
{
	WORD	imm;
	WORD	ind;
	Inst*	ins;
	struct {
		ushort	f;	/* First indirection */	
		ushort	s;	/* Second indirection */
	} i;
};

struct Inst
{
	uchar	op;
	uchar	add;
	ushort	reg;
	Adr	s;
	Adr	d;
};

struct Altc
{
	Channel*	c;
	void*		ptr;
};

struct Alt
{
	int	nsend;
	int	nrecv;
	Altc	ac[1];
};

struct REG
{
	Inst*		PC;		/* Program counter */
	uchar*		MP;		/* Module data */
	uchar*		FP;		/* Frame pointer */
	uchar*		SP;		/* Stack pointer */
	uchar*		TS;		/* Top of allocated stack */
	uchar*		EX;		/* Extent register */
	Modlink*	M;		/* Module */
	int		IC;		/* Instruction count for this quanta */
	Inst*		xpc;		/* Saved program counter */
	void*		s;		/* Source */
	void*		d;		/* Destination */
	void*		m;		/* Middle */
	WORD		t;		/* Middle temporary */
	WORD		st;		/* Source temporary */
	WORD		dt;		/* Destination temporary */
};

struct Prog
{
	REG		R;		/* Register set */
	Prog*		link;		/* Run queue */
	Prog*		comm;		/* Communication queue */
	void*		ptr;		/* Channel data pointer */
	Channel*	chan;		/* Channel pointer */
	int		state;		/* Scheduler state */
	char*		kill;		/* Set if prog should error */
	int		killer;		/* Who murdered me */
	int		pid;		/* unique Prog id */
	int		grp;		/* group id */
	int		quanta;		/* time slice */
	Prog*		prev;
	Prog*		next;
	Exception*	exsp;
	Exception*	exhdlr;
	ulong		ticks;
	void		(*addrun)(Prog*);
	void		(*xec)(Prog*);

	void*		osenv;
};

struct Module
{
	int	ref;		/* Use count */
	int	compiled;	/* Compiled into native assembler */
	ulong	ss;		/* Stack size */
	ulong	rt;		/* Runtime flags */
	ulong	mtime;		/* Modtime of dis file */
	int	nprog;		/* number of instructions */
	Inst*	prog;		/* text segment */
	uchar*	origmp;		/* unpolluted Module data */
	int	ntype;		/* Number of type descriptors */
	Type**	type;		/* Type descriptors */
	Inst*	entry;		/* Entry PC */
	Type*	entryt;		/* Entry frame */
	Inst*	eclr;		/* Code compiled to clear exceptions */
	char	name[MODNAMEMAX];	/* Implements type */
	char*	path;		/* File module loaded from */
	Module*	link;		/* Links */
	Link*	ext;		/* External dynamic links */
	ulong*	pcmap;		/* Map from PC to offset into compiled code */
};

struct Modl
{
	Linkpc	u;		/* PC of Dynamic link */
	Type*	frame;		/* Frame type for this entry */
};

struct Modlink
{
	uchar*	MP;		/* Module data for this instance */
	Module*	m;		/* The real module */
	int	compiled;	/* Compiled into native assembler */
	Inst*	prog;		/* text segment */
	Type**	type;		/* Type descriptors */
	Modl	links[1];
};

struct Exception
{
	char*		pattern;
	void*		eptr;
	WORD*		rptr;
	Inst*		lr;
	REG		R;
	Exception*	link;
};

#define SEXTYPE(f)	((Stkext*)((uchar*)(f)-OA(Stkext, reg.tos.fu)))

extern	int	cflag;
extern	int	nproc;
extern	Type	Tarray;
extern	Type	Tstring;
extern	Type	Tchannel;
extern	Type	Tlist;
extern	Type	Tmodlink;
extern	Type*	TImage;
extern	Type*	TFont;
extern	Type*	TScreen;
extern	Type*	TDisplay;
extern	Type	Tbyte;
extern	Type	Tint;
extern	Type	Tbig;
extern	Type*	TFD;
extern	Type*	TFileIO;
extern	Type*	FioTread;
extern	Type*	FioTwrite;
extern	Type	Trdchan;
extern	Type	Twrchan;
extern	REG	R;
extern	String	snil;
extern	void	(*optab[256])(void);
extern	void	(*comvec)(void);
extern	void	(*dec[])(void);
extern	Module*	modules;
extern	Inst	ieclr;

extern	int		Dconv(va_list*, Fconv*);
extern	void		acquire(void);
extern	int		activated(void*, REG*);
extern	void		addrun(Prog*);
extern	void		altdone(Alt*, Prog*, Channel*, int);
extern	void		althangup(Prog*);
extern	int		atidle(int (*)(void*), void*);
extern	void		atidledont(int (*)(void*), void*);
extern	void		builtinmod(char*, void*);
extern	void		cblock(Prog*);
extern	void		changup(Prog**p);
extern	void		closeexp(Prog*);
extern	void		cmovw(void*, void*);
extern	Channel*	cnewc(void (*)(void));
extern	int		compile(Module*, int);
extern	void		crecv(Channel*, void*);
extern	void		csend(Channel*, void*);
extern	void		csendptrs(Channel*, void*, void**);
extern	Prog*		currun(void);
extern	void		dbgexit(Prog*, int, char*);
extern	void		dbgxec(Prog*);
extern	void		delprog(Prog*, char*);
extern	Prog*		delrun(int);
extern	void		delrunq(Prog*);
extern	Prog*		delruntail(int);
extern	void		destroyimage(ulong);
extern	void		destroylinks(Module*);
extern	void		destroystack(REG*);
extern	void		drawmodinit(void);
extern	void		error(char*);
extern	void		extend(void);
extern	void		expfree(Exception*);
extern	void		freestring(Heap*, int);
extern	int		gfltconv(va_list*, Fconv*);
extern	void		go(Module*);
extern	int		handler(char*);
extern	void		initarray(Type*, Array*);
extern	void		irestore(Prog*);
extern	Prog*		isave(void);
extern	int		killprog(Prog*, char*);
extern	Modlink*	linkmod(Module*, BYTE*, int);
extern	Modlink*	mklinkmod(Module*, int);
extern	Module*		load(char*);
extern	Module*		lookmod(char*);
extern	void		markarray(Type*, void*);
extern	void		marklist(Type*, void*);
extern	void		markmodl(Type*, void*);
extern	void		mathmodinit(void);
extern	void		markmods(void*);
extern	void		markprog(Prog*);
extern	Array*		mem2array(void*, int);
extern	void		mlink(Module*, uchar*, int, int, Type*);
extern	void		modinit(void);
extern	WORD		modstatus(REG*, char*, int);
extern	void		movp(void);
extern	void		movtmp(void);
extern	void		movtmpsafe(void);
extern	Module*		newmod(char*);
extern	void		newmp(void*, void*, Type*);
extern	Prog*		newprog(Prog*, Modlink*);
extern	void		newstack(Prog*);
extern	int		nprog(void);
extern	void		opinit(void);
extern	Module*		parsemod(char*, uchar*, ulong);
extern	Prog*		progn(int);
extern	Prog*		progpid(int);
extern	void		pushrun(Prog*);
extern	uchar*		readmod(char*, Module*, ulong*, int);
extern	void		irecv(void);
extern	void		release(void);
extern	void		releasex(void);
extern	void		retnstr(char*, int, String**);
extern	void		retstr(char*, String**);
extern	void		runtime(Module*, char*, int, void(*)(void*), Type*);
extern	int		segflush(void *, ulong);
extern	void		isend(void);
extern	void		seterror(char*, ...);
extern	void		sethints(String*, int);
extern	String*		splitc(String**, int);
extern	uchar*		stack(Frame*);
extern	int		stringblen(String*);
extern	int		stringcmp(String*, String*);
extern	String*		stringdup(String*);
extern	String*		stringheap(int, int, int, int);
extern	char*		syserr(char*, char*, Prog*);
extern	void		sysinit(void);
extern	void		sysmodinit(void);
extern	int		timeconv(va_list*, Fconv*);
extern	void		tellsomeone(Prog*, char*);
extern	void		unextend(Frame*);
extern	void		unframe(void);
extern	Inst*		unlinkex(void);
extern	void		unload(Module*);
extern	int		_utfnlen(char*, int, int*);
extern	int		verifysigner(uchar*, int, uchar*);
extern	void		xec(Prog*);
extern	void		xecalt(int);
extern	int		xprint(Prog*, void*, void*, String*, char*, int);
extern	void		iyield(void);
extern	String*		newstring(int);
extern	int		runeslen(Rune*, int);
extern	String*		c2string(char*, int);
extern	char*		string2c(String*);
extern	List*		cons(ulong, List**);
extern	String*		slicer(ulong, ulong, String*);
extern	String*		addstring(String*, String*);
extern	int		brpatch(Inst*, Module*);
extern	String*		strprint(String*, char*, ...);

extern	int	libopen(char*, int);
extern	int	libclose(int);

#pragma	varargck	argpos	strprint	2

#define	O(t,e)		((long)(&((t*)0)->e))
#define	OA(t,e)		((long)(((t*)0)->e))
