Bill S wrote in to share some code from an ancient billing system still in use to this very day...

My first assignment was to make the billing system’s code Y2K compliant. Fortunately, management had given us ample time to prepare: two full months.

The good news was that there weren’t a whole lot of things that needed to be done. So little, in fact, that I decided to try to fix an error that would randomly occur in the system. It read “There is an error with the tax rate. Program Aborting.”

The billing system was originally ported from COBOL to C and can only be compiled in Borland 4.5. That is just one of its many features. The other major one is that, because of the COBOL port, most variables were global and all files, memory, and so on are initialized at the start of the program and closed at the end.

I found that the tax rate is read in from a configuration file and used only in a single part of the application. Here’s the snip from the beginning of the program:

vtaxrate = valf(buf); vtaxrate /= 100.00000;

And in the main program processing loop (which for some strange reason is an infinite for loop):

for (;;) { ... if (vtaxrate != 0.06) { cputs(" There is an error with the tax rate. Program aborting."); exit(0); } taxtot = (invtot + reimbtot) * vtaxrate; ... }

At first, I thought it was odd to test a variable that was read from configuration and never should change. All of the other “configurable” rates were tested just in this manner. Obviously, they were changing somehow.

A further investigation revealed that by allocating everything at the beginning, almost 50K of heap was being used right from the start. Borland 4.5 (for the medium model) uses 64K of shared heap and stack space. The stack starts at the top and goes down, while the heap starts at the bottom. Eventually that stack overwrites some of the heap memory, and the original programmers discovered the tax rates were changing. Thus the test.

When I asked what I should do about this, management just commented that “it’s been working for 10 years, and should be left alone.” So I fixed the Y2K errors, recompiled the program, and redeployed.

To this day, if we get a “tax error,” we simply cross our fingers and rerun. Interestingly enough, the error typically does not re-occur. Of course, who knows what other heap values are changing … but at least there’s no abort with a “Tax Error.”