Added a test for MUIA_Listview_SelectChange.
[AROS.git] / compiler / include / SDI / doc / examples / libraries / example_lib.c
blobe330bc428d2e6f7e0ace75765378a50062a49cee
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 #define VERSION 1
50 #define REVISION 2
51 #define DATE "21.06.2007"
52 #define VERS "example.library 1.2"
53 #define VSTRING "example.library 1.2 21.06.2007)\r\n"
54 #define VERSTAG "\0$VER: example.library 1.2 (21.06.2007)"
56 static const char UserLibName[] = "example.library";
57 static const char UserLibID[] = "\0$VER: example.library 1.2 (21.06.2007)";
59 #if defined(__MORPHOS__)
60 struct ExecBase *SysBase;
61 #endif
63 /******************************************************************************/
64 /* >> User defineable library functions start here << */
65 /* The following section should illustrate how the SDI_lib.h macros make it */
66 /* possible to easily maintain a typical Amiga shared library interface if */
67 /* compatibility over all common (OS3/OS4, MorphOS) is required */
68 /******************************************************************************/
70 // first the prototypes of all our public library functions
71 LIBPROTO(SayHelloOS4, char *, void);
72 LIBPROTO(SayHelloOS3, char *, void);
73 LIBPROTO(SayHelloMOS, char *, void);
74 LIBPROTO(Uppercase, char *, REG(a0, char *txt));
75 LIBPROTOVA(SPrintf, char *, REG(a0, char *buf), REG(a1, char *format), ...);
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_VA_(SPrintf)
86 // then we require to generate library stubs for each library functions
87 // because OS4 comes with an additional "struct Interface*" parameter which we
88 // want to keep transparent in our code. Therefore we need to have wrapper/stub
89 // functions to call the real functions instead.
90 #if defined(__amigaos4__)
92 LIBPROTO(SayHelloOS4, char *)
94 return SayHelloOS4();
97 LIBPROTO(SayHelloOS3, char *)
99 return SayHelloOS3();
102 LIBPROTO(SayHelloMOS, char *)
104 return SayHelloMOS();
107 LIBPROTO(Uppercase, char *, REG(a0, char *txt))
109 return Uppercase(txt);
112 LIBPROTOVA(SPrintf, char *, REG(a0, char *buf), REG(a1, char *format), ...)
114 char *ret;
115 va_list args;
116 va_startlinear(args, format);
118 ret = SPrintf(buf, format, va_getlinearva(args, ULONG));
120 va_end(args);
122 return(ret);
125 #endif
127 // Now the real implementations of the library functions above like in
128 // a normal AmigaOS shared library follow
129 LIBFUNC char * SayHelloOS4()
131 return "Hello AmigaOS4!!!";
134 LIBFUNC char * SayHelloOS3()
136 return "Hello AmigaOS3!!!";
139 LIBFUNC char * SayHelloMOS()
141 return "Hello MorphOS!!!";
144 LIBFUNC char * Uppercase(REG(a0, char *txt))
146 char *p = txt;
148 while(p)
150 *p = toupper(*p);
151 p++;
154 return txt;
157 LIBFUNC char * STDARGS SPrintf(REG(a0, char *buf), REG(a1, char *fmt), ...)
159 VA_LIST args;
161 VA_START(args, fmt);
162 RawDoFmt(fmt, VA_ARG(args, void *), NULL, buf);
163 VA_END(args);
165 return(buf);
168 /******************************************************************************/
169 /* Starting from here starts the "standard" Amiga library initialization. */
170 /* All the above should have illustrated enough how "easy" it is to use the */
171 /* SDI_lib.h header file and how it can help in developing a shared library */
172 /* for multiple AmigaOS compatible platforms. */
173 /******************************************************************************/
175 /******************************************************************************/
176 /* Local Structures & Prototypes */
177 /******************************************************************************/
179 struct LibraryHeader
181 struct Library libBase;
182 struct Library *sysBase;
183 ULONG segList;
186 #if defined(__amigaos4__)
188 LIBFUNC static struct LibraryHeader * LibInit (struct LibraryHeader *base, BPTR librarySegment, struct ExecIFace *pIExec);
189 LIBFUNC static BPTR LibExpunge (struct LibraryManagerInterface *Self);
190 LIBFUNC static struct LibraryHeader * LibOpen (struct LibraryManagerInterface *Self, ULONG version);
191 LIBFUNC static BPTR LibClose (struct LibraryManagerInterface *Self);
193 #elif defined(__MORPHOS__)
195 LIBFUNC static struct LibraryHeader * LibInit (struct LibraryHeader *base, BPTR librarySegment, struct ExecBase *sb);
196 LIBFUNC static BPTR LibExpunge(void);
197 LIBFUNC static struct LibraryHeader * LibOpen (void);
198 LIBFUNC static BPTR LibClose (void);
199 LIBFUNC static LONG LibNull (void);
201 #else
203 LIBFUNC static struct LibraryHeader * LibInit (REG(a0, BPTR Segment), REG(d0, struct LibraryHeader *lh), REG(a6, struct ExecBase *sb));
204 LIBFUNC static BPTR LibExpunge (REG(a6, struct LibraryHeader *base));
205 LIBFUNC static struct LibraryHeader * LibOpen (REG(a6, struct LibraryHeader *base));
206 LIBFUNC static BPTR LibClose (REG(a6, struct LibraryHeader *base));
207 LIBFUNC static LONG LibNull (void);
209 #endif
211 /******************************************************************************/
212 /* Dummy entry point and LibNull() function all in one */
213 /******************************************************************************/
215 #if defined(__amigaos4__)
216 int _start(void)
217 #else
218 int Main(void)
219 #endif
221 return RETURN_FAIL;
224 #if !defined(__amigaos4__)
225 LIBFUNC static LONG LibNull(VOID)
227 return(0);
229 #endif
231 /******************************************************************************/
232 /* Local data structures */
233 /******************************************************************************/
235 #if defined(__amigaos4__)
236 /* ------------------- OS4 Manager Interface ------------------------ */
237 STATIC ULONG LibObtain(struct LibraryManagerInterface *Self)
239 return(Self->Data.RefCount++);
242 STATIC ULONG LibRelease(struct LibraryManagerInterface *Self)
244 return(Self->Data.RefCount--);
247 STATIC CONST APTR LibManagerVectors[] =
249 (APTR)LibObtain,
250 (APTR)LibRelease,
251 (APTR)NULL,
252 (APTR)NULL,
253 (APTR)LibOpen,
254 (APTR)LibClose,
255 (APTR)LibExpunge,
256 (APTR)NULL,
257 (APTR)-1
260 STATIC CONST struct TagItem LibManagerTags[] =
262 {MIT_Name, (ULONG)"__library"},
263 {MIT_VectorTable, (ULONG)LibManagerVectors},
264 {MIT_Version, 1},
265 {TAG_DONE, 0}
268 /* ------------------- Library Interface(s) ------------------------ */
270 STATIC CONST APTR LibVectors[] =
272 (APTR)LibObtain,
273 (APTR)LibRelease,
274 (APTR)NULL,
275 (APTR)NULL,
276 (APTR)libvector,
277 (APTR)-1
280 STATIC CONST struct TagItem MainTags[] =
282 {MIT_Name, (ULONG)"main"},
283 {MIT_VectorTable, (ULONG)LibVectors},
284 {MIT_Version, 1},
285 {TAG_DONE, 0}
289 STATIC CONST ULONG LibInterfaces[] =
291 (ULONG)LibManagerTags,
292 (ULONG)MainTags,
293 (ULONG)0
296 /* --------------------- m68k Library stubs ------------------------ */
298 STATIC ULONG stub_OpenPPC(ULONG *regarray)
300 struct Library *Base = (struct Library *) regarray[REG68K_A6/4];
301 struct ExtendedLibrary *ExtLib = (struct ExtendedLibrary *) ((ULONG)Base + Base->lib_PosSize);
302 struct LibraryManagerInterface *Self = (struct LibraryManagerInterface *) ExtLib->ILibrary;
304 return (ULONG) Self->Open(0);
306 struct EmuTrap stub_Open = { TRAPINST, TRAPTYPE, stub_OpenPPC };
308 STATIC ULONG stub_ClosePPC(ULONG *regarray)
310 struct Library *Base = (struct Library *) regarray[REG68K_A6/4];
311 struct ExtendedLibrary *ExtLib = (struct ExtendedLibrary *) ((ULONG)Base + Base->lib_PosSize);
312 struct LibraryManagerInterface *Self = (struct LibraryManagerInterface *) ExtLib->ILibrary;
314 return (ULONG) Self->Close();
316 struct EmuTrap stub_Close = { TRAPINST, TRAPTYPE, stub_ClosePPC };
318 STATIC ULONG stub_ExpungePPC(ULONG *regarray)
320 return 0UL;
322 struct EmuTrap stub_Expunge = { TRAPINST, TRAPTYPE, stub_ExpungePPC };
324 STATIC ULONG stub_ReservedPPC(ULONG *regarray)
326 return 0UL;
328 struct EmuTrap stub_Reserved = { TRAPINST, TRAPTYPE, stub_ReservedPPC };
330 STATIC ULONG VecTable68K[] =
332 (ULONG)&stub_Open,
333 (ULONG)&stub_Close,
334 (ULONG)&stub_Expunge,
335 (ULONG)&stub_Reserved,
336 (ULONG)-1
339 /* ----------------------- LibCreate Tags -------------------------- */
341 STATIC CONST struct TagItem LibCreateTags[] =
343 {CLT_DataSize, (ULONG)(sizeof(struct LibraryHeader))},
344 {CLT_InitFunc, (ULONG)LibInit},
345 {CLT_Interfaces, (ULONG)LibInterfaces},
346 {CLT_Vector68K, (ULONG)VecTable68K},
347 {TAG_DONE, 0}
350 #else
352 STATIC CONST APTR LibVectors[] =
354 #ifdef __MORPHOS__
355 (APTR)FUNCARRAY_32BIT_NATIVE,
356 #endif
357 (APTR)LibOpen,
358 (APTR)LibClose,
359 (APTR)LibExpunge,
360 (APTR)LibNull,
361 (APTR)libvector,
362 (APTR)-1
365 STATIC CONST ULONG LibInitTab[] =
367 sizeof(struct LibraryHeader),
368 (ULONG)LibVectors,
369 (ULONG)NULL,
370 (ULONG)LibInit
373 #endif
375 /* ------------------- ROM Tag ------------------------ */
376 static const USED_VAR struct Resident ROMTag =
378 RTC_MATCHWORD,
379 (struct Resident *)&ROMTag,
380 (struct Resident *)&ROMTag + 1,
381 #if defined(__amigaos4__)
382 RTF_AUTOINIT|RTF_NATIVE, // The Library should be set up according to the given table.
383 #elif defined(__MORPHOS__)
384 RTF_AUTOINIT|RTF_PPC,
385 #else
386 RTF_AUTOINIT,
387 #endif
388 VERSION,
389 NT_LIBRARY,
391 (APTR)UserLibName,
392 VSTRING,
393 #if defined(__amigaos4__)
394 (APTR)LibCreateTags // This table is for initializing the Library.
395 #else
396 (APTR)LibInitTab
397 #endif
400 #if defined(__MORPHOS__)
402 * To tell the loader that this is a new emulppc elf and not
403 * one for the ppc.library.
404 * ** IMPORTANT **
406 ULONG USED_VAR __amigappc__=1;
407 ULONG USED_VAR __abox__=1;
409 #endif /* __MORPHOS */
411 /******************************************************************************/
412 /* Standard Library Functions, all of them are called in Forbid() state. */
413 /******************************************************************************/
415 #ifndef __amigaos4__
416 #define DeleteLibrary(LIB) \
417 FreeMem((STRPTR)(LIB)-(LIB)->lib_NegSize, (ULONG)((LIB)->lib_NegSize+(LIB)->lib_PosSize))
418 #endif
420 #if defined(__amigaos4__)
421 static struct LibraryHeader * LibInit(struct LibraryHeader *base, BPTR librarySegment, struct ExecIFace *pIExec)
423 struct ExecBase *sb = (struct ExecBase *)pIExec->Data.LibBase;
424 IExec = pIExec;
425 #elif defined(__MORPHOS__)
426 static struct LibraryHeader * LibInit(struct LibraryHeader *base, BPTR librarySegment, struct ExecBase *sb)
428 #else
429 LIBFUNC static struct LibraryHeader * LibInit(REG(a0, BPTR librarySegment), REG(d0, struct LibraryHeader *base), REG(a6, struct ExecBase *sb))
431 #endif
433 SysBase = (APTR)sb;
435 base->libBase.lib_Node.ln_Type = NT_LIBRARY;
436 base->libBase.lib_Node.ln_Pri = 0;
437 base->libBase.lib_Node.ln_Name = (char *)UserLibName;
438 base->libBase.lib_Flags = LIBF_CHANGED | LIBF_SUMUSED;
439 base->libBase.lib_Version = VERSION;
440 base->libBase.lib_Revision = REVISION;
441 base->libBase.lib_IdString = (char *)UserLibID;
443 base->segList = librarySegment;
444 base->sysBase = (APTR)SysBase;
446 return(base);
449 #if defined(__amigaos4__)
450 static BPTR LibExpunge(struct LibraryManagerInterface *Self)
452 struct LibraryHeader *base = (struct LibraryHeader *)Self->Data.LibBase;
453 #elif defined(__MORPHOS__)
454 static BPTR LibExpunge(void)
456 struct LibraryHeader *base = (struct LibraryHeader*)REG_A6;
457 #else
458 LIBFUNC static BPTR LibExpunge(REG(a6, struct LibraryHeader *base))
460 #endif
461 BPTR rc;
463 if(base->libBase.lib_OpenCnt > 0)
465 base->libBase.lib_Flags |= LIBF_DELEXP;
466 return(0);
469 SysBase = (APTR)base->sysBase;
470 rc = base->segList;
472 Remove((struct Node *)base);
473 DeleteLibrary(&base->libBase);
475 return(rc);
478 #if defined(__amigaos4__)
479 static struct LibraryHeader *LibOpen(struct LibraryManagerInterface *Self, ULONG version)
481 struct LibraryHeader *base = (struct LibraryHeader *)Self->Data.LibBase;
482 #elif defined(__MORPHOS__)
483 static struct LibraryHeader *LibOpen(void)
485 struct LibraryHeader *base = (struct LibraryHeader*)REG_A6;
486 #else
487 LIBFUNC static struct LibraryHeader * LibOpen(REG(a6, struct LibraryHeader *base))
489 #endif
491 base->libBase.lib_Flags &= ~LIBF_DELEXP;
492 base->libBase.lib_OpenCnt++;
494 return base;
497 #if defined(__amigaos4__)
498 static BPTR LibClose(struct LibraryManagerInterface *Self)
500 struct LibraryHeader *base = (struct LibraryHeader *)Self->Data.LibBase;
501 #elif defined(__MORPHOS__)
502 static BPTR LibClose(void)
504 struct LibraryHeader *base = (struct LibraryHeader *)REG_A6;
505 #else
506 LIBFUNC static BPTR LibClose(REG(a6, struct LibraryHeader *base))
508 #endif
510 if(base->libBase.lib_OpenCnt > 0 &&
511 --base->libBase.lib_OpenCnt == 0)
513 if(base->libBase.lib_Flags & LIBF_DELEXP)
515 #if defined(__amigaos4__)
516 return LibExpunge(Self);
517 #elif defined(__MORPHOS__)
518 return LibExpunge();
519 #else
520 return LibExpunge(base);
521 #endif
525 return 0;