/** protolib.c
*
*   DESCRIPTION:
*   ===========
*
*	An exec library compiled with Aztec 3.40b, small model.
*
*	Based on "elib", an example library:
*	created by jim mackraz using mylib.asm by neil katin.
*	May be used and distributed providing this comment block
*	is retained in the source code.
*
*   THIS VERSION:
*   ============
*
*
*	This version implements a protocol transfer handler.
*	This file only handles the calls to Open, Close and Expunge.
*
*   AUTHOR/DATE:  W.G.J. Langeveld, February 1989.
*   ============
*
**/

#include "protolib.h"

extern PFL   libfunctab[];   /* XPR function table (libface.asm)     */
extern LONG  funkyInit();    /* hacked up version of Aztec crt0.a68   */

LONG XPRExpunge();

struct InitTable XPRInitTab =  {
   sizeof (struct XPRBase),
   libfunctab,
   NULL,                     /* will initialize XPR data in funkymain() */
   funkyInit
};

extern UWORD XPRrevision;

extern char XPRname[];
extern char XPRid[];
extern struct Resident XPRRomTag;

unsigned long XPRO = ('X' << 24) | ('P' << 16) | ('R' << 8) | 'O';

/**
*
*   This function is Jim's C-language library initRoutine.  It is called
*   by funkyInit() after register saves and small model initialization is
*   done.
*
**/
LONG funkymain(libbase, seglist)
struct XPRBase *libbase;
ULONG seglist;
{
   register   struct XPRBase *base;
/*
*   Cookie
*/
   base = libbase;
/*
*   Debug kind of stuff
*/
   base->mb_Cookie = XPRO;
   base->mb_SegList = seglist;
/*
*   init. library structure (since I don't do automatic data init.)
*/
   base->mb_Lib.lib_Node.ln_Type = NT_LIBRARY;
   base->mb_Lib.lib_Node.ln_Name = (char *) XPRname;   
   base->mb_Lib.lib_Flags = LIBF_SUMUSED | LIBF_CHANGED;
   base->mb_Lib.lib_Version = XPRRomTag.rt_Version;
   base->mb_Lib.lib_Revision = XPRrevision;
   base->mb_Lib.lib_IdString = (APTR) XPRid;

   return;
}


/**
*
*   Open library. Baseptr in A6, version in D0.
*
**/
LONG XPROpen(base)
struct XPRBase *base;
{
/*
*   Don't allow more than one open on this one. These libraries are
*   typically non-reentrant.
*   Note: if your library *is* reentrant, remove this statement.
*/
   if (base->mb_Lib.lib_OpenCnt) return(NULL);
/*
*   mark us as having another customer
*/
   base->mb_Lib.lib_OpenCnt++;
/*
*   prevent delayed expunges (standard procedure)
*/
   base->mb_Lib.lib_Flags &= ~LIBF_DELEXP;

   return ((LONG) base);
}

/**
*
*   Close library
*
**/
LONG XPRClose(base)
struct XPRBase *base;
{
   LONG retval = 0;

   if ((--base->mb_Lib.lib_OpenCnt == 0) &&
         (base->mb_Lib.lib_Flags & LIBF_DELEXP)) {
/*
*   No more people have me open,
*   and I have a delayed expunge pending:
*   return segment list.
*/
      retval = XPRExpunge();
   }

   return (retval);
}

/**
*
*   Expunge library
*
**/
LONG XPRExpunge(base)
struct XPRBase *base;
{
   ULONG seglist = 0;
   LONG libsize;

   if (base->mb_Lib.lib_OpenCnt == 0) {
/*
*   Really expunge: remove libbase and freemem
*/
      seglist   = base->mb_SegList;

      Remove(base);

      libsize = base->mb_Lib.lib_NegSize + base->mb_Lib.lib_PosSize;

      FreeMem((char *) base - base->mb_Lib.lib_NegSize, (LONG) libsize);
   }
   else {
      base->mb_Lib.lib_Flags |= LIBF_DELEXP;
   }
/*
*   Return NULL or real seglist
*/
   return ((LONG) seglist);
}


