Made builtins int(), long(), float(), oct() and hex() more generic.
diff --git a/Include/object.h b/Include/object.h
index 081bb86..f644be3 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -146,6 +146,11 @@
 	object *(*nb_xor) FPROTO((object *, object *));
 	object *(*nb_or) FPROTO((object *, object *));
 	int (*nb_coerce) FPROTO((object **, object **));
+	object *(*nb_int) FPROTO((object *));
+	object *(*nb_long) FPROTO((object *));
+	object *(*nb_float) FPROTO((object *));
+	object *(*nb_oct) FPROTO((object *));
+	object *(*nb_hex) FPROTO((object *));
 } number_methods;
 
 typedef struct {
diff --git a/Objects/classobject.c b/Objects/classobject.c
index 514869c..9026968 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -714,6 +714,12 @@
 	return 0;
 }
 
+UNARY(instance_int, "__int__")
+UNARY(instance_long, "__long__")
+UNARY(instance_float, "__float__")
+UNARY(instance_oct, "__oct__")
+UNARY(instance_hex, "__hex__")
+
 static number_methods instance_as_number = {
 	instance_add,		/*nb_add*/
 	instance_sub,		/*nb_subtract*/
@@ -733,6 +739,11 @@
 	instance_xor,		/*nb_xor*/
 	instance_or,		/*nb_or*/
 	instance_coerce,	/*nb_coerce*/
+	instance_int,		/*nb_int*/
+	instance_long,		/*nb_long*/
+	instance_float,		/*nb_float*/
+	instance_oct,		/*nb_oct*/
+	instance_hex,		/*nb_hex*/
 };
 
 typeobject Instancetype = {
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index 5ce6202..1a1598c 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -318,6 +318,33 @@
 	return 1; /* Can't do it */
 }
 
+static object *
+float_int(v)
+	object *v;
+{
+	double x = getfloatvalue(v);
+	/* XXX should check for overflow */
+	/* XXX should define how we round */
+	return newintobject((long)x);
+}
+
+static object *
+float_long(v)
+	object *v;
+{
+	double x = getfloatvalue(v);
+	return dnewlongobject(x);
+}
+
+static object *
+float_float(v)
+	object *v;
+{
+	INCREF(v);
+	return v;
+}
+
+
 static number_methods float_as_number = {
 	float_add,	/*nb_add*/
 	float_sub,	/*nb_subtract*/
@@ -337,6 +364,11 @@
 	0,		/*nb_xor*/
 	0,		/*nb_or*/
 	float_coerce,	/*nb_coerce*/
+	float_int,	/*nb_int*/
+	float_long,	/*nb_long*/
+	float_float,	/*nb_float*/
+	0,		/*nb_oct*/
+	0,		/*nb_hex*/
 };
 
 typeobject Floattype = {
diff --git a/Objects/intobject.c b/Objects/intobject.c
index 8ecffc2..e10dab2 100644
--- a/Objects/intobject.c
+++ b/Objects/intobject.c
@@ -421,6 +421,59 @@
 	return newintobject(a | b);
 }
 
+static object *
+int_int(v)
+	object *v;
+{
+	INCREF(v);
+	return v;
+}
+
+static object *
+int_long(v)
+	object *v;
+{
+	long x = getintvalue(v);
+	return newlongobject(x);
+}
+
+static object *
+int_float(v)
+	object *v;
+{
+	long x = getintvalue(v);
+	return newfloatobject((double)x);
+}
+
+static object *
+int_oct(v)
+	object *v;
+{
+	char buf[20];
+	long x = getintvalue(v);
+	if (x == 0)
+		strcpy(buf, "0");
+	else if (x > 0)
+		sprintf(buf, "0%lo", x);
+	else
+		sprintf(buf, "-0%lo", -x);
+	return newstringobject(buf);
+}
+
+static object *
+int_hex(v)
+	object *v;
+{
+	char buf[20];
+	long x = getintvalue(v);
+	if (x >= 0)
+		sprintf(buf, "0x%lx", x);
+	else
+		sprintf(buf, "-0x%lx", -x);
+	return newstringobject(buf);
+}
+
+
 static number_methods int_as_number = {
 	int_add,	/*nb_add*/
 	int_sub,	/*nb_subtract*/
@@ -439,6 +492,12 @@
 	int_and,	/*nb_and*/
 	int_xor,	/*nb_xor*/
 	int_or,		/*nb_or*/
+	0,		/*nb_coerce*/
+	int_int,	/*nb_int*/
+	int_long,	/*nb_long*/
+	int_float,	/*nb_float*/
+	int_oct,	/*nb_oct*/
+	int_hex,	/*nb_hex*/
 };
 
 typeobject Inttype = {
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 7ede30c..25b4c64 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -1268,6 +1268,47 @@
 	return 1; /* Can't do it */
 }
 
+static object *
+long_int(v)
+	object *v;
+{
+	long x;
+	x = getlongvalue(v);
+	if (err_occurred())
+		return NULL;
+	return newintobject(x);
+}
+
+static object *
+long_long(v)
+	object *v;
+{
+	INCREF(v);
+	return v;
+}
+
+static object *
+long_float(v)
+	object *v;
+{
+	return newfloatobject(dgetlongvalue(v));
+}
+
+static object *
+long_oct(v)
+	object *v;
+{
+	return long_format(v, 8);
+}
+
+static object *
+long_hex(v)
+	object *v;
+{
+	return long_format(v, 16);
+}
+
+
 #define UF (object* (*) FPROTO((object *))) /* Unary function */
 #define BF (object* (*) FPROTO((object *, object *))) /* Binary function */
 #define IF (int (*) FPROTO((object *))) /* Int function */
