et cetera - Petewg/harbour-core GitHub Wiki
🔙 Home
- Extended Literals
- Predefined Macros
- Embed C-code into .prg file
- About -gc3 harbour compiler switch
- Harbour compiler options (switches)
- System Error Codes (win)
- Harbour build settings (envars)
- Parameters and Arguments, a terminology clarification
- Pass-by-value vs Pass-by-reference
- Understanding arrays
- xhb-diff.txt ("Must read" #1)
- The #pragma directive
-
How to build and use pCode DLL with hbmk2 (an interesting thread in old
harbour-devel
mailing list)
-
Escaped Strings
Harbour supports extended strings with C-like escaped values ase"..."
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
-
DATE constant in the form d"YYYY-MM-DD"
dDate := d"2017-02-20"
Also the
"/"
or"."
delimeters can be used instead of"-"
. -
DATE constant in the form 0dYYYYMMDD
dDate := 0d20170220
-
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"
-
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 uppercaseT
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).
IfPM
orAM
suffix is used thenHH
is in range< 1 : 12 >
otherwise is in range< 0 : 23 >
-
⬆️ Back to Top
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
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 macroHB_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 anyhbapi*.h
intoharbour\include\
folder.)
⬆️ Back to Top
Notes:
- All harbour compiler switches are prefixed by a minus
-
sign.
2) Any trailing minus-
or plus+
sign (where available) meansdisable
orenable
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
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
- 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 thePARAMETERS
statement, in which case it is declared asPRIVATE
--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 )
What's the difference between passing by reference vs. passing by value?
Why do we use arrays instead of other data structures?
⬆️ Back to Top
(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