DEFINE SUBROUTINE

#### Search Results

Search

# DEFINE SUBROUTINE

`DEFINE` [`SUBROUTINE`] subroutine-name
| statement |
| `END-SUBROUTINE` [ (subroutine-name) ] |
`RETURN` (nur im Reporting Mode)

Dieses Dokument behandelt folgende Themen:

- Funktion DEFINE SUBROUTINE

- Syntax-Beschreibung DEFINE SUBROUTINE

- Einschränkungen DEFINE SUBROUTINE

- Beispiele DEFINE SUBROUTINE

Eine Erläuterung der in dem Syntax-Diagramm verwendeten Symbole entnehmen Sie dem Abschnitt Syntax-Symbole.

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

Gehört zur Funktionsgruppe: Aufrufen von Programmen und Subprogrammen

## Funktion DEFINE SUBROUTINE

Das Statement `DEFINE SUBROUTINE` dient dazu, eine Natural-Subroutine zu definieren. Aufgerufen wird eine Subroutine mit einem `PERFORM`-Statement.

### Interne und externe Subroutinen

Eine Subroutine kann entweder innerhalb des Natural-Objekts definiert werden, das das sie aufrufende `PERFORM`-Statement enthält (interne Subroutine), oder sie kann in einem anderen Natural-Objekt definiert werden als dem, welches das aufrufende `PERFORM`-Statement enthält (externe Subroutine). Eine interne Subroutine kann entweder vor oder nach dem ersten `PERFORM`-Statement, mit dem sie aufgerufen wird, definiert werden.

Anmerkung
Die Verwendung externer Subroutinen empfiehlt sich zwar, um eine klar gegliederte Anwendungsstruktur zu erhalten, allerdings verursachen externe Subroutinen einen Verarbeitungsmehraufwand. Daher sollten nur größere funktionale Blöcke in externen Subroutinen untergebracht werden.

### Daten, die einer Subroutine zur Verfügung stehen

- Interne Subroutinen
- Externe Subroutinen

#### Interne Subroutinen

An eine interne Subroutine können mit dem `PERFORM`-Statement keine Parameter vom aufrufenden Programm übergeben werden.

Eine interne Subroutine kann auf auf den aktuell eingerichteten globalen Datenbereich (Global Data Area) sowie den vom aufrufenden Programm verwendeten lokalen Datenbereich (Local Data Area) zugreifen.

#### Externe Subroutinen

Eine externe Subroutine hat Zugriff auf den aktuell eingerichteten globalen Datenbereich (Global Data Area). Außerdem können Parameter direkt mit dem `PERFORM`-Statement vom aufrufenden Objekt an die externe Subroutine übergeben werden. Dadurch kann die Größe des globalen Datenbereichs gering gehalten werden.

Eine externe Subroutine kann nicht auf den im aufrufenden Programm definierten lokalen Datenbereich (Local Data Area), allerdings kann eine externe Subroutine einen eigenen lokalen Datenbereich haben.

## Syntax-Beschreibung DEFINE SUBROUTINE

Syntax-Element-Beschreibung:

Syntax-Element | Beschreibung
--- | ---
`subroutine-name` | Name der Subroutine: Für den Namen einer Subroutine (maximal 32 Zeichen lang) gelten die gleichen Namenskonventionen wie für Benutzervariablen. Siehe Namenskonventionen für Benutzervariablen in der Dokumentation Natural benutzen. Der Name einer Subroutine ist unabhängig vom Namen des Moduls, in dem sie definiert ist (beide Namen können, müssen aber nicht, gleich sein).
`END-SUBROUTINE` | Ende des DEFINE SUBROUTINE-Statements: Im Structured Mode muss die Definition einer Subroutine mit dem Schlüsselwort `END-SUBROUTINE` beendet werden. Im Reporting Mode kann die Definition einer Subroutine mit dem Schlüsselwort `RETURN` oder mit `END-SUBROUTINE` beendet werden.
`RETURN` oder `END-SUBROUTINE`
`(subroutine-name)` | End-Subroutine-Label: Das End-Subroutine-Label verschafft Ihnen einen Überblick, welches `END-SUBROUTINE`-Schlüsselwort zu welcher Subroutine gehört. Der Name der Subroutine muss in Klammern gesetzt werden und darf erst nach dem `END-SUBROUTINE`-Schlüsselwort stehen. Das End-Subroutine-Label muss mit dem Namen der Subroutine übereinstimmen, sonst gibt es einen Compilerfehler.

## Einschränkungen DEFINE SUBROUTINE

- Eine in einer Subroutine initiierte Verarbeitungsschleife muss vor dem `END-SUBROUTINE`-Statement wieder geschlossen werden.

- Eine interne Subroutine darf ihrerseits kein weiteres `DEFINE SUBROUTINE`-Statement enthalten (siehe Beispiel 1 unten).

- Eine externe Subroutine (d.h. ein Objekt vom Typ Subroutine) darf nicht mehr als einen `DEFINE SUBROUTINE`-Statement-Block enthalten (siehe Beispiel 2 unten). Ein externer `DEFINE SUBROUTINE`-Block darf jedoch seinerseits interne Subroutinen enthalten (siehe Beispiel 1 unten).

- Der Name einer externen Subroutine darf in einer Bibliothek nur einmal verwendet werden.

- Das End-Subroutine-Label muss denselben Subroutinen-Namen erhalten, der mit `DEFINE SUBROUTINE` definiert wurde. Das End-Subroutine-Label kann nur mit `END-SUBROUTINE` definiert werden (siehe Beispiel 3 unten).

#### Beispiel 1

Die folgende Konstruktion ist in einem Objekt vom Typ Subroutine möglich, aber nicht in einem anderen Objekt (in dem `SUBR01` als interne Subroutine gälte):

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

#### Beispiel 2 (ungültig):

Die folgende Konstruktion ist in einem Objekt vom Typ Subroutine nicht erlaubt:

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

#### Beispiel 3 (ungültig):

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

#### Beispiel 4:

    ...
    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

## Beispiele DEFINE SUBROUTINE

- Beispiel 1 — Subroutine definieren

- Beispiel 2 — Beispiel-Struktur für externe Subroutine mittels GDA-Feldern

- Beispiel 3 — Subroutinen mit End-Subroutine-Label

### Beispiel 1 — Subroutine definieren

    ** 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

Ausgabe des Programms `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

Äquivalentes Reporting-Mode-Beispiel: `DSREX1R`.

### Beispiel 2 — Beispiel-Struktur für externe Subroutine mittels GDA-Feldern

    ** 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

Vom Programm `DSREX2` benutzte Global Data Area `DSREX2G`:

    1 GDA-FIELD1                       A    2

Vom Programm `DSREX2` aufgerufene Subroutine `DSREX2S`:

    ** 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

### Beispiel 3 — Subroutinen mit 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

#### Ausgabe des Programms 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

- Funktion DEFINE SUBROUTINE
- Syntax-Beschreibung DEFINE SUBROUTINE
- Einschränkungen DEFINE SUBROUTINE
- Beispiele DEFINE SUBROUTINE