@@ -1292,6 +1333,11 @@
 	BF long_or,	/*nb_or*/
 	(int (*) FPROTO((object **, object **)))
 	long_coerce,	/*nb_coerce*/
+	UF long_int,	/*nb_int*/
+	UF long_long,	/*nb_long*/
+	UF long_float,	/*nb_float*/
+	UF long_oct,	/*nb_oct*/
+	UF long_hex,	/*nb_hex*/
 };
 
 typeobject Longtype = {
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index b74cdf1..2f46931 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -253,25 +253,15 @@
 	object *self;
 	object *v;
 {
-	if (v == NULL) {
-		/* */
+	number_methods *nb;
+	
+	if (v == NULL || (nb = v->ob_type->tp_as_number) == NULL ||
+	    nb->nb_float == NULL) {
+		err_setstr(TypeError,
+			   "float() argument can't be converted to float");
+		return NULL;
 	}
-	else if (is_intobject(v)) {
-		long x = getintvalue(v);
-		return newfloatobject((double)x);
-	}
-	else if (is_longobject(v)) {
-		return newfloatobject(dgetlongvalue(v));
-	}
-	else if (is_floatobject(v)) {
-		INCREF(v);
-		return v;
-	}
-	else if (is_instanceobject(v)) {
-		return instance_convert(v, "__float__");
-	}
-	err_setstr(TypeError, "float() argument must be int, long or float");
-	return NULL;
+	return (*nb->nb_float)(v);
 }
 
 static object *
@@ -307,22 +297,15 @@
 	object *self;
 	object *v;
 {
-	if (v != NULL) {
-		if (is_intobject(v)) {
-			char buf[20];
-			long x = getintvalue(v);
-			if (x >= 0)
-				sprintf(buf, "0x%lx", x);
-			else
-				sprintf(buf, "-0x%lx", -x);
-			return newstringobject(buf);
-		}
-		if (is_longobject(v)) {
-			return long_format(v, 16);
-		}
+	number_methods *nb;
+	
+	if (v == NULL || (nb = v->ob_type->tp_as_number) == NULL ||
+	    nb->nb_hex == NULL) {
+		err_setstr(TypeError,
+			   "hex() argument can't be converted to hex");
+		return NULL;
 	}
-	err_setstr(TypeError, "hex() requires int/long argument");
-	return NULL;
+	return (*nb->nb_hex)(v);
 }
 
 static object *
@@ -354,30 +337,15 @@
 	object *self;
 	object *v;
 {
-	if (v == NULL) {
-		/* */
+	number_methods *nb;
+	
+	if (v == NULL || (nb = v->ob_type->tp_as_number) == NULL ||
+	    nb->nb_int == NULL) {
+		err_setstr(TypeError,
+			   "int() argument can't be converted to int");
+		return NULL;
 	}
-	else if (is_intobject(v)) {
-		INCREF(v);
-		return v;
-	}
-	else if (is_longobject(v)) {
-		long x;
-		x = getlongvalue(v);
-		if (err_occurred())
-			return NULL;
-		return newintobject(x);
-	}
-	else if (is_floatobject(v)) {
-		double x = getfloatvalue(v);
-		/* XXX should check for overflow */
-		return newintobject((long)x);
-	}
-	else if (is_instanceobject(v)) {
-		return instance_convert(v, "__int__");
-	}
-	err_setstr(TypeError, "int() argument must be int, long or float");
-	return NULL;
+	return (*nb->nb_int)(v);
 }
 
 static object *
@@ -413,25 +381,15 @@
 	object *self;
 	object *v;
 {
-	if (v == NULL) {
-		/* */
+	number_methods *nb;
+	
+	if (v == NULL || (nb = v->ob_type->tp_as_number) == NULL ||
+	    nb->nb_long == NULL) {
+		err_setstr(TypeError,
+			   "long() argument can't be converted to long");
+		return 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 dnewlongobject(x);
-	}
-	else if (is_instanceobject(v)) {
-		return instance_convert(v, "__long__");
-	}
-	err_setstr(TypeError, "long() argument must be int, long or float");
-	return NULL;
+	return (*nb->nb_long)(v);
 }
 
 static object *
@@ -491,24 +449,15 @@
 	object *self;
 	object *v;
 {
-	if (v != NULL) {
-		if (is_intobject(v)) {
-			char buf[20];
-			long x = getintvalue(v);
-			if (x == 0)
-				strcpy(buf, "0");
-			else if (x > 0)
-				sprintf(buf, "0%lo", x);
-			else
-				sprintf(buf, "-0%lo", -x);
-			return newstringobject(buf);
-		}
-		if (is_longobject(v)) {
-			return long_format(v, 8);
-		}
+	number_methods *nb;
+	
+	if (v == NULL || (nb = v->ob_type->tp_as_number) == NULL ||
+	    nb->nb_oct == NULL) {
+		err_setstr(TypeError,
+			   "oct() argument can't be converted to oct");
+		return NULL;
 	}
-	err_setstr(TypeError, "oct() requires int/long argument");
-	return NULL;
+	return (*nb->nb_oct)(v);
 }
 
 static object *