/*	Copyright  (c)	Günter Woigk 2009 - 2015
					mailto:kio@little-bat.de

	This file is free software

 	This program is distributed in the hope that it will be useful,
 	but WITHOUT ANY WARRANTY; without even the implied warranty of
 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

	Redistribution and use in source and binary forms, with or without 
	modification, are permitted provided that the following conditions are met:

	• Redistributions of source code must retain the above copyright notice, 
	  this list of conditions and the following disclaimer.
	• Redistributions in binary form must reproduce the above copyright notice, 
	  this list of conditions and the following disclaimer in the documentation 
	  and/or other materials provided with the distribution.

	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
	AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
	THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
	PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
	OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
	WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
	OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
	ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/


//	Standard vcc header
//
//	16 bpb
//
//	float48
//	no int8
//	no int64


type utf8str = str
type str_r	 = ucs2char[to]		// range
type Sema	 = {}
type Mutex	 = {}
type Irpt	 = {}
type Thread	 = {}
type Tid	 = Thread¢;
type int8	= int16
type uint8	= uint16
type FD		= {};
type File	= FD + {}
type Dir	= File
type Block	= {}

//enum uint bool = { yes=1, no=0, true=1, false=0 }
const bool yes=(bool)1, no=(bool)0 
const bool true=(bool)1, false=(bool)0 
#include "errno.h"

const float pi = 3.141592653589793//238462
const float ec = 2.718281828459045//235360

void k1mc_option_procptr_in_rom()		= opcode k1mc_option_procptr_in_rom
void k1mc_option_procptr_in_ram()		= opcode k1mc_option_procptr_in_ram
void k1mc_option_return_to_rom()		= opcode k1mc_option_return_to_rom
void k1mc_option_return_to_ram()		= opcode k1mc_option_return_to_ram
void k1mc_option_proc_return_to_ram()	= opcode k1mc_option_proc_return_to_ram


// ____________________________________________________________________
// Math:

extern	
{
// int:
	ulong 	new 	(uint hi, uint lo) 		= opcode nop;

	int		sign	(int16)					= opcode sign
	int		sign	(int32)					= opcode sign

	uint16	abs		(int16)					= opcode abs
	uint32	abs		(int32)

	int16	min		(int16,int16)			= opcode min
	uint16	min		(uint16,uint16)			= opcode min
	int32	min		(int32,int32)			
	uint32	min		(uint32,uint32)			

	int16	min		(int16,int16,int16)		= opcode min
	uint16	min		(uint16,uint16,uint16)	= opcode min
	int32	min		(int32,int32,int32)		= opcode min
	uint32	min		(uint32,uint32,uint32)	= opcode min

	int16	max		(int16,int16)			= opcode max
	uint16	max		(uint16,uint16)			= opcode max
	int32	max		(int32,int32)			= opcode max
	uint32	max		(uint32,uint32)			= opcode max

	int16	max		(int16,int16,int16)		= opcode max
	uint16	max		(uint16,uint16,uint16)	= opcode max
	int32	max		(int32,int32,int32)		= opcode max
	uint32	max		(uint32,uint32,uint32)	= opcode max

	int16	swap	(int16)			= opcode swap	// revert bytes
	uint16	swap	(uint16)		= opcode swap	// ((was: SwapBytes))
	int32	swap	(int32)			= opcode swap
	uint32	swap	(uint32)		= opcode swap

	int16	hilo	(int16)			= opcode hilo
	uint16	hilo	(uint16)		= opcode hilo
	int32	hilo	(int32)			= opcode hilo
	uint32	hilo	(uint32)		= opcode hilo

	int16	lohi	(int16)			= opcode lohi
	uint16	lohi	(uint16)		= opcode lohi
	int32	lohi	(int32)			= opcode lohi
	uint32	lohi	(uint32)		= opcode lohi

	uint16	flip	(uint16)		= opcode flip	// revert bits
	uint32	flip	(uint32)		= opcode flip

	int		msbit0	(int16)			= opcode msbit0
	int		msbit0	(uint16)		= opcode msbit0
	int		msbit	(int16)			= opcode msbit
	int		msbit	(uint16)		= opcode msbit

	int16	pow		(int16,int)		= opcode pow
	uint16	pow		(uint16,int)	= opcode pow
	int32	pow		(int32,int)		= opcode pow
	uint32	pow		(uint32,int)	= opcode pow

	uint16	random	()
	uint16	random	(uint16)
	uint32	random	()
	uint32	random	(uint32)

	uint16	mul10	(uint16)		= opcode Mul10
	uint16	exp10	(uint16)		= opcode Exp10
	uint16	log10	(uint16)		= opcode Log10
	
	bool	bit15	(uint)			= opcode Bit15



// float48:
	int		sign	(float)
	float	abs		(float)			

	float	min		(float,float)
	float	max		(float,float)
//	float	min		(float,float,float)
//	float	max		(float,float,float)

	float	round	(float)			
	float	floor	(float)			
	float	ceil	(float)			
	float	integ	(float)			
	float	fract	(float)			
	
	float	random	()
	float	random	(float)

	float	sin		(float)			
	float	cos		(float)			
//	float	tan		(float)			= opcode tan
//	float	asin	(float)			= opcode asin
//	float	acos	(float)			= opcode acos
//	float	atan	(float)			= opcode atan
//	float	sinh	(float)			= opcode sinh
//	float	cosh	(float)			= opcode cosh
//	float	tanh	(float)			= opcode tanh
	float	exp10	(float)			
	float	log10	(float)			
	float	exp2	(float)			
	float	log2	(float)			
	float	expe	(float)			
	float	loge	(float)			
	float	exp		(float,float)	
	float	log		(float,float)	
	float	pow		(float,int)		
	float	sqrt	(float)			
}


// ____________________________________________________________________

extern	// Char:
{
	bool	isletter	(char)		= opcode is_letter		
	bool	isdigit2	(char)		= opcode is_bin_digit
	bool	isdigit10	(char)		= opcode is_dec_digit
	bool	isdigit16	(char)		= opcode is_hex_digit
	uint	value10		(char)		= opcode digit_value		// up to base 36
	uint	value16		(char)		= opcode digit_value		// up to base 36
	uint	value36		(char)		= opcode digit_value		// up to base 36
}	


// ____________________________________________________________________

extern	// Mem:
{
	void	memcpy		( void* z, void* q, uint n )	= opcode memcpy		// trad. memcpy, 'ldir'
	void	memcpy		( uint* z, uint* q, uint n )	= opcode memcpy
	void	memcpy		( int*  z, int*  q, uint n )	= opcode memcpy
	void	memcpy		( char* z, char* q, uint n )	= opcode memcpy

	void	rmemcpy		( void* z, void* q, uint cnt )	= opcode rmemcpy	// trad. memcpy, 'lddr'
	void	rmemcpy		( uint* z, uint* q, uint cnt )	= opcode rmemcpy
	void	rmemcpy		( int*  z, int*  q, uint cnt )	= opcode rmemcpy
	void	rmemcpy		( char* z, char* q, uint cnt )	= opcode rmemcpy

	void	memmove		( void* z, void* q, uint cnt )	= opcode memmove
	void	memmove		( uint* z, uint* q, uint cnt )	= opcode memmove
	void	memmove		( int*  z, int*  q, uint cnt )	= opcode memmove
	void	memmove		( char* z, char* q, uint cnt )	= opcode memmove

	void	memset		( void* z, byte  q, uint n )	= opcode memset
	void	memset		( char* z, char  q, uint cnt )	= opcode memset
	void	memset		( uint* z, uint  q, uint cnt )	= opcode memset
	void	memset		( int*  z, int   q, uint cnt )	= opcode memset

	void	memclr		( void* z, uint cnt )			= opcode memclr
	void	memclr		( char* z, uint cnt )			= opcode memclr
	void	memclr		( uint* z, uint cnt )			= opcode memclr
	void	memclr		( int*  z, uint cnt )			= opcode memclr

	void	copy		( uint[]¢ q, uint[]¢ z )		= opcode copy

	void	copy		( uint[]¢ q, uint qi, uint[]¢ z, uint zi, uint n )
	void	copy		( int[]¢  q, uint qi, int[]¢ z,  uint zi, uint n ) = void copy(uint[]¢,uint,uint[]¢,uint,uint);
	void	copy		( str¢    q, uint qi, str¢ z,    uint zi, uint n ) = void copy(uint[]¢,uint,uint[]¢,uint,uint);

	void	memcompact	()								= opcode MemCompact
	uint	memgetfree	()								= opcode MemGetFree

	void copy_i16_to_i8	( uint16[]¢ q, uint qi, uint8[]¢ z,  uint zi )
	void copy_i8_to_i16	( uint8[]¢ q,  uint qi, uint16[]¢ z, uint zi )
	void copy_i16_to_i8	( int16[]¢ q,  uint qi, int8[]¢ z,   uint zi ) = void copy_i16_to_i8(uint16[]¢,uint,uint8[]¢,uint)
	void copy_i8_to_i16	( int8[]¢ q,   uint qi, int16[]¢ z,  uint zi ) = void copy_i8_to_i16(uint8[]¢,uint,uint16[]¢,uint)
}


// ____________________________________________________________________
// Strings:

extern	
{
//	str[]¢	getenv		()		= opcode getenv;	
//	str[]¢	getargs		()		= opcode getargs;	

//	void	shrinktofit	( str& )						= opcode shrinktofit

	str_r	substr		( str¢ s, int a, int e )		= opcode substr
	str_r	midstr		( str¢ s, int i, int n )	//	= opcode midstr
	str_r	midstr		( str¢ s, int i )			//	= opcode midstr
	str_r	leftstr		( str¢ s, int n )			//	= opcode leftstr
	str_r	rightstr	( str¢ s, int n )			//	= opcode rightstr

	int[to] substr		( int[]¢ s, int a, int e )		= str_r	substr	 ( str¢ s, int a, int e )
	int[to] midstr		( int[]¢ s, int i, int n )		= str_r	midstr	 ( str¢ s, int i, int n )
	int[to] midstr		( int[]¢ s, int i )				= str_r	midstr	 ( str¢ s, int i )
	int[to] leftstr		( int[]¢ s, int n )				= str_r	leftstr	 ( str¢ s, int n )
	int[to] rightstr	( int[]¢ s, int n )				= str_r	rightstr ( str¢ s, int n )

	uint[to] substr		( uint[]¢ s, int a, int e )		= str_r	substr	 ( str¢ s, int a, int e )
	uint[to] midstr		( uint[]¢ s, int i, int n )		= str_r	midstr	 ( str¢ s, int i, int n )
	uint[to] midstr		( uint[]¢ s, int i )			= str_r	midstr	 ( str¢ s, int i )
	uint[to] leftstr	( uint[]¢ s, int n )			= str_r	leftstr	 ( str¢ s, int n )
	uint[to] rightstr	( uint[]¢ s, int n )			= str_r	rightstr ( str¢ s, int n )

	str		new			( int n )						= opcode spacestr
	str		spacestr	( int n )						= opcode spacestr
	str		spacestr	( int n, char c )				= opcode spacestr
	str		charstr		( uint c )						= opcode charstr

	char	hexchar		( uint n )						// TODO

	str		hexstr		( uint16 n )
	str		hexstr		( uint32 n )
	str		hexstr		( uint16 n, uint digits )
	str		hexstr		( uint32 n, uint digits )

	str		binstr		( uint16 n )					= opcode binstr
	str		binstr		( uint32 n )					= opcode binstr
	str		binstr		( uint16 n, uint digits )		= opcode binstr
	str		binstr		( uint32 n, uint digits )		= opcode binstr
	str		binstr		( uint16 n, str¢ d0, str¢ d1 )	= opcode binstr
	str		binstr		( uint32 n, str¢ d0, str¢ d1 )	= opcode binstr
	
	str		numstr		( int16  n )
	str		numstr		( uint16 n )
	str		numstr		( int32  n )
	str		numstr		( uint32 n )
	str		numstr		( float  n )					
	
	int16	numval		( str¢ )						= opcode numval
	uint16	numval		( str¢ )						= opcode numval
	int32	numval		( str¢ )						= opcode numval
	uint32	numval		( str¢ )						= opcode numval
	float	numval		( str¢ )						= opcode numval
	
	int		find		( int16[]¢,  int16,  int idx )		= opcode find
	int		find		( int32[]¢,  int32,  int idx )		= opcode find
	int		find		( uint16[]¢, uint16, int idx )		= opcode find
	int		find		( uint32[]¢, uint32, int idx )		= opcode find
	int		find		( float[]¢,  float,  int idx )		= opcode find

	int		find		( int16[]¢,  int16[]¢,  int idx )	= opcode find
//	int		find		( int32[]¢,  int32[]¢,  int idx )	= opcode find
	int		find		( uint16[]¢, uint16[]¢, int idx )	= opcode find
//	int		find		( uint32[]¢, uint32[]¢, int idx )	= opcode find

	int		rfind		( int16[]¢,  int16,  int idx )		= opcode rfind
	int		rfind		( int32[]¢,  int32,  int idx )		= opcode rfind
	int		rfind		( uint16[]¢, uint16, int idx )		= opcode rfind
	int		rfind		( uint32[]¢, uint32, int idx )		= opcode rfind
	int		rfind		( float[]¢,  float,  int idx )		= opcode rfind

	int		rfind		( int16[]¢,  int16[]¢,  int idx )	= opcode rfind	
//	int		rfind		( int32[]¢,  int32[]¢,  int idx )	= opcode rfind
	int		rfind		( uint16[]¢, uint16[]¢, int idx )	= opcode rfind	
//	int		rfind		( uint32[]¢, uint32[]¢, int idx )	= opcode rfind
	
	str		min			( str,  str  )	= opcode min
	str¢	min			( str¢, str¢ )	= opcode min

	str		max			( str,  str   )	= opcode max
	str¢	max			( str¢, str¢  )	= opcode max

	int16	min			( int16[]¢ )	= opcode min
	int32	min			( int32[]¢ )	= opcode min
	uint16	min			( uint16[]¢ )	= opcode min
	uint32	min			( uint32[]¢ )	= opcode min
	float	min			( float[]¢ )	= opcode min
	str¢	min			( str[]¢ )		= opcode min

	int16	min			( int16[to]	 )	= opcode min
	int32	min			( int32[to]	 )	= opcode min
	uint16	min			( uint16[to] )	= opcode min
	uint32	min			( uint32[to] )	= opcode min
	float	min			( float[to]	 )	= opcode min
	str¢	min			( str[to]	 )	= opcode min

	int16	max			( int16[]¢	 )	= opcode max
	int32	max			( int32[]¢ 	)	= opcode max
	uint16	max			( uint16[]¢ )	= opcode max
	uint32	max			( uint32[]¢ )	= opcode max
	float	max			( float[]¢ 	)	= opcode max
	str¢	max			( str[]¢ 	)	= opcode max

	int16	max			( int16[to]	 )	= opcode max
	int32	max			( int32[to]	 )	= opcode max
	uint16	max			( uint16[to] )	= opcode max
	uint32	max			( uint32[to] )	= opcode max
	float	max			( float[to]	 )	= opcode max
	str¢	max			( str[to]	 )	= opcode max

/*	void	sort		( T[]¢ )		= opcode sort
	void	rsort		( T[]¢ )		= opcode rsort
	void	shuffle		( T[]¢ )		= opcode shuffle
	void	flip		( T[]¢ )		= opcode flip
	void	rol			( T[]¢ )		= opcode rol	
	void	ror			( T[]¢ )		= opcode ror	

	void	sort		( T[to] )		= opcode sort
	void	rsort		( T[to] )		= opcode rsort
	void	shuffle		( T[to] )		= opcode shuffle
	void	flip		( T[to] )		= opcode flip	
	void	rol			( T[to] )		= opcode rol	
	void	ror			( T[to] )		= opcode ror	
*/
	str		join		( str[]¢, str¢ )	= opcode join
	str		join		( str[]¢, char )	= opcode join

	str[]	split		( str¢, str¢ )		= opcode split
	str[]	split		( str¢, char )		= opcode split
}

scope str
{
	str	toupper		( str )					= opcode toupper
	str	tolower		( str )					= opcode tolower
	str	escape		( str, char leftquote)	= opcode escape
	str	unescape	( str )					= opcode unescape	
}

scope char
{
	char operator+ 	( char, int )		 	= opcode Add
}



// ____________________________________________________________________
// Time:


enum	// for timestr
{
	tm_utc			= 0,	// convert to/from UTC
	tm_localtime	= 1,	// convert to/from local time
	tm_time			= 2,	// include time
	tm_date			= 4,	// include date
	tm_timezone		= 8,	// include timezone
	tm_sec			= 16,	// include seconds in time
	tm_msec			= 32	// include micro seconds in time
}

extern
{
	float	now			()									= opcode now
	str		timestr		( float seconds, int localtime )	= opcode timestr	// 2011-04-13 09:05:01'033 CEST
	float	timeval		( str¢, int localtime )				= opcode timeval
}	


// ____________________________________________________________________
// Multithreading:

type Thread =
{
// dispatcher data:
	int			state1;				// running, willing, suspended, semashed, timeshed
	int			state2;				// blocking list
	int			prio;				// actual priority: lower is better		prio = log2(reaktionszeit/sec)
	int			prio_org;			// nominal priority (most times same as prio)
	
	Tid			next1,prev1;		// list1: willing, timeshed, suspended, scrapped (or running) 
	Tid			next2,prev2;		// list2: blocking Sema or Mutex

	void*		blocker;			// Sema, Mutex or Irpt for which thread is waiting
	float		time;				// alarm time for which thread is sheduled
	Mutex*		mutexes;			// linked list of mutexes blocked by this thread

// interpreter data:
	uint*[]		rstack;				// return stack & context heap
	int[]		vstack;

// thread state:
	int*		context0;
	int*		context1;
	uint*		ip;					// instruction pointer
	uint**		rp;					// return stack pointer
	int*		vp;					// variables stack pointer
	int*		gp;					// only s_node: global data base		
	int			_errno;			
}



	Tid		self		()							= opcode self
	int		vfree		()							= opcode vfree
	int		rfree		()							= opcode rfree
	void	freeze		(bool)						= opcode freeze

