INIT PROCEDURE

INIT PROCEDURE

Declare an initialization procedure

Syntax

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

Arguments

INIT PROCEDURE declares a procedure that will be executed at program startup.

<idProcedure> is the name of the initialization procedure to declare. Initialization procedure names can be any length, but only the first 10 characters are significant. Names may not begin with an underscore but can contain any combination of characters, numbers, or underscores.

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

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.

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

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

RETURN passes control to the next initialization procedure or the first executable routine in the program, if no other initialization procedures are pending.

Description

The INIT PROCEDURE statement declares a procedure that will be executed at program startup. INIT procedures are called prior to the first executable statement in a Clipper application, and are useful for performing common initialization tasks such as reading configuration settings, or opening a communications port.

INIT PROCEDUREs are executed implicitly by Clipper at program startup. The visibility of initialization procedures is restricted to the system; therefore, it is not possible to call an INIT PROCEDURE from a procedure or user-defined function. Each INIT PROCEDURE receives a copy of the DOS command line arguments used to invoke the application.

Control passes from one INIT PROCEDURE to the next until all procedures in the initialization list have been called. Control then passes to the first executable statement in the program.

The ANNOUNCE statement declares a module identifier for a source (.prg) file. Once declared, INIT PROCEDUREs are referenced by this module identifier. An application may use any number of initialization procedures by explicitly REQUESTing their module identifiers.

If an error is raised during system initialization, the system returns to DOS, and pending initialization procedures are not called.

Examples

       .  The following example uses both INIT and EXIT PROCEDUREs to
       save and restore the context of the operating system. You can have
       your program, "Myfile.prg", REQUEST SaveDos:

       ANNOUNCE SaveDos
       #define DOS_SCREEN    1
       #define DOS_ROW       2
       #define DOS_COL       3
       #define DOS_CURSOR    4
       #define DOS_COUNT     4
       STATIC saSaveDos[ SD_COUNT ]
       INIT PROCEDURE dosSave()
          SAVE SCREEN TO saSaveDos[ DOS_SCREEN ]
          saSaveDos[ DOS_ROW ]    := ROW()
          saSaveDos[ DOS_COL ]    := COL()
          saSaveDos[ DOS_CURSOR ] := SETCURSOR()
          RETURN
       EXIT PROCEDURE dosRestore()
          RESTORE SCREEN FROM saSaveDos[ DOS_SCREEN ]
          SETPOS   ( saSaveDos[ DOS_ROW ], saSaveDos[ DOS_COL ] )
          SETCURSOR( saSaveDos[ DOS_CURSOR ] )
          RETURN

Seealso

ANNOUNCE, REQUEST, EXIT PROCEDURE

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

C5_EXIT PROCEDURE

EXIT PROCEDURE
 Declare an exit procedure
------------------------------------------------------------------------------
 Syntax

     EXIT PROCEDURE <idProcedure>
        [FIELD <idField list> [IN <idAlias>]]
        [LOCAL <identifier> [[:= <initializer>]]]
        [MEMVAR <identifer list>]
        .
        . <executable statements>
        .
        [RETURN]

 Arguments

     EXIT PROCEDURE declares a procedure that will be executed on program
     termination.

     <idProcedure> is the name of the exit procedure to declare. Exit
     procedure names can be any length, but only the first 10 characters are
     significant.  Names may not begin with an underscore but can contain any
     combination of characters, numbers, or underscores.

     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.

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

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

     RETURN passes control to the next exit procedure or to the operating
     system, if no other exit procedures are pending.

 Description

     The EXIT PROCEDURE statement declares a procedure that will be executed
     upon program termination.  EXIT procedures are called after the last
     executable statement in a Clipper application has completed.  EXIT
     PROCEDUREs can be used to perform common housekeeping tasks such as
     saving configuration settings to a file, closing a log file, or
     concluding a communications session.

     The visibility of exit procedures is restricted to the system;
     therefore, it is not possible to call an EXIT PROCEDURE from a procedure
     or user-defined function.  Exit procedures do not receive parameters.

     Once the last executable statement has completed, control passes from
     one EXIT PROCEDURE to the next until all procedures in the exit list
     have been called.  Control then passes to the operating system.

     The ANNOUNCE statement declares a module identifier for a source (.prg)
     file.  Once declared, EXIT PROCEDUREs are referenced with this module
     identifier.  An application may use any number of exit procedures by
     explicitly REQUESTing their module identifiers.

     The EXIT PROCEDUREs requested for an application are collectively
     referred to as the exit list.  There is no mandatory execution order of
     procedures in the exit list; however, if an EXIT PROCEDURE is declared
     in the same source (.prg) file as the application's primary routine
     (root), it is guaranteed to be the first exit procedure called.

     Termination of a given Clipper application can be attributed to any
     of the following:

     .  RETURNing from the primary (root) routine

     .  the QUIT command

     .  issuing a BREAK without an enclosing BEGIN SEQUENCE...END

     .  unrecoverable error

     Execution of an EXIT PROCEDURE cannot be guaranteed when the system
     encounters an unrecoverable error.  If an error is raised during an exit
     procedure, the system returns to DOS.  Pending exit procedures are not
     called.

 Examples

     .  This example illustrates construction of a simple timing
        mechanism using INIT and EXIT PROCEDUREs:

        // prints the amount of time required to read,
        // sort, and display a list of file names.

        ANNOUNCE MySystem

        STATIC nStart

        PROCEDURE Main()
           AEVAL( ASORT( DIRECTORY( "*.*" ) ),;
              { | aFileInfo | QOUT( aFileInfo[ 1 ] ) } )
           RETURN

        INIT PROCEDURE MyInit()
           nStart := SECONDS()
           RETURN

        EXIT PROCEDURE MyExit()
           ?
           ? "Elapsed Time: "
           ?? SECONDS() - nStart
           RETURN

