home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / biblioteki / c_library / easylibs / source / libheader.c < prev    next >
C/C++ Source or Header  |  1977-12-31  |  12KB  |  406 lines

  1. /*
  2.   LibHeader.c          Universal header file for libraries     V1.0
  3.   Copyright(C) 1994    Jochen Wiedmann
  4.  
  5.   This program is free software; you can redistribute it and/or modify
  6.   it under the terms of the GNU General Public License as published by
  7.   the Free Software Foundation; either version 2 of the License, or
  8.   (at your option) any later version.
  9.  
  10.   This program is distributed in the hope that it will be useful,
  11.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.   GNU General Public License for more details.
  14.   You should have received a copy of the GNU General Public License
  15.   along with this program; if not, write to the Free Software
  16.   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18.   $RCSfile: $
  19.   $Revision: $
  20.   $Date: $
  21.  
  22.   Computer: Amiga 1200
  23.   Compiler: Dice 3.01
  24.  
  25.   Author:     Jochen Wiedmann
  26.               Am Eisteich 9
  27.           72555 Metzingen
  28.           Germany
  29.           Phone: 07123 / 14881
  30.           Internet: wiedmann@zdv.uni-tuebingen.de
  31.  
  32.   This code implements the usual startup code of the library. I
  33.   recommend reading Appendix C (Sample Library Source Code) of the
  34.   RKM: Libraries, Third Edition for a complete understanding of the
  35.   following. Another good choice would be the shared library example
  36.   of the Dice distribution.
  37.  
  38.   Your library should be implmented in another file. You must define the
  39.   following preprocessor symbols with compiler options, when this file
  40.   is compiled:
  41.     LIBNAME:     Name of this library, "chess.library" for example
  42.     LIBVERSION:  Library version, "40" for example
  43.     LIBREVISION: Library revision, "1" for example
  44.  
  45.   The following preprocessor may be defined, but don't need to:
  46.     LIBINITFUNC:  Function to be called when the library is opened the
  47.                   first time to do library specific things. Will have the
  48.           library base pointer in register a6. (Default is no
  49.           library specific startup code.) This will typically open
  50.           other libraries or allocate some memory.
  51.     LIBOPENFUNC:  Function to be called every time the library is opened.
  52.                   Does not make much sense in most cases. (Default is no
  53.           library specific stuff.)
  54.     LIBCLOSEFUNC: Function to be called every time when CloseLibrary() is
  55.                   executed. This is the opponent to LIBCLOSEFUNC and does
  56.           not make much sense in most cases either. (Default is no
  57.           library specific stuff.)
  58.     LIBTERMFUNC:  Function to be called before the library is removed out
  59.                   of the RAM. This is the opponent to LIBINITFUNC and will
  60.           typically close other Libraries. (Default is no library
  61.           specific stuff.)
  62.     LIBBASESIZE:  Size of the library base, "sizeof(struct Library)" for
  63.                   example. (This is the default, if LIBBASESIZE isn't
  64.           defined.
  65.     LIBFUNCTABLE: Name of the function table. (Default LibFuncTable)
  66.  
  67.  
  68.  
  69.   WARNINGS - WARNINGS - WARNINGS - WARNINGS - WARNINGS - WARNINGS - WARNINGS
  70.     - This code depends heavily on some assumptions which are fulfilled
  71.       by Dice:
  72.         * All data declared as "const" will go to the code segment
  73.         * The compiler doesn't rearrange the order of the data and code
  74.           items.
  75.     - You may use uninialized data items in your library code. However,
  76.       the startup code will *not* clear the BSS segment. This means
  77.       that you must not depend on an uninitialized variable being zero!
  78.     - You may use the data and bss segment as usual. But remember that
  79.       this data will be global to the library and hence shared by all
  80.       users of the library. And don't forget to recreate the a4 register,
  81.       if you use such data items! (Usually by adding __saveds or
  82.       something similar to your functions.)
  83.  
  84.   EXAMPLE: To create the header of "chess.library", version 40.1 with library
  85.   specific routines InitChessLib and CloseChessLib, and a "struct
  86.   ChessLibBase" as library base you would do the following:
  87.  
  88.     dcc -DLIBNAME=chess.library -DLIBVERSION=40 -DLIBREVISION=1
  89.         -DLIBINITFUNC=InitChessLib -DLIBTERMFUNC=CloseChessLib
  90.     "-DLIBBASESIZE=sizeof(struct ChessLibBase)" -c ChessLib.c
  91. */
  92.  
  93.  
  94.  
  95.  
  96.  
  97. /****************************************************************************
  98.   Include files
  99. ****************************************************************************/
  100. #ifndef EXEC_TYPES_H
  101. #include <exec/types.h>
  102. #endif
  103. #ifndef EXEC_NODES_H
  104. #include <exec/nodes.h>
  105. #endif
  106. #ifndef EXEC_RESIDENT_H
  107. #include <exec/resident.h>
  108. #endif
  109. #ifndef EXEC_LIBRARIES_H
  110. #include <exec/libraries.h>
  111. #endif
  112. #ifndef EXEC_INITIALIZERS_H
  113. #include <exec/initializers.h>
  114. #endif
  115. #ifndef DOS_DOS_H
  116. #include <dos/dos.h>
  117. #endif
  118. #ifndef CLIB_EXEC_PROTOS_H
  119. #include <clib/exec_protos.h>
  120. #endif
  121. #ifndef PRAGMAS_EXEC_PRAGMAS_H
  122. #include <pragmas/exec_pragmas.h>
  123. #endif
  124.  
  125.  
  126.  
  127.  
  128.  
  129. /*****************************************************************************
  130.   Compiler specific stuff (Handling register arguments)
  131. *****************************************************************************/
  132. #if defined(_DCC)
  133. #define REG(x) __ ## x
  134. #define SAVEDS __geta4
  135. #define ASM
  136. #define REGARGS __regargs
  137. #else
  138. #if defined(__SASC)
  139. #define REG(x) register __ ## x
  140. #define SAVEDS __saveds
  141. #define ASM __asm
  142. #define REGARGS __regargs
  143. #else
  144. #error "Don't know how to handle register arguments for your compiler."
  145. #endif
  146. #endif
  147.  
  148.  
  149.  
  150. /*
  151.   This routine is an entry point if anyone might wish to run the library
  152.   as an executable.
  153. */
  154. STATIC LONG DummyStart(VOID){return(-1);}
  155.  
  156.  
  157.  
  158.  
  159.  
  160.  
  161. /****************************************************************************
  162.   Library name, ID and version string
  163. ****************************************************************************/
  164. #define S(x) #x
  165. const STATIC UBYTE LibName [] = S(LIBNAME);
  166. const STATIC UBYTE IdString [] = S(LIBNAME) " " S(LIBVERSION) "." \
  167.        S(LIBREVISION) " (" __DATE__ ")\r\n";
  168. const STATIC UBYTE VerString [] = "\0$VER:" S(LIBNAME) " " S(LIBVERSION) "." \
  169.        S(LIBREVISION) " (29.06.94)";
  170.  
  171.  
  172.  
  173.  
  174.  
  175.  
  176. /*****************************************************************************
  177.   The following table is used to initialize the library base. See
  178.   exec.library/InitStruct() and "exec/initializers.i" for details.
  179. *****************************************************************************/
  180. const STATIC UWORD DataTable[] =  { 0xa000 + (int) OFFSET(Node, ln_Type),
  181.                       NT_LIBRARY << 8,
  182.                     0x8000 + (int) OFFSET(Node, ln_Name)
  183.                   };
  184. const STATIC ULONG DataTable1[] = { (ULONG) LibName };
  185. const STATIC UWORD DataTable2[] = { 0xa000 + (int) OFFSET(Library, lib_Flags),
  186.                       (LIBF_SUMUSED|LIBF_CHANGED) << 8,
  187.                     0x9000 + (int) OFFSET(Library, lib_Version),
  188.                       LIBVERSION,
  189.                     0x9000 + (int) OFFSET(Library, lib_Revision),
  190.                       LIBREVISION,
  191.                     0x8000 + (int) OFFSET(Library, lib_IdString)
  192.                   };
  193. const STATIC ULONG DataTable3[] = { (ULONG) IdString,
  194.                     0
  195.                   };
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202. /****************************************************************************
  203.   The following table is expected to be at the beginning of any library.
  204. ****************************************************************************/
  205. extern APTR InitTable [];
  206. const STATIC struct Resident RomTag =
  207. {
  208.   RTC_MATCHWORD, /* ILLEGAL instruction, magic cookie to identify Resident
  209.             structure */
  210.   &RomTag,       /* Additional legality check */
  211.   &RomTag,       /* Where to continue looking for Resident structures */
  212.   RTF_AUTOINIT,  /* Easy initialization */
  213.   LIBVERSION,    /* Library version */
  214.   NT_LIBRARY,    /* type of module */
  215.   0,             /* Priority, don't use */
  216.   LibName,       /* library name */
  217.   IdString,      /* Id string */
  218.   InitTable      /* See below */
  219. };
  220.  
  221.  
  222.  
  223.  
  224.  
  225.  
  226. /*****************************************************************************
  227.   The following function will be called at startup.
  228.  
  229.   Inputs: LibPtr - pointer to the library base, initialized due to the
  230.                    specifications in DataTable
  231.       SegList - BPTR to the segment list
  232.       _SysBase - the usual ExecBase pointer
  233.  
  234.   Result: LibPtr, if all was okay and the library may be linked into the
  235.           system library list. NULL otherwise
  236. *****************************************************************************/
  237. STATIC BPTR MySegList;
  238. struct ExecBase *SysBase;
  239. SAVEDS ASM struct Library *_LibInit(REG(d0) struct Library *LibPtr,
  240.                     REG(a0) BPTR SegList,
  241.                     REG(a6) struct ExecBase *_SysBase)
  242.  
  243.   SysBase = _SysBase;
  244. #ifdef LIBINITFUNC
  245.   extern ULONG LIBINITFUNC(REG(a6) struct Library *);
  246. #endif
  247.   MySegList = SegList;
  248. #ifdef LIBINITFUNC
  249.   if (LIBINITFUNC(LibPtr))
  250.     {
  251.       return((BPTR) NULL);
  252.     }
  253. #endif
  254.  
  255.   return(LibPtr);
  256. }
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263. /****************************************************************************
  264.   The romtag specified that we were RTF_AUTOINIT. This means that rt_Init
  265.   points to the table below. (Without RTF_AUTOINIT it would point to a
  266.   routine to run.)
  267. ****************************************************************************/
  268. #ifndef LIBBASESIZE
  269. #define LIBBASESIZE sizeof(struct Library)
  270. #endif
  271.  
  272. #ifndef LIBFUNCTABLE
  273. #define LIBFUNCTABLE LibFuncTable
  274. #endif
  275.  
  276.  
  277.  
  278.  
  279.  
  280.  
  281.  
  282. /****************************************************************************
  283.   The following functions are called from exec.library/OpenLibrary(),
  284.   exec.library/CloseLibrary() and exec.library/ExpungeLibrary(),
  285.   respectively.
  286.  
  287.   Exec puts the library base pointer in a6 and turns off task switching
  288.   while they are executed, so we should not wait too long inside.
  289. ****************************************************************************/
  290.  
  291. /*
  292.   This function is called from exec.library/OpenLibrary().
  293.  
  294.   Inputs: LibPtr - pointer to the library base
  295.           Version - the suggested version number
  296.  
  297.   Result: LibPtr, if successful, NULL otherwise
  298. */
  299. ASM struct Library *_LibOpen(REG(a6) struct Library *LibPtr,
  300.                  REG(d0) ULONG Version)
  301. {
  302. #ifdef LIBOPENFUNC
  303.   extern ULONG LIBOPENFUNC(REG(a6) struct Library *);
  304. #endif
  305.  
  306.   ++LibPtr->lib_OpenCnt;
  307.   LibPtr->lib_Flags &= ~LIBF_DELEXP; /* Prevent delayed expunge */
  308.  
  309.   /* Library specific initialization */
  310. #ifdef LIBOPENFUNC
  311.   extern ULONG LIBOPENFUNC(LibPtr);
  312. #endif
  313.  
  314.   return(LibPtr);
  315. }
  316.  
  317.  
  318.  
  319.  
  320. /*
  321.   This function is called from exec.library/RemoveLibrary().
  322.  
  323.   Inputs: LibPtr - pointer to the library base.
  324.  
  325.   Result: Segment list of the library (see arguments of _LibInit()),
  326.           if the library isn't opened currently, NULL otherwise.
  327. */
  328. SAVEDS ASM BPTR _LibExpunge(REG(a6) struct Library *LibPtr)
  329.  
  330. {
  331. #ifdef LIBTERMFUNC
  332.   extern VOID LIBTERMFUNC(REG(a6) struct Library *);
  333. #endif
  334.   if (LibPtr->lib_OpenCnt)
  335.     { LibPtr->lib_Flags |= LIBF_DELEXP;
  336.       return((BPTR) NULL);
  337.     }
  338.  
  339.   /* Library specific cleanup. */
  340. #ifdef LIBTERMFUNC
  341.   LIBTERMFUNC(LibPtr);
  342. #endif
  343.  
  344.   /* Remove the library from the library list. */
  345.   Remove((struct Node *) LibPtr);
  346.  
  347.   return(MySegList);
  348. }
  349.  
  350.  
  351.  
  352.  
  353.  
  354. /*
  355.   This function is called from exec/CloseLibrary().
  356.  
  357.   Inputs: LibPtr - pointer to the library base as returned from
  358.                    OpenLibrary().
  359.  
  360.   Result: Segment list of the library (see arguments of _LibInit), if there
  361.           was a delayed expunge and the library is no longer open, NULL
  362.       otherwise.
  363. */
  364. ASM BPTR _LibClose(REG(a6) struct Library *LibPtr)
  365.  
  366. {
  367. #ifdef LIBCLOSEFUNC
  368.   extern VOID LIBCLOSEFUNC(REG(a6) struct Library *);
  369.  
  370.   LIBCLOSEFUNC(LibPtr);
  371. #endif
  372.  
  373.   if (!(--LibPtr->lib_OpenCnt)  &&  (LibPtr->lib_Flags & LIBF_DELEXP))
  374.     { return(_LibExpunge(LibPtr));
  375.     }
  376.   return((BPTR) NULL);
  377. }
  378.  
  379.  
  380.  
  381.  
  382.  
  383. /*
  384.   Dummy function to return 0.
  385. */
  386. ULONG _LibNull(VOID)
  387.  
  388. {
  389.   return(0);
  390. }
  391.  
  392.  
  393.  
  394.  
  395.  
  396. #include "LibFuncTable.c"
  397.  
  398. const APTR InitTable[4] =
  399. {
  400.   (APTR)LIBBASESIZE,  /* size of library base */
  401.   (APTR)LIBFUNCTABLE, /* library function table */
  402.   (APTR)DataTable,    /* library base initialization table */
  403.   (APTR)_LibInit,      /* function to call on startup */
  404. };
  405.