//	void	spawn		(void(*) fu,*)				= opcode spawn		// built-in
//	void	spawn		(void(*) fu,*),prio,vstack,rstack=opcode spawn	// built-in

	void	termi		()							= opcode termi		// self
	void	termi		(Tid)						= opcode termi
	void	suspend		()							= opcode suspend	// self
	void	suspend		(Tid)						= opcode suspend
	void	resume		(Tid)
	void	wait		()							= opcode wait		// until next interrupt
	void	wait		(float sec)				//	= opcode wait
	void	shedule		(float when)				= opcode shedule
	void	busywait	(uint usec)					= opcode busywait


type Sema =				// note: i386_64: struct size alignment 8 bytes
{
	Tid		waiters
	int		count		// available resources
}

scope Sema
{
	void	request		(Sema¢)						= opcode request
	void	release		(Sema¢)						= opcode release
	bool	tryrequest	(Sema¢)						= opcode tryrequest
	bool	tryrequest	(Sema¢, float timeout)		= opcode tryrequest
//	Sema	init		(Sema)						= opcode nop
	Sema	copy		(Sema)						= opcode copy
	Sema	kill		(Sema)						= opcode kill
	void	clear		(Sema¢ s)					= opcode mutexclear	// inline { s.count=0; }
	void	add			(Sema¢ s, int n)			= opcode release
}


