Harbor - the new face of xBase family

    For reference: xBase is a family of programming systems, DBMS, originating from dBase (1980). They are united by a common programming language (of course, with variations inherent in a particular implementation) and the means of access to relational databases of the DBF format built into this language. In fact, dBase began as a DBMS with a language designed to serve databases. This is a procedural programming language, it belongs to the group of interpreted languages ​​and has many, if not all, their generic features, such as, for example, dynamic typing.

    Clipper, the immediate predecessor of Harbor, was created in 1985 with the goal of increasing dBase III performance. To do this, the source code of the program was converted at the compilation stage into bytecode, which was embedded in the executable file along with a virtual machine designed to execute this bytecode. Thus, Clipper gave the output a standalone exe file that does not require an external interpreter to run and run, as in the case of dBase or FoxBase (another popular xBase product).

    In the late 80s and early 90s, Clipper was very popular, it was one of the main programming tools for database-related applications, primarily accounting, management, banking. The language was upgraded from version to version, new subsystems were added. Among the latter, the Extend System and RDD are especially noteworthy. Extend System (extension system) is designed to communicate with modules written in C - calling functions, passing parameters, receiving return values. RDD - Replaceable Database Drivers - a technology that allowed, linking a standard, special library to work with a different type of database without changing a single line of code. This is how Clipper applications worked, for example, with Novell's Btrieve (if anyone remembers,

    XBase systems have always been perceived as intended, primarily, for working with databases and, perhaps, therefore, with the growth of popularity of SQL, they began to go out of trend. And if everything was more or less successful with Fox, the Microsoft that bought it made on its basis the popular Visual Foxpro product, which a few years ago (in 2006, according to Wikipedia), was on the honorable 12th place in the TIOBE list, then Clipper was much worse. Computer Associates, which had owned it since the early 90s, has relied on other products. Clipper, on the other hand, remained aloof from the main route, the pressing problems were not solved, and in 1997 Computer Associates announced the closure of its further development, leaving programmers writing on it alone with a 16-bit programming system designed for use in the MS-DOS environment.

    Many of those who thought about their future migrated to other platforms, but there were also those who believed that the advantages of Clipper, being implemented in a modern programming environment, would be in demand further. Several such implementations were created (xBase ++, Clip, Harbor), one of which, the most successful for this day, I’ll talk about - please forgive me for such a long, but, in my opinion, necessary introduction.

    So, Harbor. The project was launched in 1999, the official website is www.harbour-project.org . The current version is 3.0 (stable), 3.2 (development).

    As Clipper, Harbour translates the source program into byte code, but, unlike his predecessor, Harbour compiler generates no object, and withfiles that you then need to “feed” With the compiler. For example, here is a simple function that displays a greeting to the console:

    Function Hello
       ? "Hello"
       Return Nil
    


    it translates to (comments are mine):

    // HB_FUNC определено как:
    // #define HB_FUNC( funcname )        HB_EXTERN_C_ HB_EXPORT HARBOUR HB_FUN_##funcname ( void )
    HB_FUNC( HELLO )
    {
       // байт-код
       static const HB_BYTE pcode[] =
       {
          36,2,0,176,2,0,106,6,72,101,108,108,111,0,
          20,1,36,3,0,100,110,7
       };
       // Вызов виртуальной машины (далее - ВМ) для выполнения байт-кода
       hb_vmExecute( pcode, symbols );
    }
    


    Consider the bytecode in more detail:

       static const HB_BYTE pcode[] =
       {
          36,2,0,                          // 36 - код, за которым следует номер строки 
                                           // исходного текста, в данном случае - 2
          176,2,0,                         // 176 - помещает символ на стек ВМ, имеется 
                                           // ввиду символ, представляющий функцию вывода
          106,6,'H','e','l','l','o','\0',  // 106 - помещает строку на стек ВМ
          20,1,                            // 20 - ВМ должна выполнить функцию и отбросить 
                                           // ее результат, 1 - количество параметров
          36,3,0,                          // 36 - код, за которым следует номер строки 
                                           // исходного текста, в данном случае - 3
          100,                             // 100 - помещает Nil на стек ВМ
          110,                             // 110 - ВМ должна вернуть значение с вершины стека
          7                                // 7 - ВМ должна завершить работу
       };
    


    Your project may include sources in Harbor ( * .prg ), in C, special object files and libraries. C code can also be embedded in a prg file, it must be enclosed in #pragma BEGINDUMP ... #pragma ENDDUMP and, of course, it must comply with the EXTEND SYSTEM conventions (I mentioned it when I spoke about Clipper). Below is an example of such a symbiosis:

    Function Main
       ? Sinus( 30 ), Sinus( 60 )
       ?
       Return Nil
    #pragma BEGINDUMP
    #include 
    #include "hbapi.h"
    #include "hbapiitm.h"
    #define PI 3.14159265
    // Вычисляем синус угла, заданного в градусах
    HB_FUNC( SINUS )
    {
       // hb_parnd( n ) - функция EXTEND SYSTEM, принимает n-й переданный параметр
       //    как double из Harbour функции
       // hb_retnd( d ) - функция EXTEND SYSTEM, возвращает double значение d
       //    обратно в Harbour функцию
       hb_retnd( sin( hb_parnd( 1 ) * PI / 180 ) );
    }
    #pragma ENDDUMP
    


    It was not by chance that I paid so much attention to C at Harbor. Extended (sorry for the involuntary tautology), compared with the Clipper, Extend System and Item API, which provides access from C code to Harbor internal structures, its variables, arrays, objects allow us to talk about the symbiosis of two languages, I consider this one of the most important features of Harbor . Thanks to this, Harbor has already "grown" with a large number of modules - shells for various products that have a C API and the list of such modules, both open source and commercial, is constantly growing (currently I'm thinking about OpenCV). Of course, C is used in Harbor not only to create shells for finished products, but also for independent development - new RDD, GUI libraries, etc. Sometimes,

    Built-in access to the database, this generic feature of xBase, is another topic that I would like to pay special attention to. It’s really very convenient to be able to, without using external DBMSs, use only the built-in language tools to perform all the necessary database manipulations — creating, modifying, updating, editing, and searching. In the case when the amount of information stored in the database is relatively small, using an external DBMS seems completely redundant, for such applications MySQL also looks like a monster (and some even put MS SQL) - the xBase approach here seems to be the most appropriate solution. However, for large databases, Harbor can be used (and is applied) quite successfully.

    I’ll give you a small code snippet demonstrating typical data access constructs - for those who have not encountered xBase languages ​​before. Of course, the arsenal of tools for working with the database in Harbor is much richer than that used in these few lines.

    Function Test
       Local aStru := { {"FAMILY","C",16,0}, {"IMYA","C",16,0}, {"OTCHES","C",16,0}, ;
          {"TELEFON","C",10,0} }
       // Создаем таблицу БД mytable с ФИО и номерами телефона
       dbCreate( "mytable", aStru )
       // Открываем mytable
       USE mytable
       // Создаем индексы по фамилии и по телефону
       INDEX ON FAMILY TAG FAMILY
       INDEX ON TELEFON TAG TELEFON
       // Добавляем записи
       APPEND BLANK
       REPLACE FAMILY WITH "Иванов", IMYA WITH "Игорь", OTCHES WITH "Константинович", ;
          TELEFON WITH "9101682020"
       ...
       // Ищем запись по номеру телефона, используя индекс
       ordSetFocus( "TELEFON" )
       IF dbSeek( "9101682020" )
          // Если запись найдена, изменяем номер
          REPLACE TELEFON WITH "9102875555"
       ENDIF
       ...
       Return Nil
    


    Means of access to the database are not limited to standard ones. There are RDDs written for client-server DBMSs, both based on DBF (commercial Advantage Database Server from Sybase and open source LetoDb), that and SQL. There are modules that provide access through ODBC and ADO, there are modules for MySQL, PostgreSQL, SQLite, using the C API of these DBMSs.

    In Harbor, all the features of Clipper were further developed, making it a high-level language that is convenient to program in - automatic memory allocation and deallocation, garbage collector, the so-called raw arrays, the ability to compile and execute code fragments in run-time, in dynamics. Added a full implementation of OOP. The preprocessor, retaining all the power of Clipper, has been expanded due to some designs taken from C. However, I will not list all the innovations here, but simply refer to the section of my Harbor site for beginners .

    Yes, I seem to have forgotten to say that Harbor is an open source cross-platform system. It exists on 32-bit and 64-bit platforms, on Windows, Linux, Unix, Mac OS X, QNX, OS / 2, it seems to be on Android, and something else that I have not seen.

    I would be glad if this article arouses interest. In this case, it will be possible to consider some aspects in more detail.

    Also popular now: