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