[comp.sources.amiga] v02i018: dres - an object-oriented resource library, Part03/03

page@swan.ulowell.edu (Bob Page) (10/25/88)

Submitted-by: dillon@cory.berkeley.edu (Matt Dillon)
Posting-number: Volume 2, Issue 18
Archive-name: util/dres.3

# This is a shell archive.  Remove anything before this line
# then unpack it by saving it in a file and typing "sh file"
# (Files unpacked will be owned by you and have default permissions).
# This archive contains the following files:
#	README
#	core/TODO
#	core/funcs.reg
#	core/libfuncs.h
#	core/libtag.asm
#	core/Makefile
#	core/func.def
#	core/library.c
#	libref.c
#
if `test ! -s README`
then
echo "writing README"
cat > README << '\Rogue\Monster\'

The makefile is in core.  CD into core and then 'make'.   Make will fist
compile libref.c which is used to generate the link library and library
function array.

\Rogue\Monster\
else
  echo "will not over write README"
fi
if [ `wc -c README | awk '{printf $1}'` -ne 163 ]
then
echo `wc -c README | awk '{print "Got " $1 ", Expected " 163}'`
fi
if `test ! -d core`
then
  mkdir core
  echo "mkdir core"
fi
if `test ! -s core/TODO`
then
echo "writing core/TODO"
cat > core/TODO << '\Rogue\Monster\'

add dos.library to list of libraries....

\Rogue\Monster\
else
  echo "will not over write core/TODO"
fi
if [ `wc -c core/TODO | awk '{printf $1}'` -ne 43 ]
then
echo `wc -c core/TODO | awk '{print "Got " $1 ", Expected " 43}'`
fi
if `test ! -s core/funcs.reg`
then
echo "writing core/funcs.reg"
cat > core/funcs.reg << '\Rogue\Monster\'

#	Q interrupts

AFUNC=	OpenQInts	    -
AFUNC=	CloseQInts	    A0
AFUNC=	SetQPri 	    D0/D1
AFUNC=	SetQVector	    D0/D1/D2/D3/A0
AFUNC=	NULL		    -
AFUNC=	NULL		    -
AFUNC=	NULL		    -
AFUNC=	NULL		    -

#	List functions

AFUNC=	GetHead 	    A0
AFUNC=	GetTail 	    A0
AFUNC=	GetSucc 	    A0
AFUNC=	GetPred 	    A0
AFUNC=	GetHeadOff	    D0/D1
AFUNC=	GetTailOff	    D0/D1
AFUNC=	GetSuccOff	    D0/D1
AFUNC=	GetPredOff	    D0/D1
AFUNC=	EnqueueLong	    D0/D1/D2/D4
AFUNC=	EnqueueOffLong	    D0/D1/D2/D3/D4
AFUNC=	SearchFwdNode	    D0/D1/A1
AFUNC=	SearchRvsNode	    D0/D1/A1
AFUNC=	SearchFwdList	    D0/D1/A1
AFUNC=	SearchRvsList	    D0/D1/A1
AFUNC=	SearchFwdNodeOff    D0/D1/A0/A1
AFUNC=	SearchRvsNodeOff    D0/D1/A0/A1
AFUNC=	SearchFwdListOff    D0/D1/A0/A1
AFUNC=	SearchRvsListOff    D0/D1/A0/A1
AFUNC=	NULL		    -
AFUNC=	NULL		    -
AFUNC=	NULL		    -
AFUNC=	NULL		    -

#	Memory functions

AFUNC=	BZero		    D0/D1
AFUNC=	BSet		    D0/D1/A0
AFUNC=	BMov		    D0/D1/A0
AFUNC=	BCmp		    D0/D1/A0
AFUNC=	NULL		    -
AFUNC=	NULL		    -
AFUNC=	NULL		    -
AFUNC=	NULL		    -

#	Misc. Functions

AFUNC=	WildCmp 	    D0/D1
AFUNC=	WaitMsg 	    A0
AFUNC=	CheckMsg	    A0
AFUNC=	CheckPort	    A0
AFUNC=	LockAddr	    A0
AFUNC=	LockAddrB	    D0/A0
AFUNC=	UnLockAddr	    A0
AFUNC=	UnLockAddrB	    D0/A0
AFUNC=	DoSyncMsg	    A0/A1
AFUNC=	FindName2	    D0/A0

#   placed in res.c
CFUNC=	GetTaskData	    D0/D1
CFUNC=	FreeTaskData	    D0

CFUNC=	DateToS 	    D0/D1/A0
CFUNC=	SetFileDate	    D0/D1
CFUNC=	NULL		    -
CFUNC=	NULL		    -
CFUNC=	NULL		    -
CFUNC=	NULL		    -

#	IPC functions

CFUNC= OpenIPC		    D0/D1
CFUNC= CloseIPC 	    D0
CFUNC= SendIPC		    D0/D1/D2/A0
CFUNC= SendIPC2 	    D0/D1
CFUNC= ReplyIPC 	    D0/D1/D2/A0
CFUNC= FreeIPC		    D0
CFUNC= DoIPC2		    D0/D1/D2/A0
CFUNC= ParseCmd 	    D0/D1/D2/D3/D4/A0
CFUNC= FreeParseCmd	    D0
CFUNC= NULL		    D0
CFUNC= NULL		    -
CFUNC= NULL		    -
CFUNC= NULL		    -

#	Resource Library functions

\Rogue\Monster\
else
  echo "will not over write core/funcs.reg"
