Nur noch kurze Frist für Einspruch bei den Normungsgremien von ANSI, ISO und DIN (Teil 3 und Schluß)

Radikalkur: Fortran soll grundlegend geändert werden

15.01.1988

*Karl-Heinz Rotthäuser ist Mitarbeiter der Gesellschaft für Mathematik und Datenverarbeitung (GMD), Sankt Augustin, und Leiter des Arbeitskreises "Fortran" beim DIN.

Die genormte Programmiersprache Fortran macht zur Zeit die radikalste und weitreichendste Veränderung ihrer Existenz durch. Fortran-Experten aller Länder, insbesondere die Mitglieder der Arbeitsgruppe X3J3 des American National Standards Institute (ANSI) und der Working Group 5 der International Standardization Organisation (ISO), haben einen neuen Normentwurf erarbeitet, der unter dem Arbeitstitel "Fortran 8x" nun zur Kommentierung veröffentlicht wird.

Attribute formaler Parameter

Bei formalen Parametern kann mit dem INTENT-Attribut die beabsichtigte Benutzung angegeben werden, und zwar IN, OUT oder INOUT. INTENT(IN) weist einen formalen Parameter als Eingabeparameter aus. INTENT(OUT) weist einen formalen Parameter als Ausgabeparameter aus. Mit INTENT (INOUT) spezifizierte Parameter können sowohl als Eingabe- als auch als Ausgabeparameter verwendet werden.

Beispiel:

SUBROUTINE TRANSFER (VON, NACH)

REAL, INTENT (IN):: VON

REAL, INTENT (OUT):: NACH

...

Darüber hinaus können formale Parameter mit dem Attribut OPTIONAL spezifiziert werden. Für solche Parameter braucht beim Aufruf kein aktuelles Argument angegeben werden.

Prozeduraufruf mit Schlüsselwörtern

Beim Prozeduraufruf dürfen die Namen der formalen Parameter wiederholt werden, zum Beispiel:

CALL ASSIGN ZEICHENKETTE(STR = STRING 1, CHAR= 'Anton' ) Vorteil dieser Schreibweise: Die aktuellen Parameter brauchen nicht in der Reihenfolge der formalen Parameter aufgeführt werden und optionale Parameter können einfach weggelassen werden.

Modulkonzept

Als neue nichtausführbare Programmeinheit wurde das Modul eingeführt. Er enthält Definitionen, Deklarationen und Spezifikationen, die in allen Programmeinheiten verwendet werden können. Sie umfassen Vereinbarungen für globale Datenobjekte, Typdeklarationen, Prozedurdefinitionen und Prozedur-Interface-Blöcke. Der Zweck eines Moduls ist die Aufnahme von Vereinbarungen, auf die dadurch von allen anderen Programmeinheiten eines ausführbaren Programmes zugegriffen werden kann. Darüber hinaus darf auch von anderen Programmeinheiten auf die Vereinbarungen, die in einem Modul enthalten sind, zugegriffen werden.

Damit ersetzt das Modul auch die Funktionalität von COMMON und BLOCK DATA, ohne die Speicherabbildung in Betracht zu ziehen. Module werden einmal definiert und können dann mit der USE-Anweisung angesprochen werden.

Beispiel:

MODULE DATEN

INTEGER, ARRAY (100):: I

REAL, ARRAY (10, 10)::R

CHARACTER (LEN = 1 0 0) TEXT

END MODULE DATEN

SUBROUTINE AUFRUF

USE DATEN, ONLY: R

...

X = R(J, K)

...

END SUBROUTINE AUFRUF

In diesem Beispiel werden drei unterschiedliche Datentypen in dem Modul DATEN definiert. In dem Unterprogramm AUFRUF wird mit der USE-Anweisung auf dieses Modul Bezug genommen; die im Modul definierten Variablen können damit benutzt werden, soweit ihre Benutzung nicht eingeschränkt wurde. Da in dem obigen Beispiel das Unterprogramm AUFRUF nur auf die Matrix R zugreifen will, wurde die Zugriffsmöglichkeit von vornherein durch den Zusatz ONLY auf diese Variable beschränkt.

Neue Steuerkonstrukte

Das CASE-Konstrukt

Beispiel (ganzzahlige Funktion Signum):

INTEGER FUNCTION SIGNUM (N)

SELECT CASE (N)

CASE (:- 1)

SIGNUM = -1

CASE (0)

SIGNUM = 0

CASE ( 1:)

SIGNUM = 1

END SELECT

END FUNCTION SIGNUM

Bei der Ausführung der SELECT CASE-Anweisung wird der Ausdruck in Klammern (hier: N) berechnet. Das Ergebnis ist der CASE-Index, der mit einem der Selektoren einer CASE-Anweisung übereinstimmen muß. Für den Fall einer Bereichsangabe a:b muß der CASE-Index in diesem Bereich liegen: a <= CASE-Index <= b.

Für a : gilt a <= CASE-Index, für : b gilt CASE-Index <= b. Wenn kein Selektor mit dem CASE-Index übereinstimmt, muß der Selektor DEFAULT angegeben sein, der dann für diesen Wert zuständig ist.

DO-Konstrukte

Beispiel für Laufanweisung:

SCHLEIFE : DO 100, I = 1 r 10, 1 oder

SCHLEIFE: DO 200 ( 10) TIMES

SCHLEIFE ist ein frei wählbarer Name für eine DO-Schleife, der auch wegfallen kann. Wenn die Laufanweisung einen Namen besitzt, muß das DO-Konstrukt mit einer END DO-Anweisung abgeschlossen werden, die denselben Namen besitzt. Im zweiten Beispiel wird die Schleife zehnmal durchlaufen.

Beispiel:

N = 0

SCHLEIFE: DO 100, I = 1, 10, 1

N = N + 1

100 END DO SCHLEIFE

Schleifenname, Marke(Label) und Schleifensteuerung können entfallen. Um in einem solchen Fall die Schleife abzubrechen, stehen zwei weitere Anweisungen zur Verfügung: EXIT Schleifenname und CYCLE Schleifenname.

Der Schleifenname (im Beispiel: SCHLEIFE) kann entfallen. Die Ausführung der EXIT-Anweisung führt zur Beendigung der DO-Schleife. Die Ausführung der CYCLE-Anweisung, die zu einer DO-Schleife gehört, verursacht, daß der Iterationszähler der Schleife um eins vermindert und die Laufvariable um die Schrittweite vermindert wird. Als Iterationszähler wird der Ausdruck MAX(INT((m2-m1+m3) / m3), 0) bezeichnet, weil er die Anzahl der noch auszuführenden Schleifendurchläufe angibt. Dabei bedeuten: m1 Anfangswert, m2 Endwert und m3 Schrittweite der DO-Schleife. Danach wird mit dem Beginn der Schleife fortgefahren. Die CYCLE-Anweisung hat somit denselben Effekt wie ein Sprung an das Ende einer Schleife und dient somit in erster Linie der Verbesserung des Programmierstils.

Beispiel:

SUM = 0

READ *, N

DO (N) TIMES

READ *, P, Q

CALL CALCULATE 8P, Q, R9

SUM = SUM + R

IF 8SUM.GT. SMAX9 EXIT

END DO

In diesem Beispiel wird die Schleife so oft ausgeführt, wie der Inhalt von N angibt, ausgenommen der Inhalt von SUM wird größer als der von SMAX, was zum Abbruch der Schleife führt. Wenn durch die READ-Anweisung die Variable N auf null gesetzt wird, wird die Schleife überhaupt nicht ausgeführt.

Formatfreie Quellform

Jede Zeile (Satz) darf zwischen 0 und 132 Zeichen enthalten. Das Zeichen "!" leitet einen Kommentar ein, außer wenn es innerhalb einer Zeichenkette auftritt. Der Kommentar reicht bis zum Ende der Quellzeile.

Mit dem Zeichen ";" trennt man die Anweisungen, wenn sie innerhalb einer Quellzeile auftreten, innerhalb einer Zeichenkette hat das Zeichen ";" keine Wirkung. Das Zeichen "&" als letztes nichtleeres Zeichen in einer Zeile und außerhalb eines Kommentars kündigt an, daß die Anweisung in der nächsten Zeile fortgesetzt wird. Ein Kommentar kann nicht fortgesetzt werden. Ein Zeichen "&" innerhalb eines Kommentars hat keine Wirkung. Wenn das erste Zeichen in der nächsten Zeile, das verschieden von Zwischenraum (Leer) ist, ebenso ein "&" ist, wird die Anweisung mit dem darauffolgenden Zeichen fortgesetzt; andernfalls wird es mit dem Zeichen in Position 1 fortgesetzt. Bei Fortsetzung einer Anweisung mit "&" gehört &" selbst nicht zur Anweisung. Wenn eine Zeichenkette, die kein Kommentar ist, fortgesetzt wird, kann dem Zeichen "&" für Fortsetzung kein Kommentar folgen und der fortgesetzte Teil muß mit einem "&" beginnen. Falls die Fortsetzung nicht innerhalb einer Zeichenkette passiert, darf dem Fortsetzungszeichen "&" ein Kommentar folgen.

NAMELIST

Mit der NAMELIST-Anweisung gibt man einer Gruppe von Variablen einen Namen; bei der Ein- und Ausgabe kann man sich auf die Gruppe beziehen, indem man nur noch den vereinbarten Gruppennamen angibt.

Beispiel:

NAMELIST /LISTE1/ A, B, C, / LISTE2/ E, F

Das Komma hinter C kann weggelassen werden.

Bei den Ein- und Ausgabe-Anweisungen bezieht man sich auf den Gruppennamen, zum Beispiel:

READ (UNIT = 6, NML = LISTE 1)

Die Zeichen in dem NAMELIST-Satz bestehen aus den Variablennamen, einem Gleichheitszeichen ( "="), gefolgt von den dazugehörigen Werten mit dazwischenliegenden Trennzeichen. Die Eingabe für eine NAMELIST-Gruppe setzt sich aus folgenden Angaben zusammen: dem Zeichen &, unmittelbar gefolgt von dem Gruppennamen, der auch in der Eingabe-Anweisung steht; danach folgen die Variablennamen mit dem Gleichheitszeichen und den dazugehörigen Werten, wobei mehrere Angaben durch Trennzeichen voneinander separiert werden. Der Schrägstrich ("/") beendet die Eingabe-Anweisung.

Beispiel:

&LISTE 1 C = 17.32, B = 56.22 /

In diesem Eingabebeispiel werden nur die Variablen B und C der LISTE 1 verändert, der Wert der Variablen A hingegen bleibt unverändert. Die Werte für die Variablen einer Gruppe dürfen in beliebiger Reihenfolge eingegeben werden.

Veraltete Sprachmerkmale

Damit Fortran 77-Programme auch unter Fortran 8x ablaufen können, wurden auch veraltete Sprachkonstrukte aus Fortran 77 beibehalten, jedoch als "decremental" gekennzeichnet, weil sie nach einem längeren Zeitraum wegfallen sollen. Darunter fallen solche Konstrukte, die sich auf die physikalische Speicheranordnung beziehen oder durch andere, bessere Konstrukte ersetzt werden können oder als schlechter Programmierstil angesehen wurden. Sie gehören jedoch alle zum Sprachumfang von Fortran 8x, bei darauffolgenden Normen wird unterschiedlich verfahren: Ein Teil, die sogenannten "obsolescent features", brauchen nicht in die nächstfolgende Norm (Fortran 9x) übernommen zu werden. Dazu zählen: arithmetisches IF;REAL- und DOUBLE PRECISION-Variable als Schleifenvariable; mehrere DO-Schleifen, die von einer gemeinsamen Anweisung beendet werden; Sprung auf eine END-IF-Anweisung von außerhalb; Rücksprung aus einer Prozedur direkt auf eine Marke (RETURN I); PAUSE-Anweisung; ASSIGN und "assigned" GO TO; Zuweisung einer Marke einer FORMAT-Anweisung an eine ganzzahlige Variable mit der ASSIGN-Anweisung.

Alle übrigen veralteten Sprachmerkmale ("deprecated features") werden noch länger in Fortran erhalten bleiben, sie sind auf jeden Fall Bestandteil der übernächsten Norm (Fortran 9x). Die folgenden Konstrukte beziehen sich auf die physikalische Speicheranordnung und wurden deshalb als "deprecated" eingestuft: COMMON, BLOCK DATA, EQUIVALENCE, Formalmatrix mit übernommener Länge (Matrix mit * in der letzten Dimension), Matrixelement oder Zeichenteilfolge (Substring) als aktueller Parameter einer Formalmatrix.

Die folgenden Sprachmerkmale wurden von besser strukturierten abgelöst und deshalb als "deprecated" eingestuft: Fortran 77-Quellformat (restriktive Benutzung der Spalten 1 bis 6), ENTRY-Anweisung, Formelfunktion, Anweisung für berechneten Sprung, anstelle spezifischer Namen für interne Standardfunktionen sollen Gattungsnamen verwendet werden, DATA-Anweisung, DIMENSION-Anweisung, DOUBLE PRECISION-Anweisung, anstelle von *i soll LEN = i bei der Definition von CHARACTER-Vatiablen verwendet werden.