As described in the previous posts, a big number of duplicated functions had me change my mind on how to complete the porting. I’m now back to the original software setup: a batch file that calls several different executables depending on errorlevel values.
I reverted the changes done, starting from removing the source files from exe01.hbp and uncomment the initializazion function calls I disabled previously: the program compiled as described in the previous post (but I still have to solve that RETURN in the SEQUENCE)
Just to streamline the various .hbp files I’m going to create, I decided to have a global hbc files that lists all the use libraries. I could have used a hbmk.hbm file but I prefer to have everything listed.
I created libs.hbc file listing all the libs:
libpaths=. libs=applib libs=funcky libs=mylib
In this way all the libraries don’t need to be listed in each .hbp but I just need to add a reference to libs.hbc. It is not only one line vs 4 in each hbp but something more strategic: in this way it is possible to add other libraries in a centralized place. For example, I’m thinking about the need to add some functions for converting the reports printed on file to PDF, and I may decide to use a library I already have: instead of updating all the .hbp files, I may just add the new one here. I also noticed that the error handlers I saw in the code are not called so I will probably need to add my error handler functions too.
I then created the file all.hbp with all the .hbp included but commented, except the one I already created.
-hbcontainer applib.hbp mylib.hbp funcky.hbp exe01.hbp # exe02 is the Utility Menu, included in exe01 exe03.hbp # exe04.hbp ... # exe13.hbp
Now with a single command I can compile everything in a standard, repeatable, way, all of them in one go, with the command:
hbmk2 -rebuildall all.hbp
Notice that the build will stop at the first error and you don’t have to check for errors like in a batch based solution. I think that all projects should have a all.hbp equivalent, a way to build the full project with one command, that can be used in an automatic building system.
I had the first 2 executables compiling, linking and running. The second has been patched but the patch not committed in the repository. I decided that before looking at that code (with the RETURN 300 lines after the BEGIN SEQUENCE and 600 before the END SEQUENCE) I’d better check if there are some other show-stopping problems. So I commented the exe03.hbp line in all.hbp and converted all .lnk files to .hbp, so that all executables are built except for the one I already know has a problem to solve.
Let’s list all the errors I found and how I solved them.
Error 1: RETURN inside BEGIN SEQUENCE/END. Harbour and Clipper 5.x syntax is probably different from Clipper 87: in the past it was possible to have a RETURN inside the sequence. This is probably the easier case as there isn’t a RECOVER and the return is only used at the start, if the files can’t be opened:
// original code BEGIN SEQUENCE IF my_usedbf( .... ) RETURN ENDIF ...
I changed to:
// changed code IF my_usedbf( .... ) RETURN ENDIF BEGIN SEQUENCE ...
Error 2: duplicated function names. This is a function clearly called by error handler. There are some of them in a file, but I never found the place where they are setup. I will check later. In this case I added a prefix.
Third program linked.
Error 3: missing function mkdir(). This function is used, in this program, to create a new workarea, and since a workarea is a subdirectory, it clearly needs to create the directory. It is also used elsewhere but before spending time developing and validating the function (with all that error handling the program uses) I’d like to complete the main port. So I created a stub mkdir() that outputs a trace and then exits the program.
Error 4: unexplicate error message by the linker: undefined reference to `HB_FUN(int0_t) static’.
Przemek explained why it happens and how can be solved. In this case the code uses a function named _size(). This function has a dbf file as parameter and it should return the file size. Since it is used together with mkdir() I created a similar stub file.
Fourth program compiled.
Error 5: undefined function, used by licensing code. In this program the licensing code is still active and this is strange: this makes me wonder if this executable is still used… I adapted the code as per other sources where licensing code is disabled.
Fifth and sixth programs compiled.
Error 5 again: another source code with licensing code active.
Several programs compiled.
Error 6: In a executable there are two missing functions reported by the linker. These functions have names that are already used in other parts of the code, in other executables. I checked if I correctly converted the .lnk to .hbp and I did. So, do I miss these functions? Are they duplicated but not present in the code I have? Should they be in the application library? or… or…
Both functions are used in a SET KEY statement and one has a source file with the same name, and the other is included in that file. I don’t have Clipper 87 installed but I feel there is something interesting possibly going on here. I’m going to ask in the newsgroup. In the meantime I’m commenting out the building of this executable.
Error 7: one comma not necessary in a list of variables
PRIV var1, var2, var3, // <- note the ending comma!
Error 8: 2 RETURNs in BEGIN SEQUENCE. In this case we have a 150 lines function that extracts data from several DBFs and depending on several conditions that show up during data processing, it RETURNs without completing, or BREAKs to skip some calculations but do something with the data found. It’s like having a 10 step process and after each step you may cancel (RETURN) or skip all the following steps (BREAK) and complete the job anyway. BREAK is used as an unconditional jump, without parameters, since it is used only to skip to the end of the sequence block.
My solution is the following: all original BREAKs, the ones that want the program flow to continue are tranformed to BREAK 1, while all RETURNs are transformed to BREAK 2 and finally a RECOVER block is added to properly handle the situation:
BEGIN SEQUENCE ... IF condition() // BREAK BREAK 1 ENDIF ... IF condition() // RETURN BREAK 2 ENDIF ... RECOVER USING nValue IF nValue == 2 RETURN ENDIF END SEQUENCE
And now also this last executable compiled.
Errors 1,2,5,7 and 8 were solved. Errors 3 and 4 are just stubs functions like the others working on directories. For error 6 I need infos from someone with a working Clipper 87. Of course there is still the RETURN in that big function to fully analyze, with nested SEQUENCE blocks, that probably will be solved as per error 8. Unfortunately, this block is in the most important executable, the one used to load the data inside the program… I will do in the next post.
I need to show the accountant lady that the program can be converted and the first round is complete: it works somehow, for sure it needs testing, but I think that there will not be too many problems in the future.