PL/1 für Linux

Im August/September 2011 befasste ich mich mit einem neuen Compiler für die Programmiersprache PL/1 unter Linux. Ich habe in meinem damaligen Blog t520.wordpress.com drei Beiträge darüber veröffentlicht. Nachstehend ihr Wortlaut, die Originalbeiträge im alten Blog habe ich inzwischen gelöscht.

1. Beitrag:

Als PL/I-Nutzer seit 1969 ist mir diese wahrhaft hervorragende Programmiersprache sozusagen ans Herz gewachsen. Wenn ich etwas zu programmieren habe, ist jedesmal PL/I meine erste Wahl, vorausgesetzt, die Umgebung lässt das zu. Ein weißer Fleck auf der PL/I-Landkarte war für mich bisher Linux. Nicht dass jetzt der erste Versuch gestartet wird, PL/I für Linux zur Verfügung zu stellen, aber es gibt jetzt einen neuen Anlauf, den ich (vorerst) mit Wohlwollen betrachte und den ich erst mal mitgehen möchte. Es handelt sich um den PL/I-Compiler der Firma Iron Spring (iron-spring.com) für Linux und OS/2.

Er ist noch so neu, dass er für OS/2 als beta- und für Linux als alpha-Version bezeichnet wird. Entsprechend schwierig war die Installation und erste Benutzung. Das Herunterladen der 2,8 MB großen Datei pli-0.9.2a.tgz war kein Problem. Beim Entpacken mittels Ark machte ich den Fehler, dass ich das Kästchen “Pfade beim Entpacken beibehalten” nicht angeklickt habe, so dass am Ende alle Dateien, auch wenn sie eigentlich in Unterverzeichnissen lagen, sich nebeneinander im gleichen Verzeichnis befanden. Dies hatte zur Folge, dass der Befehl  make install nicht vollständig ausgeführt werden konnte.

Aber ich greife vor. Zunächst erhebt sich nach dem Entpacken die Frage, wie der Compiler zu installieren ist. Nirgendwo auf den Web-Seiten fand ich irgendeinen Hinweis, bis der Zufall half: Im “Programming Guide” gibt es den Abschnitt “Linking PL/I Programs”. Dort findet sich der Verweis “Linux”, der zu einem neuen Dokument führt, das einen Abschnitt “Installation” hat, uff! Wenn man den im obigen Absatz genannten Fehler nicht macht, kann man Compiler und Bibliothek einfach installieren.

Zum Kompilieren eines PL/I-Programms muss man den Parameter -C angeben, also etwa plic -C hw.pli. Ist es in Ordnung, so wird ein Objektprogramm .o erzeugt.

Die nächste Hürde ist der link-Schritt. Angegeben ist der Befehl

ld -z muldefs -Bstatic -M -e main -t -o hw \ hw.o \ -lprf \ >hw.map

Dabei habe ich die angegebenen Variablen schon durch meine Dateinamen hw, hw.o und hw.map (wofür steht wohl hw bei meinem ersten Programm?) ersetzt.

Die Gegenschrägstriche (“\“) sollen Fortsetzungsstriche bei mehrzeiligen Befehlen sein, aber wer weiß das schon? Wenn man sie einfach weglässt, funktioniert alles wunderbar.

Demnächst versuche ich mal richtige Programme und werde weiter berichten.

2. Beitrag

Meine ursprüngliche Freude über einen neuen PL/I-Compiler für Linux (iron-spring.com) hat einen kleinen Dämpfer erfahren, nachdem ich die ersten Schritte gemacht habe.

Das Hauptproblem ist für mich der Sprachumfang des Compilers. Er entspricht dem PL/I für MVS und VM der Firma IBM, was man durchaus für veraltet erklären kann. Ich habe mindestens seit 15 Jahren mit einer neueren Version gearbeitet (PL/I für AIX und PL/I für Windows). In dem ersten Programm, das ich umstellen wollte, habe ich folgende Änderungen machen müssen:

  1. Anweisungen der Art i += 1; müssen in der Grundform i = i  + 1; geschrieben werden. Das sieht nun nicht besonders schlimm aus, aber es gibt ja auch längere Variablennamen, etwa auch qualifizierte, bei denen dann die Schreibarbeit doch wächst.
  2. In Formatlisten ist die do-Schleife nicht erlaubt. Stattdessen muss ich Schleifen um die Ausgabeanweisung herum setzen.
  3. Die Verbindung der im Programm vereinbarten file-Variablen mit dem Dateinamen außerhalb geht nicht mehr bequem über Umgebungsvariablen. Entweder muss ich die title-Option verwenden, dann muss das Programm aber die Dateinamen kennen, sie also etwa beim Aufruf mitgeteilt bekommen haben, oder ich sorge dafür, dass file-Variable und (relativer) Dateiname gleich heißen.
  4. Während ich in der bisher benutzten PL/I-Version zum Beispiel die file-Variable ein nur mit dem Attribut file versehen musste und dann sofort read file (ein) ... verwenden konnte, muss ich für denselben Zweck ein jetzt mit record input env (U) vereinbaren.

Ich vermute, dass bei anderen Programmen noch weitere Änderungen nötig sind, damit der Iron Spring-Compiler sie versteht.

Ein weiteres Problem besteht darin, dass der Compiler wegen seiner Neuheit noch einige Fehler enthält. Bisher habe ich 2 Compilerfehler gefunden (Fehlernummern 208 und 210). Positiv ist zu vermerken, dass der Compilerautor schnell und kompetent auf Fehlerhinweise reagiert.

3. Beitrag

Der PL/I-Compiler von Iron Spring (iron-spring.com) in seiner jetzigen Version (0.9.2a) hat meines Erachtens so viele Fehler bei relativ einfachen Anweisungen, dass er unbrauchbar ist. Ich habe mich daher entschlossen, ihn vorerst nicht weiter zu verwenden. Wenn eine neue Version herauskommt, sehen wir weiter.

*************************************************************************************

Soweit die Vergangenheit aus dem Jahr 2011.

Inzwischen habe ich weiter PL/1 für Windows von der Firma IBM benutzt. Da die damit erstellten Programme natürlich auch für in Linux bearbeitete Aufgaben unter Windows laufen müssen, war ein ständiges Hin- und Herschalten zwischen den beiden Betriebssystemen notwendig. Dies funktioniert zwar durch die Verwendung einer Virtualisierungssoftware (VirtualBox), bei der Windows nur ein Fenster in Linux ist, reibungslos, ist dann aber doch auf die Dauer wegen der von Zeit zu Zeit notwendigen Änderung der Windowssysteme lästig geworden.

Die Neuigkeiten des Iron Spring PL/I Compilers habe ich ständig verfolgt, so dass ich inzwischen glaube, dass ich einen neuen Versuch damit wagen sollte. Die Version ist zunächst 0.9.5, ab Problem Nr. 6 verwende ich 0.9.6.

Das (Test)Objekt ist ein PL/1-Programm von 380 Zeilen. Ich beschreibe im folgenden alle Änderungen, die ich an diesem Programm vornehmen musste, bis es lief. Wenn ich anschließend noch weiter Änderungen beschreiben muss, werde ich sie an diesen Blogbeitrag anhängen, er ist also vorläufig wahrscheinlich/eventuell unvollständig.

Ich habe für jedes Problem einen Schweregrad [n] nach folgender Tabelle vergeben:

  • [0]: Nicht reproduzierbarer Fehler, Ursache unbekannt, eigentlich kein Problem.
  • [1]: Mein Programm ist in einem anderen Dialekt geschrieben. Ich muss – einmalig – mein Programm anpassen.
  • [2]: Mein Programm ist richtig und wird ohne Fehlermeldung kompiliert, jedoch wird bei der Ausführung ein „falscher“ Fehler angezeigt, dessen Ursache nicht ersichtlich ist.
  • [3]: Mein Programm ist richtig und wird ohne Fehlermeldung kompiliert, jedoch führt die Ausführung ohne Fehlermeldung zu einem fehlerhaften Ergebnis.

1. Problem [1]:

Die Anweisung nrtag += 1; ergibt vor der Zeile 286 in der .lst-Datei die Fehlermeldungen

286 (ERR208)Unrecognized keyword NRTAG.
286 (INF249)-input flushed to next ";".

Abhilfe: Schreibe diese Anweisung wie alle ähnlichen um in nrtag = nrtag + 1;

2. Problem [1]:

Die Anweisung put file (tex) edit ((a (i) do i = 1 to 7)) (skip, a); in Zeile 88 wird am Ende der .lst-Datei mit folgender Meldung geahndet:

88 (ERR995)Deferred feature GET/PUT List contains DO.

Abhilfe für diese und entsprechende Anweisungen ist umschreiben in

do i = 1 to 7;
put file (tex) edit (a (i)) (skip, a);
end;

3. Problem [1]:

Die Anweisung do jp = 1 to laenge (i); in Zeile 285 wird am Ende der .lst-Datei mit folgender Meldung geahndet:

285 (ERR690)<exp2> (TO) contains non-scalar or non-computational data.

Abhilfe für diese und entsprechende Anweisungen ist umschreiben in

k = laenge (i);
do jp = 1 to k;

4. Problem [1]:

Der Compiler versteht das Zeichen ^ nicht als Nichtzeichen, wenn man es nicht besonders als solches kennzeichnet. Letzteres geschieht durch Angabe des Parameters "-cn(^)" (einschließlich der Gänsefüßchen) im Aufruf des Compilers.

5. Problem [0]:

Das nach den ersten 4 Änderungen fehlerfrei kompilierte und gebundene Programm geht beim Start in eine Endlosschleife. Leider oder glücklicherweise ließ sich das Problem nicht mehr reproduzieren. Ich weiß leider nicht mehr, was ich geändert habe, oder ob ich überhaupt etwas geändert habe. Weg ist weg!

6. Problem [2]:

Das Programm endet vorzeitig mit der Fehlermeldung

No WHEN clause selected in SELECT statement,
and no OTHERWISE clause present.
ERROR condition raised at address 0805D842
in procedure with entry _pli_OTH
Thread = 7183

Im Programm kommen zwei SELECT-Anweisungen vor. Die eine hat eine OTHERWISE-Klausel, bei der zweiten kann es von der Programmlogik niemals zu dem Fehler kommen. Da ich Anhänger des defensiven Programmierens bin, füge ich dennoch die fehlende Klausel hinzu, in der ich eine Fehlermeldung ausgebe und zum Programmende gehe.

Diese Programmänderung ändert aber nichts an der Fehlermeldung. Sie verschwindet erst, als ich den Bedingungspräfix (STRG): vor der PROCEDURE-Anweisung entferne. Ich bin darauf gekommen, weil ich einen solchen Fehler bereits 2011 gemeldet habe.

Das Problem Nr. 6 habe ich an den Programmautor weitergegeben. Es ist (hoffentlich) in Bearbeitung.

Lösung: Es war erfolgreich in Bearbeitung! Nach weniger als 3 Wochen gab es eine neue Programmversion 0.9.7, in der der Fehler beseitigt wurde. Großes Lob für den Programmautor Peter Flass!

7. Problem [1]:

In der für das 6. Problem hinzugefügten OTHERWISE-Klausel verwende ich die Anweisung put skip data (k);. Dies führt bei der Kompilierung für die Zeile 216 zu der Warnung

216 (WRN557)Undeclared variable SYSPRINT has been assigned default attributes "EXTERNAL FILE".

Die Warnung verschwindet durch die Hinzunahme der Deklaration dcl sysprint file ext;.

8. Problem [3]:

Das Programm beginnt in den Deklarationen mit

DCL A (12) CHAR (73) STATIC INIT (
'\documentclass{report}\usepackage{a4,colordvi,epsf}',
'\usepackage[pdftex]{color,graphicx}',

...

Ziemlich zu Anfang der Programmausführung werden die ersten Zeilen in die Ausgabedatei geschrieben:

do i = 1 to 8;
PUT FILE (TEX) EDIT (A (I)) (SKIP, A);
end;

In der Ausgabedatei fehlen die ersten 8 Zeichen der ersten Zeile!

Als Abhilfe habe ich die Deklaration des Bereichs A um ein nulltes Element ergänzt, welches nicht mit ausgegeben wird:

DCL A (0 :12) CHAR (73) STATIC INIT (
'dummydummydummy',
'\documentclass{report}\usepackage{a4,colordvi,epsf}',
'\usepackage[pdftex]{color,graphicx}',

...
Wird fortgesetzt!

Über zhongxiong

peter-preus.de
Dieser Beitrag wurde unter Allgemein abgelegt und mit , , , , verschlagwortet. Setze ein Lesezeichen auf den Permalink.

Hinterlasse einen Kommentar