home *** CD-ROM | disk | FTP | other *** search
- /* Library.c
- * Routines required in all shared libraries.
- * Copyright 1986 by James M Synge.
- */
-
- #include "exec/types.h"
- #include "exec/libraries.h"
- #include "ExtLibrary.h"
- #include "libraries/dos.h"
-
- /* Declare the name of the library */
-
- char LibraryName[] = "task.library";
- char LibraryId[] =
- "task.library V1.0 (25 May 1987)\015\012";
-
- #define LIB_VERSION 1
- #define LIB_REVISION 2
-
- /*
- * This short assembler section is included here so that
- * there is just one small place where these numbers need to
- * be replaced, instead of in two different files (i.e. here
- * and LibHead.asm).
- */
-
- #asm
- PUBLIC LibVersion
- PUBLIC LibRevision
- LibVersion EQU 1 ; Shared with libhead via
- LibRevision EQU 2 ; the PUBLIC statement
- #endasm
-
- /*
- * If the rt_Flags field of the RomTag (struct Resident) has
- * the AUTOINIT bit set, then the rt_Init field must point
- * to a block such the following LibInitBlock. This block
- * contains four of the five parameters which OpenLibrary()
- * will pass to MakeLibrary. (The fifth parameter is the
- * SegList.) If the AUTOINIT bit is not set, then the
- * rt_Init field must point to a routine which will perform
- * the equivalent initialization.
- *
- * When the library is being auto-initialized, a block of
- * memory is allocated by MakeLibrary(). Its size is
- * determined by the length of FunctionList (in Functions.c)
- * and an entry, lib_sizeof_ExtLibrary, in the structure
- * pointed to by rt_Init. That entry is the size in bytes
- * of the struct ExtLibrary to be allocated automatically,
- * before calling the routine whose address is in
- * lib_InitCode. So, this value must be known before
- * linking.
- *
- * This can be done by expressing the LibInitBlock structure
- * in C so that the compiler can determine the size for us.
- * This is a drastic improvement over figuring it out by
- * hand!
- */
-
- extern long *FunctionList[];
- void _LibInitCode();
-
- struct {
-
- long lib_sizeof_ExtLibrary; /* Bytes to allocate */
- APTR lib_FunctionList; /* Ptr to func list */
- long lib_InitStruct; /* see initializers.i */
- APTR lib_InitCode; /* Ptr to asm routine */
-
- } LibInitBlock = {
-
- sizeof( struct ExtLibrary ),
- (APTR) FunctionList,
- 0L, /* No struct init */
- (APTR) _LibInitCode
-
- };
-
- /* The assembly routine _LibInitCode calls LibraryInit() to
- * complete the initialization of the library.
- */
- struct ExtLibrary *
- LibraryInit( LibBasePtr )
-
- struct ExtLibrary *LibBasePtr;
- {
- /* These initializations are done here because it is
- * difficult to build an initializer structure with
- * Aztec Assembler 3.2. The argument, the library
- * pointer, is pushed onto the stack by the
- * assembler routine _LibInitCode.
- */
-
- LibBasePtr -> el_Node.ln_Type = NT_LIBRARY;
- LibBasePtr -> el_Node.ln_Name = LibraryName;
- LibBasePtr -> el_Version = LIB_VERSION;
- LibBasePtr -> el_Revision = LIB_REVISION;
- LibBasePtr -> el_IdString = (APTR) LibraryId;
-
- /* Now set up the initial values for my libraries'
- * variables.
- */
-
- /* NONE IN THIS EXAMPLE!!! */
-
- return LibBasePtr; /* This is the value which
- * will be returned to
- * MakeLibrary()
- */
- }
-
- /*
- * The required routines Open, Close and Expunge are called
- * not by other C routines, but rather by Exec. This means
- * that their arguments are in registers instead of on the
- * stack.
- *
- * There are three straight forward options at this point:
- *
- * 1) Use the variable LibraryBase (see LibHead.asm) which
- * should contain the same value as that in A6.
- *
- * 2) Immediately call the routine regA6() in LibHead.asm
- * which will return the value in A6 (Should be the
- * Library Base Pointer). This requires that we can be
- * certain that A6 hasn't been wiped out already by the
- * compiler generated setup code.
- *
- * 3) Place an intermediate assembly routine between exec
- * and each C routine which moves the arguments,
- * including the Library Base Pointer, from the
- * registers to the stack.
- *
- * The last method seems the best, so we'll use it.
- */
-
- struct ExtLibrary *
- Library_Open( LibBasePtr, Version )
-
- struct ExtLibrary *LibBasePtr; /* Was in A6 */
- long Version; /* Was in D0 */
- {
- Forbid();
-
- /* Note that another open has occured. */
- LibBasePtr->el_OpenCnt ++;
-
- /* Since we know that there is at least one user of
- * this library, we'll ignore any previous call to
- * Library_Expunge.
- */
-
- LibBasePtr->el_Flags &= ~LIBF_DELEXP;
-
- Permit();
-
- return LibBasePtr;
- }
-
- /* When the memory allocator in exec.library is looking for
- * more memory, it will try to get rid of the memory used by
- * libraries, devices and fonts. To do this with a library,
- * it calls Library_Expunge, the third of the required
- * routines. If Library_Expunge returns zero, then the
- * memory allocator looks elsewhere. If it returns non-zero
- * then the value must be a pointer to an AmigaDOS SegList.
- * This will be placed on the free list by the memory
- * allocator. It is the responsibility of the library to
- * free the jump table and Library structure.
- */
-
- extern BPTR LibSegList; /* Allocated in LibHead.asm */
-
- BPTR
- Library_Expunge( LibBasePtr )
-
- struct ExtLibrary * LibBasePtr; /* Was in A6 */
- {
- unsigned long size, JumpTableBase;
-
- /* The memory allocator runs inside a Forbid() /
- * Permit() pair. To protect against being called
- * by somebody else (i.e. Library_Close).
- */
-
- Forbid ();
-
- if (LibBasePtr->el_OpenCnt > 0) {
- /* Still open, so note the expunge for
- * later use in Library_Close.
- */
- LibBasePtr->el_Flags |= LIBF_DELEXP;
- Permit ();
- return 0;
- }
-
- /* Remove the library from the exec library list
- * so that nobody tries to allocate the library.
- */
-
- Remove( LibBasePtr );
-
- /* Now free up the jump table and library structure.
- * We add the sizes of the two (lib_NegSize is the
- * size of the jump table, and lib_PosSize is the
- * size of struct ExtLibrary), then free the block
- * starting at the base of the jump table.
- */
-
- size = (long)(LibBasePtr->el_NegSize)
- + (long)(LibBasePtr->el_PosSize);
-
- if ( size ) {
- JumpTableBase = (long) LibBasePtr -
- (long) (LibBasePtr->el_NegSize);
-
- FreeMem( JumpTableBase, size );
- }
-
- Permit();
-
- return LibSegList;
- }
-
- /* When the exec routine CloseLibrary() is called, it calls
- * the required Close() routine of the identified library.
- * That routine is implemented here by Library_Close. It
- * decrements the open count. If it is zero, and if the
- * delayed expunge flags is set, then Library_Expunge() is
- * called. Just as in the case of the Expunge routine, if
- * a non-zero value is returned, it must be a BPTR to an
- * AmigaDOS SegList.
- */
-
- BPTR
- Library_Close( LibBasePtr )
-
- struct ExtLibrary * LibBasePtr; /* Was in A6 */
- {
- Forbid(); /* Have to be cautious when there's
- * not much documentation. */
- LibBasePtr->el_OpenCnt -- ; /* Decrement */
- Permit();
-
- if (LibBasePtr->el_OpenCnt == 0)
- if ((LibBasePtr->el_Flags & LIBF_DELEXP) != 0)
- return Library_Expunge();
-
- return 0; /* No expunge. */
- }
-
- /* Now for the big routine!
- */
- long Library_Reserved()
- {
- return(0L);
- }
-