An Example of Code Cloning
Before we go further, we should probably explore the problem space a little. To that end, let’s consider the following two functions that are taken from version 1.6.3 of the Gnumeric source code base:
// Both functions are from the file py-gnumeric.c, version 1.6.3
static PyObject *
py_new_Range_object (GnmRange const *range) {
py_Range_object *self;
self = PyObject_NEW (py_Range_object, &py_Range_object_type);
if (self == NULL) {
return NULL;
}
self->range = *range;
return (PyObject *) self;
}
static PyObject *
py_new_RangeRef_object (const GnmRangeRef *range_ref){
py_RangeRef_object *self;
self = PyObject_NEW py_RangeRef_object, &py_RangeRef_object_type);
if (self == NULL) {
return NULL;
}
self->range_ref = *range_ref;
return (PyObject *) self;
}At first glance, it seems pretty obvious that one of these functions has been cloned
from the other (or that both have been cloned from a third source), as they are almost
token-for-token identical. Indeed, a little investigation reveals that these are
boilerplate designs for dealing with the instantiation of Python objects from within the
main C codebase. The functions differ in two ways, one obvious and one more subtle. The
obvious difference is that some of the identifiers are slight variations on each other:
each identifier that has the suffix Range in the first
function has the suffix RangeRef in the second. The more subtle difference concerns the parameters: in the first function, the parameter is a constant ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access