
/*
 *  LIBRARY.C
 *
 *  Example fully working library for Aztec C ... with comments (which is
 *  a miracle in itself).   By Matthew Dillon.	PUBLIC DOMAIN.
 *
 *  Aztec Compile with +BCDLp
 *	    +B	No startup reference
 *	    +C	Large code
 *	    +D	Large data
 *	    +L	32 bit Integers
 *	    +p	compatibility mode  (D2/D3 preserved)
 *
 *  Since Original release, the following has been fixed:
 *	-slight bug in LibClose() .. did not expunge library if DELEXP set
 *	 on final close.  (thanks to Rico Mariani for finding the bug)
 *	-Now uses MakeLibrary call rather than a hardwired Library structure.
 */

#define NULL 0L

typedef struct Library	LIB;

extern LIB *MakeLibrary();

#define VERSION     1	    /*	NOTE!  String in dc.b below must also be */
#define REVISION    3	    /*	       Changed! 			 */

#asm
VERSION     equ     1

	;   RLIB.ASM
	;
	;   Run-time library tag

	    FAR     data

	    public  _CInit
	    public  _LibOpen
	    public  _LibClose
	    public  _LibExpunge

Start:	    clr.l   D0
	    rts

InitDesc:   dc.w    $4AFC	;RTC_MATCHWORD
	    dc.l    InitDesc	;Pointer to beginning
	    dc.l    EndCode	;Note sure it matters
	    dc.b    0		;flags (NO RTF_AUTOINIT)
	    dc.b    VERSION	;version
	    dc.b    9		;NT_LIBRARY
	    dc.b    0		;priority (doesn't matter)
	    dc.l    _Libname	;Name of library
	    dc.l    _Libid	;ID string (note CR-LF at end)
	    dc.l    Init	;Pointer to init routine

_Libname:   dc.b    "dres.library",0
_Libid:     dc.b    "dres.library 1.3 (29 Sep 1988)",13,10,0
EndCode:

Init:	    move.l  A6,-(sp)    ;Must save A6
	    move.l  A0,-(sp)    ;Segment list
	    jsr     _CInit
	    addq.l  #4,sp
	    move.l  (sp)+,A6
	    rts

cifc	    macro
	    move.l  D0,-(sp)    ;Make a C call and save A6 to boot
	    move.l  A6,-(sp)
	    jsr     \1
	    move.l  (sp)+,A6
	    addq.l  #4,sp
	    rts
	    endm

__LibOpen:	cifc	_LibOpen
__LibClose:	cifc	_LibClose
__LibExpunge:	cifc	_LibExpunge

#endasm

extern char Libname[1];
extern char Libid[1];

LIB  *Lib, *DResBase;		 /*  Library Base pointer	 */
long Seglist;			/*  Save the DOS seglist	*/


/*
 *    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().
 */

#include "libfuncs.h"

LIB *
CInit(segment)
{
    extern long SysBase;
    extern long DOSBase;

    SysBase = *(long *)4;
    DOSBase = OpenLibrary("dos.library", 0);
    if (DOSBase == NULL)
	return(NULL);
    DResBase = Lib = MakeLibrary(LibVectors,NULL,NULL,sizeof(LIB),NULL);
    Lib->lib_Node.ln_Type = NT_LIBRARY;
    Lib->lib_Node.ln_Name = Libname;
    Lib->lib_Flags = LIBF_CHANGED|LIBF_SUMUSED;
    Lib->lib_Version  = VERSION;
    Lib->lib_Revision = REVISION;
    Lib->lib_IdString = (APTR)Libid;
    Seglist = segment;
    AddLibrary(Lib);
    return(Lib);
}

/*
 *    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.
 */

LIB *
LibOpen(lib,version)
LIB *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.
 */

LibClose(lib)
LIB *lib;
{
    if (lib->lib_OpenCnt && --lib->lib_OpenCnt)
	return(NULL);
    if (lib->lib_Flags & LIBF_DELEXP)
	return(LibExpunge(lib));
    return(NULL);
}

/*
 *    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.
 */

LibExpunge(lib)
LIB *lib;
{
    extern long DOSBase;

    if (lib->lib_OpenCnt) {
	lib->lib_Flags |= LIBF_DELEXP;
	return(NULL);
    }
    if (DOSBase) {
	CloseLibrary(DOSBase);
	DOSBase = NULL;
    }
    Remove(lib);
    FreeMem((char *)lib-lib->lib_NegSize, lib->lib_NegSize+lib->lib_PosSize);
    return(Seglist);
}

