Admin Panel

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