mirror of
				https://github.com/python/cpython.git
				synced 2025-10-24 18:33:49 +00:00 
			
		
		
		
	 b73cc04e62
			
		
	
	
		b73cc04e62
		
	
	
	
	
		
			
			pythonrun.c: added static forward declarations * pythonrun.h, ceval.h, longobject.h, node.h: removed declarations of static routines
		
			
				
	
	
		
			530 lines
		
	
	
	
		
			9.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			530 lines
		
	
	
	
		
			9.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /***********************************************************
 | |
| Copyright 1991, 1992, 1993 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.
 | |
| 
 | |
| ******************************************************************/
 | |
| 
 | |
| /* Python interpreter top-level routines, including init/exit */
 | |
| 
 | |
| #include "allobjects.h"
 | |
| 
 | |
| #include "grammar.h"
 | |
| #include "node.h"
 | |
| #include "parsetok.h"
 | |
| #include "graminit.h"
 | |
| #include "errcode.h"
 | |
| #include "sysmodule.h"
 | |
| #include "compile.h"
 | |
| #include "eval.h"
 | |
| #include "ceval.h"
 | |
| #include "pythonrun.h"
 | |
| #include "import.h"
 | |
| 
 | |
| #ifdef unix
 | |
| #define HANDLE_SIGNALS
 | |
| #endif
 | |
| 
 | |
| #ifdef HANDLE_SIGNALS
 | |
| #include <signal.h>
 | |
| #include "sigtype.h"
 | |
| #endif
 | |
| 
 | |
| extern char *getpythonpath();
 | |
| 
 | |
| extern grammar gram; /* From graminit.c */
 | |
| 
 | |
| /* Forward */
 | |
| static object *run_err_node PROTO((int err, node *n, char *filename,
 | |
| 				   object *globals, object *locals));
 | |
| static object *run_node PROTO((node *n, char *filename,
 | |
| 			       object *globals, object *locals));
 | |
| static object *eval_node PROTO((node *n, char *filename,
 | |
| 				object *globals, object *locals));
 | |
| void initsigs PROTO(());
 | |
| 
 | |
| int debugging; /* Needed by parser.c */
 | |
| int verbose; /* Needed by import.c */
 | |
| 
 | |
| /* Initialize all */
 | |
| 
 | |
| void
 | |
| initall()
 | |
| {
 | |
| 	static int inited;
 | |
| 	
 | |
| 	if (inited)
 | |
| 		return;
 | |
| 	inited = 1;
 | |
| 	
 | |
| 	initimport();
 | |
| 	
 | |
| 	/* Modules 'builtin' and 'sys' are initialized here,
 | |
| 	   they are needed by random bits of the interpreter.
 | |
| 	   All other modules are optional and are initialized
 | |
| 	   when they are first imported. */
 | |
| 	
 | |
| 	initbuiltin(); /* Also initializes builtin exceptions */
 | |
| 	initsys();
 | |
| 	
 | |
| 	initcalls(); /* Configuration-dependent initializations */
 | |
| 
 | |
| 	setpythonpath(getpythonpath());
 | |
| 
 | |
| 	initsigs(); /* Signal handling stuff, including initintr() */
 | |
| }
 | |
| 
 | |
| /* Parse input from a file and execute it */
 | |
| 
 | |
| int
 | |
| run(fp, filename)
 | |
| 	FILE *fp;
 | |
| 	char *filename;
 | |
| {
 | |
| 	if (filename == NULL)
 | |
| 		filename = "???";
 | |
| 	if (isatty((int)fileno(fp)))
 | |
| 		return run_tty_loop(fp, filename);
 | |
| 	else
 | |
| 		return run_script(fp, filename);
 | |
| }
 | |
| 
 | |
| int
 | |
| run_tty_loop(fp, filename)
 | |
| 	FILE *fp;
 | |
| 	char *filename;
 | |
| {
 | |
| 	object *v;
 | |
| 	int ret;
 | |
| 	v = sysget("ps1");
 | |
| 	if (v == NULL) {
 | |
| 		sysset("ps1", v = newstringobject(">>> "));
 | |
| 		XDECREF(v);
 | |
| 	}
 | |
| 	v = sysget("ps2");
 | |
| 	if (v == NULL) {
 | |
| 		sysset("ps2", v = newstringobject("... "));
 | |
| 		XDECREF(v);
 | |
| 	}
 | |
| 	for (;;) {
 | |
| 		ret = run_tty_1(fp, filename);
 | |
| #ifdef REF_DEBUG
 | |
| 		fprintf(stderr, "[%ld refs]\n", ref_total);
 | |
| #endif
 | |
| 		if (ret == E_EOF)
 | |
| 			return 0;
 | |
| 		/*
 | |
| 		if (ret == E_NOMEM)
 | |
| 			return -1;
 | |
| 		*/
 | |
| 	}
 | |
| }
 | |
