;************************************************************************** ;* * ;* sregexp.library -- pattern matching run time library. * ;* * ;* * ;* Startup module: this is heavily copied from the sample.library * ;* in the RKM includes and autodocs. * ;* This also relies on some features of dice (in particular, registered * ;* args and features of the linker.) Be carefull if you make it with * ;* something else. * ;* * ;* Created: April 20, 1991 * ;* * ;************************************************************************** CODE sregexp.start INCLUDE "sregexpbase.i" INCLUDE "exec/initializers.i" INCLUDE "libraries/dos.i" INCLUDE "exec/resident.i" INCLUDE "exec/lists.i" INCLUDE "exec/alerts.i" INCLUDE "sreg_version.i" ;-------------------------------------------------------------------- ; some generally usefull macros hiding _LVO's ;-------------------------------------------------------------------- CALLSYS macro jsr _LVO\1(a6) endm XLIB macro xref _LVO\1 endm ;-------------------------------------------------------------------- ; Declare the library calls I use. The _LVO's are brought in ; from amiga.lib ;-------------------------------------------------------------------- XLIB OpenLibrary XLIB CloseLibrary XLIB Alert XLIB FreeMem XLIB Remove ;------ defined in Amiga.lib ------ xref _AbsExecBase ;------ defined in the c source, the id string of my library. ------ xref _idString ;-------------------------------------------------------------------- ; Make some stuff visible for debuging. ;-------------------------------------------------------------------- xdef Init xdef EndCode xdef RomTag xdef funcTable xdef dataTable xdef InitRoutine xdef Open xdef Close xdef Expunge xdef Reserved ;-------------------------------------------------------------------- ; The links to the c code are in the file kludge.asm, because the ; assembler I use doesn't like to make symbols starting with a @. ; But thats what DICE starts it's regargs routines with, so... ; I make the links with das, which comes with dice. ; ; my library routines ;-------------------------------------------------------------------- xref parsesregexp xref freesregexp xref matchsregexp xref matchnsregexp xref iswild xref anchorpath xref nextfile xref buildpath xref freespathinfo ************************************************************************ * Ok, so much for the preamble, we can actually start to generate * * some code now. The very first thing we should do is return an * * error if someone tries to run us like a program, seeing as we * * will be a perfectly legal AmigaDos load module. * ************************************************************************ Start: moveq.l #-1,d0 rts ;-------------------------------------------------------------------- ; Ok, here's what exec is going to look for to tell it that we are ; a library. ;-------------------------------------------------------------------- RomTag: dc.w RTC_MATCHWORD ; magic dc.l RomTag ; pointer back to magic dc.l EndCode ; keep looking from here dc.b RTF_AUTOINIT ; yes, autoinit me. dc.b VERSION ; version number dc.b NT_LIBRARY ; I'm a library dc.b 0 ; no priority (typical) dc.l sregexpname ; I have a name dc.l _idString ; let's see some ID dc.l Init ; start me up ;-------------------------------------------------------------------- ; Ok, heres the table of 4 vectors exec is going to look for ; to autoinit me. ; ; We are word alligned here. ;-------------------------------------------------------------------- Init: dc.l SregExpBase_SIZE ; size of library structure dc.l funcTable ; table of all my routines. dc.l dataTable ; LibStructure init data dc.l InitRoutine ; Where to start me. ;-------------------------------------------------------------------- ; This is the list of functions in my library. ;-------------------------------------------------------------------- funcTable: dc.l Open dc.l Close dc.l Expunge dc.l Reserved ; my own little gems. dc.l parsesregexp dc.l freesregexp dc.l matchsregexp dc.l matchnsregexp dc.l iswild dc.l anchorpath dc.l nextfile dc.l buildpath dc.l freespathinfo dc.l -1 ; end of the list. ;-------------------------------------------------------------------- ; heres the stuff to initialise my Library structure. ;-------------------------------------------------------------------- dataTable: INITBYTE LN_TYPE,NT_LIBRARY INITLONG LN_NAME,sregexpname INITBYTE LIB_FLAGS,LIBF_SUMUSED|LIBF_CHANGED INITWORD LIB_VERSION,VERSION INITWORD LIB_REVISION,REVISION INITLONG LIB_IDSTRING,_idString dc.l 0 ******************************************************************* * Ok, so now were really ready to get cooking. * * This routine is called when the library is first linked into * * the exec LibList. The Library structure has already been * * initialised as per the dataTable instructions. * * * * When called, d0 has our library base and the segment list is * * pointed to by a0; a6 is a pointer to SysBase. * ******************************************************************* InitRoutine: move.l a4,-(sp) ; put the lib pointer move.l d0,a4 ; in a convinient place move.l a6,sb_SysBase(a4) ; save SysBase move.l a0,sb_SegList(a4) ; save our seglist lea.l dosname(pc),a1 ; try and open up moveq.l #0,d0 ; dos.library CALLSYS OpenLibrary move.l d0,sb_DOSBase(a4) ;save dos bne.s 1$ ALERT AG_OpenLib|AO_DOSLib ; couldn't get dos!!! ;------- That's all there is to do. -------- 1$ move.l a4,d0 move.l (sp)+,a4 rts *********************************************************************** * So good so far. Now come the 4 standard library routines that * * every good library must have. Each of these (in fact all of the * * library calls) comes with the pointer to our library base in a6. * *********************************************************************** ;---------------------------------------------------------------------- ; To open the library, all we have to do is up the count of current ; users and reset the delayed expunge flag. This returns the library ; pointer on d0 if we successfully opened (which is always the case). ;---------------------------------------------------------------------- Open: addq.w #1,LIB_OPENCNT(a6) bclr #LIBB_DELEXP,LIB_FLAGS(a6) move.l a6,d0 rts ;---------------------------------------------------------------------- ; When we close the library, we decrease the count of current ; users. If this has reached zeros, then we check the delayed ; expunge flag and clean up if it is set. ; If this routine returns 0 then that's that. If the return value ; is non-zero, it should be the segment pointer passed to the ; initialization routine, so we can be unloaded. ;---------------------------------------------------------------------- Close: ;--- set up the return value, which will be altered --- ;--- if we decide to do a delayed expunge. --- moveq.l #0,d0 subq.w #1,LIB_OPENCNT(a6) bne.s 1$ btst #LIBB_DELEXP,LIB_FLAGS(a6) beq.s 1$ ; --- take a shortcut into the Expunge routine that doesn't --- ; --- redo the tests we just did. --- bsr.s ReallyExpunge 1$ ; --- at this point, d0 is zero if we didn't expunge, otherwise --- ; --- it the address of our segment list. --- rts ;---------------------------------------------------------------------- ; Ok, so now we want to try to unload. First check if there ; are still any current openers, if so, just set the delayed ; expunge flag, and we'll go away when everyone closes us. ; Otherwise, clean up my resources and return the seg list to ; be unloaded ;---------------------------------------------------------------------- Expunge: tst.w LIB_OPENCNT(a6) beq.s ReallyExpunge bset #LIBB_DELEXP,LIB_FLAGS(a6) moveq.l #0,d0 ;don't unload me please rts ReallyExpunge: movem.l d2/a5,-(sp) move.l a6,a5 move.l sb_SysBase(a5),a6 move.l sb_SegList(a5),d2 ;save seglist. move.l a5,a1 ;remove the library REMOVE ;from the system list move.l sb_DOSBase(a5),a1 CALLSYS CloseLibrary ;close dos. moveq.l #0,d0 move.l a5,a1 move.w LIB_NEGSIZE(a5),d0 sub.l d0,a1 add.w LIB_POSSIZE(a5),d0 CALLSYS FreeMem ;free our library base. move.l d2,d0 ;unload us. movem.l (sp)+,d2/a5 rts ;---------------------------------------------------------------------- ; This is the reserved vector. Just return 0. ;---------------------------------------------------------------------- Reserved: moveq.l #0,d0 rts ********************************************************************** * That's all of the standard stuff. As discussed above, the links * * to the c code are in the file kludge.asm * ********************************************************************** ;---------------------------------------------------------------------- ; Here are some stings used in the above. I put them at the end so ; so I don't have to worry about alignment. ;---------------------------------------------------------------------- dosname DOSNAME sregexpname SREGEXPNAME ;---------------------------------------------------------------------- ; The end of the code, where exec can start looking for more RomTag ; structures if it wants to. ;---------------------------------------------------------------------- EVEN EndCode: ********************************************************************** * * * Now comes the clever part. Dice (and the others, I think) * * references there global data from register a4. What I do * * to have easy access to the Library structure data from the * * c code, is transfer a6 to a4 on each library call and then * * define the various things I want to access as offsets to * * this, in effect, tricking dice into thinking they're global * * variables. The real benifit of this is I don't need my own * * custom links to the Exec and DOS library routines, because * * there exists perfectly valid global variables SysBase and * * DosBase. * * * ********************************************************************** DATA data ;--------------------------------------------------------------------- ; This one is a little funny, it is the actual instance of the ; structure, and not a pointer to it. It should be declared in ; the c code as 'extern struct SregExpBase SregExpBase;' and then ; referenced with the '.' and not the '->'. This may not work ; I haven't tried it yet. ;---------------------------------------------------------------------- _SregExpBase equ 0 xdef _SregExpBase ;--- These are perfectly ordinary pointers --- _SysBase equ sb_SysBase xdef _SysBase _DOSBase equ sb_DOSBase xdef _DOSBase end