
				DYNAMIC.DOC

dynamic.library/overview.dynamic
dynamic.library/GetHyperSymbol
dynamic.library/RelsHyperSymbol
dynamic.library/FlushHyperLib
dynamic.library/LockHyperLib
dynamic.library/UnLockHyperLib
dynamic.library/ScanHyperLib
dynamic.library/DumpHyperLibStatus
dynamic.library/SetHyperDebug

dynamic.library/overview.dynamic	    dynamic.library/overview.dynamic

    DYNAMIC.LIBRARY is a shared library which provides dynamic object
    linking and loading.  When a program requests a variable or procedural
    symbol the library will dynamically load the appropriate object module
    into memory.  Furthermore, the library will load any additional
    object modules required for the requested one to function, thereby
    providing a linking capability.

    The library fully tracks all object modules, the FlushHyperLib()
    call will not flush currently active modules.  The library will
    automatically link and load any object module or JOIN type library in
    the DO: directory. DO: is usually an assignment.  This capability will
    be expanded to a general path in future versions of the library.

    Object modules and libraries in the DO: directory MUST be compiled with
    the large code and large data models.  They MUST be reentrant, which
    means handling any global variables in a non-destructive manner when
    called simultaniously from different programs.  This generally means
    semaphores.

    Any given object module may define two special routines:

	long
	_auto_start()
	{
	    ...
	}

	void
	_auto_exit()
	{
	    ...
	}

    These are both optional.  When a module is completely linked and loaded
    the _auto_start() vector will automatically be called by dynamic.library
    in an atomic fashion (i.e. while it holds a semaphore).  This code is
    meant to initialize various aspects of the object module.  For example,
    an object module whos sole purpose is to open "dos.library" would
    declare DOSBase and it's _auto_start() code would then open the library
    and initialize the base variable.  _auto_start() returns 1 on success,
    0 on failure.

    A failure code causes the object module to be unloaded and modules that
    rely on it to fail as well, eventually propogating back to the library
    call that started it all.

    The _auto_exit() procedure, if it exists, is called just before an
    object module is unloaded.	Using the same example, this procedure
    would close the "dos.library".

    NOTE: THE _auto_exit() PROCEDURE, IF IT EXISTS, IS CALLED EVEN IF
    _auto_start() FAILS.  This is actually a feature if you think about
    it, _auto_start() need not back-out of its initialization if an error
    occurs, instead letting _auto_exit() deal with it.  However, you some
    precautions must be taken.	Here is the full example:

/*
 *  DOS.C   dos.library support
 */

#include <exec/types.h>
#include <exec/libraries.h>
#include <clib/exec_protos.h>

typedef struct Library Library;

Library *hyper_DOSBase;

long
_auto_start()
{
    if (hyper_DOSBase = OpenLibrary("dos.library", 0))
	return(1);
    return(0);
}

