Issue #1717, stage 2: remove uses of tp_compare in Modules and most
Objects.
diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c
index 6778fb4..32de6bc 100644
--- a/Modules/parsermodule.c
+++ b/Modules/parsermodule.c
@@ -169,7 +169,7 @@
 
 
 static void parser_free(PyST_Object *st);
-static int parser_compare(PyST_Object *left, PyST_Object *right);
+static PyObject* parser_richcompare(PyObject *left, PyObject *right, int op);
 static PyObject* parser_compilest(PyST_Object *, PyObject *, PyObject *);
 static PyObject* parser_isexpr(PyST_Object *, PyObject *, PyObject *);
 static PyObject* parser_issuite(PyST_Object *, PyObject *, PyObject *);
@@ -203,7 +203,7 @@
     0,                                  /* tp_print             */
     0,                                  /* tp_getattr           */
     0,                                  /* tp_setattr           */
-    (cmpfunc)parser_compare,            /* tp_compare           */
+    0,                                  /* tp_compare          */
     0,                                  /* tp_repr              */
     0,                                  /* tp_as_number         */
     0,                                  /* tp_as_sequence       */
@@ -223,7 +223,7 @@
     "Intermediate representation of a Python parse tree.",
     0,                                  /* tp_traverse */
     0,                                  /* tp_clear */
-    0,                                  /* tp_richcompare */
+    parser_richcompare,                 /* tp_richcompare */
     0,                                  /* tp_weaklistoffset */
     0,                                  /* tp_iter */
     0,                                  /* tp_iternext */
@@ -231,6 +231,9 @@
 };  /* PyST_Type */
 
 
+/* PyST_Type isn't subclassable, so just check ob_type */
+#define PyST_Object_Check(v) ((v)->ob_type == &PyST_Type)
+
 static int
 parser_compare_nodes(node *left, node *right)
 {
@@ -260,27 +263,70 @@
     return (0);
 }
 
-
-/*  int parser_compare(PyST_Object* left, PyST_Object* right)
+/*  parser_richcompare(PyObject* left, PyObject* right, int op)
  *
  *  Comparison function used by the Python operators ==, !=, <, >, <=, >=
  *  This really just wraps a call to parser_compare_nodes() with some easy
  *  checks and protection code.
  *
  */
-static int
-parser_compare(PyST_Object *left, PyST_Object *right)
+
+#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
+
+static PyObject *
+parser_richcompare(PyObject *left, PyObject *right, int op)
 {
+    int result;
+    PyObject *v;
+
+    /* neither argument should be NULL, unless something's gone wrong */
+    if (left == NULL || right == NULL) {
+        PyErr_BadInternalCall();
+        return NULL;
+    }
+
+    /* both arguments should be instances of PyST_Object */
+    if (!PyST_Object_Check(left) || !PyST_Object_Check(right)) {
+        v = Py_NotImplemented;
+        goto finished;
+    }
+
     if (left == right)
-        return (0);
+        /* if arguments are identical, they're equal */
+        result = 0;
+    else
+        result = parser_compare_nodes(((PyST_Object *)left)->st_node,
+                                      ((PyST_Object *)right)->st_node);
 
-    if ((left == 0) || (right == 0))
-        return (-1);
-
-    return (parser_compare_nodes(left->st_node, right->st_node));
+    /* Convert return value to a Boolean */
+    switch (op) {
+    case Py_EQ:
+        v = TEST_COND(result == 0);
+        break;
+    case Py_NE:
+        v = TEST_COND(result != 0);
+        break;
+    case Py_LE:
+        v = TEST_COND(result <= 0);
+        break;
+    case Py_GE:
+        v = TEST_COND(result >= 0);
+        break;
+    case Py_LT:
+        v = TEST_COND(result < 0);
+        break;
+    case Py_GT:
+        v = TEST_COND(result > 0);
+        break;
+    default:
+        PyErr_BadArgument();
+        return NULL;
+    }
+  finished:
+    Py_INCREF(v);
+    return v;
 }
 
-
 /*  parser_newstobject(node* st)
  *
  *  Allocates a new Python object representing an ST.  This is simply the