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:
- Anweisungen der Art
i += 1;
müssen in der Grundformi = 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. - In Formatlisten ist die
do
-Schleife nicht erlaubt. Stattdessen muss ich Schleifen um die Ausgabeanweisung herum setzen. - Die Verbindung der im Programm vereinbarten
file
-Variablen mit dem Dateinamen außerhalb geht nicht mehr bequem über Umgebungsvariablen. Entweder muss ich dietitle
-Option verwenden, dann muss das Programm aber die Dateinamen kennen, sie also etwa beim Aufruf mitgeteilt bekommen haben, oder ich sorge dafür, dassfile
-Variable und (relativer) Dateiname gleich heißen. - Während ich in der bisher benutzten PL/I-Version zum Beispiel die
file
-Variableein
nur mit dem Attributfile
versehen musste und dann sofortread file (ein) ...
verwenden konnte, muss ich für denselben Zweckein
jetzt mitrecord 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!