Frage

Ich war auf der Suche nach einem Werkzeug, das C-Code Ausdrücke für die Form umwandeln kann:

a = (A) ? B : C;

in die 'default' Syntax mit if / else Aussagen:

if (A)
  a = B
else
  a = C

Kennt jemand ein Tool, das so zu tun, um eine Transformation fähig ist?

Ich arbeite mit GCC 4.4.2 und vorverarbeiteten Datei mit -E erstellen will aber nicht solche Strukturen darin.

Edit: Folgender Code umgewandelt werden soll, auch:

a = ((A) ? B : C)->b;
War es hilfreich?

Lösung

Coccinelle kann dies ganz einfach.

  

Coccinelle ist ein Programm, Matching und   Transformations-Engine, die liefert   die Sprache smpl (Semantic-Patch   Language) für das Festlegen der gewünschten   Streichhölzer und Umwandlungen in C-Code.   Coccinelle wurde zunächst gezielt   zur Durchführung Sicherheiten   Entwicklungen in Linux. Solche Entwicklungen   die Änderungen umfassen, die erforderlich sind,   in Client-Code als Reaktion auf   Entwicklungen in der Bibliothek APIs und kann   umfassen Modifikationen wie Umbenennungs   eine Funktion, ein Funktionsargument Addieren   dessen Wert irgendwie   kontextabhängig und eine Reorganisation   Datenstruktur. Darüber hinaus Sicherheiten   Entwicklungen, Coccinelle ist erfolgreich   verwendet (von uns und anderen) für die Suche nach   und Fehler in Systemen Code fixiert wird.

EDIT: Ein Beispiel für semantische Patch:

@@ expression E; constant C; @@
(
  !E & !C
|
- !E & C
+ !(E & C)
)

Aus der Dokumentation:

  

Das Muster! X & y. Ein Ausdruck dieser Form ist fast immer sinnlos, weil es einen Booleschen Operator mit einem Bit Operator kombiniert. wenn das Bit ganz rechts y Insbesondere 0 ist, wird das Ergebnis immer 0 sein Dieser semantische Patch konzentriert sich auf den Fall, dass y eine Konstante ist.

Sie haben einen guten Satz von Beispielen hier .

Die Mailing-Liste ist wirklich aktiv und hilfreich.

Andere Tipps

Das folgende semantische Patch für Coccinelle wird die Umwandlung tun.

@@
expression E1, E2, E3, E4;
@@

- E1 = E2 ? E3 : E4;
+ if (E2)
+   E1 = E3;
+ else
+   E1 = E4;

@@
type T;
identifier E5;
T *E3;
T *E4;
expression E1, E2;
@@

- E1 = ((E2) ? (E3) : (E4))->E5;
+ if (E2)
+   E1 = E3->E5;
+ else
+   E1 = E4->E5;


@@
type T;
identifier E5;
T E3;
T E4;
expression E1, E2;
@@

- E1 = ((E2) ? (E3) : (E4)).E5;
+ if (E2)
+   E1 = (E3).E5;
+ else
+   E1 = (E4).E5;

Der DMS Software Reengineering Toolkit kann dies tun, indem Programmtransformationen Anwendung .

Eine spezielle DMS Transformation Ihr spezifisches Beispiel übereinstimmen:

domain C.

rule ifthenelseize_conditional_expression(a:lvalue,A:condition,B:term,C:term):
stmt -> stmt
=  " \a = \A ? \B : \C; "
-> " if (\A) \a = \B;  else \a=\C ; ".

Sie würden eine andere Regel benötigen eine anderen Fall zu behandeln, aber es ist ebenso einfach auszudrücken.

Die Transformationen arbeiten auf Quellcodestrukturen und nicht als Text, so Layout und Kommentare werden nicht die Anerkennung oder die Anwendung beeinflussen. Die Anführungszeichen in der Regel nicht traditionelle String-Zitate, sondern sind metasprachlichen Zitate, die die Regelsyntax Sprache aus dem Muster langu Alter getrennt verwendet, um die konkrete Syntax angeben, geändert werden.

