Quest for formatted code

There was a post already scheduled to go online during the weekend that describes the first tests done with the code: just to check if the code was complete, which libraries used, if compiled, etc, I did some quick and dirty changes to the code. The changes were not documented, and done one after the other with the goal to have the code compile and link. Documenting the steps I probably misplaced something, so I want to redo everything in order, with proper documentation.

In the meanwhile I also started to document the progres in this blog so I took a decision: start from a clean situation and document all the changes. And the first step is to reformat the source code with a common standard. Actually there is code I received, code decompiled and code I wrote (the latter 2 will be described in next posts)

As I wrote, I received a compressed archive, decompressed it and moved files in different directories and then all of them (and I mean ALL of them, including useless clipper .obj files) were added to a mercurial repository. I also the decompiled code and now it is time to cleaning up the code.

The tool of choice is hbformat, of course. I already know that committing the hbformatted code will create a monster diff but I think we, as programmers, should work with source code that is easy to work with, pleasant to read…

And my idea was that a quick hbformat *.prg would be the solution… I had to change my idea…

hbformat *.prg

The result was depressing… There are at least 3 problems with hbformat running on this code.

The first problem is that code uses short 4-chars or abbreviated commands: among them ENDC is used instead of ENDCASE (or END). ENDC is not recognized by hbformat. Changing it manually to ENDCASE works ok.

The second problem is that it doesn’t reformat the code (all lines start at column 0) until it finds one procedure or function statement. And almost none of my 200 files has a procedure or function statement as first line of code, using implicit declaration.

The third one is that hbformat uses stdio (OutStd()) for progress report and stderr (OutErr()) for errors and there isn’t the filename in the error message. Since you can’t redirect stdio and stderr to the same file, it means that you have a file with the progress log and one with just the error type and line number… useless.
So I went to hbformat source code and added code to print the filename when an error occours:

OutErr( cFilename + ": error", oRef:nErr, "on line", oRef:nLineErr, ":", oRef:cLineErr, hb_eol() )

Now I know where the errors are! Problem 3 solved.

Now there are 87 files to manually check for errors, one by one… I don’t trust global source and replace…

After checking about 10 files I noticed they all had the ENDC command that was misleading hbformat logic, so I had a look at hbformat source code formatter routines to try to add support for ENDC but I stopped after 20 minutes… better changing by hand…

So, revert to the original files and from the error log, with a bit of vim magic, create a batch file to load all 87 files and start to manually change the files. But this time I noticed that the programmer also used OTHERW in a case statement. A quick check and I confirmed that OTHER was not recognized and not properly indented by hbformat.

Ok, after 20 minutes all ENDC and OTHERW were converted to the longer forms.

Now let’s address problem 2: add a procedure/function line to each source file so that hbformat can indent the code. As usual I will do it manually, so that I can do a little check of each file. In the process I discovered several duplicated files, some tests, some empty, some really strange. There is need for a cleanup. It took almost an hour but now the code is ready to be formatted:

hbformat *.prg

Finally, no errors reported. But is it the code properly formatted? Unfortunately it isn’t.

In the middle of the code there are these lines

EXTE HELPER, CALCOL
SET KEY K_F1 TO HELPER
SET KEY K_ALT_F1 TO CALCOL

EXTE is the abbreviation of EXTERNAL, used to tell the linker to include that functions. I checked in Harbour and preprocessor correctly converts the SET KEY to code blocks so it isn’t needed. I can’t be sure for Clipper 87. Anyway, in hbformat code, when EXTE/EXTERNAL is found, the internal state machine is reset and following lines are at column 0, like if we were out of a procedure. This is another problem of hbformat since these commands can be anywhere in the code.

I moved the EXTE directives at the top of the 16 source files in which they were present. Then a new formatting round:

hbformat *.prg

I was expecting that hg stat reported just the 16 modified files. Instead it reported more, for this kind of changes:
diff01

I browsed 30 files and found no visible errors in the formatting so, finally, it’s time to commit. The diff is a mess as expected but in the future I may strip the previous commits and have this one as the first.

Just to have the source code in a form that is easy, or confortable to work with, took several hours and needed a change in a tool to know exactly where the errors were. More changes are needed since the tool was not able to cope with completely valid Clipper/Harbour code: that time-consuming manual job was needed.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>