home *** CD-ROM | disk | FTP | other *** search
/ Speccy ClassiX 1998 / Speccy ClassiX 98.iso / amiga_system / the_aminet / dev / c / asyncio.lha / AsyncIO / src / Lib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-09-13  |  5.9 KB  |  231 lines

  1. /* LIB.C
  2.  *
  3.  * Basic Library Resource Handling
  4.  *
  5.  * This code is based on the example shared library,
  6.  * found on the DICE 3.0 disks.
  7.  *
  8.  * This code doesn't use any form of startup code (the example does).
  9.  * This is not something the novice C-programmer should attemt.
  10.  * You need to know what you are doing. :)
  11.  */
  12.  
  13. #include "async.h"
  14. #include <exec/libraries.h>
  15. #include <exec/resident.h>
  16. #include "rev.h"
  17.  
  18. #include <clib/asyncio_protos.h>
  19.  
  20.  
  21. LibCall struct Library *LibInit( _REG( d0 ) struct Library *, _REG( a0 ) APTR, _REG( a6 ) struct ExecBase * );
  22. struct Library *LibOpen( _REG( a6 ) struct Library * );
  23. APTR LibClose( _REG( a6 ) struct Library * );
  24. APTR LibExpunge( _REG( a6 ) struct Library * );
  25.  
  26. /* Due to a bug in the linker, we must have some initialized data.
  27.  * If not, the linker will not produce any smalldata section.
  28.  * By giving one of the fields a value, this problems is solved.
  29.  *
  30.  * The other variables will be cleared, since "The memory used for
  31.  * bss blocks is zeroed by the loader when it is allocated" (quote
  32.  * from the AmigaDOS manual).
  33.  */
  34. struct Library        *LibBase = NULL;    /* Our library structure */
  35. struct ExecBase        *SysBase;
  36. struct Library        *UtilityBase;
  37. struct DosLibrary    *DOSBase;
  38. APTR            SegList;
  39.  
  40.  
  41. /* In case the user tries to run us, simply exit immediately.
  42.  * This code is also used for the reserved library function,
  43.  * that all libraries currently must have.
  44.  *
  45.  * Note that this function *must* be placed before any const
  46.  * data, or else the "exit if run" effect is lost.
  47.  *
  48.  * We also use this code for the "reserved" standard library entry.
  49.  */
  50. LONG
  51. LibReserved( VOID )
  52. {
  53.     return( 0 );
  54. }
  55.  
  56.  
  57. /* The functions the library should have. Unfortunately, we can't
  58.  * use the more "compact" format, using 16-bit relative entries,
  59.  * due to the compiler (bug or limitation ;).
  60.  */
  61. const APTR FuncTable[] =
  62. {
  63.     LibOpen,    /* Standard library functions */
  64.     LibClose,
  65.     LibExpunge,
  66.     LibReserved,
  67.  
  68.     OpenAsync,    /* Our functions start here */
  69.     OpenAsyncFromFH,
  70.     CloseAsync,
  71.     SeekAsync,
  72.     ReadAsync,
  73.     WriteAsync,
  74.     ReadCharAsync,
  75.     WriteCharAsync,
  76.  
  77.     ( APTR ) -1    /* Terminate the table */
  78. };
  79.  
  80.  
  81. /* Table describing the library. We need this, since we use the
  82.  * autoinit feature. This means we don't need to call MakeLibrary()
  83.  * etc. in LibInit.
  84.  */
  85. const ULONG InitTable[] =
  86. {
  87.     sizeof( struct Library ),    /* Size of our library base, excluding jump table */
  88.     ( ULONG ) FuncTable,        /* The functions we have */
  89.     NULL,                /* InitStruct data. We init stuff ourselves instead */
  90.     ( ULONG ) LibInit        /* The library init function */
  91. };
  92.  
  93.  
  94. const TEXT LibName[] = "asyncio.library";
  95. const TEXT LibId[] = "asyncio.library "VERSION" (" DATE ")\r\n";
  96.  
  97.  
  98. /* And finaly the resident structure, used by InitResident(),
  99.  * in order to initialize everything
  100.  */
  101. const struct Resident RomTag =
  102. {
  103.     RTC_MATCHWORD,    /* rt_MatchWord */
  104.     &RomTag,    /* rt_MatchTag */
  105.     LibExpunge,    /* rt_EndSkip */
  106.     RTF_AUTOINIT,    /* rt_Flags */
  107.     VERNUM,        /* rt_Version */
  108.     NT_LIBRARY,    /* rt_Type */
  109.     0,        /* rt_Pri */
  110.     LibName,    /* rt_Name */
  111.     LibId,        /* rt_IDString */
  112.     InitTable    /* rt_Init */
  113. };
  114.  
  115.  
  116. /* This small function is a generic library structure freer. */
  117. VOID
  118. FreeLib( struct Library *lib )
  119. {
  120.     FreeMem( ( UBYTE * ) lib - lib->lib_NegSize, lib->lib_NegSize + lib->lib_PosSize );
  121. }
  122.  
  123.  
  124. /* This function is called when the library is loaded, and the library base
  125.  * is allocated. We are in a forbid section here, so don't do anything
  126.  * time-consuming, Wait() or similar.
  127.  *
  128.  * If all ok, return the library base. If anything went wrong, deallocate
  129.  * the library structure, and return NULL.
  130.  */
  131. LibCall struct Library *
  132. LibInit( _REG( d0 ) struct Library *lib, _REG( a0 ) APTR seglist, _REG( a6 ) struct ExecBase *sysBase )
  133. {
  134.     SysBase = sysBase;
  135.  
  136.     if( DOSBase = ( struct DOSLibrary * ) OpenLibrary( "dos.library", 37 ) )
  137.     {
  138.         if( UtilityBase = OpenLibrary( "utility.library", 37 ) )
  139.         {
  140.             lib->lib_Node.ln_Type    = NT_LIBRARY;
  141.             lib->lib_Node.ln_Pri    = 0;
  142.             lib->lib_Node.ln_Name    = LibName;
  143.             lib->lib_Flags        = LIBF_CHANGED | LIBF_SUMUSED;
  144.             lib->lib_Version    = VERNUM;
  145.             lib->lib_Revision    = REVNUM;
  146.             lib->lib_IdString    = ( APTR ) LibId;
  147.             SegList = seglist;
  148.         }
  149.         else
  150.         {
  151.             CloseLibrary( ( struct Library * ) DOSBase );
  152.             FreeLib( lib );
  153.             return( NULL );
  154.         }
  155.     }
  156.     else
  157.     {
  158.         FreeLib( lib );
  159.         return( NULL );
  160.     }
  161.  
  162.     return( lib );
  163. }
  164.  
  165.  
  166. /* Open is given the library pointer. Either return the library pointer or NULL.
  167.  * Remove the DELAYED-EXPUNGE flag. Exec has Forbid() for us during the call.
  168.  */
  169. struct Library *
  170. LibOpen( _REG( a6 ) struct Library *lib )
  171. {
  172.     ++lib->lib_OpenCnt;
  173.     lib->lib_Flags &= ~LIBF_DELEXP;
  174.     return( lib );
  175. }
  176.  
  177.  
  178. /* Close is given the library pointer. Be sure not to decrement the open
  179.  * count if already zero. If the open count is or becomes zero AND there
  180.  * is a LIBF_DELEXP, we expunge the library and return the seglist.
  181.  * Otherwise we return NULL.
  182.  *
  183.  * Note that this routine never sets LIBF_DELEXP on its own.
  184.  *
  185.  * Exec has Forbid() for us during the call.
  186.  */
  187. APTR
  188. LibClose( _REG( a6 ) struct Library *lib )
  189. {
  190.     if( lib->lib_OpenCnt && --lib->lib_OpenCnt )
  191.     {
  192.         return( NULL );
  193.     }
  194.  
  195.     if( lib->lib_Flags & LIBF_DELEXP )
  196.     {
  197.         return( LibExpunge( lib ) );
  198.     }
  199.  
  200.     return( NULL );
  201. }
  202.  
  203.  
  204. /* We expunge the library and return the Seglist ONLY if the open count is zero.
  205.  * If the open count is not zero we set the DELAYED-EXPUNGE flag and return NULL.
  206.  *
  207.  * Exec has Forbid() for us during the call. NOTE ALSO that Expunge might be
  208.  * called from the memory allocator and thus we CANNOT DO A Wait() or otherwise
  209.  * take a long time to complete (straight from RKM).
  210.  *
  211.  * Apparently RemLibrary( lib ) calls our expunge routine and would therefore
  212.  * freeze if we called it ourselves. As far as I can tell from RKM,
  213.  * LibExpunge( lib ) must remove the library itself as shown below.
  214.  */
  215. LibCall APTR
  216. LibExpunge( _REG( a6 ) struct Library *lib )
  217. {
  218.     if( lib->lib_OpenCnt )
  219.     {
  220.         lib->lib_Flags |= LIBF_DELEXP;
  221.         return( NULL );
  222.     }
  223.  
  224.     Remove( &lib->lib_Node );
  225.     FreeLib( lib );
  226.     CloseLibrary( ( struct Library * ) DOSBase );
  227.     CloseLibrary( UtilityBase );
  228.  
  229.     return( SegList );
  230. }
  231.