A Harbour Project How-To
A gentle introduction to an open-source implementation of the Clipper language

David Mertz, Ph.D.
President, Gnosis Software, Inc.
April 2000

This article sketches some brief details of the internal workings of Harbour, but focuses on the ordinary details of getting Harbour set up; and on recompiling existing Clipper programs (possibly to new platforms). A particular emphasis is given to the setup on Linux, but notes are also made on its other ported platforms. Some general observations are made on current limitations of Harbour relative to other Clipper implementations on which a developer might have an existing codebase.

Harbour is a collaborative project that began in 1999. The goal of the Harbour Project is to create a cross-platform and open-source compiler for the xbase superset language known as Clipper. Clipper was implemented first, and as Harbour's reference implementation, in CA-Clipper 5.2 (and largely in earlier versions of CA-Clipper); but supersets of Clipper have also been implemented commercially in at least Alaska Software's xBase++, Multisoft's Flagship and Computer Associates' Visual Objects. In less than a year, Harbour has moved from preliminary discussions to a 95% functional implementation. And unlike each of the other Clipper implementations, the source code is available under a modified GPL, and ports have been made to Linux, DOS, Win32, OS/2 and MacOS. One interesting feature, technically, of Harbour is its output: rather than output platform-specific object code, Harbour's compiler outputs source code in C, Java (incomplete), Pascal (planned), Windows Resource (planned) or a 'Harbour Runtime Binary' (hrb). From there, your existing compiler/linker takes over to produce a native executable by linking to the runtime libraries and Harbour virtual machine (VM). Alternately, a compiled native runtime interpreter can process an .hrb file.

Despite the progress made to date, at the time of this article Harbour is still in alpha versions. It is probably not yet a very good idea to consider Harbour for production environments; but the progress made makes it look like it will be ready soon (contributors to the project are always welcomed, of course). In particular, the documentation is still in a pretty rough state, and what there is--while generally well-written--is aimed primarily at the Harbour developers themselves. A Clipper programmer who is not necessarily also a C programmer or a compiler designer will probably still encounter a few bumps along the way. Hopefully, after this author works through a few of these little bumps himself, this article will ease the path to working with Harbour.

Getting Harbour installed
Being at an alpha version, the degree of compatibility and functionality differs somewhat between ported platforms; and the installation on all platforms is still a manual process. Unfortunately, this turns out to mean (at least as of this writting) that the Linux version lags behind the Win32, DOS and OS/2 versions in some important ways. The main problem right now is that the console I/O under Linux is basically broken. While the plan by the developers is to provide both curses and slang library compatibility, the latter will not compile at all yet, and the former is only partially functional. The bottom line is that Harbour on Linux is only currently robust for batch oriented processes and command-line driven utilities (see the sidebar on "CGI and HarbourScript", however).

Linux installation. Installing on Linux is similar to most Linux installations, although there is a little bit more to it than the simplest make/make install setup. The first thing to do for any version you wish to install is to visit the download section of the Harbour web site. For Linux, download the source code, which should be in a tarball with a name similar to harbour-0.33.src.tar.gz. On my own system, I decided to work only at a user level (it is, after all, alpha software; and besides, many users will not have root access). I put the tarball in a ~/Harbour/ directory, and ran the below commands:

Shell commands to setup Harbour
1  $ gunzip -c harbour-0.33.src.tar.gz | tar -x
2  $ cd harbour-0.33
3  $ export HB_GT_LIB=gtcrs
5  $ chmod u+x make_gnu.sh
6  $ ./make_gnu.sh > make_gnu.log
7  $ ln -f source/compiler/linux/gcc/harbour ~/bin
8  $ ln -f utils/hbrun/linux/gcc/hbrun ~/bin
9  $ ln -f source/pp/stdalone/linux/gcc/hbpp ~/bin
10 $ ln -f utils/hbdoc/linux/gcc/hbdoc ~/bin      

A few comments are warranted on what I do above. The make_gnu.sh script, run in (6), is a wrapper for GNU make that sets a few environment variables first. Two variables that are not set by default, but need to be for any console support other than tty-style are C_USR and HB_GT_LIB. Eventually, these will also support values for the slang libraries (and maybe others like XTM or KDE) but currently only ncurses can compile. As a minor matter, the provided make_gnu.sh does not have execute permissions when unpacked, so you'll either want to change its permission or pass it to a shell explicitly, as in (5). I found it helpful to redirect the make results to a file in (5) so that they could be examined later, and also so that the STDERR messages will stand out more evidently. I received a non-fatal warning in alpha 0.32, which was corrected in 0.33; you might still get one or two such warnings while Harbour is in other alphas. In (7)-(10) I found it convenient to create links in a standard location for the harbour executables that should be created.

