#define  _USEOLDEXEC_ 1
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/memory.h>
#include <exec/resident.h>
#include <exec/libraries.h>
#include <libraries/dos.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <string.h>


/* Prototypes */
ULONG __saveds __asm _LibExpunge( register __a6 struct MyLibrary *libbase );
ULONG __saveds __asm _LibInit( register __a0 APTR seglist,
                                register __d0 struct MyLibrary *libbase );
void __saveds __asm _UserLibInit(register __a6 struct MyLibrary *libbase );
void __saveds __asm _UserLibCleanup(register __a6 struct MyLibrary *libbase);

struct MyLibrary
{
   struct	Library ml_Lib;
   ULONG	ml_SegList;
   ULONG	ml_Flags;
   APTR		ml_ExecBase;		/* pointer to exec base */
   };

typedef LONG (*PFL)();   /* pointer to function returning 32-bit int */

/* library initialization table, used for AUTOINIT libraries */
struct InitTable
{
   ULONG        *it_DataSize;		/* library data space size */
   PFL          *it_FuncTable;		/* table of entry points */
   APTR         it_DataInit;		/* table of data initializers */
   PFL          it_InitFunc;		/* initialization function to run */
   };


/* symbols generated by blink */
extern char __far _LibID[];		/* ID string */
extern char __far _LibName[];		/* Name string */
extern char __far RESLEN;		/* size of init data */
extern long __far NEWDATAL;		/* size of global data */
extern PFL _LibFuncTab[];		/* my function table */
#define DATAWORDS ((long) &NEWDATAL)	/* magic to get right type of reloc */ 
#define SIZEJMPTAB ((long) libbase->ml_origbase->ml_numjmps)
					/* size in bytes of jmp table */
#define MYVERSION	2		/* version number */
#define MYREVISION	51		/* revision number */

/* From libent.o, needed to determine where data is loaded by loadseg */
extern long far _Libmergeddata; 

struct InitTable __far _LibInitTab =
{
   (long *)(&RESLEN + sizeof(struct MyLibrary)),
   _LibFuncTab,
   NULL,				/* will initialize my own data */
   _LibInit,
   };

/**********************************************************
 *	ULONG _LibInit(APTR seglist, struct MyLibrary *libbase)
 **********************************************************/
__saveds __asm ULONG _LibInit( register __a0 APTR seglist,
   register __d0 struct MyLibrary *libbase )
{
   long *reloc;
   long *sdata;
   char *ddata;
   long nrelocs;

   libbase->ml_SegList = (ULONG) seglist;

   /* init. library structure (since I don't do automatic data init.) */
   libbase->ml_Lib.lib_Node.ln_Type = NT_LIBRARY;
   libbase->ml_Lib.lib_Node.ln_Name = _LibName;
   libbase->ml_Lib.lib_Flags = LIBF_SUMUSED | LIBF_CHANGED;
   libbase->ml_Lib.lib_Version = MYVERSION;
   libbase->ml_Lib.lib_Revision = MYREVISION;
   libbase->ml_Lib.lib_IdString = (APTR) _LibID;

   /* Start of copy of global data after structure */
   ddata = (char *) libbase + sizeof(struct MyLibrary); 

   sdata = (long *) &_Libmergeddata;	/* where loadseg loaded the data */
   memcpy(ddata, (void *) sdata, DATAWORDS * 4);
   /*
    * perform relocs if we want one global section for all programs
    * that have this lib open. If we want a global section for each
    * open, copy the relocs, and do them on each open call.
    */
   sdata = sdata + DATAWORDS;
   nrelocs = *sdata;
   sdata++;
   while (nrelocs > 0)
   {
      reloc = (long *)((long) ddata + *sdata++);
      *reloc += (long) ddata;
      nrelocs--;
      }
   _UserLibInit(libbase);

   return ( (ULONG) libbase );
   }	/* End of ULONG _LibInit() */

/**********************************************************
 *	LONG _LibOpen(struct MyLibrary *libbase)
 **********************************************************/
LONG __saveds __asm _LibOpen( register __a6 struct MyLibrary *libbase )
{
   /* mark us as having another customer */
   libbase->ml_Lib.lib_OpenCnt++;

   /* clear delayed expunges (standard procedure) */
   libbase->ml_Lib.lib_Flags &= ~LIBF_DELEXP;

   return ( (LONG) libbase );
   }	/* End of LONG _LibOpen() */

/**********************************************************
 *	ULONG _LibClose(struct MyLibrary *libbase)
 **********************************************************/
ULONG __saveds __asm _LibClose( register __a6 struct MyLibrary *libbase )
{
   ULONG retval = 0;
    
   if (( --libbase->ml_Lib.lib_OpenCnt == 0 ) &&
      ( libbase->ml_Lib.lib_Flags & LIBF_DELEXP ))
   {
      /* no more people have me open,
       * and I have a delayed expunge pending
       */
      retval = _LibExpunge( libbase );		/* return segment list */
      }

   return (retval);
   }	/* End of ULONG _LibClose() */

/**********************************************************
 *	ULONG _LibExpunge(struct MyLibrary *libbase)
 **********************************************************/
ULONG __saveds __asm _LibExpunge( register __a6 struct MyLibrary *libbase )
{
   ULONG seglist = 0;
   LONG  libsize;

   libbase->ml_Lib.lib_Flags |= LIBF_DELEXP;
   if ( libbase->ml_Lib.lib_OpenCnt == 0 )
   {
      /* really expunge: remove libbase and freemem */
      _UserLibCleanup(libbase);
      seglist = libbase->ml_SegList;

      Remove( (struct Node *) libbase);

      libsize = libbase->ml_Lib.lib_NegSize + libbase->ml_Lib.lib_PosSize;
      FreeMem( (char *) libbase - libbase->ml_Lib.lib_NegSize, (LONG) libsize );
      }

   /* return NULL or real seglist */
   return ( (ULONG) seglist );
   }	/* End of ULONG _LibExpunge() */
/* End of Libinit.c source */
