Project hosted by
xHarbour Features

xHarbour Language Extensions

xHarbour is a fork from Harbour created December 2001. It aims to follow a more aggressive development path, and be more responsive to market trends, and users input.

As it stands at this point, xHarbour offers many Syntax extensions over Harbour and the Clipper language in general, including:

Associative Arrays:

Associative Arrays are like LITE Objects. Properties may be added on the fly without any declaration, much like new PRIVATE or PUBLIC can be created by simply assigning a value.
Associative Arrays, may use Objects Syntax (':' operator) or Array Index Syntax ('[]' operator) with the Property Name as the INDEX.
New Property will automatically be created upon first assignment.

<lValue> := TAssociativeArray()
<AA>[ "<NewProperty>" ] := <xValue>
<AA>:<NewProperty> := <xValue>
<AA>[ "<Property>" ]

Associative Arrays have LITERAL support like this:
SYNTAX: { <Property> => <Value> [, <PropertyN> => <ValueN> ] }


In the past, clipper (and then xharbour) users felt the need to have what is called "hash" or "associative array" and that is nowadays provided at language level by all the most modern languages: Perl, PHP, Python, Ruby, name it. An associative array is an array that bounds a value (that can be of any variable type allowed by the language) to a key (that may be of any "orderable" or "distinguishable" variable) in a 1:1 relationship.
An extension has been recently added to add the HASH type as one of the basic xHarbour type. In other words, hashes are now a rightful type of xHarbour. They are individuated by the "H" variable type.

Hashes, like arrays, can be managed with both a specific API and by language constructs.

SWITCH syntax:

   SWITCH <Exp>
     CASE <Constant>
     [More Cases ...]

NOTE: This syntax is modeled after the C 'switch' flow control. It offers great speed benefit [30-300%] over DO CASE flow control, but is restricted to comparing only constants. Constants maybe: Integers, Longs, or Single Character Strings [much like in C]

WARNING: Those NOT familiar with the C switch flow control, should understand that unlike DO CASE, you MUST explicitly use the EXIT statement or else logic will FALL THROUGH to the NEXT CASE, until stopped at a BREAK, or END statements.
At first this might seem VERY ODD, but it provides great flexibility exactly like the C model.
See tests/switch.prg to for a sample and to learn how the FALL-THROUGH logic works.

Multi Threading (MT) Support:

xHarbour supports MT applications. There is still some more work to be done, but you can already take advantage of this very powerful feature.
Basic sample can be found at tests/mttest.prg

StartThread( @MyThreadFunc() [, xParam1 [,xParamN ] ] )

NOTE: MT Application must link against the MT versions of the Libraries, i.e. vmmt.lib, rtlmt.lib, ppmt.lib, rddmt.lib, dbfntxmt.lib and dbfcdxmt.lib. The full description of MT is beyond the scope of this document.

Portable Sockets Support

The full description is beyond the scope of this document - please refer to samples/sitesvr/sitesvr.prg for a Web Server example.

Perl-5 compatible RegEx

xHarbour includes PCRE which is a full feature, Perl 5 compatible, Regular
Expression engine. Full feature Search & Replace classes are currently under
construction, but you may already use the full power of RegEx searches,
new operators, HAS and LIKE.

   cExp HAS cPatern|CompiledRegEx => bFound
The HAS operator scans cExp for a any match of the supplied cRegEx or CompiledRegEx, and returns .T. if found, .F. otherwise.

   cExp LIKE cPatern|CompiledRegEx => bLike
The LIKE operator returns .T. if the *complete* cExp is a match, to the supplied cRegEx or CompiledRegEx, .F. otherwise.

As well as full featured Functions:

   HB_Atx( <cRegEx>, <cTargetString> [, lCaseSensitive [, [@]nStart ]
           [, [@]nLen ] ] ] ) => cFoundText

   RegexComp( cPattern, [bCaseSens [, bNewLine]] ) --> REGEX

   HB_Regex( cPattern, cString, [bCaseSens, [, bNewLine]] ) --> aMatches

TRY syntax

[THROW( <Exp> )]

