
/*
 *  LIB.C
 *
 *  Basic Library Resource Handling
 *
 *  NOTE: all data declarations should be initialized since we skip
 *	  normal C startup code (unless initial value is don't care)
 */

#include "defs.h"

#ifndef _DCC
extern const LONG (*Vectors[])(); /*  Assembler library entry points */
#else
extern LONG Vectors();		  /*  trick a reference in the code section */
				  /*  __far would require the registered DICE */
#endif

/*  Avoid initializations so we save a data segment */
long	SegList;
#ifdef _DCC	/*  work around pc-relative bug in DICE-2.06.xx */
ExecBase * SysBase  = NULL;
#else
ExecBase * SysBase;
#endif
List	FifoList;

/*
 *    The Initialization routine is given only a seglist pointer.  Since
 *    we are NOT AUTOINIT we must construct and add the library ourselves
 *    and return either NULL or the library pointer.  Exec has Forbid()
 *    for us during the call.
 *
 *    If you have an extended library structure you must specify the size
 *    of the extended structure in MakeLibrary().
 */

LibCall Library *
LibInit(long segment)
{
    Library *lib;

    SysBase = *((ExecBase **) 4L);

    if ((lib = MakeLibrary(Vectors,NULL,NULL,sizeof(Library),NULL))) {
	lib->lib_Node.ln_Type = NT_LIBRARY;
	lib->lib_Node.ln_Name = (char *)LibName;
	lib->lib_Flags = LIBF_CHANGED|LIBF_SUMUSED;
	lib->lib_Version  = 38;
	lib->lib_Revision = 2;
	lib->lib_IdString = (APTR)LibId;
	SegList = segment;
	AddLibrary(lib);

	NewList((MaxList *)&FifoList);
    }
    return(lib);
}

/*
 *    We expunge the library and return the Seglist ONLY if the open count
 *    is zero.	If the open count is not zero we set the DELAYED-EXPUNGE
 *    flag and return NULL.
 *
 *    Exec has Forbid() for us during the call.  NOTE ALSO that Expunge
 *    might be called from the memory allocator and thus we CANNOT DO A
 *    Wait() or otherwise take a long time to complete (straight from RKM).
 *
 *    Apparently RemLibrary(lib) calls our expunge routine and would
 *    therefore freeze if we called it ourselves.  As far as I can tell
 *    from RKM, LibExpunge(lib) must remove the library itself as shown
 *    below.
 */

LibCall long
LibExpunge(long dummy, Library *lib)
{
    if (lib->lib_OpenCnt) {
	lib->lib_Flags |= LIBF_DELEXP;
	return(NULL);
    }
    Remove((MaxNode *)lib);
    FreeMem((void *)lib-lib->lib_NegSize, lib->lib_NegSize+lib->lib_PosSize);

    return(SegList);
}

/*
 *    Open is given the library pointer and the version request.  Either
 *    return the library pointer or NULL.  Remove the DELAYED-EXPUNGE flag.
 *    Exec has Forbid() for us during the call.
 */

LibCall Library *
LibOpen(long version, Library *lib)
{
    ++lib->lib_OpenCnt;
    lib->lib_Flags &= ~LIBF_DELEXP;
    return(lib);
}

/*
 *    Close is given the library pointer and the version request.  Be sure
 *    not to decrement the open count if already zero.	If the open count
 *    is or becomes zero AND there is a LIBF_DELEXP, we expunge the library
 *    and return the seglist.  Otherwise we return NULL.
 *
 *    Note that this routine never sets LIBF_DELEXP on its own.
 *
 *    Exec has Forbid() for us during the call.
 */

LibCall long
LibClose(long dummy, Library *lib)
{
    if (lib->lib_OpenCnt && --lib->lib_OpenCnt)
	return(NULL);
    if (lib->lib_Flags & LIBF_DELEXP)
	return(LibExpunge(0, lib));
    return(NULL);
}

