Subversion Repositories doc-tools

Compare Revisions

Ignore whitespace Rev 2 → Rev 3

/trunk/LISEZMOI.txt
New file
0,0 → 1,25
Ce dépôt contient des outils destinés à faciliter la documentation
des sources.
 
=Description des fichiers=
 
==php_autodoc_fornd.pl==
 
Crée une "coquille documentaire" pour Natural Docs dans les fichiers PHP.
 
Ce script est en partie autodocumenté. La syntaxe s'obtient en tapant le
nom du script sans paramètre.
 
==Topics.txt==
 
Fichier de topics Naturals Docs lié au projet et venant enrichir le
vocabluaire de base de Natural Docs avec les topics :
* Inclusion
* Language
* Module
* Repertoire
* Svn info
 
Il est nécessaire de mettre ce fichier dans le répertoire du "projet"
de documentation sous Natural Docs pour tirer pleinement parti du
script php_autodoc_fornd.pl.
Property changes:
Added: svn:keywords
+ Id Author Revision
/trunk/php_autodoc_fornd.pl
New file
0,0 → 1,693
#!/usr/bin/perl
 
#
# File: php_autodoc_fornd.pl
# Crée une "coquille documentaire" pour Natural Docs dans les fichiers PHP.
#
# Bien entendu, cela doit être ensuite complété à la main
#
# Version : 0.5.1
#
# Language: Perl
#
# Svn info: Résumé
# $Id$
#
# Svn info: Révision
# $Revision$
#
# Svn info: Auteur de la révision
# $Author$
#
 
#
# variable: $php_name
# valeur : PHP
#
# variable: $js_name
# valeur : javascript
#
# variable: $perl_name
# valeur : Perl
#
$php_name='PHP';
$js_name='javascript';
$perl_name='Perl';
 
#use strict;
 
# Pour la gestion des options
use Getopt::Std;
# Pour la copie de fichiers
use File::Copy;
 
#
# Function: print_syntaxe
#
# Affiche la syntaxe d'utilisation
#
# Retourne:
#
# rien
#
sub print_syntaxe {
# Chemin complet du script Perl
my $NomScript = $0;
# Nom du script seulement
$NomScript =~ s!.*(/|\\)!!;
print <<_FINSY_;
Syntaxe :
$NomScript -i nom_fichier [-option1 [parametres]] [-option2 ...]
$NomScript -h
Description des options :
-i nom_fichier
nom_fichier nom du (des) fichier(s)) d\'input (accepte les jokers)
-x fichiers_exclus
fichiers_exclus est un masque de fichiers exclus du traitement
note : les fichiers .bak sont toujours exclus (option -x inutile pour eux)
-d {n} n niveau de déboguage (1 seulement pour l\'instant)
-e (except) est suivi de la liste des fonctions exclues du traitement
-o (only) est suivi de la liste des seules fonctions incluses
dans le traitement
-e et -o sont incompatibles ; -o est prioritaire
les mots de la liste sont separes par des virgules, points-virgules
ou des espaces (dès que la liste contient des espaces, elle doit être
entre doubles quotes).
Les fonctions existantes actuellement sont :
- constant
- en_tete
- function (tous langages confondus)
- js_func (fonctions javascript)
- include
-h afficher cette aide
Exemples :
$NomScript -i *.php -x *.old
$NomScript -i *.php -x *_ND.php
$NomScript -i *.php -e include,js_func,constant
$NomScript -i *.php -o "en_tete function"
_FINSY_
exit;
}
 