Installation on other Operating Systems. Under Win32, DOS and OS/2, prebuilt Harbour binaries are available, which really saves a lot of work for a novice trying to get a feel for Harbour. Zip files are available for a variety of compiler/OS combinations. If you intend to compile your own executables, you will need to download a version compatible with the C compiler you intend to use. Fortunately, a variety of free and non-free C compilers are supported. Once you get the right zip file, just unpack it where you want Harbour to live (if you use pkunzip, be sure to use the -d option to maintain subdirectory structure).

The current binary distributions also include the hbrun.exe utility which will run an .hrb file for you without the need for linking an executable (hbrun.exe uses some assembly that cannot yet be built with every compiler/OS combination, but every OS has some version of hbrun.exe available). As a quick way to get started, this is very easy (the sample directory and source file below come from the Harbour source distribution):

Compiling and running a Harbour Runtime Binary
 J:\Harbour\tests>..\bin\harbour tstcolor.prg /n /i..\include /gh
 Harbour Compiler, Build 32 (2000.03.07)
 Copyright 1999-2000, http://www.harbour-project.org
 Lines 53, Functions/Procedures 1

 Generating Harbour Portable Object output to 'tstcolor.hrb'... Done.

 J:\Harbour\tests>..\bin\hbrun tstcolor.hrb

Assuming you do have a C compiler setup on your system, creating an executable is most easily accomplished by using the provided build script, e.g.:

Compiling a Harbour executable
 J:\Harbour\tests>..\bin\bld_vc.bat tstcolor /n /i..\include

Porting considerations
Probably the main issue in porting a legacy Clipper project to Harbour will be the portability of the libraries used in the original project. To a large extent, calls to third-party libraries will have to be rewritten, either in the Harbour language (which includes some enhancements to the traditional DOS/CA-Clipper capabilities), or in C as upgraded capabilities for the Harbour system itself.

However, the Harbour developers have made some efforts in the direction of supporting common CA-Clipper libraries, as well as with improving compatibility with Alaska's XBase++. A few third party tools have even started to provide Harbour ports. Of course, many popular CA-Clipper libraries--such as SuperLib and Grumpfish--are already written primarily in Clipper, and come with source code to allow end-user modification. In the case of such libraries, porting to Harbour is likely to be fairly straightforward, even if not necessarily completely effortless. I sketch below some of the library issues already addressed by the Harbour developers, or by third-parties.

A sample project
As a test of porting to Harbour, I decided to use a smallish (in the neighborhood of 1000 lines), but real-life project. Y2KComp is a utility I created in late 1998 as a consultant at a large company performing Y2K code remediation. I had since released the code to the public domain; so feel free to download it from the link in the "Resources" section if you wish. It is probably of little continuing use now that we have passed through the Y2K new-year, but it does have the virtue of using much of the most common functionality of Clipper. In a nutshell, Y2KComp reads in a few values, then performs a "aged-date consistency" comparison on two files. That is, we do not want to determine just if two files are identical, but rather if all the date difference between the two files are consistent. Add a 'mutatis mutandis' clause to the notion of sameness. These files may be DBFs, free-form reports, comma delimited files, or fixed-length flat-files. A moderate degree of machine intelligence goes into determining what sort of differences are to be expected, and what sort indicates a problem. At the end of the comparison, a textual report is produced summarizing the comparison results. In other words, we get some DBF acess, some file I/O, some date functions, some numeric functions, some string functions, and the GET system. Furthermore, I had created both a DOS and a Fivewin version of the same program (sharing most of the code in common), so potentially this could be a test of Fivewin for Harbour (but not in this article).

Compiling under Win32. Building the program under WinNT 4.0 was pretty uneventful. There were just a few quick workarounds and shortcuts I took that are worth noting. The original utility was built from 4 .prg source files. It had been built using a PVCS make file, so the old environment was a bit different from the current one. As a shortcut in this small project, I just added a few #include "filename.prg" statements at the end of the main source file. This saved the work of creating a new makefile using GNU make, or my C compiler's facilities.