type Mutex =
{
	Tid		waiters
	Tid		owner
	Mutex¢	next,prev
}

scope Mutex
{
	void	lock		(Mutex¢)					= opcode lock
	void	unlock		(Mutex¢)					= opcode unlock
	bool	trylock		(Mutex¢)					= opcode trylock
	bool	trylock		(Mutex¢, float timeout)		= opcode trylock
//	Mutex	init		(Mutex)						= opcode nop		// default c'tor is ok
	Mutex	copy		(Mutex)						= opcode copy		// 
	Mutex	kill		(Mutex)						= opcode kill		// 
}	


type Irpt =
{
	Tid		waiters
	int		count	
}

scope Irpt
{
	void	wait		(Irpt¢)						= opcode wait
	void	wait		(Irpt¢,float timeout)		= opcode wait
	void	trigger		(Irpt¢)						= opcode trigger
	void	clear		(Irpt¢ i)					= opcode semaclear	// inline { i.count = 0; }
	Irpt	copy		(Irpt)						= opcode copy
	Irpt	kill		(Irpt)						= opcode kill
}


// ____________________________________________________________________
// Debug:

extern	
{
	str		errorstr	(int error)		= opcode errorstr
	str		errorstr	()				= opcode errorstr
	
	void	log_hp	()					= opcode LogHP
	void	trace	()					= opcode Trace		// microcode trace
	void	tron	()					= opcode Tron		// millicode trace
	void	troff	()					= opcode Troff
	void	log_cc	()					= opcode LogCC
	void	log		(char)				= opcode logchar
	void	lognum	(int)				= opcode lognum
	void	log		(str)				= opcode logstr
	void	log		(str¢)				= opcode logstr
	void	logmem	()					= opcode LogMem

	void	OMEM	()					= opcode oomem
	void	TODO	()					= opcode todo
	void	abort	()					= opcode abort
	void	abort	(str msg)
	void	IERR	()					= opcode abort
	void	PANIC	()					= opcode panic
	void	PANIC	(str msg)

	void	setledred ()				= opcode SetLedRed
	void	setledyel ()				= opcode SetLedYel
	void	setledgrn ()				= opcode SetLedGrn
	void	clrledred ()				= opcode ClrLedRed
	void	clrledyel ()				= opcode ClrLedYel
	void	clrledgrn ()				= opcode ClrLedGrn

	uint	get_hp	()					= opcode PshHP
};


// ____________________________________________________________________
// Devices:

	void	select		(int)			= opcode select
	void	set_intmask	()				= opcode SetIntMask
	void	deselect	()				= opcode deselect
	void 	clear_error	();				// clear errno





















