dillon@CORY.BERKELEY.EDU (Matt Dillon) (10/17/87)
Here is a revised working sample library for Aztec C. It fixes a
bug and now uses MakeLibrary() instead of a hardwired library.
-Matt
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
# Makefile
# README
# hlib.asm
# test.c
# testlib.c
# This archive created: Sat Oct 17 11:38:41 1987
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'Makefile'" '(623 characters)'
if test -f 'Makefile'
then
echo shar: "will not over-write existing file 'Makefile'"
else
cat << \!Funky!Stuff! > 'Makefile'
# You must modify SYMBOLS to some temporary directory if you do not
# already have a complete precompiled symbol table (*/*.h .. only
# sub-directory includes, not top level includes). Remember to
# use +L when generating the precompiled symbol table.
SYMBOLS= vd0:include/symbols.m
all: lib test
lib:
cc +BCDL +p +I$(SYMBOLS) testlib.c -o ram:testlib.o
ln +Q ram:testlib.o -lcl32
copy ram:testlib libs:testlib.library
delete ram:testlib ram:testlib.o
test:
cc +L +I$(SYMBOLS) test.c -o ram:test.o
as hlib.asm -o ram:hlib.o
ln +Q ram:test.o ram:hlib.o -lc32
delete ram:test.o
!Funky!Stuff!
fi # end of overwriting check
echo shar: "extracting 'README'" '(2522 characters)'
if test -f 'README'
then
echo shar: "will not over-write existing file 'README'"
else
cat << \!Funky!Stuff! > 'README'
Working Library Skeleton for AZTEC C.
By Matthew Dillon
Placed in Public Domain
This is an example library for Aztec C. It will not work with
Lattice C due to extensive Manxisms. This library does not use the
auto-init method and thus provides a contrast with the RKM example. Note
especially the compile time options required (in the Makefile). Here are
the reasons:
+B No reference to startup code.
+CD Large code and data model. Alternately you can setup A4
on every entry point and use the small code and data model.
+L 32 bit integers. My preference.. not required when
designing your own libraries, of course. Required for
this particular example, however.
+p compatibility option... Aztec automagically saves D2 and D3
on function calls. Otherwise we would have to do it by hand
on every entry point. This also sets +L automatically.
LINK LIBRARY:
The routines in this example expect arguments on the stack. You
will note the link library is incredibly simple ... the assembly
to make a library call is only two instructions. Note that since the
arguments are expected on the stack, the link library routines cannot
save anything on the stack. A0-A1 D0-D1 are scratch however and I
simply use A0.
Thus this library is optimized for C->C calls. You want your library
to follow the AMIGA STANDARD, which is that only A0-A1 D0-D1 may be
trashed. The only register Aztec C calls will not automatically
save is A6 and this must be done WITHIN your actual library routines
(see testlib.c).
FILES:
Makefile
For making the library itself. I make reference to a
precompiled symbol table which is all the AMIGA includes
(none of the Aztec includes) */*.h . That is, all the
include files in sub-directories but none of the
top-level include files. You will have to either generate
such a symbol table yourself or simply figure out which
#include's you need to make. If generating the symbol
table yourself, remember to use the +L option.
hlib.asm
Example 'link' library... what you need to link with your
C programs to be able to call library functions after openning
the library and sticking the library base into the proper
global variable.
testlib.c
The source to the library itself.
test.c
The source to the test program. Must be linked with
hlib.o . Without arguments, the library is openned, the
routines executed, then closed. With arguments, the
program does an expunge (via allocating too much memory).
!Funky!Stuff!
fi # end of overwriting check
echo shar: "extracting 'hlib.asm'" '(216 characters)'
if test -f 'hlib.asm'
then
echo shar: "will not over-write existing file 'hlib.asm'"
else
cat << \!Funky!Stuff! > 'hlib.asm'
; TestBase
FAR code
FAR data
public _TestBase
public _Sub
public _Add
_Sub: move.l _TestBase,A0
jmp -36(A0)
_Add: move.l _TestBase,A0
jmp -30(A0)
!Funky!Stuff!
fi # end of overwriting check
echo shar: "extracting 'test.c'" '(668 characters)'
if test -f 'test.c'
then
echo shar: "will not over-write existing file 'test.c'"
else
cat << \!Funky!Stuff! > 'test.c'
/*
* Test the library
*/
long TestBase;
extern long OpenLibrary();
extern void *AllocMem();
extern long Add(), Sub();
main(ac,av)
char *av[];
{
if (ac != 1) {
register long i = 256000;
register char *ptr;
puts("Expunging by allocating too much memory");
while (ptr = AllocMem(i,0)) {
FreeMem(ptr,i);
i <<= 1;
}
puts("ok");
exit(1);
}
TestBase = OpenLibrary("testlib.library",0);
if (TestBase) {
printf("Open OK %08xl\n", TestBase);
printf("ADD 1 -> %ld (should be 2)\n", Add(1L));
printf("SUB 33-> %ld (should be 32)\n", Sub(33L));
CloseLibrary(TestBase);
puts("Close OK");
} else {
puts("Unable to Open");
}
}
!Funky!Stuff!
fi # end of overwriting check
echo shar: "extracting 'testlib.c'" '(5596 characters)'
if test -f 'testlib.c'
then
echo shar: "will not over-write existing file 'testlib.c'"
else
cat << \!Funky!Stuff! > 'testlib.c'
/*
* TESTLIB.C
*
* Example fully working library for Aztec C ... with comments (which is
* a miracle in itself). By Matthew Dillon. PUBLIC DOMAIN.
*
* Aztec Compile with +BCDL
* +B No startup reference
* +C Large code
* +D Large data
* +L 32 bit Integers
*
* 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.
*/
#asm
; RLIB.ASM
;
; Run-time library tag
FAR code
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 0 ;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 "testlib.library",0
_Libid: dc.b "testlib.library 1.0 (02 Oct 1987)",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
_ALibOpen: cifc _LibOpen
_ALibClose: cifc _LibClose
_ALibExpunge: cifc _LibExpunge
#endasm
extern char Libname[1];
extern char Libid[1];
extern long ALibExpunge(), ALibClose(), ALibOpen();
extern long Lib_Add(), Lib_Sub();
typedef struct Library LIB;
LIB *Lib; /* Library Base pointer */
long Seglist; /* Save the DOS seglist */
extern LIB *MakeLibrary();
extern void *AllocMem();
/*
* 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().
*/
LIB *
CInit(segment)
{
extern long SysBase;
static long (*Vectors[])() = {
ALibOpen,ALibClose,ALibExpunge,NULL,
Lib_Add, Lib_Sub, (long (*)())-1
};
SysBase = *(long *)4;
Lib = MakeLibrary(Vectors,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 = 0;
Lib->lib_Revision = 0;
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;
{
if (lib->lib_OpenCnt) {
lib->lib_Flags |= LIBF_DELEXP;
return(NULL);
}
Remove(lib);
FreeMem((char *)lib-lib->lib_NegSize, lib->lib_NegSize+lib->lib_PosSize);
return(Seglist);
}
/*
* The Library routines themselves. Note that we must also save A6 if
* any library routine makes a library call to another library. These
* examples do not and thus you can remove the #asm statements in them if
* you wish... just DON'T FORGET!
*
* The reason A6 must be saved is that Aztec library interface routines
* (e.g. FindTask(), OpenWindow(), etc....) trash A6 on purpose to make
* the interface routine faster.
*
* D2 and D3 are automatically saved/restored via the +p compile option
* A0,A1,D0,D1 are always scratch. In an assembly interface, these might
* also contain arguments... but they are still scratch.
*/
Lib_Add(n)
{
#asm
move.l A6,-(sp)
#endasm
++n; /* do stuff here */
#asm
move.l (sp)+,A6
#endasm
return(n);
}
Lib_Sub(n)
{
#asm
move.l A6,-(sp)
#endasm
--n; /* do stuff here */
#asm
move.l (sp)+,A6
#endasm
return(n);
}
!Funky!Stuff!
fi # end of overwriting check
exit 0
# End of shell archive