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

WITH OBJECT

WITH OBJECT

Identifies an object to receive multiple messages.

Syntax

       WITH OBJECT <object>
          :<message1>
          [<statements>]
          [:<messageN>]
       END

Arguments

WITH OBJECT <object> <object> is the symbolic name of a variable that holds a reference to an object. The object is to receive messages in the WITH OBJECT control structure.

:<message> All expressions that begin with the send operator in the OBJECT WITH block are sent as messages to <object>.

Description

The WITH OBJECT control structure delimits a block of statements where the object variable <object> receives multiple messages in abbreviated form. The name of the object variable can be omitted from a message sending expression, so that only the send operator (:) followed by the message to send must be typed.

WITH OBJECT basically relieves a programmer from typing. The name of the object variable is typed only once at the beginning of the WITH OBJECT block, and all subsequent messages sent to the object start with the send operator, omitting the object’s variable name.

Example

       // The example builds a simple database browser using a TBrowse object.
       // The columns added to the object and the cursor navigation logic is
       // programmed using the WITH OBJECT control structure.
       #include "inkey.ch"
       PROCEDURE Main
          LOCAL oTBrowse, aFields, cField, nKey
          USE Customer
          aFields := Array( FCount() )
          AEval( aFields, {|x,i| aFields[i] := FieldName(i) } )
          oTBrowse := TBrowseDB()
          WITH OBJECT oTBrowse
             FOR EACH cField IN aFields
                :addColumn( TBColumnNew( cField, FieldBlock( cField ) ) )
             NEXT
          END
          nKey := 0
          DO WHILE nKey <> K_ESC
             WITH OBJECT oTBrowse
                DO WHILE .NOT. :stabilize()
                ENDDO
                nKey := Inkey(0)
                SWITCH nKey
                   CASE K_UP
                     :up()       ; EXIT
                   CASE K_DOWN
                     :down()     ; EXIT
                   CASE K_LEFT
                     :left()     ; EXIT
                   CASE K_RIGHT
                     :right()    ; EXIT
                   CASE K_PGUP
                     :pageUp()   ; EXIT
                   CASE K_PGDN
                     :pageDown() ; EXIT
                   CASE K_HOME
                     :home()     ; EXIT
                   CASE K_END
                     :end()      ; EXIT
                END
             END
          ENDDO
          CLOSE Customer
       RETURN

Seealso

CLASS, METHOD

TRY [CATCH]

TRY [CATCH]

Alternate usage of BEGIN SEQUENCE

Syntax

       TRY
             <statements>
          [CATCH [<exp>] ]
             <errorHandling>
          [FINALLY
             <guaranteed> ]
       END      

Description

TRY/CATCH struct is similar to BEGIN/SEQUENCE struct:

         #xcommand TRY => BEGIN SEQUENCE WITH {| oErr | Break( oErr ) }
         #xcommand CATCH [<!oErr!>] => RECOVER [USING <oErr>] <-oErr->
         #xcommand ENDTRY => END

Alternatively TRY [CATCH] [FINALLY] statements are available on xHB library working like the SEQUENCE construct.

Seealso

BEGIN SEQUENCE

SWITCH

SWITCH

Executes one or more blocks of statements.

Syntax

       SWITCH SwitchExp
          CASE LiteralExp1
            ...
            [EXIT]
         [CASE LiteralExp2]
            ...
            [EXIT]
         [CASE LiteralExpn]
            ...
            [EXIT]
         OTHERWISE
                ...
       END [SWITCH]

Arguments

The <LiteralExp> must be a compiled time resolvable numeric or character expression, and may involve operators, as long as such operators involve compile time static value.

CASE <LiteralExp1> .. <LiteralExp> is a constant value of the same data type as <SwitchExp>.

The EXIT optional statement is the equivalent of the C statement break, and if present, execution of the SWITCH structure will end when the EXIT statement is reached, otherwise it will continue with the first statement below the next CASE statement (fall through)

Description

SWITCH is a Harbour construct inspired by the C implementation of switch().

The SWITCH statement compares a constant value against a series of constant values. It is similar to the DO CASE statement but outperforms it to a great extent due to the restrictions introduced with values permitted for comparison. As a general rule, only literal values in form integer or character constants may follow the CASE clauses.

The SWITCH statement evaluates <SwitchExp> and then searches for a first match between the resulting value and <LiteralExp>. When a match is found, the statements following the corresponding CASE clause are executed down to the END statement. To suppress execution of statements of the next CASE clause, the EXIT statement must be explicitely used. This is a major difference to the DO CASE statement where subsequent CASE clauses are skipped once a first match is found.

If no initial match is found with the CASE clauses, the statements following OTHERWISE are executed, if present.

