*

Studienarbeit

Repräsentation von Makros in IML

Hintergrund

Bei der Übersetzung von C-Programmen wird in der Regel zunächst der Programmtext (im Folgenden der Originaltext genannt) von einem Präprozessor eingelesen und vorhandene Präprozessoranweisungen behandelt. Der Text, der vom Präprozessor aus dem Originaltext generiert wird, wird im Folgenden als Programmtext bezeichnet. Vom Präprozessor werden Makro-Direktive ersetzt, andere Dateien eingebunden und Code-Teile durch bedingte Anweisungen ein- oder ausgeblendet. Der eigentliche C-Compiler erhält als Eingabe den Programmtext, der vom Präprozessor generiert wird, der aber in der Regel nicht dem Originaltext entspricht, wie der Programmierer ihn sieht.

Im Falle eines Compilers ist die Umwandlung des Originaltextes nicht weiter problematisch, wenn man davon absieht, dass die Spalteninformation von Tokens in Zeilen, in denen Makros expandiert werden, dem Compiler für Fehlermeldungen nicht mehr zur Verfügung steht. Für Reengineering-Werkzeuge jedoch, die mit dem Benutzer interagieren und die eventuell den Originaltext wieder generieren müssen, gehen wichtige Informationen durch den Präprozessorschritt verloren. Wenn etwa Makros zur Deklaration benannter Ausdrücke benutzt werden, die dann durch den Präprozessor expandiert werden, entgeht dem Reengineering-Frontend die Tatsache, dass sich verschiedene Programmteile auf denselben Ausdruck, d.h. das Makro, beziehen.

Wir haben eine Reihe von Werkzeuge zur Analyse von C-Programmen entwickelt, die das Reverse-Engineering, Reengineering und Programmverstehen unterstützen. Dabei werden die C-Programme zunächst von einem von uns entwickelten Frontend in unsere interne Zwischendarstellung IML übersetzt. Zur Übersetzung wird bislang ein Standardpräprozessor vorausgesetzt, so dass viele wichtige Informationen dem Frontend nicht mehr zur Verfügung stehen. Aus diesem Grunde benötigen wir eine Möglichkeit, bestimmte Informationen aus dem Originaltext des Programmes, die beim Präprozessieren mit einem Standardpräprozessor verloren gehen, zu erhalten.

Eine besondere Schwierigkeit beim Versuch, die Informationen des Originaltextes zu erhalten, stellt der Umstand dar, dass der Originaltext nicht notwendigerweise den Grammatikregeln von C entsprechen muss. Es kann vorkommen, dass erst durch die Expansion bestimmter Makros aus dem Originaltext ein gültiges C-Programm wird. In vielen Fällen werden Makros von Programmierern jedoch verwendet, als ob sie gültigen C-Deklarationen entsprächen, wie z.B. als Konstanten und Funktionen. Letztere Makrotypen bezeichnen wir als wohlgeformte Makros. Wohlgeformte Makros sind solche Makros, deren Auftreten (d.h. deren Direktive, noch vor der Expansion) den syntaktischen Regeln von C entsprechen. Wohlgeformte Makros können somit syntaktisch als Pseudo-Bezeichner (Makro ohne Argumente) oder Pseudo-Funktionsaufruf (Makro mit Argumenten; für das Function Inlining oder zur Nachbildung generischer Funktionen) betrachtet werden. Wohlgeformte Makros entsprechen jedoch nicht den semantischen Regeln von C, da beim Auftreten des Makros für den Pseudo-Bezeichner und den Pseudo-Funktionsaufruf keine Deklaration existiert.

Aufgabenstellung

