Mkd (Extracteur de documents)/Ajouter des modules
Pourquoi ajouter des modules ?
modifierIl est aisé d'extraire des fichiers, des lignes complètes, contenant une chaîne déterminée de caractères. Voir la commande Grep et Awk.
Les fichiers de textes sont de plus en plus compliqués, il est difficile d’extraire des blocs de commentaires débarrassés des signes de balisage; d'où l'intérêt de créer des modules adaptés aux langages de programmation ou d'éditions utilisant des balises; Postscript, SGML et autres méta langages; Xml, Html, ... .
Comment ajouter un module ?
modifierQuel langage de programmation ?
modifierTous les langages de programmation peuvent convenir à condition qu'ils soient compilable avec gcc pour produire des fichiers objets liables entre eux (linkables)
Définir le module
modifierIl faut déterminer quel est le style de commentaire à extraire. Repérer éventuellement un fichier similaire existant. Il existe en standard des modules d' extraction de lignes et des modules d' extraction de blocs.
Certains fichiers ont des commentaires plus compliqués comme : <!-- texte --> avec quatre caractères voire plus. Dans des cas plus complexes il pourrait être préférable de repérer des chaînes de caractères plutôt que des caractères ASCII. Ceci aurait l'avantage d'être adapté aux caractères asiatiques en UTF 8, 16, ou 32 avec des chaînes de caractères données paramètres d'entrée.
Créer le pseudo-code
modifierLe pseudo code que nous utilisons est un commentaire qui va décrire ce que l'on fait et ce que l'on doit obtenir, ce qu'il faut faire dans certaines conditions comme créer une boucle jusqu'à ce que l'on obtienne ce que l'on cherche.
Il y a de nombreux ouvrages qui décrivent les manières de programmer. Le plus célèbre est sans aucun doute la méthode Merise pour la programmation impérative.
Il est préférable d'écrire le pseudo code avant d'écrire les lignes de codes.
//O Ceci est un pseudo code style C++
std::cout << "Unable to open file "<< fprj << std::endl; // message to stdout
Examinez les fichiers à disposition pour avoir une meilleure idée de l'utilisation du pseudo code.
Intégration des lignes de codes
modifierLangue de programmation et internationalisation
modifierNous utilisons gettext pour adapter les messages aux différentes langues parlées.
Pour que l'on puisse facilement traduire les messages il convient de les écrire en anglais US (ASCII).
Les divers caractères accentués des langues européennes ne sont pas si faciles à traduire.
Compilation de l'unité de test
modifierLes options du fichier version.h
modifierLe fichier d'entête version.h est utilisé pour compiler la série d'applications dérivées de la commande mkd.
La vérification des options est indispensable avant toute compilation.
/*
* © mkd, version 2009.12 et ultérieures
*
* Concédée sous licence EUPL, version 1.1 ou – dès leur approbation par la
* Commission européenne - versions ultérieures de l’EUPL (la «Licence»).
* Vous ne pouvez utiliser la présente œuvre que conformément à la Licence.
* Vous pouvez obtenir une copie de la Licence à l’adresse suivante:
*
* http://ec.europa.eu/idabc/eupl5
*
* Sauf obligation légale ou contractuelle écrite, le logiciel distribué sous
* la Licence est distribué «en l’état»,
* SANS GARANTIES OU CONDITIONS QUELLES QU’ELLES SOIENT, expresses ou implicites.
* Consultez la Licence pour les autorisations et les restrictions linguistiques
* spécifiques relevant de la Licence.
*/
/*P
NOM DU FICHIER: version.h
PROJET INITIAL: mkd console linux & MSDOS
DOSSIER INITIAL : mkdoc3.12 Centre d’Électronique de Montpellier
PROGRAMMEUR: JPL
DATE: 18/12/2009
MODIFICATIONS:
le: 09/01/2011 par JPL objet: Ajouté l'option de compilation pour MSDEV41
le: 10/01/2012 par JPL objet: Ajouté la définition std_C pour compilation UNIX STD
le: 25/03/2012 par Clara objet: internationalisation
le: 27/03/2012 par jpl objet: internationalisation en utf-8
le: 10/04/2013 par Cardabela: Modification mineure. Alignement des commentaires.
*/
// le: ../../.. par .............. objet de la modification ....
/**# MKD.C ############################*/ /*H*/
/*U UTILISATEURS */ /*H*/
/*O ORGANIGRAMME */ /*H*/
/*S STRUCTURE */ /*H*/
/*T TESTS */ /*H*/
/*P PROGRAMMEUR */ /*H*/
/*www remarques particulières */ /*H*/
/**####################################*/ /*H*/
// define VERSION line 173
#define UNIX /*O UNIX version */ /* Delete this line for PC version */
//#define GTKMM /*O Version fenêtrée avec gtkmm pour mkdcppw uniquement */
#ifndef UNIX /*H*/
#define PC /*O version de compilation PC */ /*H*/
/*#define PC_ONLY*/ /*H find_ ne reconnaît pas: .s .f .p .sh .csh */
#define NL "\r\n" /*H*/
//#define VC10 /*O Microsoft Visual C 10.- */
#define MSDEV41
#endif /*H*/
/*H*/
#ifdef UNIX /*H*/
#define UNIX_ONLY /*H find_ ne reconnaît pas: .BAS .PAS .FOR ... */
#define NL "\n" /*H*/
#endif /*H*/
/*H*/
/*H #D *************************************************************************************/
/*H *** #Define OPTIONS DE COMPILATION: options par défaut, redéfinissables: **************
(#D pour l'extraction des options de compilation en ligne avec l'option CD3='#') */
/*H****************** #Define 'l' (ligne) commence par #define en 1ère colonne : ***********/
#define CD1 '%' /*H #Define Option CD1 en 1ère colonne prend fin avec NL */
#define CD2 '-' /*H #Define Option CD2 en 1ère colonne prend fin avec NL */
#define CD3 '#' /*H #Define Option CD3 dans la ligne prend fin avec NL */
/*H #Define Option '%' commentaire postcript */
/*H #Define Option '#' commentaire shell ou pour Makefile voir option S
#D ( le commentaire se termine avec new_line ) */
/*H #Define Option '\'' commentaires Basic */
/*H #Define Option ';' commentaires assembleur */
/*H ***************** #Define Option 'p' (dans la page) #define en 1ère colonne : **********/
#define CD4 '\"' /*H #Define Option CD4 = " début de commentaire */
#define CD5 '\"' /*H #Define Option CD5 = " fin de commentaire */
/*H #Define **************************************************************/
#define FULL_LINE /*H #Define Option de compil. copier toute la ligne */
/*H #D *************************************************************************************/
/*U*** MKD ********************************************************************
*M name: mkd (make documentation)
*U (programme extracteur de documents, Manuel, Organigramme, Structure,
*U warnings, points de Test, notes pour la maintenance du Programmeur, etc... )
*M origine: Centre d’Électronique de Montpellier
*M Univ. Sciences & Techniques du Languedoc
*M 34060 MONTPELLIER CEDEX
*P programmeur R3.12: JPLouyot, adr électronique: louyot@obelix.cnusc.fr
*P programme R3.12 pour systèmes UNIX mkdoc, et version PC IBM mkd.exe
*U
*U Ce programme range dans un fichier.doc par défaut, ou dans tout fichier
*U nommé en dernier paramètre:
*U avec les options l et p:( CD1,CD2,CD3,CD4,CD5, sont définis dans version.h )
*U -- la ligne COMMENÇANT par les caractères CD1 ou CD2 ou CD3 et suivis par
*U un des 5 caractères donnes en paramètre char_codes (avec option l).
*U -- la ligne CONTENANT le caractère défini par CD3 suivi par un des 5
*U caractères donnes en paramètre char_codes (avec option l).
*U -- les lignes CONTENANT et SUIVANT le caractère défini par CD4 et suivi par
*U un des 5 caractères donnes en paramètre char_codes (avec option p)
*U JUSQU’À la ligne qui contient le caractère CD5. Attention, si le caractère-
*U caractère CD5 est NL la ligne suivante sera ignorée.
*U
*U avec les options: A, B, C, F, P, et S:
*U le tri est effectue conformément a la définition des commentaires de
*U chaque langage, A:Assembleur, B:Basic, c:C, F:Fortran, P:Pascal, S:Shell
*U
*U avec char_code = '**' tous les commentaires correspondants aux langages ou
*U aux options l et p sélectionnés sont copies.
*U
*U syntaxe de la ligne de commande:
*U syntaxe pour pc IBM:
*U mkd [-ABCFPSajlnpstvw] char_codes [drive:]path_source [[drive:]path_target]
*M syntax for UNIX version:
*M mkdoc [-ABCFPSajlnpstvw] char_codes path_source [path_target]
*M
*M -- path_source : path source file (or project file: option j )
*M -- char_codes : all ASCII
*M -- options : -A Assembler source file or similar ( ; -> NL )
*M -B Basic source file or similar (REM or ' -> NL)
*M -C C source file, or similar (PROLOG) ( / * -> * / )
*M -F Fortran source file or similar (c,C or * -> NL)
*M -P Pascal source file ( {to}, (*to*) )
*M -S Shell files or similar ( # -> NL ' )
*M -a append target file
*M -f find langage source file (useful with project file)
*M -j if path_source is a project file only
*M -l line read line only
*M -n insert line number
*M -p page read text
*M -s screen view
*M -t comment only
*M -v verbose mode
*M -w overwrite target file
*M ( default option: overwrite switch off)
*M -- path_target : path target file
*M
*M examples for UNIX version:
*M ++++++++++++++++++++++++++
*M mkdoc -Csn '*S' mkdoc3.c verif.struct
*M mkdoc -Fst UM version.h /usr/local/docu/mkdoc.docu
*M mkdoc -Cst M version.h /usr/local/man/manl/mkdoc.l
*M mkdoc -lt '*UM' mkdoc3.c \*.manual with CD1='*' or CD2='*'
*M mkdoc -jv '**' mkd_docu.prj (for all comments, sources in prj file)
*M mkdoc -pjnv '**' mkd_docu.prj (for all strings, sources in prj file,
*M with CD4=CD5='\"')
*U exemples pour version PC:
*U +++++++++++++++++++++++++
*U mkd -Csn *SOn \mkdoc3.c vérif.str (char espace:' ' n'est pas valable)
*U mkd -Fst UM a:version.h c:\man\mkd.doc
*U mkd -Fst M a:version.h d:mkd.man
*U mkd -lt *UM mkdoc.c *.MAN (pour utilisateurs et manuel, with CD1='*', CD2='*')
*U mkd -jv ** file.prj (pour tous commentaires, sources dans le fichier projet)
*U or mkd -pjnv '**' mkd_docu.prj (for all strings, sources in .prj file,
*U with CD4=CD5='"')
*U
*U Pour l'ASSEMBLEUR utiliser ; avec l'option A
*U (ou l'option l avec CD3=';')
*U Pour le BASIC (ou BATCH) utiliser ' ou REM avec l'option B
*U (ou option l avec CD3='\'')
*U Pour le C et PROLOG utiliser / * et * / avec l'option C
*U Pour le FORTRAN utiliser C, c, ou * en 1ère colonne avec l'option F
*U ( ou option l avec CD1='c' CD2='C' CD3='*' )
*U Pour le PASCAL utiliser les accolades { et } ou (* et *)
*U ( ou option p avec CD4='{' et CD5='}' )
*U Pour le CSHELL utiliser # avec l'option S
*U ( ou option l avec CD3='#' cas fin de ligne = NL )
*U Pour les fichiers projet avec des sources UNIX: .s .c .i .f .r .p mélangés,
*U ou .ASM .C .FOR .PAS etc... sources PC, utiliser l'option f (find).
*U Pour les commentaires de fichiers POSCRIPT compiler avec CD3='%'
******************************************************************************/
/*H*/
#define VERSION "12.03" /*H*/
/*H*/
#define MAX 85 /*H longueur des buffers des path source et doc */
#define STX 0x2 /*H Start Text */
#include <stdio.h> /*H*/
/*H*/
#ifdef PC /*H*/
#include <conio.h> /*H*/
#include <process.h> /*H*/
#include <io.h> /*H*/
#endif /*H*/
#ifdef VC10 /*H Microsoft Visual C 10.- */
#define putch _putch /*H ISO C++ */
#define getch _getch /*H ISO C++ */
#define access _access /*H ISO C++ */
#endif /*H*/
/*H*/
#ifdef MSDEV41 /*H*/
//#define STD_C /*H SVr4, 4.3BSD, C89, C99.*/
#include <string.h> /*H*/
#endif /*H*/
/*H*/
#ifdef UNIX /*H*/
#define bool int
//#define STD_C /*H SVr4, 4.3BSD, C89, C99.*/
/*#define getch() getchar()*/
#define putch putchar /*H*/
#include <signal.h> /*H*/
#include <sys/file.h> /*H*/
#include <string.h> /*H*/
#endif /*H*/
La fonction maîtresse - main()
modifierLa fonction main doit ouvrir les fichiers source et cible et transmettre l'adresse de ces fichiers ouverts à la fonction à éprouver (tester).
Elle doit en retour, s'il y a lieu, d'afficher la valeur de retour de fonction à défaut de d'afficher un message correspondant à cette valeur de retour.
Il n'est pas interdit d'ouvrir "en dur" toujours les mêmes fichiers source et cible, cela dépend des tests demandés.
L'essentiel pour les tests unitaires est de répondre aux directives. Il peut cependant être nécessaire d'entrer des arguments comme n, s, t par exemple pour l'épreuve de la fonction cpp_() que nous prenons souvent en exemple.
#include "version.h"
// #include "" // entête du fichier à tester app.h si la fonction est indépendante comme cpp.c
// #include "" // fichier de la fonction app.i si la fonction doit être incluse
// Variables globales:
unsigned char A,B,C,F,P,S,a,f,j,l,n,p,s,t,v,w;
char codes[5] = {0,0,0,0,0};
//*O Début de la fontion main():
int main(int argc, char **argv)
{
//O Déclarations
int ret=0;
char fsrc[MAX]; /* Nom du fichier source */
char fdoc[MAX]; /* Nom du fichier cible */
FILE *pnfile; /* FICHIER A EXTRAIRE */
FILE *pfdoc; /* FICHIER A DOCUMENTER */
//O Pseudo code des instructions
.....
return ret;
}
//*O Fin de la fontion main()
Exemple complet avec mkdcpp (Éditeur ISO-8859-1)
mkdcpp.c
//O Programme de tests de la fonction cpp_()
#include "version.h"
#include "cpp.h"
// Variables globales
unsigned char n=0,s=0,t=0,v=0; /*P déclaration et initialisation des variables */
char codes[5] = {0,0,0,0,0}; /*P version qui copie les codes avec l'option t dans cpp_()
Il peut être nécessaire de modifier les lignes ~161 dans cpp.c */
// char codes[5] = {' ',' ',' ',' ',' '}; /*P version qui copie les commentaires après le caractère ' ' dans cpp_()*/
int main(int argc, char *argv[])
{ /*O main Test */
// char *fprj= ""; /*P nom fichier projet s'il existe */
char fdoc[MAX]; /*P nom fichier documentaire en sortie */
// char fdoc[] = "C++_doc.txt"; /*P nom fichier documentaire en sortie */
char fsrc[MAX]; /*P nom fichier source a documenter */
// char fsrc[] = ".\\C++_FILE.a"; /*P nom fichier source a documenter */
extern char codes[]; /*P codes */
extern unsigned char A,B,C,F,P,S,a,f,j,l,n,p,s,t,v,w; /*P rappels options booléennes */
/*O init options par défaut */
//?? {n=0;s=0;t=0;v=0;} /*O option v = 0 (verbose) de compilation; v n'est pas utilisé dans cpp_() */
// O=0; /* Option=0 */
int i=0; /*P compteurs */
int k=0;
char isource=0; /*P position nom du fichier source dans path source */
char itarget=0; /*P position fin du path_target avec '*' ou ':'(PC) */
char ktar=0; /*P position du '.' dans p_target */
static char O; /*P booleen =1 si option validee */
static char L; /*P booleen =1 si option langage */
register int c=0; /*P char (variable) */
int c1=0; /*P char (variable) pour version PC */
// FILE *pfprj; /*P FICHIER PROJET */
FILE *pnfile; /*P FICHIER SOURCE A TRIER */
FILE *pfdoc; /*P FICHIER A DOCUMENTER */
printf("Epreuve de cpp.c ; mkdcpp version 01/2011 compilation avec MSDEV41 pour x86-32 (Windows XP a Windows 7\n");
printf("Debug cpp.c ; mkdcpp version 01/2011 compiled with MSDEV41 for x86-32 (Windows xp to Windows 7\n");
printf("argv[0] = %s\n",argv[0]); /*T*/
if (argc > 1) printf("argv[1] = %s\n",argv[1]); /*T*/
if (argc > 2) printf("argv[2] = %s\n",argv[2]); /*T*/
if (argc > 3) printf("argv[3] = %s\n",argv[3]); /*T*/
/*O Si la syntaxe n'est pas correcte (argc <2) "mkdcpp [--nst] [-Code(DHOPSTUw)] Source_cpp" */
if (argc < 2)
/*O Alors Préciser la syntaxe et quitter sur erreur de syntaxe -1*/
{ /*S syntaxe intégrée */
//#ifdef FR
printf("Syntaxe : %s [--Options(nst)] [-5 Codes(DHOPSTUw)] source_cpp\n",argv[0]);
printf("Appuyer sur la touche 'Entree' pour quitter.\n\n");
//#endif
//#ifdef EN
printf("Syntax: %s [--Options(nst)] [-5 Codes(DHOPSTUw)] cpp_source\n",argv[0]);
printf("Press 'Enter' to quit.\n");
//#endif
getc(stdin); // attente touche 'Entrée' */
exit(-1);
} /*S syntaxe intégrée */
/*O si argc = 2 (source cpp en premier paramètre) */
if (argc == 2)
{ /*S argc = 2 */
#ifdef VC10
if (strcpy_s(fsrc,argv[1])!=0) /*w strcpy_s : évite l'erreur overflow */
#endif
#ifdef MSDEV41
if (strcpy(fsrc,argv[1])==NULL)
#endif
{
printf("Err SRC : %d chars max\n",MAX);
exit(-1);
}
else
{ /*S*/
#ifdef VC10
strcpy_s(fdoc,argv[1]); /*w strcpy_s : évite l'erreur overflow */
strcat_s(fdoc,".txt");
#endif
#ifdef MSDEV41
strcpy(fdoc,argv[1]);
strcat(fdoc,".txt");
#endif
printf("SRC = %s\n",fsrc); /*T*/
printf("DST = %s\n",fdoc); /*T*/
printf("argc=2 - Options n=%d,s=%d,t=%d,v=%d Codes %c,%c,%c,%c,%c\n",n,s,t,v,codes[0],codes[1],codes[2],codes[3],codes[4]); /*T*/
} /*S*/
} /*S argc = 2 */
/*O si argc = 3 (option ou code) */
if (argc == 3)
{ /*S argc = 3 */
if (argv[1][0]=='-' && argv[1][1]=='-') /*O Options ! */
{ /*S Options */
int i;
// printf("argv[1][0]=%c - argv[1][1]=%c\n",argv[1][0],argv[1][1]); /*T*/
for (i=0 ; i<4 && (argv[1][(i+2)]!=0) ; i++)
{ /*S*/
if (argv[1][(i+2)]=='n') n=1; /*O n,s,t sont des variables globales */
else if (argv[1][(i+2)]=='s') s=1; /*O*/
else if (argv[1][(i+2)]=='t') t=1; /*O*/
else if (argv[1][(i+2)]=='v') v=1; /*O*/
// printf("argv[1][%d]=%c & n=%c, s=%c, t=%c\n",(i+2), argv[1][i+2],n,s,t); /*T*/
} /*S*/
} /*S Options */
else if (argv[1][0]=='-' && argv[1][1]!='-') /*O Codes ! */
{ /*S Codes */
int i;
for (i=0 ; i<5 && (argv[1][i+1]!=0) ; i++) codes[i]=argv[1][i+1]; /*O affectation */
} /*S Codes */
else /*O sinon erreur de syntaxe */
{ /*S*/
puts("Options ? || Codes ?\n"); /*O*/
exit(-1); /*O*/
} /*S*/
/*O affectation du nom de fichier (.cpp) au nom de fichier destinataire, et ajouter .txt */
#ifdef VC10
if (strcpy_s(fsrc,argv[2])!=0)
#endif
#ifdef MSDEV41
if (strcpy(fsrc,argv[2])==NULL)
#endif
{ /*S*/
printf("Err SRC : %d chars max\n",MAX);
exit(-1);
} /*S*/
else
{ /*S*/
#ifdef VC10
strcpy_s(fdoc,argv[2]);
strcat_s(fdoc,".txt");
#endif
#ifdef MSDEV41
strcpy(fdoc,argv[2]);
strcat(fdoc,".txt");
#endif
printf("SRC = %s\n",fsrc); /*T*/
printf("DST = %s\n",fdoc); /*T*/
printf("argc=3 - Options n=%d,s=%d,t=%d,v=%d Codes %c,%c,%c,%c,%c\n",n,s,t,v,codes[0],codes[1],codes[2],codes[3],codes[4]); /*T*/
} /*S*/
} /*S argc = 3 */
/*O si argc = 4 (options et code) */
if (argc == 4)
{ /*S argc = 4 */
if (argv[1][0]=='-' && argv[1][1]=='-') /*O Options */
{ /*S Options */
int i;
for (i=0 ; i<4 && (argv[1][i+2]!=0) ; i++)
{ /*S*/
if (argv[1][i+2]=='n') n=1; /*O n,s,t sont des variables globales */
else if (argv[1][i+2]=='s') s=1;
else if (argv[1][i+2]=='t') t=1;
else if (argv[1][(i+2)]=='v') v=1;
} /*S*/
} /*S Options */
else
{ /*S err */
puts("Options ?\n");
exit(-1);
} /*S err */
if (argv[2][0]=='-' && argv[2][1]!='-') /*O Codes */
{ /*S Codes */
int i;
for (i=0 ; i<5 && (argv[2][i+1]!=0) ; i++) codes[i]=argv[2][i+1];
} /*S Codes */
else /*O erreur de syntaxe */
{ /*S*/
puts("Codes ?\n");
exit(-1);
} /*S*/
#ifdef VC10
if (strcpy_s(fsrc,argv[3])!=0)
#endif
#ifdef MSDEV41
if (strcpy(fsrc,argv[3])==NULL)
#endif
{ /*S*/
printf("Err SRC : %d chars max\n",MAX);
exit(-1);
} /*S*/
else
{ /*S*/
#ifdef VC10
strcpy_s(fdoc,argv[3]);
strcat_s(fdoc,".txt");
#endif
#ifdef MSDEV41
strcpy(fdoc,argv[3]);
strcat(fdoc,".txt");
#endif
printf("SRC = %s\n",fsrc); /*T*/
printf("DST = %s\n",fdoc); /*T*/
printf("argc=4 - Options n=%d,s=%d,t=%d,v=%d Codes %c,%c,%c,%c,%c\n",n,s,t,v,codes[0],codes[1],codes[2],codes[3],codes[4]); /*T*/
} /*S*/
} /*S argc = 4 */
/*O ouvrir le fichier source en lecture binaire*/
{ /*S démarrage du test */
/*O si l'ouverture du fichier source n'est pas correcte */
#ifdef VC10
if (fopen_s(&pnfile, fsrc,"rb") !=0 )
#endif
#ifdef MSDEV41
if (( pnfile = fopen ( fsrc,"rb" )) == 0 ) // old syntax
#endif
{ /*S ! open source pnfile */
/*O ecrire fichier "nomfich" non trouvé ou erreur d'ouverture */
printf ("fichier \'%s\' : non trouvé ou erreur d'ouverture\n",fsrc);
puts("Tapez sur la touche 'Entrée' pour quitter\n\n");
printf ("file \'%s\' : non found or open error\n",fsrc);
puts("Press 'Enter' to quit.\n");
getchar();
exit(2);
} /*S ! open source pnfile */
/*O sinon, ouvrir le fichier à documenter en écriture ou réécriture */
else
{ /*S open pfdoc write */
/*O si il y a une erreur à l'ouverture l'écrire et quitter en renvoyant le code d'erreur 2 */
#ifdef VC10
if((fopen_s(&pfdoc,fdoc,"wb")) != 0)
#endif
#ifdef MSDEV41
if((pfdoc = fopen(fdoc,"wb")) == NULL) // old syntax
#endif
{ /*S si err à l'ouverture de pfdoc*/
printf("fichier \'%s\' : erreur d'ouverture en écriture\n",fdoc);
puts("Tapez sur la touche 'Entrée' pour quitter\n\n");
printf("file \'%s\' : open error\n",fdoc);
puts("Press 'Enter' to quit.\n");
getchar();
exit(-2);
} /*S si err à l'ouverture de pfdoc*/
else
{ /*S sinon*/
/*O si options n ou v ou s et pas t écrire le nom du fichier lu */
if(n||v||s)
{ /*S si n ou v ou s valide */
if (!t) fprintf(pfdoc,"%s\n(file %s :)", NL, fsrc );
if( v || s ) printf("\n\n(file %s :)\n",fsrc);
if (!t)fprintf (pfdoc," Options n=%d s=%d t=%d verbose=%d",n,s,t,v);
if (!t)fprintf (pfdoc, "%s", NL );
} /*S si n ou v ou s valide */
} /*S sinon*/
} /*S open pfdoc write */
cpp_(pfdoc,pnfile);
/*O fermer le fichier source et en cas d'erreur écrire "Erreur de fermeture */
if (fclose(pnfile))
{ /*S si*/
printf("Erreur de fermeture : \'%s\'\n",fsrc);
printf("Error on closed : \'%s\'\n",fsrc);
exit(2);
} /*S fin si*/
/*O Fermer tous les autres fichiers */
{ /* fermer */
int numclosed = _fcloseall( );
printf( "Nombre de fichiers fermés par _fcloseall : %u\n", numclosed );
printf( "Number of files closed by _fcloseall: %u\n", numclosed );
} /* fermer */
} /*S demarrage du test */
puts("Tapez sur la touche 'Entrée' pour quitter\n");
puts("Press 'Enter' to quit.\n");
getchar();
return 0;
} /*O main Test */
Le Makefile pour la compilation de l'unité
modifierLe makefile suivant, mkdcpp.mak complet pour une installation standard a été bridé pour les tests unitaires.
mkdcpp.mak
# file: mkdcpp.mak (Makefile pour version LINUX UNBUNTU 10.11) mise à jour septembre 2012
# syntaxe: make -f mkdcpp.mak -d (voir install...)
# gcc et mkdoc doivent être installés, si mkdoc n'est pas installé on peut utiliser mkdcpp
# avec la ligne de commande : mkdcpp --t -$(LANG) manuel | mv manuel.txt $(PGM).1
# avec cette commande il faut hélas penser à faire un retour chariot à la fin de la commande
#
# Attention: avant de compiler, il faut valider les options de compilation
# dans version.h (notamment la langue et la version UNIX qui invalide la version PC)
#
# Use BINDIR /bin or /usr/bin or /usr/local/bin
# Use CATMANDIR = /usr/share/man/man1 or /usr/local/share/man
# LANG F for Fr or M for Eng
####################
### UNIX version ###
####################
CC = gcc
MKDOC = mkd
PGM = mkdcpp
BINDIR = #/usr/bin
BINMODE = 755
MAN = mkdcpp.1.gz
LANG = F
#CATMANDIR = /var/cache/man/cat1
#MANDIR = /usr/share/man/man1
MANDIR = /usr/local/man
MANMODE = 644
SRCS = mkdcpp.c cpp.c
HDRS = version.h cpp.h
OBJS = cpp.o mkdcpp.o
LIBS =
CFLAGS = -O
LDFLAGS =
SPLINTFLAG = -weak -nestcomment
install: $(BINDIR)/$(PGM) #$(MANDIR)/$(MAN)
$(BINDIR)/$(PGM): $(SRCS) $(HDRS)
-@echo "*********** update $(PGM) ***********"
$(CC) -c cpp.c mkdcpp.c
@#$(CC) $(CFLAGS) -o $(PGM) $(SRCS)
$(CC) $(LDFLAGS) -o $(PGM) $(OBJS) $(LIBS)
-@strip $(PGM) #clean ASM and LINK reloc.
-@echo " -- update $(BINDIR)/$(PGM):" #install pgm
-@if [ -d $(BINDIR) ]; then \
cp -f $(PGM) $(BINDIR)/$(PGM);\
chmod $(BINMODE) $(BINDIR)/$(PGM);\
if [ $(BINDIR) != "/bin" ]; then \
ln -s $(BINDIR)/$(PGM) /bin/$(PGM);\
fi \
else \
echo "couldn't find $(BINDIR)";\
fi
$(MANDIR)/$(MAN): manuel
-@echo "*********** update $(MAN) ***********"
#-$(MKDOC) -Ctw M manuel $(PGM).1
-$(MKDOC) -Ctw $(LANG) manuel $(PGM).1
#mkdcpp --t -$(LANG) manuel | mv manuel.txt $(PGM).1
-@gzip $(PGM).1
-@echo " -- update $(MANDIR)/$(MAN):" #install manual
-@if [ -d $(MANDIR) ]; then \
cp -f $(MAN) $(MANDIR)/$(MAN);\
chmod $(MANMODE) $(MANDIR)/$(MAN);\
echo " -- update $(CATMANDIR):";\
catman -M $(MANDIR)/$(MAN) 1;\
else \
echo "couldn't find $(MANDIR)/$(MAN)";\
fi
lint:
-@echo "*** lint -> warnings (file), lint n'existe plus ... ! installez splint ***"
splint $(SPLINTFLAGS) $(SRCS) > warnings
more warnings
clean:
#rm -f $(PGM) $(OBJS) $(MAN)
Épreuve unitaire
modifierGénérer la documentation unitaire
modifier- La documentation unitaire doit (devrait ?) être intégrée dans le fichier source afin d'être certain que cette documentation concerne CE fichier source.
- On extrait cette documentation par copier-coller ou avec mkd.
- Pour une production importante il faut se référer à la norme ISO[1][2]..
- Pour une petite production, cette documentation unitaire doit fournir les indications suivantes:
- FILE NAMES: Nom du fichier et nom de la fonction.
- PROJECT: Nom du projet.
- INITIAL PROJECT: Projet initial si le projet a changé de nom.
- ADMINISTRATIVE RECORD: Nom d'enregistrement dans les archives avec la date, le lieu etc.
- UPDATES: Date, auteur, nature de la modification.
- RECOMMANDED TESTS: Description des épreuves pour valider la fonction.
- Description de la fonction: (Utile pour le manuel man 3)
- NAME: Nom de la fonction (Suivi, éventuellement du nom du fichier source, Voir FILES ci après)
- SYNOPSIS: ou SYNTAX: fichiers d’entête (#include) return-value function (parameters);
- DESCRIPTION: ou ACTION: action détaillée et sa description.
- RETURN VALUE: valeurs de retour de la fonction.
- CONFORMING TO: ou STANDARDS: POSIX, ANSI C, BSD, ISO/IEC 9899:2011, gcc, MS-VC10, UTF-8, etc.
- PORTABILITY: LINUX-Debian-systems, LINUX-Red-Hat, Windows NT, etc.
- COPYRIGHT: Droit de copie s'il y a lieu.
- AUTHORS: Concepteur, traducteurs, etc. (Éventuellement)
- RESSOURCES: Si le projet nécessite des ressources particulières (gtkmm, etc.)
- FILES: Fichiers concernés Fichiers d'entête (.h), sources, etc. (où on les trouve)
- NOTES: ou recommandations.
- BUGS: Erreurs constatées ou erreurs courantes.
- SEE ALSO: Voir aussi, au cas où ...
Éprouver le module (Test unitaire)
modifierLe répertoire des tests unitaire se compose:
- Un ou plusieurs fichiers sources. le fichier source peut simplement s'appeler "Source" mais on préfère lui donner un nom qui le distinguera des autre modules lors des tests d'intégration; par exemple "Test_cpp_U.cc"
- Un fichier de commande des test que l'on peut appeler "Tests" ou "Test_cpp_U" que l'on rendra exécutable sous linux, sous Windows on utilise l'extension ".bat"
- Un fichier de nettoyage "Clean" ou Test_cpp_U.clean. On le rendra exécutable (Même remarque que précédemment)
- Un fichier qui donne le résultat de l'analyse "Analysis" en anglais.
Exemple pour le Styles C
modifier- /* ... */ : C, C++, C#, PHP, Java, Javascript, CSS, ...
- // ... NL : C++, C#, PHP, Java, Javascript
Fichiers de tests unitaires de la fonction cpp_() dans mkd
- Tests function files: Test_cpp_U.cc, Test_cpp_U.c
- Bash commands files: Tests, Tests_Clean
//T File Test_cpp_U.cc to test function cpp_()
/*P
Fonction cpp_(); Fichier cpp.c
Directives de tests unitaires version alpha 2013:
-------------------------------------------------
Vérifiez les options n, s et t séparément:
Vérifiez que la numérotation des lignes est correcte dans tous les cas de
décodage (lignes et blocs). n, ns. nt, nst.
Vérifiez que le texte reste à la bonne place dans tous les cas de décodage:
toute la ligne (dans la cas de la directive de compilation FULL_LINE), ou
texte seul.
-- Vérifiez que les tabulations sont bien prises en charge dans tous les
cas, décodage des lignes et des blocs.
-- Vérifiez de même pour les espaces.
La fonction doit être éprouvée de telle sorte qu'un commentaire qui se
termine par le caractère de fin de fichier soit entièrement copié dans le
fichier cible.
Le caractère de fin de fichier décodé avant le(les) caractère(s) de fin de
commentaire doit être remplacé par un caractère de fin de ligne.
Le caractère de fin de fichier (EOF) NE DOIT JAMAIS APPARAÎTRE DANS LE
TEXTE DU FICHIER CIBLE.
Ceci provoquait un bug dans la version Alpha de l'application fenêtrée
mkdcppw à l'étape du test d'intégration.
*/
/*T
12345678901234567890123456789012345678901234567890123456789012345678901234567890 */
#define TEST //T The macro becomes active
#ifdef TEST //T Do something (Faire quelque chose)
#undef test //T The macro becomes inactive
/*T
12345678901234567890123456789012345678901234567890123456789012345678901234567890 */
//T test in ligne with 2 tabulations
//T test in ligne with 5 spaces
/*T test bloc in first line end bloc*/
/*T test bloc in first line
with 2 tabs
with 5 spaces end bloc */
/*T
12345678901234567890123456789012345678901234567890123456789012345678901234567890 */
/*T test bloc in line with 2 tabs end bloc*/
/*T test bloc in line
2 tabs
with 5 spaces
end bloc */
//T see also "/*T" with out end of block comment and EOL in file Test_cpp_U.c
//T test inline with out end of line (EOL)(NL)(CR/LF)
File Test_cpp_U.c
//T File Test_cpp_U.c
/*T with out end of block comment and EOL (NL) in file Test_cpp_U.c
File Tests
#!/bin/bash
#O mkd tests under Linux.
#O Epreuve de vérification de la fonction cpp_() avec mkd
#O Copy Test_cpp_U.cc in target created file
cat Test_cpp_U.cc > Test_cpp_U.tstcpp
#O Test options -nstv with source "Test_cpp_U.cc" and target "*.tstcpp"
#O - and screen redirection to tstcpp.screen
#O 1: Test de l'option -s append target
mkd -savC T Test_cpp_U.cc *.tstcpp > tstcpp.screen
#O 1: Test option -t
mkd -tavC T Test_cpp_U.cc *.tstcpp # >> tstcpp.screen
#O 1: Test option -n, with append files target and screen
mkd -navC T Test_cpp_U.cc *.tstcpp # >> tstcpp.screen
#O 2: Test options -ns, with append files target and screen
mkd -nsavC T Test_cpp_U.cc *.tstcpp >> tstcpp.screen
#O 2: Test options -nt, with append files target and screen
mkd -ntavC T Test_cpp_U.cc *.tstcpp >> tstcpp.screen
#O 2: Test options -nst, with append files target and screen
mkd -nstavC T Test_cpp_U.cc *.tstcpp >> tstcpp.screen
#O 5: Independant test with -nstv "Test_cpp_U.cc" and target "*.tstcpplastline1"
mkd -nstvwC T Test_cpp_U.cc *.tstcpplastline1 > tstcpplastline.screen1
#O 5: Independant test with -nstv "Test_cpp_U.c" and target file "*.tstcpplastline2"
#w bug mkd -nstvwC T Test_cpp_U.c *.tstcpplastline2 > tstcpplastline.screen2
#O Break with gedit "Test_cpp_U.tstcpp", "tstcpp.screen"
gedit Test_cpp_U.tstcpp
gedit tstcpp.screen
gedit Test_cpp_U.tstcpplastline1
#w bug gedit Test_cpp_U.cc.tstcpplastline2
#O Erase Test_cpp_U.tstcpp
File Tests_Clean
#!/bin/bash
#O File Tests_Clean
#O Force delete files created with mkd "tests" under Linux.
rm -f Test_cpp_U.tstcpp
rm -f tstcpp.screen
rm -f Test_cpp_U.tstcpplastline1
rm -f tstcpplastline.screen1
rm -f Test_cpp_U.tstcpplastline2
rm -f tstcpplastline.screen2
rm -f *.doc
Analyse des tests unitaires
modifierÉprouver le module unitaire nécessite de répondre aux recommandations des tests contenus dans la documentation.
Exemple de fichier Analysis
Analysis
Fichier Analysis texte UTF-8
Analyse du : 4 avril 2013 par Clara pour le retour à la conception détaillée.
-------------------------------------------------------------------------------
Résultats du test unitaire de la fonction cpp_() du fichier cpp.c intégrée à
la commande mkd 2012: mkd_120508
.
Ce test est effectué avec la version mkd 2012 pour évaluer les modifications
à effectuer dans la version alpha 2013.
.
Note : Nous n'avons pas effectué ce test avec les commandes mkdcpp et mkdcppw
qui aboutiraient aux mêmes résultats.
.
D'après les directives et les fichiers d'analyse Test_cpp_U.tstcpp et
tstcpp.screen
.
Directives de tests unitaires version alpha 2013:
-------------------------------------------------
1: Vérifiez les options n, s et t séparément:
- les essais séparés fonctionnent correctement et sont conformes
.
2: Vérifiez que la numérotation des lignes est correcte dans tous les cas de
décodage (lignes et blocs). n, ns. nt, nst.
- Les essais réalisés ont été conformes
.
3: Vérifiez que le texte reste à la bonne place dans tous les cas de décodage:
toute la ligne (dans la cas de la directive de compilation FULL_LINE), ou
texte seul.
- Le résultat est conforme (Sans la numérotation des lignes)
.
4: -- Vérifiez que les tabulations sont bien prises en charge dans tous les
cas, décodage des lignes et des blocs.
-- Vérifiez de même pour les espaces.
- Les résultats sont conformes. Il est à noter que les tabulations créent un
décalage du texte avec l'option -n numérotation
La réponse aux épreuves 4 est "conforme".
.
5: La fonction doit être éprouvée de telle sorte qu'un commentaire qui se
termine par le caractère de fin de fichier soit entièrement copié dans le
fichier cible.
Le caractère de fin de fichier décodé avant le(les) caractère(s) de fin de
commentaire doit être remplacé par un caractère de fin de ligne.
- Le fichier Test_cpp_U.tstcpplastline1 commentaire ligne; fait apparaître
une fin de fichier conforme.
- Le fichier Test_cpp_U.tstcpplastline2 commentaire bloc; n'a pas été
réalisée (erreur EOF avec une boucle sans fin)
La réponse à l'épreuve 5 est "non conforme".
.
6: Le caractère de fin de fichier (EOF) NE DOIT JAMAIS APPARAÎTRE DANS LE
TEXTE DU FICHIER CIBLE.
Ceci provoquait un bug dans la version Alpha de l'application fenêtrée
mkdcppw à l'étape du test d'intégration.
- La réponse est incluse dans les tests 5:
- Nous avons constaté qu'un caractère EOF peut exister dans un fichier
cible lorsqu'un fichier source ne se termine pas par un retour chariot.
Le fichier cible (document) n'est alors pas éditable en UTF-8
En ce cas il faut vérifier son existence avec un éditeur hexadécimal
comme "Bless Hex Editor" ou Ghex. (EOF = généralement 0xFF)
Voir End-Of-File sur wikipedia.
Ceci apparaît avec l'actuelle fonction cpp_() lorsque le fichier se termine
par */ sans le retour chariot.
- Tous les caractères sont recopiés octets par octets. La commande mkd
ignore le format du texte recopié. Il n'en est pas de même pour mkdcppw
qui ne reconnaît que les caractères UTF-8 nécessaires à l'impression.
La réponse à l'épreuve 6 est donc "non conforme".
Intégration du module
modifierL'intégration du module se fait par la compilation d'une application qui utilise ce "module", cette fonction: mkd, mkdcpp, mkdcppw par exemple. Le fichier d'entête version.h doit être modifié en fonction des compilateurs et options de compilation.
Ce module peut être intégré par inclusion (#include) avec l'option de compilation gtkmm pour mkdcppw.
Il peut être compilé séparément sous forme d'objet éventuellement intégrable dans une librairie.
Le module objet sera lié (Link) à l'application par la compilation.
Attention : Une fonction intégrée dans une librairie est figée. Il faut alors veiller à proposer un fichier d'entête correspondant à l'objet; on ne peut plus utiliser version.h.
- Pour la fonction cpp() par exemple, il faudra proposer un fichier d'entête cpp.h correspondant à la compilation cpp.o
Épreuve d'intégration
modifier- Exemple:
- Constater que le module se compile bien dans l'application.
- Vérifier que le module répond bien aux paramètres d'entrée et qu'il prend en compte les variables globales. Vérifier les valeurs de retour de fonction et l'affichage des messages correspondants.
- Reprendre tous les tests unitaires des fonctions avec les fonctions intégrées dans l'application.
Générer la documentation
modifier- Déterminer à qui s'adresse cette documentation, par exemple:
- Utilisateur final
Manuels - Concepteurs
Suivi de la programmation selon les étapes du cycle en V - Programmeurs
Documentation des fonctions et librairies de fonctions
Tests unitaires, d'intégration, de validation