]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Lots of changes, most minor (fatal() instead of abort(), use of
authorGuido van Rossum <guido@python.org>
Mon, 2 Jan 1995 19:04:15 +0000 (19:04 +0000)
committerGuido van Rossum <guido@python.org>
Mon, 2 Jan 1995 19:04:15 +0000 (19:04 +0000)
err_fetch/err_restore and so on).  But...
NOTE: import.c has been rewritten and all the DL stuff is now in the
new file importdl.c.

15 files changed:
Python/Makefile.in
Python/bltinmodule.c
Python/ceval.c
Python/compile.c
Python/errors.c
Python/getargs.c
Python/import.c
Python/importdl.c [new file with mode: 0644]
Python/importdl.h [new file with mode: 0644]
Python/marshal.c
Python/modsupport.c
Python/pythonrun.c
Python/sysmodule.c
Python/thread_solaris.h
Python/traceback.c

index 54be6af0458b46d13d6977bcee58e3abd5ba3b3e..d5ced26c662ef228bcdbae8395258af2b4b0265c 100644 (file)
@@ -35,7 +35,7 @@ OBJS=         \
                errors.o \
                frozenmain.o \
                getargs.o getmtime.o graminit.o \
-               import.o \
+               import.o importdl.o \
                marshal.o modsupport.o mystrtoul.o \
                pythonmain.o pythonrun.o \
                sigcheck.o structmember.o sysmodule.o \
@@ -66,8 +66,8 @@ Makefile:     $(srcdir)/Makefile.in ../config.status
                (cd ..; CONFIG_FILES=Python/Makefile CONFIG_HEADERS= \
                $(SHELL) config.status)
 