| 
 | |
| int
 | |
| run_tty_1(fp, filename)
 | |
| 	FILE *fp;
 | |
| 	char *filename;
 | |
| {
 | |
| 	object *m, *d, *v, *w;
 | |
| 	node *n;
 | |
| 	char *ps1, *ps2;
 | |
| 	int err;
 | |
| 	v = sysget("ps1");
 | |
| 	w = sysget("ps2");
 | |
| 	if (v != NULL && is_stringobject(v)) {
 | |
| 		INCREF(v);
 | |
| 		ps1 = getstringvalue(v);
 | |
| 	}
 | |
| 	else {
 | |
| 		v = NULL;
 | |
| 		ps1 = "";
 | |
| 	}
 | |
| 	if (w != NULL && is_stringobject(w)) {
 | |
| 		INCREF(w);
 | |
| 		ps2 = getstringvalue(w);
 | |
| 	}
 | |
| 	else {
 | |
| 		w = NULL;
 | |
| 		ps2 = "";
 | |
| 	}
 | |
| 	BGN_SAVE
 | |
| 	err = parsefile(fp, filename, &gram, single_input, ps1, ps2, &n);
 | |
| 	END_SAVE
 | |
| 	XDECREF(v);
 | |
| 	XDECREF(w);
 | |
| 	if (err == E_EOF)
 | |
| 		return E_EOF;
 | |
| 	if (err != E_DONE) {
 | |
| 		err_input(err);
 | |
| 		print_error();
 | |
| 		return err;
 | |
| 	}
 | |
| 	m = add_module("__main__");
 | |
| 	if (m == NULL)
 | |
| 		return -1;
 | |
| 	d = getmoduledict(m);
 | |
| 	v = run_node(n, filename, d, d);
 | |
| 	flushline();
 | |
| 	if (v == NULL) {
 | |
| 		print_error();
 | |
| 		return -1;
 | |
| 	}
 | |
| 	DECREF(v);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int
 | |
| run_script(fp, filename)
 | |
| 	FILE *fp;
 | |
| 	char *filename;
 | |
| {
 | |
| 	object *m, *d, *v;
 | |
| 	m = add_module("__main__");
 | |
| 	if (m == NULL)
 | |
| 		return -1;
 | |
| 	d = getmoduledict(m);
 | |
| 	v = run_file(fp, filename, file_input, d, d);
 | |
| 	flushline();
 | |
| 	if (v == NULL) {
 | |
| 		print_error();
 | |
| 		return -1;
 | |
| 	}
 | |
| 	DECREF(v);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int
 | |
| run_command(command)
 | |
| 	char *command;
 | |
| {
 | |
| 	object *m, *d, *v;
 | |
| 	m = add_module("__main__");
 | |
| 	if (m == NULL)
 | |
| 		return -1;
 | |
| 	d = getmoduledict(m);
 | |
| 	v = run_string(command, file_input, d, d);
 | |
| 	flushline();
 | |
| 	if (v == NULL) {
 | |
| 		print_error();
 | |
| 		return -1;
 | |
| 	}
 | |
| 	DECREF(v);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| void
 | |
| print_error()
 | |
| {
 | |
| 	object *exception, *v, *f;
 | |
| 	err_get(&exception, &v);
 | |
| 	if (exception == SystemExit) {
 | |
| 		if (v == NULL || v == None)
 | |
| 			goaway(0);
 | |
| 		if (is_intobject(v))
 | |
| 			goaway((int)getintvalue(v));
 | |
| 		else {
 | |
| 			/* OK to use real stderr here */
 | |
| 			printobject(v, stderr, PRINT_RAW);
 | |
| 			fprintf(stderr, "\n");
 | |
| 			goaway(1);
 | |
| 		}
 | |
| 	}
 | |
| 	sysset("last_type", exception);
 | |
| 	sysset("last_value", v);
 | |
| 	f = sysget("stderr");
 | |
| 	if (f == NULL)
 | |
| 		fprintf(stderr, "lost sys.stderr\n");
 | |
| 	else {
 | |
| 		printtraceback(f);
 | |
| 		if (writeobject(exception, f, PRINT_RAW) != 0)
 | |
| 			err_clear();
 | |
| 		if (v != NULL && v != None) {
 | |
| 			writestring(": ", f);
 | |
| 			if (writeobject(v, f, PRINT_RAW) != 0)
 | |
| 				err_clear();
 | |
| 		}
 | |
| 		writestring("\n", f);
 | |
| 	}
 | |
| 	XDECREF(exception);
 | |
| 	XDECREF(v);
 | |
| }
 | |
| 
 | |
| object *
 | |
| run_string(str, start, globals, locals)
 | |
| 	char *str;
 | |
| 	int start;
 | |
| 	object *globals, *locals;
 | |
| {
 | |
| 	node *n;
 | |
| 	int err;
 | |
| 	err = parse_string(str, start, &n);
 | |
| 	return run_err_node(err, n, "<string>", globals, locals);
 | |
| }
 | |
| 
 | |
| object *
 | |
| run_file(fp, filename, start, globals, locals)
 | |
| 	FILE *fp;
 | |
| 	char *filename;
 | |
| 	int start;
 | |
| 	object *globals, *locals;
 | |
| {
 | |
| 	node *n;
 | |
| 	int err;
 | |
| 	err = parse_file(fp, filename, start, &n);
 | |
| 	return run_err_node(err, n, filename, globals, locals);
 | |
| }
 | |
| 
 | |
| static object *
 | |
| run_err_node(err, n, filename, globals, locals)
 | |
| 	int err;
 | |
| 	node *n;
 | |
| 	char *filename;
 | |
| 	object *globals, *locals;
 | |
| {
 | |
| 	if (err != E_DONE) {
 | |
| 		err_input(err);
 | |
| 		return NULL;
 | |
| 	}
 | |
| 	return run_node(n, filename, globals, locals);
 | |
| }
 | |
| 
 | |
| static object *
 | |
| run_node(n, filename, globals, locals)
 | |
| 	node *n;
 | |
| 	char *filename;
 | |
| 	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;
 | |
| 	object *v;
 | |
| 	co = compile(n, filename);
 | |
| 	freetree(n);
 | |
| 	if (co == NULL)
 | |
| 		return NULL;
 | |
| 	v = eval_code(co, globals, locals, (object *)NULL, (object *)NULL);
 | |
| 	DECREF(co);
 | |
| 	return v;
 | |
| }
 | |
| 
 | |
| object *
 | |
| compile_string(str, filename, start)
 | |
| 	char *str;
 | |
| 	char *filename;
 | |
| 	int start;
 | |
| {
 | |
| 	node *n;
 | |
| 	int err;
 | |
| 	codeobject *co;
 | |
| 	err = parse_string(str, start, &n);
 | |
| 	if (err != E_DONE) {
 | |
| 		err_input(err);
 | |
| 		return NULL;
 | |
| 	}
 | |
| 	co = compile(n, filename);
 | |
| 	freetree(n);
 | |
| 	return (object *)co;
 | |
| }
 | |
| 
 | |
| /* Simplified interface to parsefile */
 | |
| 
 | |
| int
 | |
| parse_file(fp, filename, start, n_ret)
 | |
| 	FILE *fp;
 | |
| 	char *filename;
 | |
| 	int start;
 | |
| 	node **n_ret;
 | |
| {
 | |
| 	int ret;
 | |
| 	BGN_SAVE
 | |
| 	ret = parsefile(fp, filename, &gram, start,
 | |
| 				(char *)0, (char *)0, n_ret);
 | |
| 	END_SAVE
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| /* Simplified interface to parsestring */
 | |
| 
 | |
| int
 | |
| parse_string(str, start, n_ret)
 | |
| 	char *str;
 | |
| 	int start;
 | |
| 	node **n_ret;
 | |
| {
 | |
| 	int err = parsestring(str, &gram, start, n_ret);
 | |
| 	/* Don't confuse early end of string with early end of input */
 | |
| 	if (err == E_EOF)
 | |
| 		err = E_SYNTAX;
 | |
| 	return err;
 | |
| }
 | |
| 
 | |
| /* Print fatal error message and abort */
 | |
| 
 | |
| void
 | |
| fatal(msg)
 | |
| 	char *msg;
 | |
| {
 | |
| 	fprintf(stderr, "Fatal error: %s\n", msg);
 | |
| 	abort();
 | |
| }
 | |
| 
 | |
| /* Clean up and exit */
 | |
| 
 | |
| #ifdef USE_THREAD
 | |
| extern int threads_started;
 | |
| #endif
 | |
| 
 | |
| static void
 | |
| cleanup()
 | |
| {
 | |
| 	object *exitfunc = sysget("exitfunc");
 | |
| 
 | |
| 	if (exitfunc) {
 | |
| 		object *arg;
 | |
| 		object *res;
 | |
| 		sysset("exitfunc", (object *)NULL);
 | |
| 		arg = newtupleobject(0);
 | |
| 		if (arg == NULL)
 | |
| 			res = NULL;
 | |
| 		else {
 | |
| 			res = call_object(exitfunc, arg);
 | |
| 			DECREF(arg);
 | |
| 		}
 | |
| 		if (res == NULL) {
 | |
| 			fprintf(stderr, "Error in sys.exitfunc:\n");
 | |
| 			print_error();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	flushline();
 | |
| }
 | |
| 
 | |
| #ifdef COUNT_ALLOCS
 | |
| extern void dump_counts PROTO((void));
 | |
| #endif
 | |
| 
 | |
| void
 | |
| goaway(sts)
 | |
| 	int sts;
 | |
| {
 | |
| 	cleanup();
 | |
| 
 | |
| #ifdef COUNT_ALLOCS
 | |
| 	dump_counts();
 | |
| #endif
 | |
| 
 | |
| #ifdef USE_THREAD
 | |
| 
 | |
| 	/* Other threads may still be active, so skip most of the
 | |
| 	   cleanup actions usually done (these are mostly for
 | |
| 	   debugging anyway). */
 | |
| 	
 | |
| 	(void) save_thread();
 | |
| 	donecalls();
 | |
| 	if (threads_started)
 | |
| 		_exit_prog(sts);
 | |
| 	else
 | |
| 		exit_prog(sts);
 | |
| 	
 | |
| #else /* USE_THREAD */
 | |
| 	
 | |
| 	/* XXX Call doneimport() before donecalls(), since donecalls()
 | |
| 	   calls wdone(), and doneimport() may close windows */
 | |
| 	doneimport();
 | |
| 	donecalls();
 | |
| 	
 | |
| 	err_clear();
 | |
| 
 | |
| #ifdef REF_DEBUG
 | |
| 	fprintf(stderr, "[%ld refs]\n", ref_total);
 | |
| #endif
 | |
| 
 | |
| #ifdef TRACE_REFS
 | |
| 	if (askyesno("Print left references?")) {
 | |
| 		printrefs(stderr);
 | |
| 	}
 | |
| #endif /* TRACE_REFS */
 | |
| 
 | |
| 	exit(sts);
 | |
| #endif /* USE_THREAD */
 | |
| 	/*NOTREACHED*/
 | |
| }
 | |
| 
 | |
| #ifdef HANDLE_SIGNALS
 | |
| static SIGTYPE
 | |
| sighandler(sig)
 | |
| 	int sig;
 | |
| {
 | |
| 	signal(sig, SIG_DFL); /* Don't catch recursive signals */
 | |
| 	cleanup(); /* Do essential clean-up */
 | |
| 	kill(getpid(), sig); /* Pretend the signal killed us */
 | |
| 	/*NOTREACHED*/
 | |
| }
 | |
| #endif
 | |
| 
 | |
| static void
 | |
| initsigs()
 | |
| {
 | |
| 	initintr();
 | |
| #ifdef HANDLE_SIGNALS
 | |
| 	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
 | |
| 		signal(SIGHUP, sighandler);
 | |
| 	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
 | |
| 		signal(SIGTERM, sighandler);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| #ifdef TRACE_REFS
 | |
| /* Ask a yes/no question */
 | |
| 
 | |
| int
 | |
| askyesno(prompt)
 | |
| 	char *prompt;
 | |
| {
 | |
| 	char buf[256];
 | |
| 	
 | |
| 	printf("%s [ny] ", prompt);
 | |
| 	if (fgets(buf, sizeof buf, stdin) == NULL)
 | |
| 		return 0;
 | |
| 	return buf[0] == 'y' || buf[0] == 'Y';
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #ifdef applec /* MPW (also usable for Think C 3.0) */
 | |
| 
 | |
| /* Check for file descriptor connected to interactive device.
 | |
|    Pretend that stdin is always interactive, other files never. */
 | |
| 
 | |
| int
 | |
| isatty(fd)
 | |
| 	int fd;
 | |
| {
 | |
| 	return fd == fileno(stdin);
 | |
| }
 | |
| 
 | |
| #endif
 |