void
_auto_exit()
{
    if (hyper_DOSBase) {
	CloseLibrary(hyper_DOSBase);
	hyper_DOSBase = NULL;
    }
}

    Any symbol in the object module that is to be exported (made available
    to other object modules) must be declared 'hyper_<symbol>'.  The
    modules that reference this symbol reference it normally.  In the
    example above you will note that while DOSBase is declared
    hyper_DOSBase, the startup code still calls 'OpenLibrary' to open the
    library, NOT hyper_OpenLibrary().

    This ensures that only the symbols the programmer wants to be exported
    will be exported.

    _auto_start() and _auto_exit() are special cases as they are dealt with
    by the library directly.

    Since a reference count is kept for each object module's dependancy on
    other object modules, unloading is guarenteed to occur in reverse
    dependancy order, meaning that a module like the above would be unloaded
    last .. almost last, OpenLibrary() and CloseLibrary() would be unloaded
    after the above example, with the module associated with SysBase
    unloaded at the very last.

				  DICE SUPPORT

    As of the next release of DICE, direct compiler support of this
    library will exist.  DICE is not required, but if the idea catches
    on other compilers might follow suite.  The DICE support consists of
    a new storage qualifier called __dynamic.  Declaring a variable
    __dynamic basically tells DICE that this variable exists externally
    (i.e. doesn't exist at link time).  DICE will actually declare storage
    for a pointer and the dynamically determine the pointer to the
    storage/procedure at program run time.  A failure causes an error
    message to be output and the program to exit before _main is called.

    DICE silently generates an indirection for all references to the
    variable thus making operation almost entirely transparent.  An
    example program follows:


/*
 *  DOS.C
 */

__dynamic void DosTest(void);

main()
{
    printf("DosTest is loaded as: %08lx\n", DosTest);
    DosTest();
    puts("That's it!");
    return(0);
}

    Pretty easy eh?  Variables may be declared in the same manner to
    reference shared globals loaded via the library.  This is an excellent
    way to program a shared global semaphore, for example, without the
    hassel.  The _auto_start() code in the object module declaring the
    semaphore would initialize it, thus nothing need be done by the
    calling program except Obtain and Release it.

    The only cavet is that in terms of the DICE support, you must declare
    the procedure/variable as non-extern __dynamic just once.  All other
    declarations MUST have the extern storage qualifier.  You may not
    reference a dynamic variable/procedure unless it is prototyped as
    a dyamic variable/procedure.  Not too much of a cavet.

    Note that you can load / release dynamic symbols via the dynamic.library
    calls at any time.	The __dynamic storage qualifier will do all loading
    at startup and unloading at exit but you are not limited to this type
    of operation run-time, simply make the library calls yourself if you
    need truely dynamic loading.

			      CURRENT LIMITATIONS

	* object modules must be compiled large-data + large-code.
	  This may stick around for a long while.  It actually isn't
	  much of a problem since object modules are expected to have
	  library-style reentrancy (so their code can be shared).

	  Since object modules are not loaded into the same memory block
	  supporting small-code is pretty useless since it would require
	  a jump table anyway, and small-data would require a separate A4
	  pointer for each object module and tag code to load it, slowing
	  down interface calls to a great degree (at this point interface
	  calls basically direct calls to the loaded module)

    NEWLY IMPLEMENTED

	  full support for CHIP hunks and JOIN style libraries exists.

    FUTURE TRENDS

	The tags are definitely going to be used.  For one, there is no
	current way to specify *which* procedure you want to use when
	several object modules contain the same procedure (i.e. in terms
	of one overriding the other).  (see below)

	more as I think of it ..  comments are welcome!

    UTILITIES

	A new FDTOLIB (a DICE utility) is included and now has the capability
	to generate hyper_* library tags from .FD files.  You also need the
	DICE DAS (also included) to run FDTOLIB.



dynamic.library/GetHyperSymbol		    dynamic.library/GetHyperSymbol

    NAME
	GetHyperSymbol - get pointer to external object module symbol

    SYNOPSIS
	#include <dynamic.h>

	void *ptr = GetHyperSymbol(symName, tagPtr);
	void *ptr = GetHyperSymbolTags(symName, Tag tag1, ...);

	const char *symName;
	TagItem *tagPtr;

    FUNCTION
	GetHyperSymbol() searches for the specified symbol amount object
	files in the DO: directory.  When found, the object module in
	question will be loaded (or may already be loaded).  An object
	module that references other object modules will cause the
	others to be brought in as well, and so on until all external
	references are resolved.

	NOTE that the object module is NOT linked to the caller's code in
	any way (i.e. no dynamic linking to the caller's code via the
	caller's symbol table).  The two main reasons this is not done
	are:  (1) caller may not have a symbol table or may be resident,
	(2) object modules cannot be reentrant / tracking becomes impossible.

	GetHyperSymbol() may be used to retrieve a pointer to a procedure
	or variable.

	When you GetHyperSymbol() some symbol name, such as "_fubar", the
	actual exported symbol in the object module must be '_hyper_fubar'.
	Remember that C generally sticks the first underscore on itself,
	please refer to the example code for appropriate usage.

	If an object module in DO: references a symbol _xx defined in some
	other object module, the definition in the other object module
	must be _hyper_xx.  Again, see the examples.

	You can use SetHyperDebug() or the HDEBUG utility program to
	enable library debugging to determine why a complex symbol request
	has failed (i.e. brings up many object modules)

    INPUTS
	const char *symName;	    pointer to the full symbol name,
				    (including any underscores)

	TagItem *tagPtr;	    pointer to a tag list, must currently
				    be set to NULL.  If using the var-args
				    call you must terminate the list
				    with TAG_END.


    RESULTS
	void *ptr;		    pointer to the procedure / variable
				    requested or NULL

dynamic.library/RelsHyperSymbol 	    dynamic.library/RelsHyperSymbol

    NAME
	RelsHyperSymbol - release pointer to external object module symbol

    SYNOPSIS
	#include <dynamic.h>

	(void) RelsHyperSymbol(ptr, tagPtr);
	(void) RelsHyperSymbolTags(ptr, Tag tag1, ...);

	void *ptr;
	TagItem *tagPtr;

    FUNCTION

	releases the procedure or variable reference obtained by
	GetHyperSymbol*().  You must call RelsHyperSymbol*() to release
	a loaded object module by the pointer returned by Get*().
	If you have called GetHyperSymbol*() multiple times for the
	same symbol you must call RelsHyperSymbol*() an equivalent
	number of times to release it.

	DICE's __dynamic keyword support automatically calls Get*() and
	Rels*() routines for you, making operation nearly transparent.

    INPUTS
	void *ptr;		Pointer previously obtained by
				GetHyperSymbol*().  NULL may be safely
				passed and results in a no-operation.

	TagItem *tagPtr;	Currently not used, tagPtr must be set to
	(or taglist)            NULL.  If the var-args routine is used it
				must be immediately terminated with TAG_END.

    RESULTS
	none


dynamic.library/FlushHyperLib		    dynamic.library/FlushHyperLib

	void FlushHyperLib(void);

    FUNCTION

	Flushes any loaded object modules that are not currently being
	referenced.  Also sets a rescan flag for the DO: directory.  This
	function is normally called when the user installs or changes
	object files in the DO: directory.

	Currently the library will not deinstall loaded modules not in
	use automatically, you have to make this call to free up unused
	loaded modules.

dynamic.library/LockHyperLib			dynamic.library/LockHyperLib

    NAME
	LockHyperLib - obtain the library's master semaphore

    SYNOPSIS
	#include <dynamic.h>

	void LockHyperLib(void)

    FUNCTION
	This function obtains the exclusive semaphore used by the library
	to ensure non-simultanious access.  It effectively blocks all
	library calls except those made by the task that has obtained
	the semaphore through this call.

	You may obtain this semaphore multiple times, and must release
	the semaphore the same number of times.

dynamic.library/UnLockHyperLib			dynamic.library/UnLockHyperLib

    NAME
	UnLockHyperLib - release semapohre obtained with LockHyperLib

    SYNOPSIS
	#include <dynamic.h>

	void UnLockHyperLib(void)

    FUNCTION
	This function releases the library's semaphore.  You must have
	previously obtained the semaphore.


dynamic.library/DumpHyperLibStatus	  dynamic.library/DumpHyperLibStatus

    NAME
	DumpDynamicLibStatus - make an ascii dump of the library's status

    SYNOPSIS
	#include <dynamic.h>

	void DumpDynamicLibStatus(fh, verbose)
	BPTR fh;
	long verbose;

    FUNCTION
	This function generates an ascii dump of the library's current
	status.  The verbosity level determines how much to dump.

	verbose = 0	dump only the library headers and active object
			module information

	verbose = 1	additionally, dump all library symbols whether
			they are active or not.  However, libraries with
			more than 50 symbols are not dumped.

	verbose = 2	dump all library symbols, period.

	Note that specifying a verbosity of 2 may take upwards of minutes
	to run if you have a large library installed in DO:, such as
	amiga.lib.  This is due to the fact that to display actual symbol
	names the system must go to disk.  It is not desireable for the
	library to load all symbols into memory due to the number of
	symbols that could be involved.  Instead, the library loads a
	much smaller hash table of hash values, bring symbol names in
	only on a cache basis.

    INPUTS
	BPTR fh;	    file handle to dump to.  You may specify NULL
			    to dump to Output().

	long verbose	    verbosity level, 0, 1, or 2 currently.


    RESULTS
	void *ptr;		    pointer to the procedure / variable
				    requested or NULL


dynamic.library/SetHyperDebug		    dynamic.library/SetHyperDebug

    NAME
	SetHyperDebug - set debugging mode to find load errors

    SYNOPSIS
	#include <dynamic.h>

	void SetHyperDebug(fh, level)
	BPTR fh;
	long level;

    FUNCTION
	This function enables printing of error messages to the file
	handle specified.  Specifying a file handle of NULL *disables*
	printing.  You also specify a debug level, you must specify a
	debug level of 1 to enable error messaging printing as well.

	Normally you call SetHyperDebug(Output(), 1); to generate error
	messages to the CLI.  The CLI must not be closed while
	dynamic.library has it's file handle installed!

	Currently the library will generate an error message for any
	symbol it cannot find, making debugging a bit easier.  If
	the library reports being unable to reference a symbol and the
	_hyper_<symbol> does exist, then the object module in question
	most likely attempts to do relocations that the library cannot
	handle.  Currently only large-data, large-code, and absolute
	symbol relocation (e.g. LVO symbols) is supported.

    INPUTS
	BPTR fh;	    file handle to dump to, NULL to uninstall.

	long verbose	    debug level, 0 or 1 currently.

dynamic.library/ScanHyperLib		  dynamic.library/ScanHyperLib

    NAME
	ScanHyperLib - causes the library to rescan DO:

    SYNOPSIS
	#include <dynamic.h>

	void ScanHyperLib(void)

    FUNCTION
	This function causes the library to rescan DO:	Any new or modified
	object modules that are not currently referenced will be rescanned.

    BUGS
	Currently this function doesn't delete it's symbol list for object
	modules you have deleted or renamed.  The workaround is to call
	FlushHyperLib().