See Also: ANNOUNCE REQUEST INIT PROCEDURE



C5 Flow Control Commands, Statements and Funtions

Commands :

CALL* :

Execute a C or Assembler procedure

CALL <idProcedure> [WITH <exp list>]

CANCEL* :

Terminate program processing

CANCEL* | QUIT

DO* :

Call a procedure

DO <idProcedure> [WITH <argument list>]

QUIT

Terminate program processing

QUIT | CANCEL*

RUN :

Execute a DOS command or program

RUN | !* <xcCommandLine>

SET KEY :

Assign a procedure invocation to a key

SET KEY <nInkeyCode> TO [<idProcedure>]

SET PROCEDURE *:

Compile procedures/functions into the current .OBJ file

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

WAIT* :

Suspend program processing until a key is pressed

WAIT [<expPrompt>] [TO <idVar>]

Statements :

ANNOUNCE :

Declare a module identifier

ANNOUNCE <idModule>

 BEGIN SEQUENCE :

Define a sequence of statements for a BREAK

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

DO CASE :

Execute one of several alternative blocks of statements

DO CASE
   CASE <lCondition1>
       <statements>...
   [CASE <lCondition2>]
       <statements>...
   [OTHERWISE]
       <statements>...
END[CASE]

DO WHILE :

Execute a loop while a condition is true (.T.)

[DO] WHILE <lCondition>
    <statements>...
    [EXIT]
    <statements>...
    [LOOP]
    <statements>...
END[DO]

EXIT PROCEDURE :

Declare an exit procedure

EXIT PROCEDURE <idProcedure>
    [FIELD <idField list> [IN <idAlias>]]
    [LOCAL <identifier> [[:= <initializer>]]]
    [MEMVAR <identifer list>]
    .
    . <executable statements>
    .
[RETURN]

EXTERNAL* :

Declare a list of procedure or user-defined function names

EXTERNAL <idProcedure list>

FOR :

Execute a block of statements a specified number of times

FOR <idCounter> := <nStart> TO <nEnd> [STEP <nIncrement>]
    <statements>...
    [EXIT]
    <statements>...
    [LOOP]
NEXT

FUNCTION :

Declare a user-defined function name and formal parameters

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

IF :

Execute one of several alternative blocks of statements

IF <lCondition1>
    <statements>...
[ELSEIF <lCondition2>]
    <statements>...
[ELSE]
    <statements>...
END[IF]

INIT PROCEDURE :

Declare an initialization procedure

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

NOTE :

Place a single-line comment in a program file

NOTE This is a comment line

PARAMETERS :

Create private parameter variables

PARAMETERS <idPrivate list>

PROCEDURE :

Declare a procedure name and formal parameters

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

REQUEST :

Declare a module request list

REQUEST <idModule list>

RETURN :

Terminate a procedure, user-defined function or program

RETURN [<exp>]

Functions :

BREAK() :

Branch out of a BEGIN SEQUENCE…END construct

BREAK(<exp>) --> NIL

EVAL() :

Evaluate a code block

EVAL(<bBlock>, [<BlockArg list>]) --> LastBlockValue

IF() :

Return the result of an expression based on a condition

[I]IF(<lCondition>, <expTrue>, <expFalse>) --> Value

PCOUNT() :

Determine the position of the last actual parameter passed

PCOUNT() --> nLastArgumentPos

SETKEY() :

Assign an action block to a key

SETKEY(<nInkeyCode>, [<bAction>]) --> bCurrentAction

SETCANCEL() :

Toggle Alt-C and Ctrl-Break as program termination keys

SETCANCEL([<lToggle>]) --> lCurrentSetting

WORD()* :

Convert CALL command numeric parameters from double to int

WORD(<nNumber>) --> NIL