* Python/bltinmodule.c (builtin_vars): correct typo in error msg
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index c8a8e83..d8e0d26 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -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
@@ -63,9 +63,52 @@
 	object *func, *arglist;
 	if (!getargs(args, "(OO)", &func, &arglist))
 		return NULL;
+	if (!is_tupleobject(arglist)) {
+		err_setstr(TypeError, "apply() 2nd argument must be tuple");
+		return NULL;
+	}
 	return call_object(func, arglist);
 }
 
+static int
+callable(x)
+	object *x;
+{
+	if (x == NULL)
+		return 0;
+	if (x->ob_type->tp_call != NULL ||
+	    is_funcobject(x) ||
+	    is_instancemethodobject(x) ||
+	    is_methodobject(x) ||
+	    is_classobject(x))
+		return 1;
+	if (is_instanceobject(x)) {
+		object *call = getattr(x, "__call__");
+		if (call == NULL) {
+			err_clear();
+			return 0;
+		}
+		/* Could test recursively but don't, for fear of endless
+		   recursion if some joker sets self.__call__ = self */
+		DECREF(call);
+		return 1;
+	}
+	return 0;
+}
+
+static object *
+builtin_callable(self, args)
+	object *self;
+	object *args;
+{
+	if (args == NULL) {
+		err_setstr(TypeError,
+			   "callable requires exactly one argument");
+		return NULL;
+	}
+	return newintobject((long)callable(args));
+}
+
 static object *
 builtin_filter(self, args)
 	object *self;
@@ -107,12 +150,19 @@
 			goto Fail_2;
 	}
 
-	for (i = j = 0; i < len; ++i) {
+	for (i = j = 0; ; ++i) {
 		object *item, *good;
 		int ok;
 
-		if ((item = (*sqf->sq_item)(seq, i)) == NULL)
+		if ((item = (*sqf->sq_item)(seq, i)) == NULL) {
+			if (i < len)
+				goto Fail_1;
+			if (err_occurred() == IndexError) {
+				err_clear();
+				break;
+			}
 			goto Fail_1;
+		}
 
 		if (func == None) {
 			good = item;
@@ -131,13 +181,20 @@
 		DECREF(good);
 		if (ok) {
 			INCREF(item);
-			if (setlistitem(result, j++, item) < 0)
-				goto Fail_1;
+			if (j < len) {
+				if (setlistitem(result, j++, item) < 0)
+					goto Fail_1;
+			}
+			else {
+				j++;
+				if (addlistitem(result, item) < 0)
+					goto Fail_1;
+			}
 		}
 	}
 
 
-	if (setlistslice(result, j, len, NULL) < 0)
+	if (j < len && setlistslice(result, j, len, NULL) < 0)
 		goto Fail_1;
 
 	return result;
@@ -453,7 +510,7 @@
 		goto Fail_2;
 	}
 
-	for (len = -1, i = 0, sqp = seqs; i < n; ++i, ++sqp) {
+	for (len = 0, i = 0, sqp = seqs; i < n; ++i, ++sqp) {
 		int curlen;
 	
 		if ((sqp->seq = gettupleitem(args, i + 1)) == NULL)
@@ -480,55 +537,81 @@
 		goto Fail_2;
 
 	/* XXX Special case map(None, single_list) could be more efficient */
-	for (i = 0; i < len; ++i) {
-		object *arglist, *item;
+	for (i = 0; ; ++i) {
+		object *arglist, *item, *value;
+		int any = 0;
 
-		if ((arglist = newtupleobject(n)) == NULL)
-			goto Fail_1;
+		if (func == None && n == 1)
+			arglist = NULL;
+		else {
+			if ((arglist = newtupleobject(n)) == NULL)
+				goto Fail_1;
+		}
 
 		for (j = 0, sqp = seqs; j < n; ++j, ++sqp) {
-			if (i >= sqp->len) {
+			if (sqp->len < 0) {
 				INCREF(None);
 				item = None;
 			}
 			else {
 				item = (*sqp->sqf->sq_item)(sqp->seq, i);
-				if (item == NULL)
-					goto Fail_0;
+				if (item == NULL) {
+					if (i < sqp->len)
+						goto Fail_0;
+					if (err_occurred() == IndexError) {
+						err_clear();
+						INCREF(None);
+						item = None;
+						sqp->len = -1;
+					}
+					else {
+						goto Fail_0;
+					}
+				}
+				else
+					any = 1;
 
 			}
-			if (settupleitem(arglist, j, item) < 0)
+			if (!arglist)
+				break;
+			if (settupleitem(arglist, j, item) < 0) {
+				DECREF(item);
 				goto Fail_0;
+			}
 			continue;
 
 		Fail_0:
-			DECREF(arglist);
+			XDECREF(arglist);
 			goto Fail_1;
 		}
 
-		if (func == None) {
-			if (n == 1)	{ /* avoid creating singleton */
-				INCREF(item); /* This is arglist[0] !!! */
-				DECREF(arglist);
-				if (setlistitem(result, i, item) < 0)
-					goto Fail_1;
-			}
-			else {
-				if (setlistitem(result, i, arglist) < 0)
-					goto Fail_1;
-			}
+		if (!arglist)
+			arglist = item;
+
+		if (!any) {
+			DECREF(arglist);
+			break;
 		}
+
+		if (func == None)
+			value = arglist;
 		else {
-			object *value = call_object(func, arglist);
+			value = call_object(func, arglist);
 			DECREF(arglist);
 			if (value == NULL)
 				goto Fail_1;
-			if (setlistitem((object *) result, i, value) < 0)
+		}
+		if (i >= len) {
+			if (addlistitem(result, value) < 0)
+				goto Fail_1;
+		}
+		else {
+			if (setlistitem(result, i, value) < 0)
 				goto Fail_1;
 		}
 	}
 
-	if (seqs) DEL(seqs);
+	DEL(seqs);
 	return result;
 
 Fail_1:
@@ -665,7 +748,7 @@
 	object *v;
 	int sign;
 {
-	int i, n, cmp;
+	int i;
 	object *w, *x;
 	sequence_methods *sq;
 	if (v == NULL) {
@@ -677,24 +760,30 @@
 		err_setstr(TypeError, "min() or max() of non-sequence");
 		return NULL;
 	}
-	n = (*sq->sq_length)(v);
-	if (n < 0)
-		return NULL;
-	if (n == 0) {
-		err_setstr(ValueError, "min() or max() of empty sequence");
-		return NULL;
-	}
-	w = (*sq->sq_item)(v, 0); /* Implies INCREF */
-	for (i = 1; i < n; i++) {
+	w = NULL;
+	for (i = 0; ; i++) {
 		x = (*sq->sq_item)(v, i); /* Implies INCREF */
-		cmp = cmpobject(x, w);
-		if (cmp * sign > 0) {
-			DECREF(w);
-			w = x;
+		if (x == NULL) {
+			if (err_occurred() == IndexError) {
+				err_clear();
+				break;
+			}
+			XDECREF(w);
+			return NULL;
 		}
-		else
-			DECREF(x);
+		if (w == NULL)
+			w = x;
+		else {
+			if (cmpobject(x, w) * sign > 0) {
+				DECREF(w);
+				w = x;
+			}
+			else
+				DECREF(x);
+		}
 	}
+	if (w == NULL)
+		err_setstr(ValueError, "min() or max() of empty sequence");
 	return w;
 }
 
@@ -735,10 +824,18 @@
 	object *self;
 	object *args;
 {
-	char *name, *mode;
-	if (!getargs(args, "(ss)", &name, &mode))
+	char *name;
+	char *mode = "r";
+	int bufsize = -1;
+	object *f;
+	if (!getargs(args, "s", &name) &&
+	    (err_clear(), !getargs(args, "(ss)", &name, &mode)) &&
+	    (err_clear(), !getargs(args, "(ssi)", &name, &mode, &bufsize)))
 		return NULL;
-	return newfileobject(name, mode);
+	f = newfileobject(name, mode);
+	if (f != NULL)
+		setfilebufsize(f, bufsize);
+	return f;
 }
 
 static object *
@@ -920,25 +1017,15 @@
 {
 	object *seq, *func, *result;
 	sequence_methods *sqf;
-	static char reduce_err[] = "reduce() requires 2 or 3 args";
 	register int i;
-	int start = 0;
-	int len;
 
-	if (args == NULL || !is_tupleobject(args)) {
-		err_setstr(TypeError, reduce_err);
-		return NULL;
-	}
-
-	switch (gettuplesize(args)) {
-	case 2:
-		start = 1;		/* fall through */
-	case 3:
-		func = gettupleitem(args, 0);
-		seq  = gettupleitem(args, 1);
-		break;
-	default:
-		err_setstr(TypeError, reduce_err);
+	if (getargs(args, "(OO)", &func, &seq))
+		result = NULL;
+	else {
+		err_clear();
+		if (!getargs(args, "(OOO)", &func, &seq, &result))
+			return NULL;
+		INCREF(result);
 	}
 
 	if ((sqf = seq->ob_type->tp_as_sequence) == NULL) {
@@ -947,55 +1034,47 @@
 		return NULL;
 	}
 
-	if ((len = (*sqf->sq_length)(seq)) < 0)
-		goto Fail_2;
-
-	if (start == 1) {
-		if (len == 0) {
-			err_setstr(TypeError,
-			    "reduce of empty sequence with no initial value");
-			goto Fail_2;
-		}
-
-		if ((result = (*sqf->sq_item)(seq, 0)) == NULL)
-			goto Fail_2;
-	}
-	else {
-		result = gettupleitem(args, 2);
-		INCREF(result);
-	}
-
 	if ((args = newtupleobject(2)) == NULL)
-		goto Fail_1;
+		goto Fail;
 
-	for (i = start; i < len; ++i) {
+	for (i = 0; ; ++i) {
 		object *op2;
 
 		if (args->ob_refcnt > 1) {
 			DECREF(args);
 			if ((args = newtupleobject(2)) == NULL)
-				goto Fail_1;
+				goto Fail;
 		}
 
-		if ((op2 = (*sqf->sq_item)(seq, i)) == NULL)
-			goto Fail_2;
+		if ((op2 = (*sqf->sq_item)(seq, i)) == NULL) {
+			if (err_occurred() == IndexError) {
+				err_clear();
+				break;
+			}
+			goto Fail;
+		}
 
-		settupleitem(args, 0, result);
-		settupleitem(args, 1, op2);
-		if ((result = call_object(func, args)) == NULL)
-			goto Fail_0;
+		if (result == NULL)
+			result = op2;
+		else {
+			settupleitem(args, 0, result);
+			settupleitem(args, 1, op2);
+			if ((result = call_object(func, args)) == NULL)
+				goto Fail;
+		}
 	}
 
 	DECREF(args);
 
+	if (result == NULL)
+		err_setstr(TypeError,
+			   "reduce of empty sequence with no initial value");
+
 	return result;
 
-Fail_0:
-	DECREF(args);
-	goto Fail_2;
-Fail_1:
-	DECREF(result);
-Fail_2:
+Fail:
+	XDECREF(args);
+	XDECREF(result);
 	return NULL;
 }
 
@@ -1073,9 +1152,31 @@
 	return v;
 }
 
+static object *
+builtin_vars(self, v)
+	object *self;
+	object *v;
+{
+	object *d;
+	if (v == NULL) {
+		d = getlocals();
+		INCREF(d);
+	}
+	else {
+		d = getattr(v, "__dict__");
+		if (d == NULL) {
+			err_setstr(TypeError,
+			    "vars() argument must have __dict__ attribute");
+			return NULL;
+		}
+	}
+	return d;
+}
+
 static struct methodlist builtin_methods[] = {
 	{"abs",		builtin_abs},
 	{"apply",	builtin_apply},
+	{"callable",	builtin_callable},
 	{"chr",		builtin_chr},
 	{"cmp",		builtin_cmp},
 	{"coerce",	builtin_coerce},
@@ -1111,6 +1212,7 @@
 	{"setattr",	builtin_setattr},
 	{"str",		builtin_str},
 	{"type",	builtin_type},
+	{"vars",	builtin_vars},
 	{"xrange",	builtin_xrange},
 	{NULL,		NULL},
 };
@@ -1121,7 +1223,15 @@
 getbuiltin(name)
 	object *name;
 {
-	return dict2lookup(builtin_dict, name);
+	return mappinglookup(builtin_dict, name);
+}
+
+int
+setbuiltin(cname, value)
+	char *cname;
+	object *value;
+{
+	return dictinsert(builtin_dict, cname, value);
 }
 
 /* Predefined exceptions */
@@ -1291,8 +1401,8 @@
 
 	if (func == None) {
 		/* No character is ever false -- share input string */
-		INCREF(result);
-		return result;
+		INCREF(strobj);
+		return strobj;
 	}
 	if ((result = newsizedstringobject(NULL, len)) == NULL)
 		return NULL;