The above is very similar to Clipper BEGIN SEQ, BREAK(), RECOVER USING, END, but is more inline with more "modern" languages, and dismisses the need to worry about Error codeblock.

IN operator

<Exp> IN <Array_or_StringExp> => .T./.F.

The IN operator is very similar to the $ operator, but is valid on *both* Strings and Arrays. IN is much faster than the equivalent:
aScan( <Array>, <Exp> ) > 0

Variable Parameters syntax

Function <cFuncName>( ... )

The above definition allows this Function to receive up-to 254 parameters. You may retrieve an ARRAY with all the parameters using:

The above is appropriate for such functions that may receive any number of generic parameters, which normally will then be processed in a loop, or with hard coded IF statements based on PCount(). Instead the above is much easier to code, requires less memory, and is faster than declaring the parameters.

GLOBAL variables:

GLOBAL <Id1> [,<Id2> [,<IdN>]]

GLOBAL Variables are a new kind of a declared variables. they have PUBLIC like visibility, but are faster than even STATICs. GLOBALS can be referenced from other modules using the syntax:
GLOBAL EXTERNAL <Id1> [,<Id2> [,<IdN>]]

GLOBAL Variables have the added benefit of being *directly* accessible from C code too.

Sample code:
GLOBAL g_MyObject
#include ""
   g_MyObject := MyClass()

   METHOD MyMethod INLINE Alert( "MyMethod" )

   hb_objSendMsg( &G_MYOBJECT, "MyMethod", 0 );
   // Note must be ALL-CAPS!
#pragma ENDDUMP


True C Type Structures

C STRUCTURE <strucName> [Align <align>]
[ MEMBER <memberName> IS <CTYPEDEF> ]
[ MEMBER <memberName[<arrayLength>]> IS <CTYPEDEF> ]
[ MEMBER <memberName> IS <CTYPEDEF>(<arrayLength>) ]
[ MEMBER <memberName> IS|INPLACE <strucName> ]
[ MEMBER <memberName> AS <strucName> ]
[ ... ]

C Structure can be passed *directly* TO and FROM C code. The full Description is beyond the scope of this document - please refer to cstruct.txt in doc folder.



HB_QWith() can also be used to retrieve the current WITH OBJECT within a   WITH OBJECT block.
The above syntax not only saves typing, but is also MUCH faster than equivalent conventional coding.

FOR EACH Syntax:

FOR EACH <Element> IN <Array> // <Element> must be a declared variable.
<Element> // Enumerate value of each respective element in the <exp>.
HB_EnumIndex() returns

is not only more elegant than:

FOR Counter := 1 TO Len(Array)
Element := Array[Counter]

but is also MUCH faster - and it also supports enumerating all properties in an object.

Full access to OLE Servers

CreateObject( "ServerName" ) => oOleObject
Create new instance of an Ole Server.
GetActiveObject( "ServerName" ) => oOleObject
Get existing instance of an Ole Server.

All documented methods and properties of such Server should be directly accessible.

Strings may be indexed like arrays:


String as Array Index can also accepts a numeric as an assigned value:
<StringExp>[<IndexExp>] := 65 // Same as := 'A'

String Index and all String of 1 character length, automatically carry a secondary CHAR type, which means they are also compatible with numeric operations.

cVar := "hello"; cVar[1] -= 32 // -> "Hello"

Negative Array Index:

Both Arrays and Strings may be indexed with negative numbers (Reversed), where -1 indexes the LAST Element (or NIL if the Array is empty):
cVar[-1] // => "o"

assuming cVar is the value "Hello" as per above.

Extended macro support:

will compile correctly even if cMacro is a declared var.

WinPorts extended printers support

xHarbour has the ability to print direct to the Windows pserver. Printing to USB printers is as simple as
Set(24,"WIN:" + printername)

The function GetPrinters() returns a list of all available printers.

#[x]uncommand and #[x]untranslate directives

#uncommand and untranslate directives allow the removal of a given rule from the active rules used by the Pre-Processor. It is very much like the #undefine directive.


© 2024 All rights reserved.
Contact us | Terms of Use Agreement
xHarbour.ORG is maintained by Enrico Maria Giordano
Internet services kindly provided by