/* rxil.h */

/*		Copyright © 1989 by Donald T. Meyer, Stormgate Software
 *		All Rights Reserved
 *
 *		This source code may be compiled and used in any software
 *		product.
 *		No portion of this source code is to be re-distributed or
 *		sold for profit.
 *
 *		Donald T. Meyer
 *		Stormgate Software
 *		P.O. Box 383
 *		St. Peters, MO  63376
 *
 *		BIX:	donmeyer		(usually daily)
 *		GEnie:	D.MEYER			(weekly)
 *		PLINK:	Stormgate		(weekly)
 */


#ifndef RXIL_H
#define RXIL_H




/* Include the rexx headers we may need */

#ifndef REXX_STORAGE_H
#include <rexx/storage.h>
#endif

#ifndef REXX_ERRORS_H
#include <rexx/errors.h>
#endif

#ifndef REXX_RXSLIB_H
#include <rexx/rxslib.h>
#endif



/*------------------------------------------------------------------*/
/*							Defines									*/
/*------------------------------------------------------------------*/

/*----------   I think these are from RJ's ProSuite   --------------*/
#ifndef SetFlag
#define SetFlag(v,f)		( (v) |= (f) )
#define ClearFlag(v,f)		( (v) &= ~(f) )
#define FlagIsSet(v,f)		(  ( (v) & (f) ) != 0  )
#define FlagIsClear(v,f)	(  ( (v) & (f) ) == 0  )
#endif



/* Result error codes which may be sent back to the macro program
 * as the primary result code.
 *
 * If you have purchased the database program "Microfiche Filer Plus"
 * from Software Visions, some of these error codes may sound familiar.
 * Gary Samad of Software Visions has a reasonable scheme for error
 * code values, and they are used here with his permission.  It is my
 * feeling that as ARexx ports proliferate, there should be some commmon
 * scheme for error code return values.  Obviously, no single set of
 * error codes will suffice for all possible programs, but a common
 * "core" set of standard error codes should at least be possible.
 */

/* Informative */
#define RXERR_NOTOK						 1L
#define RXERR_END_OF_LIST				 2L

/* Syntax, content, or user errors */
#define RXERR_REQUIRES_RESULT_FLAG		50L
#define RXERR_NOT_A_HARMLESS_CMD		51L
#define RXERR_NO_ARGUMENT				52L
#define RXERR_BAD_VARIABLE				53L
#define RXERR_ARG_COUNT					54L
#define RXERR_NOTHING_TO_UNLOCK			76L
#define RXERR_ALREADY_LOCKED			77L
#define RXERR_UNKNOWN_CMD				80L
#define RXERR_BUSY						81L

/* Fatal */
#define RXERR_NO_AREXX_LIBRARY		   100L
#define RXERR_NO_MEMORY				   110L
#define RXERR_FAILED				   150L			/* Misc. failure */
#define RXERR_ABORTED				   200L



#define RXIL_MAX_ARGS	20



/* These flags are used in the call to init_rexx() and are also
 * set into the from_rexx flag to indicate which port a rexx command
 * comes from.
 *
 * These are also the command privledge levels.  Setting the privledge
 * to 0 or REXX_PUBLIC means that a command received at either the
 * public or secret ports will be accepted.  If set to REXX_SECRET,
 * the command will be accepted from the secret port only.
 */

#define RXIL_PUBLIC		0x01
#define RXIL_SECRET		0x02
#define RXIL_PRIVATE	RXIL_SECRET			/* If "secret" sounds too
											 * cloak-and-dagger...
											 */
/* #define REXX_REENTRANT	0x80 */



#define RXIL_NO_ARGCHECK		-1


/* RexxInvocation.state  */

#define RXIL_STATE_AVAILABLE	0		/* This structure is idle */

#define RXIL_STATE_PENDING		1		/* Has been sent to Rexx
										 * host.
										 */

#define RXIL_STATE_RETURNED		2		/* Returned from Rexx host,
										 * but has not been "handled"
										 * yet.
										 */


/* RexxDef.Flags */

#define RXIL_NOLAUNCH			0x0001
	/* If set, the loopback launch feature will be disabled.
	 * If set, the following functions are not needed:
	 *		RxilLaunch()
	 *		RxilCreateRxi()
	 *		RxilCancel(), RxilPostCancel(), RxilEndCancel()
	 *		RxilCheckCancel()
	 */

#define RXIL_NO_CLEARABORT		0x0002
	/* If set, the Abort flag will NOT be cleared by check_rexx_port()
	 * whenever there are no pending macro invocations.
	 */

#define RXIL_NO_ABORT			0x0004
	/* Do not post the "Cancel" requester when a macro is
	 * launched.
	 */




#define RXIL_ARGV(x)		(global_rdef->Arg[(x)])
#define RXIL_ARGC			(global_rdef->ArgCount)

#define RXIL_FROM_REXX		(global_rdef ? global_rdef->FromRexx : 0)

#define RXIL_WAITFLAG		(global_rdef ? global_rdef->SigBit : 0L)



/*------------------------------------------------------------------*/
/*					Structure Template Definitions					*/
/*------------------------------------------------------------------*/

struct RxilFunction {
	char	*Name;						/* The function name. */

	void	(*Func)(struct RexxMsg *);	/* Vector to the function's 'C'
										 * code.
										 */

	WORD	ArgCount;					/* Number of args expected.
										 * Set to NO_ARGCHECK
										 * if we don't care or
										 * will ascertain within the
										 * function.
										 */

	BOOL 	CaseFlag;					/* TRUE if we care about upper
										 * and lower case for the
										 * function name.
										 */

	UWORD	Privlege;					/* Set to either REXX_PUBLIC or
										 * REXX_SECRET to control which
										 * port(s) this command is valid
										 * from.  If REXX_PUBLIC, than
										 * this command may be executed
										 * from either port.
										 */
};



struct RxilInvocation {
	struct RxilInvocation	*Next;
	struct RexxMsg			*RexxMsg;
	struct RexxMsg			*Parent;
	char					*IHostPort;
	UWORD					State;
	ULONG					Type;
	char					*Name;
	char					*FileExt;
	char					*CommAddr;
	char					*Console;
	ULONG					ActionFlags;
	BOOL					CountArgs;
	char					*FuncArg[MAXRMARG];
	UWORD					ArgLen[MAXRMARG];
};



struct RxilCancelReq {
	struct Window		*win;
	struct Requester	req;
};



struct RxilDef {
	/* Things which need to be inited by the client */
	UWORD					Flags;
	char					*PortName;			/* "MY_APP" */
	char					*Console;			/* "CON:0/0/20/40/" */
	char					*Extension;			/* "mapp" */
	char					*HostPort;			/* "REXX" */
	struct RxilFunction		*CommandTable;		/* &cmd_table[0] */

/* Should the above become a separate structure?  The client may want
 * to change what are essentialy launch & dispatch parameters on the fly
 * and as a set?
 */

	/* Things which the client may alter */
	BOOL					Abort;
	char					SecretPortName[80];
	struct Window			*CancelWindow;

	/* Things which the client needs to see, but NOT SET */
	ULONG					SigBit;
	int						FromRexx;
	char					*Arg[RXIL_MAX_ARGS];
	UWORD					ArgCount;

	/* Things the client may want to look at */
	int						LockCount;

	/* Fairly private stuff, access via function calls only */
	struct MsgPort			*PublicPort;
	struct MsgPort			*SecretPort;
	struct RxilInvocation	*Invocations;
	struct RxilCancelReq	*CReq;
};



/*------------------------------------------------------------------*/
/*					Variable Declarations							*/
/*------------------------------------------------------------------*/

extern struct RxsLib *RexxSysBase;
	/* Defined in "init.c" */

extern struct RxilDef *global_rdef;
	/* Defined in a client module */



/*------------------------------------------------------------------*/
/*					Function Declarations							*/
/*------------------------------------------------------------------*/

LONG RxilToRexx( ULONG cmd,
	STRPTR arg0, STRPTR arg1, STRPTR arg2, STRPTR arg3 );

void RxilCheckResult( struct RexxMsg *rexxmsg );

void RxilOpenConsole( char *console, struct RexxMsg *rexxmsg );

void RxilCloseConsole( struct RexxMsg *rexxmsg );

void RxilDeletePort( struct MsgPort *port );

void RxilDispatch( struct RexxMsg *rexxmsg, char *cmd );

LONG RxilLaunch( struct RexxInvocation *rxi );

struct RexxInvocation *RxilGetReturn( void );

void RxilHandleReturn( struct RexxInvocation *rxi );

void RxilCleanupReturn( struct RexxInvocation *rxi );

struct RexxInvocation *RxilCreateRxi( char *name, ULONG type );

void RxilDeleteRxi( struct RexxInvocation *rxi );

BOOL RxilPending( void );
BOOL RxilCmdPending( void );
BOOL RxilFuncPending( void );

void RxilCheckPort( void );

void RxilSetResult( struct RexxMsg *rexxmsg, char *string );

struct RexxDef *RxilInit( int flags, char *portname );

void RxilCleanup( struct RexxDef *rdef );

void RxilCmdLock( struct RexxMsg *rexxmsg );

void RxilCmdUnlock( struct RexxMsg *rexxmsg );

void RxilDumpRdef( struct RexxDef *rdef );

void RxilCancel( void );

void RxilPostCancel( void );

BOOL RxilCheckCancel( void );

void RxilEndCancel( void );



/*-----------------  ARexx Function Prototypes  ---------------*/

#ifndef REXX_PROTOS
#define REXX_PROTOS

void LockRexxBase( ULONG );

void UnlockRexxBase( ULONG );

struct RexxMsg *CreateRexxMsg( struct MsgPort *, char *, char * );

struct RexxArg *CreateArgstring( char *, ULONG );

void DeleteArgstring( struct RexxArg * );

void DeleteRexxMsg( struct RexxMsg * );

LONG IsRexxMsg( struct RexxMsg * );

LONG ErrorMsg( ULONG, struct RexxArg ** );

#endif


#endif

