Danny A. del Pilar

Contributed works of Danny A. del Pilar

Browse Test Demo

Easter Sunday Calculation

Generate Gregorian Calendar

HMG source code converter

How to build menu like old ACHOICE function?

KPI (Key Performance Indicator) Dashboard

Return value from modal window (Record Picker) 

Similar SCATTER / GATHER en HMG

SET PROCEDURE

SET PROCEDURE*

Compile procedures and functions into the current object (.OBJ) file

Syntax

      SET PROCEDURE TO [<idProgramFile>[.<ext>]]

Arguments

TO <idProgramFile> is the name of the procedure file to compile into the current object file. It can optionally include a path and/or drive designator.

<ext> is the optional extension of the procedure. If not specified, .prg is assumed.

SET PROCEDURE TO with no argument is ignored.

Description

SET PROCEDURE directs the compiler to compile all procedures and user- defined functions declared within the specified procedure file into the current object (.OBJ) file.

SET PROCEDURE is a compatibility command and not recommended. It has been superseded by other facilities more appropriate to the compiled environment (e.g., the compiler script (.clp)) file.

See the Clipper “Compiler” chapter in the Programming and Utilities Guide for a full discussion of program architecture and configuration.

Seealso

#include, DO*, FUNCTION, PROCEDURE, RETURN

QUIT

QUIT

Terminate program processing

Syntax

      QUIT | CANCEL*

Description

QUIT and CANCEL both terminate program processing, close all open files, and return control to the operating system. Each of these commands can be used from anywhere in a program system. A RETURN executed at the highest level procedure or a BREAK, with no pending SEQUENCE, also QUITs the program.

Notes

. Return code: When a Harbour program terminates, the return code is set to 1 if the process ends with a fatal error. If the process ends normally, the return code is set to zero or the last ERRORLEVEL() set in the program.

Examples

      .  This example uses QUIT in a dialog box:
      IF DialogYesNo(10, 10, "Quit to DOS", "BG+/B,B/W", 2)
         QUIT
      ENDIF
      RETURN

Seealso

BEGIN SEQUENCE, ERRORLEVEL(), RETURN

CLOSE

CLOSE

Close a specific set of files

Syntax

      CLOSE [<idAlias> | ALL | ALTERNATE | DATABASES |
             FORMAT | INDEXES]

Arguments

<idAlias> specifies the work area where all files are to be closed.

ALL closes alternate, database, and index files in all work areas, releasing all active filters, relations, and format definitions.

ALTERNATE closes the currently open alternate file, performing the same action as SET ALTERNATE TO with no argument.

DATABASES closes all open databases, memo and associated index files in all work areas, and releases all active filters and relations. It does not, however, have any effect on the active format.

FORMAT releases the current format, performing the same action as SET FORMAT TO with no argument.

INDEXES closes all index files open in the current work area.

Description

CLOSE is a general purpose command that closes various types of Clipper files depending on the specified option. CLOSE with no option closes the current database and associated files, the same as USE with no arguments.

In Harbour, a number of other commands also close files including:

          .  QUIT
          .  CANCEL*
          .  RETURN from the highest level procedure
          .  CLEAR ALL*
          .  USE with no argument

Seealso

QUIT, RETURN, SET ALTERNATE, SET INDEX, USE

CANCEL

CANCEL*

Terminate program processing

Syntax

      CANCEL* | QUIT

Description

CANCEL and QUIT both terminate the current program, closing all open files, and returning control to the operating system. You can use either command from anywhere in a Clipper program system. A RETURN executed at the highest level procedure performs the same action. Note that CANCEL is a compatibility command. QUIT should be used in its place.

Notes

. Return code: When a Clipper program terminates, the return code is set to 1 if the process ends with a fatal error. If the process ends normally, the return code is set to 0 or the last ERRORLEVEL() set in the program.

Seealso

ERRORLEVEL(), QUIT, RETURN

PROCEDURE

PROCEDURE

Declare a procedure name and formal parameters