fi
if [ `wc -c core/funcs.reg | awk '{printf $1}'` -ne 1944 ]
then
echo `wc -c core/funcs.reg | awk '{print "Got " $1 ", Expected " 1944}'`
fi
if `test ! -s core/libfuncs.h`
then
echo "writing core/libfuncs.h"
cat > core/libfuncs.h << '\Rogue\Monster\'

/*
 * Machine Generated Library Vectors
 */

#ifndef NULL
#define NULL 0L
#endif

extern long _LibOpen(), _LibClose(), _LibExpunge();
extern long lOpenQInts();
extern long lCloseQInts();
extern long lSetQPri();
extern long lSetQVector();
extern long lGetHead();
extern long lGetTail();
extern long lGetSucc();
extern long lGetPred();
extern long lGetHeadOff();
extern long lGetTailOff();
extern long lGetSuccOff();
extern long lGetPredOff();
extern long lEnqueueLong();
extern long lEnqueueOffLong();
extern long lSearchFwdNode();
extern long lSearchRvsNode();
extern long lSearchFwdList();
extern long lSearchRvsList();
extern long lSearchFwdNodeOff();
extern long lSearchRvsNodeOff();
extern long lSearchFwdListOff();
extern long lSearchRvsListOff();
extern long lBZero();
extern long lBSet();
extern long lBMov();
extern long lBCmp();
extern long lWildCmp();
extern long lWaitMsg();
extern long lCheckMsg();
extern long lCheckPort();
extern long lLockAddr();
extern long lLockAddrB();
extern long lUnLockAddr();
extern long lUnLockAddrB();
extern long lDoSyncMsg();
extern long lFindName2();
extern long _lGetTaskData();
extern long _lFreeTaskData();
extern long _lDateToS();
extern long _lSetFileDate();
extern long _lOpenIPC();
extern long _lCloseIPC();
extern long _lSendIPC();
extern long _lSendIPC2();
extern long _lReplyIPC();
extern long _lFreeIPC();
extern long _lDoIPC2();
extern long _lParseCmd();
extern long _lFreeParseCmd();


/*
 * -30-6*X
 */

long (*LibVectors[])() = {
    _LibOpen, _LibClose, _LibExpunge, NULL,

    lOpenQInts       ,    /*  -30                        */
    lCloseQInts      ,    /*  -36  A0                    */
    lSetQPri         ,    /*  -42  D0/D1                 */
    lSetQVector      ,    /*  -48  D0/D1/D2/D3/A0        */
    NULL,
    NULL,
    NULL,
    NULL,
    lGetHead         ,    /*  -78  A0                    */
    lGetTail         ,    /*  -84  A0                    */
    lGetSucc         ,    /*  -90  A0                    */
    lGetPred         ,    /*  -96  A0                    */
    lGetHeadOff      ,    /*  -102  D0/D1                 */
    lGetTailOff      ,    /*  -108  D0/D1                 */
    lGetSuccOff      ,    /*  -114  D0/D1                 */
    lGetPredOff      ,    /*  -120  D0/D1                 */
    lEnqueueLong     ,    /*  -126  D0/D1/D2/D4           */
    lEnqueueOffLong  ,    /*  -132  D0/D1/D2/D3/D4        */
    lSearchFwdNode   ,    /*  -138  D0/D1/A1              */
    lSearchRvsNode   ,    /*  -144  D0/D1/A1              */
    lSearchFwdList   ,    /*  -150  D0/D1/A1              */
    lSearchRvsList   ,    /*  -156  D0/D1/A1              */
    lSearchFwdNodeOff,    /*  -162  D0/D1/A0/A1           */
    lSearchRvsNodeOff,    /*  -168  D0/D1/A0/A1           */
    lSearchFwdListOff,    /*  -174  D0/D1/A0/A1           */
    lSearchRvsListOff,    /*  -180  D0/D1/A0/A1           */
    NULL,
    NULL,
    NULL,
    NULL,
    lBZero           ,    /*  -210  D0/D1                 */
    lBSet            ,    /*  -216  D0/D1/A0              */
    lBMov            ,    /*  -222  D0/D1/A0              */
    lBCmp            ,    /*  -228  D0/D1/A0              */
    NULL,
    NULL,
    NULL,
    NULL,
    lWildCmp         ,    /*  -258  D0/D1                 */
    lWaitMsg         ,    /*  -264  A0                    */
    lCheckMsg        ,    /*  -270  A0                    */
    lCheckPort       ,    /*  -276  A0                    */
    lLockAddr        ,    /*  -282  A0                    */
    lLockAddrB       ,    /*  -288  D0/A0                 */
    lUnLockAddr      ,    /*  -294  A0                    */
    lUnLockAddrB     ,    /*  -300  D0/A0                 */
    lDoSyncMsg       ,    /*  -306  A0/A1                 */
    lFindName2       ,    /*  -312  D0/A0                 */
    _lGetTaskData    ,    /*  -318  D0/D1                 */
    _lFreeTaskData   ,    /*  -324  D0                    */
    _lDateToS        ,    /*  -330  D0/D1/A0              */
    _lSetFileDate    ,    /*  -336  D0/D1                 */
    NULL,
    NULL,
    NULL,
    NULL,
    _lOpenIPC        ,    /*  -366  D0/D1                 */
    _lCloseIPC       ,    /*  -372  D0                    */
    _lSendIPC        ,    /*  -378  D0/D1/D2/A0           */
    _lSendIPC2       ,    /*  -384  D0/D1                 */
    _lReplyIPC       ,    /*  -390  D0/D1/D2/A0           */
    _lFreeIPC        ,    /*  -396  D0                    */
    _lDoIPC2         ,    /*  -402  D0/D1/D2/A0           */
    _lParseCmd       ,    /*  -408  D0/D1/D2/D3/D4/A0     */
    _lFreeParseCmd   ,    /*  -414  D0                    */
    NULL,
    NULL,
    NULL,
    NULL,
    (long (*)())-1
};

