
;**************************************************************************
;*									  *
;* 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

