Ich habe mit teilweise unglaublich unstrukturiertem C/C++ - Code zu tun, bei dem oft weite Teile in #ifdef xy - Klauseln eingebettet sind.
Ich frage mich, wie sich folgendes mit vertretbarem Aufwand machen lässt:
Alle source-files sollen nach
#ifdef XY
code...
#endif
gescannt werden, die Zeilen dazwischen sollen komplett rausgelöscht werden (nein, ich werde den Code nieee mit definiertem XY kompilieren müssen!). Allerdings darf sich so ein Parser nicht durch geschachtelte #ifdef's drausbringen lassen.
Außerdem sollte im Fall
#ifdef XY
code...
#else
code...
#endif
zusätzlich das abschließende #endif entfernt werden, damit der Präprozessor keinen Syntax-Fehler bringt.
Ich wäre noch in der Lage, dies formal - etwa in EBNF - zu formulieren. Aber mit welchen Tools macht man sowas dann? Geht es mit dem Präprozessor selber irgendwie? Oder mit sed/awk (Ich habe keinen Schimmer, wie man damit umgeht)?
Wäre für Tipps dankbar.
#ifdef's rausfiltern
-
Incazzato -
23. August 2005 um 19:42 -
Unerledigt
-
-
Das schreit ja richtig nach Perl :))
Also im Ernst. Mit Perl sind das sicher nur ein paar Zeilen Code um so nen Parser zu schreiben.
-
Zu Perl äußer ich mich nicht, aber hier ist eine potentielle primitive Lösung mit lex (ja, die erste Zeile gehört eingerückt):
Code
Alles anzeigenunsigned long level = 0; %% #if(n?def)? level++; #else ; #endif level--; \n if (level == 0) ECHO; . if (level == 0) ECHO;
Usage:
wobei foo.l obiger Lex-Source ist und input.c das zu transformierende Programm.Edit: Das tut jetzt übrigens alle #ifs und #ifdefs raus. Falls nur #ifdef für bestimmte Makros gemeint war, dann wirds bissi komplizierter.
-
Zitat von Plantschkuh!
Zu Perl äußer ich mich nicht, aber hier ist eine potentielle primitive Lösung mit lex (ja, die erste Zeile gehört eingerückt):
Das liest sich sehr gut!
In der Tat sollen nur genau die von einem bestimmten Makro abhängigen Blöcke raus, sagen wir mal von "KACK" . Ich versuche das mal einzubauen:Code
Alles anzeigenunsigned long level = 0; unsigned long kack_flag = 0; // oder gibts auch boolean? signed long kack_level = -1; %% #ifdef KACK kack_flag = 1; kack_level = level; #if(n?def)? level++; #else ; // nur zur Dekoration, oder? #endif level--; if (level == kack_level) kack_flag = 0; kack_level = -1; \n if (kack_flag == 0) ECHO; . if (kack_flag == 0) ECHO;
Syntax ist einfach geraten, korrigiere mich bitte gegebenenfalls. Muss bei "#ifdef KACK" das Leerzeichen gequotet werden?
Kann ich die auszuführenden Anweisungen so hintereinanderschreiben? Was bedeuten "\n" und "." am Ende?Vielen Dank übrigens!
-
Hab jetzt auf der Basis von deinem mal das zusammengezimmert:
Code
Alles anzeigenunsigned long level = 0; int kack_flag = 0; signed long kack_level = -1; ifkack #ifdef\ +__cplusplus %% {ifkack} kack_flag = 1; kack_level = level++; #if(n?def)? level++; ECHO; #else if (kack_flag) kack_flag = 0; else ECHO; #endif { level--; if (level == kack_level) { kack_flag = 0; kack_level = -1; } else ECHO; } \n if (kack_flag == 0) ECHO; . if (kack_flag == 0) ECHO;
Sollte funktionieren, solang nirgends #ifdef KACK in einem Kommentar oder String vorkommt und #ifdef KACKs nicht geschachtelt sind. Du mußt nur in der Zeile "ifkack #ifdef\ +__cplusplus" das __cplusplus durch den Namen deines Makros ersetzen.
Und ja, die Regel für #else war in meiner ersten Version redundant, sollte nur andeuten, daß ein #else explizit nicht ausgegeben werden soll.
\n steht für ein Newline (Zeilenende), . für ein beliebiges Zeichen außer Newline. D.h. alle Zeichen, die nicht Teil von einem #ifdef oder sowas sind, sollen ausgegeben werden, wenn der flag 0 ist.Und schließlich: http://www.eskimo.com/~scs/C-faq/q10.18.html
-
So früh schon so wach im Kopf?
Weils so schön ist, noch meine endgültige Version:
Code
Alles anzeigenunsigned long level = 0; int kack_flag = 0; signed long kack_level = -1; ifkack #ifdef\ +KACK %% {ifkack} kack_flag = 1; kack_level = level++; #if(n?def)? { level++; if (kack_flag == 0) ECHO; } #else { if(kack_flag) { if(kack_level == (level-1)) { kack_flag = 0; } } else ECHO; } #endif { level--; if (level == kack_level) { kack_flag = 0; kack_level = -1; } else if (kack_flag == 0) ECHO; } \n if (kack_flag == 0) ECHO; . if (kack_flag == 0) ECHO;
Waren noch kleine Änderungen nötig, damit bei innerer und äußerer Verschachtelung alls stimmt. z.B blieben in Header-Files Zeilen mit "#ifdef endif" übrig.
Aber jetzt habe ich den ganzen (entKACKten) Kack ohne Syntaxfehler kompiliert.muchos gracias!
PS: ich war mal in deiner TheoInf-Übung -
Maximilian Rupp
27. Dezember 2024 um 12:06 Hat das Thema aus dem Forum Programmieren nach Entwicklung verschoben.
Jetzt mitmachen!
Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!