DEFINE SUBROUTINE

#### Search Results

Search

# DEFINE SUBROUTINE

`DEFINE` [`SUBROUTINE`] subroutine-name
| statement |
| `END-SUBROUTINE` [ (subroutine-name) ] |
`RETURN`

This document covers the following topics:

- DEFINE SUBROUTINE Usage

- DEFINE SUBROUTINE Syntax Description

- DEFINE SUBROUTINE Restrictions

- DEFINE SUBROUTINE Examples

For an explanation of the symbols used in the syntax diagram, see Syntax Symbols.

Related Statements: `CALL` | `CALL FILE` | `CALL LOOP` | `CALLNAT` | `ESCAPE` | `FETCH` | `PERFORM`

Belongs to Function Group: Invoking Programs and Routines

## DEFINE SUBROUTINE Usage

The `DEFINE SUBROUTINE` statement is used to define a Natural subroutine. A subroutine is invoked with a `PERFORM` statement.

### Inline/External Subroutines

A subroutine may be defined within the object which contains the `PERFORM` statement that invokes the subroutine (inline subroutine); or it may be defined external to the object that contains the `PERFORM` statement (external subroutine). An inline subroutine may be defined before or after the first `PERFORM` statement which references it.

Note
Although the structuring of a program function into multiple external subroutines is recommended for achieving a clear program structure, please note that a subroutine should always contain a larger function block because the invocation of the external subroutine represents an additional overhead as compared with inline code or subroutines.

### Data Available in a Subroutine

#### Inline Subroutines

No explicit parameters can be passed from the invoking program via the `PERFORM` statement to an internal subroutine.

An inline subroutine has access to the currently established global data area as well as to the local data area used by the invoking program.

#### External Subroutines

An external subroutine has access to the currently established global data area. In addition, parameters can be passed directly with the `PERFORM` statement from the invoking object to the external subroutine; thus, you may reduce the size of the global data area.

An external subroutine has no access to the local data area defined in the calling program; however, an external subroutine may have its own local data area.

## DEFINE SUBROUTINE Syntax Description

Syntax Element | Description
--- | ---
`subroutine-name` | Name of Subroutine: For a subroutine name (maximum 32 characters), the same naming conventions apply as for user-defined variables; see Naming Conventions for User-Defined Variables in the Using Natural documentation. The subroutine name is independent of the name of the module in which the subroutine is defined (it may but need not be the same).
`statement` | Statement(s) to be Executed: In place of `statement`, you must supply one or several suitable statements, depending on the situation. For an example of a statement, see Examples below.
`END-SUBROUTINE` `RETURN` | End of DEFINE SUBROUTINE Statement: In structured mode, the subroutine definition is terminated with `END-SUBROUTINE`. In reporting mode, `RETURN` or `END-SUBROUTINE` can be used to terminate a subroutine.
`(subroutine-name)` | End-Subroutine Label: The End-Subroutine label gives you an overview of which `END-SUBROUTINE` belongs to which subroutine. The name of the subroutine must be enclosed in parentheses and positioned only after `END-SUBROUTINE`. The End-Subroutine label must match the subroutine name, otherwise a compiler error occurs.

## DEFINE SUBROUTINE Restrictions

- Any processing loop initiated within a subroutine must be closed before `END-SUBROUTINE` is issued.

- An inline subroutine must not contain another `DEFINE SUBROUTINE` statement (see Example 1 below).

- An external subroutine (that is, an object of type subroutine) must not contain more than one `DEFINE SUBROUTINE` statement block (see Example 2 below). However, an external `DEFINE SUBROUTINE` block may contain further inline subroutines (see Example 1 below).

- You may not use the name of an external subroutine twice in one library.

- The End-Subroutine label must get the same subroutine name as defined with `DEFINE SUBROUTINE`. The End-Subroutine label can only be defined with `END-SUBROUTINE` (see Example 3 below).

#### Example 1

