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.
This commit is contained in:
Guido van Rossum 1995-01-02 19:04:15 +00:00
parent 824de25fe2
commit 1ae940a587
15 changed files with 1871 additions and 1089 deletions

View file

@ -35,7 +35,7 @@ OBJS= \
errors.o \ errors.o \
frozenmain.o \ frozenmain.o \
getargs.o getmtime.o graminit.o \ getargs.o getmtime.o graminit.o \
import.o \ import.o importdl.o \
marshal.o modsupport.o mystrtoul.o \ marshal.o modsupport.o mystrtoul.o \
pythonmain.o pythonrun.o \ pythonmain.o pythonrun.o \
sigcheck.o structmember.o sysmodule.o \ sigcheck.o structmember.o sysmodule.o \
@ -66,8 +66,8 @@ Makefile: $(srcdir)/Makefile.in ../config.status
(cd ..; CONFIG_FILES=Python/Makefile CONFIG_HEADERS= \ (cd ..; CONFIG_FILES=Python/Makefile CONFIG_HEADERS= \
$(SHELL) config.status) $(SHELL) config.status)
import.o: import.c importdl.o: importdl.c
$(CC) $(CFLAGS) -I$(DLINCLDIR) -c $(srcdir)/import.c $(CC) $(CFLAGS) -I$(DLINCLDIR) -c $(srcdir)/importdl.c
depend: depend:
$(MKDEP) $(CFLAGS) `echo $(OBJS) | tr ' ' '\012' | \ $(MKDEP) $(CFLAGS) `echo $(OBJS) | tr ' ' '\012' | \
@ -88,6 +88,7 @@ getcwd.o: getcwd.c
getmtime.o: getmtime.c getmtime.o: getmtime.c
graminit.o: graminit.c graminit.o: graminit.c
import.o: import.c import.o: import.c
importdl.o: importdl.c
marshal.o: marshal.c marshal.o: marshal.c
memmove.o: memmove.c memmove.o: memmove.c
modsupport.o: modsupport.c modsupport.o: modsupport.c

View file