Syntax

       [STATIC] PROCEDURE <idProcedure> [(<idParam list>)]
              [FIELD <idField list> [IN <idAlias>]
              [LOCAL <identifier> [[:= <initializer>], ... ]]
              [MEMVAR <identifier list>]
              [STATIC <identifier> [[:= <initializer>], ... ]]
              .
              . <executable statements>
              .
              [RETURN]

Arguments

<idProcedure> is the name of the procedure to be declared. Procedure names can be any length, but only the first 10 characters are significant. Names can contain any combination of characters, numbers, or underscores, but leading underscores are reserved.

<idParam list> is the declaration of one or more parameter variables. Variables specified in this list are declared local.

STATIC PROCEDURE declares a procedure that can be called only by procedures and user-defined functions declared in the same program (.prg) file.

FIELD declares a list of identifiers, <idField list>, to use as field names whenever encountered. If the IN clause is specified, referring to the declared name, <idAlias> is a reference to the appropriate work area of the specified database.

LOCAL declares and optionally initializes a list of variables or arrays whose visibility and lifetime is the current procedure.

<identifier>, <identifier list> is a label or labels used as variable or array names. If the <identifier> is followed by square brackets ([ ]), it is created as an array. If the <identifier> is an array, the syntax for specifying the number of elements for each dimension can be array[<nElements>, <nElements2>, …] or array[<nElements>][<nElements2>]… The maximum number of elements per dimension is 4096. The maximum number of dimensions per array is limited only by available memory.

<initializer> is the value to which an optional inline assignment sets the <identifier> variable–essentially, the assignment operator, (:=) –followed by any valid Harbour expression, including a literal array. If no <initializer> is specified, variables are initialized to NIL. In the case of arrays, all element are initialized to NIL.

MEMVAR declares a list of identifiers, <identifier list>, to use as private or public memory variables or arrays whenever encountered.

STATIC declares and, optionally, initializes a list of variables or arrays whose visibility is the current procedure and whose lifetime is the duration of the program.

RETURN passes control back to the calling procedure or user-defined function. If a RETURN is not specified, control passes back to the calling routine when the procedure definitions ends. In all cases, the compiler terminates the procedure definition when it encounters another PROCEDURE statement, FUNCTION statement, or end of file character.

Description

The PROCEDURE statement declares a procedure and an optional list of local variables to receive parameters passed from a calling routine. A procedure is a subprogram comprised of a set of declarations and statements executed whenever you refer to <idProcedure>, followed by an open and close parentheses pair or with the DO statement. A procedure definition begins with a PROCEDURE statement and ends with the next PROCEDURE statement, FUNCTION statement, or end of file.

Procedures that encapsulate computational blocks of code provide readability and modularity, isolate change, and help manage complexity.

A procedure in Harbour is the same as a user-defined function, with the exception that it always returns NIL. Each procedure must begin with a PROCEDURE statement and may, optionally, contain a RETURN statement to return control to the calling procedure or user-defined function. A RETURN statement, however, is not required. Procedure declarations cannot be nested within other procedure definitions.

The visibility of procedure names falls into two classes. Procedures that are visible anywhere in a program are referred to as public procedures and declared with a PROCEDURE statement. Procedures that are visible only within the current program (.prg) file are referred to as static procedures and declared with a STATIC PROCEDURE statement. Static procedures have filewide scope.

Static procedures are quite useful for a number of reasons. First, they limit visibility of a procedure name thereby restricting access to the procedure. Because of this, subsystems defined within a single program (.prg) file can provide an access protocol with a series of public procedures and conceal the implementation details of the subsystem within static procedures and functions. Second, since the static procedure references are resolved at compile time, they preempt references to public procedures and functions which are resolved at link time. This ensures that, within a program file, a reference to a static procedure executes that procedure if there is a name conflict with a public procedure or function.

For more information on procedures, variable declarations, and parameter passing, refer to the “Basic Concepts” chapter.

Notes

. Calling a procedure: There are two ways to call a procedure in Harbour. The first and preferred way is the function-calling convention. Here you call the procedure as you would a Harbour function on a line by itself:

<idProcedure>([<argument list>])

The second and obsolete way is the command-calling convention using the DO…WITH command. The two methods of calling procedures differ only in the default method of passing parameters. The function- calling convention passes variables by value as a default, whereas the command-calling convention passes them by reference as a default.

A procedure can also be called as an aliased expression if it is prefaced with an alias and invoked using the function-calling convention, like this: <idAlias> ->(<idProcedure>(<argument list>)) When called as an aliased expression, the work area associated with <idAlias> is selected, the procedure is executed, and then the original work area is reselected. Like an expression or function, an aliased procedure can be specified on a line by itself. A procedure in Harbour may call itself recursively. This means you can call a procedure in the same procedure definition.

. Parameters: Procedures like user-defined functions can receive parameters passed from a calling procedure, user-defined function, or the DOS command line. A parameter is a place for a value or reference. In Harbour there are two ways to receive parameters: a list of local variable names can be declared as a part of the PROCEDURE declaration (referred to as formal parameters), or a list of private variables can be specified in a separate PARAMETERS statement. Note that you cannot mix a declaration of formal parameters with a PARAMETERS statement. Attempting this will cause a fatal compiler error.

Procedures receive parameters in the order passed. In Harbour the number of parameters need not match the number of arguments passed. Arguments can be skipped or left off the end of the argument list. A parameter not receiving a value or reference is initialized to NIL. If arguments are specified, PCOUNT() returns the position of the last argument passed.

Parameters specified in a procedure can receive arguments passed by value or by reference. The default method for expressions and variables depends on the calling convention. With the function-calling convention, the default passing method for expressions and variables is by value. This includes variables containing references to arrays and objects. With the command- calling convention, the default method for passing variables is by reference except for field variables, which are always passed by value. Whenever a field variable is passed, it must be specified enclosed in parentheses unless declared with the FIELD statement. Failure to do so will generate a runtime error.

Examples

       .  This example shows a skeleton of a typical Harbour
          procedure that uses lexical variables:
          PROCEDURE Skeleton( cName, cClassRoom, nBones, ;
                                  nJoints )
             LOCAL nCrossBones, aOnHand := {"skull", ;
                                           "metacarpals"}
             STATIC nCounter := 0
             .
             . <executable statements>
             .
             RETURN
       .  This example determines whether an argument was skipped by
          comparing the parameter to NIL:
          PROCEDURE MyProc( param1, param2, param3 )
             IF param2 != NIL
                param2 := "default value"
             ENDIF
             .
             . <statements>
             .
             RETURN
       .  This example invokes the procedure, UpdateAmount(), as an
          aliased expression:
          USE Invoices NEW
          USE Customer NEW
          Invoices->(UpdateAmount(Amount + Amount * nInterest))

Seealso

FUNCTION, LOCAL, PARAMETERS, PCOUNT(), RETURN, STATIC

FUNCTION

FUNCTION

Declare a user-defined function name and formal parameters

Syntax

       [STATIC] FUNCTION <idFunction>[(<idParam list>)]
              [LOCAL <identifier> [[:= <initializer>], ... ]]
              [STATIC <identifier> [[:= <initializer>], ... ]]
              [FIELD <identifier list> [IN <idAlias>]]
              [MEMVAR <identifier list>]
              .
              . <executable statements>
              .
              RETURN <exp>

Arguments

<idFunction> is the name of the user-defined function to be declared. User-defined function names can be any length, but only the first 10 characters are significant. Names can contain any combination of characters, numbers, or underscores, but must begin with a character or an underscore. Leading underscores are not recommended since they are reserved for internal functions.

<idParam list> is the declaration of one or more parameter variables. Variables specified in this list are declared local.

STATIC FUNCTION declares a user-defined function that can be invoked only by procedures and user-defined functions declared in the same program (.prg) file.

LOCAL declares and optionally initializes a list of variables or arrays whose visibility and lifetime is the current function.

STATIC declares and optionally initializes a list of variables or arrays whose visibility is the current user-defined function and lifetime is the duration of the program.

FIELD declares a list of identifiers to use as field names whenever encountered. If the IN clause is specified, referring to the declared name includes an implicit reference to the specified alias.

MEMVAR declares a list of identifiers to use as private or public memory variables or arrays whenever encountered.

<identifier> and <identifier list> are labels to be used as variable or array names.

<initializer> is a value to which an array or variable is originally set in an inline expression. RETURN <exp> passes control back to the calling procedure or user-defined function, returning the result of <exp> as the value of the function. Each function must have at least one

RETURN statement that returns a value. RETURN statements can occur anywhere in the body of a function.

Description

The FUNCTION statement declares a user-defined function and an optional list of local variables to receive parameters often referred to as formal parameters. A user-defined function is a subprogram comprised of a set of declarations and statements executed whenever you refer to <idFunction> followed by an open and closed parentheses pair. A function definition begins with a FUNCTION statement which is the FUNCTION declaration and ends with the next FUNCTION statement, PROCEDURE statement, or end of file.

Functions encapsulate a computational block of code and then later create expressions using the value returned. Functions and procedures increase both readability and modularity, isolate change, and help manage complexity.

A function in Harbour is the same as a procedure, except that it must return a value. The returned value can be any data type including an array, a code block, or NIL. Each function must begin with a FUNCTION statement and contain at least one RETURN statement with an argument. Function declarations cannot be nested within other function definitions. A user-defined function can be used wherever standard functions are supported, including expressions.

The visibility of function names falls into two classes. Functions that are visible anywhere in a program are referred to as public functions and declared with a FUNCTION statement. Functions that are visible only within the current program (.prg) file are referred to as static functions and declared with a STATIC FUNCTION statement.

Static functions have filewide scope. Static functions limit visibility of a function name, thereby restricting access to the function. Because of this, subsystems defined within a single program (.prg) file can provide an access protocol with a series of public functions and conceal the implementation details of the subsystem within static functions and procedures. Since the static function references are resolved at compile time, they preempt references to public functions which are resolved at link time. This ensures that within a program file, a reference to a static function executes that function if there is a name conflict with a public function.

For more information on user-defined functions, variable declarations, and parameter passing, refer to the “Basic Concepts” chapter.

Notes

. Calling a user-defined function: Use the same notation to call a user-defined function as when calling a standard Harbour function: <idFunction>([<argument list>])

You can call a user-defined function within an expression or on a line by itself. If called on a line by itself, the return value is ignored.

You can also call a user-defined function as an aliased expression by prefacing it with an alias and enclosing it in parentheses: <idAlias>->(<idFunction>(<argument list>))

When you call a user-defined function as an aliased expression, the work area associated with <idAlias> is selected, the expression is executed, and the original work area is then reselected. You can specify an aliased expression on a line by itself, as you would any other expression.

A user-defined function in Harbour may call itself recursively. This means you can make a reference to a user-defined function in statements or expressions of the same user-defined function definition.

. Parameters: User-defined functions, like procedures, can receive parameters passed from a calling procedure, user-defined function, or DOS command line. A parameter is a place holder for a value or reference. In Harbour, there are two ways to express parameters: you can declare a list of local variable names as a part of the FUNCTION declaration (referred to as formal parameters), or you can specify a list of private variables in a separate PARAMETERS statement. Note that you cannot mix a declaration of formal parameters with a PARAMETERS statement. Attempting this will result in a fatal compiler error.

Functions receive parameters in the order passed. In Harbour, the number of parameters does not have to match the number of arguments passed. You can skip arguments or omit them from the end of the argument list. A parameter not receiving a value or reference is initialized to NIL. You can skip a parameter by passing NIL. If arguments are specified, PCOUNT() returns the position of the last argument passed. (If more arguments are passed than are parameters, they are ignored.)

Parameters specified in a user-defined function can receive arguments passed by value or reference. The default method for expressions and variables is by value. This includes variables that contain references to arrays and objects. All variables except field variables, when prefaced with the pass-by-reference operator (@), are passed by reference. Field variables cannot be passed by reference and are always passed by value.

Examples

       .  This example demonstrates a user-defined function that formats
          numeric values as currency:
       ? Currency( 1000 )               // Result: Þ1,000.00
       FUNCTION Currency( nNumber )
          LOCAL cNumber
          IF nNumber < 0
             cNumber := TRANSFORM(-1 * nNumber, ;
                   "999,999,999,999.99")
             cNumber := PADL("(Þ" + LTRIM(cNumber) + ")", ;
                   LEN(cNumber))
          ELSE
             cNumber := TRANSFORM(nNumber, ;
                   "999,999,999,999.99")
             cNumber := PADL("Þ" + LTRIM(cNumber), ;
                   LEN(cNumber))
          ENDIF
          RETURN cNumber
       . This example demonstrates a user-defined function that takes a
          character string formatted as a comma-separated list and returns 
          an array with one element per item:
       aList := ListAsArray("One, Two")
       // Result: {"One", "Two"}
       FUNCTION ListAsArray( cList )
          LOCAL nPos
          // Define an empty array
          LOCAL aList := {}
          //
          DO WHILE (nPos := AT(",", cList)) != 0
             // Add a new element
             AADD(aList, SUBSTR(cList, 1, nPos - 1))
             cList := SUBSTR(cList, nPos + 1)
          ENDDO
          AADD(aList, cList)
          //
          // Return the array
          RETURN aList
       .  This example checks for a skipped argument by comparing
          the parameter to NIL:
       FUNCTION MyFunc( param1, param2, param3 )
          IF param2 == NIL
             param2 := "default value"
          ENDIF
          .
          . <statements>
          .
          RETURN NIL
       .  This example uses the user-defined function, Currency()
          (defined above), as an aliased expression:
       USE Invoices NEW
       USE Customer NEW
       ? Invoices->(Currency(Amount))

Seealso

LOCAL, PARAMETERS, PCOUNT(), PRIVATE, PROCEDURE, RETURN

BEGIN SEQUENCE

BEGIN SEQUENCE

Define a sequence of statements for a BREAK

Syntax

      BEGIN SEQUENCE
         <statements>...
         [BREAK [<exp>]]
              <statements>...
         [RECOVER [USING <idVar>]]
              <statements>...
      END [SEQUENCE]

Arguments

BREAK <exp> branches execution to the statement immediately following the nearest RECOVER statement if one is specified or the nearest END SEQUENCE statement.

<exp> is the value returned into the <idVar> specified in the USING clause of the RECOVER statement.

RECOVER USING <idVar> defines a recover point in the SEQUENCE construct where control branches after a BREAK statement. If USING <idVar> clause is specified, <idVar> receives the value returned by the BREAK statement. In general, this is an error object.

END defines the end point of the SEQUENCE control structure. If no RECOVER statement is specified, control branches to the first statement following the END statement after a BREAK.

Description

BEGIN SEQUENCE…END is a control structure used for exception and runtime error handling. It delimits a block of statements, including invoked procedures and user-defined functions. When a BREAK is encountered anywhere in a block of statements following the BEGIN SEQUENCE statement up to the corresponding RECOVER statement, control branches to the program statement immediately following the RECOVER statement. If a RECOVER statement is not specified, control branches to the statement following the END statement, terminating the SEQUENCE. If control reaches a RECOVER statement without encountering a BREAK, it branches to the statement following the corresponding END.

The RECOVER statement optionally receives a parameter passed by a BREAK statement that is specified with a return value. This is usually an error object, generated and returned by the current error handling block defined by ERRORBLOCK(). If an error object is returned, it can be sent messages to query information about the error. With this information, a runtime error can be handled within the context of the operation rather than in the current runtime error handler. See the example below.

Within a SEQUENCE construct there are some restrictions on what statements are allowed between the BEGIN SEQUENCE and RECOVER statements. You cannot RETURN, LOOP, or EXIT between a BEGIN SEQUENCE and RECOVER statement. From within the RECOVER statement block, however, you can LOOP, EXIT, BREAK, or RETURN since the SEQUENCE is essentially completed at that point. Using LOOP from within the RECOVER statement block is useful for re-executing the SEQUENCE statement block. See the example below.

SEQUENCE constructs are quite flexible. They can be nested and more than one can be defined in the same procedure or user-defined function. If more than one SEQUENCE construct is specified, each SEQUENCE should delimit one discrete operation.

     For more information on error objects, refer to the Error class.

Examples

       .  This code fragment demonstrates a SEQUENCE construct in which
          the BREAK occurs within the current procedure:
          BEGIN SEQUENCE
             <statements>...
             IF lBreakCond
                BREAK
             ENDIF
          RECOVER
             <recovery statements>...
          END
          <recovery statements>...
       .  This example demonstrates an error handler returning an error
          object to the variable specified in the USING clause of the RECOVER
          statement:
          LOCAL objLocal, bLastHandler
          //
          // Save current and set new error handler
          bLastHandler := ERRORBLOCK({ |objErr| ;
                MyHandler(objErr, .T.) })
          //
          BEGIN SEQUENCE
             .
             . <operation that might fail>
             .
          RECOVER USING objLocal
             //
             // Send messages to objLocal and handle the error
             ? "Error: "
             IF objLocal:genCode != 0
                ?? objLocal:description
             ENDIF
             .
             .
             .
          END
          //
          // Restore previous error handler
          ERRORBLOCK( bLastHandler )
          FUNCTION MyHandler( objError, lLocalHandler )
             //
             // Handle locally returning the error object
             IF lLocalHandler
                BREAK objError
             ENDIF
             .
             . <other statements to handle the error>
             .
             RETURN NIL
       .  This example re-executes a SEQUENCE statement block by LOOPing
          from within the RECOVER statement block:
          DO WHILE .T.
             BEGIN SEQUENCE
                .
                . <operation that may fail>
                .
             RECOVER
                IF PrintRecover()
                   LOOP      // Repeat the SEQUENCE statement block
                ENDIF
             END
             EXIT            // Escape from the operation
          ENDDO

See also:

Error class, ERRORBLOCK(), RETURN

Codeblocks

The Harbour implementation of codeblocks

Author : Ryszard Glab <rglab@imid.med.pl>

Compilation of a codeblock.
During compile time the codeblock is stored in the following form:
- the header
- the stream of pcode bytes
The header stores information about referenced local variables.
+0: the pcode byte for _PUSHBLOCK
+1: the number of bytes that defines a codeblock
+3: number of codeblock parameters (declared between || in a codeblock)
+5: number of used local variables declared in procedure/function where
 the codeblock is created
+7: the list of procedure/function local variables positions on the eval
 stack of procedure/function. Every local variable used in a codeblock
 occupies 2 bytes in this list. When nested codeblocks are used then this
 list is created for the outermost codeblock only.
+x: The stream of pcode bytes follows the header.
+y: the pcode byte for _ENDBLOCK

Creation of a codeblock.
When HB_P_PUSHBLOCK opcode is executed then the HB_ITEM structure is created
and placed on the eval stack. The type of item is IT_BLOCK. The value of this
item is a pointer to HB_CODEBLOCK structure. Additionally this item stores the
base of static variables defined for the current function/procedure - this
is used during a codeblock evaluation when the evaluation is called from a code
from other PRG module. Also the number of expected parameters is stored.
The HB_CODEBLOCK structure stores a pointer to the pcodes stream that is
executed during a codeblock evaluation. It stores also the pointer to a table
with local variables references. Values of all local variables defined in a
procedure and used in a codeblock are replaced with a reference to a
value stored in a global memory variables pool. This allows the correct access
to detached local variables in a codeblock returned from this function (either
directly in RETURN statement or indirectly by assigning it to a static or
memvar variable. This automatic and unconditional replace is required because
there is no safe method to find if a codeblock will be accessed from an outside
of a function where it is created.
When nested codeblocks are used then only the outermost codeblock creates
the table - all inner codeblock uses this table. The first element of this
table contains a reference counter for this table. It allows to share the table
between nested codeblock - the table is deleted if there is no more references
to it. This is caused by the fact that a inner codeblock can be created during
evaluation of outer codeblock when local variables don't exist like in this
example:
PROCEDUE Main()
 PRIVATE foo, bar
Test()
 Eval( foo )
 Eval( bar )

PROCEDURE Test()
 LOCAL a := "FOO", b := "BAR"
foo := {|| a + ( bar := Eval( {|| b } ) ) }
RETURN

Evaluation of a codeblock.
Parameters passed to a codeblock are placed on the eval stack before a
codeblock evaluation. They are accessed just like usual function
parameters. When a codeblock parameter is referenced then its position on the
eval stack is used. When a procedure local variable is referenced then the
index into the table of local variables positions (copied from the header) is
used. The negative value is used as an index to distinguish it from the
reference to a codeblock parameter.

Incompatbility with the Clipper.
1) Detached locals passed by reference
There is a little difference between the handling of variables passed by
the reference in a codeblock.
The following code explains it (thanks to David G. Holm)
PROCEDURE Main()
 LOCAL nTest
 LOCAL bBlock1 := MakeBlock()
 LOCAL bBlock2 := {|| DoThing( @nTest ), QOut( "From Main: ", nTest ) }
Eval( bBlock1 )
 Eval( bBlock2 )
RETURN
FUNCTION MakeBlock()
 LOCAL nTest
 RETURN {|| DoThing( @nTest ), QOut( "From MakeBlock: ", nTest ) }
FUNCTION DoThing( n )
n := 42
RETURN NIL

 In Clipper it produces:
From MakeBlock: NIL
From Main: 42
In Harbour it produces (it is the correct output, IMHO)
From MakeBlock: 42
From Main: 42

2) Scope of undeclared variables
 Consider the following code:
