* bltinmodule.c: added built-in function cmp(a, b)

* flmodule.c: added {do,check}_only_forms to fl's list of functions;
  and don't print a message when an unknown object is returned.

* pythonrun.c: catch SIGHUP and SIGTERM to do essential cleanup.

* Made jpegmodule.c smaller by using getargs() and mkvalue() consistently.

* Increased parser stack size to 500 in parser.h.

* Implemented custom allocation of stack frames to frameobject.c and
  added dynamic stack overflow checks (value stack only) to ceval.c.
  (There seems to be a bug left: sometimes stack traces don't make sense.)
diff --git a/Include/frameobject.h b/Include/frameobject.h
index e1f8190..dd36468 100644
--- a/Include/frameobject.h
+++ b/Include/frameobject.h
@@ -81,3 +81,7 @@
 
 void setup_block PROTO((frameobject *, int, int, int));
 block *pop_block PROTO((frameobject *));
+
+/* Extend the value stack */
+
+object **extend_stack PROTO((frameobject *, int, int));
diff --git a/Modules/flmodule.c b/Modules/flmodule.c
index 34f0121..dca39ad 100644
--- a/Modules/flmodule.c
+++ b/Modules/flmodule.c
@@ -2078,10 +2078,7 @@
 		}
 		g = findgeneric(generic);
 		if (g == NULL) {
-			/* XXX What kind of weird object is this? */
-			/* XXX Maybe caused by a bug here */
-			fprintf(stderr, "weird object: class %d, label '%s'\n",
-				generic->objclass, generic->label);
+			/* Object not known to us (some dialogs cause this) */
 			continue; /* Ignore it */
 		}
 		if (g->ob_callback == NULL) {
@@ -2572,7 +2569,9 @@
 	{"getmcolor",		forms_getmcolor},
 /* interaction */
 	{"do_forms",		forms_do_forms},
+	{"do_only_forms",	forms_do_only_forms},
 	{"check_forms",		forms_check_forms},
+	{"check_only_forms",	forms_check_only_forms},
 	{"set_event_call_back",	forms_set_event_call_back},
 /* goodies */
 	{"show_message",	forms_show_message},
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index a68704c..c7b5ddf 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -51,6 +51,29 @@
 	return getmember((char *)f, frame_memberlist, name);
 }
 
+/* Stack frames are allocated and deallocated at a considerable rate.
+   In an attempt to improve the speed of function calls, we maintain a
+   separate free list of stack frames (just like integers are
+   allocated in a special way -- see intobject.c).  When a stack frame
+   is on the free list, only the following members have a meaning:
+	ob_type		== &Frametype
+	f_back		next item on free list, or NULL
+	f_nvalues	size of f_valuestack
+	f_valuestack	array of (f_nvalues+1) object pointers, or NULL
+	f_nblocks	size of f_blockstack
+	f_blockstack	array of (f_nblocks+1) blocks, or NULL
+   Note that the value and block stacks are preserved -- this can save
+   another malloc() call or two (and two free() calls as well!).
+   Also note that, unlike for integers, each frame object is a
+   malloc'ed object in its own right -- it is only the actual calls to
+   malloc() that we are trying to save here, not the administration.
+   After all, while a typical program may make millions of calls, a
+   call depth of more than 20 or 30 is probably already exceptional
+   unless the program contains run-away recursion.  I hope.
+*/
+
+static frameobject *free_list = NULL;
+
 static void
 frame_dealloc(f)
 	frameobject *f;
@@ -59,9 +82,8 @@
 	XDECREF(f->f_code);
 	XDECREF(f->f_globals);
 	XDECREF(f->f_locals);
-	XDEL(f->f_valuestack);
-	XDEL(f->f_blockstack);
-	DEL(f);
+	f->f_back = free_list;
+	free_list = f;
 }
 
 typeobject Frametype = {
@@ -99,7 +121,17 @@
 		err_badcall();
 		return NULL;
 	}
-	f = NEWOBJ(frameobject, &Frametype);
+	if (free_list == NULL) {
+		f = NEWOBJ(frameobject, &Frametype);
+		f->f_nvalues = f->f_nblocks = 0;
+		f->f_valuestack = NULL;
+		f->f_blockstack = NULL;
+	}
+	else {
+		f = free_list;
+		free_list = free_list->f_back;
+		NEWREF(f);
+	}
 	if (f != NULL) {
 		if (back)
 			INCREF(back);
@@ -110,22 +142,45 @@
 		f->f_globals = globals;
 		INCREF(locals);
 		f->f_locals = locals;
-		f->f_valuestack = NEW(object *, nvalues+1);
-		f->f_blockstack = NEW(block, nblocks+1);
-		f->f_nvalues = nvalues;
-		f->f_nblocks = nblocks;
+		if (nvalues > f->f_nvalues || f->f_valuestack == NULL) {
+			XDEL(f->f_valuestack);
+			f->f_valuestack = NEW(object *, nvalues+1);
+			f->f_nvalues = nvalues;
+		}
+		if (nblocks > f->f_nblocks || f->f_blockstack == NULL) {
+			XDEL(f->f_blockstack);
+			f->f_blockstack = NEW(block, nblocks+1);
+			f->f_nblocks = nblocks;
+		}
 		f->f_iblock = 0;
+		f->f_lasti = 0;
+		f->f_lineno = -1;
 		if (f->f_valuestack == NULL || f->f_blockstack == NULL) {
 			err_nomem();
 			DECREF(f);
 			f = NULL;
 		}
-		f->f_lasti = 0;
-		f->f_lineno = -1;
 	}
 	return f;
 }
 
