14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* Support for dynamic loading of extension modules */
34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include <kernel/image.h>
54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include <kernel/OS.h>
64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include <stdlib.h>
74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "Python.h"
94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "importdl.h"
104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmconst struct filedescr _PyImport_DynLoadFiletab[] = {
124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {".so", "rb", C_EXTENSION},
134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"module.so", "rb", C_EXTENSION},
144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {0, 0}
154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#if defined(MAXPATHLEN) && !defined(_SYS_PARAM_H)
184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#undef MAXPATHLEN
194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif
204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef WITH_THREAD
224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "pythread.h"
234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyThread_type_lock beos_dyn_lock;
244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif
254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *beos_dyn_images = NULL;
274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* ----------------------------------------------------------------------
294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * BeOS dynamic loading support
304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm *
314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * This uses shared libraries, but BeOS has its own way of doing things
324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * (much easier than dlfnc.h, from the look of things).  We'll use a
334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * Python Dictionary object to store the images_ids so we can be very
344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * nice and unload them when we exit.
354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm *
364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * Note that this is thread-safe.  Probably irrelevent, because of losing
374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * systems... Python probably disables threads while loading modules.
384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * Note the use of "probably"!  Better to be safe than sorry. [chrish]
394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm *
404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * As of 1.5.1 this should also work properly when you've configured
414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * Python without thread support; the 1.5 version required it, which wasn't
424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * very friendly.  Note that I haven't tested it without threading... why
434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * would you want to avoid threads on BeOS? [chrish]
444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm *
454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * As of 1.5.2, the PyImport_BeImageID() function has been removed; Donn
464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * tells me it's not necessary anymore because of PyCObject_Import().
474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * [chrish]
484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */
494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* Whack an item; the item is an image_id in disguise, so we'll call
514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * unload_add_on() for it.
524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */
534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void beos_nuke_dyn( PyObject *item )
544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    status_t retval;
564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if( item ) {
584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        image_id id = (image_id)PyInt_AsLong( item );
594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        retval = unload_add_on( id );
614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* atexit() handler that'll call unload_add_on() for every item in the
654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * dictionary.
664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */
674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void beos_cleanup_dyn( void )
684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if( beos_dyn_images ) {
704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        int idx;
714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        int list_size;
724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *id_list;
734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef WITH_THREAD
754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyThread_acquire_lock( beos_dyn_lock, 1 );
764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif
774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        id_list = PyDict_Values( beos_dyn_images );
794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        list_size = PyList_Size( id_list );
814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for( idx = 0; idx < list_size; idx++ ) {
824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyObject *the_item;
834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            the_item = PyList_GetItem( id_list, idx );
854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            beos_nuke_dyn( the_item );
864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyDict_Clear( beos_dyn_images );
894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef WITH_THREAD
914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyThread_free_lock( beos_dyn_lock );
924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif
934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/*
974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * Initialize our dictionary, and the dictionary mutex.
984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */
994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void beos_init_dyn( void )
1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* We're protected from a race condition here by the atomic init_count
1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * variable.
1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     */
1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    static int32 init_count = 0;
1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int32 val;
1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    val = atomic_add( &init_count, 1 );
1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if( beos_dyn_images == NULL && val == 0 ) {
1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        beos_dyn_images = PyDict_New();
1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef WITH_THREAD
1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        beos_dyn_lock = PyThread_allocate_lock();
1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif
1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        atexit( beos_cleanup_dyn );
1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/*
1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * Add an image_id to the dictionary; the module name of the loaded image
1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * is the key.  Note that if the key is already in the dict, we unload
1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * that image; this should allow reload() to work on dynamically loaded
1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * modules (super-keen!).
1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */
1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void beos_add_dyn( char *name, image_id id )
1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int retval;
1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *py_id;
1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if( beos_dyn_images == NULL ) {
1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        beos_init_dyn();
1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef WITH_THREAD
1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    retval = PyThread_acquire_lock( beos_dyn_lock, 1 );
1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif
1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* If there's already an object with this key in the dictionary,
1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * we're doing a reload(), so let's nuke it.
1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     */
1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    py_id = PyDict_GetItemString( beos_dyn_images, name );
1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if( py_id ) {
1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        beos_nuke_dyn( py_id );
1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        retval = PyDict_DelItemString( beos_dyn_images, name );
1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    py_id = PyInt_FromLong( (long)id );
1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if( py_id ) {
1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        retval = PyDict_SetItemString( beos_dyn_images, name, py_id );
1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef WITH_THREAD
1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyThread_release_lock( beos_dyn_lock );
1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif
1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                    const char *pathname, FILE *fp)
1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    dl_funcptr p;
1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    image_id the_id;
1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    status_t retval;
1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char fullpath[PATH_MAX];
1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char funcname[258];
1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if( Py_VerboseFlag ) {
1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        printf( "load_add_on( %s )\n", pathname );
1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* Hmm, this old bug appears to have regenerated itself; if the
1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * path isn't absolute, load_add_on() will fail.  Reported to Be
1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * April 21, 1998.
1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     */
1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if( pathname[0] != '/' ) {
1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        (void)getcwd( fullpath, PATH_MAX );
1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        (void)strncat( fullpath, "/", PATH_MAX );
1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        (void)strncat( fullpath, pathname, PATH_MAX );
1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if( Py_VerboseFlag ) {
1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            printf( "load_add_on( %s )\n", fullpath );
1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    } else {
1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        (void)strcpy( fullpath, pathname );
1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    the_id = load_add_on( fullpath );
1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if( the_id < B_NO_ERROR ) {
1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* It's too bad load_add_on() doesn't set errno or something...
1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm         */
1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        char buff[256];  /* hate hard-coded string sizes... */
1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if( Py_VerboseFlag ) {
1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            printf( "load_add_on( %s ) failed", fullpath );
1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if( the_id == B_ERROR )
1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyOS_snprintf( buff, sizeof(buff),
1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                           "BeOS: Failed to load %.200s",
1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                           fullpath );
2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else
2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyOS_snprintf( buff, sizeof(buff),
2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                           "Unknown error loading %.200s",
2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                           fullpath );
2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString( PyExc_ImportError, buff );
2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyOS_snprintf(funcname, sizeof(funcname), "init%.200s", shortname);
2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if( Py_VerboseFlag ) {
2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        printf( "get_image_symbol( %s )\n", funcname );
2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    retval = get_image_symbol( the_id, funcname, B_SYMBOL_TYPE_TEXT, &p );
2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if( retval != B_NO_ERROR || p == NULL ) {
2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* That's bad, we can't find that symbol in the module...
2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm         */
2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        char buff[256];  /* hate hard-coded string sizes... */
2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if( Py_VerboseFlag ) {
2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            printf( "get_image_symbol( %s ) failed", funcname );
2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        switch( retval ) {
2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        case B_BAD_IMAGE_ID:
2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyOS_snprintf( buff, sizeof(buff),
2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                   "can't load init function for dynamic module: "
2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                   "Invalid image ID for %.180s", fullpath );
2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            break;
2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        case B_BAD_INDEX:
2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyOS_snprintf( buff, sizeof(buff),
2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                   "can't load init function for dynamic module: "
2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                   "Bad index for %.180s", funcname );
2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            break;
2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        default:
2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyOS_snprintf( buff, sizeof(buff),
2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                   "can't load init function for dynamic module: "
2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                   "Unknown error looking up %.180s", funcname );
2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            break;
2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        retval = unload_add_on( the_id );
2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString( PyExc_ImportError, buff );
2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* Save the module name and image ID for later so we can clean up
2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * gracefully.
2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     */
2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    beos_add_dyn( fqname, the_id );
2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return p;
2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
255