PROCEDURE Main()
 LOCAL cb
 cb := Detach()
 ? Eval( cb, 10 )
 RETURN
FUNCTION Detach()
 LOCAL b := {| x | x + a }
 LOCAL a := 0
 RETURN b

In Clipper the 'a' variable in a codeblock has the *local* scope however in
Harbour the 'a' variable has the *private* scope. As a result, in Clipper
this code will print 10 and in Harbour it will raise 'argument error' in
'+' operation.
 This will be true also when the 'a' variable will be declared as PRIVATE

PROCEDURE Main()
 LOCAL cb
 PRIVATE a
 cb := Detach()
 ? Eval( cb, 10 )
 RETURN

The above code also prints 10 in Clipper (even if compiled with -a or -v
switches)

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

C5_RETURN

RETURN
 Terminate a procedure, user-defined function, or program
------------------------------------------------------------------------------
 Syntax

     RETURN [<exp>]

 Arguments

     <exp> is an expression of any type that evaluates to the return
     value for user-defined functions.  If a user-defined function terminates
     without executing a RETURN statement, the return value is NIL.

 Description

     RETURN terminates a procedure, user-defined function, or program by
     returning control to either the calling procedure or user-defined
     function.  When RETURN executes in the highest level procedure, control
     passes to the operating system.  All private variables created and local
     variables declared in the current procedure or user-defined function are
     released when control returns to the calling procedure.

     There can be more than one RETURN in a procedure or user-defined
     function.  A procedure or user-defined function need not, however, end
     with a RETURN.  Since user-defined functions must return values, each
     must contain at least one RETURN statement with an argument.

     Note:  A procedure or user-defined function definition is terminated
     by a PROCEDURE statement, a FUNCTION statement, or end of file but not
     by a RETURN statement.

 Notes

     .  Arrays: Since array is a data type like any other data type,
        instances of array type are really values like character strings and,
        therefore, can be RETURNed from a user-defined function.

     .  RETURN TO MASTER: Clipper does not support RETURN TO MASTER
        or any other form of RETURN specifying the level to which the call is
        to return.  You can, however, simulate these operations with BEGIN
        SEQUENCE...END.

 Examples

     .  These examples illustrate the general form of the RETURN
        statement in a procedure and in a user-defined function:

        PROCEDURE <idProcedure>
           //
           <statements>...
           //
           RETURN

        FUNCTION <idFunction>
           //
           <statements>...
           //
           RETURN <expReturn>

     .  This example returns an array, created in a user-defined
        function, to a calling procedure or user-defined function:

        FUNCTION PassArrayBack
           PRIVATE aArray[10][10]
           aArray[1][1] = "myString"
           RETURN aArray

See Also: BEGIN SEQUENCE FUNCTION LOCAL PRIVATE PROCEDURE