/*
 * libsup.c -- Support routines for setting up an ARexx function
 *             library, based on the libsup.c file included with Aztec C.
 *
 *  The changes that have beed made to this file are actually quite minor,
 *  though we've renamed MyLibBase to ARLibBase...
 */

#include "arexx.h"
#include "arexxsyslib.h"
#include "rexxhs.h"
#include <exec/resident.h>

extern void myInit( void ); /* if you change this name, change libstart.asm */

LONG ARLibOpen( void );
LONG ARLibClose( void );
LONG ARLibExpunge( void );

#pragma amicall( ARLibBase, 0x06, ARLibOpen() )
#pragma amicall( ARLibBase, 0x0c, ARLibClose() )
#pragma amicall( ARLibBase, 0x12, ARLibExpunge() )

/* library initialization table, used for AUTOINIT libraries */

struct InitTable {
    unsigned long   it_DataSize;          /* library data space size */
    void          **it_FuncTable;         /* table of entry points */
    void           *it_DataInit;          /* table of data initializers */
    void          (*it_InitFunc)( void ); /* initialization function to run */
};

void *LibFuncTab[] = {
	ARLibOpen,
	ARLibClose,
	ARLibExpunge,
	NULL,
        Dispatch, /* <==== Our dispatch routine */
	(void *) -1L
};

struct InitTable myInitTab =  {
	sizeof( struct ARLibBase ),
	LibFuncTab,
	0,						/* will initialize my data in funkymain()	*/
	myInit
};

#define MYREVISION	1	/* would be nice to auto-increment this		*/

char myname[] = "rexxhs.library";
char myid[]   = "RexxHostSupport 1.0 (July 15/91)\r\n";

extern struct Resident myRomTag;

/*
 * _main -- Called from myInit when the library is first loaded into memory.
 */

LONG _main( struct ARLibBase *ARLibBase, ULONG seglist )
  {
	ARLibBase->ml_SegList = seglist;

	ARLibBase->ml_Lib.lib_Node.ln_Type = NT_LIBRARY;
	ARLibBase->ml_Lib.lib_Node.ln_Name = (char *) myname;
	ARLibBase->ml_Lib.lib_Flags        = LIBF_SUMUSED | LIBF_CHANGED;
	ARLibBase->ml_Lib.lib_Version      = myRomTag.rt_Version;
	ARLibBase->ml_Lib.lib_Revision     = MYREVISION;
	ARLibBase->ml_Lib.lib_IdString     = (APTR) myid;
  }

/*
 * ARLibOpen -- Increment the library open count and get rid of any
 *              delayed expunge flag.
 */

LONG ARLibOpen( void )
  {
    struct ARLibBase *ARLibBase;

    ARLibBase->ml_Lib.lib_OpenCnt++;
    ARLibBase->ml_Lib.lib_Flags &= ~LIBF_DELEXP;

    return( (LONG) ARLibBase );
  }

/*
 * ARLibClose -- Decrement the library open count, and expunge if no
 *               one has it open and the delayed expunge flag is set.
 */

LONG ARLibClose( void )
  {
    struct ARLibBase *ARLibBase;
    LONG              retval = 0;

    if( --ARLibBase->ml_Lib.lib_OpenCnt == 0 ){
        if( ARLibBase->ml_Lib.lib_Flags & LIBF_DELEXP ){
            retval = ARLibExpunge(); /* return segment list	*/
        }
    }

    return( retval );
  }

/*
 * ARLibExpunge -- Remove the library if no one is using it, otherwise
 *                 mark it for a delayed expunge.
 */

LONG ARLibExpunge( void )
  {
    struct ARLibBase      *ARLibBase;
    unsigned long          seglist = 0;
    long                   libsize;
    extern struct Library *DOSBase;

    if( ARLibBase->ml_Lib.lib_OpenCnt == 0 ){
        seglist = ARLibBase->ml_SegList;
        Remove( &ARLibBase->ml_Lib.lib_Node );

        libsize = ARLibBase->ml_Lib.lib_NegSize+ARLibBase->ml_Lib.lib_PosSize;
        FreeMem( (char *)ARLibBase-ARLibBase->ml_Lib.lib_NegSize, libsize );
        CloseLibrary(DOSBase); /* keep the counts even */
    } else {
        ARLibBase->ml_Lib.lib_Flags |= LIBF_DELEXP;
    }

    return( (LONG) seglist );
  }

