Neben Kommandos können Prozedurzeilen ebenso Daten und Anweisungen enthalten. Daten können in S-Prozeduren auch mit dem Kommando SEND-DATA übergeben werden und Anweisungen mit dem Kommando SEND-STMT.
Dieser Abschnitt behandelt folgende Themen:
Daten einlesen
Dateiende-Bedingung erzeugen
Daten-, Anweisungs- und Kommandozeilen mischen
Daten einlesen
Es gibt verschiedene Wege, über die einem Programm Datenzeilen übermittelt werden: So kann im Programm eine Datei eröffnet werden, die die Datenzeilen enthält, oder es können Daten von SYSDTA gelesen werden.
Damit im Programm eine Eingabedatei geöffnet und Datenzeilen gelesen werden können, muss dem Programm diese Datei zugeordnet werden. Dies verläuft in Prozeduren genauso wie auf Systemebene. Detaillierte Beschreibungen dazu enthält das Handbuch „Einführung in das DVS“ [1].
Der Standard-Eingabeweg für Daten ist SYSDTA. SYSDTA gehört wie die Systemdateien SYSCMD, SYSLST und SYSOUT zur SYSFILE-Umgebung. SYSDTA ist eine logische Datei (Systemdatei) und bezeichnet den Weg, über den Daten vom System an ein Programm weitergereicht werden.
In S-Prozeduren ist (im Gegensatz zu Nicht-S-Prozeduren) die Standardeinstellung, dass SYSDTA SYSCMD zugewiesen wird. SYSDTA kann zum Beispiel mit dem Kommando ASSIGN-SYSDTA einer Datei zugewiesen werden, aus der das Programm dann der Reihe nach die Datensätze lesen kann (zu ASSIGN-SYSDTA: siehe Handbuch „Kommandos“ [3]).
Wird SYSDTA in einer Prozedur einer Datei zugewiesen, ergeben sich keine Unterschiede gegenüber einer Dateizuweisung auf Systemebene. Datensätze können aber auch direkt in die Prozedur geschrieben werden.
Wird SYSDTA mit dem Kommando ASSIGN-SYSDTA TO-FILE=*SYSCMD „umgelenkt“, liest das Programm die Datenzeilen aus der Prozedur.
In S-Prozeduren können Datenzeilen mit dem Kommando SEND-DATA an das geladene Programm übergeben werden. Dabei enthält jeder Kommandoaufruf einen Datensatz oder einen Ausdruck, der ausgewertet den Datensatz ergibt.
Daten können auch ohne den Kommandoaufruf SEND-DATA in eigene Datenzeilen geschrieben werden, dann enthält eine Prozedurzeile genau einen Eingabe-Datensatz. Dabei muss allerdings beachtet werden, wie die Dateiende-Bedingung erzeugt wird (Dateiende-Bedingung: siehe Abschnitt "Daten und Anweisungen"). Falls die Datensätze einen ISAM-Schlüssel enthalten, wird dieser ignoriert.
Daten über das Kommando SEND-DATA einzugeben, bietet jedoch einige Vorteile:
Die Prozedurzeile, die den Datensatz „enthält“, kann mit einer Marke eingeleitet werden.
Die Prozedurzeile mit dem Datensatz kann einen Kommentar enthalten.
Der Datensatz kann sich über mehrere Fortsetzungszeilen erstrecken.
Daten und Dateiende-Bedingung werden über eine einheitliche Oberfläche erzeugt (siehe Abschnitt „Dateiende-Bedingung erzeugen“).
Beispiel
/ABC = 'Text' /DEF = 'verarbeitung' /START-EXE PROGRAM1 "Programm PROGRAM1 laden" /SEND-DATA ABC "Eingabe: Text" /SEND-DATA 'EINGABE' "Eingabe: EINGABE" /SEND-DATA 'Dies ist ein ganz langer Eingabe'- /'satz, der auf jeden Fall mehr als 72 Zei'- /'chen lang sein soll' /SEND-DATA ABC // DEF "Eingabe: Textverarbeitung" /SEND-DATA ...
In diesem Beispiel werden nacheinander verschiedene Datensätze eingelesen. Der vierte Aufruf von SEND-DATA enthält als Argument einen Ausdruck, der ausgewertet die Eingabe „Textverarbeitung“ ergibt.
SEND-DATA kann auch innerhalb einer Schleife aufgerufen werden, in der Eingabe-Datensätze nacheinander erzeugt werden.
Beispiel
/SET-VARIABLE A = 'Text' /SET-VARIABLE B = 'verarbeitung' /SET-VARIABLE C = A // B /BEGIN-BLOCK PROGRAM-INPUT=*MIXED-WITH-CMD /START-EXE PROGRAM1 "Programm PROGRAM1 laden" /FOR EINGABE = (A,B,C) "FOR-Schleife, in der der" / "FOR-Schleife, in der der" / "die Inhalte der Variablen A, B, C / zugewiesen werden" /SEND-DATA EINGABE /END-FOR /END-BLOCK
Man kann Eingabe-Datensätze auch direkt in die Prozedurzeile schreiben, ohne den Kommandoaufruf /SEND-DATA zu benutzen.
Beispiel
/SET-PROCEDURE-OPTIONS DATA-ESCAPE-CHAR = *STD /VAR1 = 'Text' /VAR2 = 'verarbeitung' /START-EXE PROGRAM1 "Programm PROGRAM1 laden" &VAR1 'EINGABE' &(VAR1 // VAR2) ...
Als Datenzeilen werden nacheinander übergeben:
Text 'EINGABE' Textverarbeitung
Daten-, Kommando- und Anweisungszeilen mischen
Für die Weitergabe von Kommandos und Datenzeilen bietet SDF-P das Kommando SEND-DATA. Dabei können Kommandos und Datenzeilen beliebig gemischt werden.
Für die Weitergabe von Anweisungen an ein Programm bietet SDF-P ein eigenes Kommando: SEND-STMT. Die Anweisung wird dabei direkt als Operandenwert im Kommandoaufruf übergeben oder als Ausdruck, der ausgewertet die Anweisung ergibt.
Daten-, Anweisungs- und Kommandozeilen zu mischen, kann auch im Kommando BEGIN-BLOCK mit der Operandeneinstellung PROGRAM-INPUT=*MIXED-WITH-CMD vereinbart werden. Diese Einstellung gilt dabei für den aktuellen Kommandoblock und für alle in diesen Block geschachtelten Blöcke; sie kann in einem untergeordneten Block nicht ausgeschaltet werden.
PROGRAM-INPUT=*MIXED-WITH-CMD bewirkt, dass Daten-, Anweisungs- und Kommandozeilen vom System „gleichartig“ behandelt werden. Das heißt, die Kommandozeile löst keine Dateiende-Bedingung aus. Stattdessen unterbricht das System das Programm:
Es hebt die „Empfangsbereitschaft“ des Programms auf, was einer Programm-Unterbrechung mit /HOLD-PROGRAM entspricht.
Das System führt die Kommandos aus, bis wieder eine Daten- oder Anweisungszeile eingelesen wird.
Es stellt die „Empfangsbereitschaft“ des Programms wieder her, was einer Fortsetzung des Programms mit /RESUME-PROGRAM entspricht.
Anschließend werden Daten- oder Anweisungszeilen an das Programm weitergereicht, bis wieder ein Kommando eingelesen wird oder explizit die Dateiende-Bedingung erzeugt wird (zum Beispiel mit /SEND-DATA *EOF).
Beispiel
/BEGIN-BLOCK PROGRAM-INPUT=*MIXED-WITH-CMD / "Daten- und Kommandozeilen mischbar" /START-EXE PROGRAM1 "PROGRAM1 starten" /FOR V = *LIST(L) "FOR-Schleife, Laufvariable: V wird an" / "PROGRAM1 weitergegeben" &V /END-FOR /END-BLOCK
In diesem Beispiel wird das Programm PROGRAM1 gestartet. Sobald von SYSDTA Daten angefordert werden, wird das Programm unterbrochen; die folgenden Kommandos (BEGIN-BLOCK und FOR) werden ausgeführt.
In der FOR-Schleife wird der Variablen V zunächst der Inhalt des ersten Elements der Liste L zugewiesen.
Die folgende Zeile (&V) ist eine Datenzeile: Das Programm wird fortgesetzt, die Datenzeile, also der Inhalt der Variablen V, an das Programm übergeben.
Sobald wieder Daten von SYSDTA angefordert werden, wird das Programm erneut unterbrochen und die folgenden Kommandos ausgeführt: END-FOR und FOR. Wenn die Listenvariable L noch mehr Elemente enthält, wird die Schleife fortgesetzt und der Variablen V der Inhalt des nächsten Elements zugewiesen. Die Dateneingabe wird beendet, wenn die Listenvariable L „abgearbeitet“ ist und die FOR-Schleife beendet wird.
Mit END-BLOCK wird die Einstellung PROGRAM-INPUT=*MIXED-WITH-CMD aufgehoben, sodass das folgende Kommando die Dateiende-Bedingung erzeugt.
Wenn Daten-, Anweisungs- und Kommandozeilen gemischt werden können, trifft dies auch auf den Aufruf geschachtelter Prozeduren mit CALL-PROCEDURE oder INCLUDE-PROCEDURE zu: Das Programm wird unterbrochen und die aufgerufene Prozedur zunächst im Kommandomodus bearbeitet. Bevor wieder Daten an das anfordernde Programm weitergereicht werden, muss das Kommando RESUME-PROGRAM aufgerufen werden (die „Empfangsbereitschaft“ wird wiederhergestellt). Es darf allerdings kein implizites RESUME-PROGRAM verwendet werden.
Datenprozeduren müssen demnach mit dem Kommando RESUME-PROGRAM beginnen. (Außerdem gilt: S-Prozeduren müssen mit einem Schrägstrich beginnen!)
Mit dem Kommando HOLD-PROGRAM kann die Dateneingabe wieder unterbrochen werden, sodass ein explizites oder implizites EXIT-PROCEDURE ausgeführt werden kann.
Beispiel
BEGIN-BLOCK PROGRAM-INPUT=*MIXED-WITH-CMD /START-EXE PROGRAM2 /CALL-PROCEDURE DATA.PROC "Aufruf einer Datenprozedur" -----> /RESUME-PROGRAM "Programm empfangsbereit" eingabe-1 eingabe-2 .. /HOLD-PROGRAM "Programm unterbrochen" /EXIT-PROCEDURE <---/... "Fortsetzung übergeordnete Prozedur"
Wenn die Datenprozedur nicht mit HOLD-PROGRAM beendet wird, wird nach dem Lesen der letzten Prozedurzeile die Dateiende-Bedingung erzeugt.
In der Datenprozedur gilt nicht das in der aufrufenden Prozedur gesetzte PROGRAM-INPUT=*MIXED-WITH-CMD. Der Kommandoaufruf /HOLD-PROGRAM erzeugt jedoch noch keine Dateiende-Bedingung. Die Kommandos der Prozedur werden ausgeführt, die Prozedur also beendet (implizit, wenn EXIT-PROCEDURE fehlt). In der aufrufenden Prozedur ist die Dateiende-Bedingung jedoch aufgehoben. Das Programm läuft also nach dem untergeschobenen RESUME-PROGRAM weiter.
Tritt bei der Ausführung eines Kommandos ein Fehler auf, wird im Kommandomodus zum nächsten Fehlerbehandlungsblock (IF-BLOCK-ERROR) verzweigt.
Einschränkungen
Nicht mit Daten gemischt werden, dürfen die Kommandos des Testhilfe-Dienstprogramms AID. Ein Mischen von Datenzeilen mit diesen Kommandos kann zu einem unerwarteten Verhalten des Programms führen, da nach jedem Kommando das Programm fortgesetzt wird (siehe Handbuch „AID (BS2000)“ [6]).
Der Fehlerstatus von Anweisungen wird nicht immer auf Kommandoebene übertragen.
So können Fehler auf Anweisungsebene nicht immer bis zum Programmende durch einen IF-BLOCK-ERROR-Block auf Kommandoebene verarbeitet werden.
Bei den Einstellungen BEGIN-BLOCK PROGRAM-INPUT=*STD / *MIXED-WITH-CMD passiert im Einzelnen Folgendes:
Bei PROGRAM-INPUT=*STD verursacht die Eingabe eines Kommandos (nicht HOLD-PROGRAM) eine Dateiende-Bedingung für Anweisungs-Eingaben und bestimmten Programmreaktionen (z.B. bei TERM mit Fehler). Mögliche Fehler werden auf Kommandoebene bei Programmbeendigung übertragen. D.h. sie können ab diesem Zeitpunkt mit IF-BLOCK-ERROR weiter verarbeitet werden.
Beispiel
/BEGIN-BLOCK PROGRAM-INPUT=*STD /START-EXE MY-UTILITY "WENN EOF BEI RDSTMT: ABBRUCH" //... "FEHLER" /IF-BLOCK-ERROR; WRITE-TEXT 'FEHLER WEGEN EOF'; END-IF /... "FEHLERVERARBEITUNG" /END-BLOCK
- Die Operandeneinstellung PROGRAM-INPUT=*MIXED-WITH-CMD(PROPAGATE-STMT-RC=*STD) unterbricht Kommandoeingaben während Programmanweisungen (und mögliche Fehler) eingegeben werden. Es wird aber kein Fehler auf Kommandoebene übertragen. IF-BLOCK-ERROR verarbeitet in diesem Fall den Fehler auf Anweisungsebene nicht. Der Fehler kann aber durch die vordefinierte Funktion STMT-SPINOFF( ) abgefragt werden: D.h. an Stelle von IF-BLOCK-ERROR muss IF-STMT-SPINOFF( ) angegeben werden.
Beispiel
/BEGIN-BLOCK PROGRAM-INPUT=*MIXED-WITH-CMD /START-EXE MY-UTILITY "WENN EOF BEI RDSTMT: ABBRUCH" //... "FEHLER" /IF-BLOCK-ERROR; WRITE-TEXT 'ES WIRD KEIN TEXT GESCHRIEBEN'; END-IF /... "KEINE FEHLERVERARBEITUNG AUF KOMMANDOEBENE" /END-BLOCK / "ES WIRD JETZT EOF GEMELDET, DA KEINE DATENEINGABE MEHR ERFOLGT." / "PROGRAM BRICHT AB." / "EIN FEHLER WIRD NACH BLOCKENDE ZUR KOMMANDOEBENE UEBERTRAGEN"
Die Operandeneinstellung PROGRAM-INPUT=*MIXED-WITH-CMD(PROPAGATE-STMT-RC=*TO-CMD-RC) unterbricht Kommandoeingaben während Programmanweisungen (und mögliche Fehler) eingegeben werden. Returncodes von Programmanweisungen werden auf die Kommandoebene übertragen. Damit können auf Anweisungsebene aufgetretene Fehler mit dem Kommando IF-BLOCK-ERROR und den vordefinierten Funktionen SUBCODE1( ), SUBCODE2( ) und MAINCODE( ) behandelt werden.
Beispiel
/BEGIN-BLOCK PROGRAM-INPUT=*MIXED-WITH-CMD - /(PROPAGATE-STMT-RC=*TO-CMD-RC) /START-LMS //... "FEHLER AUF ANWEISUNGSEBENE" //... /IF-BLOCK-ERROR /... "FEHLERBEHANDLUNG AUF KOMMANDOEBENE" /END-IF //END /END-BLOCK
Dateiende-Bedingung erzeugen
Ob das System die Dateiende-Bedingung erzeugt oder ein Kommando ausführt, hängt davon ab, wie der Operand PROGRAM-INPUT im BEGIN-BLOCK-Kommando eingestellt ist. Bei der Standardeinstellung BEGIN-BLOCK PROGRAM-INPUT=*STD wird die Dateiende-Bedingung erzeugt, wenn im Datenstrom ein Kommando aufgerufen wird. Das heißt, Daten- und Kommandozeilen können hier - außer man gibt SEND-DATA an - nicht gemischt werden.
Beispiel
/PROG: BEGIN-BLOCK /ABC = 'Text' /DEF = 'verarbeitung' /START-EXE PROGRAM1 "Programm PROGRAM1 laden" &ABC EINGABE &(ABC // DEF) ... /WRITE-TEXT ... /END-BLOCK PROG
In diesem Beispiel beendet das Kommando WRITE-TEXT die Dateneingabe: Das System erkennt am einleitenden Schrägstrich, dass es sich um eine Kommandozeile handelt und erzeugt die Dateiende-Bedingung. Nach Beendigung des Programms wird das Kommando ausgeführt.
Werden bei der Standardeinstellung von BEGIN-BLOCK Daten mit dem Kommando SEND-DATA an das Programm übergeben, muss - um die Dateiende-Bedingung zu erzeugen - im letzten SEND-DATA-Kommando der Operand RECORD = *EOF angegeben werden.
Beispiel
/PROG: BEGIN-BLOCK /VAR1 = 'Text' /VAR2 = 'verarbeitung' /START-EXE PROGRAM1 "Programm PROGRAM1 laden" /SEND-DATA VAR1 "Eingabe: Text" /SEND-DATA 'EINGABE' "Eingabe: EINGABE" /SEND-DATA VAR1 // VAR2 "Eingabe: Textverarbeitung" /SEND-DATA RECORD=*EOF "Eingabe-Ende: EOF"
Das Programm kann nacheinander die Datensätze einlesen.
Beispiel
/PROG: BEGIN-BLOCK /SET-VARIABLE A = 'Text' /SET-VARIABLE B = 'verarbeitung' /SET-VARIABLE C = A // B /BEGIN-BLOCK DATA-INSERT = *YES /START-EXE PROGRAM1 "Programm PROGRAM1 laden" /FOR EINGABE = (A,B,C) "FOR-Schleife, in der der" / "Laufvariablen EINGABE nacheinander" / "die Inhalte der Variablen A, B und C" /SEND-DATA EINGABE "zugewiesen werden" /END-FOR /SEND-DATA *EOF "Eingabe-Ende: EOF" /END-BLOCK
Bei der Einstellung BEGIN-BLOCK PROGRAM-INPUT=*MIXED-WITH-CMD können - wie im vorhergegangen Abschnitt beschrieben wurde - Daten- und Kommandozeilen ohne zusätzliche Angabe eines SEND-DATA-Kommandos gemischt werden. Allerdings muss auch hier zur Erzeugung der Dateiendebedingung SEND-DATA=*EOF angegeben werden.
Beispiel
Zwei Kommandoblöcke werden ineinander geschachtelt. Im übergeordneten Block ist PROGRAM-INPUT=*MIXED-WITH-CMD eingestellt, was sich auch auf den untergeordneten Block auswirkt.
/BEGIN-BLOCK PROGRAM-INPUT=*MIXED-WITH-CMD /... /COMP: BEGIN-BLOCK /START-EXE $RZ.FOR1 PROGRAM STATIST ... END /SEND-DATA *EOF /START-EXE $BINDER ... /END-BLOCK COMP ... /END-BLOCK
Im untergeordneten Block liest der Fortran-Compiler FOR1 ein Fortran-Programm zeilenweise ein, bis das System einen Kommandoaufruf erkennt.
Das Programm wird unterbrochen und das Kommando ausgeführt: Es wird die Dateiende-Bedingung erzeugt und dadurch im Compiler die Dateiende-Behandlung angestoßen; das Fortran-Programm wird übersetzt.
Anschließend wird der statische Binder BINDER aufgerufen: Der Compiler FOR1 wird entladen und BINDER geladen und gestartet. Es folgen Anweisungen an den BINDER.
Würde in diesem Beispiel der Kommandoaufruf /SEND-DATA *EOF entfallen, ergäbe sich folgender Verlauf:
Die Dateneingabe wird durch das erste Kommando unterbrochen, ohne dass eine EOF-Bedingung den Compiler startet, da hier PROGRAM-INPUT=*MIXED-WITH-CMD angegeben wurde.
Dieses Kommando (START-EXE $BINDER) wird ausgeführt, das heißt, der Compiler FOR1 wird entladen (ohne, dass vorher ein Compilations-Ergebnis geschrieben wird) und das Programm BINDER geladen.
Da keine Dateiende-Bedingung erzeugt wurde, wurde das Programm nicht übersetzt. BINDER kann also nicht auf ein neu übersetztes Programm zugreifen.