-import.o:      import.c
-               $(CC) $(CFLAGS) -I$(DLINCLDIR) -c $(srcdir)/import.c
+importdl.o:    importdl.c
+               $(CC) $(CFLAGS) -I$(DLINCLDIR) -c $(srcdir)/importdl.c
 
 depend:
                $(MKDEP) $(CFLAGS) `echo $(OBJS) | tr ' ' '\012' | \
@@ -88,6 +88,7 @@ getcwd.o: getcwd.c
 getmtime.o: getmtime.c
 graminit.o: graminit.c
 import.o: import.c
+importdl.o: importdl.c
 marshal.o: marshal.c
 memmove.o: memmove.c
 modsupport.o: modsupport.c
index 4f6c8524eced470fc4f5ea7f9e5b524e67e5fa10..39dcc411b2ff8fae67849655f9c1684089ae3017 100644 (file)
@@ -40,15 +40,35 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 /* Forward */
 static object *filterstring PROTO((object *, object *));
 static object *filtertuple  PROTO((object *, object *));
-static object *exec_eval PROTO((object *v, int start));
 
 static object *
-builtin_abs(self, v)
+builtin___import__(self, args)
        object *self;
-       object *v;
+       object *args;
 {
+       char *name;
+       object *m;
+
+       if (!newgetargs(args, "s:__import__", &name))
+               return NULL;
+       m = import_module(name);
+       XINCREF(m);
+
+       return m;
+}
+
+
+static object *
+builtin_abs(self, args)
+       object *self;
+       object *args;
+{
+       object *v;
        number_methods *nm;
-       if (v == NULL || (nm = v->ob_type->tp_as_number) == NULL) {
+
+       if (!newgetargs(args, "O:abs", &v))
+               return NULL;
+       if ((nm = v->ob_type->tp_as_number) == NULL) {
                err_setstr(TypeError, "abs() requires numeric argument");
                return NULL;
        }
@@ -61,7 +81,8 @@ builtin_apply(self, args)
        object *args;
 {
        object *func, *arglist;
-       if (!getargs(args, "(OO)", &func, &arglist))
+
+       if (!newgetargs(args, "OO:apply", &func, &arglist))
                return NULL;
        if (!is_tupleobject(arglist)) {
                err_setstr(TypeError, "apply() 2nd argument must be tuple");
@@ -101,12 +122,11 @@ builtin_callable(self, args)
        object *self;
        object *args;
 {
-       if (args == NULL) {
-               err_setstr(TypeError,
-                          "callable requires exactly one argument");
+       object *v;
+
+       if (!newgetargs(args, "O:callable", &v))
                return NULL;
-       }
-       return newintobject((long)callable(args));
+       return newintobject((long)callable(v));
 }
 
 static object *
@@ -119,7 +139,7 @@ builtin_filter(self, args)
        int len;
        register int i, j;
 
-       if (!getargs(args, "(OO)", &func, &seq))
+       if (!newgetargs(args, "OO:filter", &func, &seq))
                return NULL;
 
        if (is_stringobject(seq)) {
@@ -212,7 +232,8 @@ builtin_chr(self, args)
 {
        long x;
        char s[1];
-       if (!getargs(args, "l", &x))
+
+       if (!newgetargs(args, "l:chr", &x))
                return NULL;
        if (x < 0 || x >= 256) {
                err_setstr(ValueError, "chr() arg not in range(256)");
@@ -228,7 +249,8 @@ builtin_cmp(self, args)
        object *args;
 {
        object *a, *b;
-       if (!getargs(args, "(OO)", &a, &b))
+
+       if (!newgetargs(args, "OO:cmp", &a, &b))
                return NULL;
        return newintobject((long)cmpobject(a, b));
 }
@@ -241,7 +263,7 @@ builtin_coerce(self, args)
        object *v, *w;
        object *res;
 
-       if (!getargs(args, "(OO)", &v, &w))
+       if (!newgetargs(args, "OO:coerce", &v, &w))
                return NULL;
        if (is_instanceobject(v) || is_instanceobject(w))
                return instancebinop(v, w, "__coerce__", "__rcoerce__");
@@ -262,7 +284,8 @@ builtin_compile(self, args)
        char *filename;
        char *startstr;
        int start;
-       if (!getargs(args, "(sss)", &str, &filename, &startstr))
+
+       if (!newgetargs(args, "sss:compile", &str, &filename, &startstr))
                return NULL;
        if (strcmp(startstr, "exec") == 0)
                start = file_input;
@@ -277,11 +300,15 @@ builtin_compile(self, args)
 }
 
 static object *
-builtin_dir(self, v)
+builtin_dir(self, args)
        object *self;
-       object *v;
+       object *args;
 {
+       object *v = NULL;
        object *d;
+
+       if (!newgetargs(args, "|O:dir", &v))
+               return NULL;
        if (v == NULL) {
                d = getlocals();
                INCREF(d);
@@ -314,13 +341,15 @@ builtin_divmod(self, args)
        object *args;
 {
        object *v, *w, *x;
-       if (!getargs(args, "(OO)", &v, &w))
+
+       if (!newgetargs(args, "OO:divmod", &v, &w))
                return NULL;
        if (is_instanceobject(v) || is_instanceobject(w))
                return instancebinop(v, w, "__divmod__", "__rdivmod__");
        if (v->ob_type->tp_as_number == NULL ||
                                w->ob_type->tp_as_number == NULL) {
-               err_setstr(TypeError, "divmod() requires numeric or class instance arguments");
+               err_setstr(TypeError,
+                   "divmod() requires numeric or class instance arguments");
                return NULL;
        }
        if (coerce(&v, &w) != 0)
@@ -332,110 +361,80 @@ builtin_divmod(self, args)
 }
 
 static object *
-exec_eval(v, start)
-       object *v;
-       int start;
+builtin_eval(self, args)
+       object *self;
+       object *args;
 {
-       object *str = NULL, *globals = NULL, *locals = NULL;
-       char *s;
-       int n;
-       /* XXX This is a bit of a mess.  Should make it varargs */
-       if (v != NULL) {
-               if (is_tupleobject(v) &&
-                               ((n = gettuplesize(v)) == 2 || n == 3)) {
-                       str = gettupleitem(v, 0);
-                       globals = gettupleitem(v, 1);
-                       if (n == 3)
-                               locals = gettupleitem(v, 2);
-               }
-               else
-                       str = v;
-       }
-       if (str == NULL || (!is_stringobject(str) && !is_codeobject(str)) ||
-                       globals != NULL && !is_dictobject(globals) ||
-                       locals != NULL && !is_dictobject(locals)) {
-               err_setstr(TypeError,
-                 "eval arguments must be (string|code)[,dict[,dict]]");
-               return NULL;
-       }
+       object *cmd;
+       object *globals = NULL, *locals = NULL;
+       char *str;
 
-       if (is_codeobject(str))
-               return eval_code((codeobject *) str, globals, locals,
+       if (!newgetargs(args, "O|O!O!:eval",
+                       &cmd,
+                       &Mappingtype, &globals,
+                       &Mappingtype, &locals))
+               return NULL;
+       if (is_codeobject(cmd))
+               return eval_code((codeobject *) cmd, globals, locals,
                                 (object *)NULL, (object *)NULL);
-       s = getstringvalue(str);
-       if (strlen(s) != getstringsize(str)) {
-               err_setstr(ValueError, "embedded '\\0' in string arg");
+       if (!is_stringobject(cmd)) {
+               err_setstr(TypeError,
+                          "eval() argument 1 must be string or code object");
                return NULL;
        }
-       if (start == eval_input) {
-               while (*s == ' ' || *s == '\t')
-                       s++;
+       str = getstringvalue(cmd);
+       if (strlen(str) != getstringsize(cmd)) {
+               err_setstr(ValueError,
+                          "embedded '\\0' in string arg");
+               return NULL;
        }
-       return run_string(s, start, globals, locals);
-}
-
-static object *
-builtin_eval(self, v)
-       object *self;
-       object *v;
-{
-       return exec_eval(v, eval_input);
+       while (*str == ' ' || *str == '\t')
+               str++;
+       return run_string(str, eval_input, globals, locals);
 }
 
 static object *
-builtin_execfile(self, v)
+builtin_execfile(self, args)
        object *self;
-       object *v;
+       object *args;
 {
-       object *str = NULL, *globals = NULL, *locals = NULL, *w;
+       char *filename;
+       object *globals = NULL, *locals = NULL;
+       object *res;
        FILE* fp;
        char *s;
        int n;
-       if (v != NULL) {
-               if (is_stringobject(v))
-                       str = v;
-               else if (is_tupleobject(v) &&
-                               ((n = gettuplesize(v)) == 2 || n == 3)) {
-                       str = gettupleitem(v, 0);
-                       globals = gettupleitem(v, 1);
-                       if (n == 3)
-                               locals = gettupleitem(v, 2);
-               }
-       }
-       if (str == NULL || !is_stringobject(str) ||
-                       globals != NULL && !is_dictobject(globals) ||
-                       locals != NULL && !is_dictobject(locals)) {
-               err_setstr(TypeError,
-                   "execfile arguments must be filename[,dict[,dict]]");
-               return NULL;
-       }
-       s = getstringvalue(str);
-       if (strlen(s) != getstringsize(str)) {
-               err_setstr(ValueError, "embedded '\\0' in string arg");
+
+       if (!newgetargs(args, "s|O!O!:execfile",
+                       &filename,
+                       &Mappingtype, &globals,
+                       &Mappingtype, &locals))
                return NULL;
-       }
        BGN_SAVE
-       fp = fopen(s, "r");
+       fp = fopen(filename, "r");
        END_SAVE
        if (fp == NULL) {
-               err_setstr(IOError, "execfile cannot open the file argument");
+               err_errno(IOError);
                return NULL;
        }
-       w = run_file(fp, getstringvalue(str), file_input, globals, locals);
+       res = run_file(fp, filename, file_input, globals, locals);
        BGN_SAVE
        fclose(fp);
        END_SAVE
-       return w;
+       return res;
 }
 
 static object *
-builtin_float(self, v)
+builtin_float(self, args)
        object *self;
-       object *v;
+       object *args;
 {
+       object *v;
        number_methods *nb;
-       
-       if (v == NULL || (nb = v->ob_type->tp_as_number) == NULL ||
+
+       if (!newgetargs(args, "O:float", &v))
+               return NULL;
+       if ((nb = v->ob_type->tp_as_number) == NULL ||
            nb->nb_float == NULL) {
                err_setstr(TypeError,
                           "float() argument can't be converted to float");
@@ -451,7 +450,8 @@ builtin_getattr(self, args)
 {
        object *v;
        object *name;
-       if (!getargs(args, "(OS)", &v, &name))
+
+       if (!newgetargs(args, "OS:getattr", &v, &name))
                return NULL;
        return getattro(v, name);
 }
@@ -463,7 +463,8 @@ builtin_hasattr(self, args)
 {
        object *v;
        object *name;
-       if (!getargs(args, "(OS)", &v, &name))
+
+       if (!newgetargs(args, "OS:hasattr", &v, &name))
                return NULL;
        v = getattro(v, name);
        if (v == NULL) {
@@ -480,7 +481,8 @@ builtin_id(self, args)
        object *args;
 {
        object *v;
-       if (!getargs(args, "O", &v))
+
+       if (!newgetargs(args, "O:id", &v))
                return NULL;
        return newintobject((long)v);
 }
@@ -498,16 +500,17 @@ builtin_map(self, args)
 
        object *func, *result;
        sequence *seqs = NULL, *sqp;
-       int n, len, newfunc = 0;
+       int n, len;
        register int i, j;
 
-       if (args == NULL || !is_tupleobject(args)) {
+       n = gettuplesize(args);
+       if (n < 2) {
                err_setstr(TypeError, "map() requires at least two args");
                return NULL;
        }
 
        func = gettupleitem(args, 0);
-       n    = gettuplesize(args) - 1;
+       n--;
 
        if ((seqs = NEW(sequence, n)) == NULL) {
                err_nomem();
@@ -633,7 +636,8 @@ builtin_setattr(self, args)
        object *v;
        object *name;
        object *value;
-       if (!getargs(args, "(OSO)", &v, &name, &value))
+
+       if (!newgetargs(args, "OSO:setattr", &v, &name, &value))
                return NULL;
        if (setattro(v, name, value) != 0)
                return NULL;
@@ -648,7 +652,8 @@ builtin_delattr(self, args)
 {
        object *v;
        object *name;
-       if (!getargs(args, "(OS)", &v, &name))
+
+       if (!newgetargs(args, "OS:delattr", &v, &name))
                return NULL;
        if (setattro(v, name, (object *)NULL) != 0)
                return NULL;
@@ -663,7 +668,8 @@ builtin_hash(self, args)
 {
        object *v;
        long x;
-       if (!getargs(args, "O", &v))
+
+       if (!newgetargs(args, "O:hash", &v))
                return NULL;
        x = hashobject(v);
        if (x == -1)
@@ -672,13 +678,17 @@ builtin_hash(self, args)
 }
 
 static object *
-builtin_hex(self, v)
+builtin_hex(self, args)
        object *self;
-       object *v;
+       object *args;
 {
+       object *v;
        number_methods *nb;
+
+       if (!newgetargs(args, "O:hex", &v))
+               return NULL;
        
-       if (v == NULL || (nb = v->ob_type->tp_as_number) == NULL ||
+       if ((nb = v->ob_type->tp_as_number) == NULL ||
            nb->nb_hex == NULL) {
                err_setstr(TypeError,
                           "hex() argument can't be converted to hex");
@@ -690,26 +700,37 @@ builtin_hex(self, v)
 static object *builtin_raw_input PROTO((object *, object *));
 
 static object *
-builtin_input(self, v)
+builtin_input(self, args)
        object *self;
-       object *v;
+       object *args;
 {
-       object *line = builtin_raw_input(self, v);
+       object *line;
+       char *str;
+       object *res;
+
+       line = builtin_raw_input(self, args);
        if (line == NULL)
                return line;
-       v = exec_eval(line, eval_input);
+       if (!getargs(line, "s;embedded '\\0' in input line", &str))
+               return NULL;
+       while (*str == ' ' || *str == '\t')
+                       str++;
+       res = run_string(str, eval_input, (object *)NULL, (object *)NULL);
        DECREF(line);
-       return v;
+       return res;
 }
 
 static object *
-builtin_int(self, v)
+builtin_int(self, args)
        object *self;
-       object *v;
+       object *args;
 {
+       object *v;
        number_methods *nb;
-       
-       if (v == NULL || (nb = v->ob_type->tp_as_number) == NULL ||
+
+       if (!newgetargs(args, "O:int", &v))
+               return NULL;
+       if ((nb = v->ob_type->tp_as_number) == NULL ||
            nb->nb_int == NULL) {
                err_setstr(TypeError,
                           "int() argument can't be converted to int");
@@ -719,16 +740,16 @@ builtin_int(self, v)
 }
 
 static object *
-builtin_len(self, v)
+builtin_len(self, args)
        object *self;
-       object *v;
+       object *args;
 {
+       object *v;
        long len;
        typeobject *tp;
-       if (v == NULL) {
-               err_setstr(TypeError, "len() without argument");
+
+       if (!newgetargs(args, "O:len", &v))
                return NULL;
-       }
        tp = v->ob_type;
        if (tp->tp_as_sequence != NULL) {
                len = (*tp->tp_as_sequence->sq_length)(v);
@@ -747,13 +768,16 @@ builtin_len(self, v)
 }
 
 static object *
-builtin_long(self, v)
+builtin_long(self, args)
        object *self;
-       object *v;
+       object *args;
 {
+       object *v;
        number_methods *nb;
        
-       if (v == NULL || (nb = v->ob_type->tp_as_number) == NULL ||
+       if (!newgetargs(args, "O:long", &v))
+               return NULL;
+       if ((nb = v->ob_type->tp_as_number) == NULL ||
            nb->nb_long == NULL) {
                err_setstr(TypeError,
                           "long() argument can't be converted to long");
@@ -763,17 +787,18 @@ builtin_long(self, v)
 }
 
 static object *
-min_max(v, sign)
-       object *v;
+min_max(args, sign)
+       object *args;
        int sign;
 {
        int i;
-       object *w, *x;
+       object *v, *w, *x;
        sequence_methods *sq;
-       if (v == NULL) {
-               err_setstr(TypeError, "min() or max() without argument");
+
+       if (gettuplesize(args) > 1)
+               v = args;
+       else if (!newgetargs(args, "O:min/max", &v))
                return NULL;
-       }
        sq = v->ob_type->tp_as_sequence;
        if (sq == NULL) {
                err_setstr(TypeError, "min() or max() of non-sequence");
@@ -823,12 +848,15 @@ builtin_max(self, v)
 }
 
 static object *
-builtin_oct(self, v)
+builtin_oct(self, args)
        object *self;
-       object *v;
+       object *args;
 {
+       object *v;
        number_methods *nb;
-       
+
+       if (!newgetargs(args, "O:oct", &v))
+               return NULL;
        if (v == NULL || (nb = v->ob_type->tp_as_number) == NULL ||
            nb->nb_oct == NULL) {
                err_setstr(TypeError,
@@ -847,9 +875,8 @@ builtin_open(self, args)
        char *mode = "r";
        int bufsize = -1;
        object *f;
-       if (!getargs(args, "s", &name) &&
-           (err_clear(), !getargs(args, "(ss)", &name, &mode)) &&
-           (err_clear(), !getargs(args, "(ssi)", &name, &mode, &bufsize)))
+
+       if (!newgetargs(args, "s|si:open", &name, &mode, &bufsize))
                return NULL;
        f = newfileobject(name, mode);
        if (f != NULL)
@@ -862,15 +889,11 @@ builtin_ord(self, args)
        object *self;
        object *args;
 {
-       char *s;
-       int len;
-       if (!getargs(args, "s#", &s, &len))
-               return NULL;
-       if (len != 1) {
-               err_setstr(ValueError, "ord() arg must have length 1");
+       char c;
+
+       if (!newgetargs(args, "c:ord", &c))
                return NULL;
-       }
-       return newintobject((long)(s[0] & 0xff));
+       return newintobject((long)(c & 0xff));
 }
 
 static object *
@@ -878,9 +901,9 @@ builtin_pow(self, args)
        object *self;
        object *args;
 {
-       object *v, *w, *z, *x;
-       z = None;
-       if (!newgetargs(args, "OO|O", &v, &w, &z))
+       object *v, *w, *z = None, *x;
+
+       if (!newgetargs(args, "OO|O:pow", &v, &w, &z))
                return NULL;
        if (z == None) {
                if (is_instanceobject(v) || is_instanceobject(w))
@@ -913,43 +936,25 @@ builtin_pow(self, args)
 }
 
 static object *
-builtin_range(self, v)
+builtin_range(self, args)
        object *self;
-       object *v;
+       object *args;
 {
-       static char *errmsg = "range() requires 1-3 int arguments";
+       long ilow = 0, ihigh = 0, istep = 1;
        int i, n;
-       long ilow, ihigh, istep;
-       if (v != NULL && is_intobject(v)) {
-               ilow = 0; ihigh = getintvalue(v); istep = 1;
-       }
-       else if (v == NULL || !is_tupleobject(v)) {
-               err_setstr(TypeError, errmsg);
-               return NULL;
+       object *v;
+
+       if (gettuplesize(args) <= 1) {
+               if (!newgetargs(args,
+                               "i;range() requires 1-3 int arguments",
+                               &ihigh))
+                       return NULL;
        }
        else {
-               n = gettuplesize(v);
-               if (n < 1 || n > 3) {
-                       err_setstr(TypeError, errmsg);
+               if (!newgetargs(args,
+                               "ii|i;range() requires 1-3 int arguments",
+                               &ilow, &ihigh, &istep))
                        return NULL;
-               }
-               for (i = 0; i < n; i++) {
-                       if (!is_intobject(gettupleitem(v, i))) {
-                               err_setstr(TypeError, errmsg);
-                               return NULL;
-                       }
-               }
-               if (n == 3) {
-                       istep = getintvalue(gettupleitem(v, 2));
-                       --n;
-               }
-               else
-                       istep = 1;
-               ihigh = getintvalue(gettupleitem(v, --n));
-               if (n > 0)
-                       ilow = getintvalue(gettupleitem(v, 0));
-               else
-                       ilow = 0;
        }
        if (istep == 0) {
                err_setstr(ValueError, "zero step for range()");
@@ -978,73 +983,66 @@ builtin_range(self, v)
 }
 
 static object *
-builtin_xrange(self, v)
+builtin_xrange(self, args)
        object *self;
-       object *v;
+       object *args;
 {
-       static char *errmsg = "xrange() requires 1-3 int arguments";
-       int i, n;
-       long start, stop, step, len;
-       if (v != NULL && is_intobject(v))
-               start = 0, stop = getintvalue(v), step = 1;
+       long ilow = 0, ihigh = 0, istep = 1;
+       int n;
+       object *v;
 
-       else if (v == NULL || !is_tupleobject(v)) {
-               err_setstr(TypeError, errmsg);
-               return NULL;
+       if (gettuplesize(args) <= 1) {
+               if (!newgetargs(args,
+                               "i;xrange() requires 1-3 int arguments",
+                               &ihigh))
+                       return NULL;
        }
        else {
-               n = gettuplesize(v);
-               if (n < 1 || n > 3) {
-                       err_setstr(TypeError, errmsg);
+               if (!newgetargs(args,
+                               "ii|i;xrange() requires 1-3 int arguments",
+                               &ilow, &ihigh, &istep))
                        return NULL;
-               }
-               for (i = 0; i < n; i++) {
-                       if (!is_intobject(gettupleitem(v, i))) {
-                               err_setstr(TypeError, errmsg);
-                               return NULL;
-                       }
-               }
-               if (n == 3) {
-                       step = getintvalue(gettupleitem(v, 2));
-                       --n;
-               }
-               else
-                       step = 1;
-               stop = getintvalue(gettupleitem(v, --n));
-               if (n > 0)
-                       start = getintvalue(gettupleitem(v, 0));
-               else
-                       start = 0;
        }
-
-       if (step == 0) {
+       if (istep == 0) {
                err_setstr(ValueError, "zero step for xrange()");
                return NULL;
        }
-
-       len = (stop - start + step + ((step > 0) ? -1 : 1)) / step;
-       if (len < 0)
-               len = 0;
-
-       return newrangeobject(start, len, step, 1);
+       /* XXX ought to check overflow of subtraction */
+       if (istep > 0)
+               n = (ihigh - ilow + istep - 1) / istep;
+       else
+               n = (ihigh - ilow + istep + 1) / istep;
+       if (n < 0)
+               n = 0;
+       return newrangeobject(ilow, n, istep, 1);
 }
 
 static object *
-builtin_raw_input(self, v)
+builtin_raw_input(self, args)
        object *self;
-       object *v;
+       object *args;
 {
-       object *f = sysget("stdout");
-       if (f == NULL) {
-               err_setstr(RuntimeError, "lost sys.stdout");
+       object *v = NULL;
+       object *f;
+
+       if (!newgetargs(args, "|O:[raw_]input", &v))
                return NULL;
-       }
-       flushline();
        if (v != NULL) {
+               f = sysget("stdout");
+               if (f == NULL) {
+                       err_setstr(RuntimeError, "lost sys.stdout");
+                       return NULL;
+               }
+               flushline();
                if (writeobject(v, f, PRINT_RAW) != 0)
                        return NULL;
        }
-       return filegetline(sysget("stdin"), -1);
+       f = sysget("stdin");
+       if (f == NULL) {
+               err_setstr(RuntimeError, "lost sys.stdin");
+               return NULL;
+       }
+       return filegetline(f, -1);
 }
 
 static object *
@@ -1052,18 +1050,14 @@ builtin_reduce(self, args)
        object *self;
        object *args;
 {
-       object *seq, *func, *result;
+       object *seq, *func, *result = NULL;
        sequence_methods *sqf;
        register int i;
 
-       if (getargs(args, "(OO)", &func, &seq))
-               result = NULL;
-       else {
-               err_clear();
-               if (!getargs(args, "(OOO)", &func, &seq, &result))
-                       return NULL;
+       if (!newgetargs(args, "OO|O:reduce", &func, &seq, &result))
+               return NULL;
+       if (result != NULL)
                INCREF(result);
-       }
 
        if ((sqf = seq->ob_type->tp_as_sequence) == NULL) {
                err_setstr(TypeError,
@@ -1116,22 +1110,26 @@ Fail:
 }
 
 static object *
-builtin_reload(self, v)
+builtin_reload(self, args)
        object *self;
-       object *v;
+       object *args;
 {
+       object *v;
+
+       if (!newgetargs(args, "O:reload", &v))
+               return NULL;
        return reload_module(v);
 }
 
 static object *
-builtin_repr(self, v)
+builtin_repr(self, args)
        object *self;
-       object *v;
+       object *args;
 {
-       if (v == NULL) {
-               err_badarg();
+       object *v;
+
+       if (!newgetargs(args, "O:repr", &v))
                return NULL;
-       }
        return reprobject(v);
 }
 
@@ -1145,13 +1143,10 @@ builtin_round(self, args)
        double x;
        double f;
        int ndigits = 0;
-       int sign = 1;
        int i;
-       if (!getargs(args, "d", &x)) {
-               err_clear();
-               if (!getargs(args, "(di)", &x, &ndigits))
+
+       if (!newgetargs(args, "d|i:round", &x, &ndigits))
                        return NULL;
-       }
        f = 1.0;
        for (i = ndigits; --i >= 0; )
                f = f*10.0;
@@ -1164,25 +1159,27 @@ builtin_round(self, args)
 }
 
 static object *
-builtin_str(self, v)
+builtin_str(self, args)
        object *self;
-       object *v;
+       object *args;
 {
-       if (v == NULL) {
-               err_badarg();
+       object *v;
+
+       if (!newgetargs(args, "O:str", &v))
                return NULL;
-       }
        return strobject(v);
 }
 
 static object *
-builtin_tuple(self, v)
+builtin_tuple(self, args)
        object *self;
-       object *v;
+       object *args;
 {
+       object *v;
        sequence_methods *sqf;
-       if (v == NULL)
-               v = None; /* Force error later */
+
+       if (!newgetargs(args, "O:tuple", &v))
+               return NULL;
        if (is_tupleobject(v)) {
                INCREF(v);
                return v;
@@ -1235,25 +1232,29 @@ builtin_tuple(self, v)
 }
 
 static object *
-builtin_type(self, v)
+builtin_type(self, args)
        object *self;
-       object *v;
+       object *args;
 {
-       if (v == NULL) {
-               err_setstr(TypeError, "type() requires an argument");
+       object *v;
+
+       if (!newgetargs(args, "O:type", &v))
                return NULL;
-       }
        v = (object *)v->ob_type;
        INCREF(v);
        return v;
 }
 
 static object *
-builtin_vars(self, v)
+builtin_vars(self, args)
        object *self;
-       object *v;
+       object *args;
 {
+       object *v = NULL;
        object *d;
+
+       if (!newgetargs(args, "|O:vars", &v))
+               return NULL;
        if (v == NULL) {
                d = getlocals();
                INCREF(d);
@@ -1270,48 +1271,49 @@ builtin_vars(self, v)
 }
 
 static struct methodlist builtin_methods[] = {
-       {"abs",         builtin_abs},
-       {"apply",       builtin_apply},
-       {"callable",    builtin_callable},
-       {"chr",         builtin_chr},
-       {"cmp",         builtin_cmp},
-       {"coerce",      builtin_coerce},
-       {"compile",     builtin_compile},
-       {"delattr",     builtin_delattr},
-       {"dir",         builtin_dir},
-       {"divmod",      builtin_divmod},
-       {"eval",        builtin_eval},
-       {"execfile",    builtin_execfile},
-       {"filter",      builtin_filter},
-       {"float",       builtin_float},
-       {"getattr",     builtin_getattr},
-       {"hasattr",     builtin_hasattr},
-       {"hash",        builtin_hash},
-       {"hex",         builtin_hex},
-       {"id",          builtin_id},
-       {"input",       builtin_input},
-       {"int",         builtin_int},
-       {"len",         builtin_len},
-       {"long",        builtin_long},
-       {"map",         builtin_map},
-       {"max",         builtin_max},
-       {"min",         builtin_min},
-       {"oct",         builtin_oct},
-       {"open",        builtin_open},
-       {"ord",         builtin_ord},
+       {"__import__",  builtin___import__, 1},
+       {"abs",         builtin_abs, 1},
+       {"apply",       builtin_apply, 1},
+       {"callable",    builtin_callable, 1},
+       {"chr",         builtin_chr, 1},
+       {"cmp",         builtin_cmp, 1},
+       {"coerce",      builtin_coerce, 1},
+       {"compile",     builtin_compile, 1},
+       {"delattr",     builtin_delattr, 1},
+       {"dir",         builtin_dir, 1},
+       {"divmod",      builtin_divmod, 1},
+       {"eval",        builtin_eval, 1},
+       {"execfile",    builtin_execfile, 1},
+       {"filter",      builtin_filter, 1},
+       {"float",       builtin_float, 1},
+       {"getattr",     builtin_getattr, 1},
+       {"hasattr",     builtin_hasattr, 1},
+       {"hash",        builtin_hash, 1},
+       {"hex",         builtin_hex, 1},
+       {"id",          builtin_id, 1},
+       {"input",       builtin_input, 1},
+       {"int",         builtin_int, 1},
+       {"len",         builtin_len, 1},
+       {"long",        builtin_long, 1},
+       {"map",         builtin_map, 1},
+       {"max",         builtin_max, 1},
+       {"min",         builtin_min, 1},
+       {"oct",         builtin_oct, 1},
+       {"open",        builtin_open, 1},
+       {"ord",         builtin_ord, 1},
        {"pow",         builtin_pow, 1},
-       {"range",       builtin_range},
-       {"raw_input",   builtin_raw_input},
-       {"reduce",      builtin_reduce},
-       {"reload",      builtin_reload},
-       {"repr",        builtin_repr},
-       {"round",       builtin_round},
-       {"setattr",     builtin_setattr},
-       {"str",         builtin_str},
-       {"tuple",       builtin_tuple},
-       {"type",        builtin_type},
-       {"vars",        builtin_vars},
-       {"xrange",      builtin_xrange},
+       {"range",       builtin_range, 1},
+       {"raw_input",   builtin_raw_input, 1},
+       {"reduce",      builtin_reduce, 1},
+       {"reload",      builtin_reload, 1},
+       {"repr",        builtin_repr, 1},
+       {"round",       builtin_round, 1},
+       {"setattr",     builtin_setattr, 1},
+       {"str",         builtin_str, 1},
+       {"tuple",       builtin_tuple, 1},
+       {"type",        builtin_type, 1},
+       {"vars",        builtin_vars, 1},
+       {"xrange",      builtin_xrange, 1},
        {NULL,          NULL},
 };
 
@@ -1324,6 +1326,13 @@ getbuiltin(name)
        return mappinglookup(builtin_dict, name);
 }
 
+object *
+getbuiltins(name)
+       char *name;
+{
+       return dictlookup(builtin_dict, name);
+}
+
 int
 setbuiltin(cname, value)
        char *cname;
index 26b3ce34cd2b90670b20d4c49671ff057bfd30eb..2a3fe7be2686c1e28c8a41d2bc84348709131a41 100644 (file)
@@ -43,11 +43,11 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 extern int suppress_print; /* Declared in pythonrun.c, set in pythonmain.c */
 
 /* Turn this on if your compiler chokes on the big switch: */
-/* #define CASE_TOO_BIG 1      /**/
+/* #define CASE_TOO_BIG 1 */
 
 /* Turn this on if you want to debug the interpreter: */
 /* (This can be on even if NDEBUG is defined) */
-/* #define DEBUG 1             /**/
+/* #define DEBUG 1 */
 
 #if defined(DEBUG) || !defined(NDEBUG)
 /* For debugging the interpreter: */
@@ -1254,8 +1254,8 @@ eval_code(co, globals, locals, owner, arg)
                                DECREF(v);
                                break;
                        }
-                       XDECREF(w);
                        GETLISTITEM(fastlocals, oparg) = v;
+                       XDECREF(w);
                        break;
 
                case DELETE_FAST:
@@ -1270,8 +1270,8 @@ eval_code(co, globals, locals, owner, arg)
                                                     (object *)NULL);
                                break;
                        }
-                       DECREF(x);
                        GETLISTITEM(fastlocals, oparg) = NULL;
+                       DECREF(x);
                        break;
                
                case BUILD_TUPLE:
@@ -1323,10 +1323,22 @@ eval_code(co, globals, locals, owner, arg)
                        break;
                
                case IMPORT_NAME:
-                       name = GETNAME(oparg);
-                       x = import_module(name);
-                       XINCREF(x);
-                       PUSH(x);
+                       w = GETNAMEV(oparg);
+                       x = getbuiltins("__import__");
+                       if (x == NULL) {
+                               err_setstr(ImportError,
+                                          "__import__ not found");
+                               break;
+                       }
+                       w = mkvalue("(O)", w);
+                       if (w == NULL) {
+                               x = NULL;
+                               break;
+                       }
+                       x = call_object(x, w);
+                       DECREF(w);
+                       if (x)
+                               PUSH(x);
                        break;
                
                case IMPORT_FROM:
@@ -1408,7 +1420,7 @@ eval_code(co, globals, locals, owner, arg)
                case SET_LINENO:
 #ifdef LLTRACE
                        if (lltrace)
-                               printf("--- Line %d ---\n", oparg);
+                               printf("--- %s:%d \n", filename, oparg);
 #endif
                        f->f_lineno = oparg;
                        if (f->f_trace != NULL) {
@@ -1497,24 +1509,23 @@ eval_code(co, globals, locals, owner, arg)
                                        b->b_type == SETUP_EXCEPT &&
                                        why == WHY_EXCEPTION) {
                                if (why == WHY_EXCEPTION) {
-                                       object *exc, *val;
-                                       err_get(&exc, &val);
+                                       object *exc, *val, *tb;
+                                       err_fetch(&exc, &val, &tb);
                                        if (val == NULL) {
                                                val = None;
                                                INCREF(val);
                                        }
-                                       v = tb_fetch();
                                        /* Make the raw exception data
                                           available to the handler,
                                           so a program can emulate the
                                           Python main loop.  Don't do
                                           this for 'finally'. */
                                        if (b->b_type == SETUP_EXCEPT) {
-                                               sysset("exc_traceback", v);
+                                               sysset("exc_traceback", tb);
                                                sysset("exc_value", val);
                                                sysset("exc_type", exc);
                                        }
-                                       PUSH(v);
+                                       PUSH(tb);
                                        PUSH(val);
                                        PUSH(exc);
                                }
@@ -1598,26 +1609,25 @@ call_exc_trace(p_trace, p_newtrace, f)
 {
        object *type, *value, *traceback, *arg;
        int err;
-       err_get(&type, &value);
+       err_fetch(&type, &value, &traceback);
        if (value == NULL) {
                value = None;
                INCREF(value);
        }
-       traceback = tb_fetch();
-       arg = newtupleobject(3);
-       if (arg == NULL)
-               goto cleanup;
-       settupleitem(arg, 0, type);
-       settupleitem(arg, 1, value);
-       settupleitem(arg, 2, traceback);
+       arg = mkvalue("(OOO)", type, value, traceback);
+       if (arg == NULL) {
+               err_restore(type, value, traceback);
+               return;
+       }
        err = call_trace(p_trace, p_newtrace, f, "exception", arg);
-       if (!err) {
- cleanup:
-               /* Restore original exception */
-               err_setval(type, value);
-               tb_store(traceback);
+       DECREF(arg);
+       if (err == 0)
+               err_restore(type, value, traceback);
+       else {
+               XDECREF(type);
+               XDECREF(value);
+               XDECREF(traceback);
        }
-       XDECREF(arg);
 }
 
 static int
@@ -1723,18 +1733,6 @@ getframe()
        return (object *)current_frame;
 }
 
-void
-printtraceback(f)
-       object *f;
-{
-       object *v = tb_fetch();
-       if (v != NULL) {
-               tb_print(v, f);
-               DECREF(v);
-       }
-}
-
-
 void
 flushline()
 {
@@ -1818,7 +1816,7 @@ static object *
 lshift(v, w)
        object *v, *w;
 {
-       BINOP("__lshift__", "__rshift__");
+       BINOP("__lshift__", "__rlshift__");
        if (v->ob_type->tp_as_number != NULL) {
                object *x;
                object * (*f) FPROTO((object *, object *));
@@ -1962,6 +1960,9 @@ static object *
 rem(v, w)
        object *v, *w;
 {
+       if (is_stringobject(v)) {
+               return formatstring(v, w);
+       }
        BINOP("__mod__", "__rmod__");
        if (v->ob_type->tp_as_number != NULL) {
                object *x;
@@ -1972,9 +1973,6 @@ rem(v, w)
                DECREF(w);
                return x;
        }
-       if (is_stringobject(v)) {
-               return formatstring(v, w);
-       }
        err_setstr(TypeError, "bad operand type(s) for %");
        return NULL;
 }
@@ -2492,6 +2490,10 @@ import_from(locals, v, name)
        object *name;
 {
        object *w, *x;
+       if (!is_moduleobject(v)) {
+               err_setstr(TypeError, "import-from require module object");
+               return -1;
+       }
        w = getmoduledict(v);
        if (getstringvalue(name)[0] == '*') {
                int pos, err;
@@ -2542,6 +2544,22 @@ build_class(methods, bases, name)
                err_setstr(SystemError, "build_class with non-tuple bases");
                return NULL;
        }
+       if (gettuplesize(bases) > 0) {
+               object *base;
+               base = gettupleitem(bases, 0);
+               /* Call the base's *type*, if it is callable.
+                  This code is a hook for Donald Beaudry's type extensions.
+                  In unexended Python it will never be triggered since its
+                  types are not callable. */
+               if (base->ob_type->ob_type->tp_call) {
+                       object *args;
+                       object *class;
+                       args = mkvalue("(OOO)", name, bases, methods);
+                       class = call_object((object *)base->ob_type, args);
+                       DECREF(args);
+                       return class;
+               }
+       }
        if (!is_dictobject(methods)) {
                err_setstr(SystemError, "build_class with non-dictionary");
                return NULL;
index b3b610a55c8e5159ae5faf21f1098c0c1a093d11..dbc6314bc1ba9cc193395c51ce57cc8cbb78d395 100644 (file)
@@ -336,7 +336,7 @@ com_addbyte(c, byte)
        if (byte < 0 || byte > 255) {
                /*
                fprintf(stderr, "XXX compiling bad byte: %d\n", byte);
-               abort();
+               fatal("com_addbyte: byte out of range");
                */
                err_setstr(SystemError, "com_addbyte: byte out of range");
                c->c_errors++;
@@ -2379,7 +2379,7 @@ optimize(c)
        int oparg;
        object *name;
        int fast_reserved;
-       object *error_type, *error_value;
+       object *error_type, *error_value, *error_traceback;
        
 #define NEXTOP()       (*next_instr++)
 #define NEXTARG()      (next_instr += 2, (next_instr[-1]<<8) + next_instr[-2])
@@ -2393,7 +2393,7 @@ optimize(c)
        }
        nlocals = 0;
 
-       err_get(&error_type, &error_value);
+       err_fetch(&error_type, &error_value, &error_traceback);
        
        next_instr = (unsigned char *) getstringvalue(c->c_code);
        for (;;) {
@@ -2493,7 +2493,7 @@ optimize(c)
        }
 
  end:
-       err_setval(error_type, error_value);
+       err_restore(error_type, error_value, error_traceback);
  err:
        DECREF(locals);
 }
index bb3b605a819bc1da3cf67fc943c3ae39f241498c..9b0a8d28d83680576a58f82267132fcb3c333933 100644 (file)
@@ -60,6 +60,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #include <errno.h>
 
+#ifndef NT
 #ifdef macintosh
 /*
 ** For the mac, there's a function macstrerror in macosmodule.c. We can't
@@ -68,9 +69,9 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
 #define strerror macstrerror
 #include "macdefs.h"    /* For CW to find EINTR */
-#endif /* macintosh */
-
+#endif /* !macintosh */
 extern char *strerror PROTO((int));
+#endif /* !NT */
 
 /* Last exception stored by err_setval() */
 
@@ -78,17 +79,27 @@ static object *last_exception;
 static object *last_exc_val;
 
 void
-err_setval(exception, value)
+err_restore(exception, value, traceback)
        object *exception;
        object *value;
+       object *traceback;
 {
        err_clear();
 
-       XINCREF(exception);
        last_exception = exception;
-       
-       XINCREF(value);
        last_exc_val = value;
+       (void) tb_store(traceback);
+       XDECREF(traceback);
+}
+
+void
+err_setval(exception, value)
+       object *exception;
+       object *value;
+{
+       XINCREF(exception);
+       XINCREF(value);
+       err_restore(exception, value, (object *)NULL);
 }
 
 void
@@ -116,14 +127,16 @@ err_occurred()
 }
 
 void
-err_get(p_exc, p_val)
+err_fetch(p_exc, p_val, p_tb)
        object **p_exc;
        object **p_val;
+       object **p_tb;
 {
        *p_exc = last_exception;
        last_exception = NULL;
        *p_val = last_exc_val;
        last_exc_val = NULL;
+       *p_tb = tb_fetch();
 }
 
 void
index 15cd4e6ce482104cc8e778f9f9a5b78711b5cbb2..1232fd0924f6021270e2cf42105f7bcd35b93d3c 100644 (file)
@@ -38,7 +38,7 @@ int vgetargs PROTO((object *, char *, va_list));
 
 
 /* Forward */
-static int vgetargs1 PROTO((object *, char *, va_list, int));
+static int vgetargs1 PROTO((object *, char *, va_list *, int));
 static void seterror PROTO((int, char *, int *, char *, char *));
 static char *convertitem PROTO((object *, char **, va_list *, int *, char *));
 static char *converttuple PROTO((object *, char **, va_list *,
@@ -68,7 +68,7 @@ int getargs(va_alist) va_dcl
        args = va_arg(va, object *);
        format = va_arg(va, char *);
 #endif
-       retval = vgetargs1(args, format, va, 1);
+       retval = vgetargs1(args, format, &va, 1);
        va_end(va);
        return retval;
 }
@@ -95,7 +95,7 @@ int newgetargs(va_alist) va_dcl
        args = va_arg(va, object *);
        format = va_arg(va, char *);
 #endif
-       retval = vgetargs1(args, format, va, 0);
+       retval = vgetargs1(args, format, &va, 0);
        va_end(va);
        return retval;
 }
@@ -107,15 +107,23 @@ vgetargs(args, format, va)
        char *format;
        va_list va;
 {
-       return vgetargs1(args, format, va, 0);
+       va_list lva;
+
+#ifdef VA_LIST_IS_ARRAY
+       memcpy(lva, va, sizeof(va_list));
+#else
+       lva = va;
+#endif
+
+       return vgetargs1(args, format, &lva, 0);
 }
 
 
 static int
-vgetargs1(args, format, va, compat)
+vgetargs1(args, format, p_va, compat)
        object *args;
        char *format;
-       va_list va;
+       va_list *p_va;
        int compat;
 {
        char msgbuf[256];
@@ -186,7 +194,7 @@ vgetargs1(args, format, va, compat)
                                err_setstr(TypeError, msgbuf);
                                return 0;
                        }
-                       msg = convertitem(args, &format, &va, levels, msgbuf);
+                       msg = convertitem(args, &format, p_va, levels, msgbuf);
                        if (msg == NULL)
                                return 1;
                        seterror(levels[0], msg, levels+1, fname, message);
@@ -226,7 +234,7 @@ vgetargs1(args, format, va, compat)
        for (i = 0; i < len; i++) {
                if (*format == '|')
                        format++;
-               msg = convertitem(gettupleitem(args, i), &format, &va,
+               msg = convertitem(gettupleitem(args, i), &format, p_va,
                                 levels, msgbuf);
                if (msg) {
                        seterror(i+1, msg, levels, fname, message);
index ea6a6feeb7edbbb205c6f7c05da4fe989c1f9935..a0af0507eef3f93d5fe765c2268c0fdf3d2959a5 100644 (file)
@@ -37,150 +37,58 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #include "compile.h"
 #include "eval.h"
 #include "osdefs.h"
+#include "importdl.h"
 
 extern int verbose; /* Defined in pythonrun.c */
 
 extern long getmtime(); /* In getmtime.c */
 
-#ifdef DEBUG
-#define D(x) x
-#else
-#define D(x)
-#endif
-
-/* 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"
-   hpux                -- HP-UX Dynamic Linking - defined by the compiler
-
-   (The other WITH_* symbols are used only once, to set the
-   appropriate symbols.)
-*/
-
-/* Configure dynamic linking */
-
-#ifdef hpux
-#define DYNAMIC_LINK
-#include <errno.h>
-typedef void (*dl_funcptr)();
-#define _DL_FUNCPTR_DEFINED 1
-#define SHORT_EXT ".sl"
-#define LONG_EXT "module.sl"
-#endif 
-
-#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)();
-#endif
-#ifndef RTLD_LAZY
-#define RTLD_LAZY 1
-#endif
-#define SHORT_EXT ".so"
-#define LONG_EXT "module.so"
-#endif /* USE_SHLIB */
-
-#if defined(USE_DL) || defined(hpux)
-#include "dl.h"
-#endif
-
-#ifdef WITH_MAC_DL
-#include "dynamic_load.h"
-#endif
+/* Magic word to reject .pyc files generated by other Python versions */
+#define MAGIC 0x999903L /* Increment by one for each incompatible change */
 
-#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 */
+object *import_modules; /* This becomes sys.modules */
 
-extern char *getprogramname();
 
-#ifndef FUNCNAME_PATTERN
-#if defined(__hp9000s300)
-#define FUNCNAME_PATTERN "_init%s"
-#else
-#define FUNCNAME_PATTERN "init%s"
-#endif
-#endif
-
-#if !defined(SHORT_EXT) && !defined(LONG_EXT)
-#define SHORT_EXT ".o"
-#define LONG_EXT "module.o"
-#endif /* !SHORT_EXT && !LONG_EXT */
+/* Initialize things */
 
-#endif /* DYNAMIC_LINK */
+void
+initimport()
+{
+       if (import_modules != NULL)
+               fatal("duplicate initimport() call");
+       if ((import_modules = newdictobject()) == NULL)
+               fatal("no mem for dictionary of modules");
+}
 
-/* Max length of module suffix searched for -- accommodates "module.so" */
-#ifndef MAXSUFFIXSIZE
-#define MAXSUFFIXSIZE 10
-#endif
 
-/* Magic word to reject .pyc files generated by other Python versions */
-#define MAGIC 0x999903L /* Increment by one for each incompatible change */
+/* Un-initialize things, as good as we can */
 
-static object *modules;
+void
+doneimport()
+{
+       if (import_modules != NULL) {
+               int pos;
+               object *modname, *module;
+               /* Explicitly erase all modules; this is the safest way
+                  to get rid of at least *some* circular dependencies */
+               pos = 0;
+               while (mappinggetnext(import_modules,
+                                     &pos, &modname, &module)) {
+                       if (is_moduleobject(module)) {
+                               object *dict;
+                               dict = getmoduledict(module);
+                               if (dict != NULL && is_dictobject(dict))
+                                       mappingclear(dict);
+                       }
+               }
+               mappingclear(import_modules);
+               DECREF(import_modules);
+       }
+       import_modules = NULL;
+}
 
-/* Forward */
-static int init_builtin PROTO((char *));
 
-/* Helper for reading .pyc files */
+/* Helper for pythonrun.c -- return magic number */
 
 long
 get_pyc_magic()
@@ -188,255 +96,338 @@ get_pyc_magic()
        return MAGIC;
 }
 
-/* Initialization */
 
-void
-initimport()
-{
-       if ((modules = newdictobject()) == NULL)
-               fatal("no mem for dictionary of modules");
-}
+/* Helper for sysmodule.c -- return modules dictionary */
 
 object *
 get_modules()
 {
-       return modules;
+       return import_modules;
 }
 
+
+/* Get the module object corresponding to a module name.
+   First check the modules dictionary if there's one there,
+   if not, create a new one and insert in in the modules dictionary.
+   Because the former action is most common, this does not return a
+   'new' reference! */
+
 object *
 add_module(name)
        char *name;
 {
        object *m;
-       if ((m = dictlookup(modules, name)) != NULL && is_moduleobject(m))
+
+       if ((m = dictlookup(import_modules, name)) != NULL &&
+           is_moduleobject(m))
                return m;
        m = newmoduleobject(name);
        if (m == NULL)
                return NULL;
-       if (dictinsert(modules, name, m) != 0) {
+       if (dictinsert(import_modules, name, m) != 0) {
                DECREF(m);
                return NULL;
        }
        DECREF(m); /* Yes, it still exists, in modules! */
+
        return m;
 }
 
-enum filetype {SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION};
 
-static struct filedescr {
-       char *suffix;
-       char *mode;
-       enum filetype type;
-} filetab[] = {
-#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}
-};
+/* Execute a code object in a module and return its module object */
 
-#ifdef DYNAMIC_LINK
 static object *
-load_dynamic_module(name, namebuf, m, m_ret)
+exec_code_module(name, co)
        char *name;
-       char *namebuf;
-       object *m;
-       object **m_ret;
+       codeobject *co;
 {
-       char funcname[258];
-       dl_funcptr p = NULL;
-       if (m != NULL) {
-               err_setstr(ImportError,
-                          "cannot reload dynamically loaded module");
+       object *m, *d, *v;
+
+       m = add_module(name);
+       if (m == NULL)
                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;
+       d = getmoduledict(m);
+       v = eval_code((codeobject *)co, d, d, d, (object *)NULL);
+       if (v == NULL)
+               return NULL;
+       DECREF(v);
+       INCREF(m);
+
+       return m;
+}
+
+
+/* Given a pathname for a Python source file, fill a buffer with the
+   pathname for the corresponding compiled file.  Return the pathname
+   for the compiled file, or NULL if there's no space in the buffer.
+   Doesn't set an exception. */
+
+static char *
+make_compiled_pathname(pathname, buf, buflen)
+       char *pathname;
+       char *buf;
+       int buflen;
+{
+       int len;
+
+       len = strlen(pathname);
+       if (len+2 > buflen)
+               return NULL;
+       strcpy(buf, pathname);
+       strcpy(buf+len, "c");
+
+       return buf;
+}
+
+
+/* Given a pathname for a Python source file, its time of last
+   modification, and a pathname for a compiled file, check whether the
+   compiled file represents the same version of the source.  If so,
+   return a FILE pointer for the compiled file, positioned just after
+   the header; if not, return NULL.
+   Doesn't set an exception. */
+
+static FILE *
+check_compiled_module(pathname, mtime, cpathname)
+       char *pathname;
+       long mtime;
+       char *cpathname;
+{
+       FILE *fp;
+       long magic;
+       long pyc_mtime;
+
+       fp = fopen(cpathname, "rb");
+       if (fp == NULL)
+               return NULL;
+       magic = rd_long(fp);
+       if (magic != MAGIC) {
                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);
+                       fprintf(stderr, "# %s has bad magic\n", cpathname);
+               fclose(fp);
                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);
+       pyc_mtime = rd_long(fp);
+       if (pyc_mtime != mtime) {
+               if (verbose)
+                       fprintf(stderr, "# %s has bad mtime\n", cpathname);
+               fclose(fp);
                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 (verbose)
+               fprintf(stderr, "# %s matches %s\n", cpathname, pathname);
+       return fp;
+}
 
-               if(ret && rld_lookup(errorStream, funcname, &ptr))
-                       p = (dl_funcptr) ptr;
 
-               NXCloseMemory(errorStream, NX_FREEBUFFER);
+/* Read a code object from a file and check it for validity */
 
-               if(!ret)
-                       return NULL;
-       }
-#endif /* USE_RLD */
-#ifdef hpux
-       {
-               shl_t lib;
-               int flags;
+static codeobject *
+read_compiled_module(fp)
+       FILE *fp;
+{
+       object *co;
 
-               flags = BIND_DEFERRED;
-               if (verbose)
-                {
-                        flags = BIND_IMMEDIATE | BIND_NONFATAL | BIND_VERBOSE;
-                        printf("shl_load %s\n",namebuf);
-                }
-                lib = shl_load(namebuf, flags, 0);
-                if (lib == NULL)
-                {
-                        char buf[256];
-                        if (verbose)
-                                perror(namebuf);
-                        sprintf(buf, "Failed to load %.200s", namebuf);
-                        err_setstr(ImportError, buf);
-                        return NULL;
-                }
-                if (verbose)
-                        printf("shl_findsym %s\n", funcname);
-                shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p);
-                if (p == NULL && verbose)
-                        perror(funcname);
+       co = rd_object(fp);
+       /* Ugly: rd_object() may return NULL with or without error */
+       if (co == NULL || !is_codeobject(co)) {
+               if (!err_occurred())
+                       err_setstr(ImportError,
+                                  "Non-code object in .pyc file");
+               XDECREF(co);
+               return NULL;
        }
-#endif /* hpux */
-       if (p == NULL) {
-               err_setstr(ImportError,
-                  "dynamic module does not define init function");
+       return (codeobject *)co;
+}
+
+
+/* Load a module from a compiled file, execute it, and return its
+   module object */
+
+static object *
+load_compiled_module(name, cpathname, fp)
+       char *name;
+       char *cpathname;
+       FILE *fp;
+{
+       long magic;
+       codeobject *co;
+       object *m;
+
+       magic = rd_long(fp);
+       if (magic != MAGIC) {
+               err_setstr(ImportError, "Bad magic number in .pyc file");
                return NULL;
        }
-       (*p)();
+       (void) rd_long(fp);
+       co = read_compiled_module(fp);
+       if (co == NULL)
+               return NULL;
+       if (verbose)
+               fprintf(stderr, "import %s # precompiled from %s\n",
+                       name, cpathname);
+       m = exec_code_module(name, co);
+       DECREF(co);
+
+       return m;
+}
+
+
+/* Parse a source file and return the corresponding code object */
+
+static codeobject *
+parse_source_module(pathname, fp)
+       char *pathname;
+       FILE *fp;
+{
+       codeobject *co;
+       node *n;
 
-#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");
+       n = parse_file(fp, pathname, file_input);
+       if (n == NULL)
                return NULL;
+       co = compile(n, pathname);
+       freetree(n);
+
+       return co;
+}
+
+
+/* Write a compiled module to a file, placing the time of last
+   modification of its source into the header.
+   Errors are ignored, if a write error occurs an attempt is made to
+   remove the file. */
+
+static void
+write_compiled_module(co, cpathname, mtime)
+       codeobject *co;
+       char *cpathname;
+       long mtime;
+{
+       FILE *fp;
+
+       fp = fopen(cpathname, "wb");
+       if (fp == NULL) {
+               if (verbose)
+                       fprintf(stderr,
+                               "# can't create %s\n", cpathname);
+               return;
+       }
+       wr_long(MAGIC, fp);
+       /* First write a 0 for mtime */
+       wr_long(0L, fp);
+       wr_object((object *)co, fp);
+       if (ferror(fp)) {
+               if (verbose)
+                       fprintf(stderr, "# can't write %s\n", cpathname);
+               /* Don't keep partial file */
+               fclose(fp);
+               (void) unlink(cpathname);
+               return;
        }
+       /* Now write the true mtime */
+       fseek(fp, 4L, 0);
+       wr_long(mtime, fp);
+       fflush(fp);
+       fclose(fp);
        if (verbose)
-               fprintf(stderr,
-                       "import %s # dynamically loaded from %s\n",
-                       name, namebuf);
-       INCREF(None);
-       return None;
+               fprintf(stderr, "# wrote %s\n", cpathname);
+#ifdef macintosh
+       setfiletype(cpathname, 'PYTH', 'PYC ');
+#endif
 }
-#endif /* DYNAMIC_LINK */
+
+
+/* Load a source module from a given file and return its module
+   object.  If there's a matching byte-compiled file, use that
+   instead. */
 
 static object *
-get_module(m, name, m_ret)
-       /*module*/object *m;
+load_source_module(name, pathname, fp)
        char *name;
-       object **m_ret;
+       char *pathname;
+       FILE *fp;
 {
-       int err, npath, i, len, namelen;
-       long magic;
-       long mtime, pyc_mtime;
-       char namebuf[MAXPATHLEN+1];
+       long mtime;
+       FILE *fpc;
+       char buf[MAXPATHLEN+1];
+       char *cpathname;
+       codeobject *co;
+       object *m;
+
+       mtime = getmtime(pathname);
+       cpathname = make_compiled_pathname(pathname, buf, MAXPATHLEN+1);
+       if (cpathname != NULL &&
+           (fpc = check_compiled_module(pathname, mtime, cpathname))) {
+               co = read_compiled_module(fpc);
+               fclose(fpc);
+               if (co == NULL)
+                       return NULL;
+               if (verbose)
+                       fprintf(stderr, "import %s # precompiled from %s\n",
+                               name, cpathname);
+       }
+       else {
+               co = parse_source_module(pathname, fp);
+               if (co == NULL)
+                       return NULL;
+               if (verbose)
+                       fprintf(stderr, "import %s # from %s\n",
+                               name, pathname);
+               write_compiled_module(co, cpathname, mtime);
+       }
+       m = exec_code_module(name, co);
+       DECREF(co);
+
+       return m;
+}
+
+
+/* Search the path (default sys.path) for a module.  Return the
+   corresponding filedescr struct, and (via return arguments) the
+   pathname and an open file.  Return NULL if the module is not found. */
+
+static struct filedescr *
+find_module(name, path, buf, buflen, p_fp)
+       char *name;
+       object *path;
+       /* Output parameters: */
+       char *buf;
+       int buflen;
+       FILE **p_fp;
+{
+       int i, npath, len, namelen;
        struct filedescr *fdp;
-       FILE *fp = NULL, *fpc = NULL;
-       node *n = NULL;
-       object *path, *v, *d;
-       codeobject *co = NULL;
+       FILE *fp;
 
-       path = sysget("path");
+       if (path == NULL)
+               path = sysget("path");
        if (path == NULL || !is_listobject(path)) {
                err_setstr(ImportError,
-                          "sys.path must be list of directory names");
+                   "module search path must be list of directory names");
                return NULL;
        }
        npath = getlistsize(path);
        namelen = strlen(name);
        for (i = 0; i < npath; i++) {
-               v = getlistitem(path, i);
+               object *v = getlistitem(path, i);
                if (!is_stringobject(v))
                        continue;
                len = getstringsize(v);
-               if (len + 1 + namelen + MAXSUFFIXSIZE >= MAXPATHLEN)
+               if (len + 2 + namelen + import_maxsuffixsize >= buflen)
                        continue; /* Too long */
-               strcpy(namebuf, getstringvalue(v));
-               if (strlen(namebuf) != len)
+               strcpy(buf, getstringvalue(v));
+               if (strlen(buf) != len)
                        continue; /* v contains '\0' */
-               if (len > 0 && namebuf[len-1] != SEP)
-                       namebuf[len++] = SEP;
-               strcpy(namebuf+len, name);
+               if (len > 0 && buf[len-1] != SEP)
+                       buf[len++] = SEP;
+               strcpy(buf+len, name);
                len += namelen;
-               for (fdp = filetab; fdp->suffix != NULL; fdp++) {
-                       strcpy(namebuf+len, fdp->suffix);
+               for (fdp = import_filetab; fdp->suffix != NULL; fdp++) {
+                       strcpy(buf+len, fdp->suffix);
                        if (verbose > 1)
-                               fprintf(stderr, "# trying %s\n", namebuf);
-                       fp = fopen(namebuf, fdp->mode);
+                               fprintf(stderr, "# trying %s\n", buf);
+                       fp = fopen(buf, fdp->mode);
                        if (fp != NULL)
                                break;
                }
@@ -444,192 +435,164 @@ get_module(m, name, m_ret)
                        break;
        }
        if (fp == NULL) {
-               sprintf(namebuf, "No module named %.200s", name);
-               err_setstr(ImportError, namebuf);
+               char buf[256];
+               sprintf(buf, "No module named %.200s", name);
+               err_setstr(ImportError, buf);
                return NULL;
        }
 
+       *p_fp = fp;
+       return fdp;
+}
+
+
+/* Load an external module using the default search path and return
+   its module object */
+
+static object *
+load_module(name)
+       char *name;
+{
+       char buf[MAXPATHLEN+1];
+       struct filedescr *fdp;
+       FILE *fp = NULL;
+       object *m = NULL;
+
+       fdp = find_module(name, (object *)NULL, buf, MAXPATHLEN+1, &fp);
+       if (fdp == NULL)
+               return NULL;
+
        switch (fdp->type) {
 
        case PY_SOURCE:
-               mtime = getmtime(namebuf);
-               len = strlen(namebuf);
-               strcpy(namebuf + len, "c");
-               fpc = fopen(namebuf, "rb");
-               if (fpc != NULL) {
-                       magic = rd_long(fpc);
-                       if (magic != MAGIC) {
-                               if (verbose)
-                                       fprintf(stderr,
-                                               "# %s has bad magic\n",
-                                               namebuf);
-                       }
-                       else {
-                               pyc_mtime = rd_long(fpc);
-                               if (pyc_mtime != mtime) {
-                                       if (verbose)
-                                               fprintf(stderr,
-                                                 "# %s has bad mtime\n",
-                                                 namebuf);
-                               }
-                               else {
-                                       fclose(fp);
-                                       fp = fpc;
-                                       if (verbose)
-                                          fprintf(stderr,
-                                            "# %s matches %s.py\n",
-                                                  namebuf, name);
-                                       goto use_compiled;
-                               }
-                       }
-                       fclose(fpc);
-               }
-               namebuf[len] = '\0';
-               n = parse_file(fp, namebuf, file_input);
-               fclose(fp);
-               if (n == NULL)
-                       return NULL;
-               co = compile(n, namebuf);
-               freetree(n);
-               if (co == NULL)
-                       return NULL;
-               if (verbose)
-                       fprintf(stderr,
-                               "import %s # from %s\n", name, namebuf);
-               /* Now write the code object to the ".pyc" file */
-               strcpy(namebuf + len, "c");
-               fpc = fopen(namebuf, "wb");
-#ifdef macintosh
-               setfiletype(namebuf, 'PYTH', 'PYC ');
-#endif
-               if (fpc == NULL) {
-                       if (verbose)
-                               fprintf(stderr,
-                                       "# can't create %s\n", namebuf);
-               }
-               else {
-                       wr_long(MAGIC, fpc);
-                       /* First write a 0 for mtime */
-                       wr_long(0L, fpc);
-                       wr_object((object *)co, fpc);
-                       if (ferror(fpc)) {
-                               if (verbose)
-                                       fprintf(stderr,
-                                               "# can't write %s\n", namebuf);
-                               /* Don't keep partial file */
-                               fclose(fpc);
-                               (void) unlink(namebuf);
-                       }
-                       else {
-                               /* Now write the true mtime */
-                               fseek(fpc, 4L, 0);
-                               wr_long(mtime, fpc);
-                               fflush(fpc);
-                               fclose(fpc);
-                               if (verbose)
-                                       fprintf(stderr,
-                                               "# wrote %s\n", namebuf);
-                       }
-               }
+               m = load_source_module(name, buf, fp);
                break;
 
        case PY_COMPILED:
-               if (verbose)
-                       fprintf(stderr, "# %s without %s.py\n",
-                               namebuf, name);
-               magic = rd_long(fp);
-               if (magic != MAGIC) {
-                       err_setstr(ImportError,
-                                  "Bad magic number in .pyc file");
-                       return NULL;
-               }
-               (void) rd_long(fp);
-       use_compiled:
-               v = rd_object(fp);
-               fclose(fp);
-               if (v == NULL || !is_codeobject(v)) {
-                       XDECREF(v);
-                       err_setstr(ImportError,
-                                  "Bad code object in .pyc file");
-                       return NULL;
-               }
-               co = (codeobject *)v;
-               if (verbose)
-                       fprintf(stderr,
-                               "import %s # precompiled from %s\n",
-                               name, namebuf);
+               m = load_compiled_module(name, buf, fp);
                break;
 
-#ifdef DYNAMIC_LINK
        case C_EXTENSION:
-               fclose(fp);
-               return load_dynamic_module(name, namebuf, m, m_ret);
-#endif /* DYNAMIC_LINK */
+               m = load_dynamic_module(name, buf);
+               break;
 
        default:
-               fclose(fp);
                err_setstr(SystemError,
-                          "search loop returned unexpected result");
-               return NULL;
+                          "find_module returned unexpected result");
 
        }
+       fclose(fp);
 
-       /* We get here for either PY_SOURCE or PY_COMPILED */
-       if (m == NULL) {
-               m = add_module(name);
-               if (m == NULL) {
-                       freetree(n);
-                       return NULL;
+       return m;
+}
+
+
+/* Initialize a built-in module.
+   Return 1 for succes, 0 if the module is not found, and -1 with
+   an exception set if the initialization failed. */
+
+static int
+init_builtin(name)
+       char *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);
+                       (*inittab[i].initfunc)();
+                       if (err_occurred())
+                               return -1;
+                       return 1;
                }
-               *m_ret = m;
        }
-       d = getmoduledict(m);
-       v = eval_code(co, d, d, d, (object *)NULL);
-       DECREF(co);
-       return v;
+       return 0;
 }
 
-static object *
-load_module(name)
+
+/* Initialize a frozen module.
+   Return 1 for succes, 0 if the module is not found, and -1 with
+   an exception set if the initialization failed. */
+
+extern struct frozen {
+       char *name;
+       char *code;
+       int size;
+} frozen_modules[];
+
+static int
+init_frozen(name)
        char *name;
 {
-       object *m, *v;
-       v = get_module((object *)NULL, name, &m);
-       if (v == NULL)
-               return NULL;
-       DECREF(v);
-       return m;
+       struct frozen *p;
+       object *co;
+       object *m;
+       for (p = frozen_modules; ; p++) {
+               if (p->name == NULL)
+                       return 0;
+               if (strcmp(p->name, name) == 0)
+                       break;
+       }
+       if (verbose)
+               fprintf(stderr, "import %s # frozen\n", name);
+       co = rds_object(p->code, p->size);
+       if (co == NULL)
+               return -1;
+       if (!is_codeobject(co)) {
+               DECREF(co);
+               err_setstr(SystemError, "frozen object is not a code object");
+               return -1;
+       }
+       m = exec_code_module(name, (codeobject *)co);
+       DECREF(co);
+       return m == NULL ? -1 : 1;
 }
 
+
+/* Import a module, either built-in, frozen, or external, and return
+   its module object */
+
 object *
 import_module(name)
        char *name;
 {
        object *m;
-       int n;
-       if ((m = dictlookup(modules, name)) == NULL) {
-               if ((n = init_builtin(name)) || (n = init_frozen(name))) {
-                       if (n < 0)
+
+       if ((m = dictlookup(import_modules, name)) == NULL) {
+               int i;
+               if ((i = init_builtin(name)) || (i = init_frozen(name))) {
+                       if (i < 0)
                                return NULL;
-                       if ((m = dictlookup(modules, name)) == NULL) {
-                               if (err_occurred() == NULL)
-                                       err_setstr(SystemError,
-                                  "builtin module not initialized properly");
+                       if ((m = dictlookup(import_modules, name)) == NULL) {
+                           if (err_occurred() == NULL)
+                               err_setstr(SystemError,
+                                "built-in module not initialized properly");
                        }
                }
-               else {
+               else
                        m = load_module(name);
-               }
        }
+
        return m;
 }
 
+
+/* Re-import a module of any kind and return its module object, WITH
+   INCREMENTED REFERENCE COUNT */
+
 object *
 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;
@@ -637,158 +600,308 @@ reload_module(m)
        name = getmodulename(m);
        if (name == NULL)
                return NULL;
-       /* 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;
-               }
+       if (m != dictlookup(import_modules, name)) {
+               err_setstr(ImportError, "reload() module not in sys.modules");
+               return NULL;
        }
-       /* Check for frozen modules */
-       if ((i = init_frozen(name)) != 0) {
+       /* Check for built-in and frozen modules */
+       if ((i = init_builtin(name)) || (i = init_frozen(name))) {
                if (i < 0)
                        return NULL;
-               INCREF(None);
-               return None;
        }
-       return get_module(m, name, (object **)NULL);
+       else
+               m = load_module(name);
+       XINCREF(m);
+       return m;
 }
 
-void
-doneimport()
+
+/* Module 'imp' provides Python access to the primitives used for
+   importing modules.
+*/
+
+static object *
+imp_get_magic(self, args)
+       object *self;
+       object *args;
 {
-       if (modules != NULL) {
-               int pos;
-               object *modname, *module;
-               /* Explicitly erase all modules; this is the safest way
-                  to get rid of at least *some* circular dependencies */
-               pos = 0;
-               while (mappinggetnext(modules, &pos, &modname, &module)) {
-                       if (is_moduleobject(module)) {
-                               object *dict;
-                               dict = getmoduledict(module);
-                               if (dict != NULL && is_dictobject(dict))
-                                       mappingclear(dict);
-                       }
+       char buf[4];
+
+       if (!newgetargs(args, ""))
+               return NULL;
+       buf[0] = (MAGIC >>  0) & 0xff;
+       buf[1] = (MAGIC >>  8) & 0xff;
+       buf[3] = (MAGIC >> 16) & 0xff;
+       buf[4] = (MAGIC >> 24) & 0xff;
+
+       return newsizedstringobject(buf, 4);
+}
+
+static object *
+imp_get_suffixes(self, args)
+       object *self;
+       object *args;
+{
+       object *list;
+       struct filedescr *fdp;
+
+       if (!newgetargs(args, ""))
+               return NULL;
+       list = newlistobject(0);
+       if (list == NULL)
+               return NULL;
+       for (fdp = import_filetab; fdp->suffix != NULL; fdp++) {
+               object *item = mkvalue("ssi",
+                                      fdp->suffix, fdp->mode, fdp->type);
+               if (item == NULL) {
+                       DECREF(list);
+                       return NULL;
                }
-               mappingclear(modules);
+               if (addlistitem(list, item) < 0) {
+                       DECREF(list);
+                       DECREF(item);
+                       return NULL;
+               }
+               DECREF(item);
        }
-       DECREF(modules);
-       modules = NULL;
+       return list;
 }
 
+static object *
+imp_find_module(self, args)
+       object *self;
+       object *args;
+{
+       extern int fclose PROTO((FILE *));
+       char *name;
+       object *path = NULL;
+       object *fob, *ret;
+       struct filedescr *fdp;
+       char pathname[MAXPATHLEN+1];
+       FILE *fp;
+       if (!newgetargs(args, "s|O!", &name, &Listtype, &path))
+               return NULL;
+       fdp = find_module(name, path, pathname, MAXPATHLEN+1, &fp);
+       if (fdp == NULL)
+               return NULL;
+       fob = newopenfileobject(fp, pathname, fdp->mode, fclose);
+       if (fob == NULL) {
+               fclose(fp);
+               return NULL;
+       }
+       ret = mkvalue("Os(ssi)",
+                     fob, pathname, fdp->suffix, fdp->mode, fdp->type);
+       DECREF(fob);
+       return ret;
+}
 
-/* Initialize built-in modules when first imported */
+static object *
+imp_init_builtin(self, args)
+       object *self;
+       object *args;
+{
+       char *name;
+       int ret;
+       object *m;
+       if (!newgetargs(args, "s", &name))
+               return NULL;
+       ret = init_builtin(name);
+       if (ret < 0)
+               return NULL;
+       if (ret == 0) {
+               INCREF(None);
+               return None;
+       }
+       m = add_module(name);
+       XINCREF(m);
+       return m;
+}
 
-static int
-init_builtin(name)
+static object *
+imp_init_frozen(self, args)
+       object *self;
+       object *args;
+{
        char *name;
+       int ret;
+       object *m;
+       if (!newgetargs(args, "s", &name))
+               return NULL;
+       ret = init_frozen(name);
+       if (ret < 0)
+               return NULL;
+       if (ret == 0) {
+               INCREF(None);
+               return None;
+       }
+       m = add_module(name);
+       XINCREF(m);
+       return m;
+}
+
+static object *
+imp_is_builtin(self, args)
+       object *self;
+       object *args;
 {
        int i;
+       char *name;
+       if (!newgetargs(args, "s", &name))
+               return NULL;
        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);
-                       (*inittab[i].initfunc)();
-                       return 1;
+                       if (inittab[i].initfunc == NULL)
+                               return newintobject(-1);
+                       else
+                               return newintobject(1);
                }
        }
-       return 0;
+       return newintobject(0);
 }
 
-extern struct frozen {
-       char *name;
-       char *code;
-       int size;
-} frozen_modules[];
-
-int
-init_frozen(name)
-       char *name;
+static object *
+imp_is_frozen(self, args)
+       object *self;
+       object *args;
 {
        struct frozen *p;
-       codeobject *co;
-       object *m, *d, *v;
+       char *name;
+       if (!newgetargs(args, "s", &name))
+               return NULL;
        for (p = frozen_modules; ; p++) {
                if (p->name == NULL)
-                       return 0;
-               if (strcmp(p->name, name) == 0)
                        break;
+               if (strcmp(p->name, name) == 0)
+                       return newintobject(1);
        }
-       if (verbose)
-               fprintf(stderr, "import %s # frozen\n", name);
-       co = (codeobject *) rds_object(p->code, p->size);
-       if (co == NULL)
-               return -1;
-       if ((m = add_module(name)) == NULL ||
-           (d = getmoduledict(m)) == NULL ||
-           (v = eval_code(co, d, d, d, (object*)NULL)) == NULL) {
-               DECREF(co);
-               return -1;
+       return newintobject(0);
+}
+
+static FILE *
+get_file(pathname, fob, mode)
+       char *pathname;
+       object *fob;
+       char *mode;
+{
+       FILE *fp;
+       if (fob == NULL) {
+               fp = fopen(pathname, mode);
+               if (fp == NULL)
+                       err_errno(IOError);
        }
-       DECREF(co);
-       DECREF(v);
-       return 1;
+       else {
+               fp = getfilefile(fob);
+               if (fp == NULL)
+                       err_setstr(ValueError, "bad/closed file object");
+       }
+       return fp;
 }
 
+static object *
+imp_load_compiled(self, args)
+       object *self;
+       object *args;
+{
+       char *name;
+       char *pathname;
+       object *fob = NULL;
+       object *m;
+       FILE *fp;
+       if (!newgetargs(args, "ss|O!", &name, &pathname, &Filetype, &fob))
+               return NULL;
+       fp = get_file(pathname, fob, "rb");
+       if (fp == NULL)
+               return NULL;
+       m = load_compiled_module(name, pathname, fp);
+       if (fob == NULL)
+               fclose(fp);
+       return m;
+}
 
-#ifdef _AIX
+static object *
+imp_load_dynamic(self, args)
+       object *self;
+       object *args;
+{
+       char *name;
+       char *pathname;
+       object *dummy;
+       if (!newgetargs(args, "ss|O", &name, &pathname, &dummy))
+               return NULL;
+       return load_dynamic_module(name, pathname);
+}
 
-#include <ctype.h>     /* for isdigit()        */
-#include <errno.h>     /* for global errno     */
-#include <string.h>    /* for strerror()       */
+static object *
+imp_load_source(self, args)
+       object *self;
+       object *args;
+{
+       char *name;
+       char *pathname;
+       object *fob = NULL;
+       object *m;
+       FILE *fp;
+       if (!newgetargs(args, "ss|O!", &name, &pathname, &Filetype, &fob))
+               return NULL;
+       fp = get_file(pathname, fob, "r");
+       if (fp == NULL)
+               return NULL;
+       m = load_source_module(name, pathname, fp);
+       if (fob == NULL)
+               fclose(fp);
+       return m;
+}
 
-void aix_loaderror(char *namebuf)
+static object *
+imp_new_module(self, args)
+       object *self;
+       object *args;
 {
+       char *name;
+       if (!newgetargs(args, "s", &name))
+               return NULL;
+       return newmoduleobject(name);
+}
 
-       char *message[8], errbuf[1024];
-       int i,j;
+static struct methodlist imp_methods[] = {
+       {"get_magic",           imp_get_magic,          1},
+       {"get_suffixes",        imp_get_suffixes,       1},
+       {"find_module",         imp_find_module,        1},
+       {"init_builtin",        imp_init_builtin,       1},
+       {"init_frozen",         imp_init_frozen,        1},
+       {"is_builtin",          imp_is_builtin,         1},
+       {"is_frozen",           imp_is_frozen,          1},
+       {"load_compiled",       imp_load_compiled,      1},
+       {"load_dynamic",        imp_load_dynamic,       1},
+       {"load_source",         imp_load_source,        1},
+       {"new_module",          imp_new_module,         1},
+       {NULL,                  NULL}           /* sentinel */
+};
 
-       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}
-       };
+void
+initimp()
+{
+       object *m, *d, *v;
 
-#define LOAD_ERRTAB_LEN        (sizeof(load_errtab)/sizeof(load_errtab[0]))
-#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1)
+       m = initmodule("imp", imp_methods);
+       d = getmoduledict(m);
 
-       sprintf(errbuf, " from module %.200s ", namebuf);
+       v = newintobject(SEARCH_ERROR);
+       dictinsert(d, "SEARCH_ERROR", v);
+       XDECREF(v);
 
-       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; 
-}
+       v = newintobject(PY_SOURCE);
+       dictinsert(d, "PY_SOURCE", v);
+       XDECREF(v);
 
-#endif /* _AIX */
+       v = newintobject(PY_COMPILED);
+       dictinsert(d, "PY_COMPILED", v);
+       XDECREF(v);
+
+       v = newintobject(C_EXTENSION);
+       dictinsert(d, "C_EXTENSION", v);
+       XDECREF(v);
+
+       if (err_occurred())
+               fatal("imp module initialization failed");
+}
diff --git a/Python/importdl.c b/Python/importdl.c
new file mode 100644 (file)
index 0000000..f377c61
--- /dev/null
@@ -0,0 +1,381 @@
+/***********************************************************
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
+Amsterdam, The Netherlands.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its 
+documentation for any purpose and without fee is hereby granted, 
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in 
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Support for dynamic loading of extension modules */
+/* If no dynamic linking is supported, this file still generates some code! */
+
+#include "allobjects.h"
+#include "osdefs.h"
+#include "importdl.h"
+
+extern int verbose; /* Defined in pythonrun.c */
+
+/* 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"
+   hpux                -- HP-UX Dynamic Linking - defined by the compiler
+
+   (The other WITH_* symbols are used only once, to set the
+   appropriate symbols.)
+*/
+
+/* Configure dynamic linking */
+
+#ifdef hpux
+#define DYNAMIC_LINK
+#include <errno.h>
+typedef void (*dl_funcptr)();
+#define _DL_FUNCPTR_DEFINED 1
+#define SHORT_EXT ".sl"
+#define LONG_EXT "module.sl"
+#endif 
+
+#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)();
+#endif
+#ifndef RTLD_LAZY
+#define RTLD_LAZY 1
+#endif
+#define SHORT_EXT ".so"
+#define LONG_EXT "module.so"
+#endif /* USE_SHLIB */
+
+#if defined(USE_DL) || defined(hpux)
+#include "dl.h"
+#endif
+
+#ifdef WITH_MAC_DL
+#include "dynamic_load.h"
+#endif
+
+#ifdef USE_RLD
+#include <mach-o/rld.h>
+#define FUNCNAME_PATTERN "_init%.200s"
+#ifndef _DL_FUNCPTR_DEFINED
+typedef void (*dl_funcptr)();
+#endif
+#endif /* USE_RLD */
+
+extern char *getprogramname();
+
+#ifndef FUNCNAME_PATTERN
+#if defined(__hp9000s300)
+#define FUNCNAME_PATTERN "_init%.200s"
+#else
+#define FUNCNAME_PATTERN "init%.200s"
+#endif
+#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 */
+
+/* Max length of module suffix searched for -- accommodates "module.so" */
+#ifndef MAXSUFFIXSIZE
+#define MAXSUFFIXSIZE 10
+#endif
+
+/* Pass it on to import.c */
+int import_maxsuffixsize = MAXSUFFIXSIZE;
+
+struct filedescr import_filetab[] = {
+#ifdef SHORT_EXT
+       {SHORT_EXT, "rb", C_EXTENSION},
+#endif /* !SHORT_EXT */
+#ifdef LONG_EXT
+       {LONG_EXT, "rb", C_EXTENSION},
+#endif /* !LONG_EXT */
+       {".py", "r", PY_SOURCE},
+       {".pyc", "rb", PY_COMPILED},
+       {0, 0}
+};
+
+object *
+load_dynamic_module(name, pathname)
+       char *name;
+       char *pathname;
+{
+#ifndef DYNAMIC_LINK
+       err_setstr(ImportError, "dynamically linked modules not supported");
+       return NULL;
+#else
+       object *m;
+       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(pathname);
+               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(pathname, RTLD_NOW);
+#else
+               void *handle;
+               if (verbose)
+                       printf("dlopen(\"%s\", %d);\n", pathname, RTLD_LAZY);
+               handle = dlopen(pathname, 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(pathname, 1, 0);
+       if (p == NULL) {
+               aix_loaderror(pathname);
+               return NULL;
+       }
+#endif /* _AIX */
+#ifdef NT
+       {
+               HINSTANCE hDLL;
+               hDLL = LoadLibrary(pathname);
+               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(), pathname, 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] = pathname;
+               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 */
+#ifdef hpux
+       {
+               shl_t lib;
+               int flags;
+
+               flags = BIND_DEFERRED;
+               if (verbose)
+                {
+                        flags = BIND_IMMEDIATE | BIND_NONFATAL | BIND_VERBOSE;
+                        printf("shl_load %s\n",pathname);
+                }
+                lib = shl_load(pathname, flags, 0);
+                if (lib == NULL)
+                {
+                        char buf[256];
+                        if (verbose)
+                                perror(pathname);
+                        sprintf(buf, "Failed to load %.200s", pathname);
+                        err_setstr(ImportError, buf);
+                        return NULL;
+                }
+                if (verbose)
+                        printf("shl_findsym %s\n", funcname);
+                shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p);
+                if (p == NULL && verbose)
+                        perror(funcname);
+       }
+#endif /* hpux */
+       if (p == NULL) {
+               err_setstr(ImportError,
+                  "dynamic module does not define init function");
+               return NULL;
+       }
+       (*p)();
+
+#endif /* !WITH_MAC_DL */
+       m = dictlookup(import_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, pathname);
+       INCREF(m);
+       return m;
+#endif /* DYNAMIC_LINK */
+}
+
+
+#ifdef _AIX
+
+#include <ctype.h>     /* for isdigit()        */
+#include <errno.h>     /* for global errno     */
+#include <string.h>    /* for strerror()       */
+
+void aix_loaderror(char *pathname)
+{
+
+       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)-strlen(errbuf)-1)
+
+       sprintf(errbuf, " from module %.200s ", pathname);
+
+       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 */
diff --git a/Python/importdl.h b/Python/importdl.h
new file mode 100644 (file)
index 0000000..c90608e
--- /dev/null
@@ -0,0 +1,39 @@
+/***********************************************************
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
+Amsterdam, The Netherlands.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its 
+documentation for any purpose and without fee is hereby granted, 
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in 
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Definitions for dynamic loading of extension modules */
+
+enum filetype {SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION};
+
+extern struct filedescr {
+       char *suffix;
+       char *mode;
+       enum filetype type;
+} import_filetab[];
+
+extern object *import_modules;
+
+extern object *load_dynamic_module PROTO((char *name, char *pathname));
+
+extern int import_maxsuffixsize;
index 96c530a78afa8360e8a03416d5b43769a78625f9..48612b094e223e996e8fcc524f2ff0cad8856815 100644 (file)
@@ -406,6 +406,10 @@ rd_object(fp)
        FILE *fp;
 {
        RFILE rf;
+       if (err_occurred()) {
+               fprintf(stderr, "XXX rd_object called with exception set\n");
+               return NULL;
+       }
        rf.fp = fp;
        return r_object(&rf);
 }
@@ -416,6 +420,10 @@ rds_object(str, len)
        int len;
 {
        RFILE rf;
+       if (err_occurred()) {
+               fprintf(stderr, "XXX rds_object called with exception set\n");
+               return NULL;
+       }
        rf.fp = NULL;
        rf.str = NULL;
        rf.ptr = str;
index ae9a838580b6bdb42091c8a8f13bd88251980df0..2952189f0f815c03f4a9630aa05ec9afdcfdb4d1 100644 (file)
@@ -29,7 +29,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #ifdef MPW /* MPW pushes 'extended' for float and double types with varargs */
 typedef extended va_double;
-#else 
+#else
 typedef double va_double;
 #endif
 
@@ -42,7 +42,7 @@ object *
 initmodule2(name, methods, passthrough)
        char *name;
        struct methodlist *methods;
-       object *passthrough; 
+       object *passthrough;
 {
        object *m, *d, *v;
        struct methodlist *ml;
@@ -58,7 +58,7 @@ initmodule2(name, methods, passthrough)
                        fatal("out of mem for method name");
                sprintf(namebuf, "%s.%s", name, ml->ml_name);
                v = newmethodobject(namebuf, ml->ml_meth,
-                                       (object *)passthrough, ml->ml_varargs);
+                                   (object *)passthrough, ml->ml_varargs);
                /* XXX The malloc'ed memory in namebuf is never freed */
                if (v == NULL || dictinsert(d, ml->ml_name, v) != 0) {
                        fprintf(stderr, "initializing module: %s\n", name);
@@ -90,20 +90,33 @@ static int countformat(format, endchar)
        int count = 0;
        int level = 0;
        while (level > 0 || *format != endchar) {
-               if (*format == '\0') {
+               switch (*format) {
+               case '\0':
                        /* Premature end */
                        err_setstr(SystemError, "unmatched paren in format");
                        return -1;
-               }
-               else if (*format == '(') {
+               case '(':
+               case '[':
+               case '{':
                        if (level == 0)
                                count++;
                        level++;
-               }
-               else if (*format == ')')
+                       break;
+               case ')':
+               case ']':
+               case '}':
                        level--;
-               else if (level == 0 && *format != '#')
-                       count++;
+                       break;
+               case '#':
+               case ',':
+               case ':':
+               case ' ':
+               case '\t':
+                       break;
+               default:
+                       if (level == 0)
+                               count++;
+               }
                format++;
        }
        return count;
@@ -114,8 +127,85 @@ static int countformat(format, endchar)
 /* After an original idea and first implementation by Steven Miale */
 
 static object *do_mktuple PROTO((char**, va_list *, int, int));
+static object *do_mklist PROTO((char**, va_list *, int, int));
+static object *do_mkdict PROTO((char**, va_list *, int, int));
 static object *do_mkvalue PROTO((char**, va_list *));
 
+
+static object *
+do_mkdict(p_format, p_va, endchar, n)
+       char **p_format;
+       va_list *p_va;
+       int endchar;
+       int n;
+{
+       object *d;
+       int i;
+       if (n < 0)
+               return NULL;
+       if ((d = newdictobject()) == NULL)
+               return NULL;
+       for (i = 0; i < n; i+= 2) {
+               object *k, *v;
+               k = do_mkvalue(p_format, p_va);
+               if (k == NULL) {
+                       DECREF(d);
+                       return NULL;
+               }
+               v = do_mkvalue(p_format, p_va);
+               if (v == NULL) {
+                       DECREF(k);
+                       DECREF(d);
+                       return NULL;
+               }
+               if (dict2insert(d, k, v) < 0) {
+                       DECREF(k);
+                       DECREF(v);
+                       DECREF(d);
+                       return NULL;
+               }
+       }
+       if (d != NULL && **p_format != endchar) {
+               DECREF(d);
+               d = NULL;
+               err_setstr(SystemError, "Unmatched paren in format");
+       }
+       else if (endchar)
+               ++*p_format;
+       return d;
+}
+
+static object *
+do_mklist(p_format, p_va, endchar, n)
+       char **p_format;
+       va_list *p_va;
+       int endchar;
+       int n;
+{
+       object *v;
+       int i;
+       if (n < 0)
+               return NULL;
+       if ((v = newlistobject(n)) == NULL)
+               return NULL;
+       for (i = 0; i < n; i++) {
+               object *w = do_mkvalue(p_format, p_va);
+               if (w == NULL) {
+                       DECREF(v);
+                       return NULL;
+               }
+               setlistitem(v, i, w);
+       }
+       if (v != NULL && **p_format != endchar) {
+               DECREF(v);
+               v = NULL;
+               err_setstr(SystemError, "Unmatched paren in format");
+       }
+       else if (endchar)
+               ++*p_format;
+       return v;
+}
+
 static object *
 do_mktuple(p_format, p_va, endchar, n)
        char **p_format;
@@ -152,34 +242,41 @@ do_mkvalue(p_format, p_va)
        char **p_format;
        va_list *p_va;
 {
-       
-       switch (*(*p_format)++) {
-       
-       case '(':
-               return do_mktuple(p_format, p_va, ')',
-                                 countformat(*p_format, ')'));
-               
-       case 'b':
-       case 'h':
-       case 'i':
-               return newintobject((long)va_arg(*p_va, int));
-               
-       case 'l':
-               return newintobject((long)va_arg(*p_va, long));
-               
-       case 'f':
-       case 'd':
-               return newfloatobject((double)va_arg(*p_va, va_double));
-               
-       case 'c':
+       for (;;) {
+               switch (*(*p_format)++) {
+               case '(':
+                       return do_mktuple(p_format, p_va, ')',
+                                         countformat(*p_format, ')'));
+
+               case '[':
+                       return do_mklist(p_format, p_va, ']',
+                                        countformat(*p_format, ']'));
+
+               case '{':
+                       return do_mkdict(p_format, p_va, '}',
+                                        countformat(*p_format, '}'));
+
+               case 'b':
+               case 'h':
+               case 'i':
+                       return newintobject((long)va_arg(*p_va, int));
+
+               case 'l':
+                       return newintobject((long)va_arg(*p_va, long));
+
+               case 'f':
+               case 'd':
+                       return newfloatobject((double)va_arg(*p_va, double));
+
+               case 'c':
                {
                        char p[1];
                        p[0] = va_arg(*p_va, int);
                        return newsizedstringobject(p, 1);
                }
-       
-       case 's':
-       case 'z':
+
+               case 's':
+               case 'z':
                {
                        object *v;
                        char *str = va_arg(*p_va, char *);
@@ -201,33 +298,44 @@ do_mkvalue(p_format, p_va)
                        }
                        return v;
                }
-       
-       case 'S':
-       case 'O':
+
+               case 'S':
+               case 'O':
                {
                        object *v;
                        v = va_arg(*p_va, object *);
                        if (v != NULL)
                                INCREF(v);
                        else if (!err_occurred())
-                               /* If a NULL was passed because a call
-                                  that should have constructed a value
-                                  failed, that's OK, and we pass the error
-                                  on; but if no error occurred it's not
-                                  clear that the caller knew what she
-                                  was doing. */
+                               /* If a NULL was passed
+                                * because a call that should
+                                * have constructed a value
+                                * failed, that's OK, and we
+                                * pass the error on; but if
+                                * no error occurred it's not
+                                * clear that the caller knew
+                                * what she was doing. */
                                err_setstr(SystemError,
                                           "NULL object passed to mkvalue");
                        return v;
                }
-       
-       default:
-               err_setstr(SystemError, "bad format char passed to mkvalue");
-               return NULL;
-       
+
+               case ':':
+               case ',':
+               case ' ':
+               case '\t':
+                       break;
+
+               default:
+                       err_setstr(SystemError,
+                                  "bad format char passed to mkvalue");
+                       return NULL;
+
+               }
        }
 }
 
+
 #ifdef HAVE_STDARG_PROTOTYPES
 /* VARARGS 2 */
 object *mkvalue(char *format, ...)
@@ -257,6 +365,14 @@ vmkvalue(format, va)
 {
        char *f = format;
        int n = countformat(f, '\0');
+       va_list lva;
+
+#ifdef VA_LIST_IS_ARRAY
+       memcpy(lva, va, sizeof(va_list));
+#else
+       lva = va;
+#endif
+
        if (n < 0)
                return NULL;
        if (n == 0) {
@@ -264,6 +380,83 @@ vmkvalue(format, va)
                return None;
        }
        if (n == 1)
-               return do_mkvalue(&f, &va);
-       return do_mktuple(&f, &va, '\0', n);
+               return do_mkvalue(&f, &lva);
+       return do_mktuple(&f, &lva, '\0', n);
+}
+
+
+#ifdef HAVE_STDARG_PROTOTYPES
+object *
+PyEval_CallFunction(object *obj, char *format, ...)
+#else
+object *
+PyEval_CallFunction(obj, format, va_alist)
+       object *obj;
+       char *format;
+       va_dcl
+#endif
+{
+       va_list vargs;
+       object *args;
+       object *res;
+
+#ifdef HAVE_STDARG_PROTOTYPES
+       va_start(vargs, format);
+#else
+       va_start(vargs);
+#endif
+
+       args = vmkvalue(format, vargs);
+       va_end(vargs);
+
+       if (args == NULL)
+               return NULL;
+
+       res = call_object(obj, args);
+       DECREF(args);
+
+       return res;
+}
+
+
+#ifdef HAVE_STDARG_PROTOTYPES
+object *
+PyEval_CallMethod(object *obj, char *method, char *format, ...)
+#else
+object *
+PyEval_CallMethod(obj, method, format, va_alist)
+       object *obj;
+       char *method;
+       char *format;
+       va_dcl
+#endif
+{
+       va_list vargs;
+       object *meth;
+       object *args;
+       object *res;
+
+       meth = getattr(obj, method);
+       if (meth == NULL)
+               return NULL;
+
+#ifdef HAVE_STDARG_PROTOTYPES
+       va_start(vargs, format);
+#else
+       va_start(vargs);
+#endif
+
+       args = vmkvalue(format, vargs);
+       va_end(vargs);
+
+       if (args == NULL) {
+               DECREF(meth);
+               return NULL;
+       }
+
+       res = call_object(meth, args);
+       DECREF(meth);
+       DECREF(args);
+
+       return res;
 }
index de0de072febda58c85d67e56fae10f1c4c9eae6d..f66c8d738ad059ec9ae66ea84bec6f1f0f7facb3 100644 (file)
@@ -242,12 +242,10 @@ run_command(command)
 void
 print_error()
 {
-       object *exception, *v, *f;
-       err_get(&exception, &v);
-       if (exception == NULL) {
-               fprintf(stderr, "print_error called but no exception\n");
-               abort();
-       }
+       object *exception, *v, *tb, *f;
+       err_fetch(&exception, &v, &tb);
+       if (exception == NULL)
+               fatal("print_error called but no exception");
        if (exception == SystemExit) {
                if (v == NULL || v == None)
                        goaway(0);
@@ -262,11 +260,12 @@ print_error()
        }
        sysset("last_type", exception);
        sysset("last_value", v);
+       sysset("last_traceback", tb);
        f = sysget("stderr");
        if (f == NULL)
                fprintf(stderr, "lost sys.stderr\n");
        else {
-               printtraceback(f);
+               tb_print(tb, f);
                if (exception == SyntaxError) {
                        object *message;
                        char *filename, *text;
@@ -331,6 +330,7 @@ print_error()
        }
        XDECREF(exception);
        XDECREF(v);
+       XDECREF(tb);
 }
 
 object *
@@ -421,7 +421,6 @@ compile_string(str, filename, start)
        int start;
 {
        node *n;
-       int err;
        codeobject *co;
        n = parse_string(str, start);
        if (n == NULL)
index 509b819acbe285ae53d1a2c49f4402b3221036a7..4cb16585bc1b5e0187c716a293969066a42e17e0 100644 (file)
@@ -204,7 +204,8 @@ initsys()
        XDECREF(v);
        dictinsert(sysdict, "modules", get_modules());
        dictinsert(sysdict, "builtin_module_names",
-                  list_builtin_module_names());
+                  v = list_builtin_module_names());
+       XDECREF(v);
        if (err_occurred())
                fatal("can't insert sys.* objects in sys dict");
 }
index 8bbbeb09da565854c96d13f8c3dbec045fd5bd45..97be126c5f903cf785d86219d7c0107f7b6bd978 100644 (file)
@@ -68,7 +68,7 @@ int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
        funcarg = (struct func_arg *) malloc(sizeof(struct func_arg));
        funcarg->func = func;
        funcarg->arg = arg;
-       if (thr_create(0, 0, new_func, funcarg, THR_NEW_LWP, 0)) {
+       if (thr_create(0, 0, new_func, funcarg, THR_DETACHED, 0)) {
                perror("thr_create");
                free((void *) funcarg);
                success = -1;
index 1db9c941ccebb33563ba568f6939f265497d69ac..414fc8d26daa4a20af2f1ebdab6d1954c1c41ce2 100644 (file)
@@ -258,7 +258,6 @@ tb_print(v, f)
                err_badcall();
                return -1;
        }
-       sysset("last_traceback", v);
        limitv = sysget("tracebacklimit");
        if (limitv && is_intobject(limitv)) {
                limit = getintvalue(limitv);