]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
* Python/import.c: support *.o/*.so as alternative for
authorGuido van Rossum <guido@python.org>
Mon, 29 Aug 1994 12:54:38 +0000 (12:54 +0000)
committerGuido van Rossum <guido@python.org>
Mon, 29 Aug 1994 12:54:38 +0000 (12:54 +0000)
        *module.o/*module.so

        * Python/import.c: if initializing a module did not enter the
        module into sys.modules, it may have raised an exception -- don't
        override this exception.

Merged NT changes

        * Python/import.c: add lost NT-specific code back in

Fixed NT changes

Python/import.c

index a8cfe5b5ea88976e6bf0de210674557b626d3fa3..980ccd23b5eec470cb5016fea78e94c0607eeccd 100644 (file)
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
 Amsterdam, The Netherlands.
 
                         All Rights Reserved
@@ -38,9 +38,9 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #include "eval.h"
 #include "osdefs.h"
 
-extern int verbose; /* Defined in pythonmain.c */
+extern int verbose; /* Defined in pythonrun.c */
 
-extern long getmtime(); /* Defined in posixmodule.c */
+extern long getmtime(); /* In getmtime.c */
 
 #ifdef DEBUG
 #define D(x) x
@@ -48,20 +48,114 @@ extern long getmtime(); /* Defined in posixmodule.c */
 #define D(x)
 #endif
 
-#ifdef USE_DL
-#ifdef SUN_SHLIB
+/* Explanation of some of the the various #defines used by dynamic linking...
+
+   symbol      -- defined for:
+
+   DYNAMIC_LINK -- any kind of dynamic linking
+   USE_RLD     -- NeXT dynamic linking
+   USE_DL      -- Jack's dl for IRIX 4 or GNU dld with emulation for Jack's dl
+   USE_SHLIB   -- SunOS or IRIX 5 (SVR4?) shared libraries
+   _AIX                -- AIX style dynamic linking
+   NT          -- NT style dynamic linking (using DLLs)
+   _DL_FUNCPTR_DEFINED -- if the typedef dl_funcptr has been defined
+   WITH_MAC_DL -- Mac dynamic linking (highly experimental)
+   SHORT_EXT   -- short extension for dynamic module, e.g. ".so"
+   LONG_EXT    -- long extension, e.g. "module.so"
+
+   (The other WITH_* symbols are used only once, to set the
+   appropriate symbols.)
+*/
+
+/* Configure dynamic linking */
+
+#ifdef NT
+#define DYNAMIC_LINK
+#include <windows.h>
+typedef FARPROC dl_funcptr;
+#define _DL_FUNCPTR_DEFINED
+#define SHORT_EXT ".dll"
+#define LONG_EXT "module.dll"
+#endif
+
+#if defined(NeXT) || defined(WITH_RLD)
+#define DYNAMIC_LINK
+#define USE_RLD
+#endif
+
+#ifdef WITH_SGI_DL
+#define DYNAMIC_LINK
+#define USE_DL
+#endif
+
+#ifdef WITH_DL_DLD
+#define DYNAMIC_LINK
+#define USE_DL
+#endif
+
+#ifdef WITH_MAC_DL
+#define DYNAMIC_LINK
+#endif
+
+#if !defined(DYNAMIC_LINK) && defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
+#define DYNAMIC_LINK
+#define USE_SHLIB
+#endif
+
+#ifdef _AIX
+#define DYNAMIC_LINK
+#include <sys/ldr.h>
+typedef void (*dl_funcptr)();
+#define _DL_FUNCPTR_DEFINED
+static void aix_loaderror(char *name);
+#endif
+
+#ifdef DYNAMIC_LINK
+
+#ifdef USE_SHLIB
 #include <dlfcn.h>
+#ifndef _DL_FUNCPTR_DEFINED
 typedef void (*dl_funcptr)();
-#else
+#endif
+#ifndef RTLD_LAZY
+#define RTLD_LAZY 1
+#endif
+#define SHORT_EXT ".so"
+#define LONG_EXT "module.so"
+#endif /* USE_SHLIB */
+
+#ifdef USE_DL
 #include "dl.h"
-#endif /* SUN_SHLIB */
+#endif
 
-extern char *argv0;
+#ifdef WITH_MAC_DL
+#include "dynamic_load.h"
 #endif
 