+object **
+extend_stack(f, level, incr)
+	frameobject *f;
+	int level;
+	int incr;
+{
+	f->f_nvalues = level + incr + 10;
+	f->f_valuestack =
+		(object **) realloc((ANY *)f->f_valuestack,
+				    sizeof(object *) * (f->f_nvalues + 1));
+	if (f->f_valuestack == NULL) {
+		err_nomem();
+		return NULL;
+	}
+	return f->f_valuestack + level;
+}
+
 /* Block management */
 
 void
diff --git a/Parser/parser.h b/Parser/parser.h
index 72aa927..2c0e327 100644
--- a/Parser/parser.h
+++ b/Parser/parser.h
@@ -24,7 +24,7 @@
 
 /* Parser interface */
 
-#define MAXSTACK 100
+#define MAXSTACK 500
 
 typedef struct _stackentry {
 	int		 s_state;	/* State in current DFA */
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 9ba07af..18fae5c 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -78,6 +78,17 @@
 }
 
 static object *
+builtin_cmp(self, args)
+	object *self;
+	object *args;
+{
+	object *a, *b;
+	if (!getargs(args, "(OO)", &a, &b))
+		return NULL;
+	return newintobject((long)cmpobject(a, b));
+}
+
+static object *
 builtin_coerce(self, args)
 	object *self;
 	object *args;
@@ -608,6 +619,7 @@
 	{"abs",		builtin_abs},
 	{"apply",	builtin_apply},
 	{"chr",		builtin_chr},
+	{"cmp",		builtin_cmp},
 	{"coerce",	builtin_coerce},
 	{"dir",		builtin_dir},
 	{"divmod",	builtin_divmod},
diff --git a/Python/ceval.c b/Python/ceval.c
index 4637d35..d3a732a 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -204,6 +204,9 @@
 #define BASIC_PUSH(v)	(*stack_pointer++ = (v))
 #define BASIC_POP()	(*--stack_pointer)
 
+#define CHECK_STACK(n)	(STACK_LEVEL() + (n) < f->f_nvalues || \
+			  (stack_pointer = extend_stack(f, STACK_LEVEL(), n)))
+
 #ifdef LLTRACE
 #define PUSH(v)		(BASIC_PUSH(v), lltrace && prtrace(TOP(), "push"))
 #define POP()		(lltrace && prtrace(TOP(), "pop"), BASIC_POP())
@@ -324,6 +327,11 @@
 		}
 #endif
 
+		if (!CHECK_STACK(3)) {
+			x = NULL;
+			break;
+		}
+
 		/* Main switch on opcode */
 		
 		switch (opcode) {
@@ -763,6 +771,10 @@
 				x = gettupleslice(v, oparg, gettuplesize(v));
 				if (x != NULL) {
 					PUSH(x);
+					if (!CHECK_STACK(oparg)) {
+						x = NULL;
+						break;
+					}
 					for (; --oparg >= 0; ) {
 						w = gettupleitem(v, oparg);
 						INCREF(w);
@@ -858,6 +870,10 @@
 				why = WHY_EXCEPTION;
 			}
 			else {
+				if (!CHECK_STACK(oparg)) {
+					x = NULL;
+					break;
+				}
 				for (; --oparg >= 0; ) {
 					w = gettupleitem(v, oparg);
 					INCREF(w);
@@ -879,6 +895,10 @@
 				why = WHY_EXCEPTION;
 			}
 			else {
+				if (!CHECK_STACK(oparg)) {
+					x = NULL;
+					break;
+				}
 				for (; --oparg >= 0; ) {
 					w = getlistitem(v, oparg);
 					INCREF(w);
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index 90a4294..1bcc083 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -38,10 +38,21 @@
 #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 */
 
+void initsigs(); /* Forward */
+
 int debugging; /* Needed by parser.c */
 int verbose; /* Needed by import.c */
 
@@ -67,10 +78,10 @@
 	initsys();
 	
 	initcalls(); /* Configuration-dependent initializations */
-	
-	initintr(); /* For intrcheck() */
 
 	setpythonpath(getpythonpath());
+
+	initsigs(); /* Signal handling stuff, including initintr() */
 }
 
 /* Parse input from a file and execute it */
@@ -372,8 +383,7 @@
 #endif
 
 void
-goaway(sts)
-	int sts;
+cleanup()
 {
 	object *exitfunc = sysget("exitfunc");
 
@@ -395,6 +405,13 @@
 	}
 
 	flushline();
+}
+
+void
+goaway(sts)
+	int sts;
+{
+	cleanup();
 
 #ifdef USE_THREAD
 
@@ -433,6 +450,30 @@
 	/*NOTREACHED*/
 }
 
+#ifdef HANDLE_SIGNALS
+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
+
+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 */