summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/pythread.h27
-rw-r--r--Include/thread.h27
-rw-r--r--Modules/config.c.in16
-rw-r--r--Modules/threadmodule.c294
-rw-r--r--Modules/timemodule.c8
-rw-r--r--Modules/xxmodule.c92
-rw-r--r--Objects/fileobject.c11
-rw-r--r--Python/ceval.c96
-rw-r--r--Python/pythonmain.c384
-rw-r--r--Python/pythonrun.c424
-rw-r--r--Python/thread.c263
11 files changed, 1249 insertions, 393 deletions
diff --git a/Include/pythread.h b/Include/pythread.h
new file mode 100644
index 0000000..91bac2a
--- /dev/null
+++ b/Include/pythread.h
@@ -0,0 +1,27 @@
+#ifndef _THREAD_H_included
+#define _THREAD_H_included
+
+#ifdef __STDC__
+#define _P(args) args
+#else
+#define _P(args) ()
+#endif
+
+void init_thread _P((void));
+int start_new_thread _P((void (*)(void *), void *));
+void exit_thread _P((void));
+
+typedef void *type_lock;
+
+type_lock allocate_lock _P((void));
+void free_lock _P((type_lock));
+int acquire_lock _P((type_lock, int));
+#define WAIT_LOCK 1
+#define NOWAIT_LOCK 0
+void release_lock _P((type_lock));
+
+void exit_prog _P((int));
+
+#undef _P
+
+#endif
diff --git a/Include/thread.h b/Include/thread.h
new file mode 100644
index 0000000..91bac2a
--- /dev/null
+++ b/Include/thread.h
@@ -0,0 +1,27 @@
+#ifndef _THREAD_H_included
+#define _THREAD_H_included
+
+#ifdef __STDC__
+#define _P(args) args
+#else
+#define _P(args) ()
+#endif
+
+void init_thread _P((void));
+int start_new_thread _P((void (*)(void *), void *));
+void exit_thread _P((void));
+
+typedef void *type_lock;
+
+type_lock allocate_lock _P((void));
+void free_lock _P((type_lock));
+int acquire_lock _P((type_lock, int));
+#define WAIT_LOCK 1
+#define NOWAIT_LOCK 0
+void release_lock _P((type_lock));
+
+void exit_prog _P((int));
+
+#undef _P
+
+#endif
diff --git a/Modules/config.c.in b/Modules/config.c.in
index 0973b77..8ed889a 100644
--- a/Modules/config.c.in
+++ b/Modules/config.c.in
@@ -123,6 +123,7 @@ extern void initpwd();
extern void initgrp();
extern void initmarshal();
extern void initselect();
+extern void initsocket();
#ifdef USE_AUDIO
extern void initaudio();
@@ -148,15 +149,15 @@ extern void initpanel();
#ifdef USE_STDWIN
extern void initstdwin();
#endif
-#ifdef USE_SOCKET
-extern void initsocket();
-#endif
#ifdef USE_JPEG
extern void initjpeg();
#endif
#ifdef USE_CD
extern void initcd();
#endif
+#ifdef USE_THREAD
+extern void initthread();
+#endif
struct {
char *name;
@@ -173,6 +174,7 @@ struct {
{"grp", initgrp},
{"marshal", initmarshal},
{"select", initselect},
+ {"socket", initsocket},
/* Optional modules */
@@ -206,10 +208,6 @@ struct {
{"stdwin", initstdwin},
#endif
-#ifdef USE_SOCKET
- {"socket", initsocket},
-#endif
-
#ifdef USE_JPEG
{"jpeg", initjpeg},
#endif
@@ -218,5 +216,9 @@ struct {
{"cd", initcd},
#endif
+#ifdef USE_THREAD
+ {"thread", initthread},
+#endif
+
{0, 0} /* Sentinel */
};
diff --git a/Modules/threadmodule.c b/Modules/threadmodule.c
new file mode 100644
index 0000000..c4de295
--- /dev/null
+++ b/Modules/threadmodule.c
@@ -0,0 +1,294 @@
+/***********************************************************
+Copyright 1991, 1992 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.
+
+******************************************************************/
+
+/* Thread module */
+/* Interface to Sjoerd's portable C thread library */
+
+#include "allobjects.h"
+#include "modsupport.h"
+#include "compile.h"
+#include "ceval.h"
+
+#include "thread.h"
+
+extern void init_save_thread PROTO((void));
+extern void* save_thread PROTO((void));
+extern void restore_thread PROTO((void *));
+
+object *ThreadError;
+
+
+/* Lock objects */
+
+typedef struct {
+ OB_HEAD
+ type_lock lock_lock;
+} lockobject;
+
+extern typeobject Locktype; /* Really static, forward */
+
+#define is_lockobject(v) ((v)->ob_type == &Locktype)
+
+static lockobject *
+newlockobject()
+{
+ lockobject *self;
+ self = NEWOBJ(lockobject, &Locktype);
+ if (self == NULL)
+ return NULL;
+ self->lock_lock = allocate_lock();
+ if (self->lock_lock == NULL) {
+ DEL(self);
+ self = NULL;
+ err_setstr(ThreadError, "can't allocate lock");
+ }
+ return self;
+}
+
+static void
+lock_dealloc(self)
+ lockobject *self;
+{
+ /* Unlock the lock so it's safe to free it */
+ acquire_lock(self->lock_lock, 0);
+ release_lock(self->lock_lock);
+
+ free_lock(self->lock_lock);
+ DEL(self);
+}
+
+static object *
+lock_acquire_lock(self, args)
+ lockobject *self;
+ object *args;
+{
+ void *save;
+ int i;
+
+ if (args != NULL) {
+ if (!getargs(args, "i", &i))
+ return NULL;
+ }
+ else
+ i = 1;
+
+ save = save_thread();
+
+ i = acquire_lock(self->lock_lock, i);
+
+ restore_thread(save);
+
+ if (args == NULL) {
+ INCREF(None);
+ return None;
+ }
+ else
+ return newintobject((long)i);
+}
+
+static object *
+lock_release_lock(self, args)
+ lockobject *self;
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+
+ /* Sanity check: the lock must be locked */
+ if (acquire_lock(self->lock_lock, 0)) {
+ release_lock(self->lock_lock);
+ err_setstr(ThreadError, "release unlocked lock");
+ return NULL;
+ }
+
+ release_lock(self->lock_lock);
+ INCREF(None);
+ return None;
+}
+
+static object *
+lock_locked_lock(self, args)
+ lockobject *self;
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+
+ if (acquire_lock(self->lock_lock, 0)) {
+ release_lock(self->lock_lock);
+ return newintobject(0L);
+ }
+ return newintobject(1L);
+}
+
+static struct methodlist lock_methods[] = {
+ {"acquire_lock", lock_acquire_lock},
+ {"acquire", lock_acquire_lock},
+ {"release_lock", lock_release_lock},
+ {"release", lock_release_lock},
+ {"locked_lock", lock_locked_lock},
+ {"locked", lock_locked_lock},
+ {NULL, NULL} /* sentinel */
+};
+
+static object *
+lock_getattr(self, name)
+ lockobject *self;
+ char *name;
+{
+ return findmethod(lock_methods, (object *)self, name);
+}
+
+static typeobject Locktype = {
+ OB_HEAD_INIT(&Typetype)
+ 0, /*ob_size*/
+ "lock", /*tp_name*/
+ sizeof(lockobject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ lock_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ lock_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+};
+
+
+/* Module functions */
+
+static void
+t_bootstrap(args_raw)
+ void *args_raw;
+{
+ object *args = (object *) args_raw;
+ object *func, *arg, *res;
+
+ restore_thread((void *)NULL);
+ func = gettupleitem(args, 0);
+ arg = gettupleitem(args, 1);
+ res = call_object(func, arg);
+ DECREF(arg); /* Matches the INCREF(arg) in thread_start_new_thread */
+ if (res == NULL) {
+ fprintf(stderr, "Unhandled exception in thread:\n");
+ print_error(); /* From pythonmain.c */
+ fprintf(stderr, "Exiting the entire program\n");
+ goaway(1);
+ }
+ (void) save_thread();
+ exit_thread();
+}
+
+static object *
+thread_start_new_thread(self, args)
+ object *self; /* Not used */
+ object *args;
+{
+ object *func, *arg;
+
+ if (!getargs(args, "(OO)", &func, &arg))
+ return NULL;
+ INCREF(args);
+ if (!start_new_thread(t_bootstrap, (void*) args)) {
+ DECREF(args);
+ err_setstr(ThreadError, "can't start new thread\n");
+ return NULL;
+ }
+ /* Otherwise the DECREF(args) is done by t_bootstrap */
+ INCREF(None);
+ return None;
+}
+
+static object *
+thread_exit_thread(self, args)
+ object *self; /* Not used */
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+ (void) save_thread();
+ exit_thread();
+ for (;;) { } /* Should not be reached */
+}
+
+static object *
+thread_exit_prog(self, args)
+ object *self; /* Not used */
+ object *args;
+{
+ int sts;
+ if (!getargs(args, "i", &sts))
+ return NULL;
+ goaway(sts);
+ for (;;) { } /* Should not be reached */
+}
+
+static object *
+thread_allocate_lock(self, args)
+ object *self; /* Not used */
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+ return newlockobject();
+}
+
+static struct methodlist thread_methods[] = {
+ {"start_new_thread", thread_start_new_thread},
+ {"start_new", thread_start_new_thread},
+ {"allocate_lock", thread_allocate_lock},
+ {"allocate", thread_allocate_lock},
+ {"exit_thread", thread_exit_thread},
+ {"exit", thread_exit_thread},
+ {"exit_prog", thread_exit_prog},
+ {NULL, NULL} /* sentinel */
+};
+
+
+/* Initialization function */
+
+void
+initthread()
+{
+ object *m, *d, *x;
+
+ /* Create the module and add the functions */
+ m = initmodule("thread", thread_methods);
+
+ /* Add a symbolic constant */
+ d = getmoduledict(m);
+ ThreadError = newstringobject("thread.error");
+ INCREF(ThreadError);
+ dictinsert(d, "error", ThreadError);
+
+ /* Check for errors */
+ if (err_occurred())
+ fatal("can't initialize module thread");
+
+ /* Initialize the C thread library */
+ init_thread();
+
+ /* Initialize the interpreter's stack save/restore mechanism */
+ init_save_thread();
+}
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index 4a921f0..5a278a9bd 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -104,11 +104,14 @@ time_sleep(self, args)
object *self;
object *args;
{
+ void *save, *save_thread(), restore_thread();
int secs;
SIGTYPE (*sigsave)() = 0; /* Initialized to shut lint up */
if (!getintarg(args, &secs))
return NULL;
+ save = save_thread();
if (setjmp(sleep_intr)) {
+ restore_thread(save);
signal(SIGINT, sigsave);
err_set(KeyboardInterrupt);
return NULL;
@@ -117,6 +120,7 @@ time_sleep(self, args)
if (sigsave != (SIGTYPE (*)()) SIG_IGN)
signal(SIGINT, sleep_catcher);
sleep(secs);
+ restore_thread(save);
signal(SIGINT, sigsave);
INCREF(None);
return None;
@@ -147,11 +151,14 @@ time_millisleep(self, args)
object *self;
object *args;
{
+ void *save, *save_thread(), restore_thread();
long msecs;
SIGTYPE (*sigsave)();
if (!getlongarg(args, &msecs))
return NULL;
+ save = save_thread();
if (setjmp(sleep_intr)) {
+ restore_thread(save);
signal(SIGINT, sigsave);
err_set(KeyboardInterrupt);
return NULL;
@@ -160,6 +167,7 @@ time_millisleep(self, args)
if (sigsave != (SIGTYPE (*)()) SIG_IGN)
signal(SIGINT, sleep_catcher);
millisleep(msecs);
+ restore_thread(save);
signal(SIGINT, sigsave);
INCREF(None);
return None;
diff --git a/Modules/xxmodule.c b/Modules/xxmodule.c
new file mode 100644
index 0000000..070a622
--- /dev/null
+++ b/Modules/xxmodule.c
@@ -0,0 +1,92 @@
+/***********************************************************
+Copyright 1991, 1992 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.
+
+******************************************************************/
+
+/* xx module */
+
+#include "allobjects.h"
+#include "modsupport.h"
+
+
+/* Function of two integers returning integer */
+
+static object *
+xx_foo(self, args)
+ object *self; /* Not used */
+ object *args;
+{
+ long i, j;
+ long res;
+ if (!getargs(args, "(ll)", &i, &j))
+ return NULL;
+ res = i+j; /* XXX Do something here */
+ return newintobject(res);
+}
+
+
+/* Function of no arguments returning None */
+
+static object *
+xx_bar(self, args)
+ object *self; /* Not used */
+ object *args;
+{
+ int i, j;
+ if (!getnoarg(args))
+ return NULL;
+ /* XXX Do something here */
+ INCREF(None);
+ return None;
+}
+
+
+/* List of functions defined in the module */
+
+static struct methodlist xx_methods[] = {
+ {"foo", xx_foo},
+ {"bar", xx_bar},
+ {NULL, NULL} /* sentinel */
+};
+
+
+/* Initialization function for the module (*must* be called initxx) */
+
+void
+initxx()
+{
+ object *m, *d, *x;
+
+ /* Create the module and add the functions */
+ m = initmodule("xx", xx_methods);
+
+ /* Add some symbolic constants to the module */
+ d = getmoduledict(m);
+ x = newstringobject("xx.error");
+ dictinsert(d, "error", x);
+ x = newintobject(42L);
+ dictinsert(d, "magic", x);
+
+ /* Check for errors */
+ if (err_occurred())
+ fatal("can't initialize module xx");
+}
diff --git a/Objects/fileobject.c b/Objects/fileobject.c
index b026413..99f4e5e 100644
--- a/Objects/fileobject.c
+++ b/Objects/fileobject.c
@@ -321,6 +321,7 @@ getline(f, n)
fileobject *f;
int n;
{
+ void *save, *save_thread(), restore_thread();
register FILE *fp;
register int c;
register char *buf, *end;
@@ -334,16 +335,19 @@ getline(f, n)
return NULL;
buf = BUF(v);
end = buf + n2;
-
+
+ save = save_thread();
for (;;) {
if ((c = getc(fp)) == EOF) {
clearerr(fp);
if (intrcheck()) {
+ restore_thread(save);
DECREF(v);
err_set(KeyboardInterrupt);
return NULL;
}
if (n < 0 && buf == BUF(v)) {
+ restore_thread(save);
DECREF(v);
err_setstr(EOFError,
"EOF when reading a line");
@@ -361,13 +365,16 @@ getline(f, n)
break;
n1 = n2;
n2 += 1000;
+ restore_thread(save);
if (resizestring(&v, n2) < 0)
return NULL;
+ save = save_thread();
buf = BUF(v) + n1;
end = BUF(v) + n2;
}
}
-
+ restore_thread(save);
+
n1 = buf - BUF(v);
if (n1 != n2)
resizestring(&v, n1);
diff --git a/Python/ceval.c b/Python/ceval.c
index 0b2f924..32c52c7 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -84,6 +84,79 @@ static object *build_class PROTO((object *, object *));
static frameobject *current_frame;
+/* Interface for threads.
+
+ A module that plans to do a blocking system call (or something else
+ that lasts a long time and doesn't touch Python data) can allow other
+ threads to run as follows:
+
+ void *x;
+
+ ...preparations here...
+ x = save_thread();
+ ...blocking system call here...
+ restore_thread(x);
+ ...interpretr result here...
+
+ For convenience, that the value of 'errno' is restored across the
+ the call to restore_thread().
+
+ The function init_save_thread() should be called only from
+ initthread() in "threadmodule.c".
+
+ Note that not yet all candidates have been converted to use this
+ mechanism!
+*/
+
+#ifdef USE_THREAD
+#include <errno.h>
+#include "thread.h"
+static type_lock interpreter_lock;
+
+void
+init_save_thread()
+{
+#ifdef USE_THREAD
+ if (interpreter_lock)
+ fatal("2nd call to init_save_thread");
+ interpreter_lock = allocate_lock();
+ acquire_lock(interpreter_lock, 1);
+#endif
+}
+#endif
+
+void *
+save_thread()
+{
+#ifdef USE_THREAD
+ if (interpreter_lock) {
+ void *res;
+ res = (void *)current_frame;
+ current_frame = NULL;
+ release_lock(interpreter_lock);
+ return res;
+ }
+ else
+ return NULL;
+#endif
+}
+
+void
+restore_thread(x)
+ void *x;
+{
+#ifdef USE_THREAD
+ if (interpreter_lock) {
+ int err;
+ err = errno;
+ acquire_lock(interpreter_lock, 1);
+ errno = err;
+ current_frame = (frameobject *)x;
+ }
+#endif
+}
+
+
/* Status code for main loop (reason for stack unwind) */
enum why_code {
@@ -210,17 +283,34 @@ eval_code(co, globals, locals, arg)
for (;;) {
static int ticker;
- /* Do periodic things */
+ /* 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. */
if (--ticker < 0) {
- ticker = 100;
+ ticker = 10;
if (intrcheck()) {
err_set(KeyboardInterrupt);
why = WHY_EXCEPTION;
goto on_error;
}
+
+#ifdef USE_THREAD
+ if (interpreter_lock) {
+ /* Give another thread a chance */
+
+ current_frame = NULL;
+ release_lock(interpreter_lock);
+
+ /* Other threads may run now */
+
+ acquire_lock(interpreter_lock, 1);
+ current_frame = f;
+ }
+#endif
}
-
+
/* Extract opcode and argument */
opcode = NEXTOP();
diff --git a/Python/pythonmain.c b/Python/pythonmain.c
index a141168..0f76bfd 100644
--- a/Python/pythonmain.c
+++ b/Python/pythonmain.c
@@ -26,23 +26,10 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#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 "ceval.h"
-#include "pythonrun.h"
-#include "import.h"
-
extern char *getpythonpath();
-extern grammar gram; /* From graminit.c */
-
-int debugging; /* Needed by parser.c */
-int verbose; /* Needed by import.c */
+extern int debugging; /* Needed by parser.c */
+extern int verbose; /* Needed by import.c */
/* Interface to getopt(): */
extern int optind;
@@ -108,12 +95,12 @@ main(argc, argv)
initall();
- setpythonpath(getpythonpath());
if (command != NULL) {
/* Backup optind and force sys.argv[0] = '-c' */
optind--;
argv[optind] = "-c";
}
+
setpythonargv(argc-optind, argv+optind);
if (command) {
@@ -126,368 +113,3 @@ main(argc, argv)
goaway(sts);
/*NOTREACHED*/
}
-
-/* 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 should be initialized
- by the initcalls() of a specific configuration. */
-
- initbuiltin(); /* Also initializes builtin exceptions */
- initsys();
-
- initcalls(); /* Configuration-dependent initializations */
-
- initintr(); /* For intrcheck() */
-}
-
-/* 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 = "";
- }
- err = parsefile(fp, filename, &gram, single_input, ps1, ps2, &n);
- 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;
- err_get(&exception, &v);
- if (exception == SystemExit) {
- if (v == NULL || v == None)
- goaway(0);
- if (is_intobject(v))
- goaway((int)getintvalue(v));
- else {
- printobject(v, stderr, PRINT_RAW);
- fprintf(stderr, "\n");
- goaway(1);
- }
- }
- sysset("last_type", exception);
- sysset("last_value", v);
- if (printobject(exception, stderr, PRINT_RAW) != 0)
- err_clear();
- if (v != NULL && v != None) {
- fprintf(stderr, ": ");
- if (printobject(v, stderr, PRINT_RAW) != 0)
- err_clear();
- }
- fprintf(stderr, "\n");
- XDECREF(exception);
- XDECREF(v);
- printtraceback(stderr);
-}
-
-object *
-run_string(str, start, globals, locals)
- char *str;
- int start;
- /*dict*/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;
- /*dict*/object *globals, *locals;
-{
- node *n;
- int err;
- err = parse_file(fp, filename, start, &n);
- return run_err_node(err, n, filename, globals, locals);
-}
-
-object *
-run_err_node(err, n, filename, globals, locals)
- int err;
- node *n;
- char *filename;
- /*dict*/object *globals, *locals;
-{
- if (err != E_DONE) {
- err_input(err);
- return NULL;
- }
- return run_node(n, filename, globals, locals);
-}
-
-object *
-run_node(n, filename, globals, locals)
- node *n;
- char *filename;
- /*dict*/object *globals, *locals;
-{
- if (globals == NULL) {
- globals = getglobals();
- if (locals == NULL)
- locals = getlocals();
- }
- else {
- if (locals == NULL)
- locals = globals;
- }
- return eval_node(n, filename, globals, locals);
-}
-
-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);
- DECREF(co);
- return v;
-}
-
-/* Simplified interface to parsefile */
-
-int
-parse_file(fp, filename, start, n_ret)
- FILE *fp;
- char *filename;
- int start;
- node **n_ret;
-{
- return parsefile(fp, filename, &gram, start,
- (char *)0, (char *)0, n_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 */
-
-void
-goaway(sts)
- int sts;
-{
- flushline();
-
- /* 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);
- /*NOTREACHED*/
-}
-
-#ifdef TRACE_REFS
-/* Ask a yes/no question */
-
-static 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
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
new file mode 100644
index 0000000..2a68f24
--- /dev/null
+++ b/Python/pythonrun.c
@@ -0,0 +1,424 @@
+/***********************************************************
+Copyright 1991, 1992 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 "ceval.h"
+#include "pythonrun.h"
+#include "import.h"
+
+#ifdef USE_THREAD
+extern void *save_thread();
+#endif
+
+extern char *getpythonpath();
+
+extern grammar gram; /* From graminit.c */
+
+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 */
+
+ initintr(); /* For intrcheck() */
+
+ setpythonpath(getpythonpath());
+}
+
+/* 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;
+{
+ void *save, *save_thread(), restore_thread();
+ 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 = "";
+ }
+ save = save_thread();
+ err = parsefile(fp, filename, &gram, single_input, ps1, ps2, &n);
+ restore_thread(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;
+ err_get(&exception, &v);
+ if (exception == SystemExit) {
+ if (v == NULL || v == None)
+ goaway(0);
+ if (is_intobject(v))
+ goaway((int)getintvalue(v));
+ else {
+ printobject(v, stderr, PRINT_RAW);
+ fprintf(stderr, "\n");
+ goaway(1);
+ }
+ }
+ sysset("last_type", exception);
+ sysset("last_value", v);
+ if (printobject(exception, stderr, PRINT_RAW) != 0)
+ err_clear();
+ if (v != NULL && v != None) {
+ fprintf(stderr, ": ");
+ if (printobject(v, stderr, PRINT_RAW) != 0)
+ err_clear();
+ }
+ fprintf(stderr, "\n");
+ XDECREF(exception);
+ XDECREF(v);
+ printtraceback(stderr);
+}
+
+object *
+run_string(str, start, globals, locals)
+ char *str;
+ int start;
+ /*dict*/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;
+ /*dict*/object *globals, *locals;
+{
+ node *n;
+ int err;
+ err = parse_file(fp, filename, start, &n);
+ return run_err_node(err, n, filename, globals, locals);
+}
+
+object *
+run_err_node(err, n, filename, globals, locals)
+ int err;
+ node *n;
+ char *filename;
+ /*dict*/object *globals, *locals;
+{
+ if (err != E_DONE) {
+ err_input(err);
+ return NULL;
+ }
+ return run_node(n, filename, globals, locals);
+}
+
+object *
+run_node(n, filename, globals, locals)
+ node *n;
+ char *filename;
+ /*dict*/object *globals, *locals;
+{
+ if (globals == NULL) {
+ globals = getglobals();
+ if (locals == NULL)
+ locals = getlocals();
+ }
+ else {
+ if (locals == NULL)
+ locals = globals;
+ }
+ return eval_node(n, filename, globals, locals);
+}
+
+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);
+ DECREF(co);
+ return v;
+}
+
+/* Simplified interface to parsefile */
+
+int
+parse_file(fp, filename, start, n_ret)
+ FILE *fp;
+ char *filename;
+ int start;
+ node **n_ret;
+{
+ return parsefile(fp, filename, &gram, start,
+ (char *)0, (char *)0, n_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 */
+
+void
+goaway(sts)
+ int sts;
+{
+ flushline();
+
+ /* 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 */
+
+#ifdef USE_THREAD
+ (void) save_thread();
+ exit_prog(sts);
+#else
+ exit(sts);
+#endif
+ /*NOTREACHED*/
+}
+
+#ifdef TRACE_REFS
+/* Ask a yes/no question */
+
+static 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
diff --git a/Python/thread.c b/Python/thread.c
new file mode 100644
index 0000000..1f0633a
--- /dev/null
+++ b/Python/thread.c
@@ -0,0 +1,263 @@
+#include "thread.h"
+
+#ifdef __sgi
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/prctl.h>
+#include <ulocks.h>
+
+static usptr_t *shared_arena;
+static int exit_status;
+static int do_exit;
+static int exiting;
+#endif
+#ifdef sun
+#include <lwp/lwp.h>
+#include <lwp/stackdep.h>
+
+#define STACKSIZE 1000 /* stacksize for a thread */
+#define NSTACKS 2 /* # stacks to be put in cache initialy */
+
+struct lock {
+ int lock_locked;
+ cv_t lock_condvar;
+ mon_t lock_monitor;
+};
+#endif
+#ifdef C_THREADS
+#include <cthreads.h>
+#endif
+
+#ifdef __STDC__
+#define _P(args) args
+#define _P0() (void)
+#define _P1(v,t) (t)
+#define _P2(v1,t1,v2,t2) (t1,t2)
+#else
+#define _P(args) ()
+#define _P0() ()
+#define _P1(v,t) (v) t;
+#define _P2(v1,t1,v2,t2) (v1,v2) t1; t2;
+#endif
+
+static int initialized;
+
+int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
+{
+#ifdef sun
+ thread_t tid;
+#endif
+#ifdef DEBUG
+ printf("start_new_thread called\n");
+#endif
+ if (!initialized)
+ init_thread();
+#ifdef __sgi
+ if (sproc(func, PR_SALL, arg) < 0)
+ return 0;
+ return 1;
+#endif
+#ifdef SOLARIS
+ (void) thread_create(0, 0, func, arg, THREAD_NEW_LWP);
+#endif
+#ifdef sun
+ if (lwp_create(&tid, func, MINPRIO, 0, lwp_newstk(), 1, arg) < 0)
+ return 0;
+ return 1;
+#endif
+#ifdef C_THREADS
+ (void) cthread_fork(func, arg);
+#endif
+}
+
+#ifdef __sgi
+void maybe_exit _P0()
+{
+ if (exiting)
+ return;
+ exit_prog(0);
+}
+#endif
+
+void exit_thread _P0()
+{
+#ifdef DEBUG
+ printf("exit_thread called\n");
+#endif
+ if (!initialized)
+ exit(0);
+#ifdef __sgi
+ exiting = 1;
+ exit(0);
+#endif
+#ifdef SOLARIS
+ thread_exit();
+#endif
+#ifdef sun
+ lwp_destroy(SELF);
+#endif
+#ifdef C_THREADS
+ cthread_exit(0);
+#endif
+}
+
+#ifdef __sgi
+static void exit_sig _P0()
+{
+#ifdef DEBUG
+ printf("exit_sig called\n");
+#endif
+ if (do_exit) {
+#ifdef DEBUG
+ printf("exiting in exit_sig\n");
+#endif
+ exit(exit_status);
+ }
+}
+#endif
+
+void init_thread _P0()
+{
+#ifdef __sgi
+ struct sigaction s;
+#endif
+
+#ifdef DEBUG
+ printf("init_thread called\n");
+#endif
+ initialized = 1;
+
+#ifdef __sgi
+ atexit(maybe_exit);
+ s.sa_handler = exit_sig;
+ sigemptyset(&s.sa_mask);
+ sigaddset(&s.sa_mask, SIGUSR1);
+ s.sa_flags = 0;
+ sigaction(SIGUSR1, &s, 0);
+ prctl(PR_SETEXITSIG, SIGUSR1);
+ usconfig(CONF_ARENATYPE, US_SHAREDONLY);
+ /*usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);*/
+ shared_arena = usinit(tmpnam(0));
+#endif
+#ifdef sun
+ lwp_setstkcache(STACKSIZE, NSTACKS);
+#endif
+#ifdef C_THREADS
+ cthread_init();
+#endif
+}
+
+type_lock allocate_lock _P0()
+{
+#ifdef __sgi
+ ulock_t lock;
+#endif
+#ifdef sun
+ struct lock *lock;
+ extern char *malloc();
+#endif
+
+#ifdef DEBUG
+ printf("allocate_lock called\n");
+#endif
+ if (!initialized)
+ init_thread();
+
+#ifdef __sgi
+ lock = usnewlock(shared_arena);
+ (void) usinitlock(lock);
+#endif
+#ifdef sun
+ lock = (struct lock *) malloc(sizeof(struct lock));
+ lock->lock_locked = 0;
+ (void) mon_create(&lock->lock_monitor);
+ (void) cv_create(&lock->lock_condvar, lock->lock_monitor);
+#endif
+#ifdef DEBUG
+ printf("allocate_lock() -> %lx\n", (long)lock);
+#endif
+ return (type_lock) lock;
+}
+
+void free_lock _P1(lock, type_lock lock)
+{
+#ifdef DEBUG
+ printf("free_lock(%lx) called\n", (long)lock);
+#endif
+#ifdef __sgi
+ usfreelock((ulock_t) lock, shared_arena);
+#endif
+#ifdef sun
+ mon_destroy(((struct lock *) lock)->lock_monitor);
+ free((char *) lock);
+#endif
+}
+
+int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag)
+{
+ int success;
+
+#ifdef DEBUG
+ printf("acquire_lock(%lx, %d) called\n", (long)lock, waitflag);
+#endif
+#ifdef __sgi
+ if (waitflag)
+ success = ussetlock((ulock_t) lock);
+ else
+ success = uscsetlock((ulock_t) lock, 1); /* Try it once */
+#endif
+#ifdef sun
+ success = 0;
+
+ (void) mon_enter(((struct lock *) lock)->lock_monitor);
+ if (waitflag)
+ while (((struct lock *) lock)->lock_locked)
+ cv_wait(((struct lock *) lock)->lock_condvar);
+ if (!((struct lock *) lock)->lock_locked) {
+ success = 1;
+ ((struct lock *) lock)->lock_locked = 1;
+ }
+ cv_broadcast(((struct lock *) lock)->lock_condvar);
+ mon_exit(((struct lock *) lock)->lock_monitor);
+#endif
+#ifdef DEBUG
+ printf("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success);
+#endif
+ return success;
+}
+
+void release_lock _P1(lock, type_lock lock)
+{
+#ifdef DEBUG
+ printf("release lock(%lx) called\n", (long)lock);
+#endif
+#ifdef __sgi
+ (void) usunsetlock((ulock_t) lock);
+#endif
+#ifdef sun
+ (void) mon_enter(((struct lock *) lock)->lock_monitor);
+ ((struct lock *) lock)->lock_locked = 0;
+ cv_broadcast(((struct lock *) lock)->lock_condvar);
+ mon_exit(((struct lock *) lock)->lock_monitor);
+#endif
+}
+
+void exit_prog _P1(status, int status)
+{
+#ifdef DEBUG
+ printf("exit_prog(%d) called\n", status);
+#endif
+ if (!initialized)
+ exit(status);
+#ifdef __sgi
+ exiting = 1;
+ do_exit = 1;
+ exit_status = status;
+ exit(status);
+#endif
+#ifdef sun
+ pod_exit(status);
+#endif
+}