Example

        // The example demonstrates the SWITCH control structure
        // Try with and without EXIT statements
        PROC Main()
           LOCAL cSName := "Doe"
           SWITCH cSName

              CASE "Abba"
                 ? "Abaneoer"
                 EXIT

              CASE "Bo"
                 ? "Boeing"
                 EXIT
              CASE "Doe"
                 ? "John"
                 EXIT

              OTHERWISE
                 ? "Guest"
           END

            ?? '', cSName
           ?
           WAIT "EOF SwitchTest.prg"
        RETU

Seealso

DO CASE, IF…ELSEIF…ENDIF

STATIC

STATIC

Declare and initialize static variables and arrays

Syntax

       STATIC <identifier> [[:= <initializer>], ... ]

Arguments

<identifier> is the name of the variable or array to declare static. 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 is 4096. The maximum number of dimensions is limited only by available memory.

<initializer> is the optional assignment of a value to a new static variable. An <initializer> for a static variable consists of the inline assignment operator (:=) followed by a compile-time constant expression consisting entirely of constants and operators or a literal array. If no explicit <initializer> is specified, the variable is given an initial value of NIL. In the case of an array, each element is NIL. Array identifiers cannot be given values with an <initializer>.

Note: The macro operator (&) cannot be used in a STATIC declaration statement.

Description

The STATIC statement declares variables and arrays that have a lifetime of the entire program but are only visible within the entity that creates them. Static variables are visible only within a procedure or user-defined function if declared after a PROCEDURE or FUNCTION statement. Static variables are visible to all procedures and functions in a program (.prg) file (i.e., have filewide scope) if they are declared before the first procedure or user-defined function definition in the file. Use the /N compiler option to compile a program with filewide variable scoping.

All static variables in a program are created when the program is first invoked, and all values specified in a static <initializer> are assigned to the variable before the beginning of program execution.

Declarations of static variables within a procedure or user-defined function must occur before any executable statement including PRIVATE, PUBLIC, and PARAMETERS. If a variable of the same name is declared FIELD, LOCAL, or MEMVAR within the body of a procedure or user-defined function, a compiler error occurs and no object (.OBJ) file is generated.

The maximum number of static variables in a program is limited only by available memory.

Notes

. Inspecting static variables within the Debugger: To access static variable names within the Harbour debugger, you must compile program (.prg) files using the /B option so that static variable information is included in the object (.OBJ) file.

. Macro expressions: You may not refer to static variables within macro expressions or variables. If a static variable is referred to within a macro expression or variable, a private or public variable of the same name will be accessed instead. If no such variable exists, a runtime error will be generated.

. Memory files: Static variables cannot be SAVED to or RESTOREd from memory (.mem) files.

. Type of a static local variable: Since TYPE() uses the macro operator (&) to evaluate its argument, you cannot use TYPE() to determine the type of a local or static variable or an expression containing a local or static variable reference. The VALTYPE() function provides this facility by evaluating the function argument and returning the data type of its return value.

Examples

       .  This example declares static variables both with and without
          initializers:
          STATIC aArray1[20, 10], aArray2[20][10]
          STATIC cVar, cVar2
          STATIC cString := "my string", var
          STATIC aArray := {1, 2, 3}
       .  This example manipulates a static variable within a user-
          defined function.  In this example, a count variable increments
          itself each time the function is called:
          FUNCTION MyCounter( nNewValue )
             STATIC nCounter := 0         // Initial value assigned once
             IF nNewValue != NIL
                nCounter:= nNewValue      // New value for nCounter
             ELSE
                nCounter++                // Increment nCounter
             ENDIF
             RETURN nCounter
       .  This example demonstrates a static variable declaration that
          has filewide scope.  In this code fragment, aArray is visible to both
          procedures that follow the declaration:
          STATIC aArray := {1, 2, 3, 4}
          FUNCTION One
             ? aArray[1]                  // Result: 1
             RETURN NIL
          FUNCTION Two
             ? aArray[3]                  // Result: 3
             RETURN NIL

Seealso

FUNCTION, LOCAL, PARAMETERS, PRIVATE, PROCEDURE, PUBLIC

RUN

RUN

Executes an operating system command.

Syntax

       RUN <CommandLine>

Arguments

<CommandLine> This is the command to be executed on the operating system level. It can be specified as literal or as character string in parentheses.

Description

The RUN command opens a new command shell and executes the operating system commands specified with <CommandLine>.

RUN does not return until <CommandLine> is completed by the operating system. When RUN is complete, the new command shell is closed.

Example

       // The example executes the DIR command, directs its output into
       // a file and displays the result with Notepad.exe
       PROCEDURE Main
          LOCAL cCommand := "Notepad.exe files.lst"

          CLS

          ? "DIR command"
          RUN dir > files.lst

          ? "Executing Notepad.exe"
          RUN (cCommand)

          ? "Done"
       RETURN

Seealso

( ), FUNCTION, PROCEDURE

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: Harbour 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

Seealso

BEGIN SEQUENCE, FUNCTION, LOCAL, PRIVATE, PROCEDURE