From 1ae940a5870df2f706fa884afd533847f6b0b1a8 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Mon, 2 Jan 1995 19:04:15 +0000 Subject: Lots of changes, most minor (fatal() instead of abort(), use of 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. --- Python/Makefile.in | 7 +- Python/bltinmodule.c | 611 +++++++++++------------ Python/ceval.c | 106 ++-- Python/compile.c | 8 +- Python/errors.c | 27 +- Python/getargs.c | 24 +- Python/import.c | 1249 ++++++++++++++++++++++++++--------------------- Python/importdl.c | 381 +++++++++++++++ Python/importdl.h | 39 ++ Python/marshal.c | 8 + Python/modsupport.c | 291 +++++++++-- Python/pythonrun.c | 15 +- Python/sysmodule.c | 3 +- Python/thread_solaris.h | 2 +- Python/traceback.c | 1 - 15 files changed, 1777 insertions(+), 995 deletions(-) create mode 100644 Python/importdl.c create mode 100644 Python/importdl.h diff --git a/Python/Makefile.in b/Python/Makefile.in index 54be6af..d5ced26 100644 --- a/Python/Makefile.in +++ b/Python/Makefile.in @@ -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 diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 4f6c852..39dcc41 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -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; diff --git a/Python/ceval.c b/Python/ceval.c index 26b3ce3..2a3fe7b 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -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 @@ -1724,18 +1734,6 @@ getframe() } void -printtraceback(f) - object *f; -{ - object *v = tb_fetch(); - if (v != NULL) { - tb_print(v, f); - DECREF(v); - } -} - - -void flushline() { object *f = sysget("stdout"); @@ -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; diff --git a/Python/compile.c b/Python/compile.c index b3b610a..dbc6314 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -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); } diff --git a/Python/errors.c b/Python/errors.c index bb3b605..9b0a8d2 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -60,6 +60,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include +#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 diff --git a/Python/getargs.c b/Python/getargs.c index 15cd4e6..1232fd0 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -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); diff --git a/Python/import.c b/Python/import.c index ea6a6fe..a0af050 100644 --- a/Python/import.c +++ b/Python/import.c @@ -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 -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 -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 -typedef void (*dl_funcptr)(); -#define _DL_FUNCPTR_DEFINED -static void aix_loaderror(char *name); -#endif - -#ifdef DYNAMIC_LINK - -#ifdef USE_SHLIB -#include -#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 -#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 /* for isdigit() */ -#include /* for global errno */ -#include /* 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 +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 +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 +typedef void (*dl_funcptr)(); +#define _DL_FUNCPTR_DEFINED +static void aix_loaderror(char *name); +#endif + +#ifdef DYNAMIC_LINK + +#ifdef USE_SHLIB +#include +#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 +#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 /* for isdigit() */ +#include /* for global errno */ +#include /* 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; jml_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; } diff --git a/Python/pythonrun.c b/Python/pythonrun.c index de0de07..f66c8d7 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -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) diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 509b819..4cb1658 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -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"); } diff --git a/Python/thread_solaris.h b/Python/thread_solaris.h index 8bbbeb0..97be126 100644 --- a/Python/thread_solaris.h +++ b/Python/thread_solaris.h @@ -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; diff --git a/Python/traceback.c b/Python/traceback.c index 1db9c94..414fc8d 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -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); -- cgit v0.12