Gibt es einen C-Präprozessor, der #ifdef-Blöcke basierend auf definierten/undefinierten Werten eliminiert?

Lesezeit: 7 Minuten

Gibt es einen C Praprozessor der ifdef Blocke basierend auf definiertenundefinierten Werten
Jonathan Leffler

Ursprüngliche Frage

Was ich möchte, ist kein Standard-C-Präprozessor, sondern eine Variation davon, die von irgendwoher – wahrscheinlich der Befehlszeile über die Optionen -DNAME1 und -UNAME2 – eine Spezifikation akzeptieren würde, welche Makros definiert sind, und dann tot eliminieren würde Code.

Mit einigen Beispielen ist es vielleicht einfacher zu verstehen, wonach ich suche:

#ifdef NAME1
#define ALBUQUERQUE "ambidextrous"
#else
#define PHANTASMAGORIA "ghostly"
#endif

Wenn der Befehl mit ‘-DNAME1’ ausgeführt würde, wäre die Ausgabe:

#define ALBUQUERQUE "ambidextrous"

Wenn der Befehl mit ‘-UNAME1’ ausgeführt würde, wäre die Ausgabe:

#define PHANTASMAGORIA "ghostly"

Wenn der Befehl ohne beide Optionen ausgeführt würde, wäre die Ausgabe dieselbe wie die Eingabe.

Dies ist ein einfacher Fall – ich würde hoffen, dass der Code auch komplexere Fälle handhaben könnte.

Zur Veranschaulichung mit einem realen, aber immer noch einfachen Beispiel:

#ifdef USE_VOID
#ifdef PLATFORM1
#define VOID void
#else
#undef VOID
typedef void    VOID;
#endif /* PLATFORM1 */
typedef void *  VOIDPTR;
#else
typedef mint     VOID;
typedef char *  VOIDPTR;
#endif /* USE_VOID */

Ich möchte den Befehl mit ausführen -DUSE_VOID -UPLATFORM1 und bekomme die Ausgabe:

#undef VOID
typedef void    VOID;
typedef void *  VOIDPTR;

Ein anderes Beispiel:

#ifndef DOUBLEPAD
#if (defined NT) || (defined OLDUNIX)
#define DOUBLEPAD 8
#else
#define DOUBLEPAD 0
#endif /* NT */
#endif /* !DOUBLEPAD */

Idealerweise würde ich gerne mit laufen -UOLDUNIX und bekomme die Ausgabe:

#ifndef DOUBLEPAD
#if (defined NT)
#define DOUBLEPAD 8
#else
#define DOUBLEPAD 0
#endif /* NT */
#endif /* !DOUBLEPAD */

Das könnte mein Glück auf die Probe stellen!

Motivation: große, alte Codebasis mit viel bedingtem Code. Viele der Bedingungen gelten nicht mehr – die OLDUNIX-Plattform zum Beispiel wird nicht mehr hergestellt und nicht mehr unterstützt, daher besteht keine Notwendigkeit, im Code darauf zu verweisen. Andere Bedingungen sind immer wahr. Beispielsweise werden Funktionen mit bedingter Kompilierung hinzugefügt, sodass eine einzige Version des Codes sowohl für ältere Versionen der Software, in denen die Funktion nicht verfügbar ist, als auch für neuere Versionen, in denen sie (mehr oder weniger) verfügbar ist, verwendet werden kann. Schließlich werden die alten Versionen ohne die Funktion nicht mehr unterstützt – alles verwendet die Funktion – also sollte die Bedingung, ob die Funktion vorhanden ist oder nicht, entfernt werden, und der Code „wenn die Funktion fehlt“ sollte ebenfalls entfernt werden. Ich hätte gerne ein Tool, das die Arbeit automatisch erledigt, da es schneller und zuverlässiger ist als die manuelle Ausführung (was ziemlich kritisch ist, wenn die Codebasis 21.500 Quelldateien enthält).

