2009-01-26 22 views
4

J'ai une collection de code C hérité que je suis en train de refactoriser pour séparer le code de calcul C de l'interface graphique. Ceci est compliqué par le code de noyau mathématique fortement récursif étant K & déclarations de style R. J'ai déjà abandonné une tentative de les convertir en déclarations ANSI en raison de l'utilisation imbriquée des paramètres de la fonction (ne pouvait pas obtenir ces 4 dernières erreurs de compilation).Fusion de C Callergraph avec Doxygen ou détermination de l'union de tous les appels

J'ai besoin de déplacer certains fichiers dans une pure DLL et de déterminer l'interface minimale à rendre public, ce qui va nécessiter l'écriture de fonctions wrapper pour publier une interface typée.

J'ai annoté les fichiers source clés avec le balisage Doxygen @callergraph afin que des graphiques informatifs soient générés pour les fonctions individuelles. Ce que je voudrais faire au-delà est de fusionner ces graphes pour pouvoir déterminer la limite la plus étroite des fonctions exposées au monde extérieur.

Les fichiers d'en-tête d'origine ne servent à rien - ils exposent tout comme des fonctions C non typées.

Il existe des centaines de fonctions, ce qui rend l'inspection des callergraphes générés très simple. J'envisage d'écrire une sorte d'outil de fusion DOT - définir DOT_CLEANUP = NO permet à Doxygen de laisser les fichiers DOT intermédiaires là plutôt que de simplement conserver les fichiers png qu'ils ont générés. Je ne suis pas obsédé par ce qui est une solution graphique - je serais très heureux si quelqu'un pouvait suggérer un outil d'analyse alternative (gratuit ou relativement bon marché) ou une technique utilisant la sortie XML de Doxygen pour atteindre le même objectif.

A callergraph amalgamé au niveau du fichier a un certain attrait pour la documentation client plutôt qu'une simple liste :-)

+0

Pourriez-vous s'il vous plaît coller quelques exemples d'entrée (je crois savoir qu'il ya DOT et les formats XML)? –

+0

Malheureusement, non sans l'approbation du client et je manque probablement de temps libre aux États-Unis dans environ 24 heures. J'ai résolu le problème d'une manière différente - le code algorithmique n'est plus publié en tant qu'interface. Au lieu de cela, la logique métier de l'interface graphique est déplacée dans la même DLL et le seul couplage externe est les commandes et les notifications de propriété, une préoccupation beaucoup plus étroite! –

+0

Pourriez-vous ... coller des exemples anonymes? Le problème est intéressant comme "comment diviser un programme en deux d'une manière où la connexion est mince" –

Répondre

5

Dans votre Doxyfile, définissez

GENERATE_XML = YES 

et vous pouvez trouver votre graphe d'appel dans les fichiers XML. Pour chaque fonction marquée avec le callergraph, vous trouverez <referencedby> éléments dans la sortie que vous pouvez utiliser. Voici un exemple d'un de mes fichiers C:

<memberdef kind="function" id="spfs_8c_1a3" 
      prot="public" static="yes" const="no" explicit="no" 
      inline="no" virt="non-virtual"> 
    <type>svn_error_t *</type> 
    <definition>svn_error_t * init_apr</definition> 
    <argsstring>(apr_pool_t **ppool, int *argc, char const *const **argv)</argsstring> 
    <name>init_apr</name> 
    <!-- param and description elements clipped for brevity ... --> 
    <location file="src/spfs.c" line="26" bodystart="101" bodyend="120"/> 
    <referencedby refid="spfs_8c_1a13" compoundref="spfs_8c" 
        startline="45" endline="94">main</referencedby> 
    </memberdef> 

Ainsi, pour chaque paire memberdef/referencedby, vous avez une relation de l'appelant-callee, que vous pouvez saisir via XSLT:

<?xml version="1.0" encoding="utf-8"?> 

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output method="text"/> 

    <xsl:template match="/"> 
     <xsl:apply-templates select="//memberdef[@kind eq 'function']"/> 
    </xsl:template> 

    <xsl:template match="memberdef"> 
     <xsl:variable name="function-name" 
         select="concat(definition, argsstring)"/> 
     <xsl:for-each select="referencedby"> 
      <xsl:value-of select="concat(./text(), ' calls ', $function-name, '&#xA;')"/> 
     </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

Ce qui vous donne une ligne par l'appelant comme celui-ci-callee:

main calls svn_error_t * init_apr(apr_pool_t **ppool, int *argc, char const *const **argv) 

Vous aurez envie de modifier que XSLT puis la partition qui a dirigé le graphique de la manière qui coupe à travers les arêtes plus petit nombre.Woo hoo, un problème NP-complet! Heureusement, il y a beaucoup de papiers sur le sujet, certains sont ici: http://www.sandia.gov/~bahendr/partitioning.html

0

Vous pouvez utiliser Toolworks Scientific pour voir votre graphique d'appel système.

Si vous souhaitez automatiser l'analyse et la découpe, vous pouvez considérer la boîte à outils de réorganisation du logiciel DMS. Il peut calculer des graphes d'appels complets pour C (avec analyse point-à-point pour les pointeurs de fonction), et a été prouvé pour des systèmes de 35 millions de lignes de code. Il produira des fichiers DOT complets du système à inspecter; ils sont assez gros mais vous pouvez choisir des sous-ensembles à regarder. Voir flow analysis and call graphs.

1

J'avais une exigence similaire. A écrit un script perl pour fusionner un ensemble de fichiers de points dans un seul fichier de points.

https://github.com/bharanis/scripts/blob/master/doxygen_dot_merge.pl

fusionner plusieurs fichiers générés doxygen points. Ceci est utile pour générer une carte d'appel pour un fichier ou un groupe de fichiers.

1) Cette commande doit être exécutée depuis l'extérieur du répertoire html où doxygen place tous les fichiers html, point et map.

2) Cette commande suppose structure de répertoire plat utilisé dans doxygen CREATE_SUBDIRS = NO

3) doxygen préfixe le nom du fichier source pour le nom des fichiers de points de sortie. Un fichier de points est généré par fonction

4) fournir la liste des fichiers de points générés par doxygen à fusionner. par exemple:

./doxydotmerge.pl `ls html/ssd_*_8c*_cgraph.dot | grep -v test | grep -v buf`