et cetera - Petewg/harbour-core GitHub Wiki

🔙 Home


Extended Literals

  • Escaped Strings
    Harbour supports extended strings with C-like escaped values as e"..."

    example:
    ? e"Hello World\x21\n\Harbour extended string\x2e\nLorem ipsum\x2e\x2e\x2e"
    prints (3 lines):
    Hello World!
    Harbour extended string.
    Lorem ipsum...

    They works in compiler and macrocompiler.

  • Literal DATE and TIMESTAMP values

    1. DATE constant in the form d"YYYY-MM-DD"

      dDate := d"2017-02-20"

      Also the "/" or "." delimeters can be used instead of "-".

    2. DATE constant in the form 0dYYYYMMDD

      dDate := 0d20170220
    3. TIMESTAMP constant in the form t"YYYY-MM-DD HH:MM:SS.fff"
      The exact accepted timestamp pattern is:
      YYYY-MM-DD [H[H][:M[M][:S[S][.f[f[f]]]]]] [PM|AM]
      where an empty space is used to separate date and time, as well as the pm|am suffix.

      tValue := t"2009-03-21 5:31:45.437 PM"
    4. TIMESTAMP constant in the form t"YYYY-MM-DDTHH:MM:SS.fff"
      The exact accepted timestamp pattern is:
      YYYY-MM-DDT[H[H][:M[M][:S[S][.f[f[f]]]]]] [PM|AM]
      where the uppercase T is used as separator of date and time parts (XML compliant timestamp format).

      tValue := t"2009-03-21T17:31:45.437"

    Characters that can be used as date delimiters are: "-", "/", "."
    Characters that can be used as time delimiters are: ":" for H(ours), M(inutes), S(econds) and "." for f(ractions) (i.e. milliseconds).
    If PM or AM suffix is used then HH is in range < 1 : 12 > otherwise is in range < 0 : 23 >

⬆️ Back to Top


Predefined Macros

