How I can check validity of a macro ?

PROC MAIN()

    nResult   := NIL
    nDivident := 1
    nDivisor  := 0
    cMacro    := " nResult := nDivident / nDivisor "  
    QOutResult( nDivident, nDivisor, cMacro ) // 1  0  UE macro is inValid

    nDivisor  := 2
    QOutResult( nDivident, nDivisor, cMacro ) // 1  2  N  Result is :  0.50

    cMacro    := "AT( 'OK', MyUDF() ) > 0"              
    QOutResult( 'AT( OK', 'MyUDF()', cMacro ) // AT( OK ... U macro is inValid

    cMacro    :=  "{ 1, 2 }[ 2 ]"                       
    QOutResult( '{ 1, 2 }', '[2]', cMacro ) // { 1, 2 } [2]   N Result is : 2

    cMacro    :=  "{ 1, 2 }[ 5 ]"  
    QOutResult( '{ 1, 2 }', '[5]', cMacro ) // { 1, 2 } [5] UE macro is inValid

    lCond := 0
    cMacro    :=  "if( lCond, 'true', MyUDF() )"
    QOutResult( lCond, '', cMacro )           // 0        U macro is inValid   
    ?
    WAIT

RETU // Main()

*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.

PROC QOutResult( xVal1, xVal2, cMacro )

	LOCAL cType := TYPE( cMacro )

	? PAD( xVal1, 10 ), PAD( xVal2, 10 ),  PAD( cType, 3 )

    IF ( cType # "U") 
       ?? "Result is :", &cMacro
    ELSE
       ?? "macro is inValid"
    ENDIF

RETU // QOutResult()

*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._

See Also:

& (macro evaluation unary) Operator 

Macro Compiler

HB_SetMacro()

ValType()

TYPE()

C5_TYPE()

Harbour All Functions – H

HardCR

HBClass()

HB_ANSITOOEM()

hb_At

hb_cdpSelect

HB_ColorIndex

HB_DiskSpace

HB_EOL

HB_FEof

hb_FLock

hb_FUnlock

hb_gcAll
hb_gcAlloc
hb_gcCollectAll
hb_gcFree
hb_gcItemRef

hb_GetEnv

hb_HAllocate

hb_Hash
hb_HAutoAdd
hb_HBinary
hb_HCaseMatch
hb_HClone
hb_HCopy
hb_HDefault
hb_HDel
hb_HDelAt
hb_HEval
hb_HFill
hb_HGet
hb_HGetDef
hb_HHasKey
hb_HKeyAt
hb_HKeys
hb_HMerge
hb_HPairAt
hb_HPos
hb_HScan
hb_HSet

hb_HSetAutoAdd()
hb_HSetBinary() 
hb_HSetCaseMatch()

hb_HSort
hb_HValueAt
hb_HValues

hb_idleAdd
hb_idleDel
hb_idleState

hb_inetAddress
hb_inetCleanup
hb_inetClearError
hb_inetClearPeriodCallback
hb_inetClearTimeLimit
hb_inetClearTimeout
hb_inetClose
hb_inetConnect
hb_inetConnectIP
hb_inetCount
hb_inetCreate
hb_inetCRLF
hb_inetDataReady
hb_inetDGram
hb_inetDGramBind
hb_inetDGramRecv
hb_inetDGramSend
hb_inetErrorCode
hb_inetErrorDesc
hb_inetFD
hb_inetGetAlias
hb_inetGetHosts
hb_inetGetRcvBufSize
hb_inetGetSndBufSize
hb_inetInit
hb_inetIsSocket
hb_inetPeriodCallback
hb_inetPort
hb_inetRecv
hb_inetRecvAll
hb_inetRecvEndblock
hb_inetRecvLine
hb_inetSend
hb_inetSendAll
hb_inetServer
hb_inetSetRcvBufSize
hb_inetSetSndBufSize
hb_inetstatus
hb_inetTimeLimit
hb_inetTimeout

HB_IsByRef()

hb_keyPut

hb_langErrMsg
hb_langMessage
hb_langName
hb_langSelect

hb_mathErBlock
hb_mathErMode
hb_mathGetErrMode
hb_mathGetHandler
hb_mathGetLastError
hb_mathIsMathErr
hb_mathResetError
hb_mathSetErrMode
hb_mathSetHandler

hb_MemoRead
hb_MemoWrit

hb_RAt

hb_PIsByRef

hb_PValue

hb_SetKeyCheck
hb_SetKeyGet
hb_SetKeySave

hb_setListenerAdd

hb_setListenerNotify
hb_setListenerRemove

hb_SetMacro

hb_Translate

hb_ValToStr

Header

HexaToDec

Harbour Macro compiler

Invoking the macro compiler:

      &variable     
      or                               
      &( expression )               
      or                               
      &variable.text

Description

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, .T. ) 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, .T. ) 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.

Seealso

hb_SetMacro()

hb_SetMacro()

hb_SetMacro()

Enable/disable the macro compiler runtime features.

Syntax

      hb_SetMacro( <nOption>,  [<lOnOff>] ) --> <lOldSetting>

Arguments

<nOption> One of the HB_SM_* constants defined in set.ch.

<lOnOff> .T. to enable or .F. to disable a feature

Returns

hb_SetMacro() return the old state of requested feature.

Description

This function enables or disables some features of the macro compiler. The Harbour is extending the macro features compared to an original set available in CA-Cl*pper. Enabling/disabling some of them allows to keep strict CA-Cl*pper compatibility.

Available features are:

HB_SM_HARBOUR – enables harbour extensions: operators: ++, –, +=, -=, *=, /=, ˆ= objects: assigments to an instance variable

HB_SM_XBASE – enables other Xbase++ dialects extensions: expanding of expresions lists

HB_SM_SHORTCUTS – enables optimized evaluation of logical operators (.and., .or.)

HB_SM_PREPROC – enables preprocessing of commands This is meaningfull if Harbour is compiled with HB_MACRO_STATEMENTS flag

Examples

      INIT PROCEDURE IWANTCLIPPER()
         hb_SetMacro( HB_SM_HARBOUR,  .F. )
         hb_SetMacro( HB_SM_XBASE,  .F. )
         RETURN

Compliance

Harbour

Platforms

All

Files

Header file is set.ch
Library is core

Seealso

Macro compiler

Features Differences

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, .T. ) 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, .T. ) 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
      ...
   ENDWITH

   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
   ENDWITH

   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:
   CREATE CLASS foo
      VAR name INIT 'FOO'
   ENDCLASS

   CREATE CLASS bar
      VAR name INIT 'BAR'
   ENDCLASS

   WITH OBJECT foo():new()
      ? :name                 //prints 'FOO'
      ? :__withobject:name    //also prints 'FOO'
      ? :__withobject := bar():new()
      ? :name                 //prints 'BAR'
   ENDWITH

Source : https://github.com/harbour/core/blob/master/doc/clipper.txt