+#ifdef USE_RLD
+#include <mach-o/rld.h>
+#define FUNCNAME_PATTERN "_init%s"
+#ifndef _DL_FUNCPTR_DEFINED
+typedef void (*dl_funcptr)();
+#endif
+#endif /* USE_RLD */
+
+extern char *getprogramname();
+
+#ifndef FUNCNAME_PATTERN
+#define FUNCNAME_PATTERN "init%s"
+#endif
+
+#if !defined(SHORT_EXT) && !defined(LONG_EXT)
+#define SHORT_EXT ".o"
+#define LONG_EXT "module.o"
+#endif /* !SHORT_EXT && !LONG_EXT */
+
+#endif /* DYNAMIC_LINK */
+
 /* Magic word to reject .pyc files generated by other Python versions */
 
-#define MAGIC 0x999902L /* Increment by one for each incompatible change */
+#define MAGIC 0x999903L /* Increment by one for each incompatible change */
 
 static object *modules;
 
@@ -108,18 +202,145 @@ static struct filedescr {
        char *mode;
        enum filetype type;
 } filetab[] = {
-#ifdef USE_DL
-#ifdef SUN_SHLIB
-       {"module.so", "rb", C_EXTENSION},
-#else
-       {"module.o", "rb", C_EXTENSION},
-#endif /* SUN_SHLIB */
-#endif /* USE_DL */
+#ifdef DYNAMIC_LINK
+#ifdef SHORT_EXT
+       {SHORT_EXT, "rb", C_EXTENSION},
+#endif /* !SHORT_EXT */
+#ifdef LONG_EXT
+       {LONG_EXT, "rb", C_EXTENSION},
+#endif /* !LONG_EXT */
+#endif /* DYNAMIC_LINK */
        {".py", "r", PY_SOURCE},
        {".pyc", "rb", PY_COMPILED},
        {0, 0}
 };
 
+#ifdef DYNAMIC_LINK
+static object *
+load_dynamic_module(name, namebuf, m, m_ret)
+       char *name;
+       char *namebuf;
+       object *m;
+       object **m_ret;
+{
+       char funcname[258];
+       dl_funcptr p = NULL;
+       if (m != NULL) {
+               err_setstr(ImportError,
+                          "cannot reload dynamically loaded module");
+               return NULL;
+       }
+       sprintf(funcname, FUNCNAME_PATTERN, name);
+#ifdef WITH_MAC_DL
+       {
+               object *v = dynamic_load(namebuf);
+               if (v == NULL)
+                       return NULL;
+       }
+#else /* !WITH_MAC_DL */
+#ifdef USE_SHLIB
+       {
+#ifdef RTLD_NOW
+               /* RTLD_NOW: resolve externals now
+                  (i.e. core dump now if some are missing) */
+               void *handle = dlopen(namebuf, RTLD_NOW);
+#else
+               void *handle;
+               if (verbose)
+                       printf("dlopen(\"%s\", %d);\n", namebuf, RTLD_LAZY);
+               handle = dlopen(namebuf, RTLD_LAZY);
+#endif /* RTLD_NOW */
+               if (handle == NULL) {
+                       err_setstr(ImportError, dlerror());
+                       return NULL;
+               }
+               p = (dl_funcptr) dlsym(handle, funcname);
+       }
+#endif /* USE_SHLIB */
+#ifdef _AIX
+       p = (dl_funcptr) load(namebuf, 1, 0);
+       if (p == NULL) {
+               aix_loaderror(namebuf);
+               return NULL;
+       }
+#endif /* _AIX */
+#ifdef NT
+       {
+               HINSTANCE hDLL;
+               hDLL = LoadLibrary(namebuf);
+               if (hDLL==NULL){
+                       char errBuf[64];
+                       sprintf(errBuf, "DLL load failed with error code %d",
+                               GetLastError());
+                       err_setstr(ImportError, errBuf);
+               return NULL;
+               }
+               p = GetProcAddress(hDLL, funcname);
+       }
+#endif /* NT */
+#ifdef USE_DL
+       p =  dl_loadmod(getprogramname(), namebuf, funcname);
+#endif /* USE_DL */
+#ifdef USE_RLD
+       {
+               NXStream *errorStream;
+               struct mach_header *new_header;
+               const char *filenames[2];
+               long ret;
+               unsigned long ptr;
+
+               errorStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
+               filenames[0] = namebuf;
+               filenames[1] = NULL;
+               ret = rld_load(errorStream, &new_header, 
+                               filenames, NULL);
+
+               /* extract the error messages for the exception */
+               if(!ret) {
+                       char *streamBuf;
+                       int len, maxLen;
+
+                       NXPutc(errorStream, (char)0);
+
+                       NXGetMemoryBuffer(errorStream,
+                               &streamBuf, &len, &maxLen);
+                       err_setstr(ImportError, streamBuf);
+               }
+
+               if(ret && rld_lookup(errorStream, funcname, &ptr))
+                       p = (dl_funcptr) ptr;
+
+               NXCloseMemory(errorStream, NX_FREEBUFFER);
+
+               if(!ret)
+                       return NULL;
+       }
+#endif /* USE_RLD */
+
+       if (p == NULL) {
+               err_setstr(ImportError,
+                  "dynamic module does not define init function");
+               return NULL;
+       }
+       (*p)();
+
+#endif /* !WITH_MAC_DL */
+       *m_ret = m = dictlookup(modules, name);
+       if (m == NULL) {
+               if (err_occurred() == NULL)
+                       err_setstr(SystemError,
+                                  "dynamic module not initialized properly");
+               return NULL;
+       }
+       if (verbose)
+               fprintf(stderr,
+                       "import %s # dynamically loaded from %s\n",
+                       name, namebuf);
+       INCREF(None);
+       return None;
+}
+#endif /* DYNAMIC_LINK */
+
 static object *
 get_module(m, name, m_ret)
        /*module*/object *m;
