/* $Revision Header * Header built automatically - do not edit! *************
 *
 *	(C) Copyright 1990 by MXM
 *
 *	Name .....: LibMain.c
 *	Created ..: Saturday 06-Jan-90 23:30
 *	Revision .: 8
 *
 *	Date            Author          Comment
 *	=========       ========        ====================
 *	26-Apr-90       Olsen           Opened dos.library (always forgot it!)
 *	13-Apr-90       Olsen           Added NULL-function
 *	01-Apr-90       Olsen           Moved library calls
 *	27-Mar-90       Olsen           Added alerts/moved flag checks
 *	26-Mar-90       Olsen           Rearranged LibExpunge/LibClose
 *	16-Mar-90       Olsen           Rework for Aztec 5.0 release
 *	07-Jan-90       Olsen           - Empty log message -
 *	07-Jan-90       Olsen           Moved OpenLibrary call
 *	07-Jan-90       Olsen           - Empty log message -
 *	07-Jan-90       Olsen           Created this file!
 *
 * $Revision Header *********************************************************
 *
 *	This file contains the skeleton library functions employed by
 *	rexxhost.library.
 *
 ***************************************************************************/

	/* Imported from RexxHostLib.c */

extern LONG Revision;

	/* ASCII library ID. */

char *LibName	= "rexxhost.library";
char *LibId	= "rexxhost.library 34.12 (26 Apr 1990)\r\n";

	/* External data, defined in asm startup code. */

extern struct Resident	 LibRomTag;
extern LONG		 LibInit();

	/* Main rexx library base. */

struct RxsLib *RexxSysBase;

	/* External reference to DOSBase pointer. */

extern APTR DOSBase;

	/* Pointer to library segment list. */

BPTR LibSegList = ZERO;

	/* Protos for this module. */

struct RexxHostBase *	LibMain(struct RexxHostBase *,BPTR);

struct RexxHostBase *	LibOpen(VOID);
BPTR			LibClose(VOID);
BPTR			LibExpunge(VOID);
LONG			LibNull(VOID);

	/* And now for the pragmas... */

#pragma amicall(RexxHostBase, 0x06, LibOpen())
#pragma amicall(RexxHostBase, 0x0c, LibClose())
#pragma amicall(RexxHostBase, 0x12, LibExpunge())
#pragma amicall(RexxHostBase, 0x18, LibNull())

	/* The library initialization. */

#pragma regcall(LibMain(d0,a0))

	/* The structure expected by the library loader (auto-init). */

struct InitTable
{
	ULONG	 it_DataSize;	/* Data size to allocate. */
	APTR	*it_FuncTable;	/* Pointer to function table. */
	APTR	 it_DataInit;	/* Pointer to data initializers (remember InitStruct?). */
	APTR	 it_InitFunc;	/* The real library init function. */
};

	/* The list of library functions. */

APTR LibFuncTab[] =
{
	LibOpen,		/* Standard library routines. */
	LibClose,
	LibExpunge,
	LibNull,

	CreateRexxHost,		/* Now for the real stuff. */
	DeleteRexxHost,
	SendRexxCommand,
	FreeRexxCommand,
	ReplyRexxCommand,
	GetRexxCommand,
	GetRexxArg,
	GetRexxResult1,
	GetRexxResult2,
	GetToken,
	GetStringValue,
	BuildValueString,
	RexxStrCmp,

	(APTR)-1		/* End marker. */
};

	/* The romtag needs this. */

struct InitTable LibInitTab =
{
	sizeof(struct RexxHostBase),	/* Lib base. */
	LibFuncTab,			/* Function table. */
	NULL,				/* No data init table (we'll do autoinit). */
	LibInit				/* Lib init routine. */
};

	/* LibMain(RexxHostBase,SegList):
	 *
	 *	Does the main library initialization, expects
	 *	all arguments in registers.
	 */

struct RexxHostBase *
LibMain(struct RexxHostBase *RexxHostBase,BPTR SegList)
{
	struct RexxHostBase *LibBase = NULL;

		/* We want to be initialized only once, the empty
		 * seglist will (hopefully) guarantee that.
		 */

	if(!LibSegList)
	{
		if(DOSBase = (APTR)OpenLibrary("dos.library",0))
		{
				/* Try to open rexxsyslib.library. */

			if(RexxSysBase = (struct RxsLib *)OpenLibrary(RXSNAME,0))
			{
					/* Remember segment list. */

				LibSegList = SegList;

					/* Seems that all initialization went fine. */

				LibBase = RexxHostBase;

					/* Fill in the library node head. */

				RexxHostBase -> LibNode . lib_Node . ln_Type	= NT_LIBRARY;
				RexxHostBase -> LibNode . lib_Node . ln_Name	= LibName;

					/* Set the remaining flags. */

				RexxHostBase -> LibNode . lib_Flags		= LIBF_SUMUSED | LIBF_CHANGED;
				RexxHostBase -> LibNode . lib_Version		= LibRomTag . rt_Version;
				RexxHostBase -> LibNode . lib_Revision		= Revision;
				RexxHostBase -> LibNode . lib_IdString		= (APTR)LibId;

					/* Fill in the pointer. */

				RexxHostBase -> RexxSysBase = RexxSysBase;
			}
			else
			{
				/* Help! Can't open the rexx library! */

				Alert(AT_Recovery | AG_OpenLib,"REXX");
			}
		}
		else
		{
			/* Arrgh! Can't open dos.library! */

			Alert(AT_Recovery | AG_OpenLib | AO_DOSLib,"REXX");
		}
	}

		/* Return the result (surprise!). */

	return(LibBase);
}

	/* LibOpen():
	 *
	 *	Library open routine.
	 */

struct RexxHostBase *
LibOpen()
{
	struct RexxHostBase *RexxHostBase;

		/* If rexxsyslib.library didn't open we refuse
		 * to go any further.
		 */

	if(!RexxSysBase)
		return(NULL);

		/* Increment open count and prevent delayed
		 * expunges.
		 */

	RexxHostBase -> LibNode . lib_OpenCnt++;
	RexxHostBase -> LibNode . lib_Flags &= ~LIBF_DELEXP;

		/* Return base pointer. */

	return(RexxHostBase);
}

	/* LibClose():
	 *
	 *	Closes the library.
	 */

BPTR
LibClose()
{
	struct RexxHostBase	*RexxHostBase;
	BPTR			 SegList = ZERO;

		/* Is the library user count ok? */

	if(RexxHostBase -> LibNode . lib_OpenCnt > 0)
	{
			/* Decrement user count. */

		RexxHostBase -> LibNode . lib_OpenCnt--;

			/* Try the expunge. */

		SegList = LibExpunge();
	}
	else
	{
		/* One close request after the lib has already
		 * shut down? We'll call Mr. Guru.
		 */

		Alert(AT_Recovery | AG_CloseLib,"HOST");
	}

		/* Return the segment list, ramlib will know
		 * what to do with it.
		 */

	return(SegList);
}

	/* LibExpunge(RexxHostBase):
	 *
	 *	Expunge library, careful: this can be called by
	 *	ramlib without the rest of the library knowing
	 *	about it.
	 */

BPTR
LibExpunge()
{
	struct RexxHostBase	*RexxHostBase;
	BPTR			 SegList = ZERO;

		/* Is the user count zero, the delayed expunge flag
		 * set and do we have a valid segment list?
		 */

	if(RexxHostBase -> LibNode . lib_OpenCnt == 0 && (RexxHostBase -> LibNode . lib_Flags & LIBF_DELEXP) && LibSegList)
	{
			/* Remember segment list. */

		SegList = LibSegList;

			/* Set real segment list to zero which will
			 * hopefully keep us from getting expunged
			 * twice.
			 */

		LibSegList = ZERO;

			/* Remove library from lib list. */

		Remove((struct Node *)RexxHostBase);

			/* Close the libraries. */

		if(RexxSysBase)
			CloseLibrary(RexxSysBase);

		if(DOSBase)
			CloseLibrary(DOSBase);

			/* Free library/jumptable memory. */

		FreeMem((char *)RexxHostBase - RexxHostBase -> LibNode . lib_NegSize,RexxHostBase -> LibNode . lib_NegSize + RexxHostBase -> LibNode . lib_PosSize);
	}
	else
	{
		/* In any other case we'll set the delayed
		 * expunge flag (so next expunge call will
		 * hopefully wipe us from the lib list).
		 */

		RexxHostBase -> LibNode . lib_Flags |= LIBF_DELEXP;
	}

		/* Return segment list pointer. */

	return(SegList);
}

	/* LibNull():
	 *
	 *	Dummy routine, always returns NULL.
	 */

LONG
LibNull()
{
	struct RexxHostBase *RexxHostBase;

		/* Do nothing useful, return NULL. */

	return(NULL);
}
