/******************************************************************************/ /* */ /* our include */ /* */ /******************************************************************************/ #define EXTENDED /* multibase library! */ #include "libinit.h" /******************************************************************************/ /* */ /* *** FIRST *** function - prevents a crash when called from CLI! */ /* */ /******************************************************************************/ LONG safefail(VOID) { return -1; } /******************************************************************************/ /* */ /* a do nothing stub (required!) */ /* */ /******************************************************************************/ LONG LibExtFunc(VOID) { return 0; } /******************************************************************************/ /* */ /* remove library from memory if possible */ /* */ /* !!! CAUTION: This function runs in a forbidden state !!! */ /* */ /******************************************************************************/ LONG LibExpunge(REG(a6,__LIB lib)) { LONG SegList = 0; /* get 'real' base */ lib = lib->Parent; /* set delayed expunge flag */ lib->LibNode.lib_Flags |= LIBF_DELEXP; /* still in use? */ if (!lib->LibNode.lib_OpenCnt) { APTR SysBase = lib->SysBase; /* remove library from SysBase->LibList */ Remove((struct Node *)lib); /* return the seglist for UnLoadSeg() */ SegList = lib->SegList; /* free library */ FreeMem((UBYTE *)lib-lib->LibNode.lib_NegSize,lib->LibNode.lib_NegSize+lib->LibNode.lib_PosSize); } return SegList; } /******************************************************************************/ /* */ /* LibClose() will be called for every CloseLibrary() */ /* */ /* !!! CAUTION: This function runs in a forbidden state !!! */ /* */ /******************************************************************************/ LONG LibClose(REG(a6,__LIB lib)) { APTR SysBase = lib->SysBase; LONG SegList = 0; if (!--lib->Parent->LibNode.lib_OpenCnt && (lib->LibNode.lib_Flags & LIBF_DELEXP)) SegList = LibExpunge(lib); /* call user-exit */ __UserLibCleanup(lib->DataSeg); /* free library */ FreeMem((UBYTE *)lib-lib->LibNode.lib_NegSize,lib->LibNode.lib_NegSize+lib->LibNode.lib_PosSize); /* SegList or NULL (still in use) */ return SegList; } /******************************************************************************/ /* */ /* LibOpen() will be called for every OpenLibrary() */ /* */ /* !!! CAUTION: This function runs in a forbidden state !!! */ /* */ /******************************************************************************/ static __inline ULONG __DSize(void) { ULONG res; __asm("movel #___data_size,%0" : "=d" (res)); return res; } APTR LibOpen(REG(a6,__LIB lib)) { APTR dataseg, SysBase = lib->SysBase; __LIB child; /* any memory allocation can cause a call of THIS library expunge vector. if OpenCnt is zero the library might go away ... So fake a user :-) */ lib->LibNode.lib_OpenCnt++; /* create new library base */ if ((child=(__LIB)MakeLibrary(&__FuncTable__[1],NULL,(ULONG (*)())LibInit,sizeof(*lib)+lib->DataSize,0))) { LONG *relocs,numrel; /* one user */ child->LibNode.lib_OpenCnt++; /* copy dataseg */ CopyMem(child->DataSeg,dataseg=(UBYTE *)child+sizeof(*lib),__DSize()); /* relocate */ relocs = __datadata_relocs; if ((numrel=*relocs++)) { LONG dist = (LONG)child->DataSeg - (LONG)dataseg; do { *(LONG *)((LONG)dataseg + *relocs++) -= dist; } while (--numrel); } child->DataSeg = (dataseg=(UBYTE *)dataseg+0x7ffe); /* our 'real' parent */ child->Parent = lib; /* assume user-init won't fail */ lib->LibNode.lib_Flags &= LIBF_DELEXP; lib->LibNode.lib_OpenCnt++; /* now call user-init */ if (__UserLibInit(&child->LibNode,dataseg)) { FreeMem((UBYTE *)child-child->LibNode.lib_NegSize,child->LibNode.lib_NegSize+sizeof(*child)+child->DataSize); --lib->LibNode.lib_OpenCnt; child = NULL; } } /* end of expunge protection */ --lib->LibNode.lib_OpenCnt; return child; } /******************************************************************************/ /* */ /* initialization function called by MakeLibrary() */ /* */ /******************************************************************************/ void __restore_a4(void) { __asm("lea ___a4_init,a4"); } /******************************************************************************/ /* */ /* initialization function called by MakeLibrary() */ /* */ /******************************************************************************/ static __inline APTR __GetDataSeg(void) { APTR res; __asm("lea ___a4_init-0x7ffe,%0" : "=a" (res)); return res; } static __inline ULONG __GetDBSize(void) { ULONG res; __asm("movel #___data_size,%0; addl #___bss_size,%0" : "=d" (res)); return res; } APTR LibInit(REG(a0,LONG SegList),REG(d0,__LIB lib),REG(a6,struct Library *SysBase)) { /* set up header data */ lib->LibNode.lib_Node.ln_Type = NT_LIBRARY; lib->LibNode.lib_Node.ln_Name = (char *)LibName; lib->LibNode.lib_Flags = LIBF_CHANGED | LIBF_SUMUSED; lib->LibNode.lib_Version = (UWORD)LibVersion; lib->LibNode.lib_Revision = (UWORD)LibRevision; lib->LibNode.lib_IdString = (char *)LibIdString; /* setup private data */ lib->SegList = SegList; lib->SysBase = SysBase; lib->DataSeg = __GetDataSeg(); lib->DataSize = __GetDBSize(); lib->Parent = lib; /* this will be added to SysBase->LibList */ return lib; } /******************************************************************************/ /* */ /* autoinit table for use with initial MakeLibrary() */ /* */ /******************************************************************************/ static const APTR InitTab[] = { (APTR)sizeof(struct libBase), (APTR)&__LibTable__[1], (APTR)NULL, (APTR)&LibInit }; /******************************************************************************/ /* */ /* resident structure */ /* */ /******************************************************************************/ static const struct Resident RomTag = { RTC_MATCHWORD, (struct Resident *)&RomTag, (struct Resident *)&RomTag+1, RTF_AUTOINIT, 0, NT_LIBRARY, 0, (char *)LibName, (char *)LibIdString, (APTR)&InitTab }; /******************************************************************************/ /* */ /* add these functions to 'liblist' */ /* */ /******************************************************************************/ __attribute__((section(".list___FuncTable__,\"aw\""))) APTR __FuncTable__[] = {0}; ADD2LIST(LibOpen, __LibTable__,22); ADD2LIST(LibExtFunc,__LibTable__,22); ADD2LIST(LibExpunge,__LibTable__,22); ADD2LIST(LibExtFunc,__LibTable__,22); asm(".stabs \"___LibTable__\",20,0,0,-1"); /******************************************************************************/ /* */ /* add these functions to 'funclist' */ /* */ /******************************************************************************/ ADD2LIST(LibExtFunc,__FuncTable__,22); ADD2LIST(LibClose, __FuncTable__,22); ADD2LIST(LibExpunge,__FuncTable__,22); ADD2LIST(LibExtFunc,__FuncTable__,22); /******************************************************************************/ /* */ /* end of libinitr.c */ /* */ /******************************************************************************/