Usecases of diff when porting code

Today's post may seem redundant for most of you because most programmers already know what is diff and how to use it.

Diff spots the differences or equivalences between the contents of files. The comparison between two text files is mostly a solved problem, although diff can be defined for graphics, trees, lists or bags.

You don't often need to implement diff since the existing text-diff is usually enough for many tasks, but it's good thing to know that diff isn't a very precisely defined problem or limited to text files.

You can use diff as help when you are porting code to run on a new API while wanting to retain the old API in place. Here's a summary of the workflow with diff:

If the differences are huge across APIs, this kind of workflow helps separating the concerns of getting the program to run and retaining the old API. The postponing of the later problem may help to think about the porting effort and lead to more effortless port, compared to attempting to immediately make it work on both APIs.

Stubbing the code

Stub is a placeholder for actual implementation. When porting it is usually a piece of code that fails when the program runs through that point.

#if defined(OLD_API)
    int result = old_api_action();
    api_specific_action(result);
#elif defined(NEW_API)
    assert(false); // TODO: Not implemented, but fails on runtime
#else
    #error Not implemented
#endif

In rare cases, when everything else you are aware about is using one way, and there's one stupid platform that is not behaving like the others. The following is acceptable:

#if defined(WIN32) // Fallen from the tree
    HANDLE fh;
    fh = CreateFile(thing, GENERIC_READ, 0, NULL, 0, FILE_ATTRIBUTE_NORMAL, NULL);
    if (fh == INVALID_HANDLE_VALUE) fail();
#else // The proper POSIX way everyone else is using
    int fd;
    fd = open(thing, O_RDONLY, 0);
    if (fd == -1) fail();
#endif

Here's yet another option you may want to consider:

#define Win32 1
#define Xcb   2

#if WINDOWING == Win32
    int result = win32_action();
    win32_specific_action(result);
#elif WINDOWING == Xcb
    assert(false); // TODO: Not implemented, but fails on runtime
#else
    #error Not implemented (WINDOWING)
#endif

Then you may use -DWINDOWING=Win32 to select it.

C compiler warns about redefined macros these days, so the both things above are fine ways to do it.

If the case is trivial then by all means implement it straight away. But keep in mind that any failure is always better than corruption.

When the above stubs are not sufficient for porting, you have the diff-method to help with the complex cases.

Good manners of porting code

Note how the stubs I provided always have an #else case that leads to #error. This is intentional. Silent failures are worst: do not create them with intent.

Diff in editors

Some editors provide views for comparing between the files. For example, in Vim you have the command :diffsplit. Here's an example of the command in the action for today's blog post. The file to compare is the older revision of the text:

diffsplit in action

Finally

Experimentation with your workflow should be quite safe thing to do. The methods that are inefficient are quickly discarded if they do not result in results.

Diff is a time-proven, good tool in the programmer's toolchain.

Similar posts