1 /*******************************************************************************
4 Versionstring: $VER: mccinit.c 1.24 (05.10.2010)
5 Author: Jens Langner <Jens.Langner@light-speed.de>
6 Distribution: PD (public domain)
7 Description: library init file for easy generation of a MUI
8 custom classes (MCC/MCP)
11 1.0 09.06.2007 : created based on obsolete mccheader.c (damato)
12 1.1 10.06.2007 : modified LibInit/LibOpen/LibExpunge to call the actual
13 ClassOpen() in LibOpen() rather than in LibInit(). This
14 should prevent stack issues common on e.g. OS3. (damato)
15 1.2 01.07.2007 : adapted library interface initialization to what the
16 very latest idltool 52.7 produces as well.
17 1.3 04.07.2007 : added MIN_STACKSIZE and all required StackSwap()
18 mechanisms to enforce a large enough stack.
19 1.4 04.07.2007 : put the StackSwapStruct structure on the stack to avoid
21 1.5 18.07.2007 : added new inline assember stackswap_call() function which
22 allows to call a function within a new stack frame
23 initiated by StackSwap(). This should make the whole
24 stack swapping mechanism more safe.
25 1.6 24.07.2007 : corrected an else-branch which only exists if CLASSINIT
26 is defined and added an UNUSED extension to the Expunge()
27 function in case the base parameter is not used.
28 1.7 25.07.2007 : adapted GETINTERFACE() and library base definitions so
29 that mccinit.c can also be used with C++
30 1.8 25.07.2007 : removed the obsolete 2-parameter version of GETINTERFACE()
31 from mcc_common.h and adapted all calls accordingly.
32 Also moved the inclusion of mccinit.c in front of all
33 user definable functions.
34 1.9 09.08.2007 : applied a patch kindly provided by Ilkka Lehtoranta which
35 replaces the assembler code for stack swapping with the
36 appropriate call to the NewPPCStackSwap() function in
37 MorphOS. In addition, the stack size will now be properly
38 checked before a stack swap is attempted.
39 1.10 13.08.2007 : the StackSwap structure itself *must* *not* be placed on the
40 stack which will be swapped later, because swapping it back
41 will access the wrong place in memory. Hence this structure
42 is allocated from global memory now.
43 1.11 01.02.2008 : fixed some minor compiler warnings when compiled using the
45 1.12 27.03.2009 : integrated some changes which should make mccinit usable
47 1.13 01.04.2009 : fixed the broken prototype for the assembler stackswap_call
49 1.14 02.05.2009 : added RTF_EXTENDED for the MorphOS build as well
50 1.15 24.05.2009 : fixed some compiler warnings appear on AROS compile
51 1.16 25.05.2009 : fixed some compiler warnings appear on OS3/MOS compile
52 1.17 02.06.2009 : more fixes to better comply for AROS compilation
53 1.18 24.04.2010 : fixed stack swapping for AROS
54 1.19 25.05.2010 : updated for compatibility with AROS V1 API
55 1.20 01.06.2010 : added CleanupDebug() call to expunge function.
56 1.21 17.08.2010 : the UserLibName and UserLibID strings are now correctly
57 placed in the .data instead of the .text section. Also made
58 sure that the _start() function is really the first entry,
59 otherwise random data will be executed as code, which will
61 1.22 03.09.2010 : the library semaphore is now correctly cleared ahead of the
63 1.23 07.09.2010 : added missing #include <string.h> for memset().
64 1.24 05.10.2010 : make sure that removing the library during LibClose() really
65 operates on the correct base. Calling LibExpunge() on MorphOS
66 is wrong, since that takes no parameter but expects the base
67 to be in A6. We work around this by using an additional
68 function which gets called from LibClose() and LibExpunge()
69 with the correct base pointer.
73 The purpose of this source file is to provide a template for the library init
74 code for a creation of an own MUI custom class (mcc/mcp) for AmigaOS4,
75 AmigaOS3 and MorphOS. By directly including this file (#include "mccinit.c")
76 and defining certain preprocessor values, a MUI developer doesn't have to
77 care about library init stuff which is normally highly system dependent and
78 various between different Amiga operating systems.
82 This file should be included by another source file (e.g. 'library.c') in
83 your main development branch while certain preprocessor macros right before
84 the include statement can be defined to change the behaviour of mccinit.c.
85 These possible macros are:
87 USERLIBID (char*) - version string for the mcc/mcp (exluding $VER:)
88 VERSION (int) - version number (must match USERLIBID)
89 REVISION (int) - revision number (must match USERLIBID)
90 CLASS (char*) - class name (including .mcc/.mcp)
91 MASTERVERSION (int) - the minimun required muimaster version
92 (default: MUIMASTER_VMIN)
93 MIN_STACKSIZE (int) - if defined, the specified minimum stack size
94 will be enforced when calling all user functions
95 like ClassXXXX() and PreClassXXX().
99 SUPERCLASS (char*) - superclass ID of MCC (e.g. MUIC_Area)
100 INSTDATA - name of instance data structure of MCC (e.g. InstData)
101 USEDCLASSES - name of NULL terminated string array which contains
102 names of other required custom classes for MCC.
103 _Dispatcher - name of Dispatcher function for MCC
107 SUPERCLASSP (char*) - superclass ID of MCP (e.g. MUIC_Mccprefs)
108 INSTDATAP - name of instance data structure of MCP
109 USEDCLASSESP - name of NULL terminated string array which contains
110 names of other required custom classes for MCC.
111 SHORTHELP (char*) - alternative help text for prefs program's listview
112 PREFSIMAGEOBJECT - pointer to the image object for the MCP
113 _DispatcherP - name of Dispatcher function for MCP
115 In addition, the following defines and functions can be defined or are
118 CLASSINIT - if defined, a "BOOL ClassInit(struct Library *base)"
119 function can be defined in your own code and will be called
120 right after the general library initialization are
121 finished. This function should then open own libraries
122 or do own library initialization tasks as it is only called
123 once at the very first library/class open.
125 CLASSEXPUNGE - if defined a "VOID ClassExpunge(struct Library *base)"
126 function can be defined in your own code and will be called
127 as soon as the library will be freed/expunged by the
128 operating system. In this function you should close/free
129 stuff you normally opened/allocated in CLASSINIT.
131 CLASSOPEN - if defined, a "BOOL ClassOpen(struct Library *base)"
132 function can be defined in your own code and will be called
133 right after each single application opens the custom class.
134 In this function you can then set flags or do library open
137 CLASSCLOSE - if defined a "VOID ClassClose(struct Library *base)"
138 function can be defined in your own code and will be called
139 right after the library was successfully flagged as closed
140 by the CloseLibrary() call of an application.
143 PRECLASSINIT - if defined a "BOOL PreClassInit(struct Library *base)"
144 function can be defined and will be called right _before_
145 and library initialization takes place.
147 POSTCLASSEXPUNGE - if defined a "BOOL PostClassExpunge(struct Library *base)"
148 function can be defined and will be called right _after_
149 the custom class was free via MUI_DeleteCustomClass() in
150 the library expunge phase.
154 The above class functions are normally called by the operating system
155 in a Forbid()/Permit() state. That means you are supposed to make sure that
156 your operations doesn't break the Forbid() state or otherwise you may run
157 into a race condition. However, we have added semaphore locking to partly
158 protect you from that case - but you should still consider doing processor
159 intensitive tasks in a library's own function instead of using those
160 class initialization functions.
162 *******************************************************************************/
164 /******************************************************************************/
166 /******************************************************************************/
171 #include <emul/emulinterface.h>
172 #include <emul/emulregs.h>
175 #include <exec/types.h>
176 #include <exec/memory.h>
177 #include <exec/libraries.h>
178 #include <exec/semaphores.h>
179 #include <exec/resident.h>
180 #include <exec/execbase.h>
183 #include <proto/exec.h>
184 #include <proto/muimaster.h>
185 #include <proto/utility.h>
186 #include <proto/dos.h>
187 #include <proto/graphics.h>
188 #include <proto/intuition.h>
191 #include <aros/libcall.h>
192 #include <utility/utility.h>
195 #include <SDI/SDI_compiler.h>
197 #if defined(__amigaos4__)
198 struct Library
*MUIMasterBase
= NULL
;
199 struct Library
*SysBase
= NULL
;
200 struct Library
*UtilityBase
= NULL
;
201 struct Library
*DOSBase
= NULL
;
202 struct Library
*GfxBase
= NULL
;
203 struct Library
*IntuitionBase
= NULL
;
204 struct ExecIFace
*IExec
= NULL
;
205 struct MUIMasterIFace
*IMUIMaster
= NULL
;
206 struct UtilityIFace
*IUtility
= NULL
;
207 struct DOSIFace
*IDOS
= NULL
;
208 struct GraphicsIFace
*IGraphics
= NULL
;
209 struct IntuitionIFace
*IIntuition
= NULL
;
210 #if defined(__NEWLIB__)
211 struct Library
*NewlibBase
= NULL
;
212 struct Interface
*INewlib
= NULL
;
215 struct Library
*MUIMasterBase
= NULL
;
216 struct ExecBase
*SysBase
= NULL
;
217 #if defined(__AROS__)
218 struct UtilityBase
*UtilityBase
= NULL
;
220 struct Library
*UtilityBase
= NULL
;
222 struct DosLibrary
*DOSBase
= NULL
;
223 struct GfxBase
*GfxBase
= NULL
;
224 struct IntuitionBase
*IntuitionBase
= NULL
;
231 // we place a stack cookie in the binary so that
232 // newer OS version can directly take the specified
233 // number for the ramlib process
234 #if defined(MIN_STACKSIZE)
236 // transforms a define into a string
237 #define STR(x) STR2(x)
241 STATIC
const char USED_VAR stack_size
[] = "$STACK:" STR(MIN_STACKSIZE
) "\n";
245 /* The name of the class will also become the name of the library. */
246 /* We need a pointer to this string in our ROMTag (see below). */
247 STATIC
const char UserLibName
[] = CLASS
;
248 STATIC
const char UserLibID
[] = "$VER: " USERLIBID
;
251 STATIC
struct MUI_CustomClass
*ThisClass
= NULL
;
252 DISPATCHERPROTO(_Dispatcher
);
256 STATIC
struct MUI_CustomClass
*ThisClassP
= NULL
;
257 DISPATCHERPROTO(_DispatcherP
);
262 #if !defined(__NEWLIB__)
263 #if defined(__amigaos4__)
264 extern struct Library
*__UtilityBase
; // clib2
265 extern struct UtilityIFace
* __IUtility
; // clib2
267 struct Library
*__UtilityBase
= NULL
; // required by libnix & clib2
271 /* these one are needed copies for libnix.a */
273 #ifdef USE_MATHIEEEDOUBBASBASE
274 struct Library
*__MathIeeeDoubBasBase
= NULL
;
276 #ifdef USE_MATHIEEEDOUBTRANSBASE
277 struct Library
*__MathIeeeDoubTransBase
= NULL
;
281 #endif /* __GNUC__ */
284 // define own macros for the OS4 interfaces
287 #if defined(__amigaos4__)
288 #define GETINTERFACE(iface, type, base) (iface = (type)GetInterface((struct Library *)(base), "main", 1L, NULL))
289 #define DROPINTERFACE(iface) (DropInterface((struct Interface *)iface), iface = NULL)
291 #define GETINTERFACE(iface, type, base) TRUE
292 #define DROPINTERFACE(iface)
295 // in case the user didn't specify an own minimum
296 // muimaster version we increase it here.
297 #ifndef MASTERVERSION
298 #define MASTERVERSION MUIMASTER_VMIN
301 /* Our library structure, consisting of a struct Library, a segment pointer */
302 /* and a semaphore. We need the semaphore to protect init/exit stuff in our */
303 /* open/close fuSnctions */
306 struct Library lh_Library
;
309 struct SignalSemaphore lh_Semaphore
;
313 /******************************************************************************/
314 /* Local Structures & Prototypes */
315 /******************************************************************************/
317 #if defined(__amigaos4__)
319 STATIC
struct LibraryHeader
* LIBFUNC
LibInit (struct LibraryHeader
*base
, BPTR librarySegment
, struct ExecIFace
*pIExec
);
320 STATIC BPTR LIBFUNC
LibExpunge (struct LibraryManagerInterface
*Self
);
321 STATIC
struct LibraryHeader
* LIBFUNC
LibOpen (struct LibraryManagerInterface
*Self
, ULONG version
);
322 STATIC BPTR LIBFUNC
LibClose (struct LibraryManagerInterface
*Self
);
323 STATIC IPTR LIBFUNC
MCC_Query (UNUSED
struct Interface
*self
, REG(d0
, LONG which
));
325 #elif defined(__MORPHOS__)
327 STATIC
struct LibraryHeader
* LIBFUNC
LibInit (struct LibraryHeader
*base
, BPTR librarySegment
, struct ExecBase
*sb
);
328 STATIC BPTR LIBFUNC
LibExpunge (void);
329 STATIC
struct LibraryHeader
* LIBFUNC
LibOpen (void);
330 STATIC BPTR LIBFUNC
LibClose (void);
331 STATIC LONG LIBFUNC
LibNull (void);
332 STATIC IPTR LIBFUNC
MCC_Query (void);
334 #elif defined(__AROS__)
336 AROS_UFP3 (struct LibraryHeader
*, LibInit
,
337 AROS_UFPA(struct LibraryHeader
*, base
, D0
),
338 AROS_UFPA(BPTR
, librarySegment
, A0
),
339 AROS_UFPA(struct ExecBase
*, sb
, A6
)
341 AROS_LD1(BPTR
, LibExpunge
,
342 AROS_LPA(struct LibraryHeader
*, base
, D0
),
343 struct LibraryHeader
*, base
, 3, __MCC_
345 AROS_LD1 (struct LibraryHeader
*, LibOpen
,
346 AROS_LHA (ULONG
, version
, D0
),
347 struct LibraryHeader
*, base
, 1, __MCC_
349 AROS_LD0 (BPTR
, LibClose
,
350 struct LibraryHeader
*, base
, 2, __MCC_
352 AROS_LD1(IPTR
, MCC_Query
,
353 AROS_LHA(LONG
, what
, D0
),
354 struct LibraryHeader
*, LIBBASE
, 5, __MCC_
359 STATIC
struct LibraryHeader
* LIBFUNC
LibInit (REG(d0
, struct LibraryHeader
*base
), REG(a0
, BPTR librarySegment
), REG(a6
, struct ExecBase
*sb
));
360 STATIC BPTR LIBFUNC
LibExpunge (REG(a6
, struct LibraryHeader
*base
));
361 STATIC
struct LibraryHeader
* LIBFUNC
LibOpen (REG(d0
, ULONG version
), REG(a6
, struct LibraryHeader
*base
));
362 STATIC BPTR LIBFUNC
LibClose (REG(a6
, struct LibraryHeader
*base
));
363 STATIC LONG LIBFUNC
LibNull (void);
364 STATIC IPTR LIBFUNC
MCC_Query (REG(d0
, LONG which
));
368 /******************************************************************************/
369 /* Dummy entry point and LibNull() function all in one */
370 /******************************************************************************/
373 * The system (and compiler) rely on a symbol named _start which marks
374 * the beginning of execution of an ELF file. To prevent others from
375 * executing this library, and to keep the compiler/linker happy, we
376 * define an empty _start symbol here.
378 * On the classic system (pre-AmigaOS4) this was usually done by
384 #if defined(__amigaos4__) && !defined(__AROS__) && !defined(__MORPHOS__)
385 #if !defined(__mc68000__)
400 #if !defined(__amigaos4__)
401 STATIC LONG LIBFUNC
LibNull(VOID
)
407 /******************************************************************************/
408 /* Local data structures */
409 /******************************************************************************/
411 #if defined(__amigaos4__)
412 /* ------------------- OS4 Manager Interface ------------------------ */
413 STATIC uint32
_manager_Obtain(struct LibraryManagerInterface
*Self
)
416 __asm__
__volatile__(
422 : "r" (&Self
->Data
.RefCount
)
428 STATIC uint32
_manager_Release(struct LibraryManagerInterface
*Self
)
431 __asm__
__volatile__(
437 : "r" (&Self
->Data
.RefCount
)
443 STATIC CONST CONST_APTR lib_manager_vectors
[] =
445 (CONST_APTR
)_manager_Obtain
,
446 (CONST_APTR
)_manager_Release
,
450 (CONST_APTR
)LibClose
,
451 (CONST_APTR
)LibExpunge
,
456 STATIC CONST
struct TagItem lib_managerTags
[] =
458 { MIT_Name
, (Tag
)"__library" },
459 { MIT_VectorTable
, (Tag
)lib_manager_vectors
},
464 /* ------------------- Library Interface(s) ------------------------ */
466 ULONG
_MCCClass_Obtain(UNUSED
struct Interface
*Self
)
471 ULONG
_MCCClass_Release(UNUSED
struct Interface
*Self
)
476 STATIC CONST CONST_APTR main_vectors
[] =
478 (CONST_APTR
)_MCCClass_Obtain
,
479 (CONST_APTR
)_MCCClass_Release
,
482 (CONST_APTR
)MCC_Query
,
486 STATIC CONST
struct TagItem mainTags
[] =
488 { MIT_Name
, (Tag
)"main" },
489 { MIT_VectorTable
, (Tag
)main_vectors
},
494 STATIC CONST CONST_APTR libInterfaces
[] =
496 (CONST_APTR
)lib_managerTags
,
497 (CONST_APTR
)mainTags
,
501 // Our libraries always have to carry a 68k jump table with it, so
502 // lets define it here as extern, as we are going to link it to
504 #ifndef NO_VECTABLE68K
505 extern CONST APTR VecTable68K
[];
508 STATIC CONST
struct TagItem libCreateTags
[] =
510 { CLT_DataSize
, sizeof(struct LibraryHeader
) },
511 { CLT_InitFunc
, (Tag
)LibInit
},
512 { CLT_Interfaces
, (Tag
)libInterfaces
},
513 #ifndef NO_VECTABLE68K
514 { CLT_Vector68K
, (Tag
)VecTable68K
},
521 STATIC CONST CONST_APTR LibVectors
[] =
524 (CONST_APTR
)FUNCARRAY_32BIT_NATIVE
,
528 (CONST_APTR
)LibClose
,
529 (CONST_APTR
)LibExpunge
,
531 (CONST_APTR
)MCC_Query
,
533 (CONST_APTR
)AROS_SLIB_ENTRY(LibOpen
, __MCC_
, 1),
534 (CONST_APTR
)AROS_SLIB_ENTRY(LibClose
, __MCC_
, 2),
535 (CONST_APTR
)AROS_SLIB_ENTRY(LibExpunge
, __MCC_
, 3),
537 (CONST_APTR
)AROS_SLIB_ENTRY(MCC_Query
, __MCC_
, 5),
542 STATIC CONST IPTR LibInitTab
[] =
544 sizeof(struct LibraryHeader
),
552 /* ------------------- ROM Tag ------------------------ */
553 STATIC
const USED_VAR
struct Resident ROMTag
=
556 (struct Resident
*)&ROMTag
,
557 (struct Resident
*)(&ROMTag
+ 1),
558 #if defined(__amigaos4__)
559 RTF_AUTOINIT
|RTF_NATIVE
, // The Library should be set up according to the given table.
560 #elif defined(__MORPHOS__)
561 RTF_AUTOINIT
|RTF_EXTENDED
|RTF_PPC
,
562 #elif defined(__AROS__)
563 RTF_AUTOINIT
|RTF_EXTENDED
,
571 (char *)UserLibID
+6, // +6 to skip '$VER: '
572 #if defined(__amigaos4__)
573 (APTR
)libCreateTags
, // This table is for initializing the Library.
577 #if defined(__MORPHOS__) || defined(__AROS__)
583 #if defined(__MORPHOS__)
585 * To tell the loader that this is a new emulppc elf and not
586 * one for the ppc.library.
589 const USED_VAR ULONG __abox__
= 1;
591 #endif /* __MORPHOS__ */
593 /****************************************************************************/
594 /* Stack enforcing function which allows to make sure that a function has */
595 /* enough stack space during its execution time */
596 /****************************************************************************/
598 #if defined(MIN_STACKSIZE) && !defined(__amigaos4__)
600 /* generic StackSwap() function which calls function() surrounded by
602 #if (defined(__mc68000__) && !defined(__AROS__))
603 ULONG
stackswap_call(struct StackSwapStruct
*stack
,
604 ULONG (*function
)(struct LibraryHeader
*),
605 struct LibraryHeader
*arg
);
609 .globl _stackswap_call \n\
611 moveml #0x3022,sp@- \n\
615 movel _SysBase,a6 \n\
622 movel _SysBase,a6 \n\
626 moveml sp@+,#0x440c \n\
628 #elif defined(__MORPHOS__)
629 ULONG
stackswap_call(struct StackSwapStruct
*stack
,
630 ULONG (*function
)(struct LibraryHeader
*),
631 struct LibraryHeader
*arg
)
633 struct PPCStackSwapArgs swapargs
;
635 swapargs
.Args
[0] = (ULONG
)arg
;
637 return NewPPCStackSwap(stack
, function
, &swapargs
);
639 #elif defined(__AROS__)
640 ULONG
stackswap_call(struct StackSwapStruct
*stack
,
641 ULONG (*function
)(struct LibraryHeader
*),
642 struct LibraryHeader
*arg
)
644 struct StackSwapArgs swapargs
;
646 swapargs
.Args
[0] = (IPTR
)arg
;
648 return NewStackSwap(stack
, function
, &swapargs
);
651 #error Bogus operating system
654 STATIC BOOL
callMccFunction(ULONG (*function
)(struct LibraryHeader
*), struct LibraryHeader
*arg
)
656 BOOL success
= FALSE
;
660 // retrieve the task structure for the
664 #if defined(__MORPHOS__)
665 // In MorphOS we have two stacks. One for PPC code and another for 68k code.
666 // We are only interested in the PPC stack.
667 NewGetTaskAttrsA(tc
, &stacksize
, sizeof(ULONG
), TASKINFOTYPE_STACKSIZE
, NULL
);
669 // on all other systems we query via SPUpper-SPLower calculation
670 stacksize
= (IPTR
)tc
->tc_SPUpper
- (IPTR
)tc
->tc_SPLower
;
673 // Swap stacks only if current stack is insufficient
674 if(stacksize
< MIN_STACKSIZE
)
676 struct StackSwapStruct
*stack
;
678 if((stack
= AllocVec(sizeof(*stack
), MEMF_PUBLIC
)) != NULL
)
680 if((stack
->stk_Lower
= AllocVec(MIN_STACKSIZE
, MEMF_PUBLIC
)) != NULL
)
682 // perform the StackSwap
683 #if defined(__AROS__)
684 // AROS uses an APTR type for stk_Upper
685 stack
->stk_Upper
= (APTR
)((IPTR
)stack
->stk_Lower
+ MIN_STACKSIZE
);
687 // all other systems use ULONG
688 stack
->stk_Upper
= (ULONG
)stack
->stk_Lower
+ MIN_STACKSIZE
;
690 stack
->stk_Pointer
= (APTR
)stack
->stk_Upper
;
692 // call routine but with embedding it into a [NewPPC]StackSwap()
693 success
= stackswap_call(stack
, function
, arg
);
695 FreeVec(stack
->stk_Lower
);
701 success
= function(arg
);
705 #else // MIN_STACKSIZE && __amigaos4__
706 #define callMccFunction(func, arg) func(arg)
707 #endif // MIN_STACKSIZE && __amigaos4__
709 /******************************************************************************/
710 /* Wrapper functions to perform certain tasks in our LibInit/LibOpen etc. */
711 /******************************************************************************/
713 /* open and init all necessary library and stuff in the LibInit() phase */
714 STATIC ULONG
mccLibInit(struct LibraryHeader
*base
)
716 // now that this library/class is going to be initialized for the first time
717 // we go and open all necessary libraries on our own
718 #if defined(__amigaos4__)
719 if((DOSBase
= OpenLibrary("dos.library", 36)) &&
720 GETINTERFACE(IDOS
, struct DOSIFace
*, DOSBase
))
721 if((GfxBase
= OpenLibrary("graphics.library", 36)) &&
722 GETINTERFACE(IGraphics
, struct GraphicsIFace
*, GfxBase
))
723 if((IntuitionBase
= OpenLibrary("intuition.library", 36)) &&
724 GETINTERFACE(IIntuition
, struct IntuitionIFace
*, IntuitionBase
))
725 if((UtilityBase
= OpenLibrary("utility.library", 36)) &&
726 GETINTERFACE(IUtility
, struct UtilityIFace
*, UtilityBase
))
728 if((DOSBase
= (struct DosLibrary
*)OpenLibrary("dos.library", 36)) &&
729 (GfxBase
= (struct GfxBase
*)OpenLibrary("graphics.library", 36)) &&
730 (IntuitionBase
= (struct IntuitionBase
*)OpenLibrary("intuition.library", 36)) &&
731 (UtilityBase
= (APTR
)OpenLibrary("utility.library", 36)))
734 // we have to please the internal utilitybase
735 // pointers of libnix and clib2
736 #if !defined(__NEWLIB__)
737 __UtilityBase
= (APTR
)UtilityBase
;
738 #if defined(__amigaos4__)
739 __IUtility
= IUtility
;
747 if((MUIMasterBase
= OpenLibrary(MUIMASTER_NAME
, MASTERVERSION
)) &&
748 GETINTERFACE(IMUIMaster
, struct MUIMasterIFace
*, MUIMasterBase
))
750 #if defined(PRECLASSINIT)
755 ThisClass
= MUI_CreateCustomClass(&base
->lh_Library
, (STRPTR
)SUPERCLASS
, NULL
, sizeof(struct INSTDATA
), ENTRY(_Dispatcher
));
760 if((ThisClassP
= MUI_CreateCustomClass(&base
->lh_Library
, (STRPTR
)SUPERCLASSP
, NULL
, sizeof(struct INSTDATAP
), ENTRY(_DispatcherP
))))
764 #define THISCLASS ThisClass
766 #define THISCLASS ThisClassP
769 // in case the user defined an own ClassInit()
770 // function we call it protected by a semaphore as
771 // this user may be stupid and break the Forbid() state
773 #if defined(CLASSINIT)
774 if(ClassInit(&base
->lh_Library
))
777 // everything was successfully so lets
778 // make sure we return TRUE
781 #if defined(CLASSINIT)
783 E(DBF_STARTUP
, "ClassInit(%s) failed", CLASS
);
786 // if we pass this point than an error
787 // occurred and we have to cleanup
788 #if defined(SUPERCLASSP)
789 MUI_DeleteCustomClass(ThisClassP
);
794 #if defined(SUPERCLASS)
795 MUI_DeleteCustomClass(ThisClass
);
801 DROPINTERFACE(IMUIMaster
);
802 CloseLibrary(MUIMasterBase
);
803 MUIMasterBase
= NULL
;
806 DROPINTERFACE(IUtility
);
807 CloseLibrary((struct Library
*)UtilityBase
);
813 DROPINTERFACE(IIntuition
);
814 CloseLibrary((struct Library
*)IntuitionBase
);
815 IntuitionBase
= NULL
;
820 DROPINTERFACE(IGraphics
);
821 CloseLibrary((struct Library
*)GfxBase
);
828 CloseLibrary((struct Library
*)DOSBase
);
832 E(DBF_STARTUP
, "mccLibInit(%s) failed", CLASS
);
836 /* expunge everything we previously opened and call user definable functions */
837 STATIC ULONG
mccLibExpunge(UNUSED
struct LibraryHeader
*base
)
839 // in case the user specified that he has an own class
840 // expunge function we call it right here, not caring about
842 #if defined(CLASSEXPUNGE)
843 ClassExpunge(&base
->lh_Library
);
846 // now we remove our own stuff here step-by-step
850 MUI_DeleteCustomClass(ThisClassP
);
858 MUI_DeleteCustomClass(ThisClass
);
863 // we inform the user that all main class expunge stuff
864 // is finished, if he want's to get informed.
865 #if defined(POSTCLASSEXPUNGE)
873 // cleanup the various library bases and such
876 DROPINTERFACE(IMUIMaster
);
877 CloseLibrary(MUIMasterBase
);
878 MUIMasterBase
= NULL
;
883 DROPINTERFACE(IUtility
);
884 CloseLibrary((struct Library
*)UtilityBase
);
890 DROPINTERFACE(IIntuition
);
891 CloseLibrary((struct Library
*)IntuitionBase
);
892 IntuitionBase
= NULL
;
897 DROPINTERFACE(IGraphics
);
898 CloseLibrary((struct Library
*)GfxBase
);
905 CloseLibrary((struct Library
*)DOSBase
);
912 /* we call the user definable function here only */
913 #if defined(CLASSOPEN)
914 STATIC ULONG
mccLibOpen(struct LibraryHeader
*base
)
916 return ClassOpen(&base
->lh_Library
);
920 /* we call the user definable function here only */
921 #if defined(CLASSCLOSE)
922 STATIC ULONG
mccLibClose(struct LibraryHeader
*base
)
924 ClassClose(&base
->lh_Library
);
929 /******************************************************************************/
930 /* Standard Library Functions, all of them are called in Forbid() state. */
931 /******************************************************************************/
933 #if defined(__amigaos4__)
934 STATIC
struct LibraryHeader
* LibInit(struct LibraryHeader
*base
, BPTR librarySegment
, struct ExecIFace
*pIExec
)
936 struct Library
*sb
= (struct Library
*)pIExec
->Data
.LibBase
;
938 #elif defined(__MORPHOS__)
939 STATIC
struct LibraryHeader
* LibInit(struct LibraryHeader
*base
, BPTR librarySegment
, struct ExecBase
*sb
)
941 #elif defined(__AROS__)
942 AROS_UFH3 (struct LibraryHeader
*, LibInit
,
943 AROS_UFHA(struct LibraryHeader
*, base
, D0
),
944 AROS_UFHA(BPTR
, librarySegment
, A0
),
945 AROS_UFHA(struct ExecBase
*, sb
, A6
)
950 STATIC
struct LibraryHeader
* LIBFUNC
LibInit(REG(d0
, struct LibraryHeader
*base
), REG(a0
, BPTR librarySegment
), REG(a6
, struct ExecBase
*sb
))
956 // make sure that this is really a 68020+ machine if optimized for 020+
957 #if _M68060 || _M68040 || _M68030 || _M68020 || __mc68020 || __mc68030 || __mc68040 || __mc68060
958 if(!(SysBase
->AttnFlags
& AFF_68020
))
962 #if defined(__amigaos4__) && defined(__NEWLIB__)
963 if((NewlibBase
= OpenLibrary("newlib.library", 3)) &&
964 GETINTERFACE(INewlib
, struct Interface
*, NewlibBase
))
967 BOOL success
= FALSE
;
969 D(DBF_STARTUP
, "LibInit(" CLASS
")");
971 // cleanup the library header structure beginning with the
972 // library base, even if that is done automcatically, we explicitly
973 // do it here for consistency reasons.
974 base
->lh_Library
.lib_Node
.ln_Type
= NT_LIBRARY
;
975 base
->lh_Library
.lib_Node
.ln_Pri
= 0;
976 base
->lh_Library
.lib_Node
.ln_Name
= (char *)UserLibName
;
977 base
->lh_Library
.lib_Flags
= LIBF_CHANGED
| LIBF_SUMUSED
;
978 base
->lh_Library
.lib_IdString
= (char *)UserLibID
; // here without +6 or otherwise MUI doesn't identify it.
979 base
->lh_Library
.lib_Version
= VERSION
;
980 base
->lh_Library
.lib_Revision
= REVISION
;
982 // init our protecting semaphore and the
983 // initialized flag variable
984 memset(&base
->lh_Semaphore
, 0, sizeof(base
->lh_Semaphore
));
985 InitSemaphore(&base
->lh_Semaphore
);
987 // protect mccLibInit()
988 ObtainSemaphore(&base
->lh_Semaphore
);
990 // If we are not running on AmigaOS4 (no stackswap required) we go and
991 // do an explicit StackSwap() in case the user wants to make sure we
992 // have enough stack for his user functions
993 success
= callMccFunction(mccLibInit
, base
);
996 ReleaseSemaphore(&base
->lh_Semaphore
);
998 // check if everything worked out fine
1001 // everything was successfully so lets
1002 // set the initialized value and contiue
1003 // with the class open phase
1004 base
->lh_Segment
= librarySegment
;
1006 // return the library base as success
1010 #if defined(__amigaos4__) && defined(__NEWLIB__)
1013 DROPINTERFACE(INewlib
);
1014 CloseLibrary(NewlibBase
);
1026 /*****************************************************************************************************/
1027 /*****************************************************************************************************/
1029 #ifndef __amigaos4__
1030 #define DeleteLibrary(LIB) \
1031 FreeMem((STRPTR)(LIB)-(LIB)->lib_NegSize, (ULONG)((LIB)->lib_NegSize+(LIB)->lib_PosSize))
1034 STATIC BPTR
LibDelete(struct LibraryHeader
*base
)
1036 #if defined(__amigaos4__)
1037 struct ExecIFace
*IExec
= (struct ExecIFace
*)(*(struct ExecBase
**)4)->MainInterface
;
1041 // remove the library base from exec's lib list in advance
1042 Remove((struct Node
*)base
);
1044 // protect mccLibExpunge()
1045 ObtainSemaphore(&base
->lh_Semaphore
);
1047 // make sure we have enough stack here
1048 callMccFunction(mccLibExpunge
, base
);
1051 ReleaseSemaphore(&base
->lh_Semaphore
);
1053 #if defined(__amigaos4__) && defined(__NEWLIB__)
1056 DROPINTERFACE(INewlib
);
1057 CloseLibrary(NewlibBase
);
1062 // make sure the system deletes the library as well.
1063 rc
= base
->lh_Segment
;
1064 DeleteLibrary(&base
->lh_Library
);
1069 #if defined(__amigaos4__)
1070 STATIC BPTR
LibExpunge(struct LibraryManagerInterface
*Self
)
1072 struct LibraryHeader
*base
= (struct LibraryHeader
*)Self
->Data
.LibBase
;
1073 #elif defined(__MORPHOS__)
1074 STATIC BPTR
LibExpunge(void)
1076 struct LibraryHeader
*base
= (struct LibraryHeader
*)REG_A6
;
1077 #elif defined(__AROS__)
1078 AROS_LH1 (BPTR
, LibExpunge
,
1079 AROS_LHA(UNUSED
struct LibraryHeader
*, extralh
, D0
),
1080 struct LibraryHeader
*, base
, 3, __MCC_
1085 STATIC BPTR LIBFUNC
LibExpunge(REG(a6
, struct LibraryHeader
*base
))
1090 D(DBF_STARTUP
, "LibExpunge(" CLASS
"): %ld", base
->lh_Library
.lib_OpenCnt
);
1092 // in case our open counter is still > 0, we have
1093 // to set the late expunge flag and return immediately
1094 if(base
->lh_Library
.lib_OpenCnt
> 0)
1096 base
->lh_Library
.lib_Flags
|= LIBF_DELEXP
;
1101 rc
= LibDelete(base
);
1110 /*****************************************************************************************************/
1111 /*****************************************************************************************************/
1113 #if defined(__amigaos4__)
1114 STATIC
struct LibraryHeader
*LibOpen(struct LibraryManagerInterface
*Self
, ULONG version UNUSED
)
1116 struct LibraryHeader
*base
= (struct LibraryHeader
*)Self
->Data
.LibBase
;
1117 #elif defined(__MORPHOS__)
1118 STATIC
struct LibraryHeader
*LibOpen(void)
1120 struct LibraryHeader
*base
= (struct LibraryHeader
*)REG_A6
;
1121 #elif defined(__AROS__)
1122 AROS_LH1 (struct LibraryHeader
*, LibOpen
,
1123 AROS_LHA (UNUSED ULONG
, version
, D0
),
1124 struct LibraryHeader
*, base
, 1, __MCC_
1129 STATIC
struct LibraryHeader
* LIBFUNC
LibOpen(REG(d0
, UNUSED ULONG version
), REG(a6
, struct LibraryHeader
*base
))
1132 struct LibraryHeader
*res
= NULL
;
1134 D(DBF_STARTUP
, "LibOpen(" CLASS
"): %ld", base
->lh_Library
.lib_OpenCnt
);
1136 // LibOpen(), LibClose() and LibExpunge() are called while the system is in
1137 // Forbid() state. That means that these functions should be quick and should
1138 // not break this Forbid()!! Therefore the open counter should be increased
1139 // as the very first instruction during LibOpen(), because a ClassOpen()
1140 // which breaks a Forbid() and another task calling LibExpunge() will cause
1141 // to expunge this library while it is not yet fully initialized. A crash
1142 // is unavoidable then. Even the semaphore does not guarantee 100% protection
1143 // against such a race condition, because waiting for the semaphore to be
1144 // obtained will effectively break the Forbid()!
1146 // increase the open counter ahead of anything else
1147 base
->lh_Library
.lib_OpenCnt
++;
1149 // delete the late expunge flag
1150 base
->lh_Library
.lib_Flags
&= ~LIBF_DELEXP
;
1152 // check if the user defined a ClassOpen() function
1153 #if defined(CLASSOPEN)
1155 struct ExecIFace
*IExec
= (struct ExecIFace
*)(*(struct ExecBase
**)4)->MainInterface
;
1156 BOOL success
= FALSE
;
1159 ObtainSemaphore(&base
->lh_Semaphore
);
1161 // make sure we have enough stack here
1162 success
= callMccFunction(mccLibOpen
, base
);
1164 // here we call the user-specific function for LibOpen() where
1165 // he can do whatever he wants because of the semaphore protection.
1170 E(DBF_STARTUP
, "ClassOpen(" CLASS
") failed");
1172 // decrease the open counter again
1173 base
->lh_Library
.lib_OpenCnt
--;
1176 // release the semaphore
1177 ReleaseSemaphore(&base
->lh_Semaphore
);
1189 /*****************************************************************************************************/
1190 /*****************************************************************************************************/
1192 #if defined(__amigaos4__)
1193 STATIC BPTR
LibClose(struct LibraryManagerInterface
*Self
)
1195 struct LibraryHeader
*base
= (struct LibraryHeader
*)Self
->Data
.LibBase
;
1196 #elif defined(__MORPHOS__)
1197 STATIC BPTR
LibClose(void)
1199 struct LibraryHeader
*base
= (struct LibraryHeader
*)REG_A6
;
1200 #elif defined(__AROS__)
1201 AROS_LH0 (BPTR
, LibClose
,
1202 struct LibraryHeader
*, base
, 2, __MCC_
1207 STATIC BPTR LIBFUNC
LibClose(REG(a6
, struct LibraryHeader
*base
))
1212 D(DBF_STARTUP
, "LibClose(" CLASS
"): %ld", base
->lh_Library
.lib_OpenCnt
);
1214 // check if the user defined a ClassClose() function
1215 #if defined(CLASSCLOSE)
1217 struct ExecIFace
*IExec
= (struct ExecIFace
*)(*(struct ExecBase
**)4)->MainInterface
;
1220 ObtainSemaphore(&base
->lh_Semaphore
);
1222 // make sure we have enough stack here
1223 success
= callMccFunction(mccLibClose
, base
);
1225 // release the semaphore
1226 ReleaseSemaphore(&base
->lh_Semaphore
);
1230 // decrease the open counter
1231 base
->lh_Library
.lib_OpenCnt
--;
1233 // in case the opern counter is <= 0 we can
1234 // make sure that we free everything
1235 if(base
->lh_Library
.lib_OpenCnt
<= 0)
1237 // in case the late expunge flag is set we go and
1238 // expunge the library base right now
1239 if(base
->lh_Library
.lib_Flags
& LIBF_DELEXP
)
1241 rc
= LibDelete(base
);
1251 /*****************************************************************************************************/
1252 /*****************************************************************************************************/
1254 #if defined(__amigaos4__)
1255 STATIC IPTR LIBFUNC
MCC_Query(UNUSED
struct Interface
*self
, REG(d0
, LONG which
))
1257 #elif defined(__MORPHOS__)
1258 STATIC IPTR
MCC_Query(void)
1260 LONG which
= (LONG
)REG_D0
;
1261 #elif defined(__AROS__)
1262 AROS_LH1(IPTR
, MCC_Query
,
1263 AROS_LHA(LONG
, which
, D0
),
1264 UNUSED
struct LibraryHeader
*, base
, 5, __MCC_
1269 STATIC IPTR LIBFUNC
MCC_Query(REG(d0
, LONG which
))
1273 D(DBF_STARTUP
, "MCC_Query(" CLASS
"): %ld", which
);
1278 case 0: return((IPTR
)ThisClass
);
1282 case 1: return((IPTR
)ThisClassP
);
1285 #ifdef PREFSIMAGEOBJECT
1288 Object
*obj
= PREFSIMAGEOBJECT
;
1310 return((IPTR
)USEDCLASSES
);
1317 return((IPTR
)USEDCLASSESP
);
1324 return((IPTR
)SHORTHELP
);