1 /*******************************************************************************
4 Versionstring: $VER: mccinit.c 1.26 (06.03.2013)
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.
70 1.25 20.12.2010 : minimum required system version is now OS3.0 (V39).
71 1.26 06.03.2013 : removed _start entry point. This must be defined separately
72 to ensure it is the very first piece of code in the final
74 WIP 24.08.2013 fix for making it compilabe for both ABIv1 and v0 of AROS.
78 The purpose of this source file is to provide a template for the library init
79 code for a creation of an own MUI custom class (mcc/mcp) for AmigaOS4,
80 AmigaOS3 and MorphOS. By directly including this file (#include "mccinit.c")
81 and defining certain preprocessor values, a MUI developer doesn't have to
82 care about library init stuff which is normally highly system dependent and
83 various between different Amiga operating systems.
87 This file should be included by another source file (e.g. 'library.c') in
88 your main development branch while certain preprocessor macros right before
89 the include statement can be defined to change the behaviour of mccinit.c.
90 These possible macros are:
92 USERLIBID (char*) - version string for the mcc/mcp (exluding $VER:)
93 VERSION (int) - version number (must match USERLIBID)
94 REVISION (int) - revision number (must match USERLIBID)
95 CLASS (char*) - class name (including .mcc/.mcp)
96 MASTERVERSION (int) - the minimun required muimaster version
97 (default: MUIMASTER_VMIN)
98 MIN_STACKSIZE (int) - if defined, the specified minimum stack size
99 will be enforced when calling all user functions
100 like ClassXXXX() and PreClassXXX().
104 SUPERCLASS (char*) - superclass ID of MCC (e.g. MUIC_Area)
105 INSTDATA - name of instance data structure of MCC (e.g. InstData)
106 USEDCLASSES - name of NULL terminated string array which contains
107 names of other required custom classes for MCC.
108 _Dispatcher - name of Dispatcher function for MCC
112 SUPERCLASSP (char*) - superclass ID of MCP (e.g. MUIC_Mccprefs)
113 INSTDATAP - name of instance data structure of MCP
114 USEDCLASSESP - name of NULL terminated string array which contains
115 names of other required custom classes for MCC.
116 SHORTHELP (char*) - alternative help text for prefs program's listview
117 PREFSIMAGEOBJECT - pointer to the image object for the MCP
118 _DispatcherP - name of Dispatcher function for MCP
120 In addition, the following defines and functions can be defined or are
123 CLASSINIT - if defined, a "BOOL ClassInit(struct Library *base)"
124 function can be defined in your own code and will be called
125 right after the general library initialization are
126 finished. This function should then open own libraries
127 or do own library initialization tasks as it is only called
128 once at the very first library/class open.
130 CLASSEXPUNGE - if defined a "VOID ClassExpunge(struct Library *base)"
131 function can be defined in your own code and will be called
132 as soon as the library will be freed/expunged by the
133 operating system. In this function you should close/free
134 stuff you normally opened/allocated in CLASSINIT.
136 CLASSOPEN - if defined, a "BOOL ClassOpen(struct Library *base)"
137 function can be defined in your own code and will be called
138 right after each single application opens the custom class.
139 In this function you can then set flags or do library open
142 CLASSCLOSE - if defined a "VOID ClassClose(struct Library *base)"
143 function can be defined in your own code and will be called
144 right after the library was successfully flagged as closed
145 by the CloseLibrary() call of an application.
148 PRECLASSINIT - if defined a "BOOL PreClassInit(struct Library *base)"
149 function can be defined and will be called right _before_
150 and library initialization takes place.
152 POSTCLASSEXPUNGE - if defined a "BOOL PostClassExpunge(struct Library *base)"
153 function can be defined and will be called right _after_
154 the custom class was free via MUI_DeleteCustomClass() in
155 the library expunge phase.
159 The above class functions are normally called by the operating system
160 in a Forbid()/Permit() state. That means you are supposed to make sure that
161 your operations doesn't break the Forbid() state or otherwise you may run
162 into a race condition. However, we have added semaphore locking to partly
163 protect you from that case - but you should still consider doing processor
164 intensitive tasks in a library's own function instead of using those
165 class initialization functions.
167 *******************************************************************************/
169 /******************************************************************************/
171 /******************************************************************************/
176 #include <emul/emulinterface.h>
177 #include <emul/emulregs.h>
180 #include <exec/types.h>
181 #include <exec/memory.h>
182 #include <exec/libraries.h>
183 #include <exec/semaphores.h>
184 #include <exec/resident.h>
185 #include <exec/execbase.h>
188 #include <proto/exec.h>
189 #include <proto/muimaster.h>
190 #include <proto/utility.h>
191 #include <proto/dos.h>
192 #include <proto/graphics.h>
193 #include <proto/intuition.h>
196 #include <aros/libcall.h>
197 #include <utility/utility.h>
199 #include <aros/config.h>
203 #include "SDI_compiler.h"
205 #if defined(__amigaos4__)
206 struct Library
*MUIMasterBase
= NULL
;
207 struct Library
*SysBase
= NULL
;
208 struct Library
*UtilityBase
= NULL
;
209 struct Library
*DOSBase
= NULL
;
210 struct Library
*GfxBase
= NULL
;
211 struct Library
*IntuitionBase
= NULL
;
212 struct ExecIFace
*IExec
= NULL
;
213 struct MUIMasterIFace
*IMUIMaster
= NULL
;
214 struct UtilityIFace
*IUtility
= NULL
;
215 struct DOSIFace
*IDOS
= NULL
;
216 struct GraphicsIFace
*IGraphics
= NULL
;
217 struct IntuitionIFace
*IIntuition
= NULL
;
218 #if defined(__NEWLIB__)
219 struct Library
*NewlibBase
= NULL
;
220 struct Interface
*INewlib
= NULL
;
223 struct Library
*MUIMasterBase
= NULL
;
224 struct ExecBase
*SysBase
= NULL
;
225 #if defined(__AROS__)
226 struct UtilityBase
*UtilityBase
= NULL
;
228 struct Library
*UtilityBase
= NULL
;
230 struct DosLibrary
*DOSBase
= NULL
;
231 struct GfxBase
*GfxBase
= NULL
;
232 struct IntuitionBase
*IntuitionBase
= NULL
;
239 // we place a stack cookie in the binary so that
240 // newer OS version can directly take the specified
241 // number for the ramlib process
242 #if defined(MIN_STACKSIZE)
244 // transforms a define into a string
245 #define STR(x) STR2(x)
249 STATIC
const char USED_VAR stack_size
[] = "$STACK:" STR(MIN_STACKSIZE
) "\n";
253 /* The name of the class will also become the name of the library. */
254 /* We need a pointer to this string in our ROMTag (see below). */
255 STATIC
const char UserLibName
[] = CLASS
;
256 STATIC
const char UserLibID
[] = "$VER: " USERLIBID
;
259 STATIC
struct MUI_CustomClass
*ThisClass
= NULL
;
260 DISPATCHERPROTO(_Dispatcher
);
264 STATIC
struct MUI_CustomClass
*ThisClassP
= NULL
;
265 DISPATCHERPROTO(_DispatcherP
);
270 #if !defined(__NEWLIB__)
271 #if defined(__amigaos4__)
272 extern struct Library
*__UtilityBase
; // clib2
273 extern struct UtilityIFace
* __IUtility
; // clib2
275 struct Library
*__UtilityBase
= NULL
; // required by libnix & clib2
279 /* these one are needed copies for libnix.a */
281 #ifdef USE_MATHIEEEDOUBBASBASE
282 struct Library
*__MathIeeeDoubBasBase
= NULL
;
284 #ifdef USE_MATHIEEEDOUBTRANSBASE
285 struct Library
*__MathIeeeDoubTransBase
= NULL
;
289 #endif /* __GNUC__ */
292 // define own macros for the OS4 interfaces
295 #if defined(__amigaos4__)
296 #define GETINTERFACE(iface, type, base) (iface = (type)GetInterface((struct Library *)(base), "main", 1L, NULL))
297 #define DROPINTERFACE(iface) (DropInterface((struct Interface *)iface), iface = NULL)
299 #define GETINTERFACE(iface, type, base) TRUE
300 #define DROPINTERFACE(iface)
303 // in case the user didn't specify an own minimum
304 // muimaster version we increase it here.
305 #ifndef MASTERVERSION
306 #define MASTERVERSION MUIMASTER_VMIN
309 /* Our library structure, consisting of a struct Library, a segment pointer */
310 /* and a semaphore. We need the semaphore to protect init/exit stuff in our */
311 /* open/close fuSnctions */
314 struct Library lh_Library
;
317 struct SignalSemaphore lh_Semaphore
;
321 /******************************************************************************/
322 /* Local Structures & Prototypes */
323 /******************************************************************************/
325 #if defined(__amigaos4__)
327 STATIC
struct LibraryHeader
* LIBFUNC
LibInit (struct LibraryHeader
*base
, BPTR librarySegment
, struct ExecIFace
*pIExec
);
328 STATIC BPTR LIBFUNC
LibExpunge (struct LibraryManagerInterface
*Self
);
329 STATIC
struct LibraryHeader
* LIBFUNC
LibOpen (struct LibraryManagerInterface
*Self
, ULONG version
);
330 STATIC BPTR LIBFUNC
LibClose (struct LibraryManagerInterface
*Self
);
331 STATIC IPTR LIBFUNC
MCC_Query (UNUSED
struct Interface
*self
, REG(d0
, LONG which
));
333 #elif defined(__MORPHOS__)
335 STATIC
struct LibraryHeader
* LIBFUNC
LibInit (struct LibraryHeader
*base
, BPTR librarySegment
, struct ExecBase
*sb
);
336 STATIC BPTR LIBFUNC
LibExpunge (void);
337 STATIC
struct LibraryHeader
* LIBFUNC
LibOpen (void);
338 STATIC BPTR LIBFUNC
LibClose (void);
339 STATIC LONG LIBFUNC
LibNull (void);
340 STATIC IPTR LIBFUNC
MCC_Query (void);
342 #elif defined(__AROS__)
344 AROS_UFP3 (struct LibraryHeader
*, LibInit
,
345 AROS_UFPA(struct LibraryHeader
*, base
, D0
),
346 AROS_UFPA(BPTR
, librarySegment
, A0
),
347 AROS_UFPA(struct ExecBase
*, sb
, A6
)
349 AROS_LD1(BPTR
, LibExpunge
,
350 AROS_LPA(struct LibraryHeader
*, base
, D0
),
351 struct LibraryHeader
*, base
, 3, __MCC_
353 AROS_LD1 (struct LibraryHeader
*, LibOpen
,
354 AROS_LHA (ULONG
, version
, D0
),
355 struct LibraryHeader
*, base
, 1, __MCC_
357 AROS_LD0 (BPTR
, LibClose
,
358 struct LibraryHeader
*, base
, 2, __MCC_
360 AROS_LD1(IPTR
, MCC_Query
,
361 AROS_LHA(LONG
, what
, D0
),
362 struct LibraryHeader
*, LIBBASE
, 5, __MCC_
367 STATIC
struct LibraryHeader
* LIBFUNC
LibInit (REG(d0
, struct LibraryHeader
*base
), REG(a0
, BPTR librarySegment
), REG(a6
, struct ExecBase
*sb
));
368 STATIC BPTR LIBFUNC
LibExpunge (REG(a6
, struct LibraryHeader
*base
));
369 STATIC
struct LibraryHeader
* LIBFUNC
LibOpen (REG(d0
, ULONG version
), REG(a6
, struct LibraryHeader
*base
));
370 STATIC BPTR LIBFUNC
LibClose (REG(a6
, struct LibraryHeader
*base
));
371 STATIC LONG LIBFUNC
LibNull (void);
372 STATIC IPTR LIBFUNC
MCC_Query (REG(d0
, LONG which
));
376 /******************************************************************************/
377 /* Dummy LibNull() function */
378 /******************************************************************************/
380 #if !defined(__amigaos4__)
381 STATIC LONG LIBFUNC
LibNull(VOID
)
387 /******************************************************************************/
388 /* Local data structures */
389 /******************************************************************************/
391 #if defined(__amigaos4__)
392 /* ------------------- OS4 Manager Interface ------------------------ */
393 STATIC uint32
_manager_Obtain(struct LibraryManagerInterface
*Self
)
396 __asm__
__volatile__(
402 : "r" (&Self
->Data
.RefCount
)
408 STATIC uint32
_manager_Release(struct LibraryManagerInterface
*Self
)
411 __asm__
__volatile__(
417 : "r" (&Self
->Data
.RefCount
)
423 STATIC CONST CONST_APTR lib_manager_vectors
[] =
425 (CONST_APTR
)_manager_Obtain
,
426 (CONST_APTR
)_manager_Release
,
430 (CONST_APTR
)LibClose
,
431 (CONST_APTR
)LibExpunge
,
436 STATIC CONST
struct TagItem lib_managerTags
[] =
438 { MIT_Name
, (Tag
)"__library" },
439 { MIT_VectorTable
, (Tag
)lib_manager_vectors
},
444 /* ------------------- Library Interface(s) ------------------------ */
446 ULONG
_MCCClass_Obtain(UNUSED
struct Interface
*Self
)
451 ULONG
_MCCClass_Release(UNUSED
struct Interface
*Self
)
456 STATIC CONST CONST_APTR main_vectors
[] =
458 (CONST_APTR
)_MCCClass_Obtain
,
459 (CONST_APTR
)_MCCClass_Release
,
462 (CONST_APTR
)MCC_Query
,
466 STATIC CONST
struct TagItem mainTags
[] =
468 { MIT_Name
, (Tag
)"main" },
469 { MIT_VectorTable
, (Tag
)main_vectors
},
474 STATIC CONST CONST_APTR libInterfaces
[] =
476 (CONST_APTR
)lib_managerTags
,
477 (CONST_APTR
)mainTags
,
481 // Our libraries always have to carry a 68k jump table with it, so
482 // lets define it here as extern, as we are going to link it to
484 #ifndef NO_VECTABLE68K
485 extern CONST APTR VecTable68K
[];
488 STATIC CONST
struct TagItem libCreateTags
[] =
490 { CLT_DataSize
, sizeof(struct LibraryHeader
) },
491 { CLT_InitFunc
, (Tag
)LibInit
},
492 { CLT_Interfaces
, (Tag
)libInterfaces
},
493 #ifndef NO_VECTABLE68K
494 { CLT_Vector68K
, (Tag
)VecTable68K
},
501 STATIC CONST CONST_APTR LibVectors
[] =
504 (CONST_APTR
)FUNCARRAY_32BIT_NATIVE
,
508 (CONST_APTR
)LibClose
,
509 (CONST_APTR
)LibExpunge
,
511 (CONST_APTR
)MCC_Query
,
514 (CONST_APTR
)AROS_SLIB_ENTRY(LibOpen
, __MCC_
, 1),
515 (CONST_APTR
)AROS_SLIB_ENTRY(LibClose
, __MCC_
, 2),
516 (CONST_APTR
)AROS_SLIB_ENTRY(LibExpunge
, __MCC_
, 3),
518 (CONST_APTR
)AROS_SLIB_ENTRY(MCC_Query
, __MCC_
, 5),
520 (CONST_APTR
)AROS_SLIB_ENTRY(LibOpen
, __MCC_
),
521 (CONST_APTR
)AROS_SLIB_ENTRY(LibClose
, __MCC_
),
522 (CONST_APTR
)AROS_SLIB_ENTRY(LibExpunge
, __MCC_
),
524 (CONST_APTR
)AROS_SLIB_ENTRY(MCC_Query
, __MCC_
),
530 STATIC CONST IPTR LibInitTab
[] =
532 sizeof(struct LibraryHeader
),
540 /* ------------------- ROM Tag ------------------------ */
541 STATIC
const USED_VAR
struct Resident ROMTag
=
544 (struct Resident
*)&ROMTag
,
545 (struct Resident
*)(&ROMTag
+ 1),
546 #if defined(__amigaos4__)
547 RTF_AUTOINIT
|RTF_NATIVE
, // The Library should be set up according to the given table.
548 #elif defined(__MORPHOS__)
549 RTF_AUTOINIT
|RTF_EXTENDED
|RTF_PPC
,
550 #elif defined(__AROS__)
551 RTF_AUTOINIT
|RTF_EXTENDED
,
559 (char *)UserLibID
+6, // +6 to skip '$VER: '
560 #if defined(__amigaos4__)
561 (APTR
)libCreateTags
, // This table is for initializing the Library.
565 #if defined(__MORPHOS__) || defined(__AROS__)
571 #if defined(__MORPHOS__)
573 * To tell the loader that this is a new emulppc elf and not
574 * one for the ppc.library.
577 const USED_VAR ULONG __abox__
= 1;
579 #endif /* __MORPHOS__ */
581 /****************************************************************************/
582 /* Stack enforcing function which allows to make sure that a function has */
583 /* enough stack space during its execution time */
584 /****************************************************************************/
586 #if defined(MIN_STACKSIZE) && !defined(__amigaos4__)
588 /* generic StackSwap() function which calls function() surrounded by
590 #if defined(__AROS__)
591 ULONG
stackswap_call(struct StackSwapStruct
*stack
,
592 ULONG (*function
)(struct LibraryHeader
*),
593 struct LibraryHeader
*arg
)
595 struct StackSwapArgs swapargs
;
597 swapargs
.Args
[0] = (IPTR
)arg
;
599 return NewStackSwap(stack
, function
, &swapargs
);
601 #elif defined(__MORPHOS__)
602 ULONG
stackswap_call(struct StackSwapStruct
*stack
,
603 ULONG (*function
)(struct LibraryHeader
*),
604 struct LibraryHeader
*arg
)
606 struct PPCStackSwapArgs swapargs
;
608 swapargs
.Args
[0] = (ULONG
)arg
;
610 return NewPPCStackSwap(stack
, function
, &swapargs
);
612 #elif defined(__mc68000__)
613 ULONG
stackswap_call(struct StackSwapStruct
*stack
,
614 ULONG (*function
)(struct LibraryHeader
*),
615 struct LibraryHeader
*arg
);
619 .globl _stackswap_call \n\
621 moveml #0x3022,sp@- \n\
625 movel _SysBase,a6 \n\
632 movel _SysBase,a6 \n\
636 moveml sp@+,#0x440c \n\
639 #error Bogus operating system
642 STATIC BOOL
callMccFunction(ULONG (*function
)(struct LibraryHeader
*), struct LibraryHeader
*arg
)
644 BOOL success
= FALSE
;
648 // retrieve the task structure for the
652 #if defined(__MORPHOS__)
653 // In MorphOS we have two stacks. One for PPC code and another for 68k code.
654 // We are only interested in the PPC stack.
655 NewGetTaskAttrsA(tc
, &stacksize
, sizeof(ULONG
), TASKINFOTYPE_STACKSIZE
, NULL
);
657 // on all other systems we query via SPUpper-SPLower calculation
658 stacksize
= (IPTR
)tc
->tc_SPUpper
- (IPTR
)tc
->tc_SPLower
;
661 // Swap stacks only if current stack is insufficient
662 if(stacksize
< MIN_STACKSIZE
)
664 struct StackSwapStruct
*stack
;
666 if((stack
= AllocVec(sizeof(*stack
), MEMF_PUBLIC
)) != NULL
)
668 if((stack
->stk_Lower
= AllocVec(MIN_STACKSIZE
, MEMF_PUBLIC
)) != NULL
)
670 // perform the StackSwap
671 #if defined(__AROS__)
672 // AROS uses an APTR type for stk_Upper
673 stack
->stk_Upper
= (APTR
)((IPTR
)stack
->stk_Lower
+ MIN_STACKSIZE
);
675 // all other systems use ULONG
676 stack
->stk_Upper
= (ULONG
)stack
->stk_Lower
+ MIN_STACKSIZE
;
678 stack
->stk_Pointer
= (APTR
)stack
->stk_Upper
;
680 // call routine but with embedding it into a [NewPPC]StackSwap()
681 success
= stackswap_call(stack
, function
, arg
);
683 FreeVec(stack
->stk_Lower
);
689 success
= function(arg
);
693 #else // MIN_STACKSIZE && __amigaos4__
694 #define callMccFunction(func, arg) func(arg)
695 #endif // MIN_STACKSIZE && __amigaos4__
697 /******************************************************************************/
698 /* Wrapper functions to perform certain tasks in our LibInit/LibOpen etc. */
699 /******************************************************************************/
701 /* open and init all necessary library and stuff in the LibInit() phase */
702 STATIC ULONG
mccLibInit(struct LibraryHeader
*base
)
704 // now that this library/class is going to be initialized for the first time
705 // we go and open all necessary libraries on our own
706 #if defined(__amigaos4__)
707 if((DOSBase
= OpenLibrary("dos.library", 39)) &&
708 GETINTERFACE(IDOS
, struct DOSIFace
*, DOSBase
))
709 if((GfxBase
= OpenLibrary("graphics.library", 39)) &&
710 GETINTERFACE(IGraphics
, struct GraphicsIFace
*, GfxBase
))
711 if((IntuitionBase
= OpenLibrary("intuition.library", 39)) &&
712 GETINTERFACE(IIntuition
, struct IntuitionIFace
*, IntuitionBase
))
713 if((UtilityBase
= OpenLibrary("utility.library", 39)) &&
714 GETINTERFACE(IUtility
, struct UtilityIFace
*, UtilityBase
))
716 if((DOSBase
= (struct DosLibrary
*)OpenLibrary("dos.library", 39)) &&
717 (GfxBase
= (struct GfxBase
*)OpenLibrary("graphics.library", 39)) &&
718 (IntuitionBase
= (struct IntuitionBase
*)OpenLibrary("intuition.library", 39)) &&
719 (UtilityBase
= (APTR
)OpenLibrary("utility.library", 39)))
722 // we have to please the internal utilitybase
723 // pointers of libnix and clib2
724 #if !defined(__NEWLIB__)
725 __UtilityBase
= (APTR
)UtilityBase
;
726 #if defined(__amigaos4__)
727 __IUtility
= IUtility
;
735 if((MUIMasterBase
= OpenLibrary(MUIMASTER_NAME
, MASTERVERSION
)) &&
736 GETINTERFACE(IMUIMaster
, struct MUIMasterIFace
*, MUIMasterBase
))
738 #if defined(PRECLASSINIT)
743 ThisClass
= MUI_CreateCustomClass(&base
->lh_Library
, (STRPTR
)SUPERCLASS
, NULL
, sizeof(struct INSTDATA
), ENTRY(_Dispatcher
));
748 if((ThisClassP
= MUI_CreateCustomClass(&base
->lh_Library
, (STRPTR
)SUPERCLASSP
, NULL
, sizeof(struct INSTDATAP
), ENTRY(_DispatcherP
))))
752 #define THISCLASS ThisClass
754 #define THISCLASS ThisClassP
757 // in case the user defined an own ClassInit()
758 // function we call it protected by a semaphore as
759 // this user may be stupid and break the Forbid() state
761 #if defined(CLASSINIT)
762 if(ClassInit(&base
->lh_Library
))
765 // everything was successfully so lets
766 // make sure we return TRUE
769 #if defined(CLASSINIT)
771 E(DBF_STARTUP
, "ClassInit(%s) failed", CLASS
);
774 // if we pass this point than an error
775 // occurred and we have to cleanup
776 #if defined(SUPERCLASSP)
777 MUI_DeleteCustomClass(ThisClassP
);
782 #if defined(SUPERCLASS)
783 MUI_DeleteCustomClass(ThisClass
);
789 DROPINTERFACE(IMUIMaster
);
790 CloseLibrary(MUIMasterBase
);
791 MUIMasterBase
= NULL
;
794 DROPINTERFACE(IUtility
);
795 CloseLibrary((struct Library
*)UtilityBase
);
801 DROPINTERFACE(IIntuition
);
802 CloseLibrary((struct Library
*)IntuitionBase
);
803 IntuitionBase
= NULL
;
808 DROPINTERFACE(IGraphics
);
809 CloseLibrary((struct Library
*)GfxBase
);
816 CloseLibrary((struct Library
*)DOSBase
);
820 E(DBF_STARTUP
, "mccLibInit(%s) failed", CLASS
);
824 /* expunge everything we previously opened and call user definable functions */
825 STATIC ULONG
mccLibExpunge(UNUSED
struct LibraryHeader
*base
)
827 // in case the user specified that he has an own class
828 // expunge function we call it right here, not caring about
830 #if defined(CLASSEXPUNGE)
831 ClassExpunge(&base
->lh_Library
);
834 // now we remove our own stuff here step-by-step
838 MUI_DeleteCustomClass(ThisClassP
);
846 MUI_DeleteCustomClass(ThisClass
);
851 // we inform the user that all main class expunge stuff
852 // is finished, if he want's to get informed.
853 #if defined(POSTCLASSEXPUNGE)
861 // cleanup the various library bases and such
864 DROPINTERFACE(IMUIMaster
);
865 CloseLibrary(MUIMasterBase
);
866 MUIMasterBase
= NULL
;
871 DROPINTERFACE(IUtility
);
872 CloseLibrary((struct Library
*)UtilityBase
);
878 DROPINTERFACE(IIntuition
);
879 CloseLibrary((struct Library
*)IntuitionBase
);
880 IntuitionBase
= NULL
;
885 DROPINTERFACE(IGraphics
);
886 CloseLibrary((struct Library
*)GfxBase
);
893 CloseLibrary((struct Library
*)DOSBase
);
900 /* we call the user definable function here only */
901 #if defined(CLASSOPEN)
902 STATIC ULONG
mccLibOpen(struct LibraryHeader
*base
)
904 return ClassOpen(&base
->lh_Library
);
908 /* we call the user definable function here only */
909 #if defined(CLASSCLOSE)
910 STATIC ULONG
mccLibClose(struct LibraryHeader
*base
)
912 ClassClose(&base
->lh_Library
);
917 /******************************************************************************/
918 /* Standard Library Functions, all of them are called in Forbid() state. */
919 /******************************************************************************/
921 #if defined(__amigaos4__)
922 STATIC
struct LibraryHeader
* LibInit(struct LibraryHeader
*base
, BPTR librarySegment
, struct ExecIFace
*pIExec
)
924 struct Library
*sb
= (struct Library
*)pIExec
->Data
.LibBase
;
926 #elif defined(__MORPHOS__)
927 STATIC
struct LibraryHeader
* LibInit(struct LibraryHeader
*base
, BPTR librarySegment
, struct ExecBase
*sb
)
929 #elif defined(__AROS__)
930 AROS_UFH3 (struct LibraryHeader
*, LibInit
,
931 AROS_UFHA(struct LibraryHeader
*, base
, D0
),
932 AROS_UFHA(BPTR
, librarySegment
, A0
),
933 AROS_UFHA(struct ExecBase
*, sb
, A6
)
938 STATIC
struct LibraryHeader
* LIBFUNC
LibInit(REG(d0
, struct LibraryHeader
*base
), REG(a0
, BPTR librarySegment
), REG(a6
, struct ExecBase
*sb
))
944 // make sure that this is really a 68020+ machine if optimized for 020+
945 #if _M68060 || _M68040 || _M68030 || _M68020 || __mc68020 || __mc68030 || __mc68040 || __mc68060
946 if(!(SysBase
->AttnFlags
& AFF_68020
))
950 #if defined(__amigaos4__) && defined(__NEWLIB__)
951 if((NewlibBase
= OpenLibrary("newlib.library", 3)) &&
952 GETINTERFACE(INewlib
, struct Interface
*, NewlibBase
))
955 BOOL success
= FALSE
;
957 D(DBF_STARTUP
, "LibInit(" CLASS
")");
959 // cleanup the library header structure beginning with the
960 // library base, even if that is done automcatically, we explicitly
961 // do it here for consistency reasons.
962 base
->lh_Library
.lib_Node
.ln_Type
= NT_LIBRARY
;
963 base
->lh_Library
.lib_Node
.ln_Pri
= 0;
964 base
->lh_Library
.lib_Node
.ln_Name
= (char *)UserLibName
;
965 base
->lh_Library
.lib_Flags
= LIBF_CHANGED
| LIBF_SUMUSED
;
966 base
->lh_Library
.lib_IdString
= (char *)UserLibID
; // here without +6 or otherwise MUI doesn't identify it.
967 base
->lh_Library
.lib_Version
= VERSION
;
968 base
->lh_Library
.lib_Revision
= REVISION
;
970 // init our protecting semaphore and the
971 // initialized flag variable
972 memset(&base
->lh_Semaphore
, 0, sizeof(base
->lh_Semaphore
));
973 InitSemaphore(&base
->lh_Semaphore
);
975 // protect mccLibInit()
976 ObtainSemaphore(&base
->lh_Semaphore
);
978 // If we are not running on AmigaOS4 (no stackswap required) we go and
979 // do an explicit StackSwap() in case the user wants to make sure we
980 // have enough stack for his user functions
981 success
= callMccFunction(mccLibInit
, base
);
984 ReleaseSemaphore(&base
->lh_Semaphore
);
986 // check if everything worked out fine
989 // everything was successfully so lets
990 // set the initialized value and contiue
991 // with the class open phase
992 base
->lh_Segment
= librarySegment
;
994 // return the library base as success
998 #if defined(__amigaos4__) && defined(__NEWLIB__)
1001 DROPINTERFACE(INewlib
);
1002 CloseLibrary(NewlibBase
);
1014 /*****************************************************************************************************/
1015 /*****************************************************************************************************/
1017 #ifndef __amigaos4__
1018 #define DeleteLibrary(LIB) \
1019 FreeMem((STRPTR)(LIB)-(LIB)->lib_NegSize, (ULONG)((LIB)->lib_NegSize+(LIB)->lib_PosSize))
1022 STATIC BPTR
LibDelete(struct LibraryHeader
*base
)
1024 #if defined(__amigaos4__)
1025 struct ExecIFace
*IExec
= (struct ExecIFace
*)(*(struct ExecBase
**)4)->MainInterface
;
1029 // remove the library base from exec's lib list in advance
1030 Remove((struct Node
*)base
);
1032 // protect mccLibExpunge()
1033 ObtainSemaphore(&base
->lh_Semaphore
);
1035 // make sure we have enough stack here
1036 callMccFunction(mccLibExpunge
, base
);
1039 ReleaseSemaphore(&base
->lh_Semaphore
);
1041 #if defined(__amigaos4__) && defined(__NEWLIB__)
1044 DROPINTERFACE(INewlib
);
1045 CloseLibrary(NewlibBase
);
1050 // make sure the system deletes the library as well.
1051 rc
= base
->lh_Segment
;
1052 DeleteLibrary(&base
->lh_Library
);
1057 #if defined(__amigaos4__)
1058 STATIC BPTR
LibExpunge(struct LibraryManagerInterface
*Self
)
1060 struct LibraryHeader
*base
= (struct LibraryHeader
*)Self
->Data
.LibBase
;
1061 #elif defined(__MORPHOS__)
1062 STATIC BPTR
LibExpunge(void)
1064 struct LibraryHeader
*base
= (struct LibraryHeader
*)REG_A6
;
1065 #elif defined(__AROS__)
1066 AROS_LH1 (BPTR
, LibExpunge
,
1067 AROS_LHA(UNUSED
struct LibraryHeader
*, extralh
, D0
),
1068 struct LibraryHeader
*, base
, 3, __MCC_
1073 STATIC BPTR LIBFUNC
LibExpunge(REG(a6
, struct LibraryHeader
*base
))
1078 D(DBF_STARTUP
, "LibExpunge(" CLASS
"): %ld", base
->lh_Library
.lib_OpenCnt
);
1080 // in case our open counter is still > 0, we have
1081 // to set the late expunge flag and return immediately
1082 if(base
->lh_Library
.lib_OpenCnt
> 0)
1084 base
->lh_Library
.lib_Flags
|= LIBF_DELEXP
;
1089 rc
= LibDelete(base
);
1098 /*****************************************************************************************************/
1099 /*****************************************************************************************************/
1101 #if defined(__amigaos4__)
1102 STATIC
struct LibraryHeader
*LibOpen(struct LibraryManagerInterface
*Self
, ULONG version UNUSED
)
1104 struct LibraryHeader
*base
= (struct LibraryHeader
*)Self
->Data
.LibBase
;
1105 #elif defined(__MORPHOS__)
1106 STATIC
struct LibraryHeader
*LibOpen(void)
1108 struct LibraryHeader
*base
= (struct LibraryHeader
*)REG_A6
;
1109 #elif defined(__AROS__)
1110 AROS_LH1 (struct LibraryHeader
*, LibOpen
,
1111 AROS_LHA (UNUSED ULONG
, version
, D0
),
1112 struct LibraryHeader
*, base
, 1, __MCC_
1117 STATIC
struct LibraryHeader
* LIBFUNC
LibOpen(REG(d0
, UNUSED ULONG version
), REG(a6
, struct LibraryHeader
*base
))
1120 struct LibraryHeader
*res
= NULL
;
1122 D(DBF_STARTUP
, "LibOpen(" CLASS
"): %ld", base
->lh_Library
.lib_OpenCnt
);
1124 // LibOpen(), LibClose() and LibExpunge() are called while the system is in
1125 // Forbid() state. That means that these functions should be quick and should
1126 // not break this Forbid()!! Therefore the open counter should be increased
1127 // as the very first instruction during LibOpen(), because a ClassOpen()
1128 // which breaks a Forbid() and another task calling LibExpunge() will cause
1129 // to expunge this library while it is not yet fully initialized. A crash
1130 // is unavoidable then. Even the semaphore does not guarantee 100% protection
1131 // against such a race condition, because waiting for the semaphore to be
1132 // obtained will effectively break the Forbid()!
1134 // increase the open counter ahead of anything else
1135 base
->lh_Library
.lib_OpenCnt
++;
1137 // delete the late expunge flag
1138 base
->lh_Library
.lib_Flags
&= ~LIBF_DELEXP
;
1140 // check if the user defined a ClassOpen() function
1141 #if defined(CLASSOPEN)
1143 struct ExecIFace
*IExec
= (struct ExecIFace
*)(*(struct ExecBase
**)4)->MainInterface
;
1144 BOOL success
= FALSE
;
1147 ObtainSemaphore(&base
->lh_Semaphore
);
1149 // make sure we have enough stack here
1150 success
= callMccFunction(mccLibOpen
, base
);
1152 // here we call the user-specific function for LibOpen() where
1153 // he can do whatever he wants because of the semaphore protection.
1158 E(DBF_STARTUP
, "ClassOpen(" CLASS
") failed");
1160 // decrease the open counter again
1161 base
->lh_Library
.lib_OpenCnt
--;
1164 // release the semaphore
1165 ReleaseSemaphore(&base
->lh_Semaphore
);
1177 /*****************************************************************************************************/
1178 /*****************************************************************************************************/
1180 #if defined(__amigaos4__)
1181 STATIC BPTR
LibClose(struct LibraryManagerInterface
*Self
)
1183 struct LibraryHeader
*base
= (struct LibraryHeader
*)Self
->Data
.LibBase
;
1184 #elif defined(__MORPHOS__)
1185 STATIC BPTR
LibClose(void)
1187 struct LibraryHeader
*base
= (struct LibraryHeader
*)REG_A6
;
1188 #elif defined(__AROS__)
1189 AROS_LH0 (BPTR
, LibClose
,
1190 struct LibraryHeader
*, base
, 2, __MCC_
1195 STATIC BPTR LIBFUNC
LibClose(REG(a6
, struct LibraryHeader
*base
))
1200 D(DBF_STARTUP
, "LibClose(" CLASS
"): %ld", base
->lh_Library
.lib_OpenCnt
);
1202 // check if the user defined a ClassClose() function
1203 #if defined(CLASSCLOSE)
1205 struct ExecIFace
*IExec
= (struct ExecIFace
*)(*(struct ExecBase
**)4)->MainInterface
;
1208 ObtainSemaphore(&base
->lh_Semaphore
);
1210 // make sure we have enough stack here
1211 success
= callMccFunction(mccLibClose
, base
);
1213 // release the semaphore
1214 ReleaseSemaphore(&base
->lh_Semaphore
);
1218 // decrease the open counter
1219 base
->lh_Library
.lib_OpenCnt
--;
1221 // in case the opern counter is <= 0 we can
1222 // make sure that we free everything
1223 if(base
->lh_Library
.lib_OpenCnt
<= 0)
1225 // in case the late expunge flag is set we go and
1226 // expunge the library base right now
1227 if(base
->lh_Library
.lib_Flags
& LIBF_DELEXP
)
1229 rc
= LibDelete(base
);
1239 /*****************************************************************************************************/
1240 /*****************************************************************************************************/
1242 #if defined(__amigaos4__)
1243 STATIC IPTR LIBFUNC
MCC_Query(UNUSED
struct Interface
*self
, REG(d0
, LONG which
))
1245 #elif defined(__MORPHOS__)
1246 STATIC IPTR
MCC_Query(void)
1248 LONG which
= (LONG
)REG_D0
;
1249 #elif defined(__AROS__)
1250 AROS_LH1(IPTR
, MCC_Query
,
1251 AROS_LHA(LONG
, which
, D0
),
1252 UNUSED
struct LibraryHeader
*, base
, 5, __MCC_
1257 STATIC IPTR LIBFUNC
MCC_Query(REG(d0
, LONG which
))
1261 D(DBF_STARTUP
, "MCC_Query(" CLASS
"): %ld", which
);
1266 case 0: return((IPTR
)ThisClass
);
1270 case 1: return((IPTR
)ThisClassP
);
1273 #ifdef PREFSIMAGEOBJECT
1276 Object
*obj
= PREFSIMAGEOBJECT
;
1298 return((IPTR
)USEDCLASSES
);
1305 return((IPTR
)USEDCLASSESP
);
1312 return((IPTR
)SHORTHELP
);