#
# Function: output_en_tete
#
# Ajoute les généralités concernant le fichier
#
# Parameters:
# $O : Handle du fichier de sortie
#
# $entree : Nom du fichier en entrée
#
# Retourne:
#
# rien
#
sub output_en_tete {
# Si désactivé retour
if ($feature{'en_tete'}==0) {
return;
}
 
# Recup des paramètres
my ($O, $entree) = @_;
# Séparer répertoire et nom de fichier
if ($entree=~m!^(.*)(\\|/)(.*)$!) {
$repertoire=$1;
# Si répertoire est '.' alors on vide pour l'affichage
#if ($repertoire eq '.') {
# $repertoire='';
# }
$fichier=$3;
}
else {
$repertoire='.';
$fichier=$entree;
}
# En tête de fichier pour Natural Docs
if ($fichier=~/\.php3?$/) {
$langage = "\n language: $php_name\n";
}
elsif ($fichier=~/\.p(l|m)$/) {
$langage = "\n language: $perl_name\n";
}
else {
$langage = "\n";
}
$EnTete = <<_FIN_;
<?
/*
file: $fichier
Rôle du script...
Repertoire: $repertoire
$repertoire/
$langage
svn info: Résumé
\$Id\$
 
Svn info: Révision
\$Revision\$
 
Svn info: Auteur de la révision
\$Author\$
*/
_FIN_
$EnTete.="?>";
print $O $EnTete;
}
#
# Function: output_parameters
#
# Ajoute les paramètres de la fonction (un par
# ligne, séparés par une ligne vide)
#
# Retourne:
#
# rien
#
sub output_parameters {
my ($param) = @_;
print O "\n Parameters:\n";
# Sort les paramètres un par un pour commentaires manuels futurs
while ($param=~s/^(\$[a-zA-Z_0-9]+)( *, *(.*))?$/$3/) {
print O " $1 :\n\n";
}
}
#
# Function: output_function
#
# Ajoute le commentaire de fonction
#
# Retourne:
#
# rien
#
sub output_function {
# Si désactivé retour quel que soit le langage en cours
if ($feature{'function'}==0) {
return;
}
# Si désactivé pour javascript et javascript en cours, retour
if ( ($language_context eq $js_name) and ($feature{'js_func'}==0) ) {
return;
}
 
my ($func_name,$param_liste)=@_;
print O "/*\n Function: $func_name\n";
print O "\n Language:\n$language_context\n";
output_parameters($param_liste);
print O "\n*/\n";
}
#
# Function: output_constant
#
# Ajoute la constante dont le nom et la valeur
# ont été passés en paramètres
#
# Parameters:
# $ConstName : Nom de la constante
#
# $ConstValue : Valeur de la constante
#
# Retourne:
#
# rien
#
sub output_constant {
# Si désactivé retour
if ($feature{'constant'}==0) {
return;
}
 
my ($ConstName,$ConstValue) = @_;
print O "/*\n Constant: $ConstName\n\n $ConstValue\n";
print O "\n Signification: ...\n*/\n";
}
 