Es gibt einige Probleme mit Vorverarbeitung Richtlinien, wenn Sie beabsichtigen, sie zu behalten. Da Sie apparantly bereit sind, mit Prä-Prozessor-erweiterte Code zu arbeiten, können Sie DMS fragen die Vorverarbeitung als Teil des Transformationsschritt zu tun; es hat volle gcc4 und gcc4-kompatiblen Preprozessoren gebaut rechts in.

Wie andere bemerkt haben, ist dies ein ziemlich leicht Fall, weil Sie es auf der Ebene einer vollständigen Anweisung angegeben arbeiten. Wenn Sie den Code jeder Zuordnung befreien wollen, die auf diese Aussage ähnlich sieht, mit solchen Aufgaben in verschiedenen Kontexten eingebettet (initializers, etc.) können Sie eine größere Menge von Transformationen müssen die verschiedene Reihe von speziellen Fällen zu behandeln, und Sie können müssen andere Code-Strukturen (zB temporäre Variablen geeigneter Typ) herzustellen. Das Gute an einem Tool wie DMS ist, dass es explizit einen symbolischen Typ für einen beliebigen Ausdruck berechnen kann (also die Typdeklaration aller benötigten temps), und dass Sie eine solche größere eher unkompliziert eingestellt schreiben können und alle von ihnen gelten.

Alles, was gesagt, ich bin nicht sicher, ob der reale Wert Ihres ternär bedingungsausdruck Beseitigung Betrieb zu tun. Sobald die Compiler halten das Ergebnis bekommen, können Sie ähnlichen Objekt-Code erhalten, als ob Sie nicht die Transformationen alle an getan hatten. Schließlich kann der Compiler Äquivalenz erhalt Transformationen anwenden, auch.

Es bei der Herstellung von regelmäßigen Änderungen der allgemeinen offensichtlich Wert ist, though.

(DMS kann Quelle-Source-Programm Transformationen auf viele langauges gelten, einschließlich C, C ++, Java, C # und PHP).

Ich bin mir nicht bewusst, so etwas wie der ternäre Operator die Sprachspezifikationen als Abkürzung für die if Logik-in gebaut ist ... die einzige Art, wie ich ist, dies zu tun denken kann manuell für diese Linien zu suchen und Rewrite es in die Form, wo if verwendet wird ... als ein allgemeiner Konsens, der ternäre Operator funktioniert wie folgt

expr_is_true ? exec_if_expr_is_TRUE : exec_if_expr_is_FALSE;

Wenn der Ausdruck ausgewertet wird, um wahr zu sein, führen Sie den Teil zwischen ? und :, führen Sie sonst den letzten Teil zwischen : und ;. Es wäre umgekehrt, wenn der Ausdruck ausgewertet wird, um falsch zu sein

expr_is_false ? exec_if_expr_is_FALSE : exec_if_expr_is_TRUE;

Wenn die Aussagen wie diese sehr regelmäßig sind, warum nicht Ihre Dateien durch einen kleinen Perl-Skript ausführen? Die Kernlogik des find-and-Transformation zu tun ist, einfach für Ihre Beispielzeile. Hier ist ein nackter Knochen Ansatz:

use strict;
while(<>) {
    my $line = $_;
    chomp($line);
    if ( $line =~ m/(\S+)\s*=\s*\((\s*\S+\s*)\)\s*\?\s*(\S+)\s*:\s*(\S+)\s*;/ ) {
        print "if(" . $2 . ")\n\t" . $1 . " = " . $3 . "\nelse\n\t" . $1 . " = " . $4 . "\n";
    } else {
        print $line . "\n";
    }
}
exit(0);

Sie würden führen Sie es wie folgt:

perl transformer.pl < foo.c > foo.c.new

Natürlich wird es immer schwieriger, wenn die Textmuster nicht so regelmäßig wie das ist Sie auf dem Laufenden. Aber frei, schnell und einfach zu versuchen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top