Diese Studienarbeit hat zur Aufgabe die folgenden Informationen zu erhalten, die durch einen Standardpräprozessor üblicherweise verloren gehen (die Auflistung der Punkte entspricht ihrer Priorität, wobei der erste Punkt die höchste Priorität hat):
  • Genaue Spalteninformation. Die Zeileninformation wird von unseren Werkzeugen bereits richtig ermittelt. Wenn jedoch Makros expandiert werden, erhalten die Tokens, die von unserem Frontend eingelesen werden, nicht die Originalspaltenposition, sondern jene aus dem Programmtext nach Expansion. Diese Studienarbeit soll zusätzlich die Spaltenposition des Originaltextes in IML verfügbar machen.
  • Markierung von IML-Knoten, die sich aus der Expansion wohlgeformter Makros ergeben. Wohlgeformte Makros, die als benannte Ausdrücke oder für das Function-Inlining verwendet werden, entsprechen in IML einem Teilbaum, dessen Wurzel als die Makro-Direktive selbst betrachtet werden kann. Diese Wurzelknoten sollen im Rahmen dieser Studienarbeit in IML durch semantische Attributierung als Makro-Direktive gekennzeichnet werden. Dabei ist bei Makros mit Argumenten zu beachten, dass die Argumente selbst nicht zur Makroexpansion gehören und dass Makros selbst wieder Makros aufrufen können. Als Beispiel diene der folgende Originaltext.

    #define MAX 10000
    #define BOUND (a) ((a) <= MAX) ? (a) : (MAX))
    #define LEN 100
    ... x = BOUND (LEN)...

    Die Expansion von BOUND ergibt:
    x = ((100) <= 10000) ? (100) : (10000))

    Für diese Expansion ergibt sich der folgende annotierte Teilbaum:

  • Makroinformation für IML-Knoten. Diese Studienarbeit soll die Möglichkeit vorsehen, für alle IML-Knoten, die aus Makroexpansionen hervorgehen, die ursprüngliche Makro-Direktive herzuleiten.
  • Suche im Original- und Programmtext. Prinzipiell kann sowohl im Originaltext als auch im Programmtext (sowie in IML, siehe oben) selbst nach bestimmten Konstrukten gesucht werden. Da Original- und Programmtext zunächst lediglich Text sind, ist hier nur eine textuelle Suche möglich. In dieser Studienarbeit soll die Möglichkeit zur Verfügung gestellt werden, ausgehend von einer Textposition des Original- oder Programmtextes den entsprechenden IML-Knoten zu identifizieren. Dabei ist zu beachten, dass nicht für jede Textposition tatsächlich ein IML-Knoten existiert. Zum Beispiel gibt es für Klammern, Semikola und Whitespace keinen IML-Knoten. Außerdem muss berücksichtigt werden, dass Makros expandiert sein können oder Originaltext durch Präprozessoranweisungen ausgeblendet sein kann.
Für die Implementierung soll der GNU Präprozessor erweitert werden, um notwendige zusätzliche Information bereitzustellen. Die Änderungen sollen derart gestaltet sein, dass zukünftige Änderungen des Präprozessors durch die GNU-Entwickler mit möglichst minimalem Aufwand von uns integriert werden können. Die Änderungen am Präprozessor erfolgen in C.

Die Anpassung unseres Frontends, um die vom erweiterten Präprozessor zusätzlich eingefügte Information zu berücksichtigen, übernimmt unsere Abteilung. Der Studienarbeiter muss jedoch Syntax und Semantik der Einfügungen genau spezifizieren. Anpassungen der Zwischendarstellung IML, um die zusätzliche Information zu repräsentieren, sind vom Studienarbeiter in Absprache mit unserer Abteilung vorzunehmen und erfolgen in Ada 95.

Die Ansprüche an die Qualität der Implementierung sind hoch. Vollständige Dokumentation und ein umfangreicher systematischer Test sind deshalb Teil der Aufgabenstellung. Für den Test ist ein Black-Box-Test mit der Eignung zu einem automatischen Regressionstest vorzusehen. Das Testprotokoll ist abzugeben.

Grundlage für die Präprozessor-Direktiven ist die aktuelle ISO-Norm für C, wobei jedoch nur solche Direktive behandelt werden müssen, die auch vom GNU Präprozessor unterstützt werden. Insbesondere unterstützt der GNU-Präprozessor-Neuerungen, wie variable Argumentlisten und die Direktive _Pragma, noch nicht.

Voraussetzungen

Programmierkenntnisse in C und in Ada.

Betreuer

Dr. Rainer Koschke,Yan Zhang


Valid HTML 3.2! Last modified: Thu Feb 7 08:30:38 MET 2002
admin@droste.informatik.uni-stuttgart.de