#include <Devices.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <StdArg.h>
#include "debugs.h"

short	ieee,
		DevParams[11];

OSErr	MacOSErr;

//関数定義本体
#ifdef __cplusplus
extern "C"{			//CodeWarriorに特有
#endif

short state(void);
int ckactive(void);
int	_false_(void);
void no_op(void);
long _ieeewt(short refnum, char chars[]);
long _ieeerd(short refnum,char chars[],long size);
int	ieeeprtf(char *format,va_list var);
int ieeescnf(char *format,...);
OSErr ieeeinit(void);

#ifdef __cplusplus
};
#endif

/********************************************************************
 *
 * state() uses the device manager Status routine to get the I/O
 * communications state of the IEEE interface: 0 if waiting for a 
 * command 1 if waiting with a response to be read, 2 if waiting for 
 * data to OUTPUT, and 3 if waiting for the remainder of a command.
 *
 *********************************************************************/
short state(void)
{	MacOSErr=Status(ieee,0,DevParams);
	return DevParams[0];
}


/********************************************************************
 *
 * ckactive() uses the device manager Status routine to check if any
 * of the monitored conditions are active.  The ARM command is used
 * to enable monitoring.  It returns zero (false) if no conditions are
 * active, non-zero if any are.
 *
 * _false_() is a function that always returns zero (false).
 *
 * (*ieee_ckactive)() is a pointer to a function that is used during
 * ieeewt to check for an active condition.  It is usually set to
 * either ckactive or _false_, and is initially points to _false_.
 *
 * no_op() is a function that does nothing.
 *
 * (*ieee_isr)() is a pointer to a function that is executed when ieeewt
 * detects an active condition by checking (*ieee_ckactive)().  ieee_isr
 * initially points to no_op, but should be set by the program to point
 * to the actual interrupt service routine.
 *
 *********************************************************************/
int ckactive(void)
{
	char msgbuf[256];
	
	MacOSErr=Status(ieee,0,DevParams);
	if (MacOSErr!=noErr) {
		sprintf(msgbuf, "Error %d in ckactive!",MacOSErr);
		showmsgs(CtoPstr(msgbuf), "\p","\p","\p");
//		exit(0);
	}
	if (DevParams[0]==0) {
		return (int)DevParams[1];	/* if ready for command, return status */
	} else {
		return 0;				/* otherwise return no-active result */
	}
}


int	_false_(void)
{ 	return	0; }


int	(*ieee_ckactive)() = _false_;


void no_op(void)
{	}


void (*ieee_isr)() = no_op;

/********************************************************************
 *
 * ieeerestart() uses the device manager Control routine to force the IEEE
 * interface into a quiescent, ready state so that it will accept
 * new commands.
 *
 *********************************************************************/
#define	ieeerestart()	Control(ieee,256,DevParams)


/********************************************************************
 *
 * ieeewt(chars) checks for active conditions, then writes the null-
 * terminated string to the IEEE interface.
 *
 * ieeerd(chars) reads chars from the IEEE interface into the character
 * array chars.  chars must be an array so that sizeof(chars) will give
 * the size of the buffer.
 *
 *********************************************************************/

long _ieeewt(short refnum, char chars[])
{	long	size=(long)strlen(chars);
	if ( (*ieee_ckactive)() ) {
		(*ieee_isr)();
	}
	MacOSErr=FSWrite(refnum,&size,chars);
	return size;
}

/*long	_ieeerd(short,char *,long); */

long _ieeerd(short refnum,char chars[],long size)
{
	MacOSErr=FSRead(refnum,&size,chars);
	return size;
}


#define ieeewt(chars)	_ieeewt(ieee,chars)
#define	ieeerd(chars)	_ieeerd(ieee,chars,sizeof(chars))


/********************************************************************
 *
 * ieeeprtf(format,vars) is equivalent to printf(format,vars) except
 * that it sends the formatted output to the IEEE interface.
 *
 * ieeescnf(format,&vars) is equivalen to scanf(format,&vars) except
 * that it takes its input from the IEEE interface and is limited to
 * 5 arguments to read.
 *
 *********************************************************************/
int	ieeeprtf(char *format, va_list var)
{	char	buffer[256];
	vsprintf(buffer,format,var);
	return (int)ieeewt(buffer);
}

int ieeescnf(char *format,...)
{
	int retval;
	char	buf[257];
	va_list var;

	_ieeerd(ieee,buf,256);
	if (MacOSErr != noErr){
		FMError(MacOSErr);
		return EOF;
	}
	buf[256]=(char)0;

	va_start(var, format);
	retval = (int)sscanf(buf,format,var);
	va_end(var);
	return retval;
}

/********************************************************************
 *
 * ieeeinit() initializes the IEEE interface
 *
 * It first opens the device driver, restarts it so that it is ready
 * to accept commands, sends the reset command, sets the output
 * terminator to line feed so that command end in '\n', and sets the
 * input terminator to null so that well-formed C strings are returned.
 *
 *********************************************************************/
OSErr 
ieeeinit(void)
{	( (MacOSErr=OpenDriver("\p.IEEE",&ieee)) != noErr)	||
	( (MacOSErr=ieeerestart()) != noErr)				||
	( (ieeewt("reset\n"),MacOSErr) != noErr)			||
	( (ieeewt("eol in $0\n"),MacOSErr) != noErr)		;
	return MacOSErr;
}