\Rogue\Monster\
else
  echo "will not over write core/libfuncs.h"
fi
if [ `wc -c core/libfuncs.h | awk '{printf $1}'` -ne 4739 ]
then
echo `wc -c core/libfuncs.h | awk '{print "Got " $1 ", Expected " 4739}'`
fi
if `test ! -s core/libtag.asm`
then
echo "writing core/libtag.asm"
cat > core/libtag.asm << '\Rogue\Monster\'

	; Machine Generated File
	; Tags for library routines which are in C

	FAR	DATA


		public _lGetTaskData
		public __lGetTaskData

__lGetTaskData:
		movem.l	D2/D3/A6,-(sp)
		movem.l	D0/D1,-(sp)
		bsr	_lGetTaskData
		addq.l	#8,A7
		movem.l	(sp)+,D2/D3/A6
		rts

		public _lFreeTaskData
		public __lFreeTaskData

__lFreeTaskData:
		movem.l	D2/D3/A6,-(sp)
		move.l	D0,-(sp)
		bsr	_lFreeTaskData
		addq.l	#4,A7
		movem.l	(sp)+,D2/D3/A6
		rts

		public _lDateToS
		public __lDateToS

__lDateToS:
		movem.l	D2/D3/A6,-(sp)
		movem.l	D0/D1/A0,-(sp)
		bsr	_lDateToS
		add.w	#12,A7
		movem.l	(sp)+,D2/D3/A6
		rts

		public _lSetFileDate
		public __lSetFileDate

__lSetFileDate:
		movem.l	D2/D3/A6,-(sp)
		movem.l	D0/D1,-(sp)
		bsr	_lSetFileDate
		addq.l	#8,A7
		movem.l	(sp)+,D2/D3/A6
		rts

		public _lOpenIPC
		public __lOpenIPC

__lOpenIPC:
		movem.l	D2/D3/A6,-(sp)
		movem.l	D0/D1,-(sp)
		bsr	_lOpenIPC
		addq.l	#8,A7
		movem.l	(sp)+,D2/D3/A6
		rts

		public _lCloseIPC
		public __lCloseIPC

__lCloseIPC:
		movem.l	D2/D3/A6,-(sp)
		move.l	D0,-(sp)
		bsr	_lCloseIPC
		addq.l	#4,A7
		movem.l	(sp)+,D2/D3/A6
		rts

		public _lSendIPC
		public __lSendIPC

__lSendIPC:
		movem.l	D2/D3/A6,-(sp)
		movem.l	D0/D1/D2/A0,-(sp)
		bsr	_lSendIPC
		add.w	#16,A7
		movem.l	(sp)+,D2/D3/A6
		rts

		public _lSendIPC2
		public __lSendIPC2

__lSendIPC2:
		movem.l	D2/D3/A6,-(sp)
		movem.l	D0/D1,-(sp)
		bsr	_lSendIPC2
		addq.l	#8,A7
		movem.l	(sp)+,D2/D3/A6
		rts

		public _lReplyIPC
		public __lReplyIPC

__lReplyIPC:
		movem.l	D2/D3/A6,-(sp)
		movem.l	D0/D1/D2/A0,-(sp)
		bsr	_lReplyIPC
		add.w	#16,A7
		movem.l	(sp)+,D2/D3/A6
		rts

		public _lFreeIPC
		public __lFreeIPC

__lFreeIPC:
		movem.l	D2/D3/A6,-(sp)
		move.l	D0,-(sp)
		bsr	_lFreeIPC
		addq.l	#4,A7
		movem.l	(sp)+,D2/D3/A6
		rts

		public _lDoIPC2
		public __lDoIPC2

__lDoIPC2:
		movem.l	D2/D3/A6,-(sp)
		movem.l	D0/D1/D2/A0,-(sp)
		bsr	_lDoIPC2
		add.w	#16,A7
		movem.l	(sp)+,D2/D3/A6
		rts

		public _lParseCmd
		public __lParseCmd

__lParseCmd:
		movem.l	D2/D3/A6,-(sp)
		movem.l	D0/D1/D2/D3/D4/A0,-(sp)
		bsr	_lParseCmd
		add.w	#24,A7
		movem.l	(sp)+,D2/D3/A6
		rts

		public _lFreeParseCmd
		public __lFreeParseCmd

__lFreeParseCmd:
		movem.l	D2/D3/A6,-(sp)
		move.l	D0,-(sp)
		bsr	_lFreeParseCmd
		addq.l	#4,A7
		movem.l	(sp)+,D2/D3/A6
		rts
\Rogue\Monster\
else
  echo "will not over write core/libtag.asm"
fi
if [ `wc -c core/libtag.asm | awk '{printf $1}'` -ne 2290 ]
then
echo `wc -c core/libtag.asm | awk '{print "Got " $1 ", Expected " 2290}'`
fi
if `test ! -s core/Makefile`
then
echo "writing core/Makefile"
cat > core/Makefile << '\Rogue\Monster\'