The following construction is possible in an object of type subroutine, but not in any other object (where `SUBR01` would be considered an inline subroutine):

    ...
    DEFINE SUBROUTINE SUBR01
       ...
       PERFORM SUBR02
       PERFORM SUBR03
       ...
       DEFINE SUBROUTINE SUBR02
       /* inline subroutine...
       END-SUBROUTINE
       ...
       DEFINE SUBROUTINE SUBR03
       /* inline subroutine...
       END-SUBROUTINE
    END-SUBROUTINE
    END

#### Example 2 (invalid)

The following construction is not allowed in an object of type subroutine:

    ...
    DEFINE SUBROUTINE SUBR01
    ...
    END-SUBROUTINE
    DEFINE SUBROUTINE SUBR02
    ...
    END-SUBROUTINE
    END

#### Example 3 (invalid)

The following construction is not allowed:

    ...
    DEFINE SUBROUTINE SUBR01
      ...
    END-SUBROUTINE (SUBROUTINE-01)
    ...
    DEFINE SUBROUTINE SUBR02
      ...
    RETURN (SUBR02)
    ...

#### Example 4

The following construction is allowed:

    ...
    DEFINE SUBROUTINE SUBR01
      ...
    END-SUBROUTINE (SUBR01)                  /* subroutine label for SUBR01
    DEFINE SUBROUTINE SUBR02
      ...
    END-SUBROUTINE /* (SUBR02)               /* comment only
    DEFINE SUBROUTINE SUBR03
      ...
    END-SUBROUTINE /* Subroutine SUBR03      /* comment only

## DEFINE SUBROUTINE Examples

- Example 1 - Define Subroutine

- Example 2 - Sample Structure for External Subroutine Using GDA Fields

- Example 3 - Subroutines with End-Subroutine Label

### Example 1 - Define Subroutine

    ** Example 'DSREX1S': DEFINE SUBROUTINE (structured mode)
    ************************************************************************
    DEFINE DATA LOCAL
    1 EMPLOY-VIEW VIEW OF EMPLOYEES
      2 NAME
      2 ADDRESS-LINE  (A20/2)
      2 PHONE
    *
    1 #ARRAY    (A75/1:4)
    1 REDEFINE #ARRAY
      2 #ALINE  (A25/1:4,1:3)
    1 #X        (N2) INIT <1>
    1 #Y        (N2) INIT <1>
    END-DEFINE
    *
    FORMAT PS=20
    LIMIT 5
    FIND EMPLOY-VIEW WITH NAME = 'SMITH'
      MOVE NAME            TO #ALINE (#X,#Y)
      MOVE ADDRESS-LINE(1) TO #ALINE (#X+1,#Y)
      MOVE ADDRESS-LINE(2) TO #ALINE (#X+2,#Y)
      MOVE PHONE           TO #ALINE (#X+3,#Y)
      IF  #Y = 3
        RESET INITIAL #Y
        PERFORM PRINT
      ELSE
        ADD 1 TO #Y
      END-IF
      AT END OF DATA
        PERFORM PRINT
      END-ENDDATA
    END-FIND
    *
    DEFINE SUBROUTINE PRINT
      WRITE NOTITLE (AD=OI) #ARRAY(*)
      RESET #ARRAY(*)
      SKIP 1
    END-SUBROUTINE
    *
    END

#### Output of Program DSREX1S:

    SMITH                    SMITH                    SMITH
    ENGLANDSVEJ 222          3152 SHETLAND ROAD       14100 ESWORTHY RD.
                             MILWAUKEE                MONTERREY
    554349                   877-4563                 994-2260

    SMITH                    SMITH
    5 HAWTHORN               13002 NEW ARDEN COUR
    OAK BROOK                SILVER SPRING
    150-9351                 639-8963

Equivalent reporting-mode example: DSREX1R.

### Example 2 - Sample Structure for External Subroutine Using GDA Fields

    ** Example 'DSREX2': DEFINE SUBROUTINE (using GDA fields)
    ************************************************************************
    DEFINE DATA
    GLOBAL
      USING DSREX2G
    END-DEFINE
    *
    INPUT 'Enter value in GDA field' GDA-FIELD1
    *
    *  Call external subroutine in DSREX2S
    *
    PERFORM DSREX2-SUB
    *
    END

#### Global Data Area DSREX2G Used by Program DSREX2:

    1 GDA-FIELD1                       A    2

#### Subroutine DSREX2S Called by Program DSREX2:

    ** Example 'DSREX2S': SUBROUTINE (external subroutine using global data)
    ************************************************************************
    DEFINE DATA
    GLOBAL
      USING DSREX2G
    END-DEFINE
    *
    DEFINE SUBROUTINE DSREX2-SUB
    *
      WRITE 'IN SUBROUTINE' *PROGRAM '=' GDA-FIELD1
    *
    END-SUBROUTINE
    *
    END

### Example 3 - Subroutines with End-Subroutine Label

    ** Example 'DSREX3': DEFINE SUBROUTINE with end-subroutine label
    ************************************************************************
    DEFINE DATA LOCAL
    1 EMPLOY-VIEW VIEW OF EMPLOYEES
      2 NAME
      2 FIRST-NAME
      2 ADDRESS-LINE  (A20/2)
      2 PERSONNEL-ID
      2 MAR-STAT
      2 BIRTH
    *
    1 #ARRAY          (A75/1:6)
    1 REDEFINE #ARRAY
      2 #ALINE        (A25/1:6,1:3)
    1 #BIRTHDAY       (A25)
    1 #FULL-NAME      (A25)
    1 #MARITAL-STATUS (A25)
    1 #X              (N2) INIT <1>
    1 #Y              (N2) INIT <1>
    END-DEFINE
    *
    FORMAT PS=20
    LIMIT 5
    *
    FIND EMPLOY-VIEW WITH NAME = 'SMITH'
      /*
      PERFORM GET-EMPLOYEES-DATA
      /*
      IF  #Y = 3
        RESET INITIAL #Y
        PERFORM PRINT-ARRAY
      ELSE
        ADD 1 TO #Y
      END-IF
      /*
      AT END OF DATA
        PERFORM PRINT-ARRAY
      END-ENDDATA
    END-FIND
    /*----------------------------------------------------------------------
    /* ------------ End of main program ------------------------------------
    /*----------------------------------------------------------------------
    DEFINE SUBROUTINE GET-EMPLOYEES-DATA
      COMPRESS NAME ',' FIRST-NAME INTO #FULL-NAME LEAVING NO
      MOVE EDITED BIRTH (EM=DD.LLL.YYYY) TO #BIRTHDAY
      /*
      PERFORM MARITAL-STATUS
      /*
      MOVE #FULL-NAME      TO #ALINE (#X,#Y)
      MOVE PERSONNEL-ID    TO #ALINE (#X+1,#Y)
      MOVE #MARITAL-STATUS TO #ALINE (#X+2,#Y)
      MOVE #BIRTHDAY       TO #ALINE (#X+3,#Y)
      MOVE ADDRESS-LINE(1) TO #ALINE (#X+4,#Y)
      MOVE ADDRESS-LINE(2) TO #ALINE (#X+5,#Y)
    END-SUBROUTINE (GET-EMPLOYEES-DATA)         /* end-subroutine label
    *
    DEFINE SUBROUTINE MARITAL-STATUS
      DECIDE ON FIRST VALUE OF MAR-STAT
        VALUE 'M'
          #MARITAL-STATUS := 'MARRIED'
        VALUE 'S'
          #MARITAL-STATUS := 'SINGLE'
        VALUE 'D'
          #MARITAL-STATUS := 'DIVORCED'
        VALUE 'W'
          #MARITAL-STATUS := 'WIDOWED'
        NONE
          RESET #MARITAL-STATUS
      END-DECIDE
    END-SUBROUTINE /* (MARITAL-STATUS)          /* just a comment
    *
    DEFINE SUBROUTINE PRINT-ARRAY
      WRITE NOTITLE (AD=OI) #ARRAY(*)
      RESET #ARRAY(*)
      SKIP 1
    END-SUBROUTINE (PRINT-ARRAY)                /* end-subroutine label
    *
    END

#### Output of Program DSREX3:

    SMITH,GERHARD            SMITH,SEYMOUR            SMITH,MATILDA
    40000311                 20009300                 20014100
    DIVORCED                 SINGLE                   MARRIED
    21.Apr.1976              01.Jan.1970              01.Jan.1970
    ENGLANDSVEJ 222          3152 SHETLAND ROAD       14100 ESWORTHY RD.
                             MILWAUKEE                MONTERREY

    SMITH,ANN                SMITH,TONI
    20015400                 20018800
    WIDOWED                  SINGLE
    07.Nov.1946              14.Dec.1941
    5 HAWTHORN               13002 NEW ARDEN COUR
    OAK BROOK                SILVER SPRING

### On this page

- DEFINE SUBROUTINE Usage
- DEFINE SUBROUTINE Syntax Description
- DEFINE SUBROUTINE Restrictions
- DEFINE SUBROUTINE Examples