(Eine wirklich clevere Version des Tools könnte lauten #include‘d-Dateien, um festzustellen, ob die Steuerungsmakros – die durch -D oder -U in der Befehlszeile angegeben werden – in diesen Dateien definiert sind. Ich bin mir nicht sicher, ob das wirklich hilfreich ist, außer als Backup-Diagnose. Was auch immer er sonst tut, der Pseudo-Präprozessor darf Makros nicht erweitern oder Dateien wörtlich einschließen. Die Ausgabe muss eine ähnliche Quelle sein wie der Eingabecode, aber normalerweise einfacher als dieser.)

Statusbericht (ein Jahr später)

Nach einem Jahr Nutzung bin ich sehr zufrieden mit ‘sunifdef‘ von der ausgewählten Antwort empfohlen. Es hat noch keinen Fehler gemacht, und ich erwarte es auch nicht. Der einzige Makel, den ich damit habe, ist stilistisch. Bei einer Eingabe wie:

#if (defined(A) && defined(B)) || defined(C) || (defined(D) && defined(E))

und mit ‘-UC’ ausführen (C ist nie definiert), die Ausgabe ist:

#if defined(A) && defined(B) || defined(D) && defined(E)

Das ist technisch korrekt, weil ‘&&’ enger bindet als ‘||’, aber es ist eine offene Einladung zur Verwirrung. Ich würde es vorziehen, Klammern um die Sätze von ‘&&’-Bedingungen einzuschließen, wie im Original:

#if (defined(A) && defined(B)) || (defined(D) && defined(E))

Angesichts der Unklarheit einiger Codes, mit denen ich arbeiten muss, ist es jedoch ein großes Kompliment, dass dies der größte Nit-Pick ist. es ist ein wertvolles Werkzeug für mich.


Das neue Kind auf dem Block

Nachdem ich die URL für die Aufnahme in die obigen Informationen überprüft habe, sehe ich, dass (wie vorhergesagt) ein neues Programm aufgerufen wird Coan das ist der Nachfolger von ‘sunifdef’. Es ist seit Januar 2010 auf SourceForge erhältlich. Ich werde es mir ansehen … weitere Berichte später in diesem Jahr oder vielleicht nächstes Jahr oder irgendwann oder nie.

  • Danke für den Vorschlag – nein, das brauche ich nicht. Ich weiß, wie man sich ansieht, was der Compiler sieht (ich habe neulich ein paar Stunden damit verbracht, mir 37.000 Zeilen erweiterter Ausgabe anzusehen, um herauszufinden, warum etwas schief gelaufen ist). Ich möchte, dass #include und andere Zeilen erhalten bleiben und Makros nicht erweitert werden.

    – Jonathan Leffler

    8. Februar 2009 um 6:58 Uhr

Gibt es einen C Praprozessor der ifdef Blocke basierend auf definiertenundefinierten Werten
Jörg W Mittag

Ich weiß absolut nichts über C, aber es hört sich so an, als ob Sie nach so etwas suchen unifdef. Beachten Sie, dass es seit 2000 nicht aktualisiert wurde, aber es gibt einen Nachfolger namens “Sohn von unifdef” (sunifdef).

  • Habe beides heruntergeladen. Hatte ein paar Schluckauf bei der Portierung von sunifdef auf Solaris 10; Ich habe diese Informationen an den Entwickler weitergeleitet. Sieht vielversprechend aus, jetzt habe ich die Probleme umgangen. Danke.

    – Jonathan Leffler

    8. Februar 2009 um 15:22 Uhr

  • sunifdef funktioniert recht gut – und enthüllt bisher nicht erkannte Tiefen der Verdorbenheit in der Codebasis. Nun ja; es wird sauberer enden. Danke für den Hinweis, Jörg.

    – Jonathan Leffler

    10. Februar 2009 um 15:41 Uhr

  • Gern geschehen. Ich bin ein Fan von sauberem, schönem, ausdrucksstarkem Code – ich freue mich, dass ich Ihnen helfen konnte, die Welt zu einem besseren Ort zu machen 🙂

    – Jörg W Mittag

    10. Februar 2009 um 16:15 Uhr

  • Beachten Sie auch in einer ähnlichen Frage hier das unifdef wird jetzt aktiv gepflegt und im Linux-Kernel verwendet.

    – Shafik Yaghmour

    31. März 2014 um 1:50 Uhr

Sie können dieses Tool auch ausprobieren http://coan2.sourceforge.net/

so etwas entfernt ifdef-Blöcke:

coan source -UYOUR_FLAG –filter c,h –recurse YourSourceTree

  • Willkommen bei Stapelüberlauf. Bitte lesen Sie bald die FAQ. Coan wird in der Hauptfrage als „The New Kid on the Block“ erwähnt.

    – Jonathan Leffler

    20. Juni 2013 um 16:09 Uhr

Ich habe unifdef vor Jahren für genau die Art von Problem verwendet, die Sie beschreiben, und es hat gut funktioniert. Auch wenn es seit 2000 nicht aktualisiert wurde, hat sich die Syntax des Präprozessors ifdefs seitdem nicht wesentlich geändert, also gehe ich davon aus, dass es immer noch das tut, was Sie wollen. Ich nehme an, es könnte einige Kompilierungsprobleme geben, obwohl die Pakete neu zu sein scheinen.

Ich habe sunifdef noch nie verwendet, daher kann ich es nicht direkt kommentieren.

Um 2004 herum habe ich ein Tool geschrieben, das genau das tat, wonach Sie suchen. Ich bin nie dazu gekommen, das Tool zu verteilen, aber der Code ist hier zu finden:

http://casey.dnsalias.org/exifdef-0.2.zip (das ist ein dsl-link)

Es umfasst etwa 1,7 000 Zeilen und implementiert genug von der C-Grammatik, um Präprozessoranweisungen, Kommentare und Zeichenfolgen mit Bison und Flex zu analysieren.

1646741413 113 Gibt es einen C Praprozessor der ifdef Blocke basierend auf definiertenundefinierten Werten
MSalter

Wenn Sie etwas Ähnliches wie einen Präprozessor benötigen, ist die flexible Lösung Welle (vom Schub). Es ist eine Bibliothek, die entwickelt wurde, um C-Präprozessor-ähnliche Tools zu erstellen (einschließlich solcher Dinge wie C++03- und C++0x-Präprozessoren). Da es sich um eine Bibliothek handelt, können Sie sich in ihren Eingabe- und Ausgabecode einklinken.

  • Danke. Das sieht interessant aus, erfordert aber eine Verpackung, um die Arbeit zu erledigen, während sunifdef bereits verpackt ist und die Arbeit recht gut erledigt. Ich habe die URL hinzugefügt – danke für die Info.

    – Jonathan Leffler

    10. Februar 2009 um 15:40 Uhr

  • Danke. Das sieht interessant aus, erfordert aber eine Verpackung, um die Arbeit zu erledigen, während sunifdef bereits verpackt ist und die Arbeit recht gut erledigt. Ich habe die URL hinzugefügt – danke für die Info.

    – Jonathan Leffler

    10. Februar 2009 um 15:40 Uhr

974720cookie-checkGibt es einen C-Präprozessor, der #ifdef-Blöcke basierend auf definierten/undefinierten Werten eliminiert?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy