home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 390.lha / LibExample / testlib.c < prev   
Encoding:
C/C++ Source or Header  |  1990-06-02  |  5.5 KB  |  226 lines

  1.  
  2. /*
  3.  *  TESTLIB.C
  4.  *
  5.  *  Example fully working library for Aztec C ... with comments (which is
  6.  *  a miracle in itself).   By Matthew Dillon.    PUBLIC DOMAIN.
  7.  *
  8.  *  Aztec Compile with +BCDL
  9.  *        +B    No startup reference
  10.  *        +C    Large code
  11.  *        +D    Large data
  12.  *        +L    32 bit Integers
  13.  *
  14.  *  Since Original release, the following has been fixed:
  15.  *    -slight bug in LibClose() .. did not expunge library if DELEXP set
  16.  *     on final close.  (thanks to Rico Mariani for finding the bug)
  17.  *    -Now uses MakeLibrary call rather than a hardwired Library structure.
  18.  */
  19.  
  20. #asm
  21.     ;   RLIB.ASM
  22.     ;
  23.     ;   Run-time library tag
  24.  
  25.         FAR     code
  26.         FAR     data
  27.  
  28.         public  _CInit
  29.         public  _LibOpen
  30.         public  _LibClose
  31.         public  _LibExpunge
  32.  
  33. Start:        clr.l   D0
  34.         rts
  35.  
  36. InitDesc:   dc.w    $4AFC    ;RTC_MATCHWORD
  37.         dc.l    InitDesc    ;Pointer to beginning
  38.         dc.l    EndCode    ;Note sure it matters
  39.         dc.b    0        ;flags (NO RTF_AUTOINIT)
  40.         dc.b    0        ;version
  41.         dc.b    9        ;NT_LIBRARY
  42.         dc.b    0        ;priority (doesn't matter)
  43.         dc.l    _Libname    ;Name of library
  44.         dc.l    _Libid    ;ID string (note CR-LF at end)
  45.         dc.l    Init    ;Pointer to init routine
  46.  
  47. _Libname:   dc.b    "testlib.library",0
  48. _Libid:     dc.b    "testlib.library 1.0 (02 Oct 1987)",13,10,0
  49. EndCode:
  50.  
  51. Init:        move.l  A6,-(sp)    ;Must save A6
  52.         move.l  A0,-(sp)    ;Segment list
  53.         jsr     _CInit
  54.         addq.l  #4,sp
  55.         move.l  (sp)+,A6
  56.         rts
  57.  
  58. cifc        macro
  59.         move.l  D0,-(sp)    ;Make a C call and save A6 to boot
  60.         move.l  A6,-(sp)
  61.         jsr     \1
  62.         move.l  (sp)+,A6
  63.         addq.l  #4,sp
  64.         rts
  65.         endm
  66.  
  67. _ALibOpen:    cifc    _LibOpen
  68. _ALibClose:    cifc    _LibClose
  69. _ALibExpunge:    cifc    _LibExpunge
  70.  
  71. #endasm
  72.  
  73. extern char Libname[1];
  74. extern char Libid[1];
  75.  
  76. extern long ALibExpunge(), ALibClose(), ALibOpen();
  77. extern long Lib_Add(), Lib_Sub();
  78.  
  79. typedef struct Library LIB;
  80.  
  81. LIB  *Lib;            /*  Library Base pointer    */
  82. long Seglist;            /*  Save the DOS seglist    */
  83.  
  84. extern LIB *MakeLibrary();
  85. extern void *AllocMem();
  86.  
  87. /*
  88.  *    The Initialization routine is given only a seglist pointer.  Since
  89.  *    we are NOT AUTOINIT we must construct and add the library ourselves
  90.  *    and return either NULL or the library pointer.  Exec has Forbid()
  91.  *    for us during the call.
  92.  *
  93.  *    If you have an extended library structure you must specify the size
  94.  *    of the extended structure in MakeLibrary().
  95.  */
  96.  
  97. LIB *
  98. CInit(segment)
  99. {
  100.     extern long SysBase;
  101.     static long (*Vectors[])() = {
  102.     ALibOpen,ALibClose,ALibExpunge,NULL,
  103.     Lib_Add, Lib_Sub, (long (*)())-1
  104.     };
  105.  
  106.     SysBase = *(long *)4;
  107.     Lib = MakeLibrary(Vectors,NULL,NULL,sizeof(LIB),NULL);
  108.     Lib->lib_Node.ln_Type = NT_LIBRARY;
  109.     Lib->lib_Node.ln_Name = Libname;
  110.     Lib->lib_Flags = LIBF_CHANGED|LIBF_SUMUSED;
  111.     Lib->lib_Version  = 0;
  112.     Lib->lib_Revision = 0;
  113.     Lib->lib_IdString = (APTR)Libid;
  114.     Seglist = segment;
  115.     AddLibrary(Lib);
  116.     return(Lib);
  117. }
  118.  
  119. /*
  120.  *    Open is given the library pointer and the version request.  Either
  121.  *    return the library pointer or NULL.  Remove the DELAYED-EXPUNGE flag.
  122.  *    Exec has Forbid() for us during the call.
  123.  */
  124.  
  125. LIB *
  126. LibOpen(lib,version)
  127. LIB *lib;
  128. {
  129.     ++lib->lib_OpenCnt;
  130.     lib->lib_Flags &= ~LIBF_DELEXP;
  131.     return(lib);
  132. }
  133.  
  134. /*
  135.  *    Close is given the library pointer and the version request.  Be sure
  136.  *    not to decrement the open count if already zero.    If the open count
  137.  *    is or becomes zero AND there is a LIBF_DELEXP, we expunge the library
  138.  *    and return the seglist.  Otherwise we return NULL.
  139.  *
  140.  *    Note that this routine never sets LIBF_DELEXP on its own.
  141.  *
  142.  *    Exec has Forbid() for us during the call.
  143.  */
  144.  
  145. LibClose(lib)
  146. LIB *lib;
  147. {
  148.     if (lib->lib_OpenCnt && --lib->lib_OpenCnt)
  149.     return(NULL);
  150.     if (lib->lib_Flags & LIBF_DELEXP)
  151.     return(LibExpunge(lib));
  152.     return(NULL);
  153. }
  154.  
  155. /*
  156.  *    We expunge the library and return the Seglist ONLY if the open count
  157.  *    is zero.    If the open count is not zero we set the DELAYED-EXPUNGE
  158.  *    flag and return NULL.
  159.  *
  160.  *    Exec has Forbid() for us during the call.  NOTE ALSO that Expunge
  161.  *    might be called from the memory allocator and thus we CANNOT DO A
  162.  *    Wait() or otherwise take a long time to complete (straight from RKM).
  163.  *
  164.  *    Apparently RemLibrary(lib) calls our expunge routine and would
  165.  *    therefore freeze if we called it ourselves.  As far as I can tell
  166.  *    from RKM, LibExpunge(lib) must remove the library itself as shown
  167.  *    below.
  168.  */
  169.  
  170. LibExpunge(lib)
  171. LIB *lib;
  172. {
  173.     if (lib->lib_OpenCnt) {
  174.     lib->lib_Flags |= LIBF_DELEXP;
  175.     return(NULL);
  176.     }
  177.     Remove(lib);
  178.     FreeMem((char *)lib-lib->lib_NegSize, lib->lib_NegSize+lib->lib_PosSize);
  179.     return(Seglist);
  180. }
  181.  
  182. /*
  183.  *  The Library routines themselves.  Note that we must also save A6 if
  184.  *  any library routine makes a library call to another library.  These
  185.  *  examples do not and thus you can remove the #asm statements in them if
  186.  *  you wish... just DON'T FORGET!
  187.  *
  188.  *  The reason A6 must be saved is that Aztec library interface routines
  189.  *  (e.g. FindTask(), OpenWindow(), etc....) trash A6 on purpose to make
  190.  *  the interface routine faster.
  191.  *
  192.  *  D2 and D3 are automatically saved/restored via the +p compile option
  193.  *  A0,A1,D0,D1 are always scratch.  In an assembly interface, these might
  194.  *  also contain arguments... but they are still scratch.
  195.  */
  196.  
  197. Lib_Add(n)
  198. {
  199. #asm
  200.     move.l A6,-(sp)
  201. #endasm
  202.  
  203.     ++n; /* do stuff here */
  204.  
  205. #asm
  206.     move.l (sp)+,A6
  207. #endasm
  208.     return(n);
  209. }
  210.  
  211. Lib_Sub(n)
  212. {
  213. #asm
  214.     move.l A6,-(sp)
  215. #endasm
  216.  
  217.     --n; /* do stuff here */
  218.  
  219. #asm
  220.     move.l (sp)+,A6
  221. #endasm
  222.     return(n);
  223. }
  224.  
  225.  
  226.