Kaydet (Commit) a110aa65 authored tarafından Guido van Rossum's avatar Guido van Rossum

* Python/pythonrun.c (print_error): added INCREF/DECREF pair --

        the exception returned by a syntax error (when reported) would
        contain an object with refcnt zero!
MPW changes
üst bf8c0e33
/*********************************************************** /***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum, Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands. Amsterdam, The Netherlands.
All Rights Reserved All Rights Reserved
...@@ -38,13 +38,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ...@@ -38,13 +38,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "pythonrun.h" #include "pythonrun.h"
#include "import.h" #include "import.h"
#ifdef unix #ifdef HAVE_SIGNAL_H
#define HANDLE_SIGNALS
#endif
#ifdef HANDLE_SIGNALS
#include <signal.h> #include <signal.h>
#include "sigtype.h"
#endif #endif
extern char *getpythonpath(); extern char *getpythonpath();
...@@ -52,16 +47,16 @@ extern char *getpythonpath(); ...@@ -52,16 +47,16 @@ extern char *getpythonpath();
extern grammar gram; /* From graminit.c */ extern grammar gram; /* From graminit.c */
/* Forward */ /* Forward */
static object *run_err_node PROTO((int err, node *n, char *filename, static object *run_err_node PROTO((node *n, char *filename,
object *globals, object *locals)); object *globals, object *locals));
static object *run_node PROTO((node *n, char *filename, static object *run_node PROTO((node *n, char *filename,
object *globals, object *locals)); object *globals, object *locals));
static object *eval_node PROTO((node *n, char *filename, static void err_input PROTO((perrdetail *));
object *globals, object *locals));
static void initsigs PROTO((void)); static void initsigs PROTO((void));
int debugging; /* Needed by parser.c */ int debugging; /* Needed by parser.c */
int verbose; /* Needed by import.c */ int verbose; /* Needed by import.c */
int suppress_print; /* Needed by ceval.c */
/* Initialize all */ /* Initialize all */
...@@ -76,15 +71,13 @@ initall() ...@@ -76,15 +71,13 @@ initall()
initimport(); initimport();
/* Modules 'builtin' and 'sys' are initialized here, /* Modules '__builtin__' and 'sys' are initialized here,
they are needed by random bits of the interpreter. they are needed by random bits of the interpreter.
All other modules are optional and are initialized All other modules are optional and are initialized
when they are first imported. */ when they are first imported. */
initbuiltin(); /* Also initializes builtin exceptions */ initbuiltin(); /* Also initializes builtin exceptions */
initsys(); initsys();
initcalls(); /* Configuration-dependent initializations */
setpythonpath(getpythonpath()); setpythonpath(getpythonpath());
...@@ -144,8 +137,8 @@ run_tty_1(fp, filename) ...@@ -144,8 +137,8 @@ run_tty_1(fp, filename)
{ {
object *m, *d, *v, *w; object *m, *d, *v, *w;
node *n; node *n;
perrdetail err;
char *ps1, *ps2; char *ps1, *ps2;
int err;
v = sysget("ps1"); v = sysget("ps1");
w = sysget("ps2"); w = sysget("ps2");
if (v != NULL && is_stringobject(v)) { if (v != NULL && is_stringobject(v)) {
...@@ -165,16 +158,19 @@ run_tty_1(fp, filename) ...@@ -165,16 +158,19 @@ run_tty_1(fp, filename)
ps2 = ""; ps2 = "";
} }
BGN_SAVE BGN_SAVE
err = parsefile(fp, filename, &gram, single_input, ps1, ps2, &n); n = parsefile(fp, filename, &gram, single_input, ps1, ps2, &err);
END_SAVE END_SAVE
XDECREF(v); XDECREF(v);
XDECREF(w); XDECREF(w);
if (err == E_EOF) if (n == NULL) {
return E_EOF; if (err.error == E_EOF) {
if (err != E_DONE) { if (err.text)
err_input(err); free(err.text);
return E_EOF;
}
err_input(&err);
print_error(); print_error();
return err; return err.error;
} }
m = add_module("__main__"); m = add_module("__main__");
if (m == NULL) if (m == NULL)
...@@ -234,6 +230,10 @@ print_error() ...@@ -234,6 +230,10 @@ print_error()
{ {
object *exception, *v, *f; object *exception, *v, *f;
err_get(&exception, &v); err_get(&exception, &v);
if (exception == NULL) {
fprintf(stderr, "print_error called but no exception\n");
abort();
}
if (exception == SystemExit) { if (exception == SystemExit) {
if (v == NULL || v == None) if (v == NULL || v == None)
goaway(0); goaway(0);
...@@ -253,6 +253,47 @@ print_error() ...@@ -253,6 +253,47 @@ print_error()
fprintf(stderr, "lost sys.stderr\n"); fprintf(stderr, "lost sys.stderr\n");
else { else {
printtraceback(f); printtraceback(f);
if (exception == SyntaxError) {
object *message;
char *filename, *text;
int lineno, offset;
if (!getargs(v, "(O(ziiz))", &message,
&filename, &lineno, &offset, &text))
err_clear();
else {
char buf[10];
writestring(" File \"", f);
if (filename == NULL)
writestring("<string>", f);
else
writestring(filename, f);
writestring("\", line ", f);
sprintf(buf, "%d", lineno);
writestring(buf, f);
writestring("\n", f);
if (text != NULL) {
while (*text == ' ' || *text == '\t') {
text++;
offset--;
}
writestring(" ", f);
writestring(text, f);
if (*text == '\0' ||
text[strlen(text)-1] != '\n')
writestring("\n", f);
writestring(" ", f);
offset--;
while (offset > 0) {
writestring(" ", f);
offset--;
}
writestring("^\n", f);
}
INCREF(message);
DECREF(v);
v = message;
}
}
if (writeobject(exception, f, PRINT_RAW) != 0) if (writeobject(exception, f, PRINT_RAW) != 0)
err_clear(); err_clear();
if (v != NULL && v != None) { if (v != NULL && v != None) {
...@@ -272,10 +313,8 @@ run_string(str, start, globals, locals) ...@@ -272,10 +313,8 @@ run_string(str, start, globals, locals)
int start; int start;
object *globals, *locals; object *globals, *locals;
{ {
node *n; return run_err_node(parse_string(str, start),
int err; "<string>", globals, locals);
err = parse_string(str, start, &n);
return run_err_node(err, n, "<string>", globals, locals);
} }
object * object *
...@@ -285,23 +324,18 @@ run_file(fp, filename, start, globals, locals) ...@@ -285,23 +324,18 @@ run_file(fp, filename, start, globals, locals)
int start; int start;
object *globals, *locals; object *globals, *locals;
{ {
node *n; return run_err_node(parse_file(fp, filename, start),
int err; filename, globals, locals);
err = parse_file(fp, filename, start, &n);
return run_err_node(err, n, filename, globals, locals);
} }
static object * static object *
run_err_node(err, n, filename, globals, locals) run_err_node(n, filename, globals, locals)
int err;
node *n; node *n;
char *filename; char *filename;
object *globals, *locals; object *globals, *locals;
{ {
if (err != E_DONE) { if (n == NULL)
err_input(err); return NULL;
return NULL;
}
return run_node(n, filename, globals, locals); return run_node(n, filename, globals, locals);
} }
...@@ -310,16 +344,6 @@ run_node(n, filename, globals, locals) ...@@ -310,16 +344,6 @@ run_node(n, filename, globals, locals)
node *n; node *n;
char *filename; char *filename;
object *globals, *locals; object *globals, *locals;
{
return eval_node(n, filename, globals, locals);
}
static object *
eval_node(n, filename, globals, locals)
node *n;
char *filename;
object *globals;
object *locals;
{ {
codeobject *co; codeobject *co;
object *v; object *v;
...@@ -341,46 +365,88 @@ compile_string(str, filename, start) ...@@ -341,46 +365,88 @@ compile_string(str, filename, start)
node *n; node *n;
int err; int err;
codeobject *co; codeobject *co;
err = parse_string(str, start, &n); n = parse_string(str, start);
if (err != E_DONE) { if (n == NULL)
err_input(err);
return NULL; return NULL;
}
co = compile(n, filename); co = compile(n, filename);
freetree(n); freetree(n);
return (object *)co; return (object *)co;
} }
/* Simplified interface to parsefile */ /* Simplified interface to parsefile -- return node or set exception */
int node *
parse_file(fp, filename, start, n_ret) parse_file(fp, filename, start)
FILE *fp; FILE *fp;
char *filename; char *filename;
int start; int start;
node **n_ret;
{ {
int ret; node *n;
perrdetail err;
BGN_SAVE BGN_SAVE
ret = parsefile(fp, filename, &gram, start, n = parsefile(fp, filename, &gram, start,
(char *)0, (char *)0, n_ret); (char *)0, (char *)0, &err);
END_SAVE END_SAVE
return ret; if (n == NULL)
err_input(&err);
return n;
} }
/* Simplified interface to parsestring */ /* Simplified interface to parsestring -- return node or set exception */
int node *
parse_string(str, start, n_ret) parse_string(str, start)
char *str; char *str;
int start; int start;
node **n_ret;
{ {
int err = parsestring(str, &gram, start, n_ret); node *n;
/* Don't confuse early end of string with early end of input */ perrdetail err;
if (err == E_EOF) n = parsestring(str, &gram, start, &err);
err = E_SYNTAX; if (n == NULL)
return err; err_input(&err);
return n;
}
/* Set the error appropriate to the given input error code (see errcode.h) */
static void
err_input(err)
perrdetail *err;
{
object *v, *w;
char *msg = NULL;
v = mkvalue("(ziiz)", err->filename,
err->lineno, err->offset, err->text);
if (err->text != NULL) {
free(err->text);
err->text = NULL;
}
switch (err->error) {
case E_SYNTAX:
msg = "invalid syntax";
break;
case E_TOKEN:
msg = "invalid token";
break;
case E_INTR:
err_set(KeyboardInterrupt);
return;
case E_NOMEM:
err_nomem();
return;
case E_EOF:
msg = "unexpected EOF while parsing";
break;
default:
fprintf(stderr, "error=%d\n", err->error);
msg = "unknown parsing error";
break;
}
w = mkvalue("(sO)", msg, v);
XDECREF(v);
err_setval(SyntaxError, w);
XDECREF(w);
} }
/* Print fatal error message and abort */ /* Print fatal error message and abort */
...@@ -395,11 +461,12 @@ fatal(msg) ...@@ -395,11 +461,12 @@ fatal(msg)
/* Clean up and exit */ /* Clean up and exit */
#ifdef USE_THREAD #ifdef WITH_THREAD
extern int threads_started; #include "thread.h"
int threads_started = 0; /* Set by threadmodule.c and maybe others */
#endif #endif
static void void
cleanup() cleanup()
{ {
object *exitfunc = sysget("exitfunc"); object *exitfunc = sysget("exitfunc");
...@@ -438,25 +505,28 @@ goaway(sts) ...@@ -438,25 +505,28 @@ goaway(sts)
dump_counts(); dump_counts();
#endif #endif
#ifdef USE_THREAD #ifdef WITH_THREAD
/* Other threads may still be active, so skip most of the /* Other threads may still be active, so skip most of the
cleanup actions usually done (these are mostly for cleanup actions usually done (these are mostly for
debugging anyway). */ debugging anyway). */
(void) save_thread(); (void) save_thread();
donecalls(); #ifndef NO_EXIT_PROG
if (threads_started) if (threads_started)
_exit_prog(sts); _exit_prog(sts);
else else
exit_prog(sts); exit_prog(sts);
#else /* !NO_EXIT_PROG */
if (threads_started)
_exit(sts);
else
exit(sts);
#endif /* !NO_EXIT_PROG */
#else /* USE_THREAD */ #else /* WITH_THREAD */
/* XXX Call doneimport() before donecalls(), since donecalls()
calls wdone(), and doneimport() may close windows */
doneimport(); doneimport();
donecalls();
err_clear(); err_clear();
...@@ -471,18 +541,22 @@ goaway(sts) ...@@ -471,18 +541,22 @@ goaway(sts)
#endif /* TRACE_REFS */ #endif /* TRACE_REFS */
exit(sts); exit(sts);
#endif /* USE_THREAD */ #endif /* WITH_THREAD */
/*NOTREACHED*/ /*NOTREACHED*/
} }
#ifdef HANDLE_SIGNALS #ifdef HAVE_SIGNAL_H
static SIGTYPE static RETSIGTYPE
sighandler(sig) sighandler(sig)
int sig; int sig;
{ {
signal(sig, SIG_DFL); /* Don't catch recursive signals */ signal(sig, SIG_DFL); /* Don't catch recursive signals */
cleanup(); /* Do essential clean-up */ cleanup(); /* Do essential clean-up */
#ifdef HAVE_GETPID
kill(getpid(), sig); /* Pretend the signal killed us */ kill(getpid(), sig); /* Pretend the signal killed us */
#else
exit(1);
#endif
/*NOTREACHED*/ /*NOTREACHED*/
} }
#endif #endif
...@@ -490,13 +564,27 @@ sighandler(sig) ...@@ -490,13 +564,27 @@ sighandler(sig)
static void static void
initsigs() initsigs()
{ {
initintr(); RETSIGTYPE (*t)();
#ifdef HANDLE_SIGNALS #ifdef HAVE_SIGNAL_H
if (signal(SIGHUP, SIG_IGN) != SIG_IGN) #ifdef SIGPIPE
signal(SIGPIPE, SIG_IGN);
#endif
#ifdef SIGHUP
t = signal(SIGHUP, SIG_IGN);
if (t == SIG_DFL)
signal(SIGHUP, sighandler); signal(SIGHUP, sighandler);
if (signal(SIGTERM, SIG_IGN) != SIG_IGN) else
signal(SIGHUP, t);
#endif
#ifdef SIGTERM
t = signal(SIGTERM, SIG_IGN);
if (t == SIG_DFL)
signal(SIGTERM, sighandler); signal(SIGTERM, sighandler);
else
signal(SIGTERM, t);
#endif #endif
#endif /* HAVE_SIGNAL_H */
initintr(); /* May imply initsignal() */
} }
#ifdef TRACE_REFS #ifdef TRACE_REFS
...@@ -515,7 +603,7 @@ askyesno(prompt) ...@@ -515,7 +603,7 @@ askyesno(prompt)
} }
#endif #endif
#ifdef applec /* MPW (also usable for Think C 3.0) */ #ifdef MPW
/* Check for file descriptor connected to interactive device. /* Check for file descriptor connected to interactive device.
Pretend that stdin is always interactive, other files never. */ Pretend that stdin is always interactive, other files never. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment