Added long() and support for longs in int() and float();
turned abs() and divmod() into generic versions;
added pow().
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 08f34bc..9768cd7 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -42,24 +42,12 @@
 	object *self;
 	object *v;
 {
-	/* XXX This should be a method in the as_number struct in the type */
-	if (v == NULL) {
-		/* */
+	number_methods *nm;
+	if (v == NULL || (nm = v->ob_type->tp_as_number) == NULL) {
+		err_setstr(TypeError, "abs() requires numeric argument");
+		return NULL;
 	}
-	else if (is_intobject(v)) {
-		long x = getintvalue(v);
-		if (x < 0)
-			x = -x;
-		return newintobject(x);
-	}
-	else if (is_floatobject(v)) {
-		double x = getfloatvalue(v);
-		if (x < 0)
-			x = -x;
-		return newfloatobject(x);
-	}
-	err_setstr(TypeError, "abs() argument must be float or int");
-	return NULL;
+	return (*nm->nb_absolute)(v);
 }
 
 static object *
@@ -112,47 +100,18 @@
 	object *self;
 	object *v;
 {
-	object *x, *y;
-	long xi, yi, xdivy, xmody;
+	object *x;
+	number_methods *nm;
 	if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
-		err_setstr(TypeError, "divmod() requires 2 int arguments");
+		err_setstr(TypeError, "divmod() requires 2 arguments");
 		return NULL;
 	}
 	x = gettupleitem(v, 0);
-	y = gettupleitem(v, 1);
-	if (!is_intobject(x) || !is_intobject(y)) {
-		err_setstr(TypeError, "divmod() requires 2 int arguments");
+	if ((nm = x->ob_type->tp_as_number) == NULL) {
+		err_setstr(TypeError, "divmod() requires numeric arguments");
 		return NULL;
 	}
-	xi = getintvalue(x);
-	yi = getintvalue(y);
-	if (yi == 0) {
-		err_setstr(TypeError, "divmod() division by zero");
-		return NULL;
-	}
-	if (yi < 0) {
-		xdivy = -xi / -yi;
-	}
-	else {
-		xdivy = xi / yi;
-	}
-	xmody = xi - xdivy*yi;
-	if (xmody < 0 && yi > 0 || xmody > 0 && yi < 0) {
-		xmody += yi;
-		xdivy -= 1;
-	}
-	v = newtupleobject(2);
-	x = newintobject(xdivy);
-	y = newintobject(xmody);
-	if (v == NULL || x == NULL || y == NULL ||
-		settupleitem(v, 0, x) != 0 ||
-		settupleitem(v, 1, y) != 0) {
-		XDECREF(v);
-		XDECREF(x);
-		XDECREF(y);
-		return NULL;
-	}
-	return v;
+	return (*nm->nb_divmod)(x, gettupleitem(v, 1));
 }
 
 static object *
@@ -207,15 +166,19 @@
 	if (v == NULL) {
 		/* */
 	}
-	else if (is_floatobject(v)) {
-		INCREF(v);
-		return v;
-	}
 	else if (is_intobject(v)) {
 		long x = getintvalue(v);
 		return newfloatobject((double)x);
 	}
-	err_setstr(TypeError, "float() argument must be float or int");
+	else if (is_longobject(v)) {
+		extern double dgetlongvalue();
+		return newfloatobject(dgetlongvalue(v));
+	}
+	else if (is_floatobject(v)) {
+		INCREF(v);
+		return v;
+	}
+	err_setstr(TypeError, "float() argument must be int, long or float");
 	return NULL;
 }
 
@@ -249,11 +212,18 @@
 		INCREF(v);
 		return v;
 	}
+	else if (is_longobject(v)) {
+		long x;
+		x = getlongvalue(v);
+		if (x == -1 && err_occurred())
+			return NULL;
+		return newintobject(x);
+	}
 	else if (is_floatobject(v)) {
 		double x = getfloatvalue(v);
 		return newintobject((long)x);
 	}
-	err_setstr(TypeError, "int() argument must be float or int");
+	err_setstr(TypeError, "int() argument must be int, long or float");
 	return NULL;
 }
 
@@ -283,6 +253,29 @@
 }
 
 static object *
+builtin_long(self, v)
+	object *self;
+	object *v;
+{
+	if (v == NULL) {
+		/* */
+	}
+	else if (is_intobject(v)) {
+		return newlongobject(getintvalue(v));
+	}
+	else if (is_longobject(v)) {
+		INCREF(v);
+		return v;
+	}
+	else if (is_floatobject(v)) {
+		double x = getfloatvalue(v);
+		return newlongobject((long)x);
+	}
+	err_setstr(TypeError, "long() argument must be int, long or float");
+	return NULL;
+}
+
+static object *
 min_max(v, sign)
 	object *v;
 	int sign;
@@ -367,6 +360,25 @@
 }
 
 static object *
+builtin_pow(self, v)
+	object *self;
+	object *v;
+{
+	object *x;
+	number_methods *nm;
+	if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+		err_setstr(TypeError, "pow() requires 2 arguments");
+		return NULL;
+	}
+	x = gettupleitem(v, 0);
+	if ((nm = x->ob_type->tp_as_number) == NULL) {
+		err_setstr(TypeError, "pow() requires numeric arguments");
+		return NULL;
+	}
+	return (*nm->nb_power)(x, gettupleitem(v, 1));
+}
+
+static object *
 builtin_range(self, v)
 	object *self;
 	object *v;
@@ -476,10 +488,12 @@
 	{"input", builtin_input},
 	{"int", builtin_int},
 	{"len", builtin_len},
+	{"long", builtin_long},
 	{"max", builtin_max},
 	{"min", builtin_min},
 	{"open", builtin_open}, /* XXX move to OS module */
 	{"ord", builtin_ord},
+	{"pow", builtin_pow},
 	{"range", builtin_range},
 	{"raw_input", builtin_raw_input},
 	{"reload", builtin_reload},