home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / biblioteki / asyncio / src / lib.c < prev    next >
C/C++ Source or Header  |  1997-02-18  |  7KB  |  240 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. _LIBCALL struct Library    *LibInit( _REG( d0 ) struct Library *, _REG( a0 ) APTR, _REG( a6 ) struct ExecBase * );
  21. _CALL    struct Library    *LibOpen( _REG( a6 ) struct Library * );
  22. _CALL    APTR        LibClose( _REG( a6 ) struct Library * );
  23. _LIBCALL 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.     FGetsAsync,
  75.     FGetsLenAsync,
  76.     PeekAsync,
  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. static const ULONG InitTable[] =
  86. {
  87.     sizeof( struct Library ),    /* Size of our library base, excluding jump table. We have no extra data here */
  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. static const TEXT LibId[] = "asyncio.library "VERSION" (" DATE ")\r\n";
  95. static const TEXT LibName[] = "asyncio.library";
  96.  
  97.  
  98. /* And finaly the resident structure, used by InitResident(),
  99.  * in order to initialize everything.
  100.  */
  101. static 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 frees the library structure,
  117.  * and any other allocated resources.
  118.  */
  119. static VOID
  120. FreeLib( struct Library *lib )
  121. {
  122.     if( DOSBase )    /* In case we are loaded under kick 35 or earlier */
  123.     {
  124.         CloseLibrary( ( struct Library * ) DOSBase );
  125.         CloseLibrary( UtilityBase );
  126.     }
  127.  
  128.     FreeMem( ( UBYTE * ) lib - lib->lib_NegSize, lib->lib_NegSize + lib->lib_PosSize );
  129. }
  130.  
  131.  
  132. /* This function is called when the library is loaded, and the library base
  133.  * have been allocated. We are in a forbid section here, so don't do anything
  134.  * time-consuming, Wait() or similar.
  135.  *
  136.  * If all ok, return the library base. If anything went wrong, deallocate
  137.  * the library structure, and return NULL.
  138.  */
  139. _LIBCALL struct Library *
  140. LibInit( _REG( d0 ) struct Library *lib, _REG( a0 ) APTR seglist, _REG( a6 ) struct ExecBase *sysBase )
  141. {
  142.     SysBase = sysBase;
  143.  
  144.     /* Opening libraries in LibInit might not be a good idea under OS 1.x.
  145.      * Should be safe enough under 2.x and 3.x.
  146.      */
  147.     if( ( DOSBase = ( struct DosLibrary * ) OpenLibrary( "dos.library", 37 ) ) &&
  148.         ( UtilityBase = OpenLibrary( "utility.library", 37 ) ) )
  149.     {
  150.         lib->lib_Node.ln_Type    = NT_LIBRARY;
  151.         lib->lib_Node.ln_Pri    = 0;
  152.         lib->lib_Node.ln_Name    = LibName;
  153.         /* Request that checksum should be calculated */
  154.         lib->lib_Flags        = LIBF_CHANGED | LIBF_SUMUSED;
  155.         lib->lib_Version    = VERNUM;
  156.         lib->lib_Revision    = REVNUM;
  157.         lib->lib_IdString    = ( APTR ) LibId;
  158.         SegList = seglist;
  159.         AsyncIOBase = lib;
  160.     }
  161.     else
  162.     {
  163.         FreeLib( lib );
  164.         lib = NULL;
  165.     }
  166.  
  167.     return( lib );
  168. }
  169.  
  170.  
  171. /* Open is given the library pointer. Either return the library pointer or NULL.
  172.  * Remove the delayed-expunge flag. Exec has Forbid() for us during the call.
  173.  *
  174.  * Since we don't refer to any smalldata here (directly or indirectly),
  175.  * we can safely skip "_LIBCALL", to save a few bytes.
  176.  */
  177. _CALL struct Library *
  178. LibOpen( _REG( a6 ) struct Library *lib )
  179. {
  180.     ++lib->lib_OpenCnt;
  181.     lib->lib_Flags &= ~LIBF_DELEXP;
  182.     return( lib );
  183. }
  184.  
  185.  
  186. /* Close is given the library pointer. Be sure not to decrement the open
  187.  * count if already zero. If the open count is or becomes zero AND there
  188.  * is a LIBF_DELEXP, we expunge the library and return the seglist.
  189.  * Otherwise we return NULL.
  190.  *
  191.  * Note that this routine never sets LIBF_DELEXP on its own.
  192.  *
  193.  * Exec has Forbid() for us during the call.
  194.  *
  195.  * Since we don't refer to any smalldata here (directly. Indirectly we refer via
  196.  * LibExpunge, which is LibCall declared), we can safely skip "LibCall", to save
  197.  * a few bytes.
  198.  */
  199. _CALL APTR
  200. LibClose( _REG( a6 ) struct Library *lib )
  201. {
  202.     if( lib->lib_OpenCnt && --lib->lib_OpenCnt )
  203.     {
  204.         return( NULL );
  205.     }
  206.  
  207.     if( lib->lib_Flags & LIBF_DELEXP )
  208.     {
  209.         return( LibExpunge( lib ) );
  210.     }
  211.  
  212.     return( NULL );
  213. }
  214.  
  215.  
  216. /* We expunge the library and return the Seglist ONLY if the open count is zero.
  217.  * If the open count is not zero we set the delayed-expunge flag and return NULL.
  218.  *
  219.  * Exec has Forbid() for us during the call. NOTE ALSO that Expunge might be
  220.  * called from the memory allocator and thus we CANNOT DO A Wait() or otherwise
  221.  * take a long time to complete (straight from RKM).
  222.  *
  223.  * RemLibrary() calls our expunge routine and would therefore freeze if we called
  224.  * it ourselves. LibExpunge() must remove the library itself as shown below.
  225.  */
  226. _LIBCALL APTR
  227. LibExpunge( _REG( a6 ) struct Library *lib )
  228. {
  229.     if( lib->lib_OpenCnt )
  230.     {
  231.         lib->lib_Flags |= LIBF_DELEXP;
  232.         return( NULL );
  233.     }
  234.  
  235.     Remove( &lib->lib_Node );
  236.     FreeLib( lib );
  237.  
  238.     return( SegList );
  239. }
  240.