Skip to content

Linux Attitude

Le libre est un état d'esprit

Archive

Tag: Lecture de code

Niveau :      

Savoir relire le code d'un autre est indispensable. Et ce pour plusieurs raisons, soit parce que vous voulez vous mettre à travailler sur un projet existant, soit parce que vous voulez simplement fournir un patch pour un code qu'on vous a fourni (probablement open source). Nous allons donc voir de quoi il s'agit, puis mettre en pratique sur apache.

Pour vous lancer dans l'aventure, il peut vous être utile de savoir utiliser ctags ou etags. De plus, connaître des techniques de lecture rapide vous permettra d'aller plus vite.

Plantons le décor, nous voulons faire un patch à apache 2.2 pour permettre d'ajouter dans les logs les durées de récupération de données par mod_proxy. Récupérons le code source et partons de ce qu'on sait (et n'oublions pas de le dupliquer pour nous simplifier la création de patch par la suite).

$ cp -a apache2-2.2.6 apache2-2.2.6.old
$ cd apache2-2.2.6
$ find . -type f | grep "c$" | xargs ctags

On sait qu'actuellement, grâce à mod_log_config, on peut logguer les durées individuelles des requêtes. Le code source semble divisé logiquement, nous allons donc lire modules/loggers/mod_log_config.c. Parcourons-le rapidement, on constate un certain nombre de fonctions log_*, probablement pour écrire dans les logs. Étant donné la façon dont elles sont appelées, il doit y avoir une référence dans un tableau quelque part. On la trouve en fin de fichier, ainsi que la fonction qui nous intéresse : log_request_duration_microseconds.

Lisons-la :

$ vi -t log_request_duration_microseconds

Deux choses intéressantes :

  • apr_time_now() -> au vu du nom et de la précision, ça doit donner la date et l'heure en microsecondes. Donc on sait comment on va calculer notre durée.
  • r->request_time et request_rec *r -> on en déduit qu'il existe une structure par requête dans laquelle on pourra stocker les dates de début et de fin.

Cherchons maintenant où appeler ces fonctions pour calculer les durées. Nous allons donc lire ./modules/proxy/mod_proxy.c. On le parcourt en largeur et on constate que :

  • C'est plutôt bien commenté
  • Les noms de fonction ont un sens
  • La majorité des fonctions s'appelle proxy_*

continue reading...

Niveau :      
Résumé : ctags && etags

J'imagine qu'il vous arrive de lire le code d'un autre, ou même de lire le votre, et de chercher des fonctions précises. Si vous faites avec grep, vous perdez du temps a différencier les appels des déclarations. Si vous avez un vrai environnement de développement, alors vous disposez déjà de la fonction et vous avez raison.

Bon, maintenant supposons que vous n'ayez que des moyens ultra-sophistiqués à votre disposition, emacs ou vi.

Il existe deux commandes (qui en fait sont les mêmes) pour générer un fichier de tag qui sera lu par emacs ou vi pour retrouver instantanément ou est définie une fonction. Ces commandes sont etags pour emacs et ctags pour vi, avec presque les mêmes arguments. Elle comprennent toutes les 2 un très grand nombre de langages différents (etags --help pour la liste):

Pour indexer des fichiers :

$ ctags fichier1.c fchier2.h 
$ etags fichier1.c fchier2.h 

ctags génère un fichier tags alors que etags génère un fichier TAGS. Attention, les options par défaut de etags et de ctags ne sont pas les mêmes.

Avec vi, vous pouvez ouvrir directement le fichier contenant la définition de la fonction main en utilisant l'option suivante :

$ vi -t main

Pour utiliser le fichier de tags dans un éditeur déjà ouvert, vous avez plusieurs raccourcis.

Pour indexer tout un projet, utilisez une commande du style (à adapter selon le langage) :

$ find . -type f  -name '*.c' -o -name '*.h' | xargs etags

Enfin un certain nombre d'options peut vous intéresser, pour cela je vous conseille la lecture de man etags. En particulier -d -g -m -t et -T