#   Makefile for DRES.LIBRARY,	    AZTEC C 3.6a
#
#   NOTE:   You must have previously create the directory 'local' in your
#	    C include's directory and placed the distribution include/local
#	    directory there.  The libref program must also have been compiled

SYMS=	include:symbols.m
SYMC=	include:local/makesymbols.c
CFLAGS= +BCDLp +I$(SYMS)
LREXE=	srcc:libref

SRC0=	library.c
SRC1=	libtag.asm
SRC2=	/src/misc.c
SRC3=	/src/qint.asm
SRC4=	/src/lists.asm
SRC5=	/src/mem.asm
SRC6=	/src/timedate.c
SRC7=	/src/ipc.c
SRC8=	/src/res.c

OBJ0=	vd0:library.o
OBJ1=	vd0:libtag.o
OBJ2=	vd0:misc.o
OBJ3=	vd0:qint.o
OBJ4=	vd0:lists.o
OBJ5=	vd0:mem.o
OBJ6=	vd0:timedate.o
OBJ7=	vd0:ipc.o
OBJ8=	vd0:res.o

OBJS=	$(OBJ0) $(OBJ1) $(OBJ2) $(OBJ3) $(OBJ4) $(OBJ5) $(OBJ6) $(OBJ7)

all:  $(SYMS) $(LREXE) hlib $(OBJS)
    ln	+Q $(OBJS) -ldres -lcl32 -o libs:dres.library

hlib:
    libref
    assign this: /core
    cd ram:
    make
    cd this:
    assign this:

$(OBJ0): $(SRC0)
    cc	$(CFLAGS) $(SRC0) -o $(OBJ0)

$(OBJ1): $(SRC1)
    as	$(SRC1) -o $(OBJ1)

$(OBJ2): $(SRC2)
    cc	$(CFLAGS) $(SRC2) -o $(OBJ2)

$(OBJ3): $(SRC3)
    as	$(SRC3) -o $(OBJ3)

$(OBJ4): $(SRC4)
    as	$(SRC4) -o $(OBJ4)

$(OBJ5): $(SRC5)
    as	$(SRC5) -o $(OBJ5)

$(OBJ6): $(SRC6)
    cc $(CFLAGS) $(SRC6) -o $(OBJ6)

$(OBJ7): $(SRC7)
    cc $(CFLAGS) $(SRC7) -o $(OBJ7)

$(OBJ8): $(SRC8)
    cc $(CFLAGS) $(SRC8) -o $(OBJ8)

$(SYMS):    $(SYMC)
    make -f include:local/Makefile

$(LREXE):   /libref.c
    cc +L +I$(SYMS) /libref.c -o T:libref.o
    ln +Q T:libref.o -lsup32 -lc32 -o $(LREXE)
    delete T:libref.o

\Rogue\Monster\
else
  echo "will not over write core/Makefile"
fi
if [ `wc -c core/Makefile | awk '{printf $1}'` -ne 1591 ]
then
echo `wc -c core/Makefile | awk '{print "Got " $1 ", Expected " 1591}'`
fi
if `test ! -s core/func.def`
then
echo "writing core/func.def"
cat > core/func.def << '\Rogue\Monster\'

;   Run Time Library Function definition file
;
;   -Generate function table for MakeLibrary in C
;   -Generate tags in assembly for C

1=  libfuncs.h
2=  ram:
3=  libtag.asm
4=  DResBase
5=  comp:clib/dres.lib

funcs.reg

\Rogue\Monster\
else
  echo "will not over write core/func.def"
fi
if [ `wc -c core/func.def | awk '{printf $1}'` -ne 224 ]
then
echo `wc -c core/func.def | awk '{print "Got " $1 ", Expected " 224}'`
fi
if `test ! -s core/library.c`
then
echo "writing core/library.c"
cat > core/library.c << '\Rogue\Monster\'

/*
 *  LIBRARY.C
 *
 *  Example fully working library for Aztec C ... with comments (which is
 *  a miracle in itself).   By Matthew Dillon.	PUBLIC DOMAIN.
 *
 *  Aztec Compile with +BCDLp
 *	    +B	No startup reference
 *	    +C	Large code
 *	    +D	Large data
 *	    +L	32 bit Integers
 *	    +p	compatibility mode  (D2/D3 preserved)
 *
 *  Since Original release, the following has been fixed:
 *	-slight bug in LibClose() .. did not expunge library if DELEXP set
 *	 on final close.  (thanks to Rico Mariani for finding the bug)
 *	-Now uses MakeLibrary call rather than a hardwired Library structure.
 */

#define NULL 0L

typedef struct Library	LIB;

extern LIB *MakeLibrary();

#define VERSION     1	    /*	NOTE!  String in dc.b below must also be */
#define REVISION    3	    /*	       Changed! 			 */

#asm
VERSION     equ     1

	;   RLIB.ASM
	;
	;   Run-time library tag

	    FAR     data

	    public  _CInit
	    public  _LibOpen
	    public  _LibClose
	    public  _LibExpunge

Start:	    clr.l   D0
	    rts