@@ -182,35 +403,34 @@ get_module(m, name, m_ret)
                        if (magic != MAGIC) {
                                if (verbose)
                                        fprintf(stderr,
-                                               "# %s.pyc has bad magic\n",
-                                               name);
+                                               "# %s has bad magic\n",
+                                               namebuf);
                        }
                        else {
                                pyc_mtime = rd_long(fpc);
                                if (pyc_mtime != mtime) {
                                        if (verbose)
                                                fprintf(stderr,
-                                                 "# %s.pyc has bad mtime\n",
-                                                 name);
+                                                 "# %s has bad mtime\n",
+                                                 namebuf);
                                }
                                else {
                                        fclose(fp);
                                        fp = fpc;
                                        if (verbose)
                                           fprintf(stderr,
-                                            "# %s.pyc matches %s.py\n",
-                                                  name, name);
+                                            "# %s matches %s.py\n",
+                                                  namebuf, name);
                                        goto use_compiled;
                                }
                        }
                        fclose(fpc);
                }
                namebuf[len] = '\0';
-               err = parse_file(fp, namebuf, file_input, &n);
-               if (err != E_DONE) {
-                       err_input(err);
+               n = parse_file(fp, namebuf, file_input);
+               fclose(fp);
+               if (n == NULL)
                        return NULL;
-               }
                co = compile(n, namebuf);
                freetree(n);
                if (co == NULL)
@@ -254,8 +474,8 @@ get_module(m, name, m_ret)
 
        case PY_COMPILED:
                if (verbose)
