home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / dev / c / AsyncIO.lha / AsyncIO / src / Lib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-23  |  6.3 KB  |  238 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 to do.
  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. _ASM LibCall struct Library *LibInit( _REG( d0 ) struct Library *, _REG( a0 ) APTR, _REG( a6 ) struct ExecBase * );
  21. _ASM struct Library *LibOpen( _REG( a6 ) struct Library * );
  22. _ASM APTR LibClose( _REG( a6 ) struct Library * );
  23. _ASM APTR LibExpunge( _REG( a6 ) struct Library * );
  24.  
  25.  
  26. /* These variables will be zero, since "The memory used for bss
  27.  * blocks is zeroed by the loader when it is allocated" (quote
  28.  * from the AmigaDOS manual).
  29.  */
  30. struct Library        *AsyncIOBase;    /* Our library structure */
  31. struct ExecBase        *SysBase;
  32. struct Library        *UtilityBase;
  33. struct DosLibrary    *DOSBase;
  34. APTR            SegList;
  35.  
  36.  
  37. /* In case the user tries to run us, simply exit immediately.
  38.  * This code is also used for the reserved library function,
  39.  * that all libraries currently must have.
  40.  *
  41.  * Note that this function *must* be placed before any const
  42.  * data, or else the "exit if run" effect is lost (you are
  43.  * more likely to get a "crash if run" effect ;).
  44.  */
  45. LONG
  46. LibReserved( VOID )
  47. {
  48.     return( 0 );
  49. }
  50.  
  51.  
  52. /* The functions the library should have. Unfortunately, we can't
  53.  * use the more compact format, using 16-bit relative entries,
  54.  * due to the compiler (bug or limitation ;).
  55.  */
  56.  
  57. static const APTR FuncTable[] =
  58. {
  59.     LibOpen,    /* Standard library functions */
  60.     LibClose,
  61.     LibExpunge,
  62.     LibReserved,
  63.  
  64.     OpenAsync,    /* Our functions start here */
  65.     OpenAsyncFromFH,
  66.     CloseAsync,
  67.     SeekAsync,
  68.     ReadAsync,
  69.     WriteAsync,
  70.     ReadCharAsync,
  71.     WriteCharAsync,
  72.     ReadLineAsync,
  73.     WriteLineAsync,
  74.  
  75.     ( APTR ) -1    /* Terminate the table */
  76. };
  77.  
  78.  
  79. /* Table describing the library. We need this, since we use the
  80.  * autoinit feature. This means we don't need to call MakeLibrary()
  81.  * etc. in LibInit.
  82.  */
  83. static const ULONG InitTable[] =
  84. {
  85.     sizeof( struct Library ),    /* Size of our library base, excluding jump table. We have no extra data here */
  86.     ( ULONG ) FuncTable,        /* The functions we have */
  87.     NULL,                /* InitStruct data. We init stuff ourselves instead */
  88.     ( ULONG ) LibInit        /* The library init function */
  89. };
  90.  
  91.  
  92. static const TEXT LibId[] = "asyncio.library "VERSION" (" DATE ")\r\n";
  93. static const TEXT LibName[] = "asyncio.library";
  94.  
  95.  
  96. /* And finaly the resident structure, used by InitResident(),
  97.  * in order to initialize everything.
  98.  */
  99. static const struct Resident RomTag =
  100. {
  101.     RTC_MATCHWORD,        /* rt_MatchWord */
  102.     &RomTag,        /* rt_MatchTag */
  103.     LibExpunge,        /* rt_EndSkip */
  104.     RTF_AUTOINIT,        /* rt_Flags */
  105.     VERNUM,            /* rt_Version */
  106.     NT_LIBRARY,        /* rt_Type */
  107.     0,            /* rt_Pri */
  108.     LibName,        /* rt_Name */
  109.     LibId,            /* rt_IDString */
  110.     InitTable        /* rt_Init */
  111. };
  112.  
  113.  
  114. /* This small function frees the library structure,
  115.  * and any other allocated resources.
  116.  */
  117. static VOID
  118. FreeLib( struct Library *lib )
  119. {
  120.     if( DOSBase )    /* In case we are loaded under kick 35 or earlier */
  121.     {
  122.         CloseLibrary( ( struct Library * ) DOSBase );
  123.         CloseLibrary( UtilityBase );
  124.     }
  125.  
  126.     FreeMem( ( UBYTE * ) lib - lib->lib_NegSize, lib->lib_NegSize + lib->lib_PosSize );
  127. }
  128.  
  129.  
  130. /* This function is called when the library is loaded, and the library base
  131.  * have been allocated. We are in a forbid section here, so don't do anything
  132.  * time-consuming, Wait() or similar.
  133.  *
  134.  * If all ok, return the library base. If anything went wrong, deallocate
  135.  * the library structure, and return NULL.
  136.  */
  137. LibCall _ASM struct Library *
  138. LibInit( _REG( d0 ) struct Library *lib, _REG( a0 ) APTR seglist, _REG( a6 ) struct ExecBase *sysBase )
  139. {
  140.     SysBase = sysBase;
  141.  
  142.     /* Opening libraries in LibInit might not be a good idea under OS 1.x.
  143.      * Should be safe enough under 2.x and 3.x.
  144.      */
  145.     if( ( DOSBase = ( struct DosLibrary * ) OpenLibrary( "dos.library", 37 ) ) &&
  146.         ( UtilityBase = OpenLibrary( "utility.library", 37 ) ) )
  147.     {
  148.         lib->lib_Node.ln_Type    = NT_LIBRARY;
  149.         lib->lib_Node.ln_Pri    = 0;
  150.         lib->lib_Node.ln_Name    = LibName;
  151.         /* Request that checksum should be calculated */
  152.         lib->lib_Flags        = LIBF_CHANGED | LIBF_SUMUSED;
  153.         lib->lib_Version    = VERNUM;
  154.         lib->lib_Revision    = REVNUM;
  155.         lib->lib_IdString    = ( APTR ) LibId;
  156.         SegList = seglist;
  157.         AsyncIOBase = lib;
  158.     }
  159.     else
  160.     {
  161.         FreeLib( lib );
  162.         lib = NULL;
  163.     }
  164.  
  165.     return( lib );
  166. }
  167.  
  168.  
  169. /* Open is given the library pointer. Either return the library pointer or NULL.
  170.  * Remove the delayed-expunge flag. Exec has Forbid() for us during the call.
  171.  *
  172.  * Since we don't refer to any smalldata here (directly or indirectly),
  173.  * we can safely skip "LibCall", to save a few bytes.
  174.  */
  175. _ASM struct Library *
  176. LibOpen( _REG( a6 ) struct Library *lib )
  177. {
  178.     ++lib->lib_OpenCnt;
  179.     lib->lib_Flags &= ~LIBF_DELEXP;
  180.     return( lib );
  181. }
  182.  
  183.  
  184. /* Close is given the library pointer. Be sure not to decrement the open
  185.  * count if already zero. If the open count is or becomes zero AND there
  186.  * is a LIBF_DELEXP, we expunge the library and return the seglist.
  187.  * Otherwise we return NULL.
  188.  *
  189.  * Note that this routine never sets LIBF_DELEXP on its own.
  190.  *
  191.  * Exec has Forbid() for us during the call.
  192.  *
  193.  * Since we don't refer to any smalldata here (directly. Indirectly we refer via
  194.  * LibExpunge, which is LibCall declared), we can safely skip "LibCall", to save
  195.  * a few bytes.
  196.  */
  197. _ASM APTR
  198. LibClose( _REG( a6 ) struct Library *lib )
  199. {
  200.     if( lib->lib_OpenCnt && --lib->lib_OpenCnt )
  201.     {
  202.         return( NULL );
  203.     }
  204.  
  205.     if( lib->lib_Flags & LIBF_DELEXP )
  206.     {
  207.         return( LibExpunge( lib ) );
  208.     }
  209.  
  210.     return( NULL );
  211. }
  212.  
  213.  
  214. /* We expunge the library and return the Seglist ONLY if the open count is zero.
  215.  * If the open count is not zero we set the delayed-expunge flag and return NULL.
  216.  *
  217.  * Exec has Forbid() for us during the call. NOTE ALSO that Expunge might be
  218.  * called from the memory allocator and thus we CANNOT DO A Wait() or otherwise
  219.  * take a long time to complete (straight from RKM).
  220.  *
  221.  * RemLibrary() calls our expunge routine and would therefore freeze if we called
  222.  * it ourselves. LibExpunge() must remove the library itself as shown below.
  223.  */
  224. LibCall _ASM APTR
  225. LibExpunge( _REG( a6 ) struct Library *lib )
  226. {
  227.     if( lib->lib_OpenCnt )
  228.     {
  229.         lib->lib_Flags |= LIBF_DELEXP;
  230.         return( NULL );
  231.     }
  232.  
  233.     Remove( &lib->lib_Node );
  234.     FreeLib( lib );
  235.  
  236.     return( SegList );
  237. }
  238.