move the tests under the debug folder
[AROS.git] / debug / test / sdi / examples / libraries / example_lib.c
blob6706d5b3559c1b38ac390b276fe9e5c90d51bee5
1 /* Example source
3 Name: example_lib.c
4 Versionstring: $VER: example_lib.c 1.2 (21.06.2007)
5 Author: Jens Langner
6 Distribution: PD
7 Description: shows how the SDI_lib.h header include can be used
9 1.0 05.10.04 : initial version showing how the SDI_lib.h headers can help
10 when used for maintaining AmigaOS compatible shared library
11 interfaces upon compatible operating systems like AmigaOS3,
12 AmigaOS4 and MorphOS.
14 1.1 20.06.07 : moved LIBFUNC to be first in line acording to changes in
15 SDI_lib.h. (Guido Mersmann)
17 1.2 21.06.07 : added missing libvector to MorphOS/AmigaOS3 libvectors[]
18 (Guido Mersmann)
20 Please note that this example is just for educational purposes and wasn't
21 checked for complete correctness. However, it should compile and probably also
22 work as expected. But please note that its purpose is to show how a shared
23 library can held platform independent over all different available AmigaOS
24 platforms like OS3, OS4 and MorphOS.
26 Feel free to comment and submit any suggestions directly to
27 Jens.Langner@light-speed.de
31 #include <exec/types.h>
32 #include <exec/libraries.h>
33 #include <exec/resident.h>
34 #include <dos/dos.h>
36 #include <proto/exec.h>
38 #ifdef __amigaos4__
39 #include <exec/emulation.h>
40 #endif
42 #include <stdarg.h>
43 #include <stdio.h>
44 #include <ctype.h>
46 #include <SDI_lib.h>
47 #include <SDI_stdarg.h>
49 #include "libproto.h"
51 #define VERSION 1
52 #define REVISION 4
53 #define DATE "25.08.2014"
54 #define VERS "example.library 1.4"
55 #define VSTRING "example.library 1.4 25.08.2014)\r\n"
56 #define VERSTAG "\0$VER: example.library 1.4 25.08.2014)"
58 static const char UserLibName[] = "example.library";
59 static const char UserLibID[] = "\0$VER: example.library 1.4 25.08.2014)";
61 #if defined(__MORPHOS__) || defined(__AROS__)
62 struct ExecBase *SysBase;
63 #endif
65 /******************************************************************************/
66 /* >> User defineable library functions start here << */
67 /* The following section should illustrate how the SDI_lib.h macros make it */
68 /* possible to easily maintain a typical Amiga shared library interface if */
69 /* compatibility over all common (OS3/OS4, MorphOS) is required */
70 /******************************************************************************/
72 /******************************************************************************/
73 /* Local Structures & Prototypes */
74 /******************************************************************************/
77 // let us now create the libvector.
78 // Please note that the start of the vectors has to be always the "LFUNC_FAS"
79 // macro
80 #define libvector LFUNC_FAS(SayHelloOS4) \
81 LFUNC_FA_(SayHelloOS3) \
82 LFUNC_FA_(SayHelloMOS) \
83 LFUNC_FA_(Uppercase) \
84 LFUNC_FA_(SPrintfA) \
85 LFUNC_VA_(SPrintf)
87 // Now the real implementations of the library functions above like in
88 // a normal AmigaOS shared library follow
89 LIBPROTO(SayHelloOS4, char *, REG(a6, UNUSED __BASE_OR_IFACE))
91 return "Hello AmigaOS4!!!";
94 LIBPROTO(SayHelloOS3, char *, REG(a6, UNUSED __BASE_OR_IFACE))
96 return "Hello AmigaOS3!!!";
99 LIBPROTO(SayHelloMOS, char *, REG(a6, UNUSED __BASE_OR_IFACE))
101 return "Hello MorphOS!!!";
104 LIBPROTO(Uppercase, char *, REG(a6, UNUSED __BASE_OR_IFACE), REG(a0, char *txt))
106 char *p = txt;
108 while(*p)
110 *p = toupper(*p);
111 p++;
114 return txt;
117 LIBPROTO(SPrintfA, char *, REG(a6, UNUSED __BASE_OR_IFACE), REG(a0, char *buf), REG(a1, char *format), REG(a2, RAWARG args))
119 RawDoFmt(format, args, NULL, buf);
121 return(buf);
124 #if defined(__amigaos4__)
125 // for AmigaOS4 varargs functions are separate entries in the interface structure and
126 // hence must be defined as separate functions
127 LIBPROTOVA(SPrintf, char *, REG(a6, UNUSED __BASE_OR_IFACE), REG(a0, char *buf), REG(a1, char *format), ...)
129 char *ret;
130 VA_LIST args;
132 VA_START(args, format);
133 // the SPrintf function will be call via the interface
134 ret = SPrintfA(buf, format, VA_ARG(args, ULONG));
135 VA_END(args);
137 return(ret);
139 #elif defined(__MORPHOS__)
140 // define stub functions for all functions in the jump table which take the
141 // parameters from the emulated 68k registers. The parameters don't need to
142 // be specified again, because these are really functions taking no direct
143 // parameters. Only the type of the returned value is required.
144 LIBSTUB(SayHelloOS4, char *)
146 __BASE_OR_IFACE = (__BASE_OR_IFACE_TYPE)REG_A6;
147 return CALL_LFUNC_NP(SayHelloOS4);
150 LIBSTUB(SayHelloOS3, char *)
152 __BASE_OR_IFACE = (__BASE_OR_IFACE_TYPE)REG_A6;
153 return CALL_LFUNC_NP(SayHelloOS3);
156 LIBSTUB(SayHelloMOS, char *)
158 __BASE_OR_IFACE = (__BASE_OR_IFACE_TYPE)REG_A6;
159 return CALL_LFUNC_NP(SayHelloMOS);
162 LIBSTUB(Uppercase, char *)
164 __BASE_OR_IFACE = (__BASE_OR_IFACE_TYPE)REG_A6;
165 return CALL_LFUNC(Uppercase, (char *)REG_A0);
168 LIBSTUB(SPrintfA, char *)
170 __BASE_OR_IFACE = (__BASE_OR_IFACE_TYPE)REG_A6;
171 return CALL_LFUNC(SprintfA, (char)REG_A0, (char *)REG_A1, (APTR)REG_A2);
173 #elif defined(__AROS__)
174 // we use external file
175 #endif
177 /******************************************************************************/
178 /* Starting from here starts the "standard" Amiga library initialization. */
179 /* All the above should have illustrated enough how "easy" it is to use the */
180 /* SDI_lib.h header file and how it can help in developing a shared library */
181 /* for multiple AmigaOS compatible platforms. */
182 /******************************************************************************/
184 #if defined(__amigaos4__)
186 LIBFUNC static struct LibraryHeader * LibInit (struct LibraryHeader *base, BPTR librarySegment, struct ExecIFace *pIExec);
187 LIBFUNC static BPTR LibExpunge (struct LibraryManagerInterface *Self);
188 LIBFUNC static struct LibraryHeader * LibOpen (struct LibraryManagerInterface *Self, ULONG version);
189 LIBFUNC static BPTR LibClose (struct LibraryManagerInterface *Self);
191 #elif defined(__MORPHOS__)
193 LIBFUNC static struct LibraryHeader * LibInit (struct LibraryHeader *base, BPTR librarySegment, struct ExecBase *sb);
194 LIBFUNC static BPTR LibExpunge(void);
195 LIBFUNC static struct LibraryHeader * LibOpen (void);
196 LIBFUNC static BPTR LibClose (void);
197 LIBFUNC static LONG LibNull (void);
199 #elif defined(__AROS__)
201 #include <aros/libcall.h>
203 static AROS_UFP3 (struct LibraryHeader *, LibInit,
204 AROS_UFPA(struct LibraryHeader *, base, D0),
205 AROS_UFPA(BPTR, librarySegment, A0),
206 AROS_UFPA(struct ExecBase *, sb, A6)
208 static AROS_LD1 (struct LibraryHeader *, LibOpen,
209 AROS_LPA (UNUSED ULONG, version, D0),
210 struct LibraryHeader *, base, 1, example
212 static AROS_LD0 (BPTR, LibClose,
213 struct LibraryHeader *, base, 2, example
215 static AROS_LD1(BPTR, LibExpunge,
216 AROS_LPA(UNUSED struct LibraryHeader *, __extrabase, D0),
217 struct LibraryHeader *, base, 3, example
220 #else
222 LIBFUNC static struct LibraryHeader * LibInit (REG(a0, BPTR Segment), REG(d0, struct LibraryHeader *lh), REG(a6, struct ExecBase *sb));
223 LIBFUNC static BPTR LibExpunge (REG(a6, struct LibraryHeader *base));
224 LIBFUNC static struct LibraryHeader * LibOpen (REG(a6, struct LibraryHeader *base));
225 LIBFUNC static BPTR LibClose (REG(a6, struct LibraryHeader *base));
226 LIBFUNC static LONG LibNull (void);
228 #endif
230 /******************************************************************************/
231 /* Dummy entry point and LibNull() function all in one */
232 /******************************************************************************/
234 #if defined(__amigaos4__)
235 int _start(void)
236 #elif defined(__AROS__)
237 __startup int Main(void)
238 #else
239 int Main(void)
240 #endif
242 return RETURN_FAIL;
245 #if !defined(__amigaos4__)
246 LIBFUNC static LONG LibNull(VOID)
248 return(0);
250 #endif
252 /******************************************************************************/
253 /* Local data structures */
254 /******************************************************************************/
256 #if defined(__amigaos4__)
257 /* ------------------- OS4 Manager Interface ------------------------ */
258 STATIC ULONG LibObtain(struct LibraryManagerInterface *Self)
260 return(Self->Data.RefCount++);
263 STATIC ULONG LibRelease(struct LibraryManagerInterface *Self)
265 return(Self->Data.RefCount--);
268 STATIC CONST APTR LibManagerVectors[] =
270 (APTR)LibObtain,
271 (APTR)LibRelease,
272 (APTR)NULL,
273 (APTR)NULL,
274 (APTR)LibOpen,
275 (APTR)LibClose,
276 (APTR)LibExpunge,
277 (APTR)NULL,
278 (APTR)-1
281 STATIC CONST struct TagItem LibManagerTags[] =
283 {MIT_Name, (ULONG)"__library"},
284 {MIT_VectorTable, (ULONG)LibManagerVectors},
285 {MIT_Version, 1},
286 {TAG_DONE, 0}
289 /* ------------------- Library Interface(s) ------------------------ */
291 STATIC CONST APTR LibVectors[] =
293 (APTR)LibObtain,
294 (APTR)LibRelease,
295 (APTR)NULL,
296 (APTR)NULL,
297 (APTR)libvector,
298 (APTR)-1
301 STATIC CONST struct TagItem MainTags[] =
303 {MIT_Name, (ULONG)"main"},
304 {MIT_VectorTable, (ULONG)LibVectors},
305 {MIT_Version, 1},
306 {TAG_DONE, 0}
310 STATIC CONST ULONG LibInterfaces[] =
312 (ULONG)LibManagerTags,
313 (ULONG)MainTags,
314 (ULONG)0
317 /* --------------------- m68k Library stubs ------------------------ */
319 STATIC ULONG stub_OpenPPC(ULONG *regarray)
321 struct Library *Base = (struct Library *) regarray[REG68K_A6/4];
322 struct ExtendedLibrary *ExtLib = (struct ExtendedLibrary *) ((ULONG)Base + Base->lib_PosSize);
323 struct LibraryManagerInterface *Self = (struct LibraryManagerInterface *) ExtLib->ILibrary;
325 return (ULONG) Self->Open(0);
327 struct EmuTrap stub_Open = { TRAPINST, TRAPTYPE, stub_OpenPPC };
329 STATIC ULONG stub_ClosePPC(ULONG *regarray)
331 struct Library *Base = (struct Library *) regarray[REG68K_A6/4];
332 struct ExtendedLibrary *ExtLib = (struct ExtendedLibrary *) ((ULONG)Base + Base->lib_PosSize);
333 struct LibraryManagerInterface *Self = (struct LibraryManagerInterface *) ExtLib->ILibrary;
335 return (ULONG) Self->Close();
337 struct EmuTrap stub_Close = { TRAPINST, TRAPTYPE, stub_ClosePPC };
339 STATIC ULONG stub_ExpungePPC(ULONG *regarray)
341 return 0UL;
343 struct EmuTrap stub_Expunge = { TRAPINST, TRAPTYPE, stub_ExpungePPC };
345 STATIC ULONG stub_ReservedPPC(ULONG *regarray)
347 return 0UL;
349 struct EmuTrap stub_Reserved = { TRAPINST, TRAPTYPE, stub_ReservedPPC };
351 STATIC ULONG stub_SayHelloOS4PPC(ULONG *regarray)
353 struct Library *Base = (struct Library *) regarray[REG68K_A6/4];
354 struct ExtendedLibrary *ExtLib = (struct ExtendedLibrary *) ((ULONG)Base + Base->lib_PosSize);
355 struct LibraryManagerInterface *Self = (struct LibraryManagerInterface *) ExtLib->ILibrary;
357 return (char *)Self->SayHelloOS4();
359 struct EmuTrap stub_SayHelloOS4 = { TRAPINST, TRAPTYPE, stub_SayHelloOS4PPC };
361 STATIC ULONG stub_SayHelloOS3PPC(ULONG *regarray)
363 struct Library *Base = (struct Library *) regarray[REG68K_A6/4];
364 struct ExtendedLibrary *ExtLib = (struct ExtendedLibrary *) ((ULONG)Base + Base->lib_PosSize);
365 struct LibraryManagerInterface *Self = (struct LibraryManagerInterface *) ExtLib->ILibrary;
367 return (char *)Self->SayHelloOS3();
369 struct EmuTrap stub_SayHelloOS3 = { TRAPINST, TRAPTYPE, stub_SayHelloOS3PPC };
371 STATIC ULONG stub_SayHelloMOSPPC(ULONG *regarray)
373 struct Library *Base = (struct Library *) regarray[REG68K_A6/4];
374 struct ExtendedLibrary *ExtLib = (struct ExtendedLibrary *) ((ULONG)Base + Base->lib_PosSize);
375 struct LibraryManagerInterface *Self = (struct LibraryManagerInterface *) ExtLib->ILibrary;
377 return (char *)Self->SayHelloMOS();
379 struct EmuTrap stub_SayHelloMOS = { TRAPINST, TRAPTYPE, stub_SayHelloMOSPPC };
381 STATIC ULONG stub_UppercasePPC(ULONG *regarray)
383 struct Library *Base = (struct Library *) regarray[REG68K_A6/4];
384 struct ExtendedLibrary *ExtLib = (struct ExtendedLibrary *) ((ULONG)Base + Base->lib_PosSize);
385 struct LibraryManagerInterface *Self = (struct LibraryManagerInterface *) ExtLib->ILibrary;
387 return (char *)Self->Uppercase(
388 (char *)regarray[8]
391 struct EmuTrap stub_Uppercase = { TRAPINST, TRAPTYPE, stub_UppercasePPC };
393 STATIC ULONG stub_SPrintfAPPC(ULONG *regarray)
395 struct Library *Base = (struct Library *) regarray[REG68K_A6/4];
396 struct ExtendedLibrary *ExtLib = (struct ExtendedLibrary *) ((ULONG)Base + Base->lib_PosSize);
397 struct LibraryManagerInterface *Self = (struct LibraryManagerInterface *) ExtLib->ILibrary;
399 return (char *)Self->SPrintfA(
400 (char *)regarray[8],
401 (char *)regarray[9],
402 (APTR)regarray[10]
405 struct EmuTrap stub_SPrintfA = { TRAPINST, TRAPTYPE, stub_SPrintfAPPC };
407 STATIC ULONG VecTable68K[] =
409 (ULONG)&stub_Open,
410 (ULONG)&stub_Close,
411 (ULONG)&stub_Expunge,
412 (ULONG)&stub_Reserved,
413 (ULONG)&stub_SayHelloOS4,
414 (ULONG)&stub_SayHelloOS3,
415 (ULONG)&stub_SayHelloMOS,
416 (ULONG)&stub_Uppercase,
417 (ULONG)&stub_SprintfA,
418 (ULONG)-1
421 /* ----------------------- LibCreate Tags -------------------------- */
423 STATIC CONST struct TagItem LibCreateTags[] =
425 {CLT_DataSize, (ULONG)(sizeof(struct LibraryHeader))},
426 {CLT_InitFunc, (ULONG)LibInit},
427 {CLT_Interfaces, (ULONG)LibInterfaces},
428 {CLT_Vector68K, (ULONG)VecTable68K},
429 {TAG_DONE, 0}
432 #else
434 STATIC CONST APTR LibVectors[] =
436 #ifdef __MORPHOS__
437 (APTR)FUNCARRAY_32BIT_NATIVE,
438 #endif
439 #if defined(__AROS__)
440 #ifdef AROS_ABI_V1
441 AROS_SLIB_ENTRY(LibOpen, example, 1),
442 AROS_SLIB_ENTRY(LibClose, example, 2),
443 AROS_SLIB_ENTRY(LibExpunge, example, 3),
444 #else
445 AROS_SLIB_ENTRY(LibOpen, example),
446 AROS_SLIB_ENTRY(LibClose, example),
447 AROS_SLIB_ENTRY(LibExpunge, example),
448 #endif
449 #else
450 (APTR)LibOpen,
451 (APTR)LibClose,
452 (APTR)LibExpunge,
453 #endif
454 (APTR)LibNull,
455 (APTR)libvector,
456 (APTR)-1
459 STATIC CONST IPTR LibInitTab[] =
461 sizeof(struct LibraryHeader),
462 (IPTR)LibVectors,
463 (IPTR)NULL,
464 (IPTR)LibInit
467 #endif
469 /* ------------------- ROM Tag ------------------------ */
470 static const USED_VAR struct Resident ROMTag =
472 RTC_MATCHWORD,
473 (struct Resident *)&ROMTag,
474 (struct Resident *)&ROMTag + 1,
475 #if defined(__amigaos4__)
476 RTF_AUTOINIT|RTF_NATIVE, // The Library should be set up according to the given table.
477 #elif defined(__MORPHOS__)
478 RTF_AUTOINIT|RTF_PPC,
479 #elif defined(__AROS__)
480 RTF_AUTOINIT|RTF_EXTENDED,
481 #else
482 RTF_AUTOINIT,
483 #endif
484 VERSION,
485 NT_LIBRARY,
487 (APTR)UserLibName,
488 VSTRING,
489 #if defined(__amigaos4__)
490 (APTR)LibCreateTags // This table is for initializing the Library.
491 #else
492 (APTR)LibInitTab
493 #endif
496 #if defined(__MORPHOS__)
498 * To tell the loader that this is a new emulppc elf and not
499 * one for the ppc.library.
500 * ** IMPORTANT **
502 ULONG USED_VAR __amigappc__=1;
503 ULONG USED_VAR __abox__=1;
505 #endif /* __MORPHOS */
507 /******************************************************************************/
508 /* Standard Library Functions, all of them are called in Forbid() state. */
509 /******************************************************************************/
511 #ifndef __amigaos4__
512 #define DeleteLibrary(LIB) \
513 FreeMem((STRPTR)(LIB)-(LIB)->lib_NegSize, (ULONG)((LIB)->lib_NegSize+(LIB)->lib_PosSize))
514 #endif
516 #if defined(__amigaos4__)
517 static struct LibraryHeader * LibInit(struct LibraryHeader *base, BPTR librarySegment, struct ExecIFace *pIExec)
519 struct ExecBase *sb = (struct ExecBase *)pIExec->Data.LibBase;
520 IExec = pIExec;
521 #elif defined(__MORPHOS__)
522 static struct LibraryHeader * LibInit(struct LibraryHeader *base, BPTR librarySegment, struct ExecBase *sb)
524 #elif defined(__AROS__)
525 static AROS_UFH3(struct LibraryHeader *, LibInit,
526 AROS_UFHA(struct LibraryHeader *, base, D0),
527 AROS_UFHA(BPTR, librarySegment, A0),
528 AROS_UFHA(struct ExecBase *, sb, A6)
531 AROS_USERFUNC_INIT
532 #else
533 LIBFUNC static struct LibraryHeader * LibInit(REG(a0, BPTR librarySegment), REG(d0, struct LibraryHeader *base), REG(a6, struct ExecBase *sb))
535 #endif
537 SysBase = (APTR)sb;
539 base->libBase.lib_Node.ln_Type = NT_LIBRARY;
540 base->libBase.lib_Node.ln_Pri = 0;
541 base->libBase.lib_Node.ln_Name = (char *)UserLibName;
542 base->libBase.lib_Flags = LIBF_CHANGED | LIBF_SUMUSED;
543 base->libBase.lib_Version = VERSION;
544 base->libBase.lib_Revision = REVISION;
545 base->libBase.lib_IdString = (char *)UserLibID;
547 base->segList = librarySegment;
548 base->sysBase = (APTR)SysBase;
550 return(base);
551 #if defined(__AROS__)
552 AROS_USERFUNC_EXIT
553 #endif
556 #if defined(__amigaos4__)
557 static BPTR LibExpunge(struct LibraryManagerInterface *Self)
559 struct LibraryHeader *base = (struct LibraryHeader *)Self->Data.LibBase;
560 #elif defined(__MORPHOS__)
561 static BPTR LibExpunge(void)
563 struct LibraryHeader *base = (struct LibraryHeader*)REG_A6;
564 #elif defined(__AROS__)
565 static AROS_LH1(BPTR, LibExpunge,
566 AROS_LHA(UNUSED struct LibraryHeader *, __extrabase, D0),
567 struct LibraryHeader *, base, 3, example
570 AROS_LIBFUNC_INIT
571 #else
572 LIBFUNC static BPTR LibExpunge(REG(a6, struct LibraryHeader *base))
574 #endif
575 BPTR rc;
577 if(base->libBase.lib_OpenCnt > 0)
579 base->libBase.lib_Flags |= LIBF_DELEXP;
580 return(0);
583 SysBase = (APTR)base->sysBase;
584 rc = base->segList;
586 Remove((struct Node *)base);
587 DeleteLibrary(&base->libBase);
589 return(rc);
590 #if defined(__AROS__)
591 AROS_LIBFUNC_EXIT
592 #endif
595 #if defined(__amigaos4__)
596 static struct LibraryHeader *LibOpen(struct LibraryManagerInterface *Self, ULONG version)
598 struct LibraryHeader *base = (struct LibraryHeader *)Self->Data.LibBase;
599 #elif defined(__MORPHOS__)
600 static struct LibraryHeader *LibOpen(void)
602 struct LibraryHeader *base = (struct LibraryHeader*)REG_A6;
603 #elif defined(__AROS__)
604 static AROS_LH1(struct LibraryHeader *, LibOpen,
605 AROS_LHA(UNUSED ULONG, version, D0),
606 struct LibraryHeader *, base, 1, example
609 AROS_LIBFUNC_INIT
610 #else
611 LIBFUNC static struct LibraryHeader * LibOpen(REG(a6, struct LibraryHeader *base))
613 #endif
615 base->libBase.lib_Flags &= ~LIBF_DELEXP;
616 base->libBase.lib_OpenCnt++;
618 return base;
619 #if defined(__AROS__)
620 AROS_LIBFUNC_EXIT
621 #endif
624 #if defined(__amigaos4__)
625 static BPTR LibClose(struct LibraryManagerInterface *Self)
627 struct LibraryHeader *base = (struct LibraryHeader *)Self->Data.LibBase;
628 #elif defined(__MORPHOS__)
629 static BPTR LibClose(void)
631 struct LibraryHeader *base = (struct LibraryHeader *)REG_A6;
632 #elif defined(__AROS__)
633 static AROS_LH0(BPTR, LibClose,
634 struct LibraryHeader *, base, 2, example
637 AROS_LIBFUNC_INIT
638 #else
639 LIBFUNC static BPTR LibClose(REG(a6, struct LibraryHeader *base))
641 #endif
643 if(base->libBase.lib_OpenCnt > 0 &&
644 --base->libBase.lib_OpenCnt == 0)
646 if(base->libBase.lib_Flags & LIBF_DELEXP)
648 #if defined(__amigaos4__)
649 return LibExpunge(Self);
650 #elif defined(__MORPHOS__)
651 return LibExpunge();
652 #elif defined(__AROS__)
653 return AROS_LC1(BPTR, GM_UNIQUENAME(LibExpunge),
654 AROS_LCA(struct LibraryHeader *, base, D0),
655 struct LibraryHeader *, base, 3, example);
656 #else
657 return LibExpunge(base);
658 #endif
662 return 0;
663 #if defined(__AROS__)
664 AROS_LIBFUNC_EXIT
665 #endif