-                       fprintf(stderr, "# %s.pyc without %s.py\n",
-                               name, name);
+                       fprintf(stderr, "# %s without %s.py\n",
+                               namebuf, name);
                magic = rd_long(fp);
                if (magic != MAGIC) {
                        err_setstr(ImportError,
@@ -279,44 +499,11 @@ get_module(m, name, m_ret)
                                name, namebuf);
                break;
 
-#ifdef USE_DL
+#ifdef DYNAMIC_LINK
        case C_EXTENSION:
-             {
-               char funcname[258];
-               dl_funcptr p;
                fclose(fp);
-               sprintf(funcname, "init%s", name);
-#ifdef SUN_SHLIB
-               {
-                 void *handle = dlopen (namebuf, 1);
-                 p = (dl_funcptr) dlsym(handle, funcname);
-               }
-#else
-               p =  dl_loadmod(argv0, namebuf, funcname);
-#endif /* SUN_SHLIB */
-               if (p == NULL) {
-                       err_setstr(ImportError,
-                          "dynamic module does not define init function");
-                       return NULL;
-               } else {
-                       (*p)();
-                       *m_ret = m = dictlookup(modules, name);
-                       if (m == NULL) {
-                               err_setstr(SystemError,
-                                  "dynamic module not initialized properly");
-                               return NULL;
-                       } else {
-                               if (verbose)
-                                       fprintf(stderr,
-                               "import %s # dynamically loaded from %s\n",
-                                               name, namebuf);
-                               INCREF(None);
-                               return None;
-                       }
-               }
-               break;
-             }
-#endif /* USE_DL */
+               return load_dynamic_module(name, namebuf, m, m_ret);
+#endif /* DYNAMIC_LINK */
 
        default:
                fclose(fp);
@@ -363,9 +550,11 @@ import_module(name)
                if ((n = init_builtin(name)) || (n = init_frozen(name))) {
                        if (n < 0)
                                return NULL;
-                       if ((m = dictlookup(modules, name)) == NULL)
-                               err_setstr(SystemError,
-                                          "builtin module missing");
+                       if ((m = dictlookup(modules, name)) == NULL) {
+                               if (err_occurred() == NULL)
+                                       err_setstr(SystemError,
+                                  "builtin module not initialized properly");
+                       }
                }
                else {
                        m = load_module(name);
@@ -379,6 +568,7 @@ reload_module(m)
        object *m;
 {
        char *name;
+       int i;
        if (m == NULL || !is_moduleobject(m)) {
                err_setstr(TypeError, "reload() argument must be module");
                return NULL;
@@ -386,7 +576,21 @@ reload_module(m)
        name = getmodulename(m);
        if (name == NULL)
                return NULL;
-       /* XXX Ought to check for builtin modules -- can't reload these... */
+       /* Check for built-in modules */
+       for (i = 0; inittab[i].name != NULL; i++) {
+               if (strcmp(name, inittab[i].name) == 0) {
+                       err_setstr(ImportError,
+                                  "cannot reload built-in module");
+                       return NULL;
+               }
+       }
+       /* Check for frozen modules */
+       if ((i = init_frozen(name)) != 0) {
+               if (i < 0)
+                       return NULL;
+               INCREF(None);
+               return None;
+       }
        return get_module(m, name, (object **)NULL);
 }
 
@@ -423,6 +627,11 @@ init_builtin(name)
        int i;
        for (i = 0; inittab[i].name != NULL; i++) {
                if (strcmp(name, inittab[i].name) == 0) {
+                       if (inittab[i].initfunc == NULL) {
+                               err_setstr(ImportError,
+                                          "cannot re-init internal module");
+                               return -1;
+                       }
                        if (verbose)
                                fprintf(stderr, "import %s # builtin\n",
                                        name);
@@ -467,3 +676,58 @@ init_frozen(name)
        DECREF(v);
        return 1;
 }
+
+
+#ifdef _AIX
+
+#include <ctype.h>     /* for isdigit()        */
+#include <errno.h>     /* for global errno     */
+#include <string.h>    /* for strerror()       */
+
+void aix_loaderror(char *namebuf)
+{
+
+       char *message[8], errbuf[1024];
+       int i,j;
+
+       struct errtab { 
+               int errno;
+               char *errstr;
+       } load_errtab[] = {
+               {L_ERROR_TOOMANY,       "to many errors, rest skipped."},
+               {L_ERROR_NOLIB,         "can't load library:"},
+               {L_ERROR_UNDEF,         "can't find symbol in library:"},
+               {L_ERROR_RLDBAD,
+                "RLD index out of range or bad relocation type:"},
+               {L_ERROR_FORMAT,        "not a valid, executable xcoff file:"},
+               {L_ERROR_MEMBER,
+                "file not an archive or does not contain requested member:"},
+               {L_ERROR_TYPE,          "symbol table mismatch:"},
+               {L_ERROR_ALIGN,         "text allignment in file is wrong."},
+               {L_ERROR_SYSTEM,        "System error:"},
+               {L_ERROR_ERRNO,         NULL}
+       };
+
+#define LOAD_ERRTAB_LEN        (sizeof(load_errtab)/sizeof(load_errtab[0]))
+#define ERRBUF_APPEND(s)       strncat(errbuf, s, sizeof(errbuf))
+
+       sprintf(errbuf, " from module %s ", namebuf);
+
+       if (!loadquery(1, &message[0], sizeof(message))) 
+               ERRBUF_APPEND(strerror(errno));
+       for(i = 0; message[i] && *message[i]; i++) {
+               int nerr = atoi(message[i]);
+               for (j=0; j<LOAD_ERRTAB_LEN ; j++) {
+                   if (nerr == load_errtab[i].errno && load_errtab[i].errstr)
+                       ERRBUF_APPEND(load_errtab[i].errstr);
+               }
+               while (isdigit(*message[i])) message[i]++ ; 
+               ERRBUF_APPEND(message[i]);
+               ERRBUF_APPEND("\n");
+       }
+       errbuf[strlen(errbuf)-1] = '\0' ;       /* trim off last newline */
+       err_setstr(ImportError, errbuf); 
+       return; 
+}
+
+#endif /* _AIX */