Fixed compatibility of output.
[AROS.git] / external / openurl / library / libinit.c
blob35e209af667248e814ec69cabaa3d34820759c73
1 /***************************************************************************
3 openurl.library - universal URL display and browser launcher library
4 Copyright (C) 1998-2005 by Troels Walsted Hansen, et al.
5 Copyright (C) 2005-2010 by openurl.library Open Source Team
7 This library is free software; it has been placed in the public domain
8 and you can freely redistribute it and/or modify it. Please note, however,
9 that some components may be under the LGPL or GPL license.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 openurl.library project: http://sourceforge.net/projects/openurllib/
17 $Id$
19 ***************************************************************************/
21 #include "lib.h"
22 #include "version.h"
24 #include <exec/resident.h>
25 #include <proto/exec.h>
27 #include "macros.h"
28 #include "debug.h"
30 /****************************************************************************/
33 * The system (and compiler) rely on a symbol named _start which marks
34 * the beginning of execution of an ELF file. To prevent others from
35 * executing this library, and to keep the compiler/linker happy, we
36 * define an empty _start symbol here.
38 * On the classic system (pre-AmigaOS4) this was usually done by
39 * moveq #0,d0
40 * rts
44 #if defined(__amigaos3__)
45 asm(".text\n\
46 .even\n\
47 .globl _start\n\
48 _start:\n\
49 moveq #20,d0\n\
50 rts");
51 #elif defined(__AROS__)
52 __startup int Main(void)
54 return RETURN_FAIL;
56 #else
57 LONG _start(void)
59 return RETURN_FAIL;
61 #endif
63 /****************************************************************************/
65 #if defined(__amigaos4__)
66 // stack cookie for shell v45+
67 static const char USED_VAR stack_size[] = "$STACK:" STR(MIN_STACKSIZE) "\n";
68 #endif
70 /****************************************************************************/
72 #if defined(__amigaos4__)
73 struct Library *SysBase = NULL;
74 struct ExecIFace* IExec = NULL;
75 #if defined(__NEWLIB__)
76 struct Library *NewlibBase = NULL;
77 struct NewlibIFace* INewlib = NULL;
78 #endif
79 #else
80 struct ExecBase *SysBase = NULL;
81 #endif
83 struct LibraryHeader *OpenURLBase = NULL;
84 #if defined(__amigaos4__)
85 struct OpenURLIFace *IOpenURL = NULL;
86 #endif
88 static const char UserLibName[] = "openurl.library";
89 static const char UserLibID[] = "$VER: openurl.library " LIB_REV_STRING " [" SYSTEMSHORT "/" CPU "] (" LIB_DATE ") " LIB_COPYRIGHT;
91 /****************************************************************************/
93 #define libvector LFUNC_FAS(URL_OpenA) \
94 LFUNC_VA_(URL_Open) \
95 LFUNC_FA_(URL_OldGetPrefs) \
96 LFUNC_FA_(URL_OldFreePrefs) \
97 LFUNC_FA_(URL_OldSetPrefs) \
98 LFUNC_FA_(URL_OldGetDefaultPrefs) \
99 LFUNC_FA_(URL_OldLaunchPrefsApp) \
100 LFUNC_FA_(dispatch) \
101 LFUNC_FA_(URL_GetPrefsA) \
102 LFUNC_VA_(URL_GetPrefs) \
103 LFUNC_FA_(URL_FreePrefsA) \
104 LFUNC_VA_(URL_FreePrefs) \
105 LFUNC_FA_(URL_SetPrefsA) \
106 LFUNC_VA_(URL_SetPrefs) \
107 LFUNC_FA_(URL_LaunchPrefsAppA) \
108 LFUNC_VA_(URL_LaunchPrefsApp) \
109 LFUNC_FA_(URL_GetAttr)
111 /****************************************************************************/
113 #if defined(__amigaos4__)
115 static struct LibraryHeader * LIBFUNC LibInit (struct LibraryHeader *base, BPTR librarySegment, struct ExecIFace *pIExec);
116 static BPTR LIBFUNC LibExpunge (struct LibraryManagerInterface *Self);
117 static struct LibraryHeader * LIBFUNC LibOpen (struct LibraryManagerInterface *Self, ULONG version);
118 static BPTR LIBFUNC LibClose (struct LibraryManagerInterface *Self);
119 //static LONG LIBFUNC LibNull (void);
121 #elif defined(__MORPHOS__)
123 static struct LibraryHeader * LIBFUNC LibInit (struct LibraryHeader *base, BPTR librarySegment, struct ExecBase *sb);
124 static BPTR LIBFUNC LibExpunge(void);
125 static struct LibraryHeader * LIBFUNC LibOpen (void);
126 static BPTR LIBFUNC LibClose (void);
127 static LONG LIBFUNC LibNull (void);
129 #elif defined(__AROS__)
131 #include <aros/libcall.h>
133 #define Openurl_LibOpen LibOpen
134 #define Openurl_LibClose LibClose
135 #define Openurl_LibExpunge LibExpunge
137 static AROS_UFP3 (struct LibraryHeader *, LibInit,
138 AROS_UFPA(struct LibraryHeader *, base, D0),
139 AROS_UFPA(BPTR, librarySegment, A0),
140 AROS_UFPA(struct ExecBase *, sb, A6)
142 static AROS_LD1 (struct LibraryHeader *, LibOpen,
143 AROS_LPA (UNUSED ULONG, version, D0),
144 struct LibraryHeader *, base, 1, Openurl
146 static AROS_LD0 (BPTR, LibClose,
147 struct LibraryHeader *, base, 2, Openurl
149 static AROS_LD1(BPTR, LibExpunge,
150 AROS_LPA(UNUSED struct LibraryHeader *, __extrabase, D0),
151 struct LibraryHeader *, base, 3, Openurl
154 #else
156 static struct LibraryHeader * LIBFUNC LibInit (REG(d0, struct LibraryHeader *lh), REG(a0, BPTR Segment), REG(a6, struct ExecBase *sb));
157 static BPTR LIBFUNC LibExpunge (REG(a6, struct LibraryHeader *base));
158 static struct LibraryHeader * LIBFUNC LibOpen (REG(d0, ULONG version), REG(a6, struct LibraryHeader *base));
159 static BPTR LIBFUNC LibClose (REG(a6, struct LibraryHeader *base));
160 static LONG LIBFUNC LibNull (void);
162 #endif
164 /****************************************************************************/
166 #if !defined(__amigaos4__)
167 static LONG LIBFUNC LibNull(VOID)
169 return(0);
171 #endif
173 /****************************************************************************/
175 #if defined(__amigaos4__)
176 /* ------------------- OS4 Manager Interface ------------------------ */
177 STATIC uint32 _manager_Obtain(struct LibraryManagerInterface *Self)
179 uint32 res;
180 __asm__ __volatile__(
181 "1: lwarx %0,0,%1\n"
182 "addic %0,%0,1\n"
183 "stwcx. %0,0,%1\n"
184 "bne- 1b"
185 : "=&r" (res)
186 : "r" (&Self->Data.RefCount)
187 : "cc", "memory");
189 return res;
192 STATIC uint32 _manager_Release(struct LibraryManagerInterface *Self)
194 uint32 res;
195 __asm__ __volatile__(
196 "1: lwarx %0,0,%1\n"
197 "addic %0,%0,-1\n"
198 "stwcx. %0,0,%1\n"
199 "bne- 1b"
200 : "=&r" (res)
201 : "r" (&Self->Data.RefCount)
202 : "cc", "memory");
204 return res;
207 STATIC CONST CONST_APTR lib_manager_vectors[] =
209 (CONST_APTR)_manager_Obtain,
210 (CONST_APTR)_manager_Release,
211 (CONST_APTR)NULL,
212 (CONST_APTR)NULL,
213 (CONST_APTR)LibOpen,
214 (CONST_APTR)LibClose,
215 (CONST_APTR)LibExpunge,
216 (CONST_APTR)NULL,
217 (CONST_APTR)-1
220 STATIC CONST struct TagItem lib_managerTags[] =
222 { MIT_Name, (Tag)"__library" },
223 { MIT_VectorTable, (Tag)lib_manager_vectors },
224 { MIT_Version, 1 },
225 { TAG_DONE, 0 }
228 /* ------------------- Library Interface(s) ------------------------ */
230 ULONG LibObtain(UNUSED struct Interface *Self)
232 return 0;
235 ULONG LibRelease(UNUSED struct Interface *Self)
237 return 0;
240 STATIC CONST CONST_APTR main_vectors[] =
242 (CONST_APTR)LibObtain,
243 (CONST_APTR)LibRelease,
244 (CONST_APTR)NULL,
245 (CONST_APTR)NULL,
246 (CONST_APTR)libvector,
247 (CONST_APTR)-1
250 STATIC CONST struct TagItem mainTags[] =
252 { MIT_Name, (Tag)"main" },
253 { MIT_VectorTable, (Tag)main_vectors },
254 { MIT_Version, 1 },
255 { TAG_DONE, 0 }
258 STATIC CONST CONST_APTR libInterfaces[] =
260 (CONST_APTR)lib_managerTags,
261 (CONST_APTR)mainTags,
262 (CONST_APTR)NULL
265 // Our libraries always have to carry a 68k jump table with it, so
266 // lets define it here as extern, as we are going to link it to
267 // our binary here.
268 #ifndef NO_VECTABLE68K
269 extern CONST APTR VecTable68K[];
270 #endif
272 STATIC CONST struct TagItem libCreateTags[] =
274 { CLT_DataSize, sizeof(struct LibraryHeader) },
275 { CLT_InitFunc, (Tag)LibInit },
276 { CLT_Interfaces, (Tag)libInterfaces },
277 #ifndef NO_VECTABLE68K
278 { CLT_Vector68K, (Tag)VecTable68K },
279 #endif
280 { TAG_DONE, 0 }
283 #else
285 STATIC CONST CONST_APTR LibVectors[] =
287 #ifdef __MORPHOS__
288 (CONST_APTR)FUNCARRAY_32BIT_NATIVE,
289 #endif
290 #if defined(__AROS__)
291 #ifdef AROS_ABI_V1
292 (CONST_APTR)AROS_SLIB_ENTRY(LibOpen, Openurl, 1),
293 (CONST_APTR)AROS_SLIB_ENTRY(LibClose, Openurl, 2),
294 (CONST_APTR)AROS_SLIB_ENTRY(LibExpunge, Openurl, 3),
295 #else
296 (CONST_APTR)AROS_SLIB_ENTRY(LibOpen, Openurl),
297 (CONST_APTR)AROS_SLIB_ENTRY(LibClose, Openurl),
298 (CONST_APTR)AROS_SLIB_ENTRY(LibExpunge, Openurl),
299 #endif
300 #else
301 (CONST_APTR)LibOpen,
302 (CONST_APTR)LibClose,
303 (CONST_APTR)LibExpunge,
304 #endif
305 (CONST_APTR)LibNull,
306 (CONST_APTR)libvector,
307 (CONST_APTR)-1
310 STATIC CONST IPTR LibInitTab[] =
312 sizeof(struct LibraryHeader),
313 (IPTR)LibVectors,
314 (IPTR)NULL,
315 (IPTR)LibInit
318 #endif
320 /****************************************************************************/
322 static const USED_VAR struct Resident ROMTag =
324 RTC_MATCHWORD,
325 (struct Resident *)&ROMTag,
326 (struct Resident *)(&ROMTag + 1),
327 #if defined(__amigaos4__)
328 RTF_AUTOINIT|RTF_NATIVE, // The Library should be set up according to the given table.
329 #elif defined(__MORPHOS__)
330 RTF_AUTOINIT|RTF_EXTENDED|RTF_PPC,
331 #elif defined(__AROS__)
332 RTF_AUTOINIT|RTF_EXTENDED,
333 #else
334 RTF_AUTOINIT,
335 #endif
336 LIB_VERSION,
337 NT_LIBRARY,
339 (char *)UserLibName,
340 (char *)UserLibID+6, // +6 to skip '$VER: '
341 #if defined(__amigaos4__)
342 (APTR)libCreateTags // This table is for initializing the Library.
343 #else
344 (APTR)LibInitTab,
345 #endif
346 #if defined(__MORPHOS__) || defined(__AROS__)
347 LIB_REVISION,
349 #endif
352 #if defined(__MORPHOS__)
354 * To tell the loader that this is a new emulppc elf and not
355 * one for the ppc.library.
356 * ** IMPORTANT **
358 const USED_VAR ULONG __abox__ = 1;
360 #endif /* __MORPHOS */
362 /****************************************************************************/
364 #if defined(MIN_STACKSIZE) && !defined(__amigaos4__)
366 /* generic StackSwap() function which calls function() surrounded by
367 StackSwap() calls */
369 #if defined(__mc68000__)
370 ULONG stackswap_call(struct StackSwapStruct *stack,
371 ULONG (*function)(struct LibraryHeader *),
372 struct LibraryHeader *arg);
374 asm(".text \n\
375 .even \n\
376 .globl _stackswap_call \n\
377 _stackswap_call: \n\
378 moveml #0x3022,sp@- \n\
379 movel sp@(20),d3 \n\
380 movel sp@(24),a2 \n\
381 movel sp@(28),d2 \n\
382 movel _SysBase,a6 \n\
383 movel d3,a0 \n\
384 jsr a6@(-732:W) \n\
385 movel d2,sp@- \n\
386 jbsr a2@ \n\
387 movel d0,d2 \n\
388 addql #4,sp \n\
389 movel _SysBase,a6 \n\
390 movel d3,a0 \n\
391 jsr a6@(-732:W) \n\
392 movel d2,d0 \n\
393 moveml sp@+,#0x440c \n\
394 rts");
395 #elif defined(__MORPHOS__)
396 ULONG stackswap_call(struct StackSwapStruct *stack,
397 ULONG (*function)(struct LibraryHeader *),
398 struct LibraryHeader *arg)
400 struct PPCStackSwapArgs swapargs;
402 swapargs.Args[0] = (ULONG)arg;
404 return NewPPCStackSwap(stack, function, &swapargs);
406 #elif defined(__AROS__)
407 ULONG stackswap_call(struct StackSwapStruct *stack,
408 ULONG (*function)(struct LibraryHeader *),
409 struct LibraryHeader *arg)
411 struct StackSwapArgs swapargs;
413 swapargs.Args[0] = (IPTR)arg;
415 return NewStackSwap(stack, function, &swapargs);
417 #else
418 #error Bogus operating system
419 #endif
421 static BOOL callLibFunction(ULONG (*function)(struct LibraryHeader *), struct LibraryHeader *arg)
423 BOOL success = FALSE;
424 struct Task *tc;
425 ULONG stacksize;
427 // retrieve the task structure for the
428 // current task
429 tc = FindTask(NULL);
431 #if defined(__MORPHOS__)
432 // In MorphOS we have two stacks. One for PPC code and another for 68k code.
433 // We are only interested in the PPC stack.
434 NewGetTaskAttrsA(tc, &stacksize, sizeof(ULONG), TASKINFOTYPE_STACKSIZE, NULL);
435 #else
436 // on all other systems we query via SPUpper-SPLower calculation
437 stacksize = (UBYTE *)tc->tc_SPUpper - (UBYTE *)tc->tc_SPLower;
438 #endif
440 // Swap stacks only if current stack is insufficient
441 if(stacksize < MIN_STACKSIZE)
443 struct StackSwapStruct *stack;
445 if((stack = AllocVec(sizeof(*stack), MEMF_PUBLIC)) != NULL)
447 if((stack->stk_Lower = AllocVec(MIN_STACKSIZE, MEMF_PUBLIC)) != NULL)
449 // perform the StackSwap
450 #if defined(__AROS__)
451 // AROS uses an APTR type for stk_Upper
452 stack->stk_Upper = (APTR)((IPTR)stack->stk_Lower + MIN_STACKSIZE);
453 #else
454 // all other systems use ULONG
455 stack->stk_Upper = (ULONG)stack->stk_Lower + MIN_STACKSIZE;
456 #endif
457 stack->stk_Pointer = (APTR)stack->stk_Upper;
459 // call routine but with embedding it into a [NewPPC]StackSwap()
460 success = stackswap_call(stack, function, arg);
462 FreeVec(stack->stk_Lower);
464 FreeVec(stack);
467 else
468 success = function(arg);
470 return success;
472 #else // MIN_STACKSIZE && !__amigaos4__
473 #define callLibFunction(func, arg) func(arg)
474 #endif // MIN_STACKSIZE && !__amigaos4__
476 /****************************************************************************/
478 #if defined(__amigaos4__)
479 static struct LibraryHeader * LibInit(struct LibraryHeader *base, BPTR librarySegment, struct ExecIFace *pIExec)
481 struct ExecBase *sb = (struct ExecBase *)pIExec->Data.LibBase;
482 IExec = pIExec;
483 #elif defined(__MORPHOS__)
484 static struct LibraryHeader * LibInit(struct LibraryHeader *base, BPTR librarySegment, struct ExecBase *sb)
486 #elif defined(__AROS__)
487 static AROS_UFH3(struct LibraryHeader *, LibInit,
488 AROS_UFHA(struct LibraryHeader *, base, D0),
489 AROS_UFHA(BPTR, librarySegment, A0),
490 AROS_UFHA(struct ExecBase *, sb, A6)
493 AROS_USERFUNC_INIT
494 #else
495 static struct LibraryHeader * LIBFUNC LibInit(REG(d0, struct LibraryHeader *base), REG(a0, BPTR librarySegment), REG(a6, struct ExecBase *sb))
497 #endif
499 SysBase = (APTR)sb;
501 // make sure that this is really a 68020+ machine if optimized for 020+
502 #if _M68060 || _M68040 || _M68030 || _M68020 || __mc68020 || __mc68030 || __mc68040 || __mc68060
503 if(isFlagClear(SysBase->AttnFlags, AFF_68020))
504 return(NULL);
505 #endif
507 #if defined(__amigaos4__) && defined(__NEWLIB__)
508 if((NewlibBase = OpenLibrary("newlib.library", 3)) &&
509 GETINTERFACE(INewlib, NewlibBase))
510 #endif
512 BOOL success = FALSE;
514 D(DBF_STARTUP, "LibInit()");
516 // cleanup the library header structure beginning with the
517 // library base.
518 base->libBase.lib_Node.ln_Type = NT_LIBRARY;
519 base->libBase.lib_Node.ln_Pri = 0;
520 base->libBase.lib_Node.ln_Name = (char *)UserLibName;
521 base->libBase.lib_Flags = LIBF_CHANGED | LIBF_SUMUSED;
522 base->libBase.lib_Version = LIB_VERSION;
523 base->libBase.lib_Revision = LIB_REVISION;
524 base->libBase.lib_IdString = (char *)(UserLibID+6);
526 memset(&base->libSem, 0, sizeof(base->libSem));
527 InitSemaphore(&base->libSem);
528 memset(&base->poolSem, 0, sizeof(base->poolSem));
529 InitSemaphore(&base->poolSem);
530 memset(&base->prefsSem, 0, sizeof(base->prefsSem));
531 InitSemaphore(&base->prefsSem);
533 base->sysBase = (APTR)SysBase;
534 base->pool = NULL;
535 base->prefs = NULL;
536 base->flags = 0;
537 base->rexx_use = 0;
539 // protect access to initBase()
540 ObtainSemaphore(&base->libSem);
542 // set the OpenURLBase
543 OpenURLBase = base;
544 #if defined(__amigaos4__)
545 GETINTERFACE(IOpenURL, OpenURLBase);
546 #endif
548 // If we are not running on AmigaOS4 (no stackswap required) we go and
549 // do an explicit StackSwap() in case the user wants to make sure we
550 // have enough stack for his user functions
551 success = callLibFunction(initBase, base);
553 // unprotect initBase()
554 ReleaseSemaphore(&base->libSem);
556 // check if everything worked out fine
557 if(success == TRUE)
559 // everything was successfully so lets
560 // set the initialized value and contiue
561 // with the class open phase
562 base->segList = librarySegment;
564 // return the library base as success
565 return base;
567 else
569 callLibFunction(freeBase, base);
570 OpenURLBase = NULL;
571 DROPINTERFACE(IOpenURL);
574 #if defined(__amigaos4__) && defined(__NEWLIB__)
575 if(NewlibBase)
577 DROPINTERFACE(INewlib);
578 CloseLibrary(NewlibBase);
579 NewlibBase = NULL;
581 #endif
584 return(NULL);
585 #ifdef __AROS__
586 AROS_USERFUNC_EXIT
587 #endif
590 /****************************************************************************/
592 #ifndef __amigaos4__
593 #define DeleteLibrary(LIB) \
594 FreeMem((STRPTR)(LIB)-(LIB)->lib_NegSize, (ULONG)((LIB)->lib_NegSize+(LIB)->lib_PosSize))
595 #endif
597 STATIC BPTR LibDelete(struct LibraryHeader *base)
599 #if defined(__amigaos4__)
600 struct ExecIFace *IExec = (struct ExecIFace *)(*(struct ExecBase **)4)->MainInterface;
601 #endif
602 BPTR rc;
604 // make sure to restore the SysBase
605 SysBase = (APTR)base->sysBase;
607 // remove the library base from exec's lib list in advance
608 Remove((struct Node *)base);
610 // free all our private data and stuff.
611 ObtainSemaphore(&base->libSem);
613 // make sure we have enough stack here
614 callLibFunction(freeBase, base);
616 // unprotect
617 ReleaseSemaphore(&base->libSem);
619 #if defined(__amigaos4__)
620 DROPINTERFACE(IOpenURL);
621 IOpenURL = NULL;
622 #endif
623 OpenURLBase = NULL;
625 #if defined(__amigaos4__) && defined(__NEWLIB__)
626 if(NewlibBase)
628 DROPINTERFACE(INewlib);
629 CloseLibrary(NewlibBase);
630 NewlibBase = NULL;
632 #endif
634 // make sure the system deletes the library as well.
635 rc = base->segList;
636 DeleteLibrary(&base->libBase);
638 return rc;
641 #if defined(__amigaos4__)
642 static BPTR LibExpunge(struct LibraryManagerInterface *Self)
644 struct LibraryHeader *base = (struct LibraryHeader *)Self->Data.LibBase;
645 #elif defined(__MORPHOS__)
646 static BPTR LibExpunge(void)
648 struct LibraryHeader *base = (struct LibraryHeader*)REG_A6;
649 #elif defined(__AROS__)
650 static AROS_LH1(BPTR, LibExpunge,
651 AROS_LHA(UNUSED struct LibraryHeader *, __extrabase, D0),
652 struct LibraryHeader *, base, 3, Openurl
655 AROS_LIBFUNC_INIT
656 #else
657 static BPTR LIBFUNC LibExpunge(REG(a6, struct LibraryHeader *base))
659 #endif
660 BPTR rc;
662 D(DBF_STARTUP, "LibExpunge(): %ld", base->libBase.lib_OpenCnt);
664 // in case our open counter is still > 0, we have
665 // to set the late expunge flag and return immediately
666 if(base->libBase.lib_OpenCnt > 0)
668 SET_FLAG(base->libBase.lib_Flags, LIBF_DELEXP);
669 rc = 0;
671 else
673 rc = LibDelete(base);
676 return rc;
677 #ifdef __AROS__
678 AROS_LIBFUNC_EXIT
679 #endif
682 /****************************************************************************/
684 #if defined(__amigaos4__)
685 static struct LibraryHeader *LibOpen(struct LibraryManagerInterface *Self, ULONG version UNUSED)
687 struct LibraryHeader *base = (struct LibraryHeader *)Self->Data.LibBase;
688 #elif defined(__MORPHOS__)
689 static struct LibraryHeader *LibOpen(void)
691 struct LibraryHeader *base = (struct LibraryHeader*)REG_A6;
692 #elif defined(__AROS__)
693 static AROS_LH1(struct LibraryHeader *, LibOpen,
694 AROS_LHA(UNUSED ULONG, version, D0),
695 struct LibraryHeader *, base, 1, Openurl
698 AROS_LIBFUNC_INIT
699 #else
700 static struct LibraryHeader * LIBFUNC LibOpen(REG(d0, UNUSED ULONG version), REG(a6, struct LibraryHeader *base))
702 #endif
703 struct LibraryHeader *res = base;
705 D(DBF_STARTUP, "LibOpen(): %ld", base->libBase.lib_OpenCnt);
707 // LibOpen(), LibClose() and LibExpunge() are called while the system is in
708 // Forbid() state. That means that these functions should be quick and should
709 // not break this Forbid()!! Therefore the open counter should be increased
710 // as the very first instruction during LibOpen(), because a ClassOpen()
711 // which breaks a Forbid() and another task calling LibExpunge() will cause
712 // to expunge this library while it is not yet fully initialized. A crash
713 // is unavoidable then. Even the semaphore does not guarantee 100% protection
714 // against such a race condition, because waiting for the semaphore to be
715 // obtained will effectively break the Forbid()!
717 // increase the open counter ahead of anything else
718 base->libBase.lib_OpenCnt++;
720 // delete the late expunge flag
721 CLEAR_FLAG(base->libBase.lib_Flags, LIBF_DELEXP);
723 return res;
724 #ifdef __AROS__
725 AROS_LIBFUNC_EXIT
726 #endif
729 /****************************************************************************/
731 #if defined(__amigaos4__)
732 static BPTR LibClose(struct LibraryManagerInterface *Self)
734 struct LibraryHeader *base = (struct LibraryHeader *)Self->Data.LibBase;
735 #elif defined(__MORPHOS__)
736 static BPTR LibClose(void)
738 struct LibraryHeader *base = (struct LibraryHeader *)REG_A6;
739 #elif defined(__AROS__)
740 static AROS_LH0(BPTR, LibClose,
741 struct LibraryHeader *, base, 2, Openurl
744 AROS_LIBFUNC_INIT
745 #else
746 static BPTR LIBFUNC LibClose(REG(a6, struct LibraryHeader *base))
748 #endif
749 BPTR rc = 0;
751 D(DBF_STARTUP, "LibClose(): %ld", base->libBase.lib_OpenCnt);
753 // decrease the open counter
754 base->libBase.lib_OpenCnt--;
756 // in case the opern counter is <= 0 we can
757 // make sure that we free everything
758 if(base->libBase.lib_OpenCnt <= 0)
760 // in case the late expunge flag is set we go and
761 // expunge the library base right now
762 if(isFlagSet(base->libBase.lib_Flags, LIBF_DELEXP))
764 rc = LibDelete(base);
768 return rc;
769 #ifdef __AROS__
770 AROS_LIBFUNC_EXIT
771 #endif
774 /****************************************************************************/