InitDesc:   dc.w    $4AFC	;RTC_MATCHWORD
	    dc.l    InitDesc	;Pointer to beginning
	    dc.l    EndCode	;Note sure it matters
	    dc.b    0		;flags (NO RTF_AUTOINIT)
	    dc.b    VERSION	;version
	    dc.b    9		;NT_LIBRARY
	    dc.b    0		;priority (doesn't matter)
	    dc.l    _Libname	;Name of library
	    dc.l    _Libid	;ID string (note CR-LF at end)
	    dc.l    Init	;Pointer to init routine

_Libname:   dc.b    "dres.library",0
_Libid:     dc.b    "dres.library 1.3 (29 Sep 1988)",13,10,0
EndCode:

Init:	    move.l  A6,-(sp)    ;Must save A6
	    move.l  A0,-(sp)    ;Segment list
	    jsr     _CInit
	    addq.l  #4,sp
	    move.l  (sp)+,A6
	    rts

cifc	    macro
	    move.l  D0,-(sp)    ;Make a C call and save A6 to boot
	    move.l  A6,-(sp)
	    jsr     \1
	    move.l  (sp)+,A6
	    addq.l  #4,sp
	    rts
	    endm

__LibOpen:	cifc	_LibOpen
__LibClose:	cifc	_LibClose
__LibExpunge:	cifc	_LibExpunge

#endasm

extern char Libname[1];
extern char Libid[1];

LIB  *Lib, *DResBase;		 /*  Library Base pointer	 */
long Seglist;			/*  Save the DOS seglist	*/


/*
 *    The Initialization routine is given only a seglist pointer.  Since
 *    we are NOT AUTOINIT we must construct and add the library ourselves
 *    and return either NULL or the library pointer.  Exec has Forbid()
 *    for us during the call.
 *
 *    If you have an extended library structure you must specify the size
 *    of the extended structure in MakeLibrary().
 */

#include "libfuncs.h"

LIB *
CInit(segment)
{
    extern long SysBase;
    extern long DOSBase;

    SysBase = *(long *)4;
    DOSBase = OpenLibrary("dos.library", 0);
    if (DOSBase == NULL)
	return(NULL);
    DResBase = Lib = MakeLibrary(LibVectors,NULL,NULL,sizeof(LIB),NULL);
    Lib->lib_Node.ln_Type = NT_LIBRARY;
    Lib->lib_Node.ln_Name = Libname;
    Lib->lib_Flags = LIBF_CHANGED|LIBF_SUMUSED;
    Lib->lib_Version  = VERSION;
    Lib->lib_Revision = REVISION;
    Lib->lib_IdString = (APTR)Libid;
    Seglist = segment;
    AddLibrary(Lib);
    return(Lib);
}

/*
 *    Open is given the library pointer and the version request.  Either
 *    return the library pointer or NULL.  Remove the DELAYED-EXPUNGE flag.
 *    Exec has Forbid() for us during the call.
 */

LIB *
LibOpen(lib,version)
LIB *lib;
{
    ++lib->lib_OpenCnt;
    lib->lib_Flags &= ~LIBF_DELEXP;
    return(lib);
}

/*
 *    Close is given the library pointer and the version request.  Be sure
 *    not to decrement the open count if already zero.	If the open count
 *    is or becomes zero AND there is a LIBF_DELEXP, we expunge the library
 *    and return the seglist.  Otherwise we return NULL.
 *
 *    Note that this routine never sets LIBF_DELEXP on its own.
 *
 *    Exec has Forbid() for us during the call.
 */

LibClose(lib)
LIB *lib;
{
    if (lib->lib_OpenCnt && --lib->lib_OpenCnt)
	return(NULL);
    if (lib->lib_Flags & LIBF_DELEXP)
	return(LibExpunge(lib));
    return(NULL);
}

/*
 *    We expunge the library and return the Seglist ONLY if the open count
 *    is zero.	If the open count is not zero we set the DELAYED-EXPUNGE
 *    flag and return NULL.
 *
 *    Exec has Forbid() for us during the call.  NOTE ALSO that Expunge
 *    might be called from the memory allocator and thus we CANNOT DO A
 *    Wait() or otherwise take a long time to complete (straight from RKM).
 *
 *    Apparently RemLibrary(lib) calls our expunge routine and would
 *    therefore freeze if we called it ourselves.  As far as I can tell
 *    from RKM, LibExpunge(lib) must remove the library itself as shown
 *    below.
 */

LibExpunge(lib)
LIB *lib;
{
    extern long DOSBase;

    if (lib->lib_OpenCnt) {
	lib->lib_Flags |= LIBF_DELEXP;
	return(NULL);
    }
    if (DOSBase) {
	CloseLibrary(DOSBase);
	DOSBase = NULL;
    }
    Remove(lib);
    FreeMem((char *)lib-lib->lib_NegSize, lib->lib_NegSize+lib->lib_PosSize);
    return(Seglist);
}

\Rogue\Monster\
else
  echo "will not over write core/library.c"
fi
if [ `wc -c core/library.c | awk '{printf $1}'` -ne 4923 ]
then
echo `wc -c core/library.c | awk '{print "Got " $1 ", Expected " 4923}'`
fi
if `test ! -s libref.c`
then
echo "writing libref.c"
cat > libref.c << '\Rogue\Monster\'

/*
 *  LIBREF.C
 *
 *  LIBREF [cmdfile]
 *  (default func.def)
 */

#include <stdio.h>
#include <fcntl.h>
#include <local/typedefs.h>

#define FLIST	struct _FLIST

FLIST {
    MNODE   Node;
    uword   RegMask;
    uword   IsAsm;
    char    FName[64];
};

extern char *MToS();

char LibGlob[64] = { "SomeUnknownLibBase" };
char MName[128] = { "ram:MakeLib.c" };
char LName[128] = { "ram:LinkTag.asm" };
char TName[128] = { "ram:LibTag.asm" };
char LibName[128] = { "ram:Lib.lib" };
MLIST FBase;

main(ac,av)
char *av[];
{
    FILE *fi;
    char *file = "func.def";
    char buf[128];

    puts("LIBREF V1.00 Sept 1988, (c)Copyright 1988 Matthew Dillon, All Rights Reserved");
    puts("  source/executable Freely distributable for non-profit only.  May be USED");
    puts("  in-house to generate commercial libraries.");

    NewList(&FBase);
    if (ac == 2)
	file = av[1];
    fi = fopen(file, "r");
    if (!fi) {
	printf("%s not found\n", file);
	puts("LIBREF [cmdfile]");
	exit(1);
    }
    while (fgets(buf, sizeof(buf), fi)) {
	buf[strlen(buf)-1] = 0;
	if (!buf[0] || buf[0] == ';')
	    continue;
	switch((buf[0]<<8)|buf[1]) {
	case '1=':
	    sscanf(buf+2, "%s", MName);
	    break;
	case '2=':
	    sscanf(buf+2, "%s", LName);
	    break;
	case '3=':
	    sscanf(buf+2, "%s", TName);
	    break;
	case '4=':
	    sscanf(buf+2, "%s", LibGlob);
	    break;
	case '5=':
	    sscanf(buf+2, "%s", LibName);
	    break;
	case '6=':
	case '7=':
	case '8=':
	case '9=':
	    break;
	default:
	    scanfile(buf, buf, sizeof(buf));
	    break;
	}
    }
    fclose(fi);
    {
	FILE *fi = fopen(MName, "w");
	if (!fi) {
	    printf("Unable to open %s for write\n", MName);
	    exit(-1);
	}
	GenerateMakeLib(fi);
	fclose(fi);
	fi = fopen(TName, "w");
	if (!fi) {
	    printf("Unable to open %s for write\n", MName);
	    exit(-1);
	}
	GenerateTags(fi);
	fclose(fi);
	GenerateLinkLib(LName, strlen(LName));
    }
}

/*
 * scan file for functions
 *
 *  *FUNC=NAME REGS	 (C, assembly tag entry, add extra _)
 *  ;FUNC=NAME REGS	 (assembly, direct entry)
 *		 D0-2/A0/A1/A2 ...
 *		 REGISTERS ALWAYS LOADED D0-D7,A0-A7	(A6,A7 cannot be used)
 *
 *  starting within the first 16 lines of the file.
 */

scanfile(file, buf, bufsize)
char *file;
char *buf;
long bufsize;
{
    FILE *fi;
    short i;

    fi = fopen(file, "r");
    if (!fi) {
	printf("Unable to open file %s\n", file);
	return(-1);
    }
    for (i = 0; i < 16; ++i) {
	short isasm;
	short j;
	if (fgets(buf, bufsize, fi) == NULL)
	    return(0);
	for (j = 0; buf[j] == ' ' || buf[j] == 9; ++j);
	isasm = (buf[j] == ';' || buf[j] == 'A');
	++j;
	if (strncmp(buf+j, "FUNC=", 5) == 0) {
	    i = 0;
	    AddFunction(buf+j+5, isasm);
	}
    }
    fclose(fi);
}

/*
 *  FuncName	Regs	(NULL SPECIAL)
 */

AddFunction(buf, isasm)
char *buf;
{
    char fname[64];
    char regs[64];
    uword regmask = 0;	   /*  A7-A0,D7-D0 */

    if (sscanf(buf, "%s %s", fname, regs) != 2) {
	printf("Argument Error: %s\n", buf);
	return(-1);
    }
    if (strcmp(regs, "-") == 0)
	regs[0] = 0;
    {
	register short i;
	register short s, e;
	for (i = 0; regs[i]; ) {
	    s = e = regs[i+1] - '0';
	    if (s < 0 || s > 7)
		goto fail;
	    switch(regs[i]) {
	    case 'A':
		s += 8;
		e += 8;
		i += 2;
		if (regs[i] == '-') {
		    if (regs[i+1] != 'A')
			goto fail;
		    e = regs[i+2] - '0';
		    if (e < 0 || e > 7)
			goto fail;
		    e += 8;
		    i += 3;
		}
		break;
	    case 'D':
		i += 2;
		if (regs[i] == '-') {
		    if (regs[i+1] != 'D')
			goto fail;
		    e = regs[i+2] - '0';
		    if (e < 0 || e > 7)
			goto fail;
		    i += 3;
		}
		break;
	    default:
		goto fail;
	    }
	    while (s <= e) {
		regmask |= 1 << s;
		++s;
	    }
	    if (regs[i]) {
		if (regs[i] != '/')
		    goto fail;
		++i;
	    }
	}
    }
    /*
    printf("Function: %-10s Regs: %04x  Asm: %d\n", fname, regmask, isasm);
    */
    {
	register FLIST *fl = malloc(sizeof(FLIST));
	if (fl) {
	    fl->RegMask = regmask;
	    fl->IsAsm	= isasm;
	    if (strcmp(fname, "NULL") == 0)
		fl->FName[0] = 0;
	    else
		strcpy(fl->FName, fname);
	    AddTail(&FBase, fl);
	}
    }
    return(0);
fail:
    printf("Bad Register Spec: %s\n", buf);
    return(-1);
}

GenerateMakeLib(fi)
FILE *fi;
{
    register FLIST *fl;
    short i;

    fprintf(fi, "\n/*\n * Machine Generated Library Vectors\n */\n\n");
    fprintf(fi, "#ifndef NULL\n#define NULL 0L\n#endif\n\n");
    fprintf(fi, "extern long _LibOpen(), _LibClose(), _LibExpunge();\n");
    for (fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
	if (fl->FName[0]) {
	    if (fl->IsAsm) {    /*  If assembly, direct reference   */
		fprintf(fi, "extern long l%s();\n", fl->FName);
	    } else {		/*  If not, reference to tag	    */
		fprintf(fi, "extern long _l%s();\n", fl->FName);
	    }
	}
    }

    fprintf(fi, "\n\n/*\n * -30-6*X\n */\n\n");
    fprintf(fi, "long (*LibVectors[])() = {\n");
    fprintf(fi, "    _LibOpen, _LibClose, _LibExpunge, NULL,\n\n");
    for (i = 0, fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
	if (fl->FName[0]) {
	    if (fl->IsAsm)
		fprintf(fi, "    l%-16s,    /*  %3ld  %-20s  */\n", fl->FName, -30-6*i, MToS(fl->RegMask));
	    else
		fprintf(fi, "    _l%-15s,    /*  %3ld  %-20s  */\n", fl->FName, -30-6*i, MToS(fl->RegMask));
	} else {
	    fprintf(fi, "    NULL,\n");
	}
	++i;
    }
    fprintf(fi, "    (long (*)())-1\n};\n\n");
}

GenerateTags(fi)
FILE *fi;
{
    register FLIST *fl;

    fprintf(fi, "\n");
    fprintf(fi, "\t; Machine Generated File\n");
    fprintf(fi, "\t; Tags for library routines which are in C\n\n");
    fprintf(fi, "\tFAR\tDATA\n\n");
    for (fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
	uword mask;
	if (fl->IsAsm || !fl->FName[0])
	    continue;
	fprintf(fi, "\n");
	fprintf(fi, "\t\tpublic _l%s\n\t\tpublic __l%s\n\n", fl->FName, fl->FName);
	fprintf(fi, "__l%s:\n", fl->FName);

	/*
	 *  Save the set D2/D3/A6, but don't bother saving D2 or
	 *  D2 and D3 if passed as arguments.
	 */

	mask = 0x400C;
	MoveToStack(fi, mask);          /*  Save some args  */
	MoveToStack(fi, fl->RegMask);   /*  Push some args  */
	fprintf(fi, "\t\tbsr\t_l%s\n", fl->FName);
	PopStack(fi, fl->RegMask);
	MoveFromStack(fi, mask);
	fprintf(fi,"\t\trts\n");
    }
}


/*
 *  Generate the link library.	Create N output modules for
 *  each function reference by appending a number to the name
 */

GenerateLinkLib(dir, dirlen)
char *dir;
short dirlen;
{
    char tmp[128];
    short i, nobj, nj;
    FILE *fi;
    FILE *fi2;
    register FLIST *fl;
    register short off;

    strcpy(dir+dirlen, "Makefile");
    fi = fopen(dir, "w");
    if (!fi)
	goto fail;
    strcpy(dir+dirlen, "Ordin");
    fi2 = fopen(dir, "w");
    if (!fi2)
	goto fail;

    fputs("\nAFLAGS = -D\n\n", fi);

    nj = 0;
    nobj = 1;
    for (fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
	if (!fl->FName[0])
	    continue;
	fprintf(fi2, "%s.o\n", fl->FName);
	if (nj == 0)
	    fprintf(fi, "OBJ%d = ", nobj);
	fprintf(fi, "%s.o ", fl->FName);
	nj += strlen(fl->FName) + 3;
	if (nj > 70) {
	    fprintf(fi, "\n");
	    nj = 0;
	    ++nobj;
	}
    }
    fprintf(fi2, "lvo.o\n");
    if (nj == 0)
	fprintf(fi, "OBJ%d = ", nobj);
    fprintf(fi, "lvo.o\n");
    fclose(fi2);
    fprintf(fi, "\nall:\t");
    for (i = 1; i <= nobj; ++i) {
	fprintf(fi, "$(OBJ%d) ", i);
    }
    fprintf(fi, "\n");
    fprintf(fi, "\tord %s ", dir);
    strcpy(dir+dirlen, "Ordout");
    fprintf(fi, "\t%s\n", dir);
    fprintf(fi, "\t-Delete %s\n", LibName);
    fprintf(fi, "\tlb %s -f %s\n", LibName, dir);

    strcpy(dir+dirlen, "lvo.asm");


    fclose(fi);
    fi = fopen(dir, "w");
    if (!fi)
	goto fail;
    for (fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
	if (fl->FName[0])
	    fprintf(fi, "\t\tpublic\t_LVO%s\n", fl->FName);
    }
    for (off = -30, fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
	if (!fl->FName[0]) {
	    off -= 6;
	    continue;
	}
	sprintf(tmp, "_LVO%s", fl->FName);
	fprintf(fi, "%-24s\tequ\t%d\n", tmp, off);
	off -= 6;
    }
    fclose(fi);

    for (fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
	if (!fl->FName[0])
	    continue;
	strcpy(dir+dirlen, "TEMP");
	strcpy(tmp, dir);

	strcpy(dir+dirlen, fl->FName);
	strcat(dir+dirlen, ".asm");
	fi = fopen(tmp, "w");
	if (!fi)
	    goto fail;

	fprintf(fi,"\n; Machine Generated Link Tag\n\n");
	fprintf(fi,"\t\tFAR\tDATA\n");
	fprintf(fi,"\t\tpublic\t_LVO%s\n", fl->FName);
	fprintf(fi,"\t\tpublic\t_%s\n", LibGlob);
	fprintf(fi,"\t\tpublic\t_%s\n\n", fl->FName);
	fprintf(fi,"_%s:\n", fl->FName);

	/*
	 *  Generate linker tag to assembly.  If neither A0 or A1 is
	 *  used as an argument, use one as the link register, else
	 *  save A6 and use that.
	 *
	 *  If A2-A6 (inc A6 above), D2-D6 are required to hold
	 *  parameters, they are saved before the call, restored
	 *  after.   If they are not required to hold any parameters,
	 *  a JMP is issued instead of a JSR.
	 */

	{
	    uword argmask = fl->RegMask;
	    uword savmask = fl->RegMask;
	    short areg = 6;
	    if (!(argmask & 0x0100))   /*  A0 not used */
		areg = 0;
	    if (!(argmask & 0x0200))   /*  A1 not used */
		areg = 1;
	    savmask |= 1 << (areg+8);  /*  Add register usage  */
	    MoveToStack(fi, savmask & 0xFCFC);                          /*  save some regs      */
	    LoadFromStack(fi, argmask, 4+Offset(argmask & 0xFCFC));     /*  load params         */
	    fprintf(fi,"\t\tmove.l\t_%s,A%d\n", LibGlob, areg);
	    if (savmask & 0xFCFC) {
		fprintf(fi, "\t\tjsr\t_LVO%s(A%d)\n", fl->FName, areg);
		MoveFromStack(fi, savmask & 0xFCFC);                    /*  restore some regs   */
		fprintf(fi,"\t\trts\n");
	    } else {
		fprintf(fi, "\t\tjmp\t_LVO%s(A%d)\n", fl->FName, areg);
	    }
	}
	fclose(fi);
	if (cmp_file(tmp, dir) == 0) {  /*  update only if changed  */
	    DeleteFile(dir);
	    Rename(tmp, dir);
	}
    }
    return(0);
fail:
    printf("Unable to open %s\n", dir);
    return(-1);
}

char *
MToS(mask)
register uword mask;
{
    register short i;
    register short j = 0;
    static char buf[64];

    for (i = 0; i < 8; ++i, mask >>= 1) {
	if (mask & 1) {
	    if (j)
		buf[j++] = '/';
	    buf[j++] = 'D';
	    buf[j++] = i + '0';
	}
    }
    for (i = 0; i < 8; ++i, mask >>= 1) {
	if (mask & 1) {
	    if (j)
		buf[j++] = '/';
	    buf[j++] = 'A';
	    buf[j++] = i + '0';
	}
    }
    buf[j++] = 0;
    return(buf);
}


MoveToStack(fi, mask)
FILE *fi;
{
    char *str = MToS(mask);
    if (!str[0])
	return(0);
    if (!str[2]) {
	fprintf(fi, "\t\tmove.l\t%s,-(sp)\n", str);
    } else {
	fprintf(fi, "\t\tmovem.l\t%s,-(sp)\n", str);
    }
}

MoveFromStack(fi, mask)
FILE *fi;
uword mask;
{
    char *str = MToS(mask);

    if (!str[0])
	return(0);
    if (!str[2])
	fprintf(fi, "\t\tmove.l\t(sp)+,%s\n", str);
    else
	fprintf(fi, "\t\tmovem.l\t(sp)+,%s\n", str);
}

LoadFromStack(fi, mask, offset)
{
    char *str = MToS(mask);

    if (!str[0])
	return(0);
    if (!str[2])
	fprintf(fi, "\t\tmove.l\t%d(sp),%s\n", offset, str);
    else
	fprintf(fi, "\t\tmovem.l\t%d(sp),%s\n", offset, str);
}


PopStack(fi, mask)
FILE *fi;
uword mask;
{
    register short j;
    if (j = Offset(mask)) {
	if (j > 8)
	    fprintf(fi,"\t\tadd.w\t#%d,A7\n", j);
	else
	    fprintf(fi,"\t\taddq.l\t#%d,A7\n", j);
    }
}

Offset(mask)
uword mask;
{
    register short i, j;
    for (i = j = 0; i < 16; ++i) {
	if (mask & (1 << i))
	    ++j;
    }
    return(j*4);
}

cmp_file(name1, name2)
char *name1;
char *name2;
{
    short i, fd1, fd2;
    static char buf1[1024];
    static char buf2[1024];

    fd1 = open(name1, O_RDONLY);
    if (fd1 < 0)
	return(0);
    fd2 = open(name2, O_RDONLY);
    if (fd2 < 0) {
	close(fd1);
	return(0);
    }
    while ((i = read(fd1, buf1, sizeof(buf1))) > 0) {
	if (read(fd2, buf2, i) != i)
	    goto fail;
	if (bcmp(buf1, buf2, i) == 0)
	    goto fail;
    }
    if (read(fd2, buf2, 1) != 0)
	goto fail;
    close(fd1);
    close(fd2);
    return(1);
fail:
    close(fd1);
    close(fd2);
    return(0);
}

\Rogue\Monster\
else
  echo "will not over write libref.c"
fi
if [ `wc -c libref.c | awk '{printf $1}'` -ne 12306 ]
then
echo `wc -c libref.c | awk '{print "Got " $1 ", Expected " 12306}'`
fi
echo "Finished archive 3 of 3"
# if you want to concatenate archives, remove anything after this line
exit
-- 
Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
Have five nice days.