* include/hbextern.ch
* src/rtl/Makefile
+ src/rtl/hbdoc.prg
+ Added __HBDOC_LOADDIR() internal RTL function to read
NFDOC formatted documentation source directories into
memory. The result will be a list of hashes which contain
the raw content of doc files. The function does format
validation (but not content) and add all agreed-on metadata
to the hashes.
It's a start and I hope others can join to create new
layers of function for below functionality:
- doc content validation
- pre-formatting
- output generators
The goal is to avoid local solutions and standardize
the format.
+ tests/hbdoctst.prg
+ Added small test app which will find and parse all
documentation inside the Harbour source tree and
save them in .hbd (serialized doc hash) format.
Such .hdb files can be generated by the build process
in the future, so tools like HBIDE can use the content
to display intellisense or built-in help.
; TODO: HBQT doc/html should be removed as it's
hbdoc tools' job to convert HBDOC source
format to html or whatever else format needed.
* harbour.spec
* debian/rules
- doc/man
+ src/pp/hbpp.1
+ src/main/harbour.1
+ utils/hbmk2/hbmk2.1
+ utils/hbtest/hbtest.1
+ utils/hbrun/hbrun.1
* Moved man doc files to their own component dirs.
* doc/Makefile
* doc/en/Makefile
+ doc/clipper.txt
- doc/en/clipper.txt
* Moved non-NFDOC formatted doc file to doc dir.
* doc/en/Makefile
! Fixed missing 1stread.txt
* doc/en/hb_apigt.txt
* doc/en/hbinet.txt
* doc/en/tbrowse.txt
* doc/en/hb_apifs.txt
! Fixed NFDOC non-standard entries.
* bin/hbxpatch.hbs
! Fixed detecting dirs. (could cause errors only in rare cases)
* contrib/hbdoc2/tmplates.prg
* Formatting.
167 lines
4.7 KiB
Plaintext
167 lines
4.7 KiB
Plaintext
/*
|
|
* $Id$
|
|
*/
|
|
|
|
This document attempts to describe the features separating Harbour from
|
|
CA-Cl*pper.
|
|
|
|
/* TODO: @FunPointer(), and all other Harbour extensions. */
|
|
|
|
Harbour Macro Compiler
|
|
----------------------
|
|
The Harbour Macro Compiler offers 2 additional layers of functionality
|
|
controlled by means of HB_SETMACRO()* function, not available in CA-Cl*pper.
|
|
|
|
HB_SETMACRO( HB_SM_HARBOUR, TRUE ) will enable macro compilation and
|
|
evaluation of complex expressions not supported by CA-Cl*pper like:
|
|
|
|
- exp++, exp--, var += exp, (exp), etc..
|
|
- Nested codeblocks.
|
|
- Expressions longer then 254 characters.
|
|
|
|
HB_SETMACRO( HB_SM_XBASE, TRUE ) will enable macro compilation and
|
|
evaluation of comma separated lists in all contexts where lists are
|
|
acceptable by CA-Cl*pper*, including:
|
|
|
|
- { &cMacro } // Literal array elements list.
|
|
- SomeArray[ &cMacro ] // Array index list.
|
|
- SomeFun( &cMacro ) // Arguments list.
|
|
- ( &cMacro ) // parenthesized list expression.
|
|
|
|
*CA-Cl*pper only supports list macros within codeblocks context.
|
|
|
|
Both these extra layers are activated by default.
|
|
|
|
* See also -k Compiler switch.
|
|
|
|
LIST Command
|
|
------------
|
|
|
|
LIST &cMacro
|
|
|
|
LIST in CA-Cl*pper [superficially] supports macros of lists expressions.
|
|
No error will be produced, and all expressions in the list will be
|
|
evaluated, but *only* the *last* expression will be displayed. This is
|
|
not documented in either the LIST Command or the Macro Operator
|
|
descriptions, but is the de-facto behavior in all CA-Cl*pper 5.x versions.
|
|
|
|
Harbour instead will not only evaluate all of the expressions in
|
|
such list macro, but will also display all such values. This default
|
|
behavior may be disabled with HB_SETMACRO( HB_SM_XBASE, .F. )*
|
|
|
|
* See also -k Compiler switch.
|
|
|
|
INIT/EXIT and startup procedures
|
|
--------------------------------
|
|
|
|
In CA-Cl*pper the startup procedure is always the first procedure/function
|
|
of the main module, even if such symbol is an INIT or EXIT symbol. In
|
|
such case the program will never execute the "main" symbol. In Harbour
|
|
the first *non* INIT/EXIT symbol, will be executed as the main symbol
|
|
after all INIT procedures have been executed.
|
|
|
|
FOR EACH statement
|
|
------------------
|
|
Harbour has support enumeration loop with the following syntax:
|
|
|
|
FOR EACH var1 [,var255] IN expr1 [,expr255] [DESCEND]
|
|
[EXIT]
|
|
[LOOP]
|
|
...
|
|
NEXT
|
|
|
|
Note:
|
|
-expr can be a string or an array
|
|
-enumerator variable 'var<n>' stores a reference to the element of
|
|
an array or a string specified by 'expr<n>' thus assigments to the
|
|
enumerator changes the value of given array element
|
|
-after the loop the controlling variable(s) store the value which
|
|
they had before entering the loop
|
|
-the enumeraqtor variable supports the following properties
|
|
:__enumindex - the loop counter for variable
|
|
:__enumbase - the value that is being traversed
|
|
:__enumvalue - the value of variable
|
|
|
|
|
|
for example:
|
|
a = 'A'
|
|
b = 'B'
|
|
FOR EACH a,b IN { 1, 2, 3, 4 }, "abcd"
|
|
? a, b //prints: 1 a
|
|
// 2 b
|
|
// 3 c
|
|
// 4 d
|
|
NEXT
|
|
? a, b //prints: A B
|
|
|
|
// you can use EXIT statement inside the loop
|
|
FOR EACH a IN { 1, 2, 3, 4 }
|
|
IF( a:__enumindex == 3 )
|
|
? a
|
|
EXIT
|
|
ENDIF
|
|
NEXT
|
|
|
|
arr := { 1, 2, 3 }
|
|
str := "abc"
|
|
FOR EACH a, b IN arr, str
|
|
a *= 2
|
|
str := UPPER( str )
|
|
NEXT
|
|
//now 'arr' stores { 2, 4, 6 }
|
|
//howerer 'str' still stores "abc"
|
|
|
|
Notice the difference:
|
|
FOR EACH a IN someValue
|
|
? a:__enumindex //prints current value of the index
|
|
? (a):__enumindex //sends '__enumindex' message to the current value
|
|
NEXT
|
|
|
|
|
|
WITH OBJECT
|
|
-----------
|
|
Harbour supports the following statement:
|
|
|
|
WITH OBJECT expression
|
|
...
|
|
END
|
|
|
|
Inside this WITH OBJECT/END enclosure you can use the simplified
|
|
form of sending messages to the object. You can use the syntax
|
|
:message( [params] )
|
|
:property
|
|
to send messages to the object specified by 'expression'
|
|
|
|
for example:
|
|
WITH OBJECT myobj:a[1]:myitem
|
|
:message( 1 )
|
|
:value := 9
|
|
END
|
|
|
|
The above code is equivalent to:
|
|
myobj:a[1]:myitem:message( 1 )
|
|
myobj:a[1]:myitem:value := 9
|
|
|
|
Inside WITH OBJECT/END you can access (or even assign a new object)
|
|
using a special reserved property :__withobject
|
|
|
|
The runtime error will be generated at the time of message
|
|
sending (or property access/assign) if <objexpression>
|
|
is not a value of type object.
|
|
|
|
for example:
|
|
CLASS foo
|
|
DATA name INIT 'FOO'
|
|
ENDCLASS
|
|
|
|
CLASS bar
|
|
DATA name INIT 'BAR'
|
|
ENDCLASS
|
|
|
|
WITH OBJECT foo():new()
|
|
? :name //prints 'FOO'
|
|
? :__withobject:name //also prints 'FOO'
|
|
? :__withobject := bar():new()
|
|
? :name //prints 'BAR'
|
|
END
|