Gibt es ein Tool, mit dem ich den Funktionsnamen herausfinden kann, zu dem eine bestimmte Quellzeilennummer gehört?
Beispieldatei:
static enum foo bar(int c)
{
if (c < 30)
return B1;
else
return B2;
}
static enum foo somethingelse(void)
{
return B3;
}
Für Zeile 4 return B1;
sollte die Antwort lauten bar
.
Ich verwende C99- Quellsyntax. Der Quellcode kann aufgrund seiner Abhängigkeiten nur mit GCC kompiliert werden.
C99 ist eine Spezifikation für C. Ansi C wäre C89. Aber es gibt zum Beispiel Dinge wie K&R C - ziemlich wichtig, wenn es darum geht, die Quelldatei zu parsen, um die Funktionsnamen zu finden.
Die Frage wurde als Off-Topic auf SO geschlossen .
Unser DMS Software Reengineering Toolkit mit seinem C-Frontend könnte dazu problemlos verwendet werden.
DMS analysiert und erstellt ASTs für eine ihm definierte Sprache. Das C-Frontend definiert eine Vielzahl von C-Dialekten für DMS, einschließlich C99. Das Ergebnis der Anwendung des C-Frontends mit DMS auf eine C-Datei (komplett mit Präprozessordirektiven/Erweiterung usw.) ist ein AST, bei dem jeder Knoten mit seinem Grammatikregeltyp versehen ist, mit Quelldatei, Zeile und Spalte.
Bei einem solchen Baum kann man das ASTInterface von DMS verwenden, um an der Wurzel zu beginnen und über den Baum zu gehen, bis ein Knoten mit der Zeilennummer 4 gefunden wird. Unter der Annahme, dass es sich innerhalb einer Funktion befindet (was möglicherweise nicht der Fall ist), können Sie den Baum problemlos zu einem Knoten hinaufgehen, der eine Funktionsdeklaration ist, und dann einen Knoten hinunter zur Funktions-ID und dann die diesem Knoten zugeordnete Zeichenfolge drucken .
Der mit DMS auszuführende Code sieht folgendermaßen aus:
(define FindFunctionName
(lambda (function natural [FileName (reference string)] [target_line_number natural])
(local (;; (= [my_tree AST:Node] (C~GCC4:ParserComponent:Parse FileName)
(= [current_node AST:Node] (AST:FindInSubtree my_tree
(lambda (function boolean AST:Node)
(== (AST:GetLineNumber ?) target_line_number)
)lambda )=
);;
(= current_node (AST:FindParent current_node
(lambda (function boolean AST:Node)
(== (AST:GetNodeType ?)
C~GCC4:ParserComponent:TokenNumber:function_declaration)
)lambda )=
(return (AST:GetStringLiteral (AST:GetNthChild current_node 2)) ; id node under function_declaration
)local
DMS verwendet eine parallele Programmiersprache im Lisp-Syntax-Stil namens PARLANSE für seine Metaprogrammiersprache. Ich denke, was das obige tut, ist ziemlich klar. Ich habe die gesamte Fehlerprüfung (obwohl PARLANSE-Ausnahmen das meiste davon für den Programmierer erledigen) aus erklärenden Gründen weggelassen.
DMS ist insofern einzigartig, als Sie nicht unbedingt alle Präprozessordirektiven erweitern müssen, um den Text zu parsen. Das C-Frontend hat einen Modus, in dem "gut strukturierte" PP-Anweisungen einfach geparst und im Baum beibehalten werden; Es kann nicht mit PP-Bedingungen umgehen, die C-Nichtterminale umfassen. Sie können den Funktionsnamen immer noch auf die gleiche Weise finden, aber Sie müssen sich möglicherweise Sorgen machen, dass der in der Funktionsdeklaration gefundene Bezeichner tatsächlich ein Makro ist oder in eine Bedingung eingeschlossen sein könnte. Die C-Front hat einen weiteren experimentellen Modus (wir glauben, dass er funktioniert, prüfen es aber noch), in dem PP-Direktiven trotz willkürlicher Platzierung geparst werden können. Sie müssen sich immer noch um PP-Direktiven kümmern, die sich auf den Funktionsnamen auswirken. Aber diese beiden Modi erlauben es, viele C-Programme zu manipulieren, ohne den Präprozessor richtig oder überhaupt konfigurieren zu müssen.
Ich bin sicher, Sie können Clang so konfigurieren, dass es diese Zeilennummer extrahiert. AFAIK, es kann dies nur durch eine vollständige Vorverarbeitung tun. Clang wurde für solche Aufgaben entwickelt, aber hauptsächlich nur für C und C++.
Sie können dies wahrscheinlich mit GCC tun, aber GCC wurde nicht entwickelt, um hilfreich zu sein, daher ist der Aufwand dafür wahrscheinlich viel größer, als Sie erwarten würden.
Das EDG-Frontend kann C parsen, und ich bin sicher, dass Sie etwas Ähnliches damit machen, nachdem Sie die Präprozessordeklarationen erweitert haben.
Ich habe nicht viel Erfahrung mit den letzten 3, obwohl ich ihre Entwicklung buchstäblich Jahrzehnte lang verfolgt habe.
Nikolaus Raul
Gilles 'SO- hör auf, böse zu sein'
Ira Baxter