call_object: print message before abort()

This commit is contained in:
Guido van Rossum 1994-08-30 08:01:59 +00:00
parent b078ce10d4
commit e59214ed91
1 changed files with 144 additions and 157 deletions

View File

@ -1,5 +1,5 @@
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -40,6 +40,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <ctype.h>
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 /**/
@ -53,9 +55,6 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define CHECKEXC 1 /* Double-check exception checking */
#endif
/* Global option, may be set by main() */
int killprint;
/* Forward declarations */
@ -92,18 +91,15 @@ static int cmp_member PROTO((object *, object *));
static object *cmp_outcome PROTO((int, object *, object *));
static int import_from PROTO((object *, object *, object *));
static object *build_class PROTO((object *, object *, object *));
static void locals_2_fast PROTO((frameobject *, int));
static void fast_2_locals PROTO((frameobject *));
static int access_statement PROTO((object *, object *, frameobject *));
static int exec_statement PROTO((object *, object *, object *));
static void mergelocals PROTO(());
/* Pointer to current frame, used to link new frames to */
static frameobject *current_frame;
#ifdef USE_THREAD
#ifdef WITH_THREAD
#include <errno.h>
#include "thread.h"
@ -128,7 +124,7 @@ init_save_thread()
object *
save_thread()
{
#ifdef USE_THREAD
#ifdef WITH_THREAD
if (interpreter_lock) {
object *res;
res = (object *)current_frame;
@ -144,7 +140,7 @@ void
restore_thread(x)
object *x;
{
#ifdef USE_THREAD
#ifdef WITH_THREAD
if (interpreter_lock) {
int err;
err = errno;
@ -190,11 +186,11 @@ eval_code(co, globals, locals, owner, arg)
register object *t;
register frameobject *f; /* Current frame */
register listobject *fastlocals = NULL;
object *trace = NULL; /* Trace function or NULL */
object *retval; /* Return value iff why == WHY_RETURN */
char *name; /* Name used by some instructions */
int needmerge = 0; /* Set if need to merge locals back at end */
int defmode = 0; /* Default access mode for new variables */
int ticker_count = 10; /* Check for intr every Nth instruction */
#ifdef LLTRACE
int lltrace;
#endif
@ -276,7 +272,7 @@ eval_code(co, globals, locals, owner, arg)
depends on the situation. The global trace function
(sys.trace) is also called whenever an exception
is detected. */
if (call_trace(&sys_trace, &trace, f, "call", arg)) {
if (call_trace(&sys_trace, &f->f_trace, f, "call", arg)) {
/* Trace function raised an error */
current_frame = f->f_back;
DECREF(f);
@ -293,6 +289,10 @@ eval_code(co, globals, locals, owner, arg)
return NULL;
}
}
x = sysget("check_interval");
if (x != NULL && is_intobject(x))
ticker_count = getintvalue(x);
next_instr = GETUSTRINGVALUE(f->f_code->co_code);
stack_pointer = f->f_valuestack;
@ -312,17 +312,16 @@ eval_code(co, globals, locals, owner, arg)
/* Do periodic things.
Doing this every time through the loop would add
too much overhead (a function call per instruction).
So we do it only every tenth instruction. */
So we do it only every Nth instruction. */
if (--ticker < 0) {
ticker = 10;
if (intrcheck()) {
err_set(KeyboardInterrupt);
ticker = ticker_count;
if (sigcheck()) {
why = WHY_EXCEPTION;
goto on_error;
}
#ifdef USE_THREAD
#ifdef WITH_THREAD
if (interpreter_lock) {
/* Give another thread a chance */
@ -642,17 +641,15 @@ eval_code(co, globals, locals, owner, arg)
case PRINT_EXPR:
v = POP();
/* Print value except if procedure result */
if (v != None) {
/* Before printing, also assign to '_' */
if (v != None &&
(err = setbuiltin("_", v)) == 0 &&
!suppress_print) {
flushline();
x = sysget("stdout");
softspace(x, 1);
err = writeobject(v, x, 0);
flushline();
if (killprint) {
err_setstr(RuntimeError,
"printing expression statement");
x = 0;
}
}
DECREF(v);
break;
@ -692,7 +689,7 @@ eval_code(co, globals, locals, owner, arg)
v = POP();
w = POP();
/* A tuple is equivalent to its first element here */
while (is_tupleobject(w)) {
while (is_tupleobject(w) && gettuplesize(w) > 0) {
u = w;
w = gettupleitem(u, 0);
DECREF(u);
@ -740,6 +737,14 @@ eval_code(co, globals, locals, owner, arg)
DECREF(v);
PUSH(x);
break;
case SET_FUNC_ARGS:
v = POP(); /* The function */
w = POP(); /* The argument list */
err = setfuncargstuff(v, oparg, w);
PUSH(v);
DECREF(w);
break;
case POP_BLOCK:
{
@ -1109,8 +1114,7 @@ eval_code(co, globals, locals, owner, arg)
x = GETCONST(oparg);
if (x == None)
break;
if (x == NULL || !is_dictobject(x)) {
fatal("bad RESERVE_FAST");
if (x == NULL || !is_tupleobject(x)) {
err_setstr(SystemError, "bad RESERVE_FAST");
x = NULL;
break;
@ -1119,16 +1123,15 @@ eval_code(co, globals, locals, owner, arg)
XDECREF(f->f_localmap);
INCREF(x);
f->f_localmap = x;
f->f_fastlocals = x = newlistobject(
x->ob_type->tp_as_mapping->mp_length(x));
f->f_fastlocals = x = newlistobject(gettuplesize(x));
fastlocals = (listobject *) x;
break;
case LOAD_FAST:
x = GETLISTITEM(fastlocals, oparg);
if (x == NULL) {
err_setstr(NameError,
"undefined local variable");
err_setval(NameError,
gettupleitem(f->f_localmap, oparg));
break;
}
if (is_accessobject(x)) {
@ -1156,12 +1159,12 @@ eval_code(co, globals, locals, owner, arg)
case DELETE_FAST:
x = GETLISTITEM(fastlocals, oparg);
if (x == NULL) {
err_setstr(NameError,
"undefined local variable");
err_setval(NameError,
gettupleitem(f->f_localmap, oparg));
break;
}
if (w != NULL && is_accessobject(w)) {
err = setaccessvalue(w, f->f_locals,
if (x != NULL && is_accessobject(x)) {
err = setaccessvalue(x, f->f_locals,
(object *)NULL);
break;
}
@ -1306,10 +1309,10 @@ eval_code(co, globals, locals, owner, arg)
printf("--- Line %d ---\n", oparg);
#endif
f->f_lineno = oparg;
if (trace != NULL) {
if (f->f_trace != NULL) {
/* Trace each line of code reached */
f->f_lasti = INSTR_OFFSET();
err = call_trace(&trace, &trace,
err = call_trace(&f->f_trace, &f->f_trace,
f, "line", None);
}
break;
@ -1368,8 +1371,8 @@ eval_code(co, globals, locals, owner, arg)
f->f_lasti -= 2;
tb_here(f);
if (trace)
call_exc_trace(&trace, &trace, f);
if (f->f_trace)
call_exc_trace(&f->f_trace, &f->f_trace, f);
if (sys_profile)
call_exc_trace(&sys_profile, (object**)0, f);
}
@ -1446,15 +1449,15 @@ eval_code(co, globals, locals, owner, arg)
if (why != WHY_RETURN)
retval = NULL;
if (trace) {
if (f->f_trace) {
if (why == WHY_RETURN) {
if (call_trace(&trace, &trace, f, "return", retval)) {
if (call_trace(&f->f_trace, &f->f_trace, f,
"return", retval)) {
XDECREF(retval);
retval = NULL;
why = WHY_EXCEPTION;
}
}
XDECREF(trace);
}
if (sys_profile && why == WHY_RETURN) {
@ -1465,9 +1468,6 @@ eval_code(co, globals, locals, owner, arg)
why = WHY_EXCEPTION;
}
}
if (fastlocals && (f->ob_refcnt > 1 || f->f_locals->ob_refcnt > 2))
fast_2_locals(f);
/* Restore previous frame and release the current one */
@ -1561,7 +1561,7 @@ call_trace(p_trace, p_newtrace, f, msg, arg)
settupleitem(arglist, 2, arg);
tracing++;
fast_2_locals(f);
res = call_object(*p_trace, arglist);
res = call_object(*p_trace, arglist); /* May clear *p_trace! */
locals_2_fast(f, 1);
tracing--;
cleanup:
@ -1569,7 +1569,7 @@ call_trace(p_trace, p_newtrace, f, msg, arg)
if (res == NULL) {
/* The trace proc raised an exception */
tb_here(f);
DECREF(*p_trace);
XDECREF(*p_trace);
*p_trace = NULL;
if (p_newtrace) {
XDECREF(*p_newtrace);
@ -1592,91 +1592,6 @@ call_trace(p_trace, p_newtrace, f, msg, arg)
}
}
static void
fast_2_locals(f)
frameobject *f;
{
/* Merge f->f_fastlocals into f->f_locals */
object *locals, *fast, *map;
object *error_type, *error_value;
int pos;
object *key, *value;
if (f == NULL)
return;
locals = f->f_locals;
fast = f->f_fastlocals;
map = f->f_localmap;
if (locals == NULL || fast == NULL || map == NULL)
return;
if (!is_dictobject(locals) || !is_listobject(fast) ||
!is_dictobject(map))
return;
err_get(&error_type, &error_value);
pos = 0;
while (mappinggetnext(map, &pos, &key, &value)) {
int j;
if (!is_intobject(value))
continue;
j = getintvalue(value);
value = getlistitem(fast, j);
if (value == NULL) {
err_clear();
if (dict2remove(locals, key) != 0)
err_clear();
}
else {
if (dict2insert(locals, key, value) != 0)
err_clear();
}
}
err_setval(error_type, error_value);
}
static void
locals_2_fast(f, clear)
frameobject *f;
int clear;
{
/* Merge f->f_locals into f->f_fastlocals */
object *locals, *fast, *map;
object *error_type, *error_value;
int pos;
object *key, *value;
if (f == NULL)
return;
locals = f->f_locals;
fast = f->f_fastlocals;
map = f->f_localmap;
if (locals == NULL || fast == NULL || map == NULL)
return;
if (!is_dictobject(locals) || !is_listobject(fast) ||
!is_dictobject(map))
return;
err_get(&error_type, &error_value);
pos = 0;
while (mappinggetnext(map, &pos, &key, &value)) {
int j;
if (!is_intobject(value))
continue;
j = getintvalue(value);
value = dict2lookup(locals, key);
if (value == NULL)
err_clear();
else
INCREF(value);
if (value != NULL || clear)
if (setlistitem(fast, j, value) != 0)
err_clear();
}
err_setval(error_type, error_value);
}
static void
mergelocals()
{
locals_2_fast(current_frame, 1);
}
object *
getlocals()
{
@ -1704,6 +1619,12 @@ getowner()
return current_frame->f_owner;
}
object *
getframe()
{
return (object *)current_frame;
}
void
printtraceback(f)
object *f;
@ -1999,10 +1920,31 @@ call_object(func, arg)
object *func;
object *arg;
{
if (is_instancemethodobject(func) || is_funcobject(func))
return call_function(func, arg);
binaryfunc call;
object *result;
if (call = func->ob_type->tp_call) {
int size = gettuplesize(arg);
if (arg) {
size = gettuplesize(arg);
if (size == 1)
arg = gettupleitem(arg, 0);
else if (size == 0)
arg = NULL;
}
result = (*call)(func, arg);
}
else if (is_instancemethodobject(func) || is_funcobject(func))
result = call_function(func, arg);
else
return call_builtin(func, arg);
result = call_builtin(func, arg);
if (result == NULL && !err_occurred()) {
fprintf(stderr, "null result without error in call_object\n");
abort();
}
return result;
}
static object *
@ -2025,6 +1967,17 @@ call_builtin(func, arg)
if (is_classobject(func)) {
return newinstanceobject(func, arg);
}
if (is_instanceobject(func)) {
object *res, *call = getattr(func,"__call__");
if (call == NULL) {
err_clear();
err_setstr(AttributeError, "no __call__ method defined");
return NULL;
}
res = call_object(call, arg);
DECREF(call);
return res;
}
err_setstr(TypeError, "call of non-function");
return NULL;
}
@ -2038,6 +1991,8 @@ call_function(func, arg)
object *newlocals, *newglobals;
object *class = NULL;
object *co, *v;
object *argdefs;
int argcount;
if (is_instancemethodobject(func)) {
object *self = instancemethodgetself(func);
@ -2065,7 +2020,6 @@ call_function(func, arg)
}
}
else {
int argcount;
if (arg == NULL)
argcount = 0;
else if (is_tupleobject(arg))
@ -2099,6 +2053,39 @@ call_function(func, arg)
return NULL;
}
}
argdefs = getfuncargstuff(func, &argcount);
if (argdefs != NULL && arg != NULL && is_tupleobject(arg)) {
int actualcount, j;
/* Process default arguments */
if (argcount & 0x4000)
argcount ^= 0x4000;
actualcount = gettuplesize(arg);
j = gettuplesize(argdefs) - (argcount - actualcount);
if (actualcount < argcount && j >= 0) {
int i;
object *v;
if (newarg == NULL)
INCREF(arg);
newarg = newtupleobject(argcount);
if (newarg == NULL) {
DECREF(arg);
return NULL;
}
for (i = 0; i < actualcount; i++) {
v = gettupleitem(arg, i);
XINCREF(v);
settupleitem(newarg, i, v);
}
for (; i < argcount; i++, j++) {
v = gettupleitem(argdefs, j);
XINCREF(v);
settupleitem(newarg, i, v);
}
DECREF(arg);
arg = newarg;
}
}
co = getfunccode(func);
if (co == NULL) {
@ -2162,18 +2149,18 @@ loop_subscript(v, w)
object *v, *w;
{
sequence_methods *sq = v->ob_type->tp_as_sequence;
int i, n;
int i;
if (sq == NULL) {
err_setstr(TypeError, "loop over non-sequence");
return NULL;
}
i = getintvalue(w);
n = (*sq->sq_length)(v);
if (n < 0)
return NULL; /* Exception */
if (i >= n)
return NULL; /* End of loop */
return (*sq->sq_item)(v, i);
v = (*sq->sq_item)(v, i);
if (v)
return v;
if (err_occurred() == IndexError)
err_clear();
return NULL;
}
static int
@ -2300,7 +2287,7 @@ static int
cmp_member(v, w)
object *v, *w;
{
int i, n, cmp;
int i, cmp;
object *x;
sequence_methods *sq;
/* Special case for char in string */
@ -2327,11 +2314,15 @@ cmp_member(v, w)
"'in' or 'not in' needs sequence right argument");
return -1;
}
n = (*sq->sq_length)(w);
if (n < 0)
return -1;
for (i = 0; i < n; i++) {
for (i = 0; ; i++) {
x = (*sq->sq_item)(w, i);
if (x == NULL) {
if (err_occurred() == IndexError) {
err_clear();
break;
}
return -1;
}
cmp = cmpobject(v, x);
XDECREF(x);
if (cmp == 0)
@ -2473,17 +2464,13 @@ access_statement(name, vmode, f)
if (f->f_localmap == NULL)
value = dict2lookup(f->f_locals, name);
else {
value = dict2lookup(f->f_localmap, name);
if (value == NULL || !is_intobject(value))
value = NULL;
else {
fastind = getintvalue(value);
if (0 <= fastind &&
fastind < getlistsize(f->f_fastlocals))
object *map = f->f_localmap;
value = NULL;
for (fastind = gettuplesize(map); --fastind >= 0; ) {
object *fname = gettupleitem(map, fastind);
if (cmpobject(name, fname) == 0) {
value = getlistitem(f->f_fastlocals, fastind);
else {
value = NULL;
fastind = -1;
break;
}
}
}