DEFINE SUBROUTINE

DEFINE [SUBROUTINE] subroutine-name
  statement  

END-SUBROUTINE [ (subroutine-name) ]

RETURN (nur im Reporting Mode)

Dieses Dokument behandelt folgende Themen:

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

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

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