@ -40,15 +40,35 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* Forward */ /* Forward */
static object *filterstring PROTO((object *, object *)); static object *filterstring PROTO((object *, object *));
static object *filtertuple PROTO((object *, object *)); static object *filtertuple PROTO((object *, object *));
static object *exec_eval PROTO((object *v, int start));
static object * static object *
builtin_abs(self, v) builtin___import__(self, args)
object *self; 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; 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"); err_setstr(TypeError, "abs() requires numeric argument");
return NULL; return NULL;
} }
@ -61,7 +81,8 @@ builtin_apply(self, args)
object *args; object *args;
{ {
object *func, *arglist; object *func, *arglist;
if (!getargs(args, "(OO)", &func, &arglist))
if (!newgetargs(args, "OO:apply", &func, &arglist))
return NULL; return NULL;
if (!is_tupleobject(arglist)) { if (!is_tupleobject(arglist)) {
err_setstr(TypeError, "apply() 2nd argument must be tuple"); err_setstr(TypeError, "apply() 2nd argument must be tuple");
@ -101,12 +122,11 @@ builtin_callable(self, args)
object *self; object *self;
object *args; object *args;
{ {
if (args == NULL) { object *v;
err_setstr(TypeError,
"callable requires exactly one argument"); if (!newgetargs(args, "O:callable", &v))
return NULL; return NULL;
} return newintobject((long)callable(v));
return newintobject((long)callable(args));
} }
static object * static object *
@ -119,7 +139,7 @@ builtin_filter(self, args)
int len; int len;
register int i, j; register int i, j;
if (!getargs(args, "(OO)", &func, &seq)) if (!newgetargs(args, "OO:filter", &func, &seq))
return NULL; return NULL;
if (is_stringobject(seq)) { if (is_stringobject(seq)) {
@ -212,7 +232,8 @@ builtin_chr(self, args)
{ {
long x; long x;
char s[1]; char s[1];
if (!getargs(args, "l", &x))
if (!newgetargs(args, "l:chr", &x))
return NULL; return NULL;
if (x < 0 || x >= 256) { if (x < 0 || x >= 256) {
err_setstr(ValueError, "chr() arg not in range(256)"); err_setstr(ValueError, "chr() arg not in range(256)");
@ -228,7 +249,8 @@ builtin_cmp(self, args)
object *args; object *args;
{ {
object *a, *b; object *a, *b;
if (!getargs(args, "(OO)", &a, &b))
if (!newgetargs(args, "OO:cmp", &a, &b))
return NULL; return NULL;
return newintobject((long)cmpobject(a, b)); return newintobject((long)cmpobject(a, b));
} }
@ -241,7 +263,7 @@ builtin_coerce(self, args)
object *v, *w; object *v, *w;
object *res; object *res;
if (!getargs(args, "(OO)", &v, &w)) if (!newgetargs(args, "OO:coerce", &v, &w))
return NULL; return NULL;
if (is_instanceobject(v) || is_instanceobject(w)) if (is_instanceobject(v) || is_instanceobject(w))
return instancebinop(v, w, "__coerce__", "__rcoerce__"); return instancebinop(v, w, "__coerce__", "__rcoerce__");
@ -262,7 +284,8 @@ builtin_compile(self, args)
char *filename; char *filename;
char *startstr; char *startstr;
int start; int start;
if (!getargs(args, "(sss)", &str, &filename, &startstr))
if (!newgetargs(args, "sss:compile", &str, &filename, &startstr))
return NULL; return NULL;
if (strcmp(startstr, "exec") == 0) if (strcmp(startstr, "exec") == 0)
start = file_input; start = file_input;
@ -277,11 +300,15 @@ builtin_compile(self, args)
} }
static object * static object *
builtin_dir(self, v) builtin_dir(self, args)
object *self; object *self;
object *v; object *args;
{ {
object *v = NULL;
object *d; object *d;
if (!newgetargs(args, "|O:dir", &v))
return NULL;
if (v == NULL) { if (v == NULL) {
d = getlocals(); d = getlocals();
INCREF(d); INCREF(d);
@ -314,13 +341,15 @@ builtin_divmod(self, args)
object *args; object *args;
{ {
object *v, *w, *x; object *v, *w, *x;
if (!getargs(args, "(OO)", &v, &w))
if (!newgetargs(args, "OO:divmod", &v, &w))
return NULL; return NULL;
if (is_instanceobject(v) || is_instanceobject(w)) if (is_instanceobject(v) || is_instanceobject(w))
return instancebinop(v, w, "__divmod__", "__rdivmod__"); return instancebinop(v, w, "__divmod__", "__rdivmod__");
if (v->ob_type->tp_as_number == NULL || if (v->ob_type->tp_as_number == NULL ||
w->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; return NULL;
} }
if (coerce(&v, &w) != 0) if (coerce(&v, &w) != 0)
@ -332,110 +361,80 @@ builtin_divmod(self, args)
} }
static object * static object *
exec_eval(v, start) builtin_eval(self, args)
object *v; object *self;
int start; object *args;
{ {
object *str = NULL, *globals = NULL, *locals = NULL; object *cmd;
char *s; object *globals = NULL, *locals = NULL;
int n; char *str;
/* 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;
}
if (is_codeobject(str)) if (!newgetargs(args, "O|O!O!:eval",
return eval_code((codeobject *) str, globals, locals, &cmd,
&Mappingtype, &globals,
&Mappingtype, &locals))
return NULL;
if (is_codeobject(cmd))
return eval_code((codeobject *) cmd, globals, locals,
(object *)NULL, (object *)NULL); (object *)NULL, (object *)NULL);
s = getstringvalue(str); if (!is_stringobject(cmd)) {
if (strlen(s) != getstringsize(str)) { err_setstr(TypeError,
err_setstr(ValueError, "embedded '\\0' in string arg"); "eval() argument 1 must be string or code object");
return NULL; return NULL;
} }
if (start == eval_input) { str = getstringvalue(cmd);
while (*s == ' ' || *s == '\t') if (strlen(str) != getstringsize(cmd)) {
s++; err_setstr(ValueError,
"embedded '\\0' in string arg");
return NULL;
} }
return run_string(s, start, globals, locals); while (*str == ' ' || *str == '\t')
str++;
return run_string(str, eval_input, globals, locals);
} }
static object * static object *
builtin_eval(self, v) builtin_execfile(self, args)
object *self; object *self;
object *v; object *args;
{ {
return exec_eval(v, eval_input); char *filename;
} object *globals = NULL, *locals = NULL;
object *res;
static object *
builtin_execfile(self, v)
object *self;
object *v;
{
object *str = NULL, *globals = NULL, *locals = NULL, *w;
FILE* fp; FILE* fp;
char *s; char *s;
int n; int n;
if (v != NULL) {
if (is_stringobject(v)) if (!newgetargs(args, "s|O!O!:execfile",
str = v; &filename,
else if (is_tupleobject(v) && &Mappingtype, &globals,
((n = gettuplesize(v)) == 2 || n == 3)) { &Mappingtype, &locals))
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; return NULL;
}
s = getstringvalue(str);
if (strlen(s) != getstringsize(str)) {
err_setstr(ValueError, "embedded '\\0' in string arg");
return NULL;
}
BGN_SAVE BGN_SAVE
fp = fopen(s, "r"); fp = fopen(filename, "r");
END_SAVE END_SAVE
if (fp == NULL) { if (fp == NULL) {
err_setstr(IOError, "execfile cannot open the file argument"); err_errno(IOError);
return NULL; return NULL;
} }
w = run_file(fp, getstringvalue(str), file_input, globals, locals); res = run_file(fp, filename, file_input, globals, locals);
BGN_SAVE BGN_SAVE
fclose(fp); fclose(fp);
END_SAVE END_SAVE
return w; return res;
} }
static object * static object *
builtin_float(self, v) builtin_float(self, args)
object *self; object *self;
object *v; object *args;
{ {
object *v;
number_methods *nb; 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) { nb->nb_float == NULL) {
err_setstr(TypeError, err_setstr(TypeError,
"float() argument can't be converted to float"); "float() argument can't be converted to float");
@ -451,7 +450,8 @@ builtin_getattr(self, args)
{ {
object *v; object *v;
object *name; object *name;
if (!getargs(args, "(OS)", &v, &name))
if (!newgetargs(args, "OS:getattr", &v, &name))
return NULL; return NULL;
return getattro(v, name); return getattro(v, name);
} }
@ -463,7 +463,8 @@ builtin_hasattr(self, args)
{ {
object *v; object *v;
object *name; object *name;
if (!getargs(args, "(OS)", &v, &name))
if (!newgetargs(args, "OS:hasattr", &v, &name))
return NULL; return NULL;
v = getattro(v, name); v = getattro(v, name);
if (v == NULL) { if (v == NULL) {
@ -480,7 +481,8 @@ builtin_id(self, args)
object *args; object *args;
{ {
object *v; object *v;
if (!getargs(args, "O", &v))
if (!newgetargs(args, "O:id", &v))
return NULL; return NULL;
return newintobject((long)v); return newintobject((long)v);
} }
@ -498,16 +500,17 @@ builtin_map(self, args)
object *func, *result; object *func, *result;
sequence *seqs = NULL, *sqp; sequence *seqs = NULL, *sqp;
int n, len, newfunc = 0; int n, len;
register int i, j; 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"); err_setstr(TypeError, "map() requires at least two args");
return NULL; return NULL;
} }
func = gettupleitem(args, 0); func = gettupleitem(args, 0);
n = gettuplesize(args) - 1; n--;
if ((seqs = NEW(sequence, n)) == NULL) { if ((seqs = NEW(sequence, n)) == NULL) {
err_nomem(); err_nomem();
@ -633,7 +636,8 @@ builtin_setattr(self, args)
object *v; object *v;
object *name; object *name;
object *value; object *value;
if (!getargs(args, "(OSO)", &v, &name, &value))
if (!newgetargs(args, "OSO:setattr", &v, &name, &value))
return NULL; return NULL;
if (setattro(v, name, value) != 0) if (setattro(v, name, value) != 0)
return NULL; return NULL;
@ -648,7 +652,8 @@ builtin_delattr(self, args)
{ {
object *v; object *v;
object *name; object *name;
if (!getargs(args, "(OS)", &v, &name))
if (!newgetargs(args, "OS:delattr", &v, &name))
return NULL; return NULL;
if (setattro(v, name, (object *)NULL) != 0) if (setattro(v, name, (object *)NULL) != 0)
return NULL; return NULL;
@ -663,7 +668,8 @@ builtin_hash(self, args)
{ {
object *v; object *v;
long x; long x;
if (!getargs(args, "O", &v))
if (!newgetargs(args, "O:hash", &v))
return NULL; return NULL;
x = hashobject(v); x = hashobject(v);
if (x == -1) if (x == -1)
@ -672,13 +678,17 @@ builtin_hash(self, args)
} }
static object * static object *
builtin_hex(self, v) builtin_hex(self, args)
object *self; object *self;
object *v; object *args;
{ {
object *v;
number_methods *nb; 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) { nb->nb_hex == NULL) {
err_setstr(TypeError, err_setstr(TypeError,
"hex() argument can't be converted to hex"); "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_raw_input PROTO((object *, object *));
static object * static object *
builtin_input(self, v) builtin_input(self, args)
object *self; 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) if (line == NULL)
return line; 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); DECREF(line);
return v; return res;
} }
static object * static object *
builtin_int(self, v) builtin_int(self, args)
object *self; object *self;
object *v; object *args;
{ {
object *v;
number_methods *nb; 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) { nb->nb_int == NULL) {
err_setstr(TypeError, err_setstr(TypeError,
"int() argument can't be converted to int"); "int() argument can't be converted to int");
@ -719,16 +740,16 @@ builtin_int(self, v)
} }
static object * static object *
builtin_len(self, v) builtin_len(self, args)
object *self; object *self;
object *v; object *args;
{ {
object *v;
long len; long len;
typeobject *tp; typeobject *tp;
if (v == NULL) {
err_setstr(TypeError, "len() without argument"); if (!newgetargs(args, "O:len", &v))
return NULL; return NULL;
}
tp = v->ob_type; tp = v->ob_type;
if (tp->tp_as_sequence != NULL) { if (tp->tp_as_sequence != NULL) {
len = (*tp->tp_as_sequence->sq_length)(v); len = (*tp->tp_as_sequence->sq_length)(v);
@ -747,13 +768,16 @@ builtin_len(self, v)
} }
static object * static object *
builtin_long(self, v) builtin_long(self, args)
object *self; object *self;
object *v; object *args;
{ {
object *v;
number_methods *nb; 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) { nb->nb_long == NULL) {
err_setstr(TypeError, err_setstr(TypeError,
"long() argument can't be converted to long"); "long() argument can't be converted to long");
@ -763,17 +787,18 @@ builtin_long(self, v)
} }
static object * static object *
min_max(v, sign) min_max(args, sign)
object *v; object *args;
int sign; int sign;
{ {
int i; int i;
object *w, *x; object *v, *w, *x;
sequence_methods *sq; 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; return NULL;
}
sq = v->ob_type->tp_as_sequence; sq = v->ob_type->tp_as_sequence;
if (sq == NULL) { if (sq == NULL) {
err_setstr(TypeError, "min() or max() of non-sequence"); err_setstr(TypeError, "min() or max() of non-sequence");
@ -823,12 +848,15 @@ builtin_max(self, v)
} }
static object * static object *
builtin_oct(self, v) builtin_oct(self, args)
object *self; object *self;
object *v; object *args;
{ {
object *v;
number_methods *nb; number_methods *nb;
if (!newgetargs(args, "O:oct", &v))
return NULL;
if (v == NULL || (nb = v->ob_type->tp_as_number) == NULL || if (v == NULL || (nb = v->ob_type->tp_as_number) == NULL ||
nb->nb_oct == NULL) { nb->nb_oct == NULL) {
err_setstr(TypeError, err_setstr(TypeError,
@ -847,9 +875,8 @@ builtin_open(self, args)
char *mode = "r"; char *mode = "r";
int bufsize = -1; int bufsize = -1;
object *f; object *f;
if (!getargs(args, "s", &name) &&
(err_clear(), !getargs(args, "(ss)", &name, &mode)) && if (!newgetargs(args, "s|si:open", &name, &mode, &bufsize))
(err_clear(), !getargs(args, "(ssi)", &name, &mode, &bufsize)))
return NULL; return NULL;
f = newfileobject(name, mode); f = newfileobject(name, mode);
if (f != NULL) if (f != NULL)
@ -862,15 +889,11 @@ builtin_ord(self, args)
object *self; object *self;
object *args; object *args;
{ {
char *s; char c;
int len;
if (!getargs(args, "s#", &s, &len)) if (!newgetargs(args, "c:ord", &c))
return NULL; return NULL;
if (len != 1) { return newintobject((long)(c & 0xff));
err_setstr(ValueError, "ord() arg must have length 1");
return NULL;
}
return newintobject((long)(s[0] & 0xff));
} }
static object * static object *
@ -878,9 +901,9 @@ builtin_pow(self, args)
object *self; object *self;
object *args; object *args;
{ {
object *v, *w, *z, *x; object *v, *w, *z = None, *x;
z = None;
if (!newgetargs(args, "OO|O", &v, &w, &z)) if (!newgetargs(args, "OO|O:pow", &v, &w, &z))
return NULL; return NULL;
if (z == None) { if (z == None) {
if (is_instanceobject(v) || is_instanceobject(w)) if (is_instanceobject(v) || is_instanceobject(w))
@ -913,43 +936,25 @@ builtin_pow(self, args)
} }
static object * static object *
builtin_range(self, v) builtin_range(self, args)
object *self; 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; int i, n;
long ilow, ihigh, istep; object *v;
if (v != NULL && is_intobject(v)) {
ilow = 0; ihigh = getintvalue(v); istep = 1; if (gettuplesize(args) <= 1) {
} if (!newgetargs(args,
else if (v == NULL || !is_tupleobject(v)) { "i;range() requires 1-3 int arguments",
err_setstr(TypeError, errmsg); &ihigh))
return NULL; return NULL;
} }
else { else {
n = gettuplesize(v); if (!newgetargs(args,
if (n < 1 || n > 3) { "ii|i;range() requires 1-3 int arguments",
err_setstr(TypeError, errmsg); &ilow, &ihigh, &istep))
return NULL; 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) { if (istep == 0) {
err_setstr(ValueError, "zero step for range()"); err_setstr(ValueError, "zero step for range()");
@ -978,73 +983,66 @@ builtin_range(self, v)
} }
static object * static object *
builtin_xrange(self, v) builtin_xrange(self, args)
object *self; object *self;
object *v; object *args;
{ {
static char *errmsg = "xrange() requires 1-3 int arguments"; long ilow = 0, ihigh = 0, istep = 1;
int i, n; int n;
long start, stop, step, len; object *v;
if (v != NULL && is_intobject(v))
start = 0, stop = getintvalue(v), step = 1;
else if (v == NULL || !is_tupleobject(v)) { if (gettuplesize(args) <= 1) {
err_setstr(TypeError, errmsg); if (!newgetargs(args,
return NULL; "i;xrange() requires 1-3 int arguments",
&ihigh))
return NULL;
} }
else { else {
n = gettuplesize(v); if (!newgetargs(args,
if (n < 1 || n > 3) { "ii|i;xrange() requires 1-3 int arguments",
err_setstr(TypeError, errmsg); &ilow, &ihigh, &istep))
return NULL; 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 (istep == 0) {
if (step == 0) {
err_setstr(ValueError, "zero step for xrange()"); err_setstr(ValueError, "zero step for xrange()");
return NULL; return NULL;
} }
/* XXX ought to check overflow of subtraction */
len = (stop - start + step + ((step > 0) ? -1 : 1)) / step; if (istep > 0)
if (len < 0) n = (ihigh - ilow + istep - 1) / istep;
len = 0; else
n = (ihigh - ilow + istep + 1) / istep;
return newrangeobject(start, len, step, 1); if (n < 0)
n = 0;
return newrangeobject(ilow, n, istep, 1);
} }
static object * static object *
builtin_raw_input(self, v) builtin_raw_input(self, args)
object *self; object *self;
object *v; object *args;
{ {
object *f = sysget("stdout"); object *v = NULL;
if (f == NULL) { object *f;
err_setstr(RuntimeError, "lost sys.stdout");
if (!newgetargs(args, "|O:[raw_]input", &v))
return NULL; return NULL;
}
flushline();
if (v != NULL) { 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) if (writeobject(v, f, PRINT_RAW) != 0)
return NULL; 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 * static object *
@ -1052,18 +1050,14 @@ builtin_reduce(self, args)
object *self; object *self;
object *args; object *args;
{ {
object *seq, *func, *result; object *seq, *func, *result = NULL;
sequence_methods *sqf; sequence_methods *sqf;
register int i; register int i;
if (getargs(args, "(OO)", &func, &seq)) if (!newgetargs(args, "OO|O:reduce", &func, &seq, &result))
result = NULL; return NULL;
else { if (result != NULL)
err_clear();
if (!getargs(args, "(OOO)", &func, &seq, &result))
return NULL;
INCREF(result); INCREF(result);
}
if ((sqf = seq->ob_type->tp_as_sequence) == NULL) { if ((sqf = seq->ob_type->tp_as_sequence) == NULL) {
err_setstr(TypeError, err_setstr(TypeError,
@ -1116,22 +1110,26 @@ Fail:
} }
static object * static object *
builtin_reload(self, v) builtin_reload(self, args)
object *self; object *self;
object *v; object *args;
{ {
object *v;
if (!newgetargs(args, "O:reload", &v))
return NULL;
return reload_module(v); return reload_module(v);
} }
static object * static object *
builtin_repr(self, v) builtin_repr(self, args)
object *self; object *self;
object *v; object *args;
{ {
if (v == NULL) { object *v;
err_badarg();
if (!newgetargs(args, "O:repr", &v))
return NULL; return NULL;
}
return reprobject(v); return reprobject(v);
} }
@ -1145,13 +1143,10 @@ builtin_round(self, args)
double x; double x;
double f; double f;
int ndigits = 0; int ndigits = 0;
int sign = 1;
int i; int i;
if (!getargs(args, "d", &x)) {
err_clear(); if (!newgetargs(args, "d|i:round", &x, &ndigits))
if (!getargs(args, "(di)", &x, &ndigits))
return NULL; return NULL;
}
f = 1.0; f = 1.0;
for (i = ndigits; --i >= 0; ) for (i = ndigits; --i >= 0; )
f = f*10.0; f = f*10.0;
@ -1164,25 +1159,27 @@ builtin_round(self, args)
} }
static object * static object *
builtin_str(self, v) builtin_str(self, args)
object *self; object *self;
object *v; object *args;
{ {
if (v == NULL) { object *v;
err_badarg();
if (!newgetargs(args, "O:str", &v))
return NULL; return NULL;
}
return strobject(v); return strobject(v);
} }
static object * static object *
builtin_tuple(self, v) builtin_tuple(self, args)
object *self; object *self;
object *v; object *args;
{ {
object *v;
sequence_methods *sqf; sequence_methods *sqf;
if (v == NULL)
v = None; /* Force error later */ if (!newgetargs(args, "O:tuple", &v))
return NULL;
if (is_tupleobject(v)) { if (is_tupleobject(v)) {
INCREF(v); INCREF(v);
return v; return v;
@ -1235,25 +1232,29 @@ builtin_tuple(self, v)
} }
static object * static object *
builtin_type(self, v) builtin_type(self, args)
object *self; object *self;
object *v; object *args;
{ {
if (v == NULL) { object *v;
err_setstr(TypeError, "type() requires an argument");
if (!newgetargs(args, "O:type", &v))
return NULL; return NULL;
}
v = (object *)v->ob_type; v = (object *)v->ob_type;
INCREF(v); INCREF(v);
return v; return v;
} }
static object * static object *
builtin_vars(self, v) builtin_vars(self, args)
object *self; object *self;
object *v; object *args;
{ {
object *v = NULL;
object *d; object *d;
if (!newgetargs(args, "|O:vars", &v))
return NULL;
if (v == NULL) { if (v == NULL) {
d = getlocals(); d = getlocals();
INCREF(d); INCREF(d);
@ -1270,48 +1271,49 @@ builtin_vars(self, v)
} }
static struct methodlist builtin_methods[] = { static struct methodlist builtin_methods[] = {
{"abs", builtin_abs}, {"__import__", builtin___import__, 1},
{"apply", builtin_apply}, {"abs", builtin_abs, 1},
{"callable", builtin_callable}, {"apply", builtin_apply, 1},
{"chr", builtin_chr}, {"callable", builtin_callable, 1},
{"cmp", builtin_cmp}, {"chr", builtin_chr, 1},
{"coerce", builtin_coerce}, {"cmp", builtin_cmp, 1},
{"compile", builtin_compile}, {"coerce", builtin_coerce, 1},
{"delattr", builtin_delattr}, {"compile", builtin_compile, 1},
{"dir", builtin_dir}, {"delattr", builtin_delattr, 1},
{"divmod", builtin_divmod}, {"dir", builtin_dir, 1},
{"eval", builtin_eval}, {"divmod", builtin_divmod, 1},
{"execfile", builtin_execfile}, {"eval", builtin_eval, 1},
{"filter", builtin_filter}, {"execfile", builtin_execfile, 1},
{"float", builtin_float}, {"filter", builtin_filter, 1},
{"getattr", builtin_getattr}, {"float", builtin_float, 1},
{"hasattr", builtin_hasattr}, {"getattr", builtin_getattr, 1},
{"hash", builtin_hash}, {"hasattr", builtin_hasattr, 1},
{"hex", builtin_hex}, {"hash", builtin_hash, 1},
{"id", builtin_id}, {"hex", builtin_hex, 1},
{"input", builtin_input}, {"id", builtin_id, 1},
{"int", builtin_int}, {"input", builtin_input, 1},
{"len", builtin_len}, {"int", builtin_int, 1},
{"long", builtin_long}, {"len", builtin_len, 1},
{"map", builtin_map}, {"long", builtin_long, 1},
{"max", builtin_max}, {"map", builtin_map, 1},
{"min", builtin_min}, {"max", builtin_max, 1},
{"oct", builtin_oct}, {"min", builtin_min, 1},
{"open", builtin_open}, {"oct", builtin_oct, 1},
{"ord", builtin_ord}, {"open", builtin_open, 1},
{"ord", builtin_ord, 1},
{"pow", builtin_pow, 1}, {"pow", builtin_pow, 1},
{"range", builtin_range}, {"range", builtin_range, 1},
{"raw_input", builtin_raw_input}, {"raw_input", builtin_raw_input, 1},
{"reduce", builtin_reduce}, {"reduce", builtin_reduce, 1},
{"reload", builtin_reload}, {"reload", builtin_reload, 1},
{"repr", builtin_repr}, {"repr", builtin_repr, 1},
{"round", builtin_round}, {"round", builtin_round, 1},
{"setattr", builtin_setattr}, {"setattr", builtin_setattr, 1},
{"str", builtin_str}, {"str", builtin_str, 1},
{"tuple", builtin_tuple}, {"tuple", builtin_tuple, 1},
{"type", builtin_type}, {"type", builtin_type, 1},
{"vars", builtin_vars}, {"vars", builtin_vars, 1},
{"xrange", builtin_xrange}, {"xrange", builtin_xrange, 1},
{NULL, NULL}, {NULL, NULL},
}; };
@ -1324,6 +1326,13 @@ getbuiltin(name)
return mappinglookup(builtin_dict, name); return mappinglookup(builtin_dict, name);
} }
object *
getbuiltins(name)
char *name;
{
return dictlookup(builtin_dict, name);
}
int int
setbuiltin(cname, value) setbuiltin(cname, value)
char *cname; char *cname;

View 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 */ extern int suppress_print; /* Declared in pythonrun.c, set in pythonmain.c */
/* Turn this on if your compiler chokes on the big switch: */ /* 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: */ /* Turn this on if you want to debug the interpreter: */
/* (This can be on even if NDEBUG is defined) */ /* (This can be on even if NDEBUG is defined) */
/* #define DEBUG 1 /**/ /* #define DEBUG 1 */
#if defined(DEBUG) || !defined(NDEBUG) #if defined(DEBUG) || !defined(NDEBUG)
/* For debugging the interpreter: */ /* For debugging the interpreter: */
@ -1254,8 +1254,8 @@ eval_code(co, globals, locals, owner, arg)
DECREF(v); DECREF(v);
break; break;
} }
XDECREF(w);
GETLISTITEM(fastlocals, oparg) = v; GETLISTITEM(fastlocals, oparg) = v;
XDECREF(w);
break; break;
case DELETE_FAST: case DELETE_FAST:
@ -1270,8 +1270,8 @@ eval_code(co, globals, locals, owner, arg)
(object *)NULL); (object *)NULL);
break; break;
} }
DECREF(x);
GETLISTITEM(fastlocals, oparg) = NULL; GETLISTITEM(fastlocals, oparg) = NULL;
DECREF(x);
break; break;
case BUILD_TUPLE: case BUILD_TUPLE:
@ -1323,10 +1323,22 @@ eval_code(co, globals, locals, owner, arg)
break; break;
case IMPORT_NAME: case IMPORT_NAME:
name = GETNAME(oparg); w = GETNAMEV(oparg);
x = import_module(name); x = getbuiltins("__import__");
XINCREF(x); if (x == NULL) {
PUSH(x); 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; break;
case IMPORT_FROM: case IMPORT_FROM:
@ -1408,7 +1420,7 @@ eval_code(co, globals, locals, owner, arg)
case SET_LINENO: case SET_LINENO:
#ifdef LLTRACE #ifdef LLTRACE
if (lltrace) if (lltrace)
printf("--- Line %d ---\n", oparg); printf("--- %s:%d \n", filename, oparg);
#endif #endif
f->f_lineno = oparg; f->f_lineno = oparg;
if (f->f_trace != NULL) { if (f->f_trace != NULL) {
@ -1497,24 +1509,23 @@ eval_code(co, globals, locals, owner, arg)
b->b_type == SETUP_EXCEPT && b->b_type == SETUP_EXCEPT &&
why == WHY_EXCEPTION) { why == WHY_EXCEPTION) {
if (why == WHY_EXCEPTION) { if (why == WHY_EXCEPTION) {
object *exc, *val; object *exc, *val, *tb;
err_get(&exc, &val); err_fetch(&exc, &val, &tb);
if (val == NULL) { if (val == NULL) {
val = None; val = None;
INCREF(val); INCREF(val);
} }
v = tb_fetch();
/* Make the raw exception data /* Make the raw exception data
available to the handler, available to the handler,
so a program can emulate the so a program can emulate the
Python main loop. Don't do Python main loop. Don't do
this for 'finally'. */ this for 'finally'. */
if (b->b_type == SETUP_EXCEPT) { if (b->b_type == SETUP_EXCEPT) {
sysset("exc_traceback", v); sysset("exc_traceback", tb);
sysset("exc_value", val); sysset("exc_value", val);
sysset("exc_type", exc); sysset("exc_type", exc);
} }
PUSH(v); PUSH(tb);
PUSH(val); PUSH(val);
PUSH(exc); PUSH(exc);
} }
@ -1598,26 +1609,25 @@ call_exc_trace(p_trace, p_newtrace, f)
{ {
object *type, *value, *traceback, *arg; object *type, *value, *traceback, *arg;
int err; int err;
err_get(&type, &value); err_fetch(&type, &value, &traceback);
if (value == NULL) { if (value == NULL) {
value = None; value = None;
INCREF(value); INCREF(value);
} }
traceback = tb_fetch(); arg = mkvalue("(OOO)", type, value, traceback);
arg = newtupleobject(3); if (arg == NULL) {
if (arg == NULL) err_restore(type, value, traceback);
goto cleanup; return;
settupleitem(arg, 0, type); }
settupleitem(arg, 1, value); err = call_trace(p_trace, p_newtrace, f, "exception", arg);
settupleitem(arg, 2, traceback); DECREF(arg);
err = call_trace(p_trace, p_newtrace, f, "exception", arg); if (err == 0)
if (!err) { err_restore(type, value, traceback);
cleanup: else {
/* Restore original exception */ XDECREF(type);
err_setval(type, value); XDECREF(value);
tb_store(traceback); XDECREF(traceback);
} }
XDECREF(arg);
} }
static int static int
@ -1723,18 +1733,6 @@ getframe()
return (object *)current_frame; return (object *)current_frame;
} }
void
printtraceback(f)
object *f;
{
object *v = tb_fetch();
if (v != NULL) {
tb_print(v, f);
DECREF(v);
}
}
void void
flushline() flushline()
{ {
@ -1818,7 +1816,7 @@ static object *
lshift(v, w) lshift(v, w)
object *v, *w; object *v, *w;
{ {
BINOP("__lshift__", "__rshift__"); BINOP("__lshift__", "__rlshift__");
if (v->ob_type->tp_as_number != NULL) { if (v->ob_type->tp_as_number != NULL) {
object *x; object *x;
object * (*f) FPROTO((object *, object *)); object * (*f) FPROTO((object *, object *));
@ -1962,6 +1960,9 @@ static object *
rem(v, w) rem(v, w)
object *v, *w; object *v, *w;
{ {
if (is_stringobject(v)) {
return formatstring(v, w);
}
BINOP("__mod__", "__rmod__"); BINOP("__mod__", "__rmod__");
if (v->ob_type->tp_as_number != NULL) { if (v->ob_type->tp_as_number != NULL) {
object *x; object *x;
@ -1972,9 +1973,6 @@ rem(v, w)
DECREF(w); DECREF(w);
return x; return x;
} }
if (is_stringobject(v)) {
return formatstring(v, w);
}
err_setstr(TypeError, "bad operand type(s) for %"); err_setstr(TypeError, "bad operand type(s) for %");
return NULL; return NULL;
} }
@ -2492,6 +2490,10 @@ import_from(locals, v, name)
object *name; object *name;
{ {
object *w, *x; object *w, *x;
if (!is_moduleobject(v)) {
err_setstr(TypeError, "import-from require module object");
return -1;
}
w = getmoduledict(v); w = getmoduledict(v);
if (getstringvalue(name)[0] == '*') { if (getstringvalue(name)[0] == '*') {
int pos, err; int pos, err;
@ -2542,6 +2544,22 @@ build_class(methods, bases, name)
err_setstr(SystemError, "build_class with non-tuple bases"); err_setstr(SystemError, "build_class with non-tuple bases");
return NULL; 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)) { if (!is_dictobject(methods)) {
err_setstr(SystemError, "build_class with non-dictionary"); err_setstr(SystemError, "build_class with non-dictionary");
return NULL; return NULL;

View file

@ -336,7 +336,7 @@ com_addbyte(c, byte)
if (byte < 0 || byte > 255) { if (byte < 0 || byte > 255) {
/* /*
fprintf(stderr, "XXX compiling bad byte: %d\n", byte); 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"); err_setstr(SystemError, "com_addbyte: byte out of range");
c->c_errors++; c->c_errors++;
@ -2379,7 +2379,7 @@ optimize(c)
int oparg; int oparg;
object *name; object *name;
int fast_reserved; int fast_reserved;
object *error_type, *error_value; object *error_type, *error_value, *error_traceback;
#define NEXTOP() (*next_instr++) #define NEXTOP() (*next_instr++)
#define NEXTARG() (next_instr += 2, (next_instr[-1]<<8) + next_instr[-2]) #define NEXTARG() (next_instr += 2, (next_instr[-1]<<8) + next_instr[-2])
@ -2393,7 +2393,7 @@ optimize(c)
} }
nlocals = 0; nlocals = 0;
err_get(&error_type, &error_value); err_fetch(&error_type, &error_value, &error_traceback);
next_instr = (unsigned char *) getstringvalue(c->c_code); next_instr = (unsigned char *) getstringvalue(c->c_code);
for (;;) { for (;;) {
@ -2493,7 +2493,7 @@ optimize(c)
} }
end: end:
err_setval(error_type, error_value); err_restore(error_type, error_value, error_traceback);
err: err:
DECREF(locals); DECREF(locals);
} }

View file

@ -60,6 +60,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <errno.h> #include <errno.h>
#ifndef NT
#ifdef macintosh #ifdef macintosh
/* /*
** For the mac, there's a function macstrerror in macosmodule.c. We can't ** For the mac, there's a function macstrerror in macosmodule.c. We can't
@ -68,27 +69,37 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#define strerror macstrerror #define strerror macstrerror
#include "macdefs.h" /* For CW to find EINTR */ #include "macdefs.h" /* For CW to find EINTR */
#endif /* macintosh */ #endif /* !macintosh */
extern char *strerror PROTO((int)); extern char *strerror PROTO((int));
#endif /* !NT */
/* Last exception stored by err_setval() */ /* Last exception stored by err_setval() */
static object *last_exception; static object *last_exception;
static object *last_exc_val; static object *last_exc_val;
void
err_restore(exception, value, traceback)
object *exception;
object *value;
object *traceback;
{
err_clear();
last_exception = exception;
last_exc_val = value;
(void) tb_store(traceback);
XDECREF(traceback);
}
void void
err_setval(exception, value) err_setval(exception, value)
object *exception; object *exception;
object *value; object *value;
{ {
err_clear();
XINCREF(exception); XINCREF(exception);
last_exception = exception;
XINCREF(value); XINCREF(value);
last_exc_val = value; err_restore(exception, value, (object *)NULL);
} }
void void
@ -116,14 +127,16 @@ err_occurred()
} }
void void
err_get(p_exc, p_val) err_fetch(p_exc, p_val, p_tb)
object **p_exc; object **p_exc;
object **p_val; object **p_val;
object **p_tb;
{ {
*p_exc = last_exception; *p_exc = last_exception;
last_exception = NULL; last_exception = NULL;
*p_val = last_exc_val; *p_val = last_exc_val;
last_exc_val = NULL; last_exc_val = NULL;
*p_tb = tb_fetch();
} }
void void

View file

@ -38,7 +38,7 @@ int vgetargs PROTO((object *, char *, va_list));
/* Forward */ /* 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 void seterror PROTO((int, char *, int *, char *, char *));
static char *convertitem PROTO((object *, char **, va_list *, int *, char *)); static char *convertitem PROTO((object *, char **, va_list *, int *, char *));
static char *converttuple PROTO((object *, char **, va_list *, static char *converttuple PROTO((object *, char **, va_list *,
@ -68,7 +68,7 @@ int getargs(va_alist) va_dcl
args = va_arg(va, object *); args = va_arg(va, object *);
format = va_arg(va, char *); format = va_arg(va, char *);
#endif #endif
retval = vgetargs1(args, format, va, 1); retval = vgetargs1(args, format, &va, 1);
va_end(va); va_end(va);
return retval; return retval;
} }
@ -95,7 +95,7 @@ int newgetargs(va_alist) va_dcl
args = va_arg(va, object *); args = va_arg(va, object *);
format = va_arg(va, char *); format = va_arg(va, char *);
#endif #endif
retval = vgetargs1(args, format, va, 0); retval = vgetargs1(args, format, &va, 0);
va_end(va); va_end(va);
return retval; return retval;
} }
@ -107,15 +107,23 @@ vgetargs(args, format, va)
char *format; char *format;
va_list va; 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 static int
vgetargs1(args, format, va, compat) vgetargs1(args, format, p_va, compat)
object *args; object *args;
char *format; char *format;
va_list va; va_list *p_va;
int compat; int compat;
{ {
char msgbuf[256]; char msgbuf[256];
@ -186,7 +194,7 @@ vgetargs1(args, format, va, compat)
err_setstr(TypeError, msgbuf); err_setstr(TypeError, msgbuf);
return 0; return 0;
} }
msg = convertitem(args, &format, &va, levels, msgbuf); msg = convertitem(args, &format, p_va, levels, msgbuf);
if (msg == NULL) if (msg == NULL)
return 1; return 1;
seterror(levels[0], msg, levels+1, fname, message); seterror(levels[0], msg, levels+1, fname, message);
@ -226,7 +234,7 @@ vgetargs1(args, format, va, compat)
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
if (*format == '|') if (*format == '|')
format++; format++;
msg = convertitem(gettupleitem(args, i), &format, &va, msg = convertitem(gettupleitem(args, i), &format, p_va,
levels, msgbuf); levels, msgbuf);
if (msg) { if (msg) {
seterror(i+1, msg, levels, fname, message); seterror(i+1, msg, levels, fname, message);

File diff suppressed because it is too large Load diff

381
Python/importdl.c Normal file
View file

@ -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 */

39
Python/importdl.h Normal file
View file

@ -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;

View file

@ -406,6 +406,10 @@ rd_object(fp)
FILE *fp; FILE *fp;
{ {
RFILE rf; RFILE rf;
if (err_occurred()) {
fprintf(stderr, "XXX rd_object called with exception set\n");
return NULL;
}
rf.fp = fp; rf.fp = fp;
return r_object(&rf); return r_object(&rf);
} }
@ -416,6 +420,10 @@ rds_object(str, len)
int len; int len;
{ {
RFILE rf; RFILE rf;
if (err_occurred()) {
fprintf(stderr, "XXX rds_object called with exception set\n");
return NULL;
}
rf.fp = NULL; rf.fp = NULL;
rf.str = NULL; rf.str = NULL;
rf.ptr = str; rf.ptr = str;

View 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 */ #ifdef MPW /* MPW pushes 'extended' for float and double types with varargs */
typedef extended va_double; typedef extended va_double;
#else #else
typedef double va_double; typedef double va_double;
#endif #endif
@ -42,7 +42,7 @@ object *
initmodule2(name, methods, passthrough) initmodule2(name, methods, passthrough)
char *name; char *name;
struct methodlist *methods; struct methodlist *methods;
object *passthrough; object *passthrough;
{ {
object *m, *d, *v; object *m, *d, *v;
struct methodlist *ml; struct methodlist *ml;
@ -58,7 +58,7 @@ initmodule2(name, methods, passthrough)
fatal("out of mem for method name"); fatal("out of mem for method name");
sprintf(namebuf, "%s.%s", name, ml->ml_name); sprintf(namebuf, "%s.%s", name, ml->ml_name);
v = newmethodobject(namebuf, ml->ml_meth, 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 */ /* XXX The malloc'ed memory in namebuf is never freed */
if (v == NULL || dictinsert(d, ml->ml_name, v) != 0) { if (v == NULL || dictinsert(d, ml->ml_name, v) != 0) {
fprintf(stderr, "initializing module: %s\n", name); fprintf(stderr, "initializing module: %s\n", name);
@ -90,20 +90,33 @@ static int countformat(format, endchar)
int count = 0; int count = 0;
int level = 0; int level = 0;
while (level > 0 || *format != endchar) { while (level > 0 || *format != endchar) {
if (*format == '\0') { switch (*format) {
case '\0':
/* Premature end */ /* Premature end */
err_setstr(SystemError, "unmatched paren in format"); err_setstr(SystemError, "unmatched paren in format");
return -1; return -1;
} case '(':
else if (*format == '(') { case '[':
case '{':
if (level == 0) if (level == 0)
count++; count++;
level++; level++;
} break;
else if (*format == ')') case ')':
case ']':
case '}':
level--; level--;
else if (level == 0 && *format != '#') break;
count++; case '#':
case ',':
case ':':
case ' ':
case '\t':
break;
default:
if (level == 0)
count++;
}
format++; format++;
} }
return count; return count;
@ -114,8 +127,85 @@ static int countformat(format, endchar)
/* After an original idea and first implementation by Steven Miale */ /* After an original idea and first implementation by Steven Miale */
static object *do_mktuple PROTO((char**, va_list *, int, int)); 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_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 * static object *
do_mktuple(p_format, p_va, endchar, n) do_mktuple(p_format, p_va, endchar, n)
char **p_format; char **p_format;
@ -152,34 +242,41 @@ do_mkvalue(p_format, p_va)
char **p_format; char **p_format;
va_list *p_va; va_list *p_va;
{ {
for (;;) {
switch (*(*p_format)++) { switch (*(*p_format)++) {
case '(':
case '(': return do_mktuple(p_format, p_va, ')',
return do_mktuple(p_format, p_va, ')', countformat(*p_format, ')'));
countformat(*p_format, ')'));
case '[':
case 'b': return do_mklist(p_format, p_va, ']',
case 'h': countformat(*p_format, ']'));
case 'i':
return newintobject((long)va_arg(*p_va, int)); case '{':
return do_mkdict(p_format, p_va, '}',
case 'l': countformat(*p_format, '}'));
return newintobject((long)va_arg(*p_va, long));
case 'b':
case 'f': case 'h':
case 'd': case 'i':
return newfloatobject((double)va_arg(*p_va, va_double)); return newintobject((long)va_arg(*p_va, int));
case 'c': 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]; char p[1];
p[0] = va_arg(*p_va, int); p[0] = va_arg(*p_va, int);
return newsizedstringobject(p, 1); return newsizedstringobject(p, 1);
} }
case 's': case 's':
case 'z': case 'z':
{ {
object *v; object *v;
char *str = va_arg(*p_va, char *); char *str = va_arg(*p_va, char *);
@ -201,33 +298,44 @@ do_mkvalue(p_format, p_va)
} }
return v; return v;
} }
case 'S': case 'S':
case 'O': case 'O':
{ {
object *v; object *v;
v = va_arg(*p_va, object *); v = va_arg(*p_va, object *);
if (v != NULL) if (v != NULL)
INCREF(v); INCREF(v);
else if (!err_occurred()) else if (!err_occurred())
/* If a NULL was passed because a call /* If a NULL was passed
that should have constructed a value * because a call that should
failed, that's OK, and we pass the error * have constructed a value
on; but if no error occurred it's not * failed, that's OK, and we
clear that the caller knew what she * pass the error on; but if
was doing. */ * no error occurred it's not
* clear that the caller knew
* what she was doing. */
err_setstr(SystemError, err_setstr(SystemError,
"NULL object passed to mkvalue"); "NULL object passed to mkvalue");
return v; return v;
} }
default: case ':':
err_setstr(SystemError, "bad format char passed to mkvalue"); case ',':
return NULL; case ' ':
case '\t':
break;
default:
err_setstr(SystemError,
"bad format char passed to mkvalue");
return NULL;
}
} }
} }
#ifdef HAVE_STDARG_PROTOTYPES #ifdef HAVE_STDARG_PROTOTYPES
/* VARARGS 2 */ /* VARARGS 2 */
object *mkvalue(char *format, ...) object *mkvalue(char *format, ...)
@ -257,6 +365,14 @@ vmkvalue(format, va)
{ {
char *f = format; char *f = format;
int n = countformat(f, '\0'); 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) if (n < 0)
return NULL; return NULL;
if (n == 0) { if (n == 0) {
@ -264,6 +380,83 @@ vmkvalue(format, va)
return None; return None;
} }
if (n == 1) if (n == 1)
return do_mkvalue(&f, &va); return do_mkvalue(&f, &lva);
return do_mktuple(&f, &va, '\0', n); 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;
} }

View file

@ -242,12 +242,10 @@ run_command(command)
void void
print_error() print_error()
{ {
object *exception, *v, *f; object *exception, *v, *tb, *f;
err_get(&exception, &v); err_fetch(&exception, &v, &tb);
if (exception == NULL) { if (exception == NULL)
fprintf(stderr, "print_error called but no exception\n"); fatal("print_error called but no exception");
abort();
}
if (exception == SystemExit) { if (exception == SystemExit) {
if (v == NULL || v == None) if (v == NULL || v == None)
goaway(0); goaway(0);
@ -262,11 +260,12 @@ print_error()
} }
sysset("last_type", exception); sysset("last_type", exception);
sysset("last_value", v); sysset("last_value", v);
sysset("last_traceback", tb);
f = sysget("stderr"); f = sysget("stderr");
if (f == NULL) if (f == NULL)
fprintf(stderr, "lost sys.stderr\n"); fprintf(stderr, "lost sys.stderr\n");
else { else {
printtraceback(f); tb_print(tb, f);
if (exception == SyntaxError) { if (exception == SyntaxError) {
object *message; object *message;
char *filename, *text; char *filename, *text;
@ -331,6 +330,7 @@ print_error()
} }
XDECREF(exception); XDECREF(exception);
XDECREF(v); XDECREF(v);
XDECREF(tb);
} }
object * object *
@ -421,7 +421,6 @@ compile_string(str, filename, start)
int start; int start;
{ {
node *n; node *n;
int err;
codeobject *co; codeobject *co;
n = parse_string(str, start); n = parse_string(str, start);
if (n == NULL) if (n == NULL)

View file

@ -204,7 +204,8 @@ initsys()
XDECREF(v); XDECREF(v);
dictinsert(sysdict, "modules", get_modules()); dictinsert(sysdict, "modules", get_modules());
dictinsert(sysdict, "builtin_module_names", dictinsert(sysdict, "builtin_module_names",
list_builtin_module_names()); v = list_builtin_module_names());
XDECREF(v);
if (err_occurred()) if (err_occurred())
fatal("can't insert sys.* objects in sys dict"); fatal("can't insert sys.* objects in sys dict");
} }

View 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 = (struct func_arg *) malloc(sizeof(struct func_arg));
funcarg->func = func; funcarg->func = func;
funcarg->arg = arg; 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"); perror("thr_create");
free((void *) funcarg); free((void *) funcarg);
success = -1; success = -1;

View file

@ -258,7 +258,6 @@ tb_print(v, f)
err_badcall(); err_badcall();
return -1; return -1;
} }
sysset("last_traceback", v);
limitv = sysget("tracebacklimit"); limitv = sysget("tracebacklimit");
if (limitv && is_intobject(limitv)) { if (limitv && is_intobject(limitv)) {
limit = getintvalue(limitv); limit = getintvalue(limitv);