// Tolerant replacement for libnix's __initlibraries / __exitlibraries.
//
// libnix's version treats any OpenLibrary failure as fatal: it walks the
// auto-open list, and if any entry cannot be opened, it writes
// "<name> failed to load" to the CLI and exits(20) before main() runs.
//
// That behavior kills the examples on AROS, which does not provide
// locale.library as a disk library. libnix unconditionally pulls the
// locale.library entry into the auto-open list because C runtime
// utilities (e.g. tzset via time()) take LocaleBase as an argument to
// ConvToLower -- even when the runtime does not actually need a real
// Locale to run.
//
// Our replacement walks the same list but records NULL for any
// library that cannot be opened, then continues. Code that actually
// needs the library will crash when it dereferences the NULL base,
// but none of the joeylib examples do. Since these symbols are
// defined here in a user object, the linker satisfies references
// from this file instead of pulling in libnix's version.

#include <proto/exec.h>
#include <stabs.h>

extern long __LIB_LIST__;


static int endsWithResource(const char *name) {
    const char *p = name;
    while (*p) {
        p++;
    }
    p -= 9;
    if (p < name) {
        return 0;
    }
    return p[0] == '.' && p[1] == 'r' && p[2] == 'e' && p[3] == 's' &&
           p[4] == 'o' && p[5] == 'u' && p[6] == 'r' && p[7] == 'c' &&
           p[8] == 'e';
}


void __initlibraries(void) {
    long *entry = &__LIB_LIST__ + 1;
    while (*entry) {
        long       *base = entry++;
        const char *name = *(const char **)entry++;
        long        lib;

        if (endsWithResource(name)) {
            lib = (long)OpenResource((STRPTR)name);
        } else {
            lib = (long)OldOpenLibrary((STRPTR)name);
        }
        *base = lib;
    }
}


void __exitlibraries(void) {
    long *entry = &__LIB_LIST__ + 1;
    while (*entry) {
        long       *base = entry++;
        const char *name = *(const char **)entry++;
        if (*base != 0 && *base != -1 && !endsWithResource(name)) {
            CloseLibrary((struct Library *)*base);
        }
    }
}


ADD2INIT(__initlibraries, -79);
ADD2EXIT(__exitlibraries, -79);


// libnix's tzset dereferences LocaleBase to call locale.library's
// ConvToLower. On AROS (where locale.library is unavailable), our
// tolerant __initlibraries leaves LocaleBase NULL, which would crash
// the first time time() is called (via tzset). Our pattern example
// uses time() for the 5-second display; override tzset with a no-op
// so time() can run. Difference-based timing is unaffected because
// any DST correction applied consistently cancels out.
void tzset(void) {
}
