/* rxil.h */

/*
 *		General header file for RXIL, the RexX Interface Library.
 *		Version 1.0
 *		18-Nov-89
 */

/*		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)
 */

/*
 *    Modified:
 *    Andrew C. R. Martin           13.12.91    11:15
 *    SciTech Software
 *
 *    Changed prototype for RxilHandleReturn()
 *    Added prototypes for Rxil_Shell routines.
 */

#ifndef RXIL_H
#define RXIL_H


/* Include the standard Amiga headers which most, if not all, files
 * will need (these are also needed by the ARexx headers).
 */

#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/ports.h>
#include <exec/libraries.h>

#include <intuition/intuition.h>


/* The prototype headers */

#ifdef LATTICE

#include <proto/exec.h>

#endif



/* Include the arexx 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



#define RXIL_VERSION_STRING		"Rxil, the ARexx Interface Library,\
 Version 1.0S1 18-Nov-89\n\
Copyright \xA9 1989 by Donald T. Meyer, Stormgate Software.\
S1 Revision: Andrew C. R. Martin, SciTech Software."



/* 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		/* Not enough args */
#define RXERR_BAD_VARIABLE				53L		/* Invalid compound var */
#define RXERR_TOO_MANY_ARGS				54L		/* Too many args */
#define RXERR_INVALID_ARG				55L		/* Invalid keyword */
#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
	/* This is the maximum number of arguments possible on the
	 * command line sent to the ARexx port.  Actually, this is
	 * one more than the number of actual argument that will be allowed
	 * since the first "argument" is taken to be the command name.
	 */


#define RXIL_MAX_PORTNAME_LEN			40
	/* This is the longest the original portname can be.  Adding
	 * the unique instance number, or the private port stuff will
	 * make the final name longer than this.  This should *not* be
	 * changed!
	 */



/* Flags for the diagnostic routine RxilDumpRdef() */

#define RXIL_DUMP_CMDS			0x01
#define RXIL_DUMP_ENV			0x02
#define RXIL_DUMP_STATE			0x04



/* These flags are used in the call to RxilInit() and are also
 * set into the variable which is accessed by the FROM_REXX macro
 * to indicate which port an  ARexx command came in at.
 *
 * These are also the command privilege levels.  Setting the privilege
 * 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 RXIL_AS_IS		0x04				/* The default is to append
											 * an "instance" number onto
											 * the port name.
											 * This will inhibit that.
											 */


/* RxilInvocation.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.
	 * In this case, 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 RxilCheckPort()
	 * 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_NO_REQ				0x0008
	/* Prevent routines such as RxilHandleReturn() from using requesters.
	 * This will force use of the CLI as the way to send messages to
	 * the user.
	 */



#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.
										 */

	UWORD	MinArgs;					/* Minimum number of arguments
										 * this command requires.
										 */

	UWORD	MaxArgs;					/* Maximum number of arguments
										 * this command will accept.
										 */

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

	UWORD	Privilege;					/* Set to either RXIL_PUBLIC or
										 * RXIL_SECRET to control which
										 * port(s) this command is valid
										 * from.  If RXIL_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[RXIL_MAX_PORTNAME_LEN+10];
												/* "MY_APP" */
	char					*Console;			/* "CON:0/0/20/40/" */
	char					*Extension;			/* "mapp" */
	char					*HostPort;			/* "REXX" */
	struct RxilFunction		*CommandTable;		/* &cmd_table[0] */

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

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

	/* Things the client may want to look at */
	UWORD					LockCount;
	char					*Version;

	/* 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 RxilInvocation *rxi );

struct RxilInvocation *RxilGetReturn( void );

/* Changed ACRM 12.12.91 */
int  RxilHandleReturn( struct RxilInvocation *rxi,
                       int                   noisy);

void RxilCleanupReturn( struct RxilInvocation *rxi );

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

void RxilDeleteRxi( struct RxilInvocation *rxi );

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

void RxilCheckPort( void );

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

struct RxilDef *RxilInit( ULONG flags, char *portname );

void RxilCleanup( struct RexxDef *rdef );

void RxilCmdLock( struct RexxMsg *rexxmsg );

void RxilCmdUnlock( struct RexxMsg *rexxmsg );

void RxilDumpRdef( struct RexxDef *rdef, ULONG flags );

void RxilCancel( void );

void RxilPostCancel( void );

BOOL RxilCheckCancel( void );

void RxilEndCancel( void );


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

#ifndef REXX_PROTOS
#define REXX_PROTOS

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 ** );


#ifndef  NO_PRAGMAS

/* --- Multiple returns, must use a stub... */
/* pragma libcall RexxSysBase ErrorMsg 60 1 */

#pragma libcall RexxSysBase CreateArgstring 7e 802
#pragma libcall RexxSysBase DeleteArgstring 84 801
#pragma libcall RexxSysBase LengthArgstring 8a 801
#pragma libcall RexxSysBase CreateRexxMsg 90 9803
#pragma libcall RexxSysBase DeleteRexxMsg 96 801
#pragma libcall RexxSysBase IsRexxMsg a8 801

#endif		/* NO_PRAGMAS */

#endif		/* REXX_PROTOS */



/*----------  ACRM: Additional Prototypes for Rxil shell --------*/

void  SetupREXX(char *portname,
                char *extension,
                char *conspec,
                int synch,
                struct RxilFunction *comtab,
                char *startup);

void  ProcessReturns(void);

int   CloseREXX(struct Window *wind,
                int force);

void  LaunchCmd(char *buf);

int   SetFuncParam(int pos,
                   char *string);

void  LaunchFunc(void);

void  RexxReturnUsed(void);

void  BuildComLine(char *buffer);

#endif		/* RXIL_H */

