Il est fréquent d'avoir besoin d'un langage de macro-commandes lorsqu'on utilise un éditeur. La plupart d'entre eux en possède d'ailleurs un intégré et même le compilateur C possède son propre pré-processeur CPP. Lorsqu'on doit éditer des fichiers de configuration au format texte, ou même éditer des pages HTML pour maintenir un petit site Web, il peut s'avérer pratique d'utiliser le macro processeur GNU/m4 qui est livré avec toutes les distributions de Linux et qui est devenu un standard de facto dans le monde Unix.
Dans ce qui suit, nous allons voir comment utiliser le processeur de macros m4 pour construire des pages HTML et ainsi maintenir la cohérence d'un site Web. Bien sûr, il existe quantité d'autres moyens d'obtenir le même résultat ; c'est ce qui fait la beauté de ce système.
Cette technique est celle utilisée pour la génération du fameux fichier sendmail.cf. Voir à ce sujet l'article de Eric Jacoboni dans LinuxMagazine n°2 de janvier 99.
L'utilisation du langage macro m4 n'est pas limité à l'édition de fichiers texte ou HTML. Il pourra s'avérer très utile pour les programmeurs qui souhaitent étendre les possibilités du préprocesseur du langage C ou pour ceux qui veulent disposer de possibilités équivalentes au C avec un autre langage.
Définition
On parle de processeur de macros pour définir un programme qui interprète des commandes (les macros), elles-mêmes définies par l'utilisateur ; par exemple, avec une définition comme la suivante :
define(AUTEUR,`Agatha Christie<a.christie@scotland-yard.gov>')
Il suffira de mettre le mot « AUTEUR » dans le texte pour qu'il soit remplacé par le texte « Agatha Christie<a.christie@scotland-yard.gov> » après utilisation du processeur de macros. Il existe bien sûr des fonctions plus évoluées comme nous le verrons dans ce qui suit.
Un exemple
Supposons que nous ayons à maintenir un site Web qui comporte les mêmes pages dans des langues différentes. De plus, chaque page possède un en-tête et un pied de page qui assurent un aspect cohérent à l'ensemble du site. Pour faire simple et éviter d'avoir à utiliser un navigateur pour voir le résultat, notre exemple se limitera à du texte. Cela permettra aussi aux puristes qui utilisent Lynx de naviguer sans problèmes. Voici le code HTML d'une page :
Version HTML
<!-- Début de l'en-tête -->
<HTML>
<HEAD>
<TITLE>Un site pour les utilisateurs de Lynx</TITLE>
<META name="description" content="Site lynx et m4">
<META name="keywords" content="m4, lynx, GPL">
</HEAD>
<BODY BGCOLOR="#FFFFFF" LINK="#008000"
VLINK="#808080" ALINK="#8080FF">
<TABLE>
<TBODY>
<TR><TD align=middle colspan="2">
<H1>Lynx un navigateur en mode console</H1>
<TR><TD align="left" valign="top" width="15%">
<a href="./index-en.html">Anglais</A><BR>
<a href="./index-fr.html">Français</A><BR>
<a href="./index-es.html">Espagnol</A><BR>
<a href="./index-it.html">Italien</A><BR>
<a href="./index-de.html">Allemand</A><BR>
<TD align=left>
<!-- Fin de l'en-tête -->
<!-- Corps de la page -->
<P>Visitez le
<A HREF="http://lynx.browser.org/">
Site officiel de Lynx</A>
pour plus d'informations sur Lynx,
y compris les nouvelles mises à jour.</P>
<P>Les liens vers les sources de la version
courante et divers supports pour Lynx sont
tenus à jour sur le site
<A HREF="http://www.crl.com/~subir/lynx.html">
liens Lynx</A>.</P>
<P>Lynx est distribué dans le cadre de la licence GNU
(General Public License - GPL)
sans restriction sur son utilisation ni sa distribution.
Les mentions des droits de
reproduction de Lynx, "COPYHEADER", et GNU GPL,"COPYING",
sont inclus dans la racine de l'arborescence de la distribution.
Lynx est supporté par la communauté des utilisateurs de Lynx,
une communauté entièrement bénévole (et non-officielle).</P>
<!-- Fin du corps de la page -->
<!-- Début du pied de page -->
</TBODY>
</TABLE>
<HR size="0" noshadow>
<FONT SIZE=-2>
<EM>Date de mise à jour : 11/07/99
- © <A HREF="mailto:webmaster@lynx.browser.org">
lynx.browser.org</A> 1999
</EM></FONT>
</BODY>
</HTML>
<!-- Fin du pied de page -->
Voici l'apparence de cette page :
Pour la cohérence du site, toutes les pages auront les mêmes styles d'en-têtes et de pieds de page, seul le corps de la page changera. Nous allons donc créer des macros m4 que nous insérerons dans le texte HTML de nos pages et qui remplaceront tous les éléments répétitifs. Avant de donner le détail des macros, regardons ce que donnera l'exemple ci-dessus une fois réécrit de cette manière :
Version macro
LYNX_TITRE(Lynx un navigateur en mode console)
LYNX_ENTETE(Un site pour les utilisateurs de Lynx)
<P>Visitez le
<A HREF="http://lynx.browser.org/">
Site officiel de Lynx</A>
pour plus d'informations sur Lynx,
y compris les nouvelles mises à jour.</P>
<P>Les liens vers les sources de la version
courante et divers supports pour Lynx sont
tenus à jour sur le site
<A HREF="http://www.crl.com/~subir/lynx.html">
liens Lynx</A>.</P>
<P>Lynx est distribué dans le cadre de la licence GNU
(General Public License - GPL)
sans restriction sur son utilisation ni sa distribution.
Les mentions des droits de reproduction de Lynx, "COPYHEADER",
et GNU GPL, "COPYING", sont inclus dans la racine de l'arborescence de la distribution. Lynx est supporté par la communauté des utilisateurs de Lynx, une communauté entièrement bénévole (et non-officielle).</P>
LYNX_PIED
De cette manière, l'écriture des pages est beaucoup plus concise et le texte n'est pas noyé dans les balises HTML de début et de fin de page. De même, pour créer les pages dans les autres langues, nous créerons des fichiers équivalents à celui-ci mais traduits. La version anglaise donnerait :
LYNX_TITRE(Lynx a fully-featured World Wide Web
client for character-cell displays)
LYNX_ENTETE(Lynx homepage)
<P>Links to the current sources and support materials
for Lynx are maintained at
<A HREF="http://www.crl.com/~subir/lynx.html">
Lynx links</A></P>
<P> and at the Lynx homepage
<A HREF="http://lynx.browser.org/">
Lynx Information.</A></P>
<P>View these pages for information about Lynx,
including new updates.</P>
<P>Lynx is distributed under the
GNU General Public License (GPL) without
restrictions on usage or redistribution.
The Lynx copyright statement, "COPYHEADER",
and GNU GPL, "COPYING", are included in the top-level
directory of the distribution.
Lynx is supported by the Lynx user community,
an entirely volunteer (and unofficial)organization.</P>
LYNX_PIED
On utilise pour chaque langue les mêmes macros LYNX_TITRE, LYNX_ENTETE et LYNX_PIED, mais avec des arguments différents. Ces trois macros permettent de remplacer efficacement tout le code HTML de début et de fin de page. L'avantage non négligeable de ce système réside dans le fait que la définition des en-têtes et pieds de page est unique pour tout le site. Ainsi, en cas de modification du style des pages du site, il n'y aura qu'un fichier à modifier : celui qui contient les définitions des macros au lieu de reprendre toutes les pages une par une.
Définition des macros
Ci-dessus, nous avons défini le besoin de 3 macros qui feront le gros du travail. Voir le fichier qui contient la définition de ces macros dans l' encadré ci-dessous
Description
Les lignes comprises entre « divert(-1) » et « divert(0) » sont des commentaires. « Divert » est une des macros prédéfinies du processeur m4 qui permet de retarder les résultats d'interprétation du fichier d'entrée. En utilisant -1, les lignes qui suivent ne sont pas retranscrites dans le fichier HTML définitif, ce qui est bien le résultat recherché.
La macro « changequote » permet de redéfinir les apostrophes qui permettent d'encadrer les arguments des macros par défaut. Ici, elles sont remplacées par des accolades car, dans la plupart des textes en français, les apostrophes apparaissent régulièrement et faussent l'interprétation des macros. Les accolades sont moins utilisées pour du texte ou du HTML c'est pourquoi elles ont été choisies ici.
La macro « ifdef » sert à tester si la macro LANG est définie, ce qui permet de la définir comme « fr » si elle n'existe pas. La macro LANG permet de préciser la langue utilisée. Nous verrons par la suite qu'elle sera définie lors de l'appel au macro processeur m4 afin de choisir en quelle langue construire la page HTML.
La ligne « include » a le même sens qu'en C et permet d'inclure un fichier externe. Ici, il s'agit du fichier de traduction qui contient des définitions propres à chaque langue. Voici son contenu en fonction de la langue :
divert(-1)
# Fichier mac.css
# Version 1.0 des macros m4 pour Lynx
#
# Pour chaque langue est défini un fichier
# trans-LANG.m4 basé sur le modèle français.
# Si aucun fichier de traduction n'existe,
# le français est pris par défaut.
#
divert(0)
changequote({,})dnl # changer les apostrophes en accolades
ifdef({LANG},,{define({LANG},{fr})})dnl # Défaut= français
include({trans-}LANG{.m4})dnl # Appeler le fichier de traduction
undefine({format})dnl # Supprimer la définition de format
define({_ANNEE_},esyscmd(date +%Y))dnl #Année en cours
define({LYNX_TITRE},{define(_TITLE_,$1)})dnl # Déclaration de la 1ère macro
dnl # Déclaration de la 2ième macro
define({LYNX_ENTETE},{<!-- Début de l'en-tête -->
<HTML>
<HEAD>
<TITLE>$1</TITLE>
<META name="description" content="Site Lynx et m4">
<META name="keywords" content="m4, Lynx, GPL">
</HEAD>
<BODY BGCOLOR="#FFFFFF" LINK="#008000" VLINK="#808080" ALINK="#8080FF">
<TABLE>
<TBODY>
<TR><TD align=middle colspan="2">
<H1>_TITLE_</H1>
<TR><TD align="left" valign="top" width="15%">
<a href="./index-en.html">_ANGLAIS_</A><BR>
<a href="./index-fr.html">_FRANCAIS_</A><BR>
<a href="./index-es.html">_ESPAGNOL_</A><BR>
<a href="./index-it.html">_ITALIEN_</A><BR>
<a href="./index-de.html">_ALLEMAND_</A><BR>
<TD align=left>
<!-- Fin de l'en-tête -->})dnl
dnl # Déclaration de la 3ième macro
define({LYNX_PIED},{<!-- Début du pied de page -->
</TBODY>
</TABLE>
<HR size="0" noshadow>
<FONT SIZE=-2>
<EM>_MAINTENEUR_.<BR>
_MAJ_
esyscmd(date +%d/%m/%y)
- © <A HREF="mailto:webmaster@lynx.browser.org">
lynx.browser.org</A>
_ANNEE_</EM></FONT>
</BODY>
</HTML>
<!-- Fin du pied de page -->})dnl
divert(-1)
# Fichier trans-fr.m4
# Définitions pour le français
divert(0)
define({_ANGLAIS_},{Anglais})dnl
define({_FRANCAIS_},{Français})dnl
define({_ITALIEN_},{Espagnol})dnl
define({_ESPAGNOL_},{Italien})dnl
define({_ALLEMAND_},{Allemand})dnl
define({_WEBMASTER_},{John Perr})dnl
define({_MAINTENEUR_},{Page maintenue par _WEBMASTER_})dnl
define({_MAJ_},{Date de mise à jour:})dnl
divert(-1)
# Fichier trans-en.m4
# Définitions pour l'anglais
divert(0)
define({_ANGLAIS_},{English})dnl
define({_FRANCAIS_},{French})dnl
define({_ITALIEN_},{Spanish})dnl
define({_ESPAGNOL_},{Italian})dnl
define({_ALLEMAND_},{German})dnl
define({_WEBMASTER_},{John Perr})dnl
define({_MAINTENEUR_},{Page maintained by _WEBMASTER_})dnl
define({_MAJ_},{Page updated on })dnl
Si vous parlez espagnol, italien ou allemand, vous pourrez sans difficulté créer les fichiers pour ces langues à partir des deux exemples ci-dessus.
La ligne « undefine » supprime la définition par défaut de la macro prédéfinie de m4 qui s'appelle « format » car elle n'est pas utilisée ici. Si cette ligne est omise, chaque apparition du mot « format » dans le texte sera supprimée, à moins de l'encadrer par des accolades, ce qui est contraignant pour rédiger une simple page Web.
Vient ensuite la définition de l'année courante à partir de la macro « easyscmd », qui appelle la commande système « date ». On retrouve cette commande dans la définition du pied de page pour afficher la date de mise à jour de la page.
La ligne suivante définit la première de nos trois macros principales :
LYNX_TITRE. C'est en fait une macro qui en définit une autre appelée _TITRE_. Cette façon de faire permet d'utiliser plusieurs fois, si nécessaire, le titre dans l'en-tête ou le pied de page à partir d'une déclaration. Notez l'utilisation du symbole $1 pour appeler le premier argument de la macro.
Les lignes restantes définissent les deux autres macros principales :
LYNX_ENTETE et LYNX_PIED qui correspondent respectivement au contenu de l'en-tête et du pied de notre page HTML à quelques détails près. Les différences concernent les éléments variables de ces parties de la page, à savoir :
- Les mots devant être traduits dans une langue et provenant du fichier de traduction.
- Les éléments susceptibles d'être modifiés lors de la création de la page tels que la date de mise à jour, l'année ou le nom du webmestre.
Le « dnl » qui apparaît à la fin de chaque ligne est une macro prédéfinie de m4, qui permet de ne pas prendre en compte le reste de la ligne et évite aussi la création d'une ligne blanche dans le fichier de sortie, lors de l'interprétation d'une ligne de macro.
Création des pages
L'ensemble du dispositif étant en place, la génération d'une page HTML à partir du fichier de base contenant le corps du texte se fait par la commande :
m4 -DLANG=XX mac.css index-XX.m4 > index-XX.html
Où "XX" est le code de la langue à utiliser. Si aucune langue n'est spécifiée, le français est utilisé, soit "XX=fr". Notez que l'option -D permet, tout comme avec gcc, de définir une macro depuis la ligne de commande.
Récapitulatif
Le tableau ci-dessous résume l'ensemble des fichiers utilisés et leurs fonctions dans le cadre de cette application.
index-XX.html Le corps de l'article, c'est-à-dire le texte écrit par l'auteur ou le traducteur. Il est différent pour chaque article et chaque langue (le code XX=en pour l'anglais, es pour l'espagnol, etc.).
mac.css Les définitions standards pour tous les groupes. Ce fichier est commun à toutes les pages et toutes les langues. Il peut être vu comme un modèle ou une feuille de style.
trans-XX.m4 Les définitions standards pour une langue (le code XX=en pour l'anglais, es pour l'espagnol, etc.). Ce fichier est commun à toutes les pages et une langue.
Les fichiers servent à la génération des pages HTML.
Conclusion
Bien qu'il soit puissant, le macro processeur m4 n'est qu'un processeur de macro-commandes et ne saurait être comparé à un langage de programmation de scripts comme Perl ou TCL. Une fois ces quelques particularités maîtrisées, il reste quand même un outil rapide et pratique tel que seul le monde Unix a su en créer. Pour en savoir plus, consulter la documentation fournie avec votre distribution. Un didacticiel m4 d'une trentaine de pages y figure en particulier et couvre tous les aspects de son utilisation. Vous pouvez aussi consulter, à titre d'exemple, le site de l'Association Bordelaise des Utilisateurs Linux qui est maintenu avec un jeu de macros similaires à celles présentées ici.
LinuxFocus 1999 (ce document est publié simultanément sur Linux Focus et dans Linux Mag).
John Perr
Utilisateur Linux depuis 1994 ; éditeur français de la revue LinuxFocus.