
			SHARED_LIB EXAMPLE CODE

    This is a fully compilable shared library implemented for DICE
    demonstrating how one can write their very own shared library.  Some
    knowledge in shared libraries is required to understand the code..
    the basic thing to remember is (1) that a shared library is NOT a
    normal C program, and (2) the interface calls MUST be reentrant...
    i.e. multiple tasks can make a library call simultaniously.

    The only limitation with this example is that I use -mRR which turns on
    registered arguments.  The limitation is that currently DICE will only
    generated registered functions for those routines that take no more
    than 2 integers and 2 pointers.  Routines that take more than that
    limit or take other types (structures, floating pt, etc...) will
    not have a registered entry point.

			    SHARED LIBRARY

    DEFS.H	contains header stuff
    TAG.A	library independant basic code
    LIB.C	library independant basic code
    INIT.C	library dependant initialization routines
    FUNCS.C	library dependant routines

    TAG.A and LIB.C are almost self contained with only a few modifications
    required to use them for other library projects... basically the
    name of the library in TAG.A and the function list in LIB.C

    TAG.A contains a subset of the standard startup code, LIB/AMIGA/C.A,
    and assumes non-resident compilation (i.e. you cannot use the -r
    option).  This isn't a problem since the -r option doesn't gain you
    anything as far as shared libraries go.

    The individual library interface routines are declared with the LibCall
    macro, defined in DEFS.H, which ensures the small-data pointer is set
    up for all interface calls allowing use of the small-data model.

			    LIBRARY INTERFACE

    LIB.FD	The .FD file must match library prototypes.  The first two
		integer arguments are stuck in D0 & D1 while the first
		two pointer arguments are stuck in A0 & A1.

    AUTO.A	This is extremely DICE specific in that it gives programs
		that link with the interface .lib (link library) the
		capability to auto-open & close test.library without
		having to explicitly do so in main().

		Notice that test.c doesn't explicitly OpenLibrary() or
		CloseLibrary() "test.library".  DICE provides such
		capabilities for most standard amiga libraries in the
		same fashion.

    ---

    To compile, be sure that -2.0 is specified in your DCCOPTS an the
    2.0 registered libraries are unpacked:

	DLIB:amigasr20.lib
	DLIB:cr.lib

	DINCLUDE:AMIGA20/*/*.h

    Create a temporary directory to hold the resulting objects and the
    resulting .lib tag library.  The resulting .library file will be placed
    in LIBS: and the test program will be T:test

	DTMP:sharlib/	    (to hold the objects & .lib file)

    Note that you will get warnings from FDTOLIB, these can be ignored. A
    non-registered and registered version of the interface link library
    required when linking TEST.C is generated, and two versions of TEST.C
    are included to show what is required to compile either a normal
    program or registered-args program that talks to the registered-args
    library.

    1> dmake
	... compiles it all ...
    1> test.script


				THE LINK LIB

    You will notice that the test program must be linked with test.lib
    from DTMP:sharlib/ .. this is the library interface tag library
    which interfaces C calls to a shared library.  Under DICE, a twist
    is added in the form of a special auto-open module appended to the
    .lib file.

    This auto-open module allows the TEST program to make library calls
    without explicitly openning the shared library!  This greatly simplifies
    the complication that using shared libraries generally adds.

    If you are interested, you should run 'DOBJ DTMP:SHARLIB/TEST.LIB' to
    see how the link library works.

			   ORDERING OF REGISTERED ARGUMENTS

    Arguments to registered calls work as follows:

	if (number of args <= 4 && not var-args-call && only int & ptr args)
	    put arguments in registers
	else
	    use stack call

    Registers are assigned to arguments in argument order.  Integers are
    assigned to D0 and D1 if available at the point they are scanned, else
    A0 then A1 will be used (again, if not already assigned).  Pointers
    are assigned to A0 and A1 if available at the point they are scanned,
    else D0 then D1 will be used (again, if not already assigned to a
    previous argument).

	(a few examples of register ordering)

    fubar(int, char *, int, char *)
	   D0	A0     D1    A1

    fubar(char *, int, char *, int)
	   A0	  D0	A0	D0

    fubar(char *, int, int, int)
	    A0	  D0   D1   A1

    fubar(int, int, int, char *)
	   D0  D1   A0	  A1		<---- note!

    fubar(char *, char *, char *, int)
	    A0	    A1	   D0	  D1	<---- note!

    You need to know the register ordering to construct your .FD file
    properly.


			 NOT USING REGISTERED ARGUMENTS

    When you are not using registered arguments you will still want
    the library to be called with arguments in registers.  However,
    since your library routine does not use registered arguments you
    will need to create an assembly tag in TAG.A to deal with it, then
    have your function array in LIB.C point to the tags instead of the
    actual library functions.

    Example:	if you have a routine called 'MyLibCall' in C, it's
    symbol in assembly would be _MyLibCall.  The easiest thing to do
    then is in lib.c change the MyLibCall function pointer to Asm_MyLibCall
    and in assembly write the following:

			xdef	_Asm_MyLibCall	; assembly tag
			xref	_MyLibCall	; C stack call

	_Asm_MyLibCall	movem.l  D0/D1,-(sp)     ; push registers
			jsr	_MyLibCall(pc)
			addq.l	#8,sp
			rts

    Be extremely careful pushing registers, MOVEM always orders registers
    being pushed D0..D7,A0..A7, you cannot specify the order in the MOVEM
    call and may have to resort to several MOVE calls to accomplish your
    task.  You do not have to restore the registers since only A2-A6/D2-D7
    are required to be left alone, and the C function will do this
    automatically, so in the example above I simply addq.l #8,sp to pop
    the stack back up (if more than 8 bytes use lea XX(sp),sp).

    Complex libraries with complex calls may be easier to write if you
    use assembly tags and not rely on registered arguments for the
    library routines themselves.  Actually, the best way is to use
    reg-args for those library calls that fit the requirements and
    tags for those that do not, but this can be complicated and should
    not be tried unless you are an experienced C programmer.

    -------------------------------------------------------------------

    version 1
	Fixed bug in open if error occurs openning librariies... accidently
	put garbage into A7 before returning.  Oops

    version 0
	Initial release of example