Harbour automatically defines some macros, recognized by preprocessor (they're kind of inbuild #defines), which, if present in source-code, are evaluated (during preprocessing) and be substituted by specific internal information about code being processed, e.g. filename and line, the compilation date/time, as well as, harbour version, environment platform, architecture, endianness and such. These inbuild #defines can be referenced inside user code using their literal identifiers; some of the most common of them are:

__FILE__ and __LINE__
They are substituted by the full pathname (__FILE__ ) and by the line number ( __LINE__) of the source file being compiled, where the identifier(s) are encountered.
f.e.: ? __FILE__ , __LINE__ --> C:\dev\myapp\main.prg 32
(can be particularly useful f.e. in debugging) (see also: ProcName() & ProcLine() functions)

__DATE__ , __TIME__ and __TIMESTAMP__
the build date and time, that is, the date/time/timestamp when the particular .prg file (into which the __DATE__ , __TIME__ or __TIMESTAMP__ literals are encountered), was compiled, in the form: YYYYMMDD , HH:MM:SS and YYYY-MM-DD HH:MM:SS.fff respectively.

example:
? __DATE__ , __TIME__   // --> 20160824 12:27:30
? __TIMESTAMP__   // --> t"2016-08-24 12:27:31.716"

(the above constants, might potentially be useful in application versioning etc.).

__HARBOUR__
the decimal representation of the hexadecimal harbour version used to compile the source. (Three bytes: Major + Minor + Release). For example:

? __HARBOUR__ --> 197120

for harbour 3.2 it will return 197120 which in Hexadecimal notation is 0x030200,
"deciphered" as: MajorVersion =03 MinorVersion =02 Release =00
whereas for harbour 3.4 (Viktor's fork) it will be: 197632 or 0x030400 in Hexadecimal.
(see also hb_Version() & Version() functions)
(also, take a look there)

⬆️ Back to Top


Embedding C-code into .prg file

As suggested by Przemek in this post, it is strongly recommended to not mix PRG and C code into same .prg source file. C-code must be put in separate .c files which then are being compiled/linked by build-toolchain, as needed.\

Anyway, there are two methods of inserting C code in PRG files though not officially supported.

  • Method 1.
    C-code must be encapsulated between a #pragma begindump ... #pragma enddump pair of directives.
    Functions declaration and naming must realized with macro HB_FUNC( <FUNCNAME> ) (important: all letters capitalized!).
 #pragma begindump

 #include(s) (header files) ...
  static vars, etc ...

/* C code here for _MYEXEC( cSql )  */
HB_FUNC( _MYEXEC )
{
   const char * cmd = hb_parc( 1 );

   #ifdef _WRITESQL_
      prsql(cmd);
   #endif

   ResetMysqlError( &MyConnection );
   mysql_query( &MyConnection, cmd );
   if( verify( &MyConnection ) )
   {
      sprintf( errors, "Error executing : User %s executed : %s",
               getenv( "USER" ), cmd );
      prerror( errors );
   }
   else
      hb_retni( mysql_affected_rows( &MyConnection ) );

   /* frees the memory asociated with result */
   mysql_free_result( MyRecordSet );
   MyRecordSet = NULL;
}
#pragma enddump
  • Method 2.
    Here, C-code can be written directly into (and mixed with) Harbour '.prg' code!
    using the macro: HB_INLINE( [<params,...>] ) { C code like above }
    LOCAL nVal
    nVal := HB_INLINE( 1, 5 ) { hb_retni( hb_parni( 1 ) <<
                                          hb_parni( 2 ) ); }
    ? nVal 

Worth to note here, that Harbour has a similar to Clipper public C API which helps porting C-code quite fast.

  • Any passed parameters are accessed/evaluated by API according to their ordinal number of appearance (starting from 1), using hb_par*() functions,
  • values can be assigned to parameters passed by reference using hb_stor*() functions
  • while values can be returned using hb_ret*() functions.
    (for more, see hbapi.h as well as any hbapi*.h into harbour\include\ folder.)

⬆️ Back to Top


Harbour compiler options (switches)

Notes:

  1. All harbour compiler switches are prefixed by a minus - sign.
    2) Any trailing minus - or plus + sign (where available) means disable or enable respectively.
Syntax:  harbour <file[s][.prg]|@file> [options]

Options:  
   -a               automatic memvar declaration
   
   -b               debug info
   
   -build           display detailed version info
   
   -credits         display credits
   
   -d<id>[=<val>]   #define <id>
   
   -es[<level>]     set exit severity
   
   -fn[:[l|u]|-]    set filename casing (l=lower u=upper)
   
   -fd[:[l|u]|-]    set directory casing (l=lower u=upper)
   
   -fp[:<char>]     set path separator
   
   -fs[-]           turn filename space trimming on or off (default)
   
   -g<type>         output type generated is <type> (see below)
   
      -gc[<type>]       output type: C source (.c) (default)
                        <type>: 0=compact (default) 1=normal 2=verbose
                            3=generate real C code
      -gh               output type: Harbour Portable Object (.hrb)
      -gd[.<destext>]   generate dependencies list into (.d) file
      -ge[<mode>]       error output <mode>: 0=Clipper (default)
                                             1=IDE friendly
                                       
   -i<path>         #include file search path
   
   -i[-|+]          disable/enable support for INCLUDE envvar
   
   -j[<file>]       generate i18n gettext file (.pot)
   
   -k<mode>         compilation mode (see below)
      -kc               clear all flags (strict Clipper mode)
      -kh[-]            Harbour mode (default)
      -ko[-]            allow operator optimizations
      -ki[-]            enable support for HB_INLINE (default)
      -kr[-]            runtime settings enabled
      -ks[-]            allow indexed assignment on all types
      -kx[-]            extended Xbase++ mode (default)
      -ku[-]            strings in user encoding
      -kd[-]            accept macros with declared symbols
      -km[+]            turn off macrotext substitution
      -kj[+]            turn off jump optimization in pcode
      
   -l               suppress line number information
   
   -m               compile module only
   
   -n[<type>]       no implicit starting procedure
                    <type>: 0=no implicit starting procedure
                            1=no starting procedure at all
                            2=add starting procedure if necessary
                            
   -o<path>         object file drive and/or path
   
   -p[<path>]       generate pre-processed output (.ppo) file
   
   -p+              generate pre-processor trace (.ppt) file
   
   -q               quiet
   
   -q0              quiet and don't display program header
   
   -q2              disable all output messages
   
   -ql              hide line counter gauge
   
   -r:<max>         set maximum number of preprocessor iterations
   
   -s[m]            syntax check only [minimal for dependencies list]
   
   -u[<file>]       use command def set in <file> (or none)
   
   -u+<file>        add command def set from <file>
   
   -undef:<id>      #undef <id>
   
   -v               variables are assumed M->
   
   -w[<level>]      set warning level number (0..3, default 1)
   
   -z               suppress shortcutting (.and. & .or.)
   
   @<file>          compile list of modules in <file>

⬆️ Back to Top


About -gc3 harbour compiler switch

Harbour can generate machine code instead of PCODE with -gc3 switch.
It's ~10%-20% faster but only if no other slow functions are executed. Just pure PRG code only. The size of final binaries are about 4-5 times bigger.
BTW PCODE is not interpreted. PCODE is evaluated and the difference is fundamental for the speed. Unlike many people think and said on public forums Clipper and Harbour are compilers. Even hbrun executing PRG code is compiler. Interpreter is completely different animal. Early versions of Ron's xBase Script were interpreters. Current ones are mix of compiler and interpreter.

(above comment by Przemek in this post)

Also, below is an excerpt from this relevant post. (it's a bit long message, scroll down to last paragraph).

BTW Harbour compiler internally generates from .prg code .c files.
In -gc[0-2] modes (-gc[0-3] is Harbour compiler switch) it generates PCODE for whole functions encapsulated in very small C preamble and postamble.
In -gc3 mode it generates real C code which calls HVM functions directly. The last version is a little bit faster (~10 to ~25 %) but needs much more memory for code. In practice only the code generated for -gc3 can be optimized by C compiler and linker with LT-IPO. For -gc[0-2] there is no place for some advances optimizations (for -gc0, -gc1 and -gc2 exactly the same code is generated and the difference is only in human readability but not for C compilers). If you are interesting in details and you want to see with your own eyes C code generated by Harbour compiler then you can use -hbraw option with hbmk2.

best regards, Przemek

ps. In tests/speedtst.prg you will find simply speed test code which you can use to compare speed differences in cases (also with other xbase compatible compilers).
For Harbour if you want to reach optimal results use:
hbmk2 -w -kmo -l -gc2 -static -st speedtst

⬆️ Back to Top


Parameters and Arguments, a terminology clarification

  • A parameter of a function or procedure is a variable specified in function definition, acting as place-holder waiting to receive a value being sent (passed) by the caller. Worth to note that such a parameter variable is declared as LOCAL in the function, (unless it's being created inside the body of function using the PARAMETERS statement, in which case it is declared as PRIVATE --and for this reason, using PARAMETERS statement isn't a good practice).
  • An argument is the actual value that is passed to above parameter, when the function is called.
PROCEDURE Main()
   LOCAL nSum
   nSum := Add( 1, 7 ) // we're calling the function Add() with the arguments: 1, 7

// function definition
FUNCTION Add( nNum1, nNum2 ) // our function defines two parameters: nNum1, nNum2
   RETURN ( nNum1 + nNum2 )

Pass-by-value vs Pas-by-reference

What's the difference between passing by reference vs. passing by value?

Understanding arrays

Why do we use arrays instead of other data structures?

⬆️ Back to Top


System Error Codes (win)

(for a complete list see here)

Code Description Code Description
01 Function number invalid 02 File not found
03 Path not found 04 Too many open files
05 Access denied 06 Handle invalid
07 Memory control blocks destroyed 08 Insufficient memory
09 Memory block address invalid 10 Environment invalid
11 Format invalid 12 Access code invalid
13 Data invalid 14 Unknown unit
15 Disk drive invalid 16 Attempted to remove current directory
17 Not same device 18 No more files
19 Write-protected disk 20 Unknown unit
21 Drive not ready 22 Unknown command
23 Data error (CRC) 24 Bad request-structure length
25 Seek error 26 Unknown media type
27 Sector not found 28 Printer out of paper
29 Write fault 30 Read fault
31 General failure 32 Sharing violation
33 File-lock violation 34 Disk change invalid
35 FCB unavailable 36 Sharing buffer exceeded
37-49 Reserved 50 Unsupported network request
51 Remote machine not listening 52 Duplicate name on network
53 Network name not found 54 Network busy
55 Device no longer exists on network 56 NetBIOS command limit exceeded
57 Error in network adapter hardware 58 Incorrect response from network
59 Unexpected network error 60 Remote adapter incompatible
61 Printer queue full 62 Not enough room for print file
63 Print file was deleted 64 Network name deleted
65 Network access denied 66 Incorrect network device type
67 Network name not found 68 Network name limit exceeded
69 NetBIOS session limit exceeded 70 Temporary pause
71 Network request not accepted 72 Print or disk redirection paused
73-79 Reserved 80 File already exists
81 Reserved 82 Cannot make directory
83 Fail on Int 24H (critical error handler) 84 Too many redirections
85 Duplicate redirection 86 Invalid password
87 Invalid parameter 88 Net write fault

⬆️ Back to Top
🔙 Home

⚠️ **GitHub.com Fallback** ⚠️