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
-
-
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
Jetzt mitmachen!
Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!