¿Hay alguna herramienta que pueda usar para averiguar el nombre de la función a la que pertenece un número de línea fuente específico?
Archivo de ejemplo:
static enum foo bar(int c)
{
if (c < 30)
return B1;
else
return B2;
}
static enum foo somethingelse(void)
{
return B3;
}
Para la línea 4, return B1;
la respuesta debería ser bar
.
Uso la sintaxis fuente C99 . El código fuente solo se puede compilar con GCC debido a sus dependencias.
C99 es una especificación para C. Ansi C sería C89. Pero hay, por ejemplo, cosas como K&R C, bastante importantes cuando se trata de analizar el archivo fuente para encontrar los nombres de las funciones.
La pregunta se cerró como fuera de tema en SO .
Nuestro kit de herramientas de reingeniería de software DMS con su C Front End podría usarse fácilmente para hacer esto.
DMS analiza y crea AST para un idioma definido para él. El extremo frontal de C define una variedad de dialectos de C para DMS, incluido C99. El resultado de aplicar C Front-end con DMS a un archivo C (completo con directivas/expansión de preprocesador, etc.) es un AST con cada nodo marcado en cuanto a su tipo de regla gramatical, con archivo fuente, línea y columna.
Dado un árbol de este tipo, se puede usar la interfaz AST de DMS para comenzar en la raíz, recorrer el árbol hasta encontrar un nodo con el número de línea 4. Bajo la suposición de que está dentro de una función (puede que no lo esté), puede subir fácilmente por el árbol hasta un nodo que es una declaración de función, y luego bajar un nodo hasta la identificación de la función, y luego imprimir la cadena asociada con ese nodo .
El código para lograr con DMS se ve así:
(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 utiliza un lenguaje de programación paralelo estilo lisp-syntax llamado PARLANSE para su lenguaje de metaprogramación. Creo que lo que hace lo anterior es bastante claro. He dejado de lado toda la comprobación de errores (aunque las excepciones de PARLANSE harán la mayor parte por el programador) por motivos explicativos.
DMS es único en el sentido de que no necesariamente tiene que expandir todas las directivas del preprocesador para analizar el texto. El extremo frontal C tiene un modo en el que las directivas PP "bien estructuradas" simplemente se analizan y retienen en el árbol; no puede manejar condicionales PP que abarquen no terminales C. Todavía puede encontrar el nombre de la función de la misma manera, pero es posible que deba preocuparse de que el identificador que se encuentra en la declaración de la función sea en realidad una macro o que esté envuelto en un condicional. El frente C tiene otro modo experimental (creemos que funciona, pero aún lo estamos comprobando) en el que las directivas PP se pueden analizar a pesar de la ubicación arbitraria. Aún debe preocuparse por las directivas PP que afectan el nombre de la función. Pero estos dos modos permiten manipular muchos programas C sin tener que configurar el preprocesador correctamente o sin tener que configurarlo.
Estoy seguro de que puede configurar Clang para hacer esta extracción de número de línea; AFAIK, solo puede hacer esto haciendo un preprocesamiento completo. Clang está diseñado para usarse en tareas como esta, pero principalmente solo para C y C++.
Probablemente puedas hacer esto con GCC, pero GCC no fue diseñado para ser útil, por lo que el esfuerzo para hacer esto probablemente sea mucho más de lo que esperas.
El front-end de EDG puede analizar C, y estoy seguro de que hará algo similar con él después de expandir las declaraciones del preprocesador.
No tengo mucha experiencia con los últimos 3, aunque he estado siguiendo su evolución literalmente durante décadas.
Nicolás Raúl
Gilles 'SO- deja de ser malvado'
Ira Baxter