A bit more significant was the fact I had also used a call to SWPRUNCMD() in the original program, which is a function in the Blinker library (to run a child process in a more DOS-memory-friendly way than CA-Clipper's RUN). The issue behind this is a bit antiquated, but other legacy code might use this or other Blinker functions. This particular call was to run an external program presumed to be called 'EDIT' on the report file that is created by running the utility. I tried two things here: (1) Just remove the call altogether (and look at the report using whatever viewer I wish); (2) Substitute a call to the RUN command. The first worked fine, of course. The second produced a slightly odd effect. The console did not clear its previous screen, but the cursor highlight moved within the screen, as if EDIT.COM was launched. Upon forcing a close of the window, I saw a brief flash of what was apparently the EDIT.COM screen. It appears that the child process is having its console output blocked in some manner; I did not, however, experiment to determine if this effect was specific to particular child applications.

Compiling under Linux. Building the Y2KComp project under Linux had a number of additional issues beyond those for Win32. I used the same #include shortcut as under Win32; and I also had the same issue with Blinker library functions. More significantly were a mix of issues that one will always expect under Linux with ones that reflect the unfinished version of Harbour I was working with. The main problem is the incomplete console I/O handling. DBF support and file I/O is in pretty good shape even in the alpha 0.32, and the functions are almost all implemented.

Here are some issues to expect under Linux, even with later versions of Harbour: (1) Linux uses a case-sensitive filesystem, while DOS, OS/2 and Windows do not. This will not be news to developers, but a few steps are likely to be required. Specifically, I found that I had used a variety of #include's in the project (including those I added for the Win32 version above) where the case of the filename used did not match that in the actual filesystem. Since Clipper was never case-sensitive in its keywords (unlike a lot of languages), a Clipper programmer had some flexibility in when to use caps that was stylistic rather than functional; but some of that is restricted under Linux. (2) curses/slang support will only work under a Linux console, not under a KDE Konsole or an xterm window. There may eventually be support for all the styles of Linux terminal windows, but most likely the Linux console will be supported first.

I also encountered some difficulties with compiling/linking the default Harbour output of intermediate C files. There were not included in the release I worked with any shell scripts analogous to the bld_vc.bat files for Windows. Although the bld_tpl.cmd contained some lines for using gcc under OS/2 that seemed similar to what was needed, an initial effort to adapt it to a shell script still produced some linking errors. Overall, I found it most direct simply to use the .hrb output format, and the hbrun utility to get up-and-running with sample programs, e.g.:

Compiling and running the project under Linux
 $ cd ~/Harbour/y2kcomp/
 $ ~/bin/harbour y2kcomp.prg -n -gh -i../harbour.0.32/include
 Harbour Compiler, Build 32 (2000.03.07)
 Copyright 1999-2000, http://www.harbour-project.org
 Lines 231, Functions/Procedures 37

 Generating Harbour Portable Object output to 'y2kcomp.hrb'... Done.
 $ ~/bin/hbrun y2kcomp

The console I/O problems I encounted in alpha 0.32 are discussed below. Some are fairly serious, and unfortunately, a quick examination of alpha 0.33--released at press times--shows that it does not yet address these issues, for the most part. (1) curses support is still monochrome. This suffices for the basic GET/SAY of the sample program, but anything with a complicated screen design is likely to rely on color elements (some color appears in 0.33, but so do some other screen artifacts). (2) INKEY() codes are not trapped correctly. Specifically, arrow keys are treated as an ESC and/or abnormally terminate an application. This limitation makes it impossible to use ACHOICE() or MENU TO for item selection. This again makes complex user interaction difficult. (3) Possibly related to the INKEY() codes, READ doesn't behave as expected. An ENTER will not terminate a read, CTRL-W is required. This also changes the interaction a user expects. Each of the above issues greatly limit the possibilities for user interaction in an application. I expect, they will all be improved in later releases (largely by 0.34 according to a developer working on this aspect).

Despite those difficulties I encountered using Harbour in its current versions, I believe that Harbour is "the future of xbase" (a slogan of the developers). While it will be a while before Harbour is faster, has smaller executables, is more stable, or has any such positive attribute over commercial Clipper implementations, it is the very fact the Harbour is open source that makes it so exciting. Commercial vendors may drop their compiler products any day they wish; and even as long as they support them it will be on the platform, price-basis, and license terms that the vendor wishes. With Harbour, you have all the source to the compiler and the right to enhance it, improve it, or re-platform it however you want (as well as an intelligent and committed developers community behind it). And even today, Harbour has better cross-platform support than any other Clipper implementation. A modified GPL assures that Harbour will remain free forever (but the modification grants you the right to distribute applications compiled with Harbour on whatever terms you want).


About the author
David Mertz leads at least a dual life. When not developing software or writing about it, he also writes articles in obscure areas of academic political philosophy. Nowadays, his main focus in software development, is in web-applications, particularly with high-level scripting languages. He may be reached at mertz@gnosis.cx.