#include "stdc.h"


// 	––––––––––––––––––––––––––––––––––––––
//	K1-bus driver ioctl function codes:

enum uint8
{
	c_reset		= 0,	// 00 + set			reset

	// sio:
	c_speed 	= 1,	// 01 + set/get		set/get serial speed * 100
	c_hwhsk 	= 2,	// 02 + set/get		set/get HW handshake on/off
	c_swhsk 	= 3,	// 03 + set/get		set/get SW handshake state for send data on/off
	c_flushin  	= 4,	// 04 + set			flush
	c_availin  	= 4,	// 04 + 	get		get avail bytes in input buffer
	c_flushout 	= 5,	// 05 + set			flush
	c_availout 	= 5,	// 05 + 	get		get avail space in output buffer
	c_clk_hsk	= 6,	// 06 + set/get		set synchronous mode

	//block:
	c_log2blocksize  = 7,	//	get		ioctl_blk_log2blocksize
	c_totalblocks_lo = 8,	// 	get 	ioctl_blk_totalblocks_lo
	c_totalblocks_hi = 9,	//	get 	ioctl_blk_totalblocks_hi
	c_reserved2		 = 10	//			ioctl_blk_reserved2
};


// 	––––––––––––––––––––––––––––––––––––––
// Error codes:

enum uint8 OSErr =
{
	// error codes defined for K1-Bus driver eeproms:
	ok = 0,
	parameter_error = 1,
	function_not_supported = 1,
	io_error = 2,
	device_not_responding = 3,

	FileError,			// generic file system error

	filesystem_invalid,
	device_not_found,
	directory_not_found,
	file_not_found,

	not_a_directory,
	is_a_directory,
	file_already_open_for_writing,
	file_already_open,
	file_exists,

	file_not_writable,
	end_of_file,
	disk_full,
	directory_corrupted,
	filesystem_corrupted
};


extern
{
	OSErr 	errno;
	// use setters and getters: shorter, faster
	OSErr	error();
	void	clear_error();
	void	set_error(OSErr);
	bool 	yes_with_error(OSErr);
	void*	null_with_error(OSErr);		// null_with_error__5OSErr_4voidP
}


// 	––––––––––––––––––––––––––––––––––––––
// 	FD NodeType:
//
// 	these are enumerated to match FileTypes in directories

enum uint8 NodeType =
{
	t_endmarker = 0,		// end of directory marker
	t_file	= 1,		// regular file
	t_dir 	= 2,		// directory file
	t_ser	= 3,		// serial device
	t_block	= 4, 		// block device
	m_erased = 0x80		// + num bytes to skip
};

scope NodeType
{
	NodeType operator| (NodeType,NodeType) = opcode operator |;
	NodeType operator& (NodeType,NodeType) = opcode operator &;
}


// 	––––––––––––––––––––––––––––––––––––––
//	Standard member functions:
// do not reorder!

type FD_Handlers =
{
	uint  (FD¢, uint8 fu)      	getctl;		// all
	void  (FD¢, uint8 fu, uint)	setctl;		// all

	uint  (FD¢)    				avail_in;	// file, ser
	uint  (FD¢)   				avail_out;	// file, ser

	char  (FD¢)        			getc;		// file, ser	blocking
	void  (FD¢, char)    		putc;		// file, ser	blocking

	bool  (FD¢, uint8[…]) 		read;		// file, ser	blocking
	bool  (FD¢, uint8[…]) 		write;		// file, ser	blocking

	bool  (FD¢, uint32, uint8[]¢) read_block;	// file, blk
	bool  (FD¢, uint32, uint8[]¢) write_block;	// file, blk

	void  (FD¢)					kill;		// all	for "T T.kill(T)"

	ulong (FD¢)  	 			getfpos;	// file			[bytes]
	bool  (FD¢, ulong fpos)  	setfpos;	// file			[bytes]
}

// dummy handlers:
// these set fd.error to function_not_supported.

extern
{
uint  no_avail_in(FD¢)
uint  no_avail_out(FD¢)	 	= no_avail_in;
char  no_getc	(FD¢)		= no_avail_in;
void  no_putc	(FD¢, char)
ulong no_getfpos(FD¢)
bool  no_setfpos(FD¢, ulong)
bool  no_read	(FD¢, uint8[…])
bool  no_write	(FD¢, uint8[…])				= no_read;
bool  no_read_block(FD¢, uint32, uint8[]¢)
bool  no_write_block(FD¢, uint32, uint8[]¢)	= no_read_block;
}


//	––––––––––––––––––––––––––––––––––––––
//	base class for serial and block device and files:

type FD =
{
	FD_Handlers¢ handlers;
	NodeType	 nodetype;
	str			 name;
}


//	––––––––––––––––––––––––––––––––––––––
//	convenience functions for stdin and stdout:

extern
{
	uint 	avail_in	();					// stdin	✓
	uint 	avail_out	();					// stdout	✓

	const uint delimiters = 1<<0 + 1<<4 + 1<<10 + 1<<12 + 1<<13;

	char  	getc		();					// stdin	✓
	void  	putc		(char c);			// stdout	✓
	str 	gets		(uint delimiters);	// stdin	✓
	void  	puts		(str¢);				// stdout	✓
	void  	puts		(str);				// stdout	✓
	void	putnum		(uint);				// stdout	✓
	void	putnum		(int);				// stdout	✓
	bool   	read		(uint8[…]);  		// stdin	✓
	bool   	write		(uint8[…]);  		// stdout	✓

	//bool 	error		(OSErr);			// set errno and return "yes" for error
}


//	––––––––––––––––––––––––––––––––––––––
//	convenience functions to call the handler functions:

scope FD
{ extern
{
	void  	init		(FD¢, NodeType, str¢ name, FD_Handlers¢);  //  ✓
	void	kill		(FD¢);					//		✓
	FD  	kill		(FD);					//		✓

	uint 	getctl		(FD¢, uint8 fu)      	// all	✓
	void 	setctl		(FD¢, uint8 fu, uint n) // all	✓

	uint	avail_in	(FD¢);   				// ser	✓
	uint	avail_out	(FD¢);  				// ser	✓

	char 	getc		(FD¢);       			// file, ser  ✓  note: all i/o is blocking
	void 	putc		(FD¢, char c);    		// file, ser  ✓

	str 	gets		(FD¢, uint delimiters);	// ser, file  ✓
	void 	puts		(FD¢, str¢);			// ser, file  ✓
	void 	puts		(FD¢, str);				// ser, file  ✓
	void	putnum		(FD¢, uint);			// ser, file  ✓
	void	putnum		(FD¢, int);				// ser, file  ✓
	bool  	read		(FD¢, uint8[…])			// ser, file  ✓
	bool 	write		(FD¢, uint8[…])		  	// ser, file  ✓

	bool  	read_block	(FD¢, uint32 blk, uint8[]¢);  // file, blk  ✓
	bool  	write_block	(FD¢, uint32 blk, uint8[]¢);  // file, blk  ✓

	ulong	getfpos		(FD¢)	  				// file  ✓
	bool 	setfpos		(FD¢, ulong fpos)	  	// file  ✓

	bool 	is_dir		(FD¢);
	bool 	is_file		(FD¢);
}}