#
# Function: output_include
#
# Ajoute la déclaration d'inclusion passée en paramètre
#
# Parameters:
# $IncludeWord : commande d'inclusion
#
# $IncludeFile : Fichier inclus (peut être une formule)
#
# Retourne:
#
# rien
#
sub output_include {
# Si désactivé retour
if ($feature{'include'}==0) {
return;
}
 
my ($IncludeWord,$IncludeFile) = @_;
print O "/*\n Inclusion: $IncludeWord\n\n";
print O " $IncludeFile\n*/\n";
}
#
# Function: try_language_context
#
# Essai de repérer le langage de programmation courant.
# Suppose l'absence de changement au sein d'une ligne ce qui est une
# simplification abusive, on le sait.
#
# Toutes les regexp de ce script sont de vraies passoires laissant
# délibérément de côté tout un tas de cas (par manque de temps par
# rapport aux enjeux)
#
# Modifie:
#
# Les variables globales $language_context et @language_context_stack
#
# Retourne:
#
# rien
#
sub try_language_context {
 
# Ignorer les courtes inclusions de PHP au sein du HTML
# ou du javascript
if (/^ *<\?(php)?.+\?>/) {
return;
}
# Début PHP ?
if (/^ *<\?(php)?/i) {
push(@language_context_stack, $language_context);
$language_context=$php_name;
if ($debug_level eq 1) {
print "$line_number:dp:#$_ current : $language_context\n";
print @language_context_stack; print "\n";
}
}
# javascript sur une seule ligne -> on ne change rien
if (m:^ *<(!--)?SCRIPT +LANGUAGE=.?javascript.?>.*</script(--)?>:i) {
# On ne fait rien en l'état actuel du développement
}
# Sinon début javascript
else {
if (/^ *<(!--)?SCRIPT +LANGUAGE=.?javascript.?>/i) {
push(@language_context_stack, $language_context);
$language_context=$js_name;
if ($debug_level eq 1) {
print "$line_number:dj:#$_ current : $language_context\n";
print @language_context_stack; print "\n";
}
return;
}
}
# Fin javascript ?
if (m:</script(--)?>:i) {
$language_context=pop(@language_context_stack);
if ($debug_level eq 1) {
print "$line_number:fj:#$_ current : $language_context\n";
print @language_context_stack; print "\n";
}
}
# Fin PHP ? (Hum regexp bidon on peut avoir un "<" qui ne soit pas
# un "<?")
if ((/\?>.*$/) and ($language_context eq $php_name)) {
my $ligne=$_;
while ($ligne=~/\?>.*<\?/) {
$ligne=~s/^.*\?>.*<\?(.*)$/$1/;
}
if ($ligne=~/\?>.*$/) {
$language_context=pop(@language_context_stack);
if ($debug_level eq 1) {
print "$line_number:fp:#$_ current : $language_context\n";
print @language_context_stack; print "\n";
}
}
}
}
#
# Function: try_to_skip_svnid
#
# Efface le mot-clé Id de subversion s'il existe déjà dans le fichier
#
# Retourne:
#
# Un booléen
#
# - true : il n'y plus rien d'autre sur la ligne qu'un signe de début
# de commentaire ligne et des espaces
# - il reste des éléments d'information sur la ligne
#
sub try_to_skip_svnid {
if ($_=~/\$Id.*\$/) {
$_=~s!^(.*?)\$Id[^\$]*\$(.*)$!$1$2!;
if ($_=~/^(\/\/|#) *$/) {return 1;}
}
return 0;
}
#
# Function: try_function_begin
#
# Teste si une fonction débute et si oui traite en conséquence
#
# Parameters:
#
# aucun
#
# Retourne:
#
# vrai (1) si début de fonction trouvé et faux (0) sinon
#
sub try_function_begin {
if ($_=~/^ *function *([a-zA-Z_0-9]+)\(([^)]*)(.*)$/i) {
output_function($1,$2);
print O $_;
return 1;
}
else {
return 0;
}
}
#
# Function: try_constant_define
#
# Teste si une définition de constante est sur la ligne.
# Si oui, traite en conséquence.
#
# Parameters:
#
# aucun
#
# Retourne:
#
# vrai (1) si définition de constante trouvée et faux (0) sinon
#
sub try_constant_define {
# Attention aux références arrières \1 et \3 qu permettent de s'assurer
# que la paire de quote (simple ou double) est cohérente
if ($_=~/^ *define *\( *(['"])([a-zA-Z_0-9]+)\1 *, *(["']?)(.*?)\3 *\)/) {
output_constant($2,$4);
print O $_;
return 1;
}
else {
return 0;
}
}
#
# Function: try_include_def
#
# Teste si une inclusion de fichier est sur la ligne.
# Si oui, traite en conséquence.
#
# Parameters:
#
# aucun
#
# Retourne:
#
# vrai (1) si définition de constante trouvée et faux (0) sinon
#
sub try_include_def {
# Trouver le mot-clé
my $regexp='^ *(include|require)(_once)? *\\(';
 
# Trouver la succession d'éléments constants et littéraux
# (pas traité éléments variables : à faire)
$regexp.="((($TYPE2_FILE_PATTERN|$LAXIST_CONST_PATTERN)\\.?)+)";
# Fermer la regexp par la reconnaissance de la fin de parenthèse
$regexp.=' *\\)';
if ($_=~/$regexp/) {
output_include($1.$2,$3);
print O $_;
return 1;
}
else {
return 0;
}
}
#
# Function: process_one_file
#
# Traite un fichier en entrée en lui ajoutant les commentaires
#
# Parameters:
# $rep : chemin de travail (sans le slash final)
#
# $entree : Nom du fichier
#
# Retourne:
#
# rien
#
sub process_one_file {
$line_number=0;
# Récupération chemin de tavail et nom de fichier
my ($rep,$entree) = @_;
# Initialisation de variable
my $langage = "";
# Calcul nom du fichier de sortie selon qu'il ait une extension ou pas
if ($entree=~m/^(.*)\.(.*)$/) {
$sortie=$rep."/$1_ND.$2";
}
else {
$sortie=$rep."/$1_ND";
}
# Calcul du chemin du fichier d'entrée
$inputFile="$rep/$entree";
# Calcul du fichier de backup
my $backupFile="ND_backup_dir/$inputFile";
$backupFile.='.bak';
# Affichage écran du travail en cours
print "Traitement de $entree vers $sortie\n";
# Faire copie de sauvegarde
copy($inputFile,$backupFile);
 
# Ouvrir les fichiers d'entrée et de sortie
open F,"$inputFile";
open O,">$sortie";
# Eliminer l'éventuel "./" du début de chemin pour les affichages
$inputFile=~s/^(.\/)?(.*)/$2/;
# Ajouter l'en-tête fichier pour Natural Docs
output_en_tete(O, $inputFile);
 
# Traitement du fichier proprement dit
while (<F>) {
$line_number+=1;
#print "$_\n";
# Mettre à jour le contexte de langage
try_language_context();
# Enlever le Id subversion si présent (car ajouté dans en-tête)
if (try_to_skip_svnid()) {
next;
}
# Trouver, traiter les fonctions
if (try_function_begin()) {
next;
}
# Trouver, traiter les définition de constantes
if (try_constant_define()) {
next;
}
# Trouver, traiter les inclusions
if (try_include_def()) {
next;
}
# Ecrit la ligne courante dans le fichier de sortie
print O $_;
}
close F;
close O;
}
#
# Function: process_many_files
#
# Traite de multiples fichiers en entrée en leur ajoutant les commentaires
#
# Parameters:
# $masque : répertoire de travail et masque des fichiers à traiter
#
# $x_masque : masque de fichiers à exclure
# (les fichier .bak sont toujours exclus quoiqu'il arrive)
#
# Retourne:
#
# rien
#
sub process_many_files {
# Récupérer les masques de fichiers à inclure et à exclure
my ($masque,$x_masque) = @_;
 
# Déterminer le répertoire de travail
my $repertoire = $masque;
# Si ni / ni \ alors c'est le répertoire courant
if ($repertoire!~s!(.*)(/|\\)(.*)!$1!) {
$repertoire=".";
}
else {
# sinon récupérer juste le masque de fichiers
$masque=~s!(.*)(/|\\)(.*)!$3!;
}
# print "\nRepertoire : $repertoire\n"; # debug
# Transformer les masques de nom de fichiers en regexp
# Protéger les "."
$masque=~s/\./\\./g;
$x_masque=~s/\./\\./g;
# Ajouter un "." devant les quantificateurs "*" et "?"
$masque=~s/\*/.*/g;
$masque=~s/\?/.?/g;
$x_masque=~s/\*/.*/g;
$x_masque=~s/\?/.?/g;
my $enregistrement;
my $nom_chemin;
local *DH;
 
unless (opendir(DH, $repertoire)) {
return;
}
while (defined ($enregistrement = readdir(DH))) {
next if($enregistrement eq "." or $enregistrement eq "..");
# Passer les .bak
next if($enregistrement=~/\.bak$/);
# Passer les éléments exclus
next if($enregistrement=~/^$x_masque$/);
$nom_chemin = $repertoire."/".$enregistrement;
if( -d $nom_chemin) {
# print "\n$nom_chemin est un repertoire -> pas de traitement recursif\n";
}
else {
if ($enregistrement=~/^$masque$/) {
#print "\n$nom_chemin -> en cours de traitement";
process_one_file($repertoire,$enregistrement);
}
}
# Plus tard pour le traitement récusrsif
# push(@tous, $HTML_enregistrement);
# rechercher($nom_chemin) if(-d $nom_chemin);
}
closedir(DH);
}
 
#
# Main part of script
#
 
# Récupérer les options de la ligne de commande
getopts( "i:x:e:o:d:s:h", \%opts) or print_syntaxe();
print_syntaxe() if defined($opt{h});
 
# Initialisation variables
$line_number=0;
$language_context='unknown';
@language_context_stack = ('stackbase_');
$TYPE2_FILE_PATTERN="('[A-Za-z0-9_.\-]+'|\"[A-Za-z0-9_.\-]+\")";
$CONST_PATTERN='[A-Z0-9_]+';
$LAXIST_CONST_PATTERN='[a-zA-Z0-9_]+';
 
# traiter les options de la ligne de commande
 
# récupérer le(s) nom(s) de(s) fichier(s) à traiter et de ceux à exclure
my $inputfile = $opts{i};
my $exclude_files = $opts{x};
 
# récupérer les options de travail
my $except_features = $opts{e};
my $only_features = $opts{o};
$debug_level = $opts{d};
 
# établir la liste des fonctionnalités actives
%feature = (
en_tete => 1,
function => 1,
js_func => 1,
constant => 1,
include => 1,
exec => 0
);
 
# traiter l'option -e (liste de fonctionnalités exclues du traitement)
my @exception_liste = split(/ *[ ,;] */,$except_features);
foreach my $val (@exception_liste) {
$feature{$val}=0;
}
# traiter l'option -o (traiter seulement les fonctionnalités listées)
if ($only_features ne "") {
# désactiver toutes les fontionnalités
foreach my $key (keys %feature) {
$feature{$key}=0;
}
# réactiver uniquement cells de la liste fournie
my @restricted_liste = split(/ *[ ,;] */,$only_features);
foreach my $val (@restricted_liste) {
$feature{$val}=1;
}
}
# Si nom de fichier vide afficher syntaxe
if ($inputfile eq "") {
print_syntaxe();
}
# Tester le paramètre input (-i)
if ($inputfile=~/\*|\?/) {
process_many_files($inputfile,$exclude_files);
}
else {
if (-e $inputfile) {
# Attention BUG en perspective - PROVISOIRE (pas le temps)
# Il faut d'abord séparer chemin du nom de fichier
process_one_file(".",$inputfile);
}
else {
print "\n$inputfile n'existe pas !\n";
print_syntaxe();
}
}
 
if ($debug_level eq 1) {
print @language_context_stack;
}
 
# Fin du script
Property changes:
Added: